mirror of
https://github.com/torvalds/linux.git
synced 2026-11-06 21:58:01 +01:00
bpf: Reject non-IPv6 packets in BPF_LWT_ENCAP_SEG6
The mode BPF_LWT_ENCAP_SEG6 of bpf_lwt_push_encap() pushes an IPv6 header
and an SRH, and it replaces the dst. The SRH says that IPv6 follows, and
skb->protocol does not change. Thus the mode assumes an IPv6 packet, but an
lwt_in prog also runs for IPv4 packets. After the prog, bpf_input() calls
orig_input() of the old dst. This IPv4 handler reads the pushed headers as
IPv4. It can write after the packet data, and the kernel crashes.
after the push orig_input() expects
--------------------- --------------------
skb->protocol ETH_P_IP ETH_P_IP
dst rt6_info rtable
packet | IPv6 | SRH | IPv4 | | IPv4 |
The mode BPF_LWT_ENCAP_SEG6_INLINE returns -EBADMSG for non-IPv6 packets.
Apply this check to both modes. End.BPF does not change, because
seg6_local_input() drops non-IPv6 packets.
Fixes: fe94cc290f ("bpf: Add IPv6 Segment Routing helpers")
Signed-off-by: Chris Mason <mason@kernel.org>
Signed-off-by: Alexei Starovoitov <ast@kernel.org>
Link: https://patch.msgid.link/20261101190535.1454146-17-alexei.starovoitov@gmail.com
This commit is contained in:
parent
6d8118937b
commit
58e39f8d58
|
|
@ -6927,11 +6927,15 @@ static int bpf_push_seg6_encap(struct sk_buff *skb, u32 type, void *hdr, u32 len
|
|||
if (!seg6_validate_srh(srh, len, false))
|
||||
return -EINVAL;
|
||||
|
||||
/*
|
||||
* The encap mode names IPv6 as the inner protocol, and neither mode
|
||||
* updates skb->protocol.
|
||||
*/
|
||||
if (skb->protocol != htons(ETH_P_IPV6))
|
||||
return -EBADMSG;
|
||||
|
||||
switch (type) {
|
||||
case BPF_LWT_ENCAP_SEG6_INLINE:
|
||||
if (skb->protocol != htons(ETH_P_IPV6))
|
||||
return -EBADMSG;
|
||||
|
||||
err = seg6_do_srh_inline(skb, srh);
|
||||
break;
|
||||
case BPF_LWT_ENCAP_SEG6:
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user