Thanks to visit codestin.com
Credit goes to github.com

Skip to content

Commit 8a0ed25

Browse files
wdebruijdavem330
authored andcommitted
ip_gre: validate csum_start only on pull
The GRE tunnel device can pull existing outer headers in ipge_xmit. This is a rare path, apparently unique to this device. The below commit ensured that pulling does not move skb->data beyond csum_start. But it has a false positive if ip_summed is not CHECKSUM_PARTIAL and thus csum_start is irrelevant. Refine to exclude this. At the same time simplify and strengthen the test. Simplify, by moving the check next to the offending pull, making it more self documenting and removing an unnecessary branch from other code paths. Strengthen, by also ensuring that the transport header is correct and therefore the inner headers will be after skb_reset_inner_headers. The transport header is set to csum_start in skb_partial_csum_set. Link: https://lore.kernel.org/netdev/YS+h%2FtqCJJiQei+W@shredder/ Fixes: 1d011c4 ("ip_gre: add validation for csum_start") Reported-by: Ido Schimmel <[email protected]> Suggested-by: Alexander Duyck <[email protected]> Signed-off-by: Willem de Bruijn <[email protected]> Reviewed-by: Alexander Duyck <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 0a4fd8d commit 8a0ed25

File tree

1 file changed

+6
-3
lines changed

1 file changed

+6
-3
lines changed

net/ipv4/ip_gre.c

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -473,8 +473,6 @@ static void __gre_xmit(struct sk_buff *skb, struct net_device *dev,
473473

474474
static int gre_handle_offloads(struct sk_buff *skb, bool csum)
475475
{
476-
if (csum && skb_checksum_start(skb) < skb->data)
477-
return -EINVAL;
478476
return iptunnel_handle_offloads(skb, csum ? SKB_GSO_GRE_CSUM : SKB_GSO_GRE);
479477
}
480478

@@ -632,15 +630,20 @@ static netdev_tx_t ipgre_xmit(struct sk_buff *skb,
632630
}
633631

634632
if (dev->header_ops) {
633+
const int pull_len = tunnel->hlen + sizeof(struct iphdr);
634+
635635
if (skb_cow_head(skb, 0))
636636
goto free_skb;
637637

638638
tnl_params = (const struct iphdr *)skb->data;
639639

640+
if (pull_len > skb_transport_offset(skb))
641+
goto free_skb;
642+
640643
/* Pull skb since ip_tunnel_xmit() needs skb->data pointing
641644
* to gre header.
642645
*/
643-
skb_pull(skb, tunnel->hlen + sizeof(struct iphdr));
646+
skb_pull(skb, pull_len);
644647
skb_reset_mac_header(skb);
645648
} else {
646649
if (skb_cow_head(skb, dev->needed_headroom))

0 commit comments

Comments
 (0)