Author: rmacklem
Date: Fri Jul  7 21:26:27 2017
New Revision: 320794
URL: https://svnweb.freebsd.org/changeset/base/320794

Log:
  MFC: r320208
  Ensure that the credentials field of the NFSv4 client open structure is
  initialized.
  
  bdrewery@ has reported panics "newnfs_copycred: negative nfsc_ngroups".
  The only way I can see that this occurs is that the credentials field of
  the open structure gets used before being filled in.
  I am not sure quite how this happens, but for the file create case, the
  code is serialized via the vnode lock on the directory. If, somehow, a
  link to the same file gets created just after file creation, this might
  occur.
  
  This patch ensures that the credentials field is initialized to a reasonable
  set of credentials before the structure is linked into any list, so I
  this should ensure it is initialized before use.
  I am committing the patch now, since bdrewery@ notes that the panics
  are intermittent and it may be months before he knows if the patch fixes
  his problem.

Modified:
  stable/11/sys/fs/nfsclient/nfs_clstate.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/fs/nfsclient/nfs_clstate.c
==============================================================================
--- stable/11/sys/fs/nfsclient/nfs_clstate.c    Fri Jul  7 21:23:37 2017        
(r320793)
+++ stable/11/sys/fs/nfsclient/nfs_clstate.c    Fri Jul  7 21:26:27 2017        
(r320794)
@@ -133,7 +133,7 @@ static int nfscl_localconflict(struct nfsclclient *, u
     struct nfscllock *, u_int8_t *, struct nfscldeleg *, struct nfscllock **);
 static void nfscl_newopen(struct nfsclclient *, struct nfscldeleg *,
     struct nfsclowner **, struct nfsclowner **, struct nfsclopen **,
-    struct nfsclopen **, u_int8_t *, u_int8_t *, int, int *);
+    struct nfsclopen **, u_int8_t *, u_int8_t *, int, struct ucred *, int *);
 static int nfscl_moveopen(vnode_t , struct nfsclclient *,
     struct nfsmount *, struct nfsclopen *, struct nfsclowner *,
     struct nfscldeleg *, struct ucred *, NFSPROC_T *);
@@ -287,7 +287,7 @@ nfscl_open(vnode_t vp, u_int8_t *nfhp, int fhlen, u_in
         * Create a new open, as required.
         */
        nfscl_newopen(clp, dp, &owp, &nowp, &op, &nop, own, nfhp, fhlen,
-           newonep);
+           cred, newonep);
 
        /*
         * Now, check the mode on the open and return the appropriate
@@ -346,7 +346,7 @@ static void
 nfscl_newopen(struct nfsclclient *clp, struct nfscldeleg *dp,
     struct nfsclowner **owpp, struct nfsclowner **nowpp, struct nfsclopen 
**opp,
     struct nfsclopen **nopp, u_int8_t *own, u_int8_t *fhp, int fhlen,
-    int *newonep)
+    struct ucred *cred, int *newonep)
 {
        struct nfsclowner *owp = *owpp, *nowp;
        struct nfsclopen *op, *nop;
@@ -399,6 +399,8 @@ nfscl_newopen(struct nfsclclient *clp, struct nfscldel
                        nop->nfso_stateid.other[0] = 0;
                        nop->nfso_stateid.other[1] = 0;
                        nop->nfso_stateid.other[2] = 0;
+                       KASSERT(cred != NULL, ("%s: cred NULL\n", __func__));
+                       newnfs_copyincred(cred, &nop->nfso_cred);
                        if (dp != NULL) {
                                TAILQ_REMOVE(&clp->nfsc_deleg, dp, nfsdl_list);
                                TAILQ_INSERT_HEAD(&clp->nfsc_deleg, dp,
@@ -3970,7 +3972,7 @@ nfscl_recalldeleg(struct nfsclclient *clp, struct nfsm
                                    M_WAITOK);
                                nfscl_newopen(clp, NULL, &owp, &nowp, &op, 
                                    NULL, lowp->nfsow_owner, dp->nfsdl_fh,
-                                   dp->nfsdl_fhlen, NULL);
+                                   dp->nfsdl_fhlen, NULL, NULL);
                                newnfs_copycred(&dp->nfsdl_cred, cred);
                                ret = nfscl_moveopen(vp, clp, nmp, lop,
                                    owp, dp, cred, p);
@@ -4052,7 +4054,7 @@ nfscl_moveopen(vnode_t vp, struct nfsclclient *clp, st
            lop->nfso_fhlen - 1, M_NFSCLOPEN, M_WAITOK);
        newone = 0;
        nfscl_newopen(clp, NULL, &owp, NULL, &op, &nop, owp->nfsow_owner,
-           lop->nfso_fh, lop->nfso_fhlen, &newone);
+           lop->nfso_fh, lop->nfso_fhlen, cred, &newone);
        ndp = dp;
        error = nfscl_tryopen(nmp, vp, np->n_v4->n4_data, np->n_v4->n4_fhlen,
            lop->nfso_fh, lop->nfso_fhlen, lop->nfso_mode, op,
@@ -4061,8 +4063,6 @@ nfscl_moveopen(vnode_t vp, struct nfsclclient *clp, st
                if (newone)
                        nfscl_freeopen(op, 0);
        } else {
-               if (newone)
-                       newnfs_copyincred(cred, &op->nfso_cred);
                op->nfso_mode |= lop->nfso_mode;
                op->nfso_opencnt += lop->nfso_opencnt;
                nfscl_freeopen(lop, 1);
_______________________________________________
svn-src-all@freebsd.org mailing list
https://lists.freebsd.org/mailman/listinfo/svn-src-all
To unsubscribe, send any mail to "svn-src-all-unsubscr...@freebsd.org"

Reply via email to