summaryrefslogtreecommitdiff
path: root/sys/kern
diff options
context:
space:
mode:
authorPhilip Guenthe <guenther@cvs.openbsd.org>2008-10-14 18:27:30 +0000
committerPhilip Guenthe <guenther@cvs.openbsd.org>2008-10-14 18:27:30 +0000
commit842c943d0b9533fb5f723d2e8d941739ee0898a8 (patch)
tree4d960b53281ef12ca29875d02b3074b0e8c3d260 /sys/kern
parent92fa2f6c129706b56b14aa9120b49ced73d4a6ab (diff)
Back-in; problems were apparently elsewhere.
Put a reference count in struct process to prevent use-after-free if the main thread reaches the reaper ahead of some other thread in the process. Use the reference count to update the user process count correctly when changin real uid. "please re-commit before something else nasty comes in" deraadt@
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/init_main.c3
-rw-r--r--sys/kern/kern_exit.c4
-rw-r--r--sys/kern/kern_fork.c4
-rw-r--r--sys/kern/kern_prot.c10
4 files changed, 12 insertions, 9 deletions
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index c9b542c33bf..2dfe7ccba78 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: init_main.c,v 1.152 2008/10/10 14:35:06 deraadt Exp $ */
+/* $OpenBSD: init_main.c,v 1.153 2008/10/14 18:27:29 guenther Exp $ */
/* $NetBSD: init_main.c,v 1.84.4.1 1996/06/02 09:08:06 mrg Exp $ */
/*
@@ -256,6 +256,7 @@ main(void *framep)
process0.ps_mainproc = p;
TAILQ_INIT(&process0.ps_threads);
TAILQ_INSERT_TAIL(&process0.ps_threads, p, p_thr_link);
+ process0.ps_refcnt = 1;
p->p_p = &process0;
LIST_INSERT_HEAD(&allproc, p, p_list);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index 2c81bc73348..ee45596f495 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_exit.c,v 1.75 2008/10/10 14:35:06 deraadt Exp $ */
+/* $OpenBSD: kern_exit.c,v 1.76 2008/10/14 18:27:29 guenther Exp $ */
/* $NetBSD: kern_exit.c,v 1.39 1996/04/22 01:38:25 christos Exp $ */
/*
@@ -590,7 +590,7 @@ proc_zap(struct proc *p)
* Remove us from our process list, possibly killing the process
* in the process (pun intended).
*/
- if ((p->p_flag & P_THREAD) == 0) {
+ if (--p->p_p->ps_refcnt == 0) {
KASSERT(TAILQ_EMPTY(&p->p_p->ps_threads));
limfree(p->p_p->ps_limit);
if (--p->p_p->ps_cred->p_refcnt == 0) {
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 83ad6805002..4d435e85aa2 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_fork.c,v 1.97 2008/10/10 14:35:06 deraadt Exp $ */
+/* $OpenBSD: kern_fork.c,v 1.98 2008/10/14 18:27:29 guenther Exp $ */
/* $NetBSD: kern_fork.c,v 1.29 1996/02/09 18:59:34 christos Exp $ */
/*
@@ -161,6 +161,7 @@ process_new(struct proc *newproc, struct proc *parent)
pr->ps_mainproc = newproc;
TAILQ_INIT(&pr->ps_threads);
TAILQ_INSERT_TAIL(&pr->ps_threads, newproc, p_thr_link);
+ pr->ps_refcnt = 1;
newproc->p_p = pr;
}
@@ -231,6 +232,7 @@ fork1(struct proc *p1, int exitsig, int flags, void *stack, size_t stacksize,
atomic_setbits_int(&p2->p_flag, P_THREAD);
p2->p_p = p1->p_p;
TAILQ_INSERT_TAIL(&p2->p_p->ps_threads, p2, p_thr_link);
+ p2->p_p->ps_refcnt++;
} else {
process_new(p2, p1);
}
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 039b0cbad36..13c94cd0adb 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_prot.c,v 1.33 2008/10/10 14:35:06 deraadt Exp $ */
+/* $OpenBSD: kern_prot.c,v 1.34 2008/10/14 18:27:29 guenther Exp $ */
/* $NetBSD: kern_prot.c,v 1.33 1996/02/09 18:59:42 christos Exp $ */
/*
@@ -377,8 +377,8 @@ sys_setresuid(struct proc *p, void *v, register_t *retval)
/*
* Transfer proc count to new user.
*/
- (void)chgproccnt(pc->p_ruid, -1);
- (void)chgproccnt(ruid, 1);
+ (void)chgproccnt(pc->p_ruid, -p->p_p->ps_refcnt);
+ (void)chgproccnt(ruid, p->p_p->ps_refcnt);
pc->p_ruid = ruid;
}
if (euid != (uid_t)-1 && euid != pc->pc_ucred->cr_uid) {
@@ -582,8 +582,8 @@ sys_setuid(struct proc *p, void *v, register_t *retval)
* Transfer proc count to new user.
*/
if (uid != pc->p_ruid) {
- (void)chgproccnt(pc->p_ruid, -1);
- (void)chgproccnt(uid, 1);
+ (void)chgproccnt(pc->p_ruid, -p->p_p->ps_refcnt);
+ (void)chgproccnt(uid, p->p_p->ps_refcnt);
}
pc->p_ruid = uid;
pc->p_svuid = uid;