summaryrefslogtreecommitdiff
path: root/net/sunrpc
AgeCommit message (Collapse)Author
44 hoursxprtrdma: fix up the nfs/nfs-anna merge of the Write chunk head trimSasha Levin
Two fixes for the same Write chunk payload corruption meet in linux-next. In the nfs tree, commit a0db57fee35e ("xprtrdma: Fix Write chunk payload corruption on a short reply header") trims head[0].iov_len in rpcrdma_decode_msg(). In the nfs-anna tree, commit 9ee534a75912 ("xprtrdma: trim head iovec when the payload arrives via a Write chunk") trims it in rpcrdma_inline_fixup() and reduces buflen by the same amount. The merge resolution keeps the caller-side trim. By the time rpcrdma_inline_fixup() runs, head[0].iov_len already equals copy_len, so the block added by the nfs-anna commit never runs and its buflen reduction in rq_rcv_buf and rq_private_buf is lost. The helper is also still passed xdr_pad_size(writelist), while its kernel-doc now describes @writelist as the number of bytes conveyed by the Write chunk. Drop the caller-side trim and pass the full Write chunk length, so that rpcrdma_inline_fixup() is the only place that trims head[0] and reduces buflen. Compute the pad with xdr_pad_size() in the helper, so the padding from the nfs commit stays correct for lengths that are not a multiple of four. Its rpclen calculation and empty reply check stay in rpcrdma_decode_msg(). Fixes: 53ab189bdc14 ("Merge branch 'linux-next' of git://git.linux-nfs.org/projects/anna/linux-nfs.git") Link: https://lore.kernel.org/all/as4aacUf2Q78FMvY@sirena.org.uk/ Signed-off-by: Sasha Levin <sashal@kernel.org> Tested-by: Tim Menninger <tmenninger@everpuredata.com> Reviewed-by: Tim Menninger <tmenninger@everpuredata.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
7 daysMerge tag 'nfs-for-7.4-1' of git://git.linux-nfs.org/projects/anna/linux-nfsLinus Torvalds
Pull nfs client updates from Anna Schumaker: "New Features: - Modernize the direct I/O path - Size the LAYOUTGET reply buffer for wide flexfiles layouts - Flexfiles device notifications and caching for wide striped layouts - isolate mTLS client credentials by network namespace Bugfixes: - Various localio, flexfiles, xprtrdma, and TLS fixes - Merged bugfixes from Trond that he was unable to send during the 7.3-rc cycle Other Cleanups and Improvements: - Split up pNFS block layout and SCSI layout support" * tag 'nfs-for-7.4-1' of git://git.linux-nfs.org/projects/anna/linux-nfs: (68 commits) nfs/localio: pin UUIDs during global invalidation NFSv4/flexfiles: fail I/O to the data server once a lock is lost pNFS/flexfiles: don't report an interrupted DS connect as a DS error pNFS/flexfiles: make pg_init retry loops killable nfsv4/pnfs: use the MDS authflavor for data server connections xprtrdma: trim head iovec when the payload arrives via a Write chunk nfs: set gencount on protocol-specific remove xprtrdma: prevent disconnect feedback during endpoint teardown NFS: add a key type that reveals the namespace .nfs keyring serial number NFS: name the namespace .nfs keyring in the x509 handshake SUNRPC: pass a keyring serial number to the TLS handshake NFS: allocate the .nfs keyring per network namespace NFS: name the init_nfs_fs() error labels NFS: return DENIED in decode_lock_denied if we cannot decode owner pNFS/flexfiles: don't reset to MDS for v4 error when previous layout forbid it pNFS/flexfiles: don't read through MDS when previous layout forbid it pNFS/flexfiles: honor FF_FLAGS_NO_IO_THRU_MDS over the mdsthreshold hint NFS/localio: report the stability a DIO WRITE actually has NFS/localio: detect a short read or write before the iterator has moved NFS/localio: fix nfs_local_dio_misaligned tracepoint ...
7 daysMerge tag 'nfsd-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linuxLinus Torvalds
Pull nfsd updates from Chuck Lever: "Jeff Layton extended the netlink listener-set operation so that a management daemon can register NFSD's programs with rpcbind itself. This prevents an unresponsive rpcbind from stalling NFSD administration for a minute at a time. Bulk delegation recall now adjusts the number of delegations it wants returned, based on memory pressure. The previous mechanism was spec-conformant, but it requested all delegations to be returned at once. Clients are free to return few or none in such cases, but requesting smaller batches of delegations is more neighborly. In preparation for handling TLS KeyUpdate, the server's TCP receive path has been reworked to handle control records. In the process, the use of sock_recvmsg was replaced with ->read_sock, which contends less with other holders of the socket lock. NFSv2 XDR code is now generated by xdrgen, which mechanically generates the encoders and decoders from the RPC language specification for the protocol. Replacing hand-built XDR code makes prototyping new protocol elements faster, reduces errors, and improves memory safety. Replacement of XDR code for newer NFS versions will continue in subsequent releases of NFSD. The remaining bulk of changes in v7.4 is bug fixes, clean-ups, and small optimizations. Sincere thanks to all contributors, reviewers, testers, and bug reporters who participated in the v7.4 NFSD development cycle" * tag 'nfsd-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/cel/linux: (184 commits) SUNRPC: use assign_bit() where applicable nfsd: Fix id-to-name cache entry leak in idtoname_parse() NFSD: Use xdrgen XDR functions for NFSv2 READDIR results NFSD: Refactor NFSv2 directory cookie encoding NFSD: Add a streaming directory reader NFSD: Use xdrgen XDR functions for NFSv2 READDIR arguments NFSD: Use xdrgen XDR functions for the NFSv2 STATFS procedure NFSD: Use xdrgen XDR functions for NFSv2 RMDIR procedure NFSD: Use xdrgen XDR functions for NFSv2 MKDIR procedure NFSD: Use xdrgen XDR functions for NFSv2 SYMLINK procedure NFSD: Use xdrgen XDR functions for the NFSv2 LINK procedure NFSD: Use xdrgen XDR functions for the NFSv2 RENAME procedure NFSD: Use xdrgen XDR functions for the NFSv2 REMOVE procedure NFSD: Use xdrgen XDR functions for NFSv2 CREATE procedure NFSD: Refactor nfsd_proc_create() NFSD: Use xdrgen XDR functions for NFSv2 WRITE procedure NFSD: Use xdrgen XDR functions for the NFSv2 WRITECACHE procedure NFSD: Use xdrgen XDR functions for NFSv2 READ procedure NFSD: Use xdrgen XDR functions for NFSv2 READLINK procedure NFSD: Use xdrgen XDR functions for the NFSv2 LOOKUP procedure ...
11 daysMerge commit '211cda4fdf33011cee39f8970c4625b207142d6b' of ↵Anna Schumaker
git://git.linux-nfs.org/projects/trondmy/linux-nfs.git into anna/linux-next This pulls in NFS client bugfixes from the Linux 7.3-rc cycle that were never sent upstream. Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
2026-10-12xprtrdma: trim head iovec when the payload arrives via a Write chunkYongjian Mu
The upper layer sets rq_rcv_buf.head[0].iov_len from its estimate of the reply header size. For RPCSEC_GSS that estimate includes auth->au_ralign, which gss_create_new() initializes to GSS_VERF_SLACK >> 2 (25 XDR words, or 100 bytes) and which is corrected to the real verifier size only after the first reply on that rpc_auth has been unwrapped. In this case, the krb5 MIC verifier is 36 bytes, so every request encoded before the first reply completes has a head that is 64 bytes too long. On TCP this is harmless: xdr_realign_pages() moves the excess head bytes, which are genuine reply data, into the page list. With RPC-over-RDMA and a Write chunk (sec=krb5, i.e. RPC_GSS_SVC_NONE, where DDP is allowed), the payload has already been placed directly into the page list, and the receive buffer holds only the inline part of the reply. rpcrdma_inline_fixup() clamps its local copy of the head length to the inline length but leaves head.iov_len untouched, so xdr_realign_pages() still sees iov_len > cur and shifts whatever lies past the inline reply in the receive buffer into the front of the directly-placed payload: rpc_xdr_recvfrom: head=[...,196] page=524288 tail=[...,64] rpc_xdr_alignment: nfsv4 READ offset=132 copied=64 The first 64 bytes returned by each such READ are incorrect (zeroed, or shifted right by 64 bytes depending on the kernel's xdr_shrink_bufhead() implementation). This is readily hit with pNFS flexfiles over RDMA and sec=krb5: the per-DS rpc_clnt gets a fresh rpc_auth whose first RPC is a large READ. Reads following the first completed reply return the expected data. Commit cb0ae1fbb2f5 ("xprtrdma: Do not update {head, tail}.iov_len in rpcrdma_inline_fixup()") removed the head-length correction while fixing the handling of pure-inline krb5p replies. When a Write chunk conveyed the payload, trim head.iov_len (in both rq_rcv_buf and rq_private_buf, which call_decode() expects to match) to the inline length actually received so that the XDR layer does not realign the page list. These READ replies have no trailing inline fields, and the payload is already in the page list, so the upper layer's head estimate can be safely reduced. Reduce buflen by the same amount to avoid treating unused head capacity as additional tail capacity. Pure inline replies and Reply chunk replies are unchanged. Tested on Linux 6.8.0 and 7.3-rc4 with NFSv4.1 pNFS flexfiles over RPC/RDMA and sec=krb5. Fixes: cb0ae1fbb2f5 ("xprtrdma: Do not update {head, tail}.iov_len in rpcrdma_inline_fixup()") Cc: stable@vger.kernel.org Signed-off-by: Yongjian Mu <ymu@everpuredata.com> Reviewed-by: Chuck Lever <cel@kernel.org> Signed-off-by: Tim Menninger <tmenninger@everpuredata.com> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
2026-10-12xprtrdma: prevent disconnect feedback during endpoint teardownTim Menninger
xprt_autoclose() clears XPRT_CLOSE_WAIT before invoking the transport's ->close() operation. For RPC/RDMA, ->close() calls rpcrdma_xprt_disconnect(), which disconnects the RDMA CM endpoint and drains its QP. Since commit 31e62d25b5b8 ("xprtrdma: Simplify RPC wake-ups on connect"), RDMA_CM_EVENT_DISCONNECTED requests a SUNRPC transport disconnect. Today that path, along with failed completion handling, reaches xprt_force_disconnect() through rpcrdma_force_disconnect(). Commit c487eb7d8e41 ("xprtrdma: Clean up disconnect") later added re_force_disconnect to ensure that multiple failure indications request only one SUNRPC disconnect. However, the gate remains open when SUNRPC itself begins endpoint teardown. If re_force_disconnect is still clear, either a CM disconnect event or a completion error can set XPRT_CLOSE_WAIT again while the current close is in progress. When the transport send lock is subsequently released, xprt_clear_locked() observes XPRT_CLOSE_WAIT and queues another autoclose. Requesting a disconnect this way is necessary when a connection is lost unexpectedly, but not when the event was generated by rpcrdma_xprt_disconnect() itself. In that case SUNRPC is already committed to closing the transport. Mark re_force_disconnect before initiating local endpoint teardown so that CM events and completion errors caused by that teardown cannot request another close. An unexpected error that wins the race before local endpoint teardown begins can still request a disconnect normally. Use a fully ordered exchange so that the gate is globally closed before rdma_disconnect() can transition the QP to error and generate the callbacks that the gate suppresses. In 30-second traces of a sustained recovery loop, without this change there were 7,693 xprt_force_disconnect() calls, 6,267 SUNRPC autocloses, and 172,892 receive-side IB_WC_WR_FLUSH_ERR completions. With this change, the same tracepoints recorded 3,512 xprt_force_disconnect() calls, 3,212 autocloses, and 131,287 receive-side flush completions. Thus QP teardown continues to produce flushed completions, but closing the disconnect gate before teardown substantially reduces their feedback into the SUNRPC close path. Fixes: 31e62d25b5b8 ("xprtrdma: Simplify RPC wake-ups on connect") Cc: stable@vger.kernel.org Signed-off-by: Tim Menninger <tmenninger@everpuredata.com> Reviewed-by: Chuck Lever <cel@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
2026-10-12SUNRPC: pass a keyring serial number to the TLS handshakeChuck Lever
The handshake upcall links the keyring named in ta_keyring into tlshd's process keyring before tlshd reads the client certificate and private key. That link is how tlshd gains possession of keys that grant no user read permission. xprtsock never fills the field, so an x509 handshake can present only keys that tlshd's own credentials can read. Add a keyring serial number to struct xprtsec_parms and pass it to the x509 handshake, so an RPC client can name the keyring that holds its credentials. Signed-off-by: Chuck Lever <cel@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
2026-10-11SUNRPC: use assign_bit() where applicablePeng Fan
Convert open-coded if/else with set_bit/clear_bit the assign_bit API. Done with Coccinelle semantic patch: // set_bit -> clear_bit => assign_bit @@ expression cond, bit, addr; @@ -if (cond) - set_bit(bit, addr); -else - clear_bit(bit, addr); +assign_bit(bit, addr, cond); @@ expression cond, bit, addr; @@ -if (cond) - clear_bit(bit, addr); -else - set_bit(bit, addr); +assign_bit(bit, addr, !cond); Signed-off-by: Peng Fan <peng.fan@nxp.com> Link: https://patch.msgid.link/20260920022714.3145751-1-peng.fan@oss.nxp.com Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-11SUNRPC: allow a service to opt out of rpcbind registrationJeff Layton
svc_bind() creates the local rpcbind client, and svc_register() then makes one synchronous call for each program and version. Both run under the caller's mutex. A caller that registers from userland needs neither. Add sv_no_rpcbind to struct svc_serv, and fix up the code to honor it. No caller sets the flag yet, so behaviour does not change. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260915-nfsd-norpcb-v3-1-3c60d49ade02@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-05sunrpc: use sk_set_nospace() and sk_clear_nospace()Eric Dumazet
Use the new helpers instead of open coding the SOCK_NOSPACE manipulation, so that TCP can later maintain a cheaper private copy of this bit. No functional change intended. Reviewed-by: Kuniyuki Iwashima <kuniyu@google.com> Signed-off-by: Eric Dumazet <edumazet@kernel.org> Acked-by: Chuck Lever <cel@kernel.org> Link: https://patch.msgid.link/20260929071743.23624-4-edumazet@kernel.org Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-10-05SUNRPC: fold xs_sock_process_cmsg() into its only callerChuck Lever
xs_sock_process_cmsg() switches on the TLS record type, and every arm but TLS_RECORD_TYPE_ALERT returns the -EAGAIN its caller passed in. The DATA arm clears MSG_EOR in the caller's msghdr, but xs_sock_recvmsg() has already cleared that flag before the call. Deriving the record type a second time inside the helper also fires trace_tls_contenttype() twice for every alert. Move the alert handling into xs_sock_recv_cmsg() and delete the helper. Every other record type still returns -EAGAIN. The DATA arm's account of MSG_EOR moves to xs_sock_recvmsg(), where the flag is cleared. Signed-off-by: Chuck Lever <cel@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
2026-10-05SUNRPC: treat every client-side TLS error alert as fatalChuck Lever
xs_sock_process_cmsg() decides whether an alert ends the session by reading the alert's level octet. RFC 8446 Section 6 retired that field. The severity is implicit in the description, and a receiver treats every alert listed in Section 6.2 as an error alert "regardless of the AlertLevel in the message". A peer that aborts with unexpected_message but leaves the legacy octet set to warning makes the client return -EAGAIN. xs_stream_data_receive() wakes no pending task for that error, so RPC Calls queued on a dead TLS session wait for their timeouts to expire. Decide from the alert description instead. close_notify and user_canceled are the closure alerts (RFC 8446 Section 6.1). Every other description ends the session, including one this kernel does not recognize. Fixes: 39067dda1d86 ("SUNRPC: Use new helpers to handle TLS Alerts") Signed-off-by: Chuck Lever <cel@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
2026-10-05SUNRPC: reject a client-side TLS alert record that is not two octetsChuck Lever
tls_alert_recv() reads two octets from the kvec it is handed and does not check the length (net/handshake/alert.c). xs_sock_process_cmsg() calls it for any alert record, and the alert[] buffer that xs_sock_recv_cmsg() supplies carries no initializer. A one-octet alert body leaves the description read from uninitialized stack and reported through trace_tls_alert_recv(). The peer controls that length. Neither tls_rx_msg_size() nor tls_rx_one_record() enforces the two-octet Alert payload. A TLS 1.3 record carrying only the inner content-type octet decrypts to a zero-length payload. RFC 8446 Section 5.1 requires a record with an Alert type to carry exactly one message, so any other length is malformed. RFC 9289 Section 5 bars RPC-with-TLS from negotiating a version below TLS 1.3, so no other alert framing applies. Require exactly two octets before parsing and return -EACCES otherwise. xs_stream_data_receive() already treats -EACCES as a fatal alert and reports it to the pending tasks. Gate the path on a control message rather than a positive count so that a zero-length record reaches the check. Fixes: cc5d59081fa2 ("sunrpc: fix client side handling of tls alerts") Signed-off-by: Chuck Lever <cel@kernel.org> Signed-off-by: Anna Schumaker <anna.schumaker@hammerspace.com>
2026-10-04sunrpc: pin gss module across auth_domain RCU freeChris Mason
A gss auth_domain stores a raw pointer to svcauthops_gss in dom->flavour, and its release queues svcauth_gss_domain_release_rcu() via call_rcu(). Both live in auth_rpcgss.ko text, and nothing pins the module while a domain referencing it is reachable. rmmod auth_rpcgss can therefore unmap that text while an NFSD export still holds a reference to the domain. The export cache is one such holder. When the export is finally released, the domain reference drops from module text: svc_export_put() auth_domain_put(exp->ex_client) auth_domain_release() dom->flavour->domain_release(dom) /* into module text */ svcauth_gss_domain_release() call_rcu(&dom->rcu_head, svcauth_gss_domain_release_rcu) Once auth_rpcgss is unloaded, the domain_release call lands in unmapped memory. The rcu_barrier() in exit_rpcsec_gss() does not help: it waits only for callbacks already queued, and this one is not queued until the export goes away. NFSD's NFSv4 objects import symbols from auth_rpcgss.ko, so only a server built without CONFIG_NFSD_V4 can unload auth_rpcgss while exports still name a gss domain. Take a module reference in svcauth_gss_register_pseudoflavor() before publishing the domain and drop it at the end of svcauth_gss_domain_release_rcu(). The rcu_barrier() then holds the module image until this callback has returned. Fixes: 608a0ab2f54a ("SUNRPC: Add lockless lookup of the server's auth domain") Cc: stable@vger.kernel.org Assisted-by: kres:claude-opus-4-7 Signed-off-by: Chris Mason <clm@meta.com> [ cel: rewrote description ] Link: https://patch.msgid.link/20260913160706.384180-1-cel@kernel.org Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: trace an accepted transport before publishing itZhiling Zou
svc_handle_xprt() publishes a newly accepted transport before tracing it. svc_add_new_temp_xprt() places the transport on sv_tempsocks and clears XPT_BUSY, so another nfsd thread can dequeue it at once. If the peer has already closed the connection, that thread runs svc_delete_xprt(), which drops the list reference, the only reference the new transport holds. trace_svc_xprt_accept() then reads the transport's addresses and network namespace from freed memory. Before publication the accepting thread owns the transport exclusively: XPT_BUSY is still set from svc_xprt_init() and the transport is on no list. Emit the tracepoint there. Fixes: 11bbb0f76e99 ("SUNRPC: Trace a few more generic svc_xprt events") Cc: stable@vger.kernel.org Reported-by: VEGA <vega@nebusec.ai> Assisted-by: LLM Signed-off-by: Zhiling Zou <zhilinz@nebusec.ai> Link: https://patch.msgid.link/d15495bff2247e3f9d4f9ef36df8e246a3898380.1789220778.git.zhilinz@nebusec.ai [ cel: trace before publication instead of taking an extra reference ] Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: fix oversized GSS proxy token copyJérémy Jean
gss_read_proxy_verf() allocates one page per token chunk, but it copies the entire linear head of an RPC request into in_token->pages[0]. A UDP datagram can leave more than PAGE_SIZE bytes in the linear head, so a large RPCSEC_GSS INIT token overwrites following pages. Copy the linear head in page-sized chunks before switching to the request page array. The linear head itself can span multiple pages. Fixes: 5866efa8cbfb ("SUNRPC: Fix svcauth_gss_proxy_init()") Cc: stable@vger.kernel.org Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr> Assisted-by: Codex:gpt-5 Link: https://patch.msgid.link/20260910125120.3798995-1-Jeremy.Jean@oss.cyber.gouv.fr Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Carry a generated-codec context pointer in struct xdr_streamChuck Lever
A generated XDR codec function receives only an xdr_stream, yet some codecs need state that the stream does not carry. Passing that state as an additional argument changes the signature of every function on the path from the program entry point down to the one that consumes it, and for generated code it makes each function's argument list depend on an analysis of the entire specification. Add xdrgen_ctx to struct xdr_stream, a pointer that the layer initializing the stream sets aside for generated codecs to find, following the precedent of seq_file->private and netlink_callback->data. Every xdr_stream initializer clears it, so a codec never reads a residual value left in a stream that was allocated on the stack or taken from a transport's free pool. Acked-by: Jeff Layton <jlayton@kernel.org> Reviewed-by: NeilBrown <neil@brown.name> Link: https://patch.msgid.link/20260908134234.512312-2-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: fix netns use-after-free in write_gssp()Zijing Yin
While fuzzing with a customized syzkaller, I hit a refcount warning in xprt_alloc(), reached from a write to /proc/net/rpc/use-gss-proxy: refcount_t: addition on 0; use-after-free. WARNING: lib/refcount.c:25 at refcount_warn_saturate+0xf8/0x120 CPU: 0 PID: 10404 Comm: syz.0.17 Not tainted 7.3.0-rc1-00096-gcfebfd3db73d Call Trace: <TASK> xprt_alloc+0x83f/0x9d0 xs_setup_xprt+0xaf/0x3c0 xs_setup_local+0x47/0x7f0 xprt_create_transport+0x16c/0x730 rpc_create+0x38e/0x7f0 gssp_rpc_create+0xe2/0x180 set_gssp_clnt+0xba/0x1b0 write_gssp+0x200/0x310 proc_reg_write+0x240/0x330 vfs_write+0x2aa/0x1050 ksys_write+0x12a/0x250 do_syscall_64+0x117/0x750 entry_SYSCALL_64_after_hwframe+0x77/0x7f </TASK> create_use_gss_proxy_proc_entry() stores the struct net pointer as the proc entry's private data without taking a reference on it, and an open file descriptor does not pin the namespace either, as procfs only pins the proc_dir_entry. write_gssp() reads that pointer back with pde_data() and hands it to set_gssp_clnt(), which reaches xprt_init(): xprt->xprt_net = get_net_track(net, &xprt->ns_tracker, GFP_KERNEL); get_net_track() -> get_net() -> refcount_inc() is unconditional, so rpc_create() assumes its caller holds a reference on args.net. write_gssp() does not. Dropping the last ns.count reference does not make the file go away. __put_net() only queues cleanup_net() on a workqueue, and the remove_proc_entry() that fences off further writes runs from the rpcsec_gss pernet .exit method, that is, from inside cleanup_net(). A write landing between those two points increments a refcount that is already zero. cleanup_net() does not re-read ns.count, so the namespace is freed anyway and the rpc_xprt -- along with the AF_LOCAL socket opened for it -- is left pointing at freed memory. The resurrected count is visible to the rest of that teardown too: with CONFIG_IPV6_MROUTE the same cleanup_net() worker then trips !mr_can_free_table() in ip6mr_free_table(), which tests check_net() on the namespace it is freeing. It reduces to opening /proc/net/rpc/use-gss-proxy inside a new network namespace, calling setns() back to the original one to drop the last reference, and then writing "1" to the still-open descriptor. Take the reference in write_gssp() itself and refuse the write when the namespace is already gone. This is what procfs does for every other /proc/net file: get_proc_net() is maybe_get_net(PDE_NET(PDE(inode))) and seq_open_net() returns -ENXIO when it fails. PDE_NET() cannot be reused here because the parent directory /proc/net/rpc carries no namespace pointer. Adding a .pre_exit to rpcsec_gss_net_ops so the entry is removed earlier would only narrow the window, since pre_exit also runs from cleanup_net(). Live namespaces are unaffected: a write still returns the error from set_gssp_clnt(), a write of "2" still returns -EINVAL, and reads are untouched. Fixes: 030d794bf498 ("SUNRPC: Use gssproxy upcall for server RPCGSS authentication.") Cc: stable@vger.kernel.org Signed-off-by: Zijing Yin <yzjaurora@gmail.com> Link: https://patch.msgid.link/20260907085435.644076-1-yzjaurora@gmail.com Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Copy the deferred RPC Call from the head bufferChuck Lever
svc_defer() snapshots the RPC Call for replay once a pending cache upcall resolves. It copies the Call starting (rq_arg.len - head[0].iov_len) bytes before head[0].iov_base, a back-up that once covered a transport header. No transport has had one since commit 983084b2672c ("SUNRPC: Remove svc_rqst::rq_xprt_hlen"), so the two lengths are meant to be equal. An RPCSEC_GSS Call breaks that assumption. Unwrapping the integrity service truncates rq_arg.len by the length of the trailing checksum, and unwrapping the privacy service leaves rq_arg.len short by an amount the client sets with trailing bytes after the wrap token. Neither adjusts head[0].iov_len. Both lengths are size_t, so the subtraction underflows and the copy starts past head[0].iov_base. Every deferred integrity Call replays a shifted snapshot. A deferred replay skips GSS verification, so a shifted snapshot runs as an authenticated Call. With the privacy service the offset is client-chosen. A forged Call placed in that window, naming another user's GSS context handle, runs under that identity. Copy the Call from head[0].iov_base. Refuse to defer a Call whose length runs past the head buffer, so the copy cannot read out of bounds. Fixes: 260c1d1298f6 ("svc: Add transport hdr size for defer/revisit") Cc: stable@vger.kernel.org Reported-by: Kimi Security Team <bug-report@moonshot.ai> Reported-by: Yilin Zhang <yilinzhang@moonshot.ai> Link: https://patch.msgid.link/20260902133101.48914-1-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: stop unregistering listeners once rpcbind stops answeringJeff Layton
svc_delete_xprt() unregisters each listener it destroys. One NFSD_CMD_LISTENER_SET that removes listeners therefore pays one local rpcbind timeout for each of them, under nfsd_mutex, on top of the one the create loop already bounds. One failure is enough to know that the rest of the teardown will not fare better. When the call gets no answer, clear XPT_RPCB_UNREG on every remaining transport in the same net. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-9-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: stop the svc_unregister() sweep once rpcbind stops answeringJeff Layton
svc_unregister() clears the rpcbind entry for every non-hidden program and version. svc_rpcb_setup() runs it to drop stale entries when a serv binds, and svc_rpcb_cleanup() runs it when one goes away. An nfsd serv with v3 and v4 enabled sweeps four or five entries, so a local rpcbind that never replies costs that many timeouts, twice per NFSD_CMD_LISTENER_SET, all under nfsd_mutex. Give up after the first call that gets no answer. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-8-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: stop svc_register() once rpcbind stops answeringJeff Layton
svc_register() walks every program and every version. The break on error leaves the version loop only, so a program whose call to the local rpcbind timed out is followed by the next program timing out in the same way. With the 1s bound on the local rpcbind client, an nfsd serv pays 2s for that, once for nfsd and once for nfsacl. Stop the program loop too, but only when the call got no answer. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-7-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: report local rpcbind calls that get no answerJeff Layton
A caller that creates many listeners in one operation calls svc_register() once for each of them. Every call waits for the local rpcbind on its own, so a rpcbind that never answers costs the caller one timeout per listener. The caller has no way to learn that the first call already failed. Split rpcb_register_call() failures by whether rpcbind answered: - answered: a FALSE reply, or an RPC-level rejection that rpc_decode_header() derives from the reply. -EACCES (FALSE reply or AUTH_ERROR), -EPROTONOSUPPORT, -EPFNOSUPPORT, -EOPNOTSUPP. - never sent: -ENOMEM, -EMSGSIZE, -ERESTARTSYS. - no answer: everything else, i.e. transport errors. Any no-answer error gets represented by -EIO, which is already what the RPC layer reports for most of it: rpc_check_timeout() returns -EIO for a soft timeout without RPC_TASK_TIMEOUT, and call_status() documents -EIO as "shutdown or soft timeout". Keep a count of the number of rpcbind failures in the serv. Later patches will use that to watch for hard rpcbind failures, and alter their behavior accordingly. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-6-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: bound the local rpcbind client timeout to 1sJeff Layton
The kernel's local rpcbind client uses the transport defaults: a 10s major timeout for AF_LOCAL, and 60s for the loopback TCP fallback. xprt_calc_majortimeo() returns to_initval when to_increment is 0. Those calls are synchronous, and they run under nfsd_mutex. One operation makes several of them. rpcb_create_local() tries up to three client creations, and svc_register() sends one call for each program and version. A local rpcbind that accepts the connection but never replies stalls every one of these calls. The accumulated hold is long enough to trip the hung-task watchdog on other NFSD netlink operations. The holder itself waits killably and escapes the watchdog: INFO: task hung in nfsd_nl_cache_flush_doit The local rpcbind is on loopback or on an AF_LOCAL socket, and it answers in microseconds. Bound its client to one attempt of 1s. This shortens the stall. It does not remove the stall, and it is not free. Registration stays synchronous and stays fatal. An rpcb_create_local() failure aborts nfsd_create_serv() through svc_bind(), and an svc_register() failure makes svc_setup_socket() fail. An rpcbind that is merely slow to be scheduled can therefore now fail server startup, where it succeeded before. The real fix is to make the registration asynchronous. Assisted-by: LLM Link: https://syzkaller.appspot.com/bug?extid=c7eae0eb80858a2dba0f Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-4-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: keep the first error in svc_register()Jeff Layton
svc_register() assigns every pg_rpcbind_set() result to the same "error" variable and returns the last one, so a later result erases an earlier failure. Keep the first error instead of the last. Fixes: 642ee6b209c2 ("SUNRPC: Allow further customisation of RPC program registration") Cc: stable@vger.kernel.org Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260901-nfsd-nl-hang-v5-3-a540d86668b0@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Skip xpt_reserved accounting for non-UDP transportsChuck Lever
The xpt_reserved counter exists for UDP socket-buffer back-pressure. svc_udp_has_wspace() is the only has_wspace implementation that consults it, so on TCP and RDMA the counter is maintained and never read. svc_handle_xprt() adds to it once per RPC. svc_reserve() shrinks it again on each call from svc_process_common(), from svc_xprt_release(), and from each proc function that calls svc_reserve_auth(). Every shrinking call also runs svc_xprt_resource_released(), which issues an smp_mb() and can enqueue the transport. Add an xcl_flags field to svc_xprt_class and set SVC_XPRT_FLAG_WSPACE_RESERVE on the UDP class. Gate the xpt_reserved accounting on that flag. After the change, svc_reserve() no longer calls svc_xprt_resource_released() on TCP and RDMA. Two paths still cover that enqueue. svc_xprt_release() reaches the helper through svc_xprt_release_slot(), and svc_xprt_received() enqueues a transport whose XPT_DATA remains set. Link: https://patch.msgid.link/20260828135036.796842-4-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04svcrdma: Clear XPT_DATA when the last receive context is consumedChuck Lever
svc_rdma_wc_receive() and svc_rdma_wc_read_done() set XPT_DATA after adding a completed context to sc_rq_dto_q or sc_read_complete_q. svc_rdma_recvfrom() dequeues one context and leaves XPT_DATA set, so the svc_xprt_received() that follows re-enqueues the transport and svc_xprt_enqueue() dispatches a second thread. That thread finds both queues empty and returns zero. Recheck the receive queues after each dequeue and clear XPT_DATA when the last context is taken, rather than only when a dequeue finds nothing. svc_xprt_received()'s kernel-doc no longer describes every transport, so relax its note about when XPT_DATA is cleared. Measured on one NFSv4.2 connection over 100GbE RoCE. A 4KB random read at queue depth 1 falls from 2.997 transport dequeues per RPC to 1.998, and from 96,629 to 82,398 server cycles per RPC. A 256KB random write falls from 3.270 dequeues to 2.004, and from 259,936 to 246,059 cycles. Each dispatch removed is worth about 10,000 cycles. The gain shrinks as the receive queues fill, since a leftover XPT_DATA then dispatches a thread that finds real work. An 8KB random write at queue depth 512 already runs at the two dequeues an RPC with a Read chunk requires, and shows no change. Throughput moves only where the server has no idle CPU to absorb the saving, so only the queue depth 1 read gains, by 1.8%. One dispatch per RPC remains. svc_rdma_send_ctxt_put() sets XPT_DATA to schedule a drain of sc_send_release_list, and svc_rdma_recvfrom() does not service that list. Link: https://patch.msgid.link/20260828135036.796842-3-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04svcrdma: Grant credits from the clamped sc_max_requestsChuck Lever
svc_rdma_accept() computes sc_fc_credits from sc_max_requests before the Receive Queue depth is checked against the device's max_qp_wr. When that check lowers sc_max_requests, the credit grant keeps the original value, so the server advertises more credits than it has Receives posted. A client that uses the full grant overruns the Receive Queue, and the connection is lost with an RNR error. Set sc_fc_credits after the clamp so the grant matches the number of Receives the server posts. Fixes: fc2e69db82c1 ("svcrdma: Clean up comment in svc_rdma_accept()") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260828135036.796842-2-cel@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Bypass sock_recvmsg() for the TLS control-record receiveChuck Lever
svc_tcp_recvfrom() parses the RPC record stream with ->read_sock, which calls neither security_socket_recvmsg() nor the sock:sock_recv_length tracepoint. svc_tcp_recv_cmsg() still goes through sock_recvmsg(), so an LSM mediates only the TLS control records on a server socket, and sock:sock_recv_length reports only those. Partial coverage is worse than none. It makes the RPC stream look mediated and observed when it is not. Until the record stream moved to ->read_sock, an LSM saw every octet NFSD read from a TCP socket. An SELinux policy that denies SOCKET__READ to NFSD blocked the receive. After this change no call on the server's TCP receive path consults an LSM, so that denial has no effect. Dispatch ->recvmsg directly so the whole receive path behaves one way. sock_recvmsg_nosec() reaches ->recvmsg through INDIRECT_CALL_INET(), so on a retpoline build the direct dispatch costs one indirect call per control record. Control records are rare on an established connection. Link: https://patch.msgid.link/20260821-tls-read-sock-2-v1-5-7ffce164eb45@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Receive RPC records with ->read_sockChuck Lever
svc_tcp_recvfrom() reads an RPC record with two recvmsg() calls, one for the four-octet fragment marker and one for the body. Neither supplies a control-message buffer, so kTLS reports a TLS control record on either one by raising MSG_CTRUNC and delivering nothing. Both receives have to recognize that outcome and hand off to a recovery path that re-reads the record. Commit bee47cb026e7 ("sunrpc: fix handling of server side tls alerts") built that recovery path. It stays on both receives for as long as one recvmsg() serves data and control alike. Instead, parse the record stream in a ->read_sock actor. The data path then carries no control-message buffer at all. A control record at the head stops ->read_sock short, so svc_tcp_recv_ctrl_record() classifies the head of the receive queue with MSG_PEEK before consuming anything. skb_copy_bits() walks an skb from its head to reach the copy offset, so an actor that copies a page at a time rewalks a large GRO or kTLS skb once per page. Copy each callback's share of the record into rq_bvec with one skb_copy_datagram_iter() instead. A non-final fragment carries four octets of marker and may carry no payload. sk_datalen advances only by the payload, so neither a run of empty fragments nor a run of one-octet fragments trips the sv_max_mesg check before desc->count runs out. Only desc->count bounds such a run, four or five octets at a time. Cap the fragments per socket-lock hold. recvmsg() skips an urgent octet and clears the condition, so the old receive path advanced past it. ->read_sock consumes what precedes the urgent octet and then stops there for good. The data path calls no recvmsg() now, so the record stream cannot advance again. An RPC stream carries no urgent data, so close the connection. The read that first reaches the mark returns a positive count, so a zero-length read does not mark the stop. Key the close on an incomplete record. Link: https://patch.msgid.link/20260821-tls-read-sock-2-v1-4-7ffce164eb45@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Flush a received record's pages once it is completeChuck Lever
svc_tcp_read_msg() flushes the destination pages after every receive. A record that arrives in several pieces is therefore flushed once per piece. A page spanning two pieces is flushed twice. Nothing reads the message body before the record is complete, so no reader needs the intermediate flushes. Flush every page of the record in one pass from svc_tcp_recvfrom(), once the last fragment has arrived. Remove svc_flush_bvec() and its ARCH_IMPLEMENTS_FLUSH_DCACHE_PAGE guard. The guard avoided setting up a bvec iterator, and a plain walk of rq_pages compiles away on its own where flush_dcache_page() is an empty inline. Link: https://patch.msgid.link/20260821-tls-read-sock-2-v1-3-7ffce164eb45@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Close the transport on an unhandled TLS record typeChuck Lever
svc_tcp_sock_recv_cmsg() drains a TLS record that is neither an alert nor application data, then returns -EAGAIN so the receive loop retries. It runs only on an established TLS session. A handshake record there carries a post-handshake message, and the server has no handler for one. Draining a KeyUpdate only delays the close. kTLS sets key_update_pending when it decrypts that record, and a later receive returns -EKEYEXPIRED. kTLS flags only a KeyUpdate, so any other post-handshake message disappears and the connection keeps running. Return -EPROTO for an unhandled record type. Any error but -EAGAIN closes the transport. An application data record keeps its -EAGAIN return. No NFS client is known to send a handshake record on an established connection. Link: https://patch.msgid.link/20260821-tls-read-sock-2-v1-2-7ffce164eb45@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Separate the TLS control-record receive from its policyChuck Lever
svc_tcp_sock_recv_cmsg() receives the record at the head of the kTLS receive queue and decides what its content type means for the transport. The receive and the decision are one step, so a caller cannot learn a record's type without also acting on it. A later caller classifies the head of the queue with MSG_PEEK before it decides whether to consume the record. It needs the receive without the decision. Move the receive into svc_tcp_recv_cmsg(), which takes the recvmsg() flags and reports the octet count, the record type, and the message flags. The alert policy stays in svc_tcp_sock_recv_cmsg(), the helper's only caller in this patch. The zeroed control buffer replaces the msg_controllen check. An unfilled buffer reports record type zero, so a positive octet count with no record type now returns -EBADMSG instead of a count. The alert parse runs on a second msghdr over the alert buffer, so the copy and the parse share no iterator state. The rewind that commit bee47cb026e7 ("sunrpc: fix handling of server side tls alerts") added by hand is no longer needed. Link: https://patch.msgid.link/20260821-tls-read-sock-2-v1-1-7ffce164eb45@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Reject a socket that already has an svc_sock attachedChuck Lever
Writing the same socket descriptor to /proc/fs/nfsd/portlist twice attaches a second svc_sock to one socket. svc_setup_socket() saves the socket's callbacks before installing its own, so the second attach records svc_write_space() as the old write_space callback. svc_udp_init() invokes that callback by way of svc_sock_setbufsize(), and svc_write_space() then calls itself until the kernel stack is exhausted: BUG: TASK stack guard page was hit at ffffc900037d7ff8 svc_write_space+0x90/0x2b0 net/sunrpc/svcsock.c:429 svc_write_space+0xe6/0x2b0 net/sunrpc/svcsock.c:430 ... 700 more ... svc_sock_setbufsize+0x18d/0x220 net/sunrpc/svcsock.c:386 svc_udp_init net/sunrpc/svcsock.c:854 [inline] svc_setup_socket+0xb2f/0x1090 net/sunrpc/svcsock.c:1498 svc_addsock+0x2fd/0x760 net/sunrpc/svcsock.c:1547 __write_ports_addfd fs/nfsd/nfsctl.c:742 [inline] write_ports+0xa5b/0xcc0 fs/nfsd/nfsctl.c:861 nfsctl_transaction_write+0x106/0x1a0 fs/nfsd/nfsctl.c:112 svc_data_ready() and svc_tcp_state_change() chain through their saved callbacks the same way, so a TCP descriptor added twice recurses on the next incoming segment instead. Reaching any of this takes a writer on portlist, and the nfsd filesystem sets no FS_USERNS_MOUNT, so the reproducer needs CAP_SYS_ADMIN in the initial user namespace. Reject a socket that already carries sk_user_data. svc_setup_socket() overwrites that field unconditionally, so a socket some other consumer has claimed is one NFSD would corrupt whether or not the callbacks recurse. Fixes: b41b66d63c73 ("[PATCH] knfsd: allow sockets to be passed to nfsd via 'portlist'") Cc: stable@vger.kernel.org Reported-by: syzbot+54cdc566f64abf51b7f1@syzkaller.appspotmail.com Closes: https://syzkaller.appspot.com/bug?extid=54cdc566f64abf51b7f1 Link: https://patch.msgid.link/20260815162844.8219-1-cel@kernel.org Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04sunrpc: honor the netlink unix_gid NEGATIVE flagAmeer Hamza
The unix_gid netlink upcall protocol has an explicit SUNRPC_A_UNIX_GID_NEGATIVE attribute for failed group lookups, and mountd sends it, but sunrpc_nl_parse_one_unix_gid() only allocates an empty group list for a flagged reply without propagating the flag into the entry, so it installs a valid positive entry with zero groups. Such an entry strips the uid of all supplementary groups until it is refreshed or expires: the same defect the previous patch fixes on the classic channel, on a transport that can say "lookup failed" explicitly. Set CACHE_NEGATIVE for flagged replies, as the netlink ip_map path already does for its negative flag. An empty GIDS list without the flag remains a positive entry. Fixes: 0850e8603cd7 ("sunrpc: add netlink upcall for the auth.unix.gid cache") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-fable-5 Signed-off-by: Ameer Hamza <ameer.hamza@truenas.com> Link: https://patch.msgid.link/20260814221953.108837-3-ameer.hamza@truenas.com Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04sunrpc: treat empty auth.unix.gid replies as negative entriesAmeer Hamza
When rpc.mountd cannot resolve a uid (getpwuid() or getgrouplist() failure, e.g. while winbind or sssd is briefly unreachable), it answers the auth.unix.gid upcall with zero groups. unix_gid_parse() installs that as a valid positive entry, and svcauth_unix_set_client() then replaces the credential's group list with the empty one on every request, RPCSEC_GSS included via svcauth_gss_set_client(). One failed lookup strips that uid of all supplementary groups on every export for up to mountd's configured TTL (30 minutes by default), long after the NSS backend has recovered. mountd cannot send an empty list for a successful lookup, since getgrouplist(3) always includes at least the user's primary group, so a zero-group reply can only mean the lookup failed. Record it as a negative entry: unix_gid_find() then returns -ENOENT and svcauth_unix_set_client() keeps the groups the RPC credential already carries. This is the fallback that commit 3fc605a2aa38 ("[PATCH] knfsd: allow the server to provide a gid list when using AUTH_UNIX authentication") promised when no answer is available, and the same state try_to_negate_entry() already creates when no listener holds the channel open. Fixes: 3fc605a2aa38 ("[PATCH] knfsd: allow the server to provide a gid list when using AUTH_UNIX authentication") Cc: stable@vger.kernel.org Assisted-by: Claude:claude-fable-5 Signed-off-by: Ameer Hamza <ameer.hamza@truenas.com> Link: https://patch.msgid.link/20260814221953.108837-2-ameer.hamza@truenas.com Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Resume receiving after a TLS control recordChuck Lever
A TLS control record delivers no payload to the RPC layer. svc_tcp_recvfrom() clears XPT_DATA before the receive, and svc_tcp_sock_recv_cmsg() returns -EAGAIN for the record it consumed. Nothing marks the transport ready again. kTLS raises data_ready for arriving TCP segments, not for records it has already decrypted. An RPC Call queued behind an alert or a KeyUpdate waits until the client sends more. The client blocks until its RPC timeout expires. The receive takes only the first two octets of the record. kTLS holds the remainder on its receive list, where each later receive takes two octets more. Drain a record that is not an alert, then mark the transport ready once a control record has been consumed. Fixes: 5e052dda121e ("SUNRPC: Recognize control messages in server-side TCP socket code") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260808-svcsock-cmsg-fixes-v3-4-62d9a631c880@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Treat every TLS error alert as fatalChuck Lever
svc_tcp_sock_process_cmsg() decides whether an alert ends the session by reading the alert's level octet. RFC 8446 Section 6 retired that field. The severity is implicit in the description, and a receiver treats every alert listed in Section 6.2 as an error alert "regardless of the AlertLevel in the message". A peer that aborts with unexpected_message but leaves the legacy octet set to warning makes the server return -EAGAIN. svc_tcp_recvfrom() then leaves a dead TLS session attached to an open transport. NFSD keeps polling it. Decide from the alert description instead. close_notify and user_canceled are the closure alerts (RFC 8446 Section 6.1). Every other description ends the session, including one this kernel does not recognize. Fixes: 39067dda1d86 ("SUNRPC: Use new helpers to handle TLS Alerts") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260808-svcsock-cmsg-fixes-v3-3-62d9a631c880@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Reject a TLS alert record that is not two octetsChuck Lever
tls_alert_recv() reads two octets from the kvec it is handed and does not check the length (net/handshake/alert.c). svc_tcp_sock_recv_cmsg() calls it for any positive receive, and the alert[] buffer it supplies carries no initializer. A one-octet alert body leaves the description read from uninitialized stack and reported through trace_tls_alert_recv(). The peer controls that length. Neither tls_rx_msg_size() nor tls_rx_one_record() enforces the two-octet Alert payload. A TLS 1.3 record carrying only the inner content-type octet decrypts to a zero-length payload. RFC 8446 Section 5.1 requires a record with an Alert type to carry exactly one message, so any other length is malformed. Require exactly two octets before parsing and return -EBADMSG otherwise. That closes the transport rather than acting on a partly uninitialized alert. Gate the path on a control message rather than a positive count so that a zero-length record reaches the check. Fixes: bee47cb026e7 ("sunrpc: fix handling of server side tls alerts") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260808-svcsock-cmsg-fixes-v3-2-62d9a631c880@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-10-04SUNRPC: Do not credit control-record octets to the RPC streamChuck Lever
svc_tcp_sock_recv_cmsg() receives up to two octets into a local buffer, and returns that count for any record type other than TLS_RECORD_TYPE_ALERT. Nothing reached the caller's buffer, but svc_tcp_read_marker() adds the count to sk_tcplen and svc_tcp_read_msg()'s caller adds it to sk_datalen. The RPC stream advances over octets it never received. The fragment marker is assembled from stale sk_marker octets. The message body comes from pages nothing wrote. A conforming client reaches this. RFC 8446 Section 4.6.3 lets either peer send KeyUpdate once it has sent its Finished, and svcsock has no rekey path. kTLS leaves the partially consumed record on ctx->rx_list, so the body drains two octets per svc_tcp_recvfrom() call. Each pair is credited the same way. Return -EAGAIN for a record that is not an alert. That is what svc_tcp_sock_process_cmsg()'s default arm returned before the receive moved into a local buffer. Fixes: bee47cb026e7 ("sunrpc: fix handling of server side tls alerts") Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20260808-svcsock-cmsg-fixes-v3-1-62d9a631c880@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-09-24xprtrdma: Fix Write chunk payload corruption on a short reply headerChuck Lever
An NFSv3 server may return READ3resok with attributes_follow set to FALSE. The client has already reserved enough head iovec space for the largest possible reply header, so such a reply falls 84 bytes short of that estimate. rpcrdma_inline_fixup() points the head iovec at the received message but leaves its length at the reserved size, so it runs past the header into stale receive buffer content. xdr_realign_pages() then shifts those bytes into the page list, and the READ returns transport data where READ payload belongs. nfs3_read_done() records the shorter header size, so on an ordinary NFSv3 mount, only the first READ is corrupted. However, the FlexFiles layout driver installs its own completion callback, so every READ from a data server is corrupt. To address this, reduce the head iovec to the header bytes actually received when a Write chunk carries the READ payload. An auth flavor that transforms the payload cannot use a Write chunk, so scoping it to Write chunks leaves krb5[ip] alone. Fixes: cb0ae1fbb2f5 ("xprtrdma: Do not update {head, tail}.iov_len in rpcrdma_inline_fixup()") Reported-by: Rakesh Bhargava <Rakesh.Bhargava@netapp.com> Closes: https://lore.kernel.org/linux-nfs/SA6PR06MB104695205126871E29444567A8BA02@SA6PR06MB10469.namprd06.prod.outlook.com/ Signed-off-by: Chuck Lever <cel@kernel.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-09-04treewide: refresh kmalloc_obj() conversionsKees Cook
This is another run of the Coccinelle script for converting kmalloc() family of allocations to kmalloc_obj() via the existing rules in scripts/coccinelle/api/kmalloc_objs.cocci This catches both the set of kmalloc() uses added since the first kmalloc_obj() conversions in v7.0 and adds a large group missed in the first pass due to Coccinelle not interacting well with the cleanup.h scoped_...() family of macros[1]. I worked around this with spatch's "--macro-file" argument to a file with all the scoped_...() macros mapped to Coccinelle's YACFE_ITERATOR[2] as that was the closest viable control flow indicator I could find. Build tested allmodconfig on x86, arm64, arm, loongarch, mips, powerpc, riscv, and s390 with no new warnings. Link: https://lore.kernel.org/lkml/202609021314.8A9C0B8@keescook/ [1] Link: https://github.com/coccinelle/coccinelle/blob/master/standard.h [2] Signed-off-by: Kees Cook <kees+treewide@kernel.org>
2026-08-26Merge tag 'nfs-for-7.3-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfsLinus Torvalds
Pull NFS client updates from Trond Myklebust: "Highlights include: Stable fixes: - Use-after-free fixes for the sunrpc client code - Delegation hash table leak - NULL dereference on lockowner allocation failure - Fix a handshake completion race in the TLS code - Fix an error sign checking issue when deciding whether the pNFS layout is still in use, or can be returned - Fix a layout segment leak in pnfs_layout_process() Other bugfixes: - Fix a missing NULL check in the rpcbind client - annotate shared socket callbacks with READ_ONCE/WRITE_ONCE - nfs_inode_set_delegation() error paths should return the delegation - Use clear_and_wake_up_bit() in nfs_clear_invalid_mapping() and the pNFS code. - Fix the nfs4_alloc_client() error paths to free the IDR allocation - fix folio dereference before NULL check in nfs_inode_remove_request() - Fix delayed delegation return - Fix another state manager race with umount - Fix device leaks on parse failure - Avoid cancelling in-flight I/O during a layout recall if the server doesn't require it - flexfiles: report cancelled I/O as a layout error - flexfiles: fix NULL dereference for NFSv4.0 data servers - Fix incorrect argument passed to nfs4_delete_lease() - Fix several symlink issues resulting from nfs_atomic_open_v23() - Fix an uninitialised variable issue in the NFSv4.1 callback code - fix LAYOUTSTATS send buffer exhaustion Features and cleanups: - NFSv4.2: Allow the server to specify that file data may not be cached - localio: optimise I/O submission when when not doing memory reclaim - localio: Remove duplicate wait code in nfs_local_commit - flexfiles: support loosely coupled NFSv4.x data servers - pNFS: key the data server cache on the NFS version" * tag 'nfs-for-7.3-1' of git://git.linux-nfs.org/projects/trondmy/linux-nfs: (33 commits) NFSv4.1: fix layout segment leak on the pnfs_layout_process() forget path NFSv4/pnfs: key the data server cache on the NFS version NFSv4.2: fix LAYOUTSTATS send buffer exhaustion pNFS: Fix EBUSY check in pnfs_layout_need_return NFSv4.1: zero referring call lists before decoding nfs: fix ENXIO on O_CREAT open of existing symlink over NFSv3 SUNRPC: wait for in-flight client TLS handshake callback NFSv4: Fix incorrect argument passed to nfs4_delete_lease() in nfs4_add_lease() lockd: fix NULL dereference on lockowner allocation failure NFS: fix delegation_hash_table leak when nfs4_server_common_setup() fails NFSv4/flexfiles: support loosely coupled data servers NFSv4/flexfiles: fix NULL dereference for NFSv4.0 data servers NFSv4: pin the superblock for active state owners sunrpc: fix use-after-free in __rpc_clnt_handle_event and __rpc_clnt_remove_pipedir NFS/localio: issue commit inline when not in a memory-reclaim context NFS/localio: remove dead FLUSH_SYNC handling from nfs_local_commit NFS/localio: issue IO inline when not in a memory-reclaim context NFS: Fix delayed delegation return list handling NFS: Verify symlink inode before caching target NFS: fix folio dereference before NULL check in nfs_inode_remove_request() ...
2026-08-21Merge tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdmaLinus Torvalds
Pull RDMA updates from Jason Gunthorpe: "About the normal size, still a lot of AI bug fixes and so on, but some interesting new functionality too: - Assorted locking, bounds-checking, cleanup, and error-path fixes across UCMA/CMA, bng_re, bnxt_re, cxgb4, EFA, ERDMA, HFI1, HNS, ionic, iRDMA, mlx4/mlx5, RXE, SIW, SRP/SRPT, and iSER target. - netlink report for max # of supported resources - get_zeroed_page()/etc removal - Robust udata for ionic - Allow unique RDMA device names per network namespace - Completion counters and v2 admit queue support for EFA - UC QP support for MANA - Completion timestamps for ionic - Harden uverbs data validation and resource lifetime handling, fixing several core use-after-free conditions. - bnxt_re toggle-page ownership and lifetime bug fixes - dmabuf SRQ support for mlx5" * tag 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/rdma/rdma: (160 commits) RDMA/ucma: Allow path records to exactly fit the output buffer RDMA/uverbs: Guard legacy bundles without method_elm RDMA/efa: Add support for 128B admin v2 SQ entry RDMA/efa: Generalize the admin SQ RDMA/efa: Decouple admin command payload from admin header RDMA/rxe: Fix OOB in free_rd_atomic_resources() RDMA/cma: Fix WARNING in res_to_rt RDMA/cxgb4: Free debugfs on registration failure RDMA/cxgb4: Cancel reg_work before freeing device on remove RDMA/ucma: Lock the handler in ucma_set_ib_path() RDMA/ucma: Lock the handler in ucma_write_cm_event() RDMA/erdma: restrict the driver to little-endian systems RDMA/ionic: Embed counter driver data in rdma_counter allocation RDMA/ionic: Cap eq_count to the eth driver's interrupt vector budget RDMA/siw: Fix use-after-free in siw_accept() IB/isert: post the full-feature receive buffers after session registration IB/isert: delay the final Login Response until the session is registered RDMA/srp: fix heap information leak on a truncated SRP_CRED_REQ RDMA/erdma: Hold QP references for AE and CM processing RDMA/erdma: Hold CQ references when processing EQ events ...
2026-08-17SUNRPC: wait for in-flight client TLS handshake callbackJérémy Jean
xs_tls_handshake_sync() gives xs_tls_handshake_done() a reference to the lower transport before submitting the handshake request. On timeout or signal, the synchronous waiter drops that reference after calling tls_handshake_cancel(). handshake_req_cancel() returns false when handshake_complete() has already marked the request complete. In that case the completion callback can still be running, so dropping the callback-owned reference in the waiter can free the lower transport before xs_tls_handshake_done() stores xprt_err or drops its own reference. If cancellation loses to completion, wait until xs_tls_handshake_done() signals handshake_done and let the callback release its reference. This mirrors the server-side handshake lifetime handling and keeps the timeout or signal return value unchanged. Fixes: 75eb6af7acdf ("SUNRPC: Add a TCP-with-TLS RPC transport class") Cc: stable@vger.kernel.org Assisted-by: Codex:gpt-5 Signed-off-by: Jérémy Jean <Jeremy.Jean@oss.cyber.gouv.fr> Reviewed-by: Chuck Lever <cel@kernel.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-17sunrpc: fix use-after-free in __rpc_clnt_handle_event and ↵Luxiao Xu
__rpc_clnt_remove_pipedir Normal client creation goes through rpc_setup_pipedir(), which records clnt->pipefs_sb, but the mount-event path in __rpc_clnt_handle_event() calls rpc_setup_pipedir_sb() directly and never refreshes that field. The umount path also removes the directory without clearing clnt->pipefs_sb. After a late pipefs mount or any remount, rpc_clnt_remove_pipedir() compares the current superblock against a stale pipefs_sb pointer and skips cleanup, leaving pipefs dentries whose inode private data still points at a freed rpc_clnt, leading to a potential use-after-free during subsequent rpc_info_open() or rpc_show_info() calls. Fix this by properly updating clnt->pipefs_sb upon mount events and clearing it during unmount or failure paths. Fixes: bfca5fb4e97c ("SUNRPC: Fix RPC client cleaned up the freed pipefs dentries") Cc: stable@vger.kernel.org Reported-by: Yuan Tan <yuantan098@gmail.com> Reported-by: Xin Liu <dstsmallbird@foxmail.com> Reviewed-by: Ren Wei <enjou1224z@gmail.com> Assisted-by: Codex:gpt-5.4 Signed-off-by: Luxiao Xu <rakukuip@gmail.com> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-10sunrpc: xprtsock: annotate shared socket callbacks with READ_ONCE/WRITE_ONCERunyu Xiao
xprtsock replaces and restores sk->sk_data_ready and sk->sk_write_space on live sockets with plain stores, and xs_udp_do_set_buffer_size() invokes sk->sk_write_space via a plain load. These callback pointers are shared with generic socket and protocol paths that may read or invoke them concurrently, so xprtsock needs the same READ_ONCE()/WRITE_ONCE() callback visibility contract that the validated 4022 family applied elsewhere. When SUNRPC takes over an AF_LOCAL, UDP, or TCP socket and later restores the lower-socket callbacks during teardown, another CPU may still hold an earlier callback snapshot. The plain replace/restore pattern leaves the same visibility hole as the validated 4022 family, so a stale snapshot can still invoke xs_data_ready() or xs_udp_write_space() after the live callback fields have already been restored to the lower-socket handlers. Use WRITE_ONCE() for the shared sk_data_ready and sk_write_space stores in xs_local_finish_connecting(), xs_udp_finish_connecting(), xs_tcp_finish_connecting(), and xs_restore_old_callbacks(). Use READ_ONCE() for the direct sk_write_space invocation in xs_udp_do_set_buffer_size(). This matches the required callback visibility contract while leaving adjacent sk_state_change and sk_error_report handling unchanged. Fixes: a246b0105bbd ("[PATCH] RPC: introduce client-side transport switch") Signed-off-by: Runyu Xiao <runyu.xiao@seu.edu.cn> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-10SUNRPC: check rpc_sockaddr2uaddr() return value in rpcb_register_inet4/6Weiming Shi
rpcb_register_inet4() and rpcb_register_inet6() store the result of rpc_sockaddr2uaddr() into map->r_addr without checking it for NULL. rpc_sockaddr2uaddr() returns NULL when its final kstrdup() fails, and the unchecked NULL is then carried into the synchronous RPCBPROC_SET encode path: rpcb_register_call() -> rpc_call_sync() -> rpcb_enc_getaddr() -> encode_rpcb_string(), whose first statement is strlen(string), dereferencing NULL and oopsing the kernel. The crash reproduces under failslab on v6.12; with KASAN the NULL dereference surfaces as a fault on the shadow of address zero: Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000 [#1] PREEMPT SMP KASAN RIP: 0010:strlen (lib/string.c:409) Call Trace: encode_rpcb_string (net/sunrpc/rpcb_clnt.c:890) rpcb_enc_getaddr (net/sunrpc/rpcb_clnt.c:910) rpcauth_wrap_req_encode (net/sunrpc/auth.c:745) call_encode (net/sunrpc/clnt.c:1966) __rpc_execute (net/sunrpc/sched.c:952) rpc_run_task (net/sunrpc/clnt.c:1243) rpc_call_sync (net/sunrpc/clnt.c:1272) rpcb_v4_register (net/sunrpc/rpcb_clnt.c:500) svc_generic_rpcbind_set nfsd_rpcbind_set svc_register svc_setup_socket svc_addsock write_ports nfsctl_transaction_write vfs_write The crash is reachable when an in-kernel RPC service (nfsd, lockd, nfs-callback) registers with the local rpcbind under enough memory pressure for the small GFP_KERNEL kstrdup() in rpc_sockaddr2uaddr() to fail. The asynchronous getport path already handles this exact failure mode by returning -ENOMEM; only the two register helpers omit the check. Mirror that handling: bail out with -ENOMEM when rpc_sockaddr2uaddr() returns NULL, before the address is fed into the encoder. Fixes: d77385f23830 ("SUNRPC: Fix rpc_sockaddr2uaddr") Reported-by: Xiang Mei <xmei5@asu.edu> Assisted-by: Claude:claude-opus-4-8 Signed-off-by: Weiming Shi <bestswngs@gmail.com> Reviewed-by: Jeff Layton <jlayton@kernel.org> Signed-off-by: Trond Myklebust <trond.myklebust@hammerspace.com>
2026-08-10sunrpc: remove unused svc_version vs_count fieldJeff Layton
Now that svc_seq_show() and the nfsd netlink stats handler both use the per-netns svc_stat vs_count arrays, the global per-version vs_count percpu counters are no longer read by anything. Remove the vs_count field from struct svc_version and all the associated DEFINE_PER_CPU_ALIGNED arrays and initializers across nfsd, lockd, and the NFS client callback service. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260717-exportd-netlink-v7-4-b7ce17b83b60@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>
2026-08-10sunrpc: use per-net counts in svc_seq_show()Jeff Layton
Update svc_seq_show() to read from the per-netns statp->vs_count[] arrays instead of the global svc_version->vs_count[]. The only caller is nfsd, which always allocates vs_count via svc_stat_alloc_counts() in nfsd_net_init(), so the per-netns arrays are always available. This makes /proc/net/rpc/nfsd report per-network-namespace procedure call counts. Assisted-by: LLM Signed-off-by: Jeff Layton <jlayton@kernel.org> Link: https://patch.msgid.link/20260717-exportd-netlink-v7-2-b7ce17b83b60@kernel.org Signed-off-by: Chuck Lever <cel@kernel.org>