diff options
author | pjd <pjd@FreeBSD.org> | 2005-06-12 07:03:23 +0000 |
---|---|---|
committer | pjd <pjd@FreeBSD.org> | 2005-06-12 07:03:23 +0000 |
commit | d2fe610c90770fc475b5be2d6ca70974207754e9 (patch) | |
tree | bc73e5222c4446ea10124d21f9a11454010699c4 /sys/kern | |
parent | 2a4fb1caf123f1a11d6912437c7d7ee3473f44f3 (diff) | |
download | FreeBSD-src-d2fe610c90770fc475b5be2d6ca70974207754e9.zip FreeBSD-src-d2fe610c90770fc475b5be2d6ca70974207754e9.tar.gz |
Do not allocate memory while holding a mutex.
I introduce a very small race here (some file system can be mounted or
unmounted between 'count' calculation and file systems list creation),
but it is harmless.
Found by: FreeBSD Kernel Stress Test Suite: http://www.holm.cc/stress/
Reported by: Peter Holm <peter@holm.cc>
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/vfs_extattr.c | 6 | ||||
-rw-r--r-- | sys/kern/vfs_syscalls.c | 6 |
2 files changed, 8 insertions, 4 deletions
diff --git a/sys/kern/vfs_extattr.c b/sys/kern/vfs_extattr.c index 242473f..b3bb0b2 100644 --- a/sys/kern/vfs_extattr.c +++ b/sys/kern/vfs_extattr.c @@ -409,23 +409,25 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, int error; maxcount = bufsize / sizeof(struct statfs); - mtx_lock(&Giant); - mtx_lock(&mountlist_mtx); if (bufsize == 0) sfsp = NULL; else if (bufseg == UIO_USERSPACE) sfsp = *buf; else /* if (bufseg == UIO_SYSSPACE) */ { count = 0; + mtx_lock(&mountlist_mtx); TAILQ_FOREACH(mp, &mountlist, mnt_list) { count++; } + mtx_unlock(&mountlist_mtx); if (maxcount > count) maxcount = count; sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP, M_WAITOK); } count = 0; + mtx_lock(&Giant); + mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { if (prison_canseemount(td->td_ucred, mp) != 0) { nmp = TAILQ_NEXT(mp, mnt_list); diff --git a/sys/kern/vfs_syscalls.c b/sys/kern/vfs_syscalls.c index 242473f..b3bb0b2 100644 --- a/sys/kern/vfs_syscalls.c +++ b/sys/kern/vfs_syscalls.c @@ -409,23 +409,25 @@ kern_getfsstat(struct thread *td, struct statfs **buf, size_t bufsize, int error; maxcount = bufsize / sizeof(struct statfs); - mtx_lock(&Giant); - mtx_lock(&mountlist_mtx); if (bufsize == 0) sfsp = NULL; else if (bufseg == UIO_USERSPACE) sfsp = *buf; else /* if (bufseg == UIO_SYSSPACE) */ { count = 0; + mtx_lock(&mountlist_mtx); TAILQ_FOREACH(mp, &mountlist, mnt_list) { count++; } + mtx_unlock(&mountlist_mtx); if (maxcount > count) maxcount = count; sfsp = *buf = malloc(maxcount * sizeof(struct statfs), M_TEMP, M_WAITOK); } count = 0; + mtx_lock(&Giant); + mtx_lock(&mountlist_mtx); for (mp = TAILQ_FIRST(&mountlist); mp != NULL; mp = nmp) { if (prison_canseemount(td->td_ucred, mp) != 0) { nmp = TAILQ_NEXT(mp, mnt_list); |