All of lore.kernel.org
 help / color / mirror / Atom feed
From: Mike Snitzer <snitzer@kernel.org>
To: Chuck Lever <cel@kernel.org>, Jeff Layton <jlayton@kernel.org>
Cc: linux-nfs@vger.kernel.org
Subject: [PATCH] SUNRPC: preserve RQ_SECURE across request deferral
Date: Fri,  2 Oct 2026 09:50:27 -0400	[thread overview]
Message-ID: <20261002135027.72494-1-snitzer@kernel.org> (raw)

Commit 319951eba0fc ("SUNRPC: Remove ->xpo_secure_port()") moved the
setting of RQ_SECURE from svc_recv() into each transport's
->xpo_recvfrom(). But a deferred request is replayed through
svc_deferred_recv(), which bypasses ->xpo_recvfrom(), so RQ_SECURE is
no longer recomputed for it. The replaying thread instead carries
whatever RQ_SECURE value was left behind by the last request it
processed, and svc_defer() does not save the original value.

An AUTH_SYS request from a privileged port can therefore be deferred
on an ip_map or export cache upcall and then replayed by a thread
whose RQ_SECURE is clear (e.g. a newly created nfsd thread, whose
svc_rqst is zero-allocated). nfsd_setuser_and_check_port() then
rejects it with nfserr_perm on an export that lacks "insecure".
Conversely, a request from an unprivileged port can be replayed with
a stale RQ_SECURE set and pass that check.

Deferral is most likely right after an NFS server restart, when the
auth caches are empty and every client reconnects at once: if a pool
has no idle threads, cache_wait_req() waits only one second for the
upcall before deferring. This was observed as NFSv3 clients getting
EPERM shortly after a server reboot.

Save RQ_SECURE in struct svc_deferred_req when the request is first
deferred and restore it in svc_deferred_recv(). Restoring the saved
bit, rather than recomputing it from the peer address, keeps it
correct for transports such as RDMA that set RQ_SECURE
unconditionally.

Fixes: 319951eba0fc ("SUNRPC: Remove ->xpo_secure_port()")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Mike Snitzer <snitzer@kernel.org>
---
 include/linux/sunrpc/svc.h | 1 +
 net/sunrpc/svc_xprt.c      | 7 +++++++
 2 files changed, 8 insertions(+)

diff --git a/include/linux/sunrpc/svc.h b/include/linux/sunrpc/svc.h
index bdff8ccb92c77..2906481644f7a 100644
--- a/include/linux/sunrpc/svc.h
+++ b/include/linux/sunrpc/svc.h
@@ -382,6 +382,7 @@ struct svc_deferred_req {
 	struct sockaddr_storage	daddr;	/* where reply must come from */
 	size_t			daddrlen;
 	void			*xprt_ctxt;
+	bool			secure;	/* RQ_SECURE of the original request */
 	struct cache_deferred_req handle;
 	int			argslen;
 	__be32			args[];
diff --git a/net/sunrpc/svc_xprt.c b/net/sunrpc/svc_xprt.c
index 0de613b36fffc..bf5b2cdad35ea 100644
--- a/net/sunrpc/svc_xprt.c
+++ b/net/sunrpc/svc_xprt.c
@@ -1343,6 +1343,7 @@ static struct cache_deferred_req *svc_defer(struct cache_req *req)
 		memcpy(&dr->addr, &rqstp->rq_addr, rqstp->rq_addrlen);
 		dr->addrlen = rqstp->rq_addrlen;
 		dr->daddr = rqstp->rq_daddr;
+		dr->secure = test_bit(RQ_SECURE, &rqstp->rq_flags);
 		dr->argslen = rqstp->rq_arg.len >> 2;
 
 		memcpy(dr->args, rqstp->rq_arg.head[0].iov_base,
@@ -1377,6 +1378,12 @@ static noinline int svc_deferred_recv(struct svc_rqst *rqstp)
 	rqstp->rq_addrlen     = dr->addrlen;
 	rqstp->rq_daddr       = dr->daddr;
 	rqstp->rq_xprt_ctxt   = dr->xprt_ctxt;
+	/*
+	 * ->xpo_recvfrom() is bypassed for a deferred request, so the
+	 * replaying thread's RQ_SECURE is stale from whatever request
+	 * it handled last. Restore the value computed at receive time.
+	 */
+	assign_bit(RQ_SECURE, &rqstp->rq_flags, dr->secure);
 
 	dr->xprt_ctxt = NULL;
 	svc_xprt_received(rqstp->rq_xprt);
-- 
2.52.0


             reply	other threads:[~2026-10-02 13:50 UTC|newest]

Thread overview: 2+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-10-02 13:50 Mike Snitzer [this message]
2026-10-05 15:06 ` [PATCH] SUNRPC: preserve RQ_SECURE across request deferral Chuck Lever

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20261002135027.72494-1-snitzer@kernel.org \
    --to=snitzer@kernel.org \
    --cc=cel@kernel.org \
    --cc=jlayton@kernel.org \
    --cc=linux-nfs@vger.kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.