* [PATCH 0/10] pull request (net): ipsec 2025-11-18
@ 2025-11-18 8:52 Steffen Klassert
2025-11-18 8:52 ` [PATCH 01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match Steffen Klassert
` (9 more replies)
0 siblings, 10 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
1) Misc fixes for xfrm_state creation/modification/deletion.
Patchset from Sabrina Dubroca.
2) Fix inner packet family determination for xfrm offloads.
From Jianbo Liu.
3) Don't push locally generated packets directly to L2 tunnel
mode offloading, they still need processing from the standard
xfrm path. From Jianbo Liu.
4) Fix memory leaks in xfrm_add_acquire for policy offloads and policy
security contexts. From Zilin Guan.
Please pull or let me know if there are problems.
Thanks!
The following changes since commit f584239a9ed25057496bf397c370cc5163dde419:
net/smc: fix general protection fault in __smc_diag_dump (2025-10-20 17:46:06 -0700)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/klassert/ipsec.git tags/ipsec-2025-11-18
for you to fetch changes up to a55ef3bff84f11ee8c84a1ae29b071ffd4ccbbd9:
xfrm: fix memory leak in xfrm_add_acquire() (2025-11-14 10:12:36 +0100)
----------------------------------------------------------------
ipsec-2025-11-18
----------------------------------------------------------------
Jianbo Liu (3):
xfrm: Check inner packet family directly from skb_dst
xfrm: Determine inner GSO type from packet inner protocol
xfrm: Prevent locally generated packets from direct output in tunnel mode
Sabrina Dubroca (6):
xfrm: drop SA reference in xfrm_state_update if dir doesn't match
xfrm: also call xfrm_state_delete_tunnel at destroy time for states that were never added
xfrm: make state as DEAD before final put when migrate fails
xfrm: call xfrm_dev_state_delete when xfrm_state_migrate fails to add the state
xfrm: set err and extack on failure to create pcpu SA
xfrm: check all hash buckets for leftover states during netns deletion
Zilin Guan (1):
xfrm: fix memory leak in xfrm_add_acquire()
include/net/xfrm.h | 3 ++-
net/ipv4/esp4_offload.c | 6 ++++--
net/ipv6/esp6_offload.c | 6 ++++--
net/xfrm/xfrm_device.c | 2 +-
net/xfrm/xfrm_output.c | 8 ++++++--
net/xfrm/xfrm_state.c | 30 ++++++++++++++++++++++--------
net/xfrm/xfrm_user.c | 8 +++++++-
7 files changed, 46 insertions(+), 17 deletions(-)
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-19 2:10 ` patchwork-bot+netdevbpf
2025-11-18 8:52 ` [PATCH 02/10] xfrm: also call xfrm_state_delete_tunnel at destroy time for states that were never added Steffen Klassert
` (8 subsequent siblings)
9 siblings, 1 reply; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Sabrina Dubroca <sd@queasysnail.net>
We're not updating x1, but we still need to put() it.
Fixes: a4a87fa4e96c ("xfrm: Add Direction to the SA in or out")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_state.c | 8 ++++++--
1 file changed, 6 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index d213ca3653a8..e4736d1ebb44 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2191,14 +2191,18 @@ int xfrm_state_update(struct xfrm_state *x)
}
if (x1->km.state == XFRM_STATE_ACQ) {
- if (x->dir && x1->dir != x->dir)
+ if (x->dir && x1->dir != x->dir) {
+ to_put = x1;
goto out;
+ }
__xfrm_state_insert(x);
x = NULL;
} else {
- if (x1->dir != x->dir)
+ if (x1->dir != x->dir) {
+ to_put = x1;
goto out;
+ }
}
err = 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 02/10] xfrm: also call xfrm_state_delete_tunnel at destroy time for states that were never added
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
2025-11-18 8:52 ` [PATCH 01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 03/10] xfrm: make state as DEAD before final put when migrate fails Steffen Klassert
` (7 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Sabrina Dubroca <sd@queasysnail.net>
In commit b441cf3f8c4b ("xfrm: delete x->tunnel as we delete x"), I
missed the case where state creation fails between full
initialization (->init_state has been called) and being inserted on
the lists.
In this situation, ->init_state has been called, so for IPcomp
tunnels, the fallback tunnel has been created and added onto the
lists, but the user state never gets added, because we fail before
that. The user state doesn't go through __xfrm_state_delete, so we
don't call xfrm_state_delete_tunnel for those states, and we end up
leaking the FB tunnel.
There are several codepaths affected by this: the add/update paths, in
both net/key and xfrm, and the migrate code (xfrm_migrate,
xfrm_state_migrate). A "proper" rollback of the init_state work would
probably be doable in the add/update code, but for migrate it gets
more complicated as multiple states may be involved.
At some point, the new (not-inserted) state will be destroyed, so call
xfrm_state_delete_tunnel during xfrm_state_gc_destroy. Most states
will have their fallback tunnel cleaned up during __xfrm_state_delete,
which solves the issue that b441cf3f8c4b (and other patches before it)
aimed at. All states (including FB tunnels) will be removed from the
lists once xfrm_state_fini has called flush_work(&xfrm_state_gc_work).
Reported-by: syzbot+999eb23467f83f9bf9bf@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=999eb23467f83f9bf9bf
Fixes: b441cf3f8c4b ("xfrm: delete x->tunnel as we delete x")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_state.c | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index e4736d1ebb44..721ef0f409b5 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -592,6 +592,7 @@ void xfrm_state_free(struct xfrm_state *x)
}
EXPORT_SYMBOL(xfrm_state_free);
+static void xfrm_state_delete_tunnel(struct xfrm_state *x);
static void xfrm_state_gc_destroy(struct xfrm_state *x)
{
if (x->mode_cbs && x->mode_cbs->destroy_state)
@@ -607,6 +608,7 @@ static void xfrm_state_gc_destroy(struct xfrm_state *x)
kfree(x->replay_esn);
kfree(x->preplay_esn);
xfrm_unset_type_offload(x);
+ xfrm_state_delete_tunnel(x);
if (x->type) {
x->type->destructor(x);
xfrm_put_type(x->type);
@@ -806,7 +808,6 @@ void __xfrm_state_destroy(struct xfrm_state *x)
}
EXPORT_SYMBOL(__xfrm_state_destroy);
-static void xfrm_state_delete_tunnel(struct xfrm_state *x);
int __xfrm_state_delete(struct xfrm_state *x)
{
struct net *net = xs_net(x);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 03/10] xfrm: make state as DEAD before final put when migrate fails
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
2025-11-18 8:52 ` [PATCH 01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match Steffen Klassert
2025-11-18 8:52 ` [PATCH 02/10] xfrm: also call xfrm_state_delete_tunnel at destroy time for states that were never added Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 04/10] xfrm: call xfrm_dev_state_delete when xfrm_state_migrate fails to add the state Steffen Klassert
` (6 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Sabrina Dubroca <sd@queasysnail.net>
xfrm_state_migrate/xfrm_state_clone_and_setup create a new state, and
call xfrm_state_put to destroy it in case of
failure. __xfrm_state_destroy expects the state to be in
XFRM_STATE_DEAD, but we currently don't do that.
Reported-by: syzbot+5cd6299ede4d4f70987b@syzkaller.appspotmail.com
Closes: https://syzkaller.appspot.com/bug?extid=5cd6299ede4d4f70987b
Fixes: 78347c8c6b2d ("xfrm: Fix xfrm_state_migrate leak")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_state.c | 2 ++
1 file changed, 2 insertions(+)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 721ef0f409b5..1ab19ca007de 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2074,6 +2074,7 @@ static struct xfrm_state *xfrm_state_clone_and_setup(struct xfrm_state *orig,
return x;
error:
+ x->km.state = XFRM_STATE_DEAD;
xfrm_state_put(x);
out:
return NULL;
@@ -2163,6 +2164,7 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
return xc;
error:
+ xc->km.state = XFRM_STATE_DEAD;
xfrm_state_put(xc);
return NULL;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 04/10] xfrm: call xfrm_dev_state_delete when xfrm_state_migrate fails to add the state
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
` (2 preceding siblings ...)
2025-11-18 8:52 ` [PATCH 03/10] xfrm: make state as DEAD before final put when migrate fails Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 05/10] xfrm: set err and extack on failure to create pcpu SA Steffen Klassert
` (5 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Sabrina Dubroca <sd@queasysnail.net>
In case xfrm_state_migrate fails after calling xfrm_dev_state_add, we
directly release the last reference and destroy the new state, without
calling xfrm_dev_state_delete (this only happens in
__xfrm_state_delete, which we're not calling on this path, since the
state was never added).
Call xfrm_dev_state_delete on error when an offload configuration was
provided.
Fixes: ab244a394c7f ("xfrm: Migrate offload configuration")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_state.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index 1ab19ca007de..c3518d1498cd 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -2159,10 +2159,13 @@ struct xfrm_state *xfrm_state_migrate(struct xfrm_state *x,
xfrm_state_insert(xc);
} else {
if (xfrm_state_add(xc) < 0)
- goto error;
+ goto error_add;
}
return xc;
+error_add:
+ if (xuo)
+ xfrm_dev_state_delete(xc);
error:
xc->km.state = XFRM_STATE_DEAD;
xfrm_state_put(xc);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 05/10] xfrm: set err and extack on failure to create pcpu SA
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
` (3 preceding siblings ...)
2025-11-18 8:52 ` [PATCH 04/10] xfrm: call xfrm_dev_state_delete when xfrm_state_migrate fails to add the state Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 06/10] xfrm: check all hash buckets for leftover states during netns deletion Steffen Klassert
` (4 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Sabrina Dubroca <sd@queasysnail.net>
xfrm_state_construct can fail without setting an error if the
requested pcpu_num value is too big. Set err and add an extack message
to avoid confusing userspace.
Fixes: 1ddf9916ac09 ("xfrm: Add support for per cpu xfrm state handling.")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_user.c | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 010c9e6638c0..9d98cc9daa37 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -947,8 +947,11 @@ static struct xfrm_state *xfrm_state_construct(struct net *net,
if (attrs[XFRMA_SA_PCPU]) {
x->pcpu_num = nla_get_u32(attrs[XFRMA_SA_PCPU]);
- if (x->pcpu_num >= num_possible_cpus())
+ if (x->pcpu_num >= num_possible_cpus()) {
+ err = -ERANGE;
+ NL_SET_ERR_MSG(extack, "pCPU number too big");
goto error;
+ }
}
err = __xfrm_init_state(x, extack);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 06/10] xfrm: check all hash buckets for leftover states during netns deletion
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
` (4 preceding siblings ...)
2025-11-18 8:52 ` [PATCH 05/10] xfrm: set err and extack on failure to create pcpu SA Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 07/10] xfrm: Check inner packet family directly from skb_dst Steffen Klassert
` (3 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Sabrina Dubroca <sd@queasysnail.net>
The current hlist_empty checks only test the first bucket of each
hashtable, ignoring any other bucket. They should be caught by the
WARN_ON for state_all, but better to make all the checks accurate.
Fixes: 73d189dce486 ("netns xfrm: per-netns xfrm_state_bydst hash")
Fixes: d320bbb306f2 ("netns xfrm: per-netns xfrm_state_bysrc hash")
Fixes: b754a4fd8f58 ("netns xfrm: per-netns xfrm_state_byspi hash")
Fixes: fe9f1d8779cb ("xfrm: add state hashtable keyed by seq")
Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_state.c | 12 ++++++++----
1 file changed, 8 insertions(+), 4 deletions(-)
diff --git a/net/xfrm/xfrm_state.c b/net/xfrm/xfrm_state.c
index c3518d1498cd..9e14e453b55c 100644
--- a/net/xfrm/xfrm_state.c
+++ b/net/xfrm/xfrm_state.c
@@ -3308,6 +3308,7 @@ int __net_init xfrm_state_init(struct net *net)
void xfrm_state_fini(struct net *net)
{
unsigned int sz;
+ int i;
flush_work(&net->xfrm.state_hash_work);
xfrm_state_flush(net, 0, false);
@@ -3315,14 +3316,17 @@ void xfrm_state_fini(struct net *net)
WARN_ON(!list_empty(&net->xfrm.state_all));
+ for (i = 0; i <= net->xfrm.state_hmask; i++) {
+ WARN_ON(!hlist_empty(net->xfrm.state_byseq + i));
+ WARN_ON(!hlist_empty(net->xfrm.state_byspi + i));
+ WARN_ON(!hlist_empty(net->xfrm.state_bysrc + i));
+ WARN_ON(!hlist_empty(net->xfrm.state_bydst + i));
+ }
+
sz = (net->xfrm.state_hmask + 1) * sizeof(struct hlist_head);
- WARN_ON(!hlist_empty(net->xfrm.state_byseq));
xfrm_hash_free(net->xfrm.state_byseq, sz);
- WARN_ON(!hlist_empty(net->xfrm.state_byspi));
xfrm_hash_free(net->xfrm.state_byspi, sz);
- WARN_ON(!hlist_empty(net->xfrm.state_bysrc));
xfrm_hash_free(net->xfrm.state_bysrc, sz);
- WARN_ON(!hlist_empty(net->xfrm.state_bydst));
xfrm_hash_free(net->xfrm.state_bydst, sz);
free_percpu(net->xfrm.state_cache_input);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 07/10] xfrm: Check inner packet family directly from skb_dst
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
` (5 preceding siblings ...)
2025-11-18 8:52 ` [PATCH 06/10] xfrm: check all hash buckets for leftover states during netns deletion Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 08/10] xfrm: Determine inner GSO type from packet inner protocol Steffen Klassert
` (2 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Jianbo Liu <jianbol@nvidia.com>
In the output path, xfrm_dev_offload_ok and xfrm_get_inner_ipproto
need to determine the protocol family of the inner packet (skb) before
it gets encapsulated.
In xfrm_dev_offload_ok, the code checked x->inner_mode.family. This is
unreliable because, for states handling both IPv4 and IPv6, the
relevant inner family could be either x->inner_mode.family or
x->inner_mode_iaf.family. Checking only the former can lead to a
mismatch with the actual packet being processed.
In xfrm_get_inner_ipproto, the code checked x->outer_mode.family. This
is also incorrect for tunnel mode, as the inner packet's family can be
different from the outer header's family.
At both of these call sites, the skb variable holds the original inner
packet. The most direct and reliable source of truth for its protocol
family is its destination entry. This patch fixes the issue by using
skb_dst(skb)->ops->family to ensure protocol-specific headers are only
accessed for the correct packet type.
Fixes: 91d8a53db219 ("xfrm: fix offloading of cross-family tunnels")
Fixes: 45a98ef4922d ("net/xfrm: IPsec tunnel mode fix inner_ipproto setting in sec_path")
Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Zhu Yanjun <yanjun.zhu@linux.dev>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_device.c | 2 +-
net/xfrm/xfrm_output.c | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/net/xfrm/xfrm_device.c b/net/xfrm/xfrm_device.c
index 44b9de6e4e77..52ae0e034d29 100644
--- a/net/xfrm/xfrm_device.c
+++ b/net/xfrm/xfrm_device.c
@@ -438,7 +438,7 @@ bool xfrm_dev_offload_ok(struct sk_buff *skb, struct xfrm_state *x)
check_tunnel_size = x->xso.type == XFRM_DEV_OFFLOAD_PACKET &&
x->props.mode == XFRM_MODE_TUNNEL;
- switch (x->inner_mode.family) {
+ switch (skb_dst(skb)->ops->family) {
case AF_INET:
/* Check for IPv4 options */
if (ip_hdr(skb)->ihl != 5)
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index 9077730ff7d0..a98b5bf55ac3 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -698,7 +698,7 @@ static void xfrm_get_inner_ipproto(struct sk_buff *skb, struct xfrm_state *x)
return;
if (x->outer_mode.encap == XFRM_MODE_TUNNEL) {
- switch (x->outer_mode.family) {
+ switch (skb_dst(skb)->ops->family) {
case AF_INET:
xo->inner_ipproto = ip_hdr(skb)->protocol;
break;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 08/10] xfrm: Determine inner GSO type from packet inner protocol
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
` (6 preceding siblings ...)
2025-11-18 8:52 ` [PATCH 07/10] xfrm: Check inner packet family directly from skb_dst Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 09/10] xfrm: Prevent locally generated packets from direct output in tunnel mode Steffen Klassert
2025-11-18 8:52 ` [PATCH 10/10] xfrm: fix memory leak in xfrm_add_acquire() Steffen Klassert
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Jianbo Liu <jianbol@nvidia.com>
The GSO segmentation functions for ESP tunnel mode
(xfrm4_tunnel_gso_segment and xfrm6_tunnel_gso_segment) were
determining the inner packet's L2 protocol type by checking the static
x->inner_mode.family field from the xfrm state.
This is unreliable. In tunnel mode, the state's actual inner family
could be defined by x->inner_mode.family or by
x->inner_mode_iaf.family. Checking only the former can lead to a
mismatch with the actual packet being processed, causing GSO to create
segments with the wrong L2 header type.
This patch fixes the bug by deriving the inner mode directly from the
packet's inner protocol stored in XFRM_MODE_SKB_CB(skb)->protocol.
Instead of replicating the code, this patch modifies the
xfrm_ip2inner_mode helper function. It now correctly returns
&x->inner_mode if the selector family (x->sel.family) is already
specified, thereby handling both specific and AF_UNSPEC cases
appropriately.
With this change, ESP GSO can use xfrm_ip2inner_mode to get the
correct inner mode. It doesn't affect existing callers, as the updated
logic now mirrors the checks they were already performing externally.
Fixes: 26dbd66eab80 ("esp: choose the correct inner protocol for GSO on inter address family tunnels")
Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Cosmin Ratiu <cratiu@nvidia.com>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
include/net/xfrm.h | 3 ++-
net/ipv4/esp4_offload.c | 6 ++++--
net/ipv6/esp6_offload.c | 6 ++++--
3 files changed, 10 insertions(+), 5 deletions(-)
diff --git a/include/net/xfrm.h b/include/net/xfrm.h
index f3014e4f54fc..0a14daaa5dd4 100644
--- a/include/net/xfrm.h
+++ b/include/net/xfrm.h
@@ -536,7 +536,8 @@ static inline int xfrm_af2proto(unsigned int family)
static inline const struct xfrm_mode *xfrm_ip2inner_mode(struct xfrm_state *x, int ipproto)
{
- if ((ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
+ if ((x->sel.family != AF_UNSPEC) ||
+ (ipproto == IPPROTO_IPIP && x->props.family == AF_INET) ||
(ipproto == IPPROTO_IPV6 && x->props.family == AF_INET6))
return &x->inner_mode;
else
diff --git a/net/ipv4/esp4_offload.c b/net/ipv4/esp4_offload.c
index e0d94270da28..05828d4cb6cd 100644
--- a/net/ipv4/esp4_offload.c
+++ b/net/ipv4/esp4_offload.c
@@ -122,8 +122,10 @@ static struct sk_buff *xfrm4_tunnel_gso_segment(struct xfrm_state *x,
struct sk_buff *skb,
netdev_features_t features)
{
- __be16 type = x->inner_mode.family == AF_INET6 ? htons(ETH_P_IPV6)
- : htons(ETH_P_IP);
+ const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x,
+ XFRM_MODE_SKB_CB(skb)->protocol);
+ __be16 type = inner_mode->family == AF_INET6 ? htons(ETH_P_IPV6)
+ : htons(ETH_P_IP);
return skb_eth_gso_segment(skb, features, type);
}
diff --git a/net/ipv6/esp6_offload.c b/net/ipv6/esp6_offload.c
index 7b41fb4f00b5..22410243ebe8 100644
--- a/net/ipv6/esp6_offload.c
+++ b/net/ipv6/esp6_offload.c
@@ -158,8 +158,10 @@ static struct sk_buff *xfrm6_tunnel_gso_segment(struct xfrm_state *x,
struct sk_buff *skb,
netdev_features_t features)
{
- __be16 type = x->inner_mode.family == AF_INET ? htons(ETH_P_IP)
- : htons(ETH_P_IPV6);
+ const struct xfrm_mode *inner_mode = xfrm_ip2inner_mode(x,
+ XFRM_MODE_SKB_CB(skb)->protocol);
+ __be16 type = inner_mode->family == AF_INET ? htons(ETH_P_IP)
+ : htons(ETH_P_IPV6);
return skb_eth_gso_segment(skb, features, type);
}
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 09/10] xfrm: Prevent locally generated packets from direct output in tunnel mode
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
` (7 preceding siblings ...)
2025-11-18 8:52 ` [PATCH 08/10] xfrm: Determine inner GSO type from packet inner protocol Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
2025-11-18 8:52 ` [PATCH 10/10] xfrm: fix memory leak in xfrm_add_acquire() Steffen Klassert
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Jianbo Liu <jianbol@nvidia.com>
Add a check to ensure locally generated packets (skb->sk != NULL) do
not use direct output in tunnel mode, as these packets require proper
L2 header setup that is handled by the normal XFRM processing path.
Fixes: 5eddd76ec2fd ("xfrm: fix tunnel mode TX datapath in packet offload mode")
Signed-off-by: Jianbo Liu <jianbol@nvidia.com>
Reviewed-by: Leon Romanovsky <leonro@nvidia.com>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_output.c | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/net/xfrm/xfrm_output.c b/net/xfrm/xfrm_output.c
index a98b5bf55ac3..54222fcbd7fd 100644
--- a/net/xfrm/xfrm_output.c
+++ b/net/xfrm/xfrm_output.c
@@ -772,8 +772,12 @@ int xfrm_output(struct sock *sk, struct sk_buff *skb)
/* Exclusive direct xmit for tunnel mode, as
* some filtering or matching rules may apply
* in transport mode.
+ * Locally generated packets also require
+ * the normal XFRM path for L2 header setup,
+ * as the hardware needs the L2 header to match
+ * for encryption, so skip direct output as well.
*/
- if (x->props.mode == XFRM_MODE_TUNNEL)
+ if (x->props.mode == XFRM_MODE_TUNNEL && !skb->sk)
return xfrm_dev_direct_output(sk, x, skb);
return xfrm_output_resume(sk, skb, 0);
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 10/10] xfrm: fix memory leak in xfrm_add_acquire()
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
` (8 preceding siblings ...)
2025-11-18 8:52 ` [PATCH 09/10] xfrm: Prevent locally generated packets from direct output in tunnel mode Steffen Klassert
@ 2025-11-18 8:52 ` Steffen Klassert
9 siblings, 0 replies; 12+ messages in thread
From: Steffen Klassert @ 2025-11-18 8:52 UTC (permalink / raw)
To: David Miller, Jakub Kicinski; +Cc: Herbert Xu, Steffen Klassert, netdev
From: Zilin Guan <zilin@seu.edu.cn>
The xfrm_add_acquire() function constructs an xfrm policy by calling
xfrm_policy_construct(). This allocates the policy structure and
potentially associates a security context and a device policy with it.
However, at the end of the function, the policy object is freed using
only kfree() . This skips the necessary cleanup for the security context
and device policy, leading to a memory leak.
To fix this, invoke the proper cleanup functions xfrm_dev_policy_delete(),
xfrm_dev_policy_free(), and security_xfrm_policy_free() before freeing the
policy object. This approach mirrors the error handling path in
xfrm_add_policy(), ensuring that all associated resources are correctly
released.
Fixes: 980ebd25794f ("[IPSEC]: Sync series - acquire insert")
Signed-off-by: Zilin Guan <zilin@seu.edu.cn>
Reviewed-by: Sabrina Dubroca <sd@queasysnail.net>
Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
---
net/xfrm/xfrm_user.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index 9d98cc9daa37..403b5ecac2c5 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -3038,6 +3038,9 @@ static int xfrm_add_acquire(struct sk_buff *skb, struct nlmsghdr *nlh,
}
xfrm_state_free(x);
+ xfrm_dev_policy_delete(xp);
+ xfrm_dev_policy_free(xp);
+ security_xfrm_policy_free(xp->security);
kfree(xp);
return 0;
--
2.43.0
^ permalink raw reply related [flat|nested] 12+ messages in thread
* Re: [PATCH 01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match
2025-11-18 8:52 ` [PATCH 01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match Steffen Klassert
@ 2025-11-19 2:10 ` patchwork-bot+netdevbpf
0 siblings, 0 replies; 12+ messages in thread
From: patchwork-bot+netdevbpf @ 2025-11-19 2:10 UTC (permalink / raw)
To: Steffen Klassert; +Cc: davem, kuba, herbert, netdev
Hello:
This series was applied to netdev/net.git (main)
by Steffen Klassert <steffen.klassert@secunet.com>:
On Tue, 18 Nov 2025 09:52:34 +0100 you wrote:
> From: Sabrina Dubroca <sd@queasysnail.net>
>
> We're not updating x1, but we still need to put() it.
>
> Fixes: a4a87fa4e96c ("xfrm: Add Direction to the SA in or out")
> Signed-off-by: Sabrina Dubroca <sd@queasysnail.net>
> Signed-off-by: Steffen Klassert <steffen.klassert@secunet.com>
>
> [...]
Here is the summary with links:
- [01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match
https://git.kernel.org/netdev/net/c/8d2a2a49c30f
- [02/10] xfrm: also call xfrm_state_delete_tunnel at destroy time for states that were never added
https://git.kernel.org/netdev/net/c/10deb6986484
- [03/10] xfrm: make state as DEAD before final put when migrate fails
https://git.kernel.org/netdev/net/c/5502bc4746e8
- [04/10] xfrm: call xfrm_dev_state_delete when xfrm_state_migrate fails to add the state
https://git.kernel.org/netdev/net/c/7f0228576479
- [05/10] xfrm: set err and extack on failure to create pcpu SA
https://git.kernel.org/netdev/net/c/1dcf617bec5c
- [06/10] xfrm: check all hash buckets for leftover states during netns deletion
https://git.kernel.org/netdev/net/c/f2bc8231fd43
- [07/10] xfrm: Check inner packet family directly from skb_dst
https://git.kernel.org/netdev/net/c/082ef944e55d
- [08/10] xfrm: Determine inner GSO type from packet inner protocol
https://git.kernel.org/netdev/net/c/61fafbee6cfe
- [09/10] xfrm: Prevent locally generated packets from direct output in tunnel mode
https://git.kernel.org/netdev/net/c/59630e2ccd72
- [10/10] xfrm: fix memory leak in xfrm_add_acquire()
https://git.kernel.org/netdev/net/c/a55ef3bff84f
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2025-11-19 2:10 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-11-18 8:52 [PATCH 0/10] pull request (net): ipsec 2025-11-18 Steffen Klassert
2025-11-18 8:52 ` [PATCH 01/10] xfrm: drop SA reference in xfrm_state_update if dir doesn't match Steffen Klassert
2025-11-19 2:10 ` patchwork-bot+netdevbpf
2025-11-18 8:52 ` [PATCH 02/10] xfrm: also call xfrm_state_delete_tunnel at destroy time for states that were never added Steffen Klassert
2025-11-18 8:52 ` [PATCH 03/10] xfrm: make state as DEAD before final put when migrate fails Steffen Klassert
2025-11-18 8:52 ` [PATCH 04/10] xfrm: call xfrm_dev_state_delete when xfrm_state_migrate fails to add the state Steffen Klassert
2025-11-18 8:52 ` [PATCH 05/10] xfrm: set err and extack on failure to create pcpu SA Steffen Klassert
2025-11-18 8:52 ` [PATCH 06/10] xfrm: check all hash buckets for leftover states during netns deletion Steffen Klassert
2025-11-18 8:52 ` [PATCH 07/10] xfrm: Check inner packet family directly from skb_dst Steffen Klassert
2025-11-18 8:52 ` [PATCH 08/10] xfrm: Determine inner GSO type from packet inner protocol Steffen Klassert
2025-11-18 8:52 ` [PATCH 09/10] xfrm: Prevent locally generated packets from direct output in tunnel mode Steffen Klassert
2025-11-18 8:52 ` [PATCH 10/10] xfrm: fix memory leak in xfrm_add_acquire() Steffen Klassert
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.