FAILED: patch "[PATCH] nfsd: decouple the xprtsec policy check from" failed to apply to 6.6-stable tree
Subsystems (2)
[email protected]
maintainerThe patch below does not apply to the 6.6-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.
To reproduce the conflict and resubmit, you may use the following commands:
git fetch https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/ linux-6.6.y
git checkout FETCH_HEAD
git cherry-pick -x e4f574ca9c6dfa66695bb054ff5df43ecea873ec
# <resolve conflicts, build, test, etc.>
git commit -s
git send-email --to '<[email protected]>' --in-reply-to '2025101611-revisit-ranging-52d6@gregkh' --subject-prefix 'PATCH 6.6.y' HEAD^..
Possible dependencies:
thanks,
greg k-h
------------------ original commit in Linus's tree ------------------
From e4f574ca9c6dfa66695bb054ff5df43ecea873ec Mon Sep 17 00:00:00 2001
From: Scott Mayhew <[email protected]>
Date: Wed, 6 Aug 2025 15:15:43 -0400
Subject: [PATCH] nfsd: decouple the xprtsec policy check from
check_nfsd_access()
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().
fs/nfsd/export.c +57 -25
@@ -1082,50 +1082,62 @@ static struct svc_export *exp_find(struct cache_detail *cd, }/** -* 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;
@@ -1167,10 +1179,30 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp, } } -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;
fs/nfsd/export.h +3 -0
@@ -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);
fs/nfsd/nfsfh.c +23 -1
@@ -364,10 +364,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;/*
@@ -379,13 +399,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:
PATCH 1/1 nfsd: decouple the xprtsec policy check from check_nfsd_access()
[ Upstream commit e4f574ca9c6dfa66695bb054ff5df43ecea873ec ]
This is a backport of e4f574ca9c6d specifically for the 6.6-stable kernel. It differs from the upstream version mainly in that it's working around the absence of some 6.12-era commits:
- 1459ad57673b nfsd: Move error code mapping to per-version proc code.
- 0a183f24a7ae NFSD: Handle @rqstp == NULL in check_nfsd_access()
- 5e66d2d92a1c nfsd: factor out __fh_verify to allow NULL rqstp to be passed
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.
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().
--- fs/nfsd/export.c | 60 +++++++++++++++++++++++++++++++++++++++++------- fs/nfsd/export.h | 2 ++ fs/nfsd/nfsfh.c | 12 +++++++++- 3 files changed, 65 insertions(+), 9 deletions(-)
fs/nfsd/export.c +52 -8
@@ -1071,28 +1071,62 @@ static struct svc_export *exp_find(struct cache_detail *cd,return exp; } -__be32 check_nfsd_access (struct svc_export *exp,struct svc_rqst *rqstp) +/** +* 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. +* +* 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_acces or %nfserr_wrongsec if access is denied +*/ +__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 = 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; } - goto denied; -ok: +return rqstp->rq_vers <4 ? nfserr_acces : nfserr_wrongsec; +} + +/** +* check_security_flavor - 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. +* +* 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_acces or %nfserr_wrongsec if access is denied +*/ +__be32 check_security_flavor (struct svc_export *exp,struct svc_rqst *rqstp) +{ +struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; +/* legacy gss-only clients are always OK: */ if (exp->ex_client == rqstp->rq_gssclient)return 0 ;
@@ -1117,10 +1151,20 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)if (nfsd4_spo_must_allow (rqstp))return 0 ; -denied:return rqstp->rq_vers <4 ? nfserr_acces : nfserr_wrongsec; } +__be32 check_nfsd_access (struct svc_export *exp,struct svc_rqst *rqstp) +{ +__be32 status; + + status =check_xprtsec_policy (exp, rqstp); +if (status != nfs_ok) +return status; + +return check_security_flavor (exp, rqstp); +} +/* * 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;
fs/nfsd/export.h +2 -0
@@ -100,6 +100,8 @@ struct svc_expkey {#define EX_WGATHER (exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)int nfsexp_flags (struct svc_rqst *rqstp,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);__be32 check_nfsd_access (struct svc_export *exp,struct svc_rqst *rqstp);/*
fs/nfsd/nfsfh.c +11 -1
@@ -370,6 +370,16 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)if (error) goto out; +/* +* NLM is allowed to bypass the xprtsec policy check because lockd +* doesn't support xprtsec. +*/ +if (!(access &NFSD_MAY_LOCK )) { + error =check_xprtsec_policy (exp, rqstp); +if (error) + goto out; + } +/* * pseudoflavor restrictions are not enforced on NLM, * which clients virtually always use auth_sys for,
@@ -386,7 +396,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access) && exp->ex_path.dentry == dentry) goto skip_pseudoflavor_check; - error =check_nfsd_access (exp, rqstp); + error =check_security_flavor (exp, rqstp);if (error) goto out;
Signature · 1 line
2.47.3
Re: [PATCH 6.6.y] nfsd: decouple the xprtsec policy check from check_nfsd_access()
Quoted 163 lines · Scott Mayhew
[ Upstream commit
e4f574ca9c6dfa66695bb054ff5df43ecea873ec]This is a backport of
e4f574ca9c6dspecifically for the 6.6-stable kernel. It differs from the upstream version mainly in that it's working around the absence of some 6.12-era commits:
-1459ad57673bnfsd: Move error code mapping to per-version proc code.
-0a183f24a7aeNFSD: Handle @rqstp == NULL incheck_nfsd_access()
-5e66d2d92a1cnfsd: factor out__fh_verifyto allow NULL rqstp to be passedA 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 withNFS3ERR_ACCES.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 havefh_verify()call the helpers directly sincefh_verify()has logic that allows one or both of the checks to be skipped. All other sites will continue to callcheck_nfsd_access().Fixes 9280c5774314 ("NFSD: Handle new xprtsec= export option")Signed-off-by Scott Mayhew <[email protected]>--- fs/nfsd/export.c | 60 +++++++++++++++++++++++++++++++++++++++++------- fs/nfsd/export.h | 2 ++ fs/nfsd/nfsfh.c | 12 +++++++++- 3 files changed, 65 insertions(+), 9 deletions(-)fs/nfsd/export.c +52
-8@@ -1071,28 +1071,62 @@ static struct svc_export *exp_find(struct cache_detail *cd,return exp; } -__be32 check_nfsd_access (struct svc_export *exp,struct svc_rqst *rqstp) +/** +* 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. +* +* 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_acces or %nfserr_wrongsec if access is denied +*/ +__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 = 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; } - goto denied; -ok: +return rqstp->rq_vers <4 ? nfserr_acces : nfserr_wrongsec; +} + +/** +* check_security_flavor - 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. +* +* 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_acces or %nfserr_wrongsec if access is denied +*/ +__be32 check_security_flavor (struct svc_export *exp,struct svc_rqst *rqstp) +{ +struct exp_flavor_info *f, *end = exp->ex_flavors + exp->ex_nflavors; +/* legacy gss-only clients are always OK: */ if (exp->ex_client == rqstp->rq_gssclient)return 0 ;@@ -1117,10 +1151,20 @@ __be32 check_nfsd_access(struct svc_export *exp, struct svc_rqst *rqstp)if (nfsd4_spo_must_allow (rqstp))return 0 ; -denied:return rqstp->rq_vers <4 ? nfserr_acces : nfserr_wrongsec; } +__be32 check_nfsd_access (struct svc_export *exp,struct svc_rqst *rqstp) +{ +__be32 status; + + status =check_xprtsec_policy (exp, rqstp); +if (status != nfs_ok) +return status; + +return check_security_flavor (exp, rqstp); +} +/* * 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; fs/nfsd/export.h +2
-0@@ -100,6 +100,8 @@ struct svc_expkey {#define EX_WGATHER (exp) ((exp)->ex_flags & NFSEXP_GATHERED_WRITES)int nfsexp_flags (struct svc_rqst *rqstp,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);__be32 check_nfsd_access (struct svc_export *exp,struct svc_rqst *rqstp);/* fs/nfsd/nfsfh.c +10
-0@@ -370,6 +370,16 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access)if (error) goto out; +/* +* NLM is allowed to bypass the xprtsec policy check because lockd +* doesn't support xprtsec. +*/ +if (!(access &NFSD_MAY_LOCK )) { + error =check_xprtsec_policy (exp, rqstp); +if (error) + goto out; + } +/* * pseudoflavor restrictions are not enforced on NLM, * which clients virtually always use auth_sys for,
fs/nfsd/nfsfh.c fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access) · line 402
Quoted 8 lines
fs/nfsd/nfsfh.c +1
-1@@ -386,7 +396,7 @@ fh_verify(struct svc_rqst *rqstp, struct svc_fh *fhp, umode_t type, int access) && exp->ex_path.dentry == dentry) goto skip_pseudoflavor_check; - error =check_nfsd_access (exp, rqstp); + error =check_security_flavor (exp, rqstp);if (error) goto out;
Signature · 1 line
Chuck Lever