From: Greg Kroah-Hartman Date: Sun, 19 Oct 2025 12:25:13 +0000 (+0200) Subject: 6.12-stable patches X-Git-Tag: v5.15.195~2 X-Git-Url: http://git.ipfire.org/gitweb.cgi?a=commitdiff_plain;h=e250b97228dcbc4c6e229da72ade00f98c462230;p=thirdparty%2Fkernel%2Fstable-queue.git 6.12-stable patches added patches: nfsd-decouple-the-xprtsec-policy-check-from-check_nfsd_access.patch --- diff --git a/queue-6.12/nfsd-decouple-the-xprtsec-policy-check-from-check_nfsd_access.patch b/queue-6.12/nfsd-decouple-the-xprtsec-policy-check-from-check_nfsd_access.patch new file mode 100644 index 0000000000..a9dc4a1ede --- /dev/null +++ b/queue-6.12/nfsd-decouple-the-xprtsec-policy-check-from-check_nfsd_access.patch @@ -0,0 +1,222 @@ +From e4f574ca9c6dfa66695bb054ff5df43ecea873ec Mon Sep 17 00:00:00 2001 +From: Scott Mayhew +Date: Wed, 6 Aug 2025 15:15:43 -0400 +Subject: nfsd: decouple the xprtsec policy check from check_nfsd_access() + +From: Scott Mayhew + +commit e4f574ca9c6dfa66695bb054ff5df43ecea873ec upstream. + +A while back I had reported that an NFSv3 client could successfully +mount using '-o xprtsec=none' an export that had been exported with +'xprtsec=tls:mtls'. By "successfully" I mean that the mount command +would succeed and the mount would show up in /proc/mount. Attempting +to do anything futher with the mount would be met with NFS3ERR_ACCES. + +This was fixed (albeit accidentally) by commit bb4f07f2409c ("nfsd: +Fix NFSD_MAY_BYPASS_GSS and NFSD_MAY_BYPASS_GSS_ON_ROOT") and was +subsequently re-broken by commit 0813c5f01249 ("nfsd: fix access +checking for NLM under XPRTSEC policies"). + +Transport Layer Security isn't an RPC security flavor or pseudo-flavor, +so we shouldn't be conflating them when determining whether the access +checks can be bypassed. Split check_nfsd_access() into two helpers, and +have __fh_verify() call the helpers directly since __fh_verify() has +logic that allows one or both of the checks to be skipped. All other +sites will continue to call check_nfsd_access(). + +Link: https://lore.kernel.org/linux-nfs/ZjO3Qwf_G87yNXb2@aion/ +Fixes: 9280c5774314 ("NFSD: Handle new xprtsec= export option") +Cc: stable@vger.kernel.org +Signed-off-by: Scott Mayhew +Signed-off-by: Chuck Lever +Signed-off-by: Greg Kroah-Hartman +--- + fs/nfsd/export.c | 82 ++++++++++++++++++++++++++++++++++++++----------------- + fs/nfsd/export.h | 3 ++ + fs/nfsd/nfsfh.c | 24 +++++++++++++++- + 3 files changed, 83 insertions(+), 26 deletions(-) + +--- a/fs/nfsd/export.c ++++ b/fs/nfsd/export.c +@@ -1075,50 +1075,62 @@ static struct svc_export *exp_find(struc + } + + /** +- * check_nfsd_access - check if access to export is allowed. ++ * check_xprtsec_policy - check if access to export is allowed by the ++ * xprtsec policy + * @exp: svc_export that is being accessed. +- * @rqstp: svc_rqst attempting to access @exp (will be NULL for LOCALIO). +- * @may_bypass_gss: reduce strictness of authorization check ++ * @rqstp: svc_rqst attempting to access @exp. ++ * ++ * Helper function for check_nfsd_access(). Note that callers should be ++ * using check_nfsd_access() instead of calling this function directly. The ++ * one exception is __fh_verify() since it has logic that may result in one ++ * or both of the helpers being skipped. + * + * Return values: + * %nfs_ok if access is granted, or + * %nfserr_wrongsec if access is denied + */ +-__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, +- bool may_bypass_gss) ++__be32 check_xprtsec_policy(struct svc_export *exp, struct svc_rqst *rqstp) + { +- struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; +- struct svc_xprt *xprt; +- +- /* +- * If rqstp is NULL, this is a LOCALIO request which will only +- * ever use a filehandle/credential pair for which access has +- * been affirmed (by ACCESS or OPEN NFS requests) over the +- * wire. So there is no need for further checks here. +- */ +- if (!rqstp) +- return nfs_ok; +- +- xprt = rqstp->rq_xprt; ++ struct svc_xprt *xprt = rqstp->rq_xprt; + + if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_NONE) { + if (!test_bit(XPT_TLS_SESSION, &xprt->xpt_flags)) +- goto ok; ++ return nfs_ok; + } + if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_TLS) { + if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) && + !test_bit(XPT_PEER_AUTH, &xprt->xpt_flags)) +- goto ok; ++ return nfs_ok; + } + if (exp->ex_xprtsec_modes & NFSEXP_XPRTSEC_MTLS) { + if (test_bit(XPT_TLS_SESSION, &xprt->xpt_flags) && + test_bit(XPT_PEER_AUTH, &xprt->xpt_flags)) +- goto ok; ++ return nfs_ok; + } +- if (!may_bypass_gss) +- goto denied; ++ return nfserr_wrongsec; ++} ++ ++/** ++ * check_security_flavor - check if access to export is allowed by the ++ * security flavor ++ * @exp: svc_export that is being accessed. ++ * @rqstp: svc_rqst attempting to access @exp. ++ * @may_bypass_gss: reduce strictness of authorization check ++ * ++ * Helper function for check_nfsd_access(). Note that callers should be ++ * using check_nfsd_access() instead of calling this function directly. The ++ * one exception is __fh_verify() since it has logic that may result in one ++ * or both of the helpers being skipped. ++ * ++ * Return values: ++ * %nfs_ok if access is granted, or ++ * %nfserr_wrongsec if access is denied ++ */ ++__be32 check_security_flavor(struct svc_export *exp, struct svc_rqst *rqstp, ++ bool may_bypass_gss) ++{ ++ struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; + +-ok: + /* legacy gss-only clients are always OK: */ + if (exp->ex_client == rqstp->rq_gssclient) + return nfs_ok; +@@ -1160,10 +1172,30 @@ ok: + } + } + +-denied: + return nfserr_wrongsec; + } + ++/** ++ * check_nfsd_access - check if access to export is allowed. ++ * @exp: svc_export that is being accessed. ++ * @rqstp: svc_rqst attempting to access @exp. ++ * @may_bypass_gss: reduce strictness of authorization check ++ * ++ * Return values: ++ * %nfs_ok if access is granted, or ++ * %nfserr_wrongsec if access is denied ++ */ ++__be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, ++ bool may_bypass_gss) ++{ ++ __be32 status; ++ ++ status = check_xprtsec_policy(exp, rqstp); ++ if (status != nfs_ok) ++ return status; ++ return check_security_flavor(exp, rqstp, may_bypass_gss); ++} ++ + /* + * Uses rq_client and rq_gssclient to find an export; uses rq_client (an + * auth_unix client) if it's available and has secinfo information; +--- a/fs/nfsd/export.h ++++ b/fs/nfsd/export.h +@@ -101,6 +101,9 @@ struct svc_expkey { + + struct svc_cred; + int nfsexp_flags(struct svc_cred *cred, struct svc_export *exp); ++__be32 check_xprtsec_policy(struct svc_export *exp, struct svc_rqst *rqstp); ++__be32 check_security_flavor(struct svc_export *exp, struct svc_rqst *rqstp, ++ bool may_bypass_gss); + __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, + bool may_bypass_gss); + +--- a/fs/nfsd/nfsfh.c ++++ b/fs/nfsd/nfsfh.c +@@ -363,10 +363,30 @@ __fh_verify(struct svc_rqst *rqstp, + if (error) + goto out; + ++ /* ++ * If rqstp is NULL, this is a LOCALIO request which will only ++ * ever use a filehandle/credential pair for which access has ++ * been affirmed (by ACCESS or OPEN NFS requests) over the ++ * wire. Skip both the xprtsec policy and the security flavor ++ * checks. ++ */ ++ if (!rqstp) ++ goto check_permissions; ++ + if ((access & NFSD_MAY_NLM) && (exp->ex_flags & NFSEXP_NOAUTHNLM)) + /* NLM is allowed to fully bypass authentication */ + goto out; + ++ /* ++ * NLM is allowed to bypass the xprtsec policy check because lockd ++ * doesn't support xprtsec. ++ */ ++ if (!(access & NFSD_MAY_NLM)) { ++ error = check_xprtsec_policy(exp, rqstp); ++ if (error) ++ goto out; ++ } ++ + if (access & NFSD_MAY_BYPASS_GSS) + may_bypass_gss = true; + /* +@@ -378,13 +398,15 @@ __fh_verify(struct svc_rqst *rqstp, + && exp->ex_path.dentry == dentry) + may_bypass_gss = true; + +- error = check_nfsd_access(exp, rqstp, may_bypass_gss); ++ error = check_security_flavor(exp, rqstp, may_bypass_gss); + if (error) + goto out; ++ + /* During LOCALIO call to fh_verify will be called with a NULL rqstp */ + if (rqstp) + svc_xprt_set_valid(rqstp->rq_xprt); + ++check_permissions: + /* Finally, check access permissions. */ + error = nfsd_permission(cred, exp, dentry, access); + out: diff --git a/queue-6.12/series b/queue-6.12/series index c854c235aa..d4b240ccf4 100644 --- a/queue-6.12/series +++ b/queue-6.12/series @@ -275,3 +275,4 @@ nfsd-fix-__fh_verify-for-localio.patch nfsd-fix-access-checking-for-nlm-under-xprtsec-policies.patch asoc-sof-ipc4-pcm-fix-start-offset-calculation-for-chain-dma.patch mount-handle-null-values-in-mnt_ns_release.patch +nfsd-decouple-the-xprtsec-policy-check-from-check_nfsd_access.patch