aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--sys/kern/kern_fork.c48
1 files changed, 23 insertions, 25 deletions
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index c7edf76ac6de..32d008d0a144 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -246,17 +246,24 @@ static int
fork_findpid(int flags)
{
pid_t result;
- int trypid;
+ int trypid, random;
+
+ /*
+ * Avoid calling arc4random with procid_lock held.
+ */
+ random = 0;
+ if (__predict_false(randompid))
+ random = arc4random() % randompid;
+
+ mtx_lock(&procid_lock);
trypid = lastpid + 1;
if (flags & RFHIGHPID) {
if (trypid < 10)
trypid = 10;
} else {
- if (randompid)
- trypid += arc4random() % randompid;
+ trypid += random;
}
- mtx_lock(&procid_lock);
retry:
if (trypid >= pid_max)
trypid = 2;
@@ -341,33 +348,16 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
struct vmspace *vm2, struct file *fp_procdesc)
{
struct proc *p1, *pptr;
- int trypid;
struct filedesc *fd;
struct filedesc_to_leader *fdtol;
struct sigacts *newsigacts;
- sx_assert(&allproc_lock, SX_XLOCKED);
-
p1 = td->td_proc;
- trypid = fork_findpid(fr->fr_flags);
- p2->p_state = PRS_NEW; /* protect against others */
- p2->p_pid = trypid;
- AUDIT_ARG_PID(p2->p_pid);
- LIST_INSERT_HEAD(&allproc, p2, p_list);
- allproc_gen++;
- sx_xlock(PIDHASHLOCK(p2->p_pid));
- LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
- sx_xunlock(PIDHASHLOCK(p2->p_pid));
- PROC_LOCK(p2);
PROC_LOCK(p1);
-
- sx_xunlock(&allproc_lock);
-
bcopy(&p1->p_startcopy, &p2->p_startcopy,
__rangeof(struct proc, p_startcopy, p_endcopy));
pargs_hold(p2->p_args);
-
PROC_UNLOCK(p1);
bzero(&p2->p_startzero,
@@ -376,7 +366,18 @@ do_fork(struct thread *td, struct fork_req *fr, struct proc *p2, struct thread *
/* Tell the prison that we exist. */
prison_proc_hold(p2->p_ucred->cr_prison);
- PROC_UNLOCK(p2);
+ p2->p_state = PRS_NEW; /* protect against others */
+ p2->p_pid = fork_findpid(fr->fr_flags);
+ AUDIT_ARG_PID(p2->p_pid);
+
+ sx_xlock(&allproc_lock);
+ LIST_INSERT_HEAD(&allproc, p2, p_list);
+ allproc_gen++;
+ sx_xunlock(&allproc_lock);
+
+ sx_xlock(PIDHASHLOCK(p2->p_pid));
+ LIST_INSERT_HEAD(PIDHASH(p2->p_pid), p2, p_hash);
+ sx_xunlock(PIDHASHLOCK(p2->p_pid));
tidhash_add(td2);
@@ -969,8 +970,6 @@ fork1(struct thread *td, struct fork_req *fr)
newproc->p_klist = knlist_alloc(&newproc->p_mtx);
STAILQ_INIT(&newproc->p_ktr);
- sx_xlock(&allproc_lock);
-
/*
* Increment the count of procs running with this uid. Don't allow
* a nonprivileged user to exceed their current limit.
@@ -986,7 +985,6 @@ fork1(struct thread *td, struct fork_req *fr)
return (0);
fail0:
error = EAGAIN;
- sx_xunlock(&allproc_lock);
#ifdef MAC
mac_proc_destroy(newproc);
#endif