From 035e1fed892d3d06002a73ff73668f618a514644 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 28 Jun 2026 06:44:13 +0200 Subject: [PATCH 1/6] batman-adv: retrieve ethhdr after potential skb realloc on RX pskb_may_pull() in batadv_interface_rx() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free. This was done correctly for the VLAN header but missed for the ethernet header which is later used for the TT and AP isolation handling. Cc: stable@vger.kernel.org Reported-by: Sashiko Fixes: c6c8fea29769 ("net: Add batman-adv meshing protocol") Fixes: c78296665c3d ("batman-adv: Check skb size before using encapsulated ETH+VLAN header") Signed-off-by: Sven Eckelmann --- net/batman-adv/mesh-interface.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/batman-adv/mesh-interface.c b/net/batman-adv/mesh-interface.c index 44026810b99c..511f70e0706a 100644 --- a/net/batman-adv/mesh-interface.c +++ b/net/batman-adv/mesh-interface.c @@ -434,6 +434,7 @@ void batadv_interface_rx(struct net_device *mesh_iface, if (!pskb_may_pull(skb, VLAN_ETH_HLEN)) goto dropped; + ethhdr = eth_hdr(skb); vhdr = skb_vlan_eth_hdr(skb); /* drop batman-in-batman packets to prevent loops */ From 7141990add3f75436f2933cb310654cad3b1e3e9 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 28 Jun 2026 08:35:35 +0200 Subject: [PATCH 2/6] batman-adv: access unicast_ttvn skb->data only after skb realloc The pskb_may_pull() called by batadv_get_vid() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free. This was done correctly for the ethernet header but missed for the unicast_packet pointer. Cc: stable@vger.kernel.org Reported-by: Sashiko Fixes: c018ad3de61a ("batman-adv: add the VLAN ID attribute to the TT entry") Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index c05fcc9241ad..2cc2307a4170 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -855,8 +855,8 @@ static bool batadv_check_unicast_ttvn(struct batadv_priv *bat_priv, if (skb_cow(skb, sizeof(*unicast_packet)) < 0) return false; - unicast_packet = (struct batadv_unicast_packet *)skb->data; vid = batadv_get_vid(skb, hdr_len); + unicast_packet = (struct batadv_unicast_packet *)skb->data; ethhdr = (struct ethhdr *)(skb->data + hdr_len); /* do not reroute multicast frames in a unicast header */ From 77880a3be88d378d60cc1e8f8ec70430e2ed0518 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 28 Jun 2026 08:45:41 +0200 Subject: [PATCH 3/6] batman-adv: gw: acquire ethernet header only after skb realloc The pskb_may_pull() called by batadv_get_vid() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free. Cc: stable@vger.kernel.org Fixes: 6c413b1c22a2 ("batman-adv: send every DHCP packet as bat-unicast") Signed-off-by: Sven Eckelmann --- net/batman-adv/gateway_client.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/gateway_client.c b/net/batman-adv/gateway_client.c index 305488a74a25..a5ac82eabd25 100644 --- a/net/batman-adv/gateway_client.c +++ b/net/batman-adv/gateway_client.c @@ -684,12 +684,13 @@ bool batadv_gw_out_of_range(struct batadv_priv *bat_priv, struct batadv_gw_node *gw_node = NULL; struct batadv_gw_node *curr_gw = NULL; struct batadv_neigh_ifinfo *curr_ifinfo, *old_ifinfo; - struct ethhdr *ethhdr = (struct ethhdr *)skb->data; + struct ethhdr *ethhdr; bool out_of_range = false; u8 curr_tq_avg; unsigned short vid; vid = batadv_get_vid(skb, 0); + ethhdr = (struct ethhdr *)skb->data; if (is_multicast_ether_addr(ethhdr->h_dest)) goto out; From 48067b2ae4504500a7093d9e1e16b42e70330480 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 28 Jun 2026 08:45:41 +0200 Subject: [PATCH 4/6] batman-adv: dat: acquire ARP hw source only after skb realloc The pskb_may_pull() called by batadv_get_vid() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free. Cc: stable@vger.kernel.org Fixes: b61ec31c8575 ("batman-adv: Snoop DHCPACKs for DAT") Signed-off-by: Sven Eckelmann --- net/batman-adv/distributed-arp-table.c | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index ae39ceaa2e29..ead02c9e0848 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -1747,6 +1747,7 @@ void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, struct ethhdr *ethhdr; __be32 ip_src, yiaddr; unsigned short vid; + int hdr_size_tmp; __be16 proto; u8 *hw_src; @@ -1763,8 +1764,10 @@ void batadv_dat_snoop_incoming_dhcp_ack(struct batadv_priv *bat_priv, if (!batadv_dat_check_dhcp_ack(skb, proto, &ip_src, chaddr, &yiaddr)) return; + hdr_size_tmp = hdr_size; + vid = batadv_dat_get_vid(skb, &hdr_size_tmp); + ethhdr = (struct ethhdr *)(skb->data + hdr_size); hw_src = ethhdr->h_source; - vid = batadv_dat_get_vid(skb, &hdr_size); batadv_dat_entry_add(bat_priv, yiaddr, chaddr, vid); batadv_dat_entry_add(bat_priv, ip_src, hw_src, vid); From cdf3b5af2bc4431e58629e8ad2086b1e9185c761 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 28 Jun 2026 08:45:41 +0200 Subject: [PATCH 5/6] batman-adv: bla: reacquire gw address after skb realloc The pskb_may_pull() called by batadv_bla_is_backbone_gw() could reallocate the buffer behind the skb. Variables which were pointing to the old buffer need to be reassigned to avoid an use-after-free. Cc: stable@vger.kernel.org Fixes: 9e794b6bf4a2 ("batman-adv: drop unicast packets from other backbone gw") Signed-off-by: Sven Eckelmann --- net/batman-adv/routing.c | 1 + 1 file changed, 1 insertion(+) diff --git a/net/batman-adv/routing.c b/net/batman-adv/routing.c index 2cc2307a4170..bbd40fe3a8e5 100644 --- a/net/batman-adv/routing.c +++ b/net/batman-adv/routing.c @@ -1029,6 +1029,7 @@ int batadv_recv_unicast_packet(struct sk_buff *skb, hdr_size); batadv_orig_node_put(orig_node_gw); if (is_gw) { + orig_addr_gw = eth_hdr(skb)->h_source; batadv_dbg(BATADV_DBG_BLA, bat_priv, "%s(): Dropped unicast pkt received from another backbone gw %pM.\n", __func__, orig_addr_gw); From 26560c4a03dc4d607331600c187f59ab2df5f341 Mon Sep 17 00:00:00 2001 From: Sven Eckelmann Date: Sun, 28 Jun 2026 10:37:07 +0200 Subject: [PATCH 6/6] batman-adv: dat: ensure accessible eth_hdr proto field 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 Fixes: be1db4f6615b ("batman-adv: make the Distributed ARP Table vlan aware") Signed-off-by: Sven Eckelmann --- net/batman-adv/distributed-arp-table.c | 23 +++++++++++++++++++++++ net/batman-adv/main.c | 3 +++ 2 files changed, 26 insertions(+) diff --git a/net/batman-adv/distributed-arp-table.c b/net/batman-adv/distributed-arp-table.c index ead02c9e0848..c40c9e02391b 100644 --- a/net/batman-adv/distributed-arp-table.c +++ b/net/batman-adv/distributed-arp-table.c @@ -1066,6 +1066,9 @@ static u16 batadv_arp_get_type(struct batadv_priv *bat_priv, * @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); diff --git a/net/batman-adv/main.c b/net/batman-adv/main.c index 3c4572284b53..4d3807a645b7 100644 --- a/net/batman-adv/main.c +++ b/net/batman-adv/main.c @@ -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. */