Eric Dumazet wrote:
> A tc egress BPF program can push a tiny link-layer header with
> bpf_skb_change_head() on an skb whose head is almost empty, then
> redirect it to an Ethernet device ingress. __bpf_redirect_common()
> only checks mac_header < network_header, and __dev_forward_skb2()
> crashes in eth_type_trans():
> 
>   tc filter add dev lo egress pref 1 matchall action vlan pop_eth continue
>   tc filter add dev lo egress pref 2 bpf da obj prog.o
>   # prog: bpf_skb_change_head(skb, 1, 0);
>   #       return bpf_redirect(veth1_ifindex, BPF_F_INGRESS);
>   # AF_PACKET SOCK_RAW on lo: eth / eth / 8192 bytes of payload
> 
>   kernel BUG at include/linux/skbuff.h:2839!
>   RIP: 0010:eth_type_trans (include/linux/etherdevice.h:635 
> net/ethernet/eth.c:163)
>   Call Trace:
>    __dev_forward_skb2 (net/core/dev.c:2507)
>    dev_forward_skb_nomtu (net/core/dev.c:2546)
>    __dev_queue_xmit (net/core/dev.c:4738 net/core/dev.c:4998)
>    packet_sendmsg (net/packet/af_packet.c:3157 net/packet/af_packet.c:3189)
> 
> Use eth_type_trans_careful(), and drop the packet if the Ethernet
> header can not be pulled. This also covers other dev_forward_skb()
> users (veth, macvlan, ipvlan, netdevsim, l2tp_eth).
> 
> Update the empty_skb BPF selftest: at lwt_xmit, BPF_PROG_TEST_RUN
> strips the Ethernet header, so the "veth ETH_HLEN+1" packet is a 1-byte
> skb. Redirecting it to veth ingress used to read the Ethernet header
> past skb->tail and deliver a 1-byte frame; it is now dropped with
> NET_RX_DROP, as veth_xmit() already does at egress.
> 
> Fixes: 3a0af8fd61f9 ("bpf: BPF for lightweight tunnel infrastructure")
> Signed-off-by: Eric Dumazet <[email protected]>
> Reviewed-by: Jamal Hadi Salim <[email protected]>
> Tested-by: Jamal Hadi Salim <[email protected]>

Reviewed-by: Willem de Bruijn <[email protected]>
_______________________________________________
dev mailing list
[email protected]
https://mail.openvswitch.org/mailman/listinfo/ovs-dev

Reply via email to