summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_exec.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_exec.c')
-rw-r--r--sys/kern/kern_exec.c15
1 files changed, 14 insertions, 1 deletions
diff --git a/sys/kern/kern_exec.c b/sys/kern/kern_exec.c
index 1c5380c40f9..ff53d3feb9a 100644
--- a/sys/kern/kern_exec.c
+++ b/sys/kern/kern_exec.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exec.c,v 1.120 2011/10/16 05:29:51 guenther Exp $ */
+/* $OpenBSD: kern_exec.c,v 1.121 2011/12/11 19:42:28 guenther Exp $ */
/* $NetBSD: kern_exec.c,v 1.75 1996/02/09 18:59:28 christos Exp $ */
/*-
@@ -267,6 +267,10 @@ sys_execve(struct proc *p, void *v, register_t *retval)
#endif
char *pathbuf = NULL;
+ /* get other threads to stop */
+ if ((error = single_thread_set(p, SINGLE_UNWIND, 1)))
+ goto bad;
+
/*
* Cheap solution to complicated problems.
* Mark this process as "leave me alone, I'm execing".
@@ -410,6 +414,13 @@ sys_execve(struct proc *p, void *v, register_t *retval)
pack.ep_ssize = len; /* maybe should go elsewhere, but... */
/*
+ * we're committed: any further errors will kill the process, so
+ * kill the other threads now.
+ * XXX wait until threads are reaped to make uvmspace_exec() cheaper?
+ */
+ single_thread_set(p, SINGLE_EXIT, 0);
+
+ /*
* Prepare vmspace for remapping. Note that uvmspace_exec can replace
* p_vmspace!
*/
@@ -667,6 +678,7 @@ sys_execve(struct proc *p, void *v, register_t *retval)
#endif
atomic_clearbits_int(&p->p_flag, P_INEXEC);
+ single_thread_clear(p);
#if NSYSTRACE > 0
if (ISSET(p->p_flag, P_SYSTRACE) &&
@@ -702,6 +714,7 @@ bad:
clrflag:
#endif
atomic_clearbits_int(&p->p_flag, P_INEXEC);
+ single_thread_clear(p);
if (pathbuf != NULL)
pool_put(&namei_pool, pathbuf);