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@vger.kernel.org Signed-off-by: Jérémy Jean --- 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