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

net: Fix usage of pskb_trim_rcsum

In certain cases, pskb_trim_rcsum() may change skb pointers.
Reinitialize header pointers afterwards to avoid potential
use-after-frees. Add a note in the documentation of
pskb_trim_rcsum(). Found by KASAN.

Signed-off-by: Ross Lagerwall <ross.lagerwall@citrix.com>
Signed-off-by: David S. Miller <davem@davemloft.net>

authored by

Ross Lagerwall and committed by
David S. Miller
6c57f045 e40e2a2e

+5
+1
drivers/net/ppp/pppoe.c
··· 445 445 if (pskb_trim_rcsum(skb, len)) 446 446 goto drop; 447 447 448 + ph = pppoe_hdr(skb); 448 449 pn = pppoe_pernet(dev_net(dev)); 449 450 450 451 /* Note that get_item does a sock_hold(), so sk_pppox(po)
+1
include/linux/skbuff.h
··· 3218 3218 * 3219 3219 * This is exactly the same as pskb_trim except that it ensures the 3220 3220 * checksum of received packets are still valid after the operation. 3221 + * It can change skb pointers. 3221 3222 */ 3222 3223 3223 3224 static inline int pskb_trim_rcsum(struct sk_buff *skb, unsigned int len)
+1
net/bridge/br_netfilter_ipv6.c
··· 131 131 IPSTATS_MIB_INDISCARDS); 132 132 goto drop; 133 133 } 134 + hdr = ipv6_hdr(skb); 134 135 } 135 136 if (hdr->nexthdr == NEXTHDR_HOP && br_nf_check_hbh_len(skb)) 136 137 goto drop;
+1
net/bridge/netfilter/nft_reject_bridge.c
··· 229 229 pskb_trim_rcsum(skb, ntohs(ip6h->payload_len) + sizeof(*ip6h))) 230 230 return false; 231 231 232 + ip6h = ipv6_hdr(skb); 232 233 thoff = ipv6_skip_exthdr(skb, ((u8*)(ip6h+1) - skb->data), &proto, &fo); 233 234 if (thoff < 0 || thoff >= skb->len || (fo & htons(~0x7)) != 0) 234 235 return false;
+1
net/ipv4/ip_input.c
··· 488 488 goto drop; 489 489 } 490 490 491 + iph = ip_hdr(skb); 491 492 skb->transport_header = skb->network_header + iph->ihl*4; 492 493 493 494 /* Remove any debris in the socket control block */