mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-08-30 14:33:24 -04:00
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
This commit is contained in:
committed by
Daniel Borkmann
parent
3a39c214fd
commit
ec20dee2f2
@@ -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;
|
||||
|
||||
Reference in New Issue
Block a user