NFSD: Don't apply NFS version-specific behavior to LOCALIO requests

LOCALIO serves NFS clients of every version through one entry point,
so no protocol version is associated with such a request.
nfsd_set_fh_dentry() selects version-specific behavior anyway: its
switch keys off fh_maxsize, and nfsd_open_local_fh() passes
NFS4_FHSIZE because that is the size of the buffer it copies into, so
LOCALIO lands in the NFSv4 arm. fh_getattr() keys off fh_maxsize too
and does run on a LOCALIO open, adding STATX_BTIME and
STATX_CHANGE_COOKIE to the mask it requests: work on filesystems that
compute them for a caller that never reads them.

nfsd_open_local_fh() only verifies a handle it received, so it has no
maximum size to state. Pass NFSD_FHSIZE_UNSPEC as nlm_fopen() already
does, which selects the switch arm that applies no version-specific
behavior, and state the bound on the copy out of struct nfs_fh as
NFS_MAXFHSIZE.

Suggested-by: NeilBrown <neil@brown.name>
Reviewed-by: NeilBrown <neil@brown.name>
Reviewed-by: Mike Snitzer <snitzer@kernel.org>
Link: https://patch.msgid.link/20260728165911.462534-6-cel@kernel.org
Signed-off-by: Chuck Lever <cel@kernel.org>
This commit is contained in:
Chuck Lever 2026-07-28 12:59:11 -04:00
parent dc8fd3caff
commit c79fbe8bb8

View File

@ -11,7 +11,6 @@
#include <linux/exportfs.h>
#include <linux/sunrpc/svcauth.h>
#include <linux/sunrpc/clnt.h>
#include <linux/nfs4.h>
#include <linux/nfs_common.h>
#include <linux/nfs_fh.h>
#include <linux/nfslocalio.h>
@ -54,7 +53,7 @@ nfsd_open_local_fh(struct net *net, struct auth_domain *dom,
struct nfsd_file *localio;
__be32 beres;
if (nfs_fh->size > NFS4_FHSIZE)
if (nfs_fh->size > NFS_MAXFHSIZE)
return ERR_PTR(-EINVAL);
if (!nfsd_net_try_get(net))
@ -67,7 +66,7 @@ nfsd_open_local_fh(struct net *net, struct auth_domain *dom,
return localio;
/* nfs_fh -> svc_fh */
fh_init(&fh, NFS4_FHSIZE);
fh_init(&fh, NFSD_FHSIZE_UNSPEC);
fh.fh_handle.fh_size = nfs_fh->size;
memcpy(fh.fh_handle.fh_raw, nfs_fh->data, nfs_fh->size);