[PATCH ipsec v2 6/7] xfrm: segment untrusted GSO packets before sequence allocation
From: Jérémy Jean
Date: Sun Nov 08 2026 - 09:33:38 EST
Packets received through TUN or virtio-net can have gso_segs == 0,
with SKB_GSO_DODGY set until the segmentation metadata is checked.
When ESP defers segmentation, gso_segs is still zero, so the SA
sequence counter is not advanced. The segments receive sequence
numbers starting at oseq + 1, which subsequent packets can reuse,
causing AES-GCM nonce reuse.
This affects IPv4 and IPv6, with or without ESN, when the ESP offload
type is registered. Hardware encryption is not required.
Segment SKB_GSO_DODGY packets in xfrm_output() before allocating
sequence numbers, so each segment gets its own number. Set the ESP
encapsulation flag in xfrm_output_one(), after early segmentation, so
UFO fragment offsets and flags are filled in correctly.
Fixes: d7dbefc45cf5 ("xfrm: Add xfrm_replay_overflow functions for offloading")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Jérémy Jean <Jeremy.Jean@xxxxxxxxxxxxxxxxx>
---
net/xfrm/xfrm_output.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 99d1b33db52a6..a1fb60971c6bc 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -505,6 +505,9 @@ static int xfrm_output_one(struct sk_buff *skb, int err)
if (err <= 0 || x->xso.type == XFRM_DEV_OFFLOAD_PACKET)
goto resume;
+ if (xfrm_offload(skb))
+ skb->encapsulation = 1;
+
do {
err = xfrm_skb_check_space(skb);
if (err) {
@@ -814,10 +817,10 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
xfrm_state_hold(x);
xfrm_get_inner_ipproto(skb, x);
- skb->encapsulation = 1;
if (skb_is_gso(skb)) {
- if (skb->inner_protocol && x->props.mode == XFRM_MODE_TUNNEL)
+ if ((skb_shinfo(skb)->gso_type & SKB_GSO_DODGY) ||
+ (skb->inner_protocol && x->props.mode == XFRM_MODE_TUNNEL))
return xfrm_output_gso(net, sk, skb);
skb_shinfo(skb)->gso_type |= SKB_GSO_ESP;
--
2.47.3