In the software ESP offload path, xfrm_output_gso() leaves its segments
sharing a secpath extension. Each segment gets its own ESP sequence
number, but stores it in the same xo->seq field for IV generation.
If encryption is delayed, later segments overwrite the value needed by
earlier ones: esp*_xmit() can then encrypt several packets with the same
AES-GCM nonce, despite their distinct ESP sequence numbers.
Give each segment a private secpath before allocating its sequence
number.
Fixes: a204aef9fd77 ("xfrm: call xfrm_output_gso when inner_protocol is set in xfrm_output")
Cc: stable@vger.kernel.org
Assisted-by: LLM
Signed-off-by: Jérémy Jean <redacted>
---
net/xfrm/xfrm_output.c | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index e305ba32e356..f6644daa68ba 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -672,6 +672,13 @@ static int xfrm_output_gso(struct net *net, struct sock *sk, struct sk_buff *skb
skb_list_walk_safe(segs, segs, nskb) {
int err;
+ /* Each segment reserves its own sequence number below. */
+ if (xfrm_offload(segs) && !secpath_set(segs)) {
+ XFRM_INC_STATS(net, LINUX_MIB_XFRMOUTERROR);
+ kfree_skb_list(segs);
+ return -ENOMEM;
+ }
+
skb_mark_not_on_list(segs);
err = xfrm_output2(net, sk, segs);
--
2.47.3