The branch main has been updated by rmacklem:

URL: 
https://cgit.FreeBSD.org/src/commit/?id=947bd2479ba9661a99f2415038e7b5fa972ec843

commit 947bd2479ba9661a99f2415038e7b5fa972ec843
Author:     Rick Macklem <rmack...@freebsd.org>
AuthorDate: 2021-05-31 00:52:43 +0000
Commit:     Rick Macklem <rmack...@freebsd.org>
CommitDate: 2021-05-31 00:52:43 +0000

    nfsd: Add support for the NFSv4.1/4.2 Secinfo_no_name operation
    
    The Linux client is now attempting to use the Secinfo_no_name
    operation for NFSv4.1/4.2 mounts.  Although it does not seem to
    mind the NFSERR_NOTSUPP reply, adding support for it seems
    reasonable.
    
    I also noticed that "savflag" needed to be 64bits in
    nfsrvd_secinfo() since nd_flag in now 64bits, so I changed
    the declaration of it there.  I also added code to set "vp" NULL
    after performing Secinfo/Secinfo_no_name, since these
    operations consume the current FH, which is represented
    by "vp" in nfsrvd_compound().
    
    Fixing when the server replies NFSERR_WRONGSEC so that
    it conforms to RFC5661 Sec. 2.6 still needs to be done
    in a future commit.
    
    MFC after:      2 weeks
---
 sys/fs/nfs/nfs_commonsubs.c       |   2 +-
 sys/fs/nfs/nfs_var.h              |   2 +
 sys/fs/nfs/nfsproto.h             |   4 ++
 sys/fs/nfsserver/nfs_nfsdserv.c   | 113 +++++++++++++++++++++++++++++++++++++-
 sys/fs/nfsserver/nfs_nfsdsocket.c |  15 ++++-
 sys/fs/nfsserver/nfs_nfsdsubs.c   |   3 +-
 6 files changed, 134 insertions(+), 5 deletions(-)

