From: wenxu <we...@ucloud.cn> BUG report in selftests: bpf: test_tunnel.sh
Testing IPIP tunnel... BUG: unable to handle kernel NULL pointer dereference at 0000000000000000 PGD 0 P4D 0 Oops: 0010 [#1] SMP PTI CPU: 0 PID: 16822 Comm: ping Not tainted 5.0.0-rc3-00352-gc8b34e6 #1 Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.10.2-1 04/01/2014 RIP: 0010: (null) Code: Bad RIP value. RSP: 0018:ffffc9000104f9c8 EFLAGS: 00010286 RAX: 0000000000000000 RBX: ffffe8ffffc071a8 RCX: 0000000000000000 RDX: ffff888054e33000 RSI: ffff88807796f500 RDI: ffffe8ffffc07130 RBP: ffff88807796f500 R08: ffff88806da4f0a0 R09: 0000000000000000 R10: 0000000000000004 R11: ffff888054e33000 R12: 0000000000000054 R13: ffff88805e714000 R14: ffff88806da4f0a0 R15: 0000000000000000 FS: 00007f4c00431500(0000) GS:ffff88813fc00000(0000) knlGS:0000000000000000 CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033 CR2: ffffffffffffffd6 CR3: 000000008276e000 CR4: 00000000000406f0 Call Trace: ? tnl_update_pmtu+0x21b/0x250 [ip_tunnel] ? ip_md_tunnel_xmit+0x1b7/0xdc0 [ip_tunnel] ? ipip_tunnel_xmit+0x90/0xc0 [ipip] ? dev_hard_start_xmit+0x98/0x210 ? __dev_queue_xmit+0x6a9/0x8e0 The bpf program set tunnel_key through bpf_skb_set_tunnel_key which will drop the old dst_entry and create a DST_METADATA dst_entry. It will lead the tunnel_update_pmtu operator the dst_entry incorrect. So It should be check the dst_entry is valid. Fixes: c8b34e680a09 ("ip_tunnel: Add tnl_update_pmtu in ip_md_tunnel_xmit") Signed-off-by: wenxu <we...@ucloud.cn> --- net/ipv4/ip_tunnel.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/net/ipv4/ip_tunnel.c b/net/ipv4/ip_tunnel.c index 893f013..a665f11 100644 --- a/net/ipv4/ip_tunnel.c +++ b/net/ipv4/ip_tunnel.c @@ -515,7 +515,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, mtu = dst_mtu(&rt->dst) - dev->hard_header_len - sizeof(struct iphdr) - tunnel_hlen; else - mtu = skb_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; + mtu = skb_valid_dst(skb) ? dst_mtu(skb_dst(skb)) : dev->mtu; skb_dst_update_pmtu(skb, mtu); @@ -530,7 +530,7 @@ static int tnl_update_pmtu(struct net_device *dev, struct sk_buff *skb, } #if IS_ENABLED(CONFIG_IPV6) else if (skb->protocol == htons(ETH_P_IPV6)) { - struct rt6_info *rt6 = (struct rt6_info *)skb_dst(skb); + struct rt6_info *rt6 = (struct rt6_info *)skb_valid_dst(skb); __be32 daddr; daddr = md ? dst : tunnel->parms.iph.daddr; -- 1.8.3.1