Author: rmacklem
Date: Wed Jun  6 01:21:33 2018
New Revision: 334698
URL: https://svnweb.freebsd.org/changeset/base/334698

Log:
  MFC: r334396
  Strengthen locking for the NFSv4.1 server DestroySession operation.
  
  If a client did a DestroySession on a session while it was still in use,
  the server might try to use the session structure after it is free'd.
  I think the client has violated RFC5661 if it does this, but this patch
  makes DestroySession block all other nfsd threads so no thread could
  be using the session when it is free'd. After the DestroySession, nfsd
  threads will not be able to find the session. The patch also adds a check
  for nd_sessionid being set, although if that was not the case it would have
  been all 0s and unlikely to have a false match.
  This might fix the crashes described in PR#228497 for the FreeNAS server.
  
  PR:           228497

Modified:
  stable/11/sys/fs/nfsserver/nfs_nfsdstate.c
Directory Properties:
  stable/11/   (props changed)

Modified: stable/11/sys/fs/nfsserver/nfs_nfsdstate.c
==============================================================================
--- stable/11/sys/fs/nfsserver/nfs_nfsdstate.c  Wed Jun  6 00:59:43 2018        
(r334697)
+++ stable/11/sys/fs/nfsserver/nfs_nfsdstate.c  Wed Jun  6 01:21:33 2018        
(r334698)
@@ -5946,17 +5946,32 @@ nfsrv_findsession(uint8_t *sessionid)
 int
 nfsrv_destroysession(struct nfsrv_descript *nd, uint8_t *sessionid)
 {
-       int error, samesess;
+       int error, igotlock, samesess;
 
        samesess = 0;
-       if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID)) {
+       if (!NFSBCMP(sessionid, nd->nd_sessionid, NFSX_V4SESSIONID) &&
+           (nd->nd_flag & ND_HASSEQUENCE) != 0) {
                samesess = 1;
                if ((nd->nd_flag & ND_LASTOP) == 0)
                        return (NFSERR_BADSESSION);
        }
+
+       /* Lock out other nfsd threads */
+       NFSLOCKV4ROOTMUTEX();
+       nfsv4_relref(&nfsv4rootfs_lock);
+       do {
+               igotlock = nfsv4_lock(&nfsv4rootfs_lock, 1, NULL,
+                   NFSV4ROOTLOCKMUTEXPTR, NULL);
+       } while (igotlock == 0);
+       NFSUNLOCKV4ROOTMUTEX();
+
        error = nfsrv_freesession(NULL, sessionid);
        if (error == 0 && samesess != 0)
                nd->nd_flag &= ~ND_HASSEQUENCE;
+
+       NFSLOCKV4ROOTMUTEX();
+       nfsv4_unlock(&nfsv4rootfs_lock, 1);
+       NFSUNLOCKV4ROOTMUTEX();
        return (error);
 }
 
_______________________________________________
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