aboutsummaryrefslogtreecommitdiff
path: root/sys/kern/kern_fork.c
diff options
context:
space:
mode:
authorMateusz Guzik <mjg@FreeBSD.org>2015-03-21 20:24:03 +0000
committerMateusz Guzik <mjg@FreeBSD.org>2015-03-21 20:24:03 +0000
commit12cec311e607245abbfe1b9afb4a81255e9eb5e0 (patch)
treeb95abf70e8dc5f5e95256989f5f3825b40b3ae59 /sys/kern/kern_fork.c
parent22a3c2dd5d7955463b4e496304317cd2502375c4 (diff)
downloadsrc-12cec311e607245abbfe1b9afb4a81255e9eb5e0.tar.gz
src-12cec311e607245abbfe1b9afb4a81255e9eb5e0.zip
fork: assign refed credentials earlier
Prior to this change the kernel would take p1's credentials and assign them tempororarily to p2. But p1 could change credentials at that time and in effect give us a use-after-free. No objections from: kib
Notes
Notes: svn path=/head/; revision=280330
Diffstat (limited to 'sys/kern/kern_fork.c')
-rw-r--r--sys/kern/kern_fork.c15
1 files changed, 7 insertions, 8 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index ae86fe17a407..15833fd643d0 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -410,9 +410,6 @@ do_fork(struct thread *td, int flags, struct proc *p2, struct thread *td2,
bzero(&p2->p_startzero,
__rangeof(struct proc, p_startzero, p_endzero));
- crhold(td->td_ucred);
- proc_set_cred(p2, td->td_ucred);
-
/* Tell the prison that we exist. */
prison_proc_hold(p2->p_ucred->cr_prison);
@@ -832,7 +829,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
td2 = thread_alloc(pages);
if (td2 == NULL) {
error = ENOMEM;
- goto fail1;
+ goto fail2;
}
proc_linkup(newproc, td2);
} else {
@@ -841,7 +838,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
vm_thread_dispose(td2);
if (!thread_alloc_stack(td2, pages)) {
error = ENOMEM;
- goto fail1;
+ goto fail2;
}
}
}
@@ -850,7 +847,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
vm2 = vmspace_fork(p1->p_vmspace, &mem_charged);
if (vm2 == NULL) {
error = ENOMEM;
- goto fail1;
+ goto fail2;
}
if (!swap_reserve(mem_charged)) {
/*
@@ -861,7 +858,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
*/
swap_reserve_force(mem_charged);
error = ENOMEM;
- goto fail1;
+ goto fail2;
}
} else
vm2 = NULL;
@@ -870,7 +867,7 @@ fork1(struct thread *td, int flags, int pages, struct proc **procp,
* XXX: This is ugly; when we copy resource usage, we need to bump
* per-cred resource counters.
*/
- proc_set_cred(newproc, p1->p_ucred);
+ proc_set_cred(newproc, crhold(td->td_ucred));
/*
* Initialize resource accounting for the child process.
@@ -946,6 +943,8 @@ fail:
#endif
racct_proc_exit(newproc);
fail1:
+ crfree(proc_set_cred(newproc, NULL));
+fail2:
if (vm2 != NULL)
vmspace_free(vm2);
uma_zfree(proc_zone, newproc);