diff options
author | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-12-30 00:58:20 +0000 |
---|---|---|
committer | Philip Guenthe <guenther@cvs.openbsd.org> | 2012-12-30 00:58:20 +0000 |
commit | 13ee0efb097fa7f5ee5bf28530211a67920cb7d4 (patch) | |
tree | 6ebcf8c234e9082caa24b1195d57848409a98565 /sys/kern | |
parent | 098521495befe79fd8dd64e98244db01d50289e3 (diff) |
In sysctl_proc_cwd(), vref() the target proc's fd_cdir before calling
malloc(), so that it can't exit and be freed if we sleep.
(another sparc.p nightmare test case)
ok beck@, phessler@
Diffstat (limited to 'sys/kern')
-rw-r--r-- | sys/kern/kern_sysctl.c | 10 |
1 files changed, 8 insertions, 2 deletions
diff --git a/sys/kern/kern_sysctl.c b/sys/kern/kern_sysctl.c index 49f2dfcc8e5..1ff334cc116 100644 --- a/sys/kern/kern_sysctl.c +++ b/sys/kern/kern_sysctl.c @@ -1,4 +1,4 @@ -/* $OpenBSD: kern_sysctl.c,v 1.228 2012/11/05 19:39:35 miod Exp $ */ +/* $OpenBSD: kern_sysctl.c,v 1.229 2012/12/30 00:58:19 guenther Exp $ */ /* $NetBSD: kern_sysctl.c,v 1.17 1996/05/20 17:49:05 mrg Exp $ */ /*- @@ -1762,6 +1762,7 @@ sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp, struct proc *cp) { struct proc *findp; + struct vnode *vp; pid_t pid; int error; size_t lenused, len; @@ -1800,6 +1801,10 @@ sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp, return (ERANGE); *oldlenp = 0; + /* snag a reference to the vnode before we can sleep */ + vp = findp->p_fd->fd_cdir; + vref(vp); + path = malloc(len, M_TEMP, M_WAITOK); bp = &path[len]; @@ -1807,13 +1812,14 @@ sysctl_proc_cwd(int *name, u_int namelen, void *oldp, size_t *oldlenp, *(--bp) = '\0'; /* Same as sys__getcwd */ - error = vfs_getcwd_common(findp->p_fd->fd_cdir, NULL, + error = vfs_getcwd_common(vp, NULL, &bp, path, len / 2, GETCWD_CHECK_ACCESS, cp); if (error == 0) { *oldlenp = lenused = bend - bp; error = copyout(bp, oldp, lenused); } + vrele(vp); free(path, M_TEMP); return (error); |