]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/commitdiff
6.12-stable patches
authorGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Oct 2025 12:25:13 +0000 (14:25 +0200)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Sun, 19 Oct 2025 12:25:13 +0000 (14:25 +0200)
added patches:
nfsd-decouple-the-xprtsec-policy-check-from-check_nfsd_access.patch

queue-6.12/nfsd-decouple-the-xprtsec-policy-check-from-check_nfsd_access.patch [new file with mode: 0644]
queue-6.12/series

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 (file)
index 0000000..a9dc4a1
--- /dev/null
@@ -0,0 +1,222 @@
+From e4f574ca9c6dfa66695bb054ff5df43ecea873ec Mon Sep 17 00:00:00 2001
+From: Scott Mayhew <smayhew@redhat.com>
+Date: Wed, 6 Aug 2025 15:15:43 -0400
+Subject: nfsd: decouple the xprtsec policy check from check_nfsd_access()
+
+From: Scott Mayhew <smayhew@redhat.com>
+
+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 <smayhew@redhat.com>
+Signed-off-by: Chuck Lever <chuck.lever@oracle.com>
+Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
+---
+ 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:
index c854c235aac42c2221efd7457bf5aaeb467b9f50..d4b240ccf49d14bf99ac29b2ba907c61d19bf2c4 100644 (file)
@@ -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