From owner-svn-src-head@FreeBSD.ORG Thu Dec 18 12:01:19 2008 Return-Path: Delivered-To: svn-src-head@freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:4f8:fff6::34]) by hub.freebsd.org (Postfix) with ESMTP id B28161065674; Thu, 18 Dec 2008 12:01:19 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (svn.freebsd.org [IPv6:2001:4f8:fff6::2c]) by mx1.freebsd.org (Postfix) with ESMTP id A1C298FC31; Thu, 18 Dec 2008 12:01:19 +0000 (UTC) (envelope-from kib@FreeBSD.org) Received: from svn.freebsd.org (localhost [127.0.0.1]) by svn.freebsd.org (8.14.3/8.14.3) with ESMTP id mBIC1JDA039810; Thu, 18 Dec 2008 12:01:19 GMT (envelope-from kib@svn.freebsd.org) Received: (from kib@localhost) by svn.freebsd.org (8.14.3/8.14.3/Submit) id mBIC1JFo039809; Thu, 18 Dec 2008 12:01:19 GMT (envelope-from kib@svn.freebsd.org) Message-Id: <200812181201.mBIC1JFo039809@svn.freebsd.org> From: Konstantin Belousov Date: Thu, 18 Dec 2008 12:01:19 +0000 (UTC) To: src-committers@freebsd.org, svn-src-all@freebsd.org, svn-src-head@freebsd.org X-SVN-Group: head MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Cc: Subject: svn commit: r186277 - head/sys/kern X-BeenThere: svn-src-head@freebsd.org X-Mailman-Version: 2.1.5 Precedence: list List-Id: SVN commit messages for the src tree for head/-current List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 18 Dec 2008 12:01:19 -0000 Author: kib Date: Thu Dec 18 12:01:19 2008 New Revision: 186277 URL: http://svn.freebsd.org/changeset/base/186277 Log: The quotactl, statfs and fstatfs syscall implementations may dereference NULL pointer to struct mount if the looked up vnode is reclaimed. Also, these syscalls only mnt_ref() the mp, still allowing it to be unmounted; only struct mount memory is kept from being reused. Lock the vnode when doing name lookup, then reference its mount point, unlock the vnode and vfs_busy the mountpoint. This sequence shall take care of both races. Reported and tested by: pho Discussed with: attilio MFC after: 1 month Modified: head/sys/kern/vfs_syscalls.c Modified: head/sys/kern/vfs_syscalls.c ============================================================================== --- head/sys/kern/vfs_syscalls.c Thu Dec 18 11:58:12 2008 (r186276) +++ head/sys/kern/vfs_syscalls.c Thu Dec 18 12:01:19 2008 (r186277) @@ -200,19 +200,21 @@ quotactl(td, uap) AUDIT_ARG(uid, uap->uid); if (jailed(td->td_ucred) && !prison_quotas) return (EPERM); - NDINIT(&nd, LOOKUP, FOLLOW | MPSAFE | AUDITVNODE1, + NDINIT(&nd, LOOKUP, FOLLOW | LOCKLEAF | MPSAFE | AUDITVNODE1, UIO_USERSPACE, uap->path, td); if ((error = namei(&nd)) != 0) return (error); vfslocked = NDHASGIANT(&nd); NDFREE(&nd, NDF_ONLY_PNBUF); mp = nd.ni_vp->v_mount; - if ((error = vfs_busy(mp, 0))) { - vrele(nd.ni_vp); + vfs_ref(mp); + vput(nd.ni_vp); + error = vfs_busy(mp, 0); + vfs_rel(mp); + if (error) { VFS_UNLOCK_GIANT(vfslocked); return (error); } - vrele(nd.ni_vp); error = VFS_QUOTACTL(mp, uap->cmd, uap->uid, uap->arg, td); vfs_unbusy(mp); VFS_UNLOCK_GIANT(vfslocked); @@ -306,6 +308,12 @@ kern_statfs(struct thread *td, char *pat vfs_ref(mp); NDFREE(&nd, NDF_ONLY_PNBUF); vput(nd.ni_vp); + error = vfs_busy(mp, 0); + vfs_rel(mp); + if (error) { + VFS_UNLOCK_GIANT(vfslocked); + return (error); + } #ifdef MAC error = mac_mount_check_stat(td->td_ucred, mp); if (error) @@ -329,7 +337,7 @@ kern_statfs(struct thread *td, char *pat } *buf = *sp; out: - vfs_rel(mp); + vfs_unbusy(mp); VFS_UNLOCK_GIANT(vfslocked); if (mtx_owned(&Giant)) printf("statfs(%d): %s: %d\n", vfslocked, path, error); @@ -391,6 +399,10 @@ kern_fstatfs(struct thread *td, int fd, error = EBADF; goto out; } + error = vfs_busy(mp, 0); + vfs_rel(mp); + if (error) + goto out; #ifdef MAC error = mac_mount_check_stat(td->td_ucred, mp); if (error) @@ -415,7 +427,7 @@ kern_fstatfs(struct thread *td, int fd, *buf = *sp; out: if (mp) - vfs_rel(mp); + vfs_unbusy(mp); VFS_UNLOCK_GIANT(vfslocked); return (error); }