summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exec.c
diff options
context:
space:
mode:
authorguenther <guenther@openbsd.org>2012-02-15 04:26:27 +0000
committerguenther <guenther@openbsd.org>2012-02-15 04:26:27 +0000
commit638f0017823ed0e106d01f08deef215e05f1e560 (patch)
treecba8201347fdd0e19f16ceee4f173da6d23b9754 /sys/kern/kern_exec.c
parent82571/82572 do not properly set byte enables 2 and 3 on MSI (diff)
downloadwireguard-openbsd-638f0017823ed0e106d01f08deef215e05f1e560.tar.xz
wireguard-openbsd-638f0017823ed0e106d01f08deef215e05f1e560.zip
Hold struct filedesc's fd_lock when writing to the fd_ofiles, fd_ofileflags,
or fd_{lo,hi}maps members, or when doing a read for a write. Fixes hangs when an rthreaded processes sleeps while copying the fd table for fork() and catches another thread with the lock. ok jsing@ tedu@
Diffstat (limited to 'sys/kern/kern_exec.c')
-rw-r--r--sys/kern/kern_exec.c15
1 files changed, 11 insertions, 4 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index c72d2fcdead..1b1ac0d84d2 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.122 2011/12/14 07:32:16 guenther Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.123 2012/02/15 04:26:27 guenther Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -529,6 +529,8 @@ sys_execve(struct proc *p, void *v, register_t *retval)
* For set[ug]id processes, a few caveats apply to
* stdin, stdout, and stderr.
*/
+ error = 0;
+ fdplock(p->p_fd);
for (i = 0; i < 3; i++) {
struct file *fp = NULL;
@@ -562,7 +564,7 @@ sys_execve(struct proc *p, void *v, register_t *retval)
int indx;
if ((error = falloc(p, &fp, &indx)) != 0)
- goto exec_abort;
+ break;
#ifdef DIAGNOSTIC
if (indx != i)
panic("sys_execve: falloc indx != i");
@@ -570,13 +572,13 @@ sys_execve(struct proc *p, void *v, register_t *retval)
if ((error = cdevvp(getnulldev(), &vp)) != 0) {
fdremove(p->p_fd, indx);
closef(fp, p);
- goto exec_abort;
+ break;
}
if ((error = VOP_OPEN(vp, flags, p->p_ucred, p)) != 0) {
fdremove(p->p_fd, indx);
closef(fp, p);
vrele(vp);
- goto exec_abort;
+ break;
}
if (flags & FWRITE)
vp->v_writecount++;
@@ -587,6 +589,9 @@ sys_execve(struct proc *p, void *v, register_t *retval)
FILE_SET_MATURE(fp);
}
}
+ fdpunlock(p->p_fd);
+ if (error)
+ goto exec_abort;
} else
atomic_clearbits_int(&pr->ps_flags, PS_SUGID);
p->p_cred->p_svuid = p->p_ucred->cr_uid;
@@ -695,7 +700,9 @@ bad:
/* kill any opened file descriptor, if necessary */
if (pack.ep_flags & EXEC_HASFD) {
pack.ep_flags &= ~EXEC_HASFD;
+ fdplock(p->p_fd);
(void) fdrelease(p, pack.ep_fd);
+ fdpunlock(p->p_fd);
}
if (pack.ep_interp != NULL)
pool_put(&namei_pool, pack.ep_interp);