* FAILED: patch "[PATCH] sunrpc: defer rq_argp and rq_resp free until after RCU grace" failed to apply to 6.1-stable tree
@ 2026-09-03 14:06 gregkh
2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin
2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin
0 siblings, 2 replies; 11+ messages in thread
From: gregkh @ 2026-09-03 14:06 UTC (permalink / raw)
To: jlayton, cel; +Cc: stable
The patch below does not apply to the 6.1-stable tree.
If someone wants it applied there, or to any other stable or longterm
tree, then please email the backport, including the original git commit
id to <stable@vger.kernel.org>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.1.y
git checkout FETCH_HEAD
git cherry-pick -x c479bde671cbe2f9e152834a8b0eb7c3c295bbaf
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<stable@vger.kernel.org>' --in-reply-to '2026090350-comment-projector-6988@gregkh' --subject-prefix 'PATCH 6.1.y' 'HEAD^..'
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From c479bde671cbe2f9e152834a8b0eb7c3c295bbaf Mon Sep 17 00:00:00 2001
From: Jeff Layton <jlayton@kernel.org>
Date: Thu, 11 Jun 2026 16:00:47 -0400
Subject: [PATCH] sunrpc: defer rq_argp and rq_resp free until after RCU grace
period
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
svc_rqst_free() frees rqstp->rq_argp and rqstp->rq_resp synchronously
via kfree(), but defers the rqstp struct free via kfree_rcu(). After
svc_exit_thread() calls list_del_rcu() and svc_rqst_free(), there is
a window where RCU readers that started before list_del_rcu() can still
traverse the thread list and find the rqstp. These readers (e.g.
nfsd_nl_rpc_status_get_dumpit()) dereference rqstp->rq_argp, which has
already been freed — a use-after-free.
Fix this by moving the kfree of rq_argp and rq_resp into an explicit
call_rcu() callback alongside the struct free. Resources not accessed
by RCU readers (bvec, buffer pages, scratch folio, auth_data) remain
synchronously freed.
Fixes: 812443865c5f ("sunrpc: add a rcu_head to svc_rqst and use kfree_rcu to free it")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-4-8
Signed-off-by: Jeff Layton <jlayton@kernel.org>
Link: https://patch.msgid.link/20260611-nfsd-testing-v2-4-5b90e276f2d9@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c
index 86d39610cf0a..dd80a2eaaa74 100644
--- a/net/sunrpc/svc.c
+++ b/net/sunrpc/svc.c
@@ -716,6 +716,15 @@ svc_release_buffer(struct svc_rqst *rqstp)
}
}
+static void svc_rqst_free_rcu(struct rcu_head *head)
+{
+ struct svc_rqst *rqstp = container_of(head, struct svc_rqst, rq_rcu_head);
+
+ kfree(rqstp->rq_resp);
+ kfree(rqstp->rq_argp);
+ kfree(rqstp);
+}
+
static void
svc_rqst_free(struct svc_rqst *rqstp)
{
@@ -724,10 +733,8 @@ svc_rqst_free(struct svc_rqst *rqstp)
svc_release_buffer(rqstp);
if (rqstp->rq_scratch_folio)
folio_put(rqstp->rq_scratch_folio);
- kfree(rqstp->rq_resp);
- kfree(rqstp->rq_argp);
kfree(rqstp->rq_auth_data);
- kfree_rcu(rqstp, rq_rcu_head);
+ call_rcu(&rqstp->rq_rcu_head, svc_rqst_free_rcu);
}
static struct svc_rqst *
^ permalink raw reply related [flat|nested] 11+ messages in thread* [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() 2026-09-03 14:06 FAILED: patch "[PATCH] sunrpc: defer rq_argp and rq_resp free until after RCU grace" failed to apply to 6.1-stable tree gregkh @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin ` (3 more replies) 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin 1 sibling, 4 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: NeilBrown, Chuck Lever, Sasha Levin From: NeilBrown <neilb@suse.de> [ Upstream commit c743b4259c3af2c0637c307f08a062d25fa3c99f ] Most svc threads have no interest in a timeout. nfsd sets it to 1 hour, but this is a wart of no significance. lockd uses the timeout so that it can call nlmsvc_retry_blocked(). It also sometimes calls svc_wake_up() to ensure this is called. So change lockd to be consistent and always use svc_wake_up() to trigger nlmsvc_retry_blocked() - using a timer instead of a timeout to svc_recv(). And change svc_recv() to not take a timeout arg. This makes the sp_threads_timedout counter always zero. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> [ Stable backport note: The svc_recv timeout cleanup is unrelated to the follow-up fix and does not fit the older lockd service loop. Drop those hunks. Instead, make the existing svc request allocation/free helpers private, move svc_rqst_free() before its first use, and convert the scratch page to a folio. This aligns the lifetime-management context so the follow-up fix applies cleanly. ] [ sashal: Reduced backport -- upstream c743b4259c3af touches 9 file(s), this backport carries 2. Not backported here: fs/lockd/svc.c fs/lockd/svclock.c fs/nfs/callback.c fs/nfsd/nfssvc.c include/linux/lockd/lockd.h include/linux/sunrpc/svcsock.h net/sunrpc/svc_xprt.c This note is generated from the file lists only; see the resolution record for the reasoning. ] Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/svc.h | 7 ++----- net/sunrpc/svc.c | 38 +++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 49621cc4e01bd..d26e01c63dde0 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -247,7 +247,7 @@ struct svc_rqst { struct xdr_buf rq_arg; struct xdr_stream rq_arg_stream; struct xdr_stream rq_res_stream; - struct page *rq_scratch_page; + struct folio *rq_scratch_folio; struct xdr_buf rq_res; struct page *rq_pages[RPCSVC_MAXPAGES + 1]; struct page * *rq_respages; /* points into rq_pages */ @@ -473,11 +473,8 @@ void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); int svc_bind(struct svc_serv *serv, struct net *net); struct svc_serv *svc_create(struct svc_program *, unsigned int, int (*threadfn)(void *data)); -struct svc_rqst *svc_rqst_alloc(struct svc_serv *serv, - struct svc_pool *pool, int node); void svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page); -void svc_rqst_free(struct svc_rqst *); void svc_exit_thread(struct svc_rqst *); struct svc_serv * svc_create_pooled(struct svc_program *prog, struct svc_stat *stats, @@ -554,7 +551,7 @@ static inline void svcxdr_init_decode(struct svc_rqst *rqstp) buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len; xdr_init_decode(xdr, buf, argv->iov_base, NULL); - xdr_set_scratch_page(xdr, rqstp->rq_scratch_page); + xdr_set_scratch_page(xdr, folio_page(rqstp->rq_scratch_folio, 0)); } /** diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 9ae85347ab397..faa5193231240 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -630,7 +630,19 @@ svc_release_buffer(struct svc_rqst *rqstp) put_page(rqstp->rq_pages[i]); } -struct svc_rqst * +static void +svc_rqst_free(struct svc_rqst *rqstp) +{ + svc_release_buffer(rqstp); + if (rqstp->rq_scratch_folio) + folio_put(rqstp->rq_scratch_folio); + kfree(rqstp->rq_resp); + kfree(rqstp->rq_argp); + kfree(rqstp->rq_auth_data); + kfree_rcu(rqstp, rq_rcu_head); +} + +static struct svc_rqst * svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) { struct svc_rqst *rqstp; @@ -644,8 +656,10 @@ svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) rqstp->rq_server = serv; rqstp->rq_pool = pool; - rqstp->rq_scratch_page = alloc_pages_node(node, GFP_KERNEL, 0); - if (!rqstp->rq_scratch_page) + if (node == NUMA_NO_NODE) + node = numa_mem_id(); + rqstp->rq_scratch_folio = __folio_alloc_node(GFP_KERNEL, 0, node); + if (!rqstp->rq_scratch_folio) goto out_enomem; rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); @@ -664,7 +678,6 @@ svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) svc_rqst_free(rqstp); return NULL; } -EXPORT_SYMBOL_GPL(svc_rqst_alloc); static struct svc_rqst * svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) @@ -847,23 +860,6 @@ void svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page) } EXPORT_SYMBOL_GPL(svc_rqst_replace_page); -/* - * Called from a server thread as it's exiting. Caller must hold the "service - * mutex" for the service. - */ -void -svc_rqst_free(struct svc_rqst *rqstp) -{ - svc_release_buffer(rqstp); - if (rqstp->rq_scratch_page) - put_page(rqstp->rq_scratch_page); - kfree(rqstp->rq_resp); - kfree(rqstp->rq_argp); - kfree(rqstp->rq_auth_data); - kfree_rcu(rqstp, rq_rcu_head); -} -EXPORT_SYMBOL_GPL(svc_rqst_free); - void svc_exit_thread(struct svc_rqst *rqstp) { -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported. 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() Sasha Levin ` (2 subsequent siblings) 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: NeilBrown, Chuck Lever, Sasha Levin From: NeilBrown <neilb@suse.de> [ Upstream commit f2b27e1d72527f94f030b6356b3187576e60885b ] Various functions are only used within the sunrpc module, and several are only use in the one file. So clean up: These are marked static, and any EXPORT is removed. svc_rcpb_setup() svc_rqst_alloc() svc_rqst_free() - also moved before first use svc_rpcbind_set_version() svc_drop() - also moved to svc.c These are now not EXPORTed, but are not static. svc_authenticate() svc_sock_update_bufs() Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> [ Stable backport note: svc_rqst_alloc() and svc_rqst_free() are already static, and the latter already precedes its first use, in the preceding dependency. Keep that implementation and its scratch folio handling. Do not import the newer page-release helper or authentication interfaces. Retain the visibility cleanup for svc_rpcb_setup(), svc_rpcbind_set_version(), svc_authenticate(), and svc_sock_update_bufs(). Declare svc_authenticate() as int in the private header to match 6.1. Keep svc_drop() in svc_xprt.c: it still calls the file-local svc_xprt_release(), which upstream no longer calls from svc_drop(). Add braces around the existing svc_release_buffer() page-release loop, without changing its behavior, to provide the exact context required by the first hunk of c479bde671cb. No functions are added. ] [ sashal: Reduced backport -- upstream f2b27e1d72527 touches 8 file(s), this backport carries 7. Not backported here: net/sunrpc/svc_xprt.c This note is generated from the file lists only; see the resolution record for the reasoning. ] Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/svc.h | 6 ------ include/linux/sunrpc/svcauth.h | 1 - include/linux/sunrpc/svcsock.h | 1 - net/sunrpc/sunrpc.h | 4 ++++ net/sunrpc/svc.c | 10 +++++----- net/sunrpc/svcauth.c | 1 - net/sunrpc/svcsock.c | 1 - 7 files changed, 9 insertions(+), 15 deletions(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index d26e01c63dde0..4144a256fc255 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -468,7 +468,6 @@ struct svc_procedure { /* * Function prototypes. */ -int svc_rpcb_setup(struct svc_serv *serv, struct net *net); void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); int svc_bind(struct svc_serv *serv, struct net *net); struct svc_serv *svc_create(struct svc_program *, unsigned int, @@ -509,11 +508,6 @@ int svc_generic_rpcbind_set(struct net *net, u32 version, int family, unsigned short proto, unsigned short port); -int svc_rpcbind_set_version(struct net *net, - const struct svc_program *progp, - u32 version, int family, - unsigned short proto, - unsigned short port); #define RPC_MAX_ADDRBUFLEN (63U) diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index 6d9cc9080aca7..5e11fbe1fe463 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -149,7 +149,6 @@ struct auth_ops { struct svc_xprt; -extern int svc_authenticate(struct svc_rqst *rqstp); extern int svc_authorise(struct svc_rqst *rqstp); extern int svc_set_client(struct svc_rqst *rqstp); extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops); diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index 13aff355d5a13..cfcdbf4def22c 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -58,7 +58,6 @@ void svc_close_net(struct svc_serv *, struct net *); int svc_recv(struct svc_rqst *, long); int svc_send(struct svc_rqst *); void svc_drop(struct svc_rqst *); -void svc_sock_update_bufs(struct svc_serv *serv); int svc_addsock(struct svc_serv *serv, struct net *net, const int fd, char *name_return, const size_t len, const struct cred *cred); diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h index d4a362c9e4b3b..07ab21b64f904 100644 --- a/net/sunrpc/sunrpc.h +++ b/net/sunrpc/sunrpc.h @@ -36,7 +36,11 @@ static inline int sock_is_loopback(struct sock *sk) return loopback; } +struct svc_serv; +struct svc_rqst; int rpc_clients_notifier_register(void); void rpc_clients_notifier_unregister(void); void auth_domain_cleanup(void); +void svc_sock_update_bufs(struct svc_serv *serv); +int svc_authenticate(struct svc_rqst *rqstp); #endif /* _NET_SUNRPC_SUNRPC_H */ diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index faa5193231240..3fe7152ee8bf5 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -32,6 +32,7 @@ #include <trace/events/sunrpc.h> #include "fail.h" +#include "sunrpc.h" #define RPCDBG_FACILITY RPCDBG_SVCDSP @@ -388,7 +389,7 @@ struct svc_pool *svc_pool_for_cpu(struct svc_serv *serv) return &serv->sv_pools[pidx % serv->sv_nrpools]; } -int svc_rpcb_setup(struct svc_serv *serv, struct net *net) +static int svc_rpcb_setup(struct svc_serv *serv, struct net *net) { int err; @@ -400,7 +401,6 @@ int svc_rpcb_setup(struct svc_serv *serv, struct net *net) svc_unregister(serv, net); return 0; } -EXPORT_SYMBOL_GPL(svc_rpcb_setup); void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net) { @@ -625,9 +625,10 @@ svc_release_buffer(struct svc_rqst *rqstp) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++) + for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++) { if (rqstp->rq_pages[i]) put_page(rqstp->rq_pages[i]); + } } static void @@ -1009,7 +1010,7 @@ static int __svc_register(struct net *net, const char *progname, return error; } -int svc_rpcbind_set_version(struct net *net, +static int svc_rpcbind_set_version(struct net *net, const struct svc_program *progp, u32 version, int family, unsigned short proto, @@ -1019,7 +1020,6 @@ int svc_rpcbind_set_version(struct net *net, version, family, proto, port); } -EXPORT_SYMBOL_GPL(svc_rpcbind_set_version); int svc_generic_rpcbind_set(struct net *net, const struct svc_program *progp, diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c index e72ba2f13f6c6..1694c01bbaf9c 100644 --- a/net/sunrpc/svcauth.c +++ b/net/sunrpc/svcauth.c @@ -84,7 +84,6 @@ svc_authenticate(struct svc_rqst *rqstp) rqstp->rq_authop = aops; return aops->accept(rqstp); } -EXPORT_SYMBOL_GPL(svc_authenticate); int svc_set_client(struct svc_rqst *rqstp) { diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 23b4c728de598..e6204afa78fd6 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1283,7 +1283,6 @@ void svc_sock_update_bufs(struct svc_serv *serv) set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); spin_unlock_bh(&serv->sv_lock); } -EXPORT_SYMBOL_GPL(svc_sock_update_bufs); /* * Initialize socket for RPC use and create svc_sock struct -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period Sasha Levin 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: Anna Schumaker, Sasha Levin From: Anna Schumaker <anna.schumaker@oracle.com> [ Upstream commit c8a127596edc026e5364a7a609986dcd3999914c ] This will replace xdr_set_scratch_page() when we switch pages to folios. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/xdr.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index f84e2a1358e17..2b73b3db87d99 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -299,6 +299,19 @@ xdr_set_scratch_page(struct xdr_stream *xdr, struct page *page) xdr_set_scratch_buffer(xdr, page_address(page), PAGE_SIZE); } +/** + * xdr_set_scratch_folio - Attach a scratch buffer for decoding data + * @xdr: pointer to xdr_stream struct + * @page: an anonymous folio + * + * See xdr_set_scratch_buffer(). + */ +static inline void +xdr_set_scratch_folio(struct xdr_stream *xdr, struct folio *folio) +{ + xdr_set_scratch_buffer(xdr, folio_address(folio), folio_size(folio)); +} + /** * xdr_reset_scratch_buffer - Clear scratch buffer information * @xdr: pointer to xdr_stream struct -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period Sasha Levin 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: Anna Schumaker, Sasha Levin From: Anna Schumaker <anna.schumaker@oracle.com> [ Upstream commit d57e43b72bf2071caac90da323849c3983a695f0 ] The only snag here is that __folio_alloc_node() doesn't handle NUMA_NO_NODE, so I also need to update svc_pool_map_get_node() to return numa_mem_id() instead. I arrived at this approach by looking at what other users of __folio_alloc_node() do for this case. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> [ Stable backport note: Earlier dependencies already converted rq_scratch_page to rq_scratch_folio, including allocation and release. Keep those changes and switch svcxdr_init_decode() to the xdr_set_scratch_folio() helper added by the immediately preceding dependency. Drop the svc_pool_map_get_node() change: svc_rqst_alloc() already converts NUMA_NO_NODE to numa_mem_id() before __folio_alloc_node(). Preserve that fallback and the existing pool/thread placement policy. The resulting dependency changes only the existing decoder helper call; no functions are added. The scratch-folio release and surrounding context required by c479bde671cb are retained, and its patch applies cleanly. ] [ sashal: Reduced backport -- upstream d57e43b72bf20 touches 2 file(s), this backport carries 1. Not backported here: net/sunrpc/svc.c This note is generated from the file lists only; see the resolution record for the reasoning. ] Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/svc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 4144a256fc255..40ab44b993cf9 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -545,7 +545,7 @@ static inline void svcxdr_init_decode(struct svc_rqst *rqstp) buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len; xdr_init_decode(xdr, buf, argv->iov_base, NULL); - xdr_set_scratch_page(xdr, folio_page(rqstp->rq_scratch_folio, 0)); + xdr_set_scratch_folio(xdr, rqstp->rq_scratch_folio); } /** -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin ` (2 preceding siblings ...) 2026-09-09 0:25 ` [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: Jeff Layton, Chuck Lever, Sasha Levin From: Jeff Layton <jlayton@kernel.org> [ Upstream commit c479bde671cbe2f9e152834a8b0eb7c3c295bbaf ] svc_rqst_free() frees rqstp->rq_argp and rqstp->rq_resp synchronously via kfree(), but defers the rqstp struct free via kfree_rcu(). After svc_exit_thread() calls list_del_rcu() and svc_rqst_free(), there is a window where RCU readers that started before list_del_rcu() can still traverse the thread list and find the rqstp. These readers (e.g. nfsd_nl_rpc_status_get_dumpit()) dereference rqstp->rq_argp, which has already been freed — a use-after-free. Fix this by moving the kfree of rq_argp and rq_resp into an explicit call_rcu() callback alongside the struct free. Resources not accessed by RCU readers (bvec, buffer pages, scratch folio, auth_data) remain synchronously freed. Fixes: 812443865c5f ("sunrpc: add a rcu_head to svc_rqst and use kfree_rcu to free it") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260611-nfsd-testing-v2-4-5b90e276f2d9@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> --- net/sunrpc/svc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 3fe7152ee8bf5..c3d18ff3ce296 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -631,16 +631,23 @@ svc_release_buffer(struct svc_rqst *rqstp) } } +static void svc_rqst_free_rcu(struct rcu_head *head) +{ + struct svc_rqst *rqstp = container_of(head, struct svc_rqst, rq_rcu_head); + + kfree(rqstp->rq_resp); + kfree(rqstp->rq_argp); + kfree(rqstp); +} + static void svc_rqst_free(struct svc_rqst *rqstp) { svc_release_buffer(rqstp); if (rqstp->rq_scratch_folio) folio_put(rqstp->rq_scratch_folio); - kfree(rqstp->rq_resp); - kfree(rqstp->rq_argp); kfree(rqstp->rq_auth_data); - kfree_rcu(rqstp, rq_rcu_head); + call_rcu(&rqstp->rq_rcu_head, svc_rqst_free_rcu); } static struct svc_rqst * -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() 2026-09-03 14:06 FAILED: patch "[PATCH] sunrpc: defer rq_argp and rq_resp free until after RCU grace" failed to apply to 6.1-stable tree gregkh 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin ` (3 more replies) 1 sibling, 4 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: NeilBrown, Chuck Lever, Sasha Levin From: NeilBrown <neilb@suse.de> [ Upstream commit c743b4259c3af2c0637c307f08a062d25fa3c99f ] Most svc threads have no interest in a timeout. nfsd sets it to 1 hour, but this is a wart of no significance. lockd uses the timeout so that it can call nlmsvc_retry_blocked(). It also sometimes calls svc_wake_up() to ensure this is called. So change lockd to be consistent and always use svc_wake_up() to trigger nlmsvc_retry_blocked() - using a timer instead of a timeout to svc_recv(). And change svc_recv() to not take a timeout arg. This makes the sp_threads_timedout counter always zero. Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> [ Stable backport note: The svc_recv timeout cleanup is unrelated to the follow-up fix and does not fit the older lockd service loop. Drop those hunks. Instead, make the existing svc request allocation/free helpers private, move svc_rqst_free() before its first use, and convert the scratch page to a folio. This aligns the lifetime-management context so the follow-up fix applies cleanly. ] [ sashal: Reduced backport -- upstream c743b4259c3af touches 9 file(s), this backport carries 2. Not backported here: fs/lockd/svc.c fs/lockd/svclock.c fs/nfs/callback.c fs/nfsd/nfssvc.c include/linux/lockd/lockd.h include/linux/sunrpc/svcsock.h net/sunrpc/svc_xprt.c This note is generated from the file lists only; see the resolution record for the reasoning. ] Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/svc.h | 7 ++----- net/sunrpc/svc.c | 38 +++++++++++++++++--------------------- 2 files changed, 19 insertions(+), 26 deletions(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 49621cc4e01bd..d26e01c63dde0 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -247,7 +247,7 @@ struct svc_rqst { struct xdr_buf rq_arg; struct xdr_stream rq_arg_stream; struct xdr_stream rq_res_stream; - struct page *rq_scratch_page; + struct folio *rq_scratch_folio; struct xdr_buf rq_res; struct page *rq_pages[RPCSVC_MAXPAGES + 1]; struct page * *rq_respages; /* points into rq_pages */ @@ -473,11 +473,8 @@ void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); int svc_bind(struct svc_serv *serv, struct net *net); struct svc_serv *svc_create(struct svc_program *, unsigned int, int (*threadfn)(void *data)); -struct svc_rqst *svc_rqst_alloc(struct svc_serv *serv, - struct svc_pool *pool, int node); void svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page); -void svc_rqst_free(struct svc_rqst *); void svc_exit_thread(struct svc_rqst *); struct svc_serv * svc_create_pooled(struct svc_program *prog, struct svc_stat *stats, @@ -554,7 +551,7 @@ static inline void svcxdr_init_decode(struct svc_rqst *rqstp) buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len; xdr_init_decode(xdr, buf, argv->iov_base, NULL); - xdr_set_scratch_page(xdr, rqstp->rq_scratch_page); + xdr_set_scratch_page(xdr, folio_page(rqstp->rq_scratch_folio, 0)); } /** diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 9ae85347ab397..faa5193231240 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -630,7 +630,19 @@ svc_release_buffer(struct svc_rqst *rqstp) put_page(rqstp->rq_pages[i]); } -struct svc_rqst * +static void +svc_rqst_free(struct svc_rqst *rqstp) +{ + svc_release_buffer(rqstp); + if (rqstp->rq_scratch_folio) + folio_put(rqstp->rq_scratch_folio); + kfree(rqstp->rq_resp); + kfree(rqstp->rq_argp); + kfree(rqstp->rq_auth_data); + kfree_rcu(rqstp, rq_rcu_head); +} + +static struct svc_rqst * svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) { struct svc_rqst *rqstp; @@ -644,8 +656,10 @@ svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) rqstp->rq_server = serv; rqstp->rq_pool = pool; - rqstp->rq_scratch_page = alloc_pages_node(node, GFP_KERNEL, 0); - if (!rqstp->rq_scratch_page) + if (node == NUMA_NO_NODE) + node = numa_mem_id(); + rqstp->rq_scratch_folio = __folio_alloc_node(GFP_KERNEL, 0, node); + if (!rqstp->rq_scratch_folio) goto out_enomem; rqstp->rq_argp = kmalloc_node(serv->sv_xdrsize, GFP_KERNEL, node); @@ -664,7 +678,6 @@ svc_rqst_alloc(struct svc_serv *serv, struct svc_pool *pool, int node) svc_rqst_free(rqstp); return NULL; } -EXPORT_SYMBOL_GPL(svc_rqst_alloc); static struct svc_rqst * svc_prepare_thread(struct svc_serv *serv, struct svc_pool *pool, int node) @@ -847,23 +860,6 @@ void svc_rqst_replace_page(struct svc_rqst *rqstp, struct page *page) } EXPORT_SYMBOL_GPL(svc_rqst_replace_page); -/* - * Called from a server thread as it's exiting. Caller must hold the "service - * mutex" for the service. - */ -void -svc_rqst_free(struct svc_rqst *rqstp) -{ - svc_release_buffer(rqstp); - if (rqstp->rq_scratch_page) - put_page(rqstp->rq_scratch_page); - kfree(rqstp->rq_resp); - kfree(rqstp->rq_argp); - kfree(rqstp->rq_auth_data); - kfree_rcu(rqstp, rq_rcu_head); -} -EXPORT_SYMBOL_GPL(svc_rqst_free); - void svc_exit_thread(struct svc_rqst *rqstp) { -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported. 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() Sasha Levin ` (2 subsequent siblings) 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: NeilBrown, Chuck Lever, Sasha Levin From: NeilBrown <neilb@suse.de> [ Upstream commit f2b27e1d72527f94f030b6356b3187576e60885b ] Various functions are only used within the sunrpc module, and several are only use in the one file. So clean up: These are marked static, and any EXPORT is removed. svc_rcpb_setup() svc_rqst_alloc() svc_rqst_free() - also moved before first use svc_rpcbind_set_version() svc_drop() - also moved to svc.c These are now not EXPORTed, but are not static. svc_authenticate() svc_sock_update_bufs() Signed-off-by: NeilBrown <neilb@suse.de> Signed-off-by: Chuck Lever <chuck.lever@oracle.com> [ Stable backport note: svc_rqst_alloc() and svc_rqst_free() are already static, and the latter already precedes its first use, in the preceding dependency. Keep that implementation and its scratch folio handling. Do not import the newer page-release helper or authentication interfaces. Retain the visibility cleanup for svc_rpcb_setup(), svc_rpcbind_set_version(), svc_authenticate(), and svc_sock_update_bufs(). Declare svc_authenticate() as int in the private header to match 6.1. Keep svc_drop() in svc_xprt.c: it still calls the file-local svc_xprt_release(), which upstream no longer calls from svc_drop(). Add braces around the existing svc_release_buffer() page-release loop, without changing its behavior, to provide the exact context required by the first hunk of c479bde671cb. No functions are added. ] [ sashal: Reduced backport -- upstream f2b27e1d72527 touches 8 file(s), this backport carries 7. Not backported here: net/sunrpc/svc_xprt.c This note is generated from the file lists only; see the resolution record for the reasoning. ] Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/svc.h | 6 ------ include/linux/sunrpc/svcauth.h | 1 - include/linux/sunrpc/svcsock.h | 1 - net/sunrpc/sunrpc.h | 4 ++++ net/sunrpc/svc.c | 10 +++++----- net/sunrpc/svcauth.c | 1 - net/sunrpc/svcsock.c | 1 - 7 files changed, 9 insertions(+), 15 deletions(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index d26e01c63dde0..4144a256fc255 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -468,7 +468,6 @@ struct svc_procedure { /* * Function prototypes. */ -int svc_rpcb_setup(struct svc_serv *serv, struct net *net); void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net); int svc_bind(struct svc_serv *serv, struct net *net); struct svc_serv *svc_create(struct svc_program *, unsigned int, @@ -509,11 +508,6 @@ int svc_generic_rpcbind_set(struct net *net, u32 version, int family, unsigned short proto, unsigned short port); -int svc_rpcbind_set_version(struct net *net, - const struct svc_program *progp, - u32 version, int family, - unsigned short proto, - unsigned short port); #define RPC_MAX_ADDRBUFLEN (63U) diff --git a/include/linux/sunrpc/svcauth.h b/include/linux/sunrpc/svcauth.h index 6d9cc9080aca7..5e11fbe1fe463 100644 --- a/include/linux/sunrpc/svcauth.h +++ b/include/linux/sunrpc/svcauth.h @@ -149,7 +149,6 @@ struct auth_ops { struct svc_xprt; -extern int svc_authenticate(struct svc_rqst *rqstp); extern int svc_authorise(struct svc_rqst *rqstp); extern int svc_set_client(struct svc_rqst *rqstp); extern int svc_auth_register(rpc_authflavor_t flavor, struct auth_ops *aops); diff --git a/include/linux/sunrpc/svcsock.h b/include/linux/sunrpc/svcsock.h index 13aff355d5a13..cfcdbf4def22c 100644 --- a/include/linux/sunrpc/svcsock.h +++ b/include/linux/sunrpc/svcsock.h @@ -58,7 +58,6 @@ void svc_close_net(struct svc_serv *, struct net *); int svc_recv(struct svc_rqst *, long); int svc_send(struct svc_rqst *); void svc_drop(struct svc_rqst *); -void svc_sock_update_bufs(struct svc_serv *serv); int svc_addsock(struct svc_serv *serv, struct net *net, const int fd, char *name_return, const size_t len, const struct cred *cred); diff --git a/net/sunrpc/sunrpc.h b/net/sunrpc/sunrpc.h index d4a362c9e4b3b..07ab21b64f904 100644 --- a/net/sunrpc/sunrpc.h +++ b/net/sunrpc/sunrpc.h @@ -36,7 +36,11 @@ static inline int sock_is_loopback(struct sock *sk) return loopback; } +struct svc_serv; +struct svc_rqst; int rpc_clients_notifier_register(void); void rpc_clients_notifier_unregister(void); void auth_domain_cleanup(void); +void svc_sock_update_bufs(struct svc_serv *serv); +int svc_authenticate(struct svc_rqst *rqstp); #endif /* _NET_SUNRPC_SUNRPC_H */ diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index faa5193231240..3fe7152ee8bf5 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -32,6 +32,7 @@ #include <trace/events/sunrpc.h> #include "fail.h" +#include "sunrpc.h" #define RPCDBG_FACILITY RPCDBG_SVCDSP @@ -388,7 +389,7 @@ struct svc_pool *svc_pool_for_cpu(struct svc_serv *serv) return &serv->sv_pools[pidx % serv->sv_nrpools]; } -int svc_rpcb_setup(struct svc_serv *serv, struct net *net) +static int svc_rpcb_setup(struct svc_serv *serv, struct net *net) { int err; @@ -400,7 +401,6 @@ int svc_rpcb_setup(struct svc_serv *serv, struct net *net) svc_unregister(serv, net); return 0; } -EXPORT_SYMBOL_GPL(svc_rpcb_setup); void svc_rpcb_cleanup(struct svc_serv *serv, struct net *net) { @@ -625,9 +625,10 @@ svc_release_buffer(struct svc_rqst *rqstp) { unsigned int i; - for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++) + for (i = 0; i < ARRAY_SIZE(rqstp->rq_pages); i++) { if (rqstp->rq_pages[i]) put_page(rqstp->rq_pages[i]); + } } static void @@ -1009,7 +1010,7 @@ static int __svc_register(struct net *net, const char *progname, return error; } -int svc_rpcbind_set_version(struct net *net, +static int svc_rpcbind_set_version(struct net *net, const struct svc_program *progp, u32 version, int family, unsigned short proto, @@ -1019,7 +1020,6 @@ int svc_rpcbind_set_version(struct net *net, version, family, proto, port); } -EXPORT_SYMBOL_GPL(svc_rpcbind_set_version); int svc_generic_rpcbind_set(struct net *net, const struct svc_program *progp, diff --git a/net/sunrpc/svcauth.c b/net/sunrpc/svcauth.c index e72ba2f13f6c6..1694c01bbaf9c 100644 --- a/net/sunrpc/svcauth.c +++ b/net/sunrpc/svcauth.c @@ -84,7 +84,6 @@ svc_authenticate(struct svc_rqst *rqstp) rqstp->rq_authop = aops; return aops->accept(rqstp); } -EXPORT_SYMBOL_GPL(svc_authenticate); int svc_set_client(struct svc_rqst *rqstp) { diff --git a/net/sunrpc/svcsock.c b/net/sunrpc/svcsock.c index 23b4c728de598..e6204afa78fd6 100644 --- a/net/sunrpc/svcsock.c +++ b/net/sunrpc/svcsock.c @@ -1283,7 +1283,6 @@ void svc_sock_update_bufs(struct svc_serv *serv) set_bit(XPT_CHNGBUF, &svsk->sk_xprt.xpt_flags); spin_unlock_bh(&serv->sv_lock); } -EXPORT_SYMBOL_GPL(svc_sock_update_bufs); /* * Initialize socket for RPC use and create svc_sock struct -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period Sasha Levin 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: Anna Schumaker, Sasha Levin From: Anna Schumaker <anna.schumaker@oracle.com> [ Upstream commit c8a127596edc026e5364a7a609986dcd3999914c ] This will replace xdr_set_scratch_page() when we switch pages to folios. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/xdr.h | 13 +++++++++++++ 1 file changed, 13 insertions(+) diff --git a/include/linux/sunrpc/xdr.h b/include/linux/sunrpc/xdr.h index f84e2a1358e17..2b73b3db87d99 100644 --- a/include/linux/sunrpc/xdr.h +++ b/include/linux/sunrpc/xdr.h @@ -299,6 +299,19 @@ xdr_set_scratch_page(struct xdr_stream *xdr, struct page *page) xdr_set_scratch_buffer(xdr, page_address(page), PAGE_SIZE); } +/** + * xdr_set_scratch_folio - Attach a scratch buffer for decoding data + * @xdr: pointer to xdr_stream struct + * @page: an anonymous folio + * + * See xdr_set_scratch_buffer(). + */ +static inline void +xdr_set_scratch_folio(struct xdr_stream *xdr, struct folio *folio) +{ + xdr_set_scratch_buffer(xdr, folio_address(folio), folio_size(folio)); +} + /** * xdr_reset_scratch_buffer - Clear scratch buffer information * @xdr: pointer to xdr_stream struct -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period Sasha Levin 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: Anna Schumaker, Sasha Levin From: Anna Schumaker <anna.schumaker@oracle.com> [ Upstream commit d57e43b72bf2071caac90da323849c3983a695f0 ] The only snag here is that __folio_alloc_node() doesn't handle NUMA_NO_NODE, so I also need to update svc_pool_map_get_node() to return numa_mem_id() instead. I arrived at this approach by looking at what other users of __folio_alloc_node() do for this case. Signed-off-by: Anna Schumaker <anna.schumaker@oracle.com> [ Stable backport note: Earlier dependencies already converted rq_scratch_page to rq_scratch_folio, including allocation and release. Keep those changes and switch svcxdr_init_decode() to the xdr_set_scratch_folio() helper added by the immediately preceding dependency. Drop the svc_pool_map_get_node() change: svc_rqst_alloc() already converts NUMA_NO_NODE to numa_mem_id() before __folio_alloc_node(). Preserve that fallback and the existing pool/thread placement policy. The resulting dependency changes only the existing decoder helper call; no functions are added. The scratch-folio release and surrounding context required by c479bde671cb are retained, and its patch applies cleanly. ] [ sashal: Reduced backport -- upstream d57e43b72bf20 touches 2 file(s), this backport carries 1. Not backported here: net/sunrpc/svc.c This note is generated from the file lists only; see the resolution record for the reasoning. ] Stable-dep-of: c479bde671cb ("sunrpc: defer rq_argp and rq_resp free until after RCU grace period") Signed-off-by: Sasha Levin <sashal@kernel.org> --- include/linux/sunrpc/svc.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h index 4144a256fc255..40ab44b993cf9 100644 --- a/include/linux/sunrpc/svc.h +++ b/include/linux/sunrpc/svc.h @@ -545,7 +545,7 @@ static inline void svcxdr_init_decode(struct svc_rqst *rqstp) buf->len = buf->head->iov_len + buf->page_len + buf->tail->iov_len; xdr_init_decode(xdr, buf, argv->iov_base, NULL); - xdr_set_scratch_page(xdr, folio_page(rqstp->rq_scratch_folio, 0)); + xdr_set_scratch_folio(xdr, rqstp->rq_scratch_folio); } /** -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
* [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin ` (2 preceding siblings ...) 2026-09-09 0:25 ` [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() Sasha Levin @ 2026-09-09 0:25 ` Sasha Levin 3 siblings, 0 replies; 11+ messages in thread From: Sasha Levin @ 2026-09-09 0:25 UTC (permalink / raw) To: stable; +Cc: Jeff Layton, Chuck Lever, Sasha Levin From: Jeff Layton <jlayton@kernel.org> [ Upstream commit c479bde671cbe2f9e152834a8b0eb7c3c295bbaf ] svc_rqst_free() frees rqstp->rq_argp and rqstp->rq_resp synchronously via kfree(), but defers the rqstp struct free via kfree_rcu(). After svc_exit_thread() calls list_del_rcu() and svc_rqst_free(), there is a window where RCU readers that started before list_del_rcu() can still traverse the thread list and find the rqstp. These readers (e.g. nfsd_nl_rpc_status_get_dumpit()) dereference rqstp->rq_argp, which has already been freed — a use-after-free. Fix this by moving the kfree of rq_argp and rq_resp into an explicit call_rcu() callback alongside the struct free. Resources not accessed by RCU readers (bvec, buffer pages, scratch folio, auth_data) remain synchronously freed. Fixes: 812443865c5f ("sunrpc: add a rcu_head to svc_rqst and use kfree_rcu to free it") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260611-nfsd-testing-v2-4-5b90e276f2d9@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org> Signed-off-by: Sasha Levin <sashal@kernel.org> --- net/sunrpc/svc.c | 13 ++++++++++--- 1 file changed, 10 insertions(+), 3 deletions(-) diff --git a/net/sunrpc/svc.c b/net/sunrpc/svc.c index 3fe7152ee8bf5..c3d18ff3ce296 100644 --- a/net/sunrpc/svc.c +++ b/net/sunrpc/svc.c @@ -631,16 +631,23 @@ svc_release_buffer(struct svc_rqst *rqstp) } } +static void svc_rqst_free_rcu(struct rcu_head *head) +{ + struct svc_rqst *rqstp = container_of(head, struct svc_rqst, rq_rcu_head); + + kfree(rqstp->rq_resp); + kfree(rqstp->rq_argp); + kfree(rqstp); +} + static void svc_rqst_free(struct svc_rqst *rqstp) { svc_release_buffer(rqstp); if (rqstp->rq_scratch_folio) folio_put(rqstp->rq_scratch_folio); - kfree(rqstp->rq_resp); - kfree(rqstp->rq_argp); kfree(rqstp->rq_auth_data); - kfree_rcu(rqstp, rq_rcu_head); + call_rcu(&rqstp->rq_rcu_head, svc_rqst_free_rcu); } static struct svc_rqst * -- 2.53.0 ^ permalink raw reply related [flat|nested] 11+ messages in thread
end of thread, other threads:[~2026-09-09 0:25 UTC | newest] Thread overview: 11+ messages (download: mbox.gz follow: Atom feed -- links below jump to the message on this page -- 2026-09-03 14:06 FAILED: patch "[PATCH] sunrpc: defer rq_argp and rq_resp free until after RCU grace" failed to apply to 6.1-stable tree gregkh 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 1/5] SUNRPC: remove timeout arg from svc_recv() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 2/5] SUNRPC: make various functions static, or not exported Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 3/5] SUNRPC: Introduce xdr_set_scratch_folio() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 4/5] SUNRPC: Update svcxdr_init_decode() to call xdr_set_scratch_folio() Sasha Levin 2026-09-09 0:25 ` [PATCH 6.1.y 5/5] sunrpc: defer rq_argp and rq_resp free until after RCU grace period Sasha Levin
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.