Jakub Kicinski wrote: > A not-so-careful NAT46 BPF program can crash the kernel > if it indiscriminately flips ingress packets from v4 to v6: > > BUG: kernel NULL pointer dereference, address: 0000000000000000 > ip6_rcv_core (net/ipv6/ip6_input.c:190:20) > ipv6_rcv (net/ipv6/ip6_input.c:306:8) > process_backlog (net/core/dev.c:6186:4) > napi_poll (net/core/dev.c:6906:9) > net_rx_action (net/core/dev.c:7028:13) > do_softirq (kernel/softirq.c:462:3) > netif_rx (net/core/dev.c:5326:3) > dev_loopback_xmit (net/core/dev.c:4015:2) > ip_mc_finish_output (net/ipv4/ip_output.c:363:8) > NF_HOOK (./include/linux/netfilter.h:314:9) > ip_mc_output (net/ipv4/ip_output.c:400:5) > dst_output (./include/net/dst.h:459:9) > ip_local_out (net/ipv4/ip_output.c:130:9) > ip_send_skb (net/ipv4/ip_output.c:1496:8) > udp_send_skb (net/ipv4/udp.c:1040:8) > udp_sendmsg (net/ipv4/udp.c:1328:10) > > The output interface has a 4->6 program attached at ingress. > We try to loop the multicast skb back to the sending socket. > Ingress BPF runs as part of netif_rx(), pushes a valid v6 hdr > and changes skb->protocol to v6. We enter ip6_rcv_core which > tries to use skb_dst(). But the dst is still an IPv4 one left > after IPv4 mcast output. > > Clear the dst in all BPF helpers which change the protocol. > Try to preserve metadata dsts, those may carry non-routing > metadata. > > Cc: stable@xxxxxxxxxxxxxxx > Reviewed-by: Maciej Żenczykowski <maze@xxxxxxxxxx> > Acked-by: Daniel Borkmann <daniel@xxxxxxxxxxxxx> > Fixes: d219df60a70e ("bpf: Add ipip6 and ip6ip decap support for bpf_skb_adjust_room()") > Fixes: 1b00e0dfe7d0 ("bpf: update skb->protocol in bpf_skb_net_grow") > Fixes: 6578171a7ff0 ("bpf: add bpf_skb_change_proto helper") > Signed-off-by: Jakub Kicinski <kuba@xxxxxxxxxx> Reviewed-by: Willem de Bruijn <willemb@xxxxxxxxxx>