summaryrefslogtreecommitdiff
path: root/net/core
diff options
context:
space:
mode:
authorNick Hudson <nhudson@akamai.com>2026-08-12 09:31:14 +0100
committerDaniel Borkmann <daniel@iogearbox.net>2026-08-17 11:30:13 +0200
commitec20dee2f2c4796c0f7c0a7d8a3a3e8a9e9da7a4 (patch)
tree960f0c8598a1bf1d1a5c68c6eb0ad06e921ff6e5 /net/core
parent3a39c214fd2c3dd8266649e7f9f85ca1439eb738 (diff)
bpf: Clear decap state on skb_adjust_room shrink path
On shrink in bpf_skb_adjust_room(), apply decapsulation state updates according to BPF_F_ADJ_ROOM_DECAP_* flags. For GSO skbs, clear only the tunnel gso_type bits that correspond to the requested decap layer: - DECAP_L4_UDP: SKB_GSO_UDP_TUNNEL{,_CSUM} - DECAP_L4_GRE: SKB_GSO_GRE{,_CSUM} - DECAP_IPXIP4: SKB_GSO_IPXIP4 - DECAP_IPXIP6: SKB_GSO_IPXIP6 Then clear skb->encapsulation only if no tunnel GSO bits remain, keeping encapsulation set for cases such as ESP-in-UDP where tunnel state remains. For non-GSO skbs, there are no tunnel GSO bits to consult, so clear skb->encapsulation directly when DECAP_L4_* or DECAP_IPXIP_* flags are set. This keeps decap state handling consistent between GSO and non-GSO packets. Co-developed-by: Max Tottenham <mtottenh@akamai.com> Co-developed-by: Anna Glasgall <aglasgal@akamai.com> Signed-off-by: Max Tottenham <mtottenh@akamai.com> Signed-off-by: Anna Glasgall <aglasgal@akamai.com> Signed-off-by: Nick Hudson <nhudson@akamai.com> Signed-off-by: Daniel Borkmann <daniel@iogearbox.net> Reviewed-by: Willem de Bruijn <willemb@google.com> Link: https://lore.kernel.org/bpf/20260812083115.73100-6-nhudson@akamai.com
Diffstat (limited to 'net/core')
-rw-r--r--net/core/filter.c39
1 files changed, 39 insertions, 0 deletions
diff --git a/net/core/filter.c b/net/core/filter.c
index 3ba653ab3239..61940e753552 100644
--- a/net/core/filter.c
+++ b/net/core/filter.c
@@ -3754,9 +3754,48 @@ static int bpf_skb_net_shrink(struct sk_buff *skb, u32 off, u32 len_diff,
if (!(flags & BPF_F_ADJ_ROOM_FIXED_GSO))
skb_increase_gso_size(shinfo, len_diff);
+ /* Selective GSO flag clearing based on decap type.
+ * Only clear the flags for the tunnel layer being removed.
+ */
+ if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_UDP) &&
+ (shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
+ SKB_GSO_UDP_TUNNEL_CSUM)))
+ shinfo->gso_type &= ~(SKB_GSO_UDP_TUNNEL |
+ SKB_GSO_UDP_TUNNEL_CSUM);
+ if ((flags & BPF_F_ADJ_ROOM_DECAP_L4_GRE) &&
+ (shinfo->gso_type & (SKB_GSO_GRE | SKB_GSO_GRE_CSUM)))
+ shinfo->gso_type &= ~(SKB_GSO_GRE |
+ SKB_GSO_GRE_CSUM);
+ if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP4) &&
+ (shinfo->gso_type & SKB_GSO_IPXIP4))
+ shinfo->gso_type &= ~SKB_GSO_IPXIP4;
+ if ((flags & BPF_F_ADJ_ROOM_DECAP_IPXIP6) &&
+ (shinfo->gso_type & SKB_GSO_IPXIP6))
+ shinfo->gso_type &= ~SKB_GSO_IPXIP6;
+
+ /* Clear encapsulation flag only when no tunnel GSO flags remain */
+ if (flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
+ BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) {
+ if (!(shinfo->gso_type & (SKB_GSO_UDP_TUNNEL |
+ SKB_GSO_UDP_TUNNEL_CSUM |
+ SKB_GSO_GRE |
+ SKB_GSO_GRE_CSUM |
+ SKB_GSO_IPXIP4 |
+ SKB_GSO_IPXIP6 |
+ SKB_GSO_ESP)))
+ if (skb->encapsulation)
+ skb->encapsulation = 0;
+ }
+
/* Header must be checked, and gso_segs recomputed. */
shinfo->gso_type |= SKB_GSO_DODGY;
shinfo->gso_segs = 0;
+ } else {
+ /* For non-GSO packets, clear encapsulation if decap flags are set */
+ if ((flags & (BPF_F_ADJ_ROOM_DECAP_L4_MASK |
+ BPF_F_ADJ_ROOM_DECAP_IPXIP_MASK)) &&
+ skb->encapsulation)
+ skb->encapsulation = 0;
}
return 0;