From 3a39c214fd2c3dd8266649e7f9f85ca1439eb738 Mon Sep 17 00:00:00 2001 From: Nick Hudson Date: Wed, 12 Aug 2026 09:31:13 +0100 Subject: [PATCH] bpf: Allow new DECAP flags and add guard rails Add checks to require shrink-only decap, reject conflicting decap flag combinations, and verify removed length is sufficient for claimed header decapsulation. Co-developed-by: Max Tottenham Co-developed-by: Anna Glasgall Signed-off-by: Max Tottenham Signed-off-by: Anna Glasgall Signed-off-by: Nick Hudson Signed-off-by: Daniel Borkmann Reviewed-by: Willem de Bruijn Link: https://lore.kernel.org/bpf/20260812083115.73100-5-nhudson@akamai.com --- net/core/filter.c | 44 +++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 43 insertions(+), 1 deletion(-) diff --git a/net/core/filter.c b/net/core/filter.c index 00b7ebe4a02b..3ba653ab3239 100644 --- a/net/core/filter.c +++ b/net/core/filter.c @@ -56,6 +56,7 @@ #include #include #include +#include #include #include #include @@ -3572,6 +3573,12 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb) #define BPF_F_ADJ_ROOM_DECAP_L3_MASK (BPF_F_ADJ_ROOM_DECAP_L3_IPV4 | \ BPF_F_ADJ_ROOM_DECAP_L3_IPV6) +#define BPF_F_ADJ_ROOM_DECAP_L4_MASK (BPF_F_ADJ_ROOM_DECAP_L4_UDP | \ + BPF_F_ADJ_ROOM_DECAP_L4_GRE) + +#define BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK (BPF_F_ADJ_ROOM_DECAP_IPXIP4 | \ + BPF_F_ADJ_ROOM_DECAP_IPXIP6) + #define BPF_F_ADJ_ROOM_ENCAP_MASK (BPF_F_ADJ_ROOM_ENCAP_L3_MASK | \ BPF_F_ADJ_ROOM_ENCAP_L4_GRE | \ BPF_F_ADJ_ROOM_ENCAP_L4_UDP | \ @@ -3579,7 +3586,9 @@ static u32 bpf_skb_net_base_len(const struct sk_buff *skb) BPF_F_ADJ_ROOM_ENCAP_L2( \ BPF_ADJ_ROOM_ENCAP_L2_MASK)) -#define BPF_F_ADJ_ROOM_DECAP_MASK (BPF_F_ADJ_ROOM_DECAP_L3_MASK) +#define BPF_F_ADJ_ROOM_DECAP_MASK (BPF_F_ADJ_ROOM_DECAP_L3_MASK | \ + BPF_F_ADJ_ROOM_DECAP_L4_MASK | \ + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) #define BPF_F_ADJ_ROOM_MASK (BPF_F_ADJ_ROOM_FIXED_GSO | \ BPF_F_ADJ_ROOM_ENCAP_MASK | \ @@ -3827,6 +3836,8 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff, } if (flags & BPF_F_ADJ_ROOM_DECAP_MASK) { + u32 len_decap_min = 0; + if (!shrink) return -EINVAL; @@ -3835,6 +3846,37 @@ BPF_CALL_4(bpf_skb_adjust_room, struct sk_buff *, skb, s32, len_diff, BPF_F_ADJ_ROOM_DECAP_L3_MASK) return -EINVAL; + if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) == + BPF_F_ADJ_ROOM_DECAP_L4_MASK) + return -EINVAL; + + if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) == + BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK) + return -EINVAL; + + /* Reject mutually exclusive decap tunnel type flags. */ + if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) && + (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) + return -EINVAL; + + if (flags & BPF_F_ADJ_ROOM_DECAP_L4_MASK) + len_decap_min += bpf_skb_net_base_len(skb); + + if (flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) + len_decap_min += sizeof(struct udphdr); + + if (flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE) + len_decap_min += sizeof(struct gre_base_hdr); + + if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4) + len_decap_min += sizeof(struct iphdr); + + if (flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6) + len_decap_min += sizeof(struct ipv6hdr); + + if (len_diff_abs < len_decap_min) + return -EINVAL; + if (flags & BPF_F_ADJ_ROOM_DECAP_L3_IPV4) len_min = sizeof(struct iphdr);