From 4e0269352534715915aae3fb84dd4d3bb3ff3738 Mon Sep 17 00:00:00 2001 From: Anna Schumaker Date: Fri, 21 Nov 2025 14:53:50 -0500 Subject: [PATCH] NFS: Add a way to disable NFS v4.0 via KConfig I introduce NFS4_MIN_MINOR_VERSION as a parallel to NFS4_MAX_MINOR_VERSION to check if NFS v4.0 has been compiled in and return an appropriate error if not. Signed-off-by: Anna Schumaker --- fs/nfs/Kconfig | 9 +++++++++ fs/nfs/Makefile | 3 ++- fs/nfs/fs_context.c | 3 ++- fs/nfs/nfs4_fs.h | 6 ++++++ fs/nfs/nfs4client.c | 3 ++- fs/nfs/nfs4proc.c | 2 ++ fs/nfs/nfs4state.c | 2 ++ fs/nfs/nfs4xdr.c | 24 ++++++++++++++++++++++-- 8 files changed, 47 insertions(+), 5 deletions(-) diff --git a/fs/nfs/Kconfig b/fs/nfs/Kconfig index 07932ce9246c1..058ed67b98cc6 100644 --- a/fs/nfs/Kconfig +++ b/fs/nfs/Kconfig @@ -96,6 +96,15 @@ config NFS_SWAP help This option enables swapon to work on files located on NFS mounts. +config NFS_V4_0 + bool "NFS client support for NFSv4.0" + depends on NFS_V4 + help + This option enables support for minor version 0 of the NFSv4 protocol + (RFC 3530) in the kernel's NFS client. + + If unsure, say N. + config NFS_V4_1 bool "NFS client support for NFSv4.1" depends on NFS_V4 diff --git a/fs/nfs/Makefile b/fs/nfs/Makefile index d05e69c00fe1e..6a9aaf2f913bd 100644 --- a/fs/nfs/Makefile +++ b/fs/nfs/Makefile @@ -27,9 +27,10 @@ CFLAGS_nfs4trace.o += -I$(src) nfsv4-y := nfs4proc.o nfs4xdr.o nfs4state.o nfs4renewd.o nfs4super.o nfs4file.o \ delegation.o nfs4idmap.o callback.o callback_xdr.o callback_proc.o \ nfs4namespace.o nfs4getroot.o nfs4client.o nfs4session.o \ - dns_resolve.o nfs4trace.o nfs40proc.o nfs40client.o + dns_resolve.o nfs4trace.o nfsv4-$(CONFIG_NFS_USE_LEGACY_DNS) += cache_lib.o nfsv4-$(CONFIG_SYSCTL) += nfs4sysctl.o +nfsv4-$(CONFIG_NFS_V4_0) += nfs40client.o nfs40proc.o nfsv4-$(CONFIG_NFS_V4_1) += pnfs.o pnfs_dev.o pnfs_nfs.o nfsv4-$(CONFIG_NFS_V4_2) += nfs42proc.o nfs42xattr.o diff --git a/fs/nfs/fs_context.c b/fs/nfs/fs_context.c index b4679b7161b09..86750f1100533 100644 --- a/fs/nfs/fs_context.c +++ b/fs/nfs/fs_context.c @@ -806,7 +806,8 @@ static int nfs_fs_context_parse_param(struct fs_context *fc, ctx->mount_server.version = result.uint_32; break; case Opt_minorversion: - if (result.uint_32 > NFS4_MAX_MINOR_VERSION) + if (result.uint_32 < NFS4_MIN_MINOR_VERSION || + result.uint_32 > NFS4_MAX_MINOR_VERSION) goto out_of_bounds; ctx->minorversion = result.uint_32; break; diff --git a/fs/nfs/nfs4_fs.h b/fs/nfs/nfs4_fs.h index a5dd4a8377695..5a6728acb5897 100644 --- a/fs/nfs/nfs4_fs.h +++ b/fs/nfs/nfs4_fs.h @@ -10,6 +10,12 @@ #ifndef __LINUX_FS_NFS_NFS4_FS_H #define __LINUX_FS_NFS_NFS4_FS_H +#if defined(CONFIG_NFS_V4_0) +#define NFS4_MIN_MINOR_VERSION 0 +#else +#define NFS4_MIN_MINOR_VERSION 1 +#endif + #if defined(CONFIG_NFS_V4_2) #define NFS4_MAX_MINOR_VERSION 2 #elif defined(CONFIG_NFS_V4_1) diff --git a/fs/nfs/nfs4client.c b/fs/nfs/nfs4client.c index c376b2420b6cf..00b57e55aba80 100644 --- a/fs/nfs/nfs4client.c +++ b/fs/nfs/nfs4client.c @@ -203,7 +203,8 @@ struct nfs_client *nfs4_alloc_client(const struct nfs_client_initdata *cl_init) if (err) goto error; - if (cl_init->minorversion > NFS4_MAX_MINOR_VERSION) { + if (cl_init->minorversion < NFS4_MIN_MINOR_VERSION || + cl_init->minorversion > NFS4_MAX_MINOR_VERSION) { err = -EINVAL; goto error; } diff --git a/fs/nfs/nfs4proc.c b/fs/nfs/nfs4proc.c index c621294e3f0f4..3ee5394aca724 100644 --- a/fs/nfs/nfs4proc.c +++ b/fs/nfs/nfs4proc.c @@ -10591,7 +10591,9 @@ static const struct nfs4_minor_version_ops nfs_v4_2_minor_ops = { #endif const struct nfs4_minor_version_ops *nfs_v4_minor_ops[] = { +#if defined(CONFIG_NFS_V4_0) [0] = &nfs_v4_0_minor_ops, +#endif /* CONFIG_NFS_V4_0 */ #if defined(CONFIG_NFS_V4_1) [1] = &nfs_v4_1_minor_ops, #endif diff --git a/fs/nfs/nfs4state.c b/fs/nfs/nfs4state.c index f3d441bb28af8..3330a188e1a57 100644 --- a/fs/nfs/nfs4state.c +++ b/fs/nfs/nfs4state.c @@ -1804,9 +1804,11 @@ static int nfs4_recovery_handle_error(struct nfs_client *clp, int error) switch (error) { case 0: break; +#if IS_ENABLED(CONFIG_NFS_V4_0) case -NFS4ERR_CB_PATH_DOWN: nfs40_handle_cb_pathdown(clp); break; +#endif /* CONFIG_NFS_V4_0 */ case -NFS4ERR_NO_GRACE: nfs4_state_end_reclaim_reboot(clp); break; diff --git a/fs/nfs/nfs4xdr.c b/fs/nfs/nfs4xdr.c index b6fe30577fab5..85ddcee51162f 100644 --- a/fs/nfs/nfs4xdr.c +++ b/fs/nfs/nfs4xdr.c @@ -1399,11 +1399,13 @@ static void encode_locku(struct xdr_stream *xdr, const struct nfs_locku_args *ar xdr_encode_hyper(p, nfs4_lock_length(args->fl)); } +#if defined(CONFIG_NFS_V4_0) static void encode_release_lockowner(struct xdr_stream *xdr, const struct nfs_lowner *lowner, struct compound_hdr *hdr) { encode_op_hdr(xdr, OP_RELEASE_LOCKOWNER, decode_release_lockowner_maxsz, hdr); encode_lockowner(xdr, lowner); } +#endif /* CONFIG_NFS_V4_0 */ static void encode_lookup(struct xdr_stream *xdr, const struct qstr *name, struct compound_hdr *hdr) { @@ -2583,6 +2585,7 @@ static void nfs4_xdr_enc_locku(struct rpc_rqst *req, struct xdr_stream *xdr, encode_nops(&hdr); } +#if defined(CONFIG_NFS_V4_0) static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, struct xdr_stream *xdr, const void *data) @@ -2596,6 +2599,7 @@ static void nfs4_xdr_enc_release_lockowner(struct rpc_rqst *req, encode_release_lockowner(xdr, &args->lock_owner, &hdr); encode_nops(&hdr); } +#endif /* CONFIG_NFS_V4_0 */ /* * Encode a READLINK request @@ -2825,6 +2829,7 @@ static void nfs4_xdr_enc_server_caps(struct rpc_rqst *req, /* * a RENEW request */ +#if defined(CONFIG_NFS_V4_0) static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, const void *data) @@ -2838,6 +2843,7 @@ static void nfs4_xdr_enc_renew(struct rpc_rqst *req, struct xdr_stream *xdr, encode_renew(xdr, clp->cl_clientid, &hdr); encode_nops(&hdr); } +#endif /* CONFIG_NFS_V4_0 */ /* * a SETCLIENTID request @@ -5224,10 +5230,12 @@ static int decode_locku(struct xdr_stream *xdr, struct nfs_locku_res *res) return status; } +#if defined(CONFIG_NFS_V4_0) static int decode_release_lockowner(struct xdr_stream *xdr) { return decode_op_hdr(xdr, OP_RELEASE_LOCKOWNER); } +#endif /* CONFIG_NFS_V4_0 */ static int decode_lookup(struct xdr_stream *xdr) { @@ -6930,6 +6938,7 @@ out: return status; } +#if defined(CONFIG_NFS_V4_0) static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, struct xdr_stream *xdr, void *dummy) { @@ -6941,6 +6950,7 @@ static int nfs4_xdr_dec_release_lockowner(struct rpc_rqst *rqstp, status = decode_release_lockowner(xdr); return status; } +#endif /* CONFIG_NFS_V4_0 */ /* * Decode READLINK response @@ -7162,6 +7172,7 @@ out: /* * Decode RENEW response */ +#if defined(CONFIG_NFS_V4_0) static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, void *__unused) { @@ -7173,6 +7184,7 @@ static int nfs4_xdr_dec_renew(struct rpc_rqst *rqstp, struct xdr_stream *xdr, status = decode_renew(xdr); return status; } +#endif /* CONFIG_NFS_V4_0 */ /* * Decode SETCLIENTID response @@ -7754,6 +7766,14 @@ int nfs4_decode_dirent(struct xdr_stream *xdr, struct nfs_entry *entry, .p_name = #proc, \ } +#if defined(CONFIG_NFS_V4_0) +#define PROC40(proc, argtype, restype) \ + PROC(proc, argtype, restype) +#else +#define PROC40(proc, argtype, restype) \ + STUB(proc) +#endif /* CONFIG_NFS_V4_0 */ + #if defined(CONFIG_NFS_V4_1) #define PROC41(proc, argtype, restype) \ PROC(proc, argtype, restype) @@ -7781,7 +7801,7 @@ const struct rpc_procinfo nfs4_procedures[] = { PROC(CLOSE, enc_close, dec_close), PROC(SETATTR, enc_setattr, dec_setattr), PROC(FSINFO, enc_fsinfo, dec_fsinfo), - PROC(RENEW, enc_renew, dec_renew), + PROC40(RENEW, enc_renew, dec_renew), PROC(SETCLIENTID, enc_setclientid, dec_setclientid), PROC(SETCLIENTID_CONFIRM, enc_setclientid_confirm, dec_setclientid_confirm), PROC(LOCK, enc_lock, dec_lock), @@ -7805,7 +7825,7 @@ const struct rpc_procinfo nfs4_procedures[] = { PROC(GETACL, enc_getacl, dec_getacl), PROC(SETACL, enc_setacl, dec_setacl), PROC(FS_LOCATIONS, enc_fs_locations, dec_fs_locations), - PROC(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), + PROC40(RELEASE_LOCKOWNER, enc_release_lockowner, dec_release_lockowner), PROC(SECINFO, enc_secinfo, dec_secinfo), PROC(FSID_PRESENT, enc_fsid_present, dec_fsid_present), PROC41(EXCHANGE_ID, enc_exchange_id, dec_exchange_id), -- 2.47.3