diff --git a/sys/fs/nfs/nfs_commonsubs.c b/sys/fs/nfs/nfs_commonsubs.c
index 7ddef0f19ddc..02416da54f01 100644
--- a/sys/fs/nfs/nfs_commonsubs.c
+++ b/sys/fs/nfs/nfs_commonsubs.c
@@ -168,7 +168,7 @@ struct nfsv4_opflag nfsv4_opflag[NFSV42_NOPS] = {
        { 0, 1, 0, 1, LK_EXCLUSIVE, 1, 1 },             /* Layout Commit */
        { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },             /* Layout Get */
        { 0, 1, 0, 1, LK_EXCLUSIVE, 1, 0 },             /* Layout Return */
-       { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },             /* Secinfo No name */
+       { 0, 1, 0, 0, LK_EXCLUSIVE, 1, 1 },             /* Secinfo No name */
        { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 0 },             /* Sequence */
        { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },             /* Set SSV */
        { 0, 0, 0, 0, LK_EXCLUSIVE, 1, 1 },             /* Test StateID */
diff --git a/sys/fs/nfs/nfs_var.h b/sys/fs/nfs/nfs_var.h
index f23d56050449..c1ca7c03af39 100644
--- a/sys/fs/nfs/nfs_var.h
+++ b/sys/fs/nfs/nfs_var.h
@@ -232,6 +232,8 @@ int nfsrvd_renew(struct nfsrv_descript *, int,
     vnode_t, struct nfsexstuff *);
 int nfsrvd_secinfo(struct nfsrv_descript *, int,
     vnode_t, struct nfsexstuff *);
+int nfsrvd_secinfononame(struct nfsrv_descript *, int,
+    vnode_t, struct nfsexstuff *);
 int nfsrvd_setclientid(struct nfsrv_descript *, int,
     vnode_t, struct nfsexstuff *);
 int nfsrvd_setclientidcfrm(struct nfsrv_descript *, int,
diff --git a/sys/fs/nfs/nfsproto.h b/sys/fs/nfs/nfsproto.h
index a1a992d14cdb..62d86c3a4593 100644
--- a/sys/fs/nfs/nfsproto.h
+++ b/sys/fs/nfs/nfsproto.h
@@ -726,6 +726,10 @@
 #define        NFSCDFS4_BACK           0x2
 #define        NFSCDFS4_BOTH           0x3
 
+/* Enum values for Secinfo_no_name. */
+#define        NFSSECINFONONAME_CURFH  0
+#define        NFSSECINFONONAME_PARENT 1
+
 #if defined(_KERNEL) || defined(KERNEL)
 /* Conversion macros */
 #define        vtonfsv2_mode(t,m)                                              
\
diff --git a/sys/fs/nfsserver/nfs_nfsdserv.c b/sys/fs/nfsserver/nfs_nfsdserv.c
index ef78f90fabfc..5d3c6f65ced0 100644
--- a/sys/fs/nfsserver/nfs_nfsdserv.c
+++ b/sys/fs/nfsserver/nfs_nfsdserv.c
@@ -3664,7 +3664,8 @@ nfsrvd_secinfo(struct nfsrv_descript *nd, int isdgram,
        struct nfsrvfh fh;
        struct nfsexstuff retnes;
        u_int32_t *sizp;
-       int error = 0, savflag, i;
+       int error = 0, i;
+       uint64_t savflag;
        char *bufp;
        u_long *hashp;
        struct thread *p = curthread;
@@ -3754,6 +3755,116 @@ out:
        return (error);
 }
 
+/*
+ * nfsv4 security info no name service
+ */
+int
+nfsrvd_secinfononame(struct nfsrv_descript *nd, int isdgram,
+    vnode_t dp, struct nfsexstuff *exp)
+{
+       uint32_t *tl, *sizp;
+       struct nameidata named;
+       vnode_t dirp = NULL, vp;
+       struct nfsrvfh fh;
+       struct nfsexstuff retnes;
+       int error = 0, fhstyle, i, len;
+       uint64_t savflag;
+       char *bufp;
+       u_long *hashp;
+       struct thread *p = curthread;
+
+       NFSM_DISSECT(tl, uint32_t *, NFSX_UNSIGNED);
+       fhstyle = fxdr_unsigned(int, *tl);
+       switch (fhstyle) {
+       case NFSSECINFONONAME_PARENT:
+               NFSNAMEICNDSET(&named.ni_cnd, nd->nd_cred, LOOKUP,
+                   LOCKLEAF | SAVESTART);
+               nfsvno_setpathbuf(&named, &bufp, &hashp);
+               error = nfsrv_parsename(nd, bufp, hashp, &named.ni_pathlen);
+               if (error != 0) {
+                       vput(dp);
+                       nfsvno_relpathbuf(&named);
+                       goto nfsmout;
+               }
+               if (nd->nd_repstat == 0)
+                       nd->nd_repstat = nfsvno_namei(nd, &named, dp, 1, exp, 
p, &dirp);
+               else
+                       vput(dp);
+               if (dirp != NULL)
+                       vrele(dirp);
+               vrele(named.ni_startdir);
+               nfsvno_relpathbuf(&named);
+               vp = named.ni_vp;
+               break;
+       case NFSSECINFONONAME_CURFH:
+               vp = dp;
+               break;
+       default:
+               nd->nd_repstat = NFSERR_INVAL;
+               vput(dp);
+       }
+       if (nd->nd_repstat != 0)
+               goto nfsmout;
+       fh.nfsrvfh_len = NFSX_MYFH;
+       nd->nd_repstat = nfsvno_getfh(vp, (fhandle_t *)fh.nfsrvfh_data, p);
+       vput(vp);
+       savflag = nd->nd_flag;
+       if (nd->nd_repstat == 0) {
+               nfsd_fhtovp(nd, &fh, LK_SHARED, &vp, &retnes, NULL, 0);
+               if (vp != NULL)
+                       vput(vp);
+       }
+       nd->nd_flag = savflag;
+       if (nd->nd_repstat != 0)
+               goto nfsmout;
+
+       /*
+        * Finally have the export flags for fh/parent, so we can create
+        * the security info.
+        */
+       len = 0;
+       NFSM_BUILD(sizp, uint32_t *, NFSX_UNSIGNED);
+       for (i = 0; i < retnes.nes_numsecflavor; i++) {
+               if (retnes.nes_secflavors[i] == AUTH_SYS) {
+                       NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+                       *tl = txdr_unsigned(RPCAUTH_UNIX);
+                       len++;
+               } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5) {
+                       NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+                       *tl = txdr_unsigned(RPCAUTH_GSS);
+                       nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
+                           nfsgss_mechlist[KERBV_MECH].len);
+                       NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+                       *tl++ = txdr_unsigned(GSS_KERBV_QOP);
+                       *tl = txdr_unsigned(RPCAUTHGSS_SVCNONE);
+                       len++;
+               } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5I) {
+                       NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+                       *tl = txdr_unsigned(RPCAUTH_GSS);
+                       nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
+                           nfsgss_mechlist[KERBV_MECH].len);
+                       NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+                       *tl++ = txdr_unsigned(GSS_KERBV_QOP);
+                       *tl = txdr_unsigned(RPCAUTHGSS_SVCINTEGRITY);
+                       len++;
+               } else if (retnes.nes_secflavors[i] == RPCSEC_GSS_KRB5P) {
+                       NFSM_BUILD(tl, uint32_t *, NFSX_UNSIGNED);
+                       *tl = txdr_unsigned(RPCAUTH_GSS);
+                       nfsm_strtom(nd, nfsgss_mechlist[KERBV_MECH].str,
+                           nfsgss_mechlist[KERBV_MECH].len);
+                       NFSM_BUILD(tl, uint32_t *, 2 * NFSX_UNSIGNED);
+                       *tl++ = txdr_unsigned(GSS_KERBV_QOP);
+                       *tl = txdr_unsigned(RPCAUTHGSS_SVCPRIVACY);
+                       len++;
+               }
+       }
+       *sizp = txdr_unsigned(len);
+
+nfsmout:
+       NFSEXITCODE2(error, nd);
+       return (error);
+}
+
 /*
  * nfsv4 set client id service
  */
diff --git a/sys/fs/nfsserver/nfs_nfsdsocket.c 
b/sys/fs/nfsserver/nfs_nfsdsocket.c
index e9602c352420..a8e1757835ac 100644
--- a/sys/fs/nfsserver/nfs_nfsdsocket.c
+++ b/sys/fs/nfsserver/nfs_nfsdsocket.c
@@ -188,7 +188,7 @@ int (*nfsrv4_ops0[NFSV42_NOPS])(struct nfsrv_descript *,
        nfsrvd_layoutcommit,
        nfsrvd_layoutget,
        nfsrvd_layoutreturn,
-       nfsrvd_notsupp,
+       nfsrvd_secinfononame,
        nfsrvd_sequence,
        nfsrvd_notsupp,
        nfsrvd_teststateid,
@@ -1175,9 +1175,20 @@ tryagain:
                                        }
                                        break;
                                }
-                               if (nd->nd_repstat == 0)
+                               if (nd->nd_repstat == 0) {
                                        error = (*(nfsrv4_ops0[op]))(nd,
                                            isdgram, vp, &vpnes);
+                                       if ((op == NFSV4OP_SECINFO ||
+                                            op == NFSV4OP_SECINFONONAME) &&
+                                           error == 0 && nd->nd_repstat == 0) {
+                                               /*
+                                                * Secinfo and Secinfo_no_name
+                                                * consume the current FH.
+                                                */
+                                               vrele(vp);
+                                               vp = NULL;
+                                       }
+                               }
                                if (nfsv4_opflag[op].modifyfs)
                                        vn_finished_write(temp_mp);
                        } else {
diff --git a/sys/fs/nfsserver/nfs_nfsdsubs.c b/sys/fs/nfsserver/nfs_nfsdsubs.c
index 49c5cac999c7..2b6e17752544 100644
--- a/sys/fs/nfsserver/nfs_nfsdsubs.c
+++ b/sys/fs/nfsserver/nfs_nfsdsubs.c
@@ -1890,7 +1890,8 @@ nfsrv_parsename(struct nfsrv_descript *nd, char *bufp, 
u_long *hashp,
         * For V4, check for lookup parent.
         * Otherwise, get the component name.
         */
-       if ((nd->nd_flag & ND_NFSV4) && nd->nd_procnum == NFSV4OP_LOOKUPP) {
+       if ((nd->nd_flag & ND_NFSV4) && (nd->nd_procnum == NFSV4OP_LOOKUPP ||
+           nd->nd_procnum == NFSV4OP_SECINFONONAME)) {
            *tocp++ = '.';
            hash += ((u_char)'.');
            *tocp++ = '.';
_______________________________________________
dev-commits-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/dev-commits-src-all
To unsubscribe, send any mail to "dev-commits-src-all-unsubscr...@freebsd.org"

Reply via email to