]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
batman-adv: dat: ensure accessible eth_hdr proto field
authorSven Eckelmann <sven@narfation.org>
Sun, 28 Jun 2026 08:37:07 +0000 (10:37 +0200)
committerSven Eckelmann <sven@narfation.org>
Sun, 28 Jun 2026 09:49:04 +0000 (11:49 +0200)
When batadv_get_vid() accesses the proto field of the ethernet header, it
is not checking if the data itself is accessible. The caller is responsible
for it. But in contrast to other call sites, batadv_dat_get_vid() and its
caller didn't make sure this is true. This could have caused an
out-of-bounds access.

Cc: stable@vger.kernel.org
Reported-by: Sashiko <sashiko-bot@kernel.org>
Fixes: be1db4f6615b ("batman-adv: make the Distributed ARP Table vlan aware")
Signed-off-by: Sven Eckelmann <sven@narfation.org>
net/batman-adv/distributed-arp-table.c
net/batman-adv/main.c

index ead02c9e084842353f15c2234b64f472a4d365b8..c40c9e02391befb5e9a01a2bea16d6d263578bda 100644 (file)
@@ -1066,6 +1066,9 @@ out:
  * @skb: the buffer containing the packet to extract the VID from
  * @hdr_size: the size of the batman-adv header encapsulating the packet
  *
+ * The caller must ensure that at least @hdr_size + ETH_HLEN bytes are
+ * accessible after skb->data.
+ *
  * Return: If the packet embedded in the skb is vlan tagged this function
  * returns the VID with the BATADV_VLAN_HAS_TAG flag. Otherwise BATADV_NO_FLAGS
  * is returned.
@@ -1148,6 +1151,10 @@ bool batadv_dat_snoop_outgoing_arp_request(struct batadv_priv *bat_priv,
        if (!READ_ONCE(bat_priv->distributed_arp_table))
                goto out;
 
+       /* first, find out the vid. */
+       if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
+               goto out;
+
        vid = batadv_dat_get_vid(skb, &hdr_size);
 
        type = batadv_arp_get_type(bat_priv, skb, hdr_size);
@@ -1243,6 +1250,10 @@ bool batadv_dat_snoop_incoming_arp_request(struct batadv_priv *bat_priv,
        if (!READ_ONCE(bat_priv->distributed_arp_table))
                goto out;
 
+       /* first, find out the vid. */
+       if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
+               goto out;
+
        vid = batadv_dat_get_vid(skb, &hdr_size);
 
        type = batadv_arp_get_type(bat_priv, skb, hdr_size);
@@ -1305,6 +1316,10 @@ void batadv_dat_snoop_outgoing_arp_reply(struct batadv_priv *bat_priv,
        if (!READ_ONCE(bat_priv->distributed_arp_table))
                return;
 
+       /* first, find out the vid. */
+       if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
+               return;
+
        vid = batadv_dat_get_vid(skb, &hdr_size);
 
        type = batadv_arp_get_type(bat_priv, skb, hdr_size);
@@ -1353,6 +1368,10 @@ bool batadv_dat_snoop_incoming_arp_reply(struct batadv_priv *bat_priv,
        if (!READ_ONCE(bat_priv->distributed_arp_table))
                goto out;
 
+       /* first, find out the vid. */
+       if (!pskb_may_pull(skb, hdr_size + ETH_HLEN))
+               goto out;
+
        vid = batadv_dat_get_vid(skb, &hdr_size);
 
        type = batadv_arp_get_type(bat_priv, skb, hdr_size);
@@ -1807,6 +1826,10 @@ bool batadv_dat_drop_broadcast_packet(struct batadv_priv *bat_priv,
        if (batadv_forw_packet_is_rebroadcast(forw_packet))
                goto out;
 
+       /* first, find out the vid. */
+       if (!pskb_may_pull(forw_packet->skb, hdr_size + ETH_HLEN))
+               goto out;
+
        vid = batadv_dat_get_vid(forw_packet->skb, &hdr_size);
 
        type = batadv_arp_get_type(bat_priv, forw_packet->skb, hdr_size);
index 3c4572284b532f93aba817fa404e3ec89c15675c..4d3807a645b78b639c4f3d0a9cdc193cd936d050 100644 (file)
@@ -580,6 +580,9 @@ void batadv_recv_handler_unregister(u8 packet_type)
  * @skb: the buffer containing the packet
  * @header_len: length of the batman header preceding the ethernet header
  *
+ * The caller must ensure that at least @header_len + ETH_HLEN bytes are
+ * accessible after skb->data.
+ *
  * Return: VID with the BATADV_VLAN_HAS_TAG flag when the packet embedded in the
  * skb is vlan tagged. Otherwise BATADV_NO_FLAGS.
  */