Thread (3 messages) read the whole thread 3 messages, 2 authors, 4d ago

Re: [PATCH net 1/1] xfrm: hold input state around secpath resets

From: Steffen Klassert <steffen.klassert@secunet.com>
Date: 2026-07-28 09:11:53

On Tue, Jul 28, 2026 at 01:44:10AM +0800, Ren Wei wrote:
quoted hunk ↗ jump to hunk
From: Zhiling Zou <redacted>

xfrm_input() keeps the current state reference through the skb secpath
while it performs final transport processing.  Some input paths can reset
the secpath before xfrm_input() is done dereferencing that state.

Receive callback users such as VTI and XFRM interfaces can scrub packets
that cross network namespaces by resetting the secpath.  The
XFRM_MAX_DEPTH error path can also reset the secpath before the final drop
callback reads the current state's type.  If that drops the last state
reference and the state is concurrently deleted, xfrm_input() can still
dereference the freed state.

Take a temporary state reference before invoking the receive callback and
before resetting the secpath on the max-depth error path.  Release it after
xfrm_input() no longer dereferences the state.

Fixes: df3893c176e9 ("vti: Update the ipv4 side to use it's own receive hook.")
Cc: stable@vger.kernel.org
Reported-by: Vega <redacted>
Assisted-by: Codex:gpt-5.4
Signed-off-by: Zhiling Zou <redacted>
Signed-off-by: Ren Wei <redacted>
---
 net/xfrm/xfrm_input.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)
diff --git a/net/xfrm/xfrm_input.c b/net/xfrm/xfrm_input.c
index eecab337bd0a7..f4deca8b4aab2 100644
--- a/net/xfrm/xfrm_input.c
+++ b/net/xfrm/xfrm_input.c
@@ -479,6 +479,7 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 	int async = 0;
 	bool xfrm_gro = false;
 	bool crypto_done = false;
+	bool x_held = false;
 	struct xfrm_offload *xo = xfrm_offload(skb);
 	struct sec_path *sp;
 
@@ -585,6 +586,10 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 		sp = skb_sec_path(skb);
 
 		if (sp->len == XFRM_MAX_DEPTH) {
+			if (x) {
+				xfrm_state_hold(x);
+				x_held = true;
+			}
 			secpath_reset(skb);
 			XFRM_INC_STATS(net, LINUX_MIB_XFRMINBUFFERERROR);
 			goto drop;
@@ -727,6 +732,9 @@ int xfrm_input(struct sk_buff *skb, int nexthdr, __be32 spi, int encap_type)
 		crypto_done = false;
 	} while (!err);
 
+	xfrm_state_hold(x);
This adds an additional refcount on every received packet.
It might make more sense to save afinfo etc. on the stack
instead.
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help