svn commit: r186277 - head/sys/kern
Konstantin Belousov
kib at FreeBSD.org
Thu Dec 18 12:01:19 UTC 2008
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);
}
More information about the svn-src-all
mailing list