From owner-svn-src-all@freebsd.org Wed Jun 6 01:21:34 2018 Return-Path: Delivered-To: svn-src-all@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 95C31FDB471; Wed, 6 Jun 2018 01:21:34 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client CN "mxrelay.nyi.freebsd.org", Issuer "Let's Encrypt Authority X3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4BAC37D7F3; Wed, 6 Jun 2018 01:21:34 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org (repo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:0]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 2CB02242DA; Wed, 6 Jun 2018 01:21:34 +0000 (UTC) (envelope-from rmacklem@FreeBSD.org) Received: from repo.freebsd.org ([127.0.1.37]) by repo.freebsd.org (8.15.2/8.15.2) with ESMTP id w561LX7V040005; Wed, 6 Jun 2018 01:21:33 GMT (envelope-from rmacklem@FreeBSD.org) Received: (from rmacklem@localhost) by repo.freebsd.org (8.15.2/8.15.2/Submit) id w561LXBX040004; Wed, 6 Jun 2018 01:21:33 GMT (envelope-from rmacklem@FreeBSD.org) Message-Id: <201806060121.w561LXBX040004@repo.freebsd.org> X-Authentication-Warning: repo.freebsd.org: rmacklem set sender to rmacklem@FreeBSD.org using -f From: Rick Macklem Date: Wed, 6 Jun 2018 01:21:33 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-stable@freebsd.org, svn-src-stable-11@freebsd.org Subject: svn commit: r334698 - stable/11/sys/fs/nfsserver X-SVN-Group: stable-11 X-SVN-Commit-Author: rmacklem X-SVN-Commit-Paths: stable/11/sys/fs/nfsserver X-SVN-Commit-Revision: 334698 X-SVN-Commit-Repository: base MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit X-BeenThere: svn-src-all@freebsd.org X-Mailman-Version: 2.1.26 Precedence: list List-Id: "SVN commit messages for the entire src tree \(except for " user" and " projects" \)" List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Wed, 06 Jun 2018 01:21:34 -0000 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); }