Merge pull request #521 from ecsv/batadv-for-17.01
[feed/routing.git] / batman-adv / patches / 0011-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch
diff --git a/batman-adv/patches/0011-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch b/batman-adv/patches/0011-batman-adv-Only-read-OGM-tvlv_len-after-buffer-len-c.patch
new file mode 100644 (file)
index 0000000..47d9785
--- /dev/null
@@ -0,0 +1,74 @@
+From: Sven Eckelmann <sven@narfation.org>
+Date: Fri, 23 Aug 2019 14:34:27 +0200
+Subject: batman-adv: Only read OGM tvlv_len after buffer len check
+
+Multiple batadv_ogm_packet can be stored in an skbuff. The functions
+batadv_iv_ogm_send_to_if()/batadv_iv_ogm_receive() use
+batadv_iv_ogm_aggr_packet() to check if there is another additional
+batadv_ogm_packet in the skb or not before they continue processing the
+packet.
+
+The length for such an OGM is BATADV_OGM_HLEN +
+batadv_ogm_packet->tvlv_len. The check must first check that at least
+BATADV_OGM_HLEN bytes are available before it accesses tvlv_len (which is
+part of the header. Otherwise it might try read outside of the currently
+available skbuff to get the content of tvlv_len.
+
+Fixes: 0b6aa0d43767 ("batman-adv: tvlv - basic infrastructure")
+Reported-by: syzbot+355cab184197dbbfa384@syzkaller.appspotmail.com
+Signed-off-by: Sven Eckelmann <sven@narfation.org>
+Acked-by: Antonio Quartulli <a@unstable.cc>
+
+Origin: upstream, https://git.open-mesh.org/batman-adv.git/commit/07b6051ebcfaa7ea89b4f278eca2ff4070d29e56
+
+diff --git a/net/batman-adv/bat_iv_ogm.c b/net/batman-adv/bat_iv_ogm.c
+index 7bfd0d7ef49df8e699f91e2b827b824aa3657c0d..5afc4e9646d622c6f924d4610ac58eb77404b37a 100644
+--- a/net/batman-adv/bat_iv_ogm.c
++++ b/net/batman-adv/bat_iv_ogm.c
+@@ -450,17 +450,23 @@ static u8 batadv_hop_penalty(u8 tq, const struct batadv_priv *bat_priv)
+  * batadv_iv_ogm_aggr_packet - checks if there is another OGM attached
+  * @buff_pos: current position in the skb
+  * @packet_len: total length of the skb
+- * @tvlv_len: tvlv length of the previously considered OGM
++ * @ogm_packet: potential OGM in buffer
+  *
+  * Return: true if there is enough space for another OGM, false otherwise.
+  */
+-static bool batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
+-                                    __be16 tvlv_len)
++static bool
++batadv_iv_ogm_aggr_packet(int buff_pos, int packet_len,
++                        const struct batadv_ogm_packet *ogm_packet)
+ {
+       int next_buff_pos = 0;
+-      next_buff_pos += buff_pos + BATADV_OGM_HLEN;
+-      next_buff_pos += ntohs(tvlv_len);
++      /* check if there is enough space for the header */
++      next_buff_pos += buff_pos + sizeof(*ogm_packet);
++      if (next_buff_pos > packet_len)
++              return false;
++
++      /* check if there is enough space for the optional TVLV */
++      next_buff_pos += ntohs(ogm_packet->tvlv_len);
+       return (next_buff_pos <= packet_len) &&
+              (next_buff_pos <= BATADV_MAX_AGGREGATION_BYTES);
+@@ -488,7 +494,7 @@ static void batadv_iv_ogm_send_to_if(struct batadv_forw_packet *forw_packet,
+       /* adjust all flags and log packets */
+       while (batadv_iv_ogm_aggr_packet(buff_pos, forw_packet->packet_len,
+-                                       batadv_ogm_packet->tvlv_len)) {
++                                       batadv_ogm_packet)) {
+               /* we might have aggregated direct link packets with an
+                * ordinary base packet
+                */
+@@ -1838,7 +1844,7 @@ static int batadv_iv_ogm_receive(struct sk_buff *skb,
+       /* unpack the aggregated packets and process them one by one */
+       while (batadv_iv_ogm_aggr_packet(ogm_offset, skb_headlen(skb),
+-                                       ogm_packet->tvlv_len)) {
++                                       ogm_packet)) {
+               batadv_iv_ogm_process(skb, ogm_offset, if_incoming);
+               ogm_offset += BATADV_OGM_HLEN;