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.