summaryrefslogtreecommitdiff
path: root/net/xfrm/xfrm_device.c
diff options
context:
space:
mode:
authorChristian Langrock <christian.langrock@secunet.com>2022-10-17 08:34:47 +0200
committerSteffen Klassert <steffen.klassert@secunet.com>2022-10-19 09:00:53 +0200
commit4b549ccce941798703f159b227aa28c716aa78fa (patch)
tree3fa86e1058150975d089ffa94dfe041fede45d0a /net/xfrm/xfrm_device.c
parentd83f7040e18489265b4b121f33f99b02e52dabda (diff)
downloadlwn-4b549ccce941798703f159b227aa28c716aa78fa.tar.gz
lwn-4b549ccce941798703f159b227aa28c716aa78fa.zip
xfrm: replay: Fix ESN wrap around for GSO
When using GSO it can happen that the wrong seq_hi is used for the last packets before the wrap around. This can lead to double usage of a sequence number. To avoid this, we should serialize this last GSO packet. Fixes: d7dbefc45cf5 ("xfrm: Add xfrm_replay_overflow functions for offloading") Co-developed-by: Steffen Klassert <steffen.klassert@secunet.com> Signed-off-by: Christian Langrock <christian.langrock@secunet.com> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
Diffstat (limited to 'net/xfrm/xfrm_device.c')
-rw-r--r--net/xfrm/xfrm_device.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 5f5aafd418af..21269e8f2db4 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -97,6 +97,18 @@ static void xfrm_outer_mode_prep(struct xfrm_state *x, struct sk_buff *skb)
}
}
+static inline bool xmit_xfrm_check_overflow(struct sk_buff *skb)
+{
+ struct xfrm_offload *xo = xfrm_offload(skb);
+ __u32 seq = xo->seq.low;
+
+ seq += skb_shinfo(skb)->gso_segs;
+ if (unlikely(seq < xo->seq.low))
+ return true;
+
+ return false;
+}
+
struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t features, bool *again)
{
int err;
@@ -134,7 +146,8 @@ struct sk_buff *validate_xmit_xfrm(struct sk_buff *skb, netdev_features_t featur
return skb;
}
- if (skb_is_gso(skb) && unlikely(x->xso.dev != dev)) {
+ if (skb_is_gso(skb) && (unlikely(x->xso.dev != dev) ||
+ unlikely(xmit_xfrm_check_overflow(skb)))) {
struct sk_buff *segs;
/* Packet got rerouted, fixup features and segment it. */