diff options
| -rw-r--r-- | sys/kern/kern_fork.c | 48 |
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 |
