Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

Staging: batman-adv: ensure that eth_type_trans gets linear memory

eth_type_trans tries to pull data with the length of the ethernet header
from the skb. We only ensured that enough data for the first ethernet
header and the batman header is available in non-paged memory of the skb
and not for the ethernet after the batman header.

eth_type_trans would fail sometimes with drivers which don't ensure that
all there data is perfectly linearised.

The failure was noticed through a kernel bug Oops generated by the
skb_pull inside eth_type_trans.

Reported-by: Rafal Lesniak <lesniak@eresi-project.org>
Signed-off-by: Marek Lindner <lindner_marek@yahoo.de>
Signed-off-by: Sven Eckelmann <sven.eckelmann@gmx.de>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Marek Lindner and committed by
Greg Kroah-Hartman
b6faaae1 9ee89873

+10 -4
+10 -4
drivers/staging/batman-adv/soft-interface.c
··· 194 194 struct bat_priv *priv = netdev_priv(soft_iface); 195 195 196 196 /* check if enough space is available for pulling, and pull */ 197 - if (!pskb_may_pull(skb, hdr_size)) { 198 - kfree_skb(skb); 199 - return; 200 - } 197 + if (!pskb_may_pull(skb, hdr_size)) 198 + goto dropped; 199 + 201 200 skb_pull_rcsum(skb, hdr_size); 202 201 /* skb_set_mac_header(skb, -sizeof(struct ethhdr));*/ 203 202 204 203 /* skb->dev & skb->pkt_type are set here */ 204 + if (unlikely(!pskb_may_pull(skb, ETH_HLEN))) 205 + goto dropped; 205 206 skb->protocol = eth_type_trans(skb, soft_iface); 206 207 207 208 /* should not be neccesary anymore as we use skb_pull_rcsum() ··· 217 216 soft_iface->last_rx = jiffies; 218 217 219 218 netif_rx(skb); 219 + return; 220 + 221 + dropped: 222 + kfree_skb(skb); 223 + return; 220 224 } 221 225 222 226 #ifdef HAVE_NET_DEVICE_OPS