On 26/02/18(Mon) 17:52, Martin Pieuchot wrote: > On 20/10/17(Fri) 11:50, Martin Pieuchot wrote: > > On 14/10/17(Sat) 22:07, Philip Guenther wrote: > > > > > > The diff below adds proctreelk, an rwlock protecting the links of the > > > process tree and related bits, as well as uidinfolk, an rwlock protecting > > > the uidinfo hash table. > > > > > > Parts of this are based on FreeBSD's proctree_lock, particularly the > > > reorganization of enterpgrp() into enternewpgrp() and enterthispgrp() and > > > the splitting out of killjobc() from exit1(). > > > > > > This diff should address the previously reported crashes seen when using > > > ktrace(2) while creating/exiting processes. > > > > > > This has been stable for quite a while under my usage; please test and > > > report any issues. > > > > First of all, I'm very happy to see this diff. Thanks Philip. > > > > I have been running this diff on my amd64 NFS client/server build > > machine since you posted it. So far no issue, so it is stable for > > this usage as well. > > > > I'd however appreciate if you could commit the killjobc() and > > enter*grp() refactoring first. Because in case of revert this > > would be less pain. > > I've done that. > > > That's also for this reason that I introduced a macro for the > > NET_LOCK(). So I could enable/disable it without having to revert > > N files. No idea if this could be useful there two. > > > > I like the way you annotate the protected elements in the structure. > > I'll try to do the same for bpf. > > > > I'm also suggesting you commit the `uidinfolk' bits first. This seems > > quite safe. In this exact part, what about introducing a uid_release(), > > a wrapper around rw_exit_write(&uidinfolk), to be called after uid_find()? > > This way you can keep the lock local. > > And that too, here's an updated/rebased diff.
Here's an updated diff where I fixed multiple issues reported by visa@. This is mostly for discussion / backup. Changes include: - Release the `proctreelk' in sys_getsid()'s error path. - Document that process_zap() releases the `proctreelk'. - Do not hold the `proctreelk' around ttywait() in killjobc() - All access to fields marked with [t] in sys/proc.h should now be protected or documented with XXXPT. - As a result setlogin(2) and getlogin_r(2) are now marked NOLOCK. The bigger problem is currently csignal() and pgsignal(). Both can be called from interrupt context. That means that `pg_members' might have to be protected differently. Thoughts? diff --git sys/kern/exec_elf.c sys/kern/exec_elf.c index 0a2fc0a9c8a..e371acf1b33 100644 --- sys/kern/exec_elf.c +++ sys/kern/exec_elf.c @@ -1168,12 +1168,14 @@ coredump_notes_elf(struct proc *p, void *iocookie, size_t *sizep) cpi.cpi_sigcatch = pr->ps_sigacts->ps_sigcatch; cpi.cpi_pid = pr->ps_pid; + rw_enter_read(&proctreelk); cpi.cpi_ppid = pr->ps_pptr->ps_pid; cpi.cpi_pgrp = pr->ps_pgid; if (pr->ps_session->s_leader) cpi.cpi_sid = pr->ps_session->s_leader->ps_pid; else cpi.cpi_sid = 0; + rw_exit_read(&proctreelk); cpi.cpi_ruid = p->p_ucred->cr_ruid; cpi.cpi_euid = p->p_ucred->cr_uid; diff --git sys/kern/kern_acct.c sys/kern/kern_acct.c index 9951a2a2789..78c6fa6a8ac 100644 --- sys/kern/kern_acct.c +++ sys/kern/kern_acct.c @@ -206,11 +206,13 @@ acct_process(struct proc *p) acct.ac_gid = pr->ps_ucred->cr_rgid; /* (7) The terminal from which the process was started */ + rw_enter_read(&proctreelk); if ((pr->ps_flags & PS_CONTROLT) && pr->ps_pgrp->pg_session->s_ttyp) acct.ac_tty = pr->ps_pgrp->pg_session->s_ttyp->t_dev; else acct.ac_tty = NODEV; + rw_exit_read(&proctreelk); /* (8) The boolean flags that tell how the process terminated, etc. */ acct.ac_flag = pr->ps_acflag; diff --git sys/kern/kern_exec.c sys/kern/kern_exec.c index 7aa601f43a3..acb91590e36 100644 --- sys/kern/kern_exec.c +++ sys/kern/kern_exec.c @@ -509,9 +509,11 @@ sys_execve(struct proc *p, void *v, register_t *retval) atomic_setbits_int(&pr->ps_flags, PS_EXEC); if (pr->ps_flags & PS_PPWAIT) { + rw_enter_read(&proctreelk); atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT); atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT); wakeup(pr->ps_pptr); + rw_exit_read(&proctreelk); } /* diff --git sys/kern/kern_exit.c sys/kern/kern_exit.c index dfd4e38078f..6e90b86c641 100644 --- sys/kern/kern_exit.c +++ sys/kern/kern_exit.c @@ -146,6 +146,7 @@ exit1(struct proc *p, int rv, int flags) * is set; we wake up the parent early to avoid deadlock. */ if (pr->ps_flags & PS_PPWAIT) { + /* XXXPT `proctreelk` ? */ atomic_clearbits_int(&pr->ps_flags, PS_PPWAIT); atomic_clearbits_int(&pr->ps_pptr->ps_flags, PS_ISPWAIT); @@ -198,6 +199,7 @@ exit1(struct proc *p, int rv, int flags) * If parent has the SAS_NOCLDWAIT flag set, we're not * going to become a zombie. */ + /* XXXPT `proctreelk` ? */ if (pr->ps_pptr->ps_sigacts->ps_flags & SAS_NOCLDWAIT) atomic_setbits_int(&pr->ps_flags, PS_NOZOMBIE); } @@ -212,11 +214,7 @@ exit1(struct proc *p, int rv, int flags) * thread of a process that isn't PS_NOZOMBIE, we'll put * the process on the zombprocess list below. */ - /* - * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP! - */ - p->p_stat = SDEAD; - + rw_enter_write(&proctreelk); LIST_REMOVE(p, p_hash); LIST_REMOVE(p, p_list); @@ -264,6 +262,7 @@ exit1(struct proc *p, int rv, int flags) } } } + rw_exit_write(&proctreelk); /* add thread's accumulated rusage into the process's total */ ruadd(rup, &p->p_ru); @@ -292,9 +291,13 @@ exit1(struct proc *p, int rv, int flags) * wait4() to return ECHILD. */ if (pr->ps_flags & PS_NOZOMBIE) { - struct process *ppr = pr->ps_pptr; + struct process *ppr; + + rw_enter_write(&proctreelk); + ppr = pr->ps_pptr; proc_reparent(pr, initprocess); wakeup(ppr); + rw_exit_write(&proctreelk); } /* @@ -311,6 +314,11 @@ exit1(struct proc *p, int rv, int flags) KASSERT(pr->ps_refcnt > 0); } + /* + * NOTE: WE ARE NO LONGER ALLOWED TO SLEEP! + */ + p->p_stat = SDEAD; + /* * Other substructures are freed from reaper and wait(). */ @@ -413,6 +421,7 @@ reaper(void) /* Release the rest of the process's vmspace */ uvm_exit(pr); + rw_enter_write(&proctreelk); if ((pr->ps_flags & PS_NOZOMBIE) == 0) { /* Process is now a true zombie. */ atomic_setbits_int(&pr->ps_flags, PS_ZOMBIE); @@ -420,8 +429,14 @@ reaper(void) /* Wake up the parent so it can get exit status. */ wakeup(pr->ps_pptr); + rw_exit_write(&proctreelk); } else { - /* No one will wait for us. Just zap the process now */ + /* + * No one will wait for us. Just zap the + * process now. + * + * Release `proctreelk' for us. + */ process_zap(pr); } } @@ -467,12 +482,12 @@ dowait4(struct proc *q, pid_t pid, int *statusp, int options, struct proc *p; int error; - if (pid == 0) - pid = -q->p_p->ps_pgid; if (options &~ (WUNTRACED|WNOHANG|WCONTINUED)) return (EINVAL); - loop: + rw_enter_write(&proctreelk); + if (pid == 0) + pid = -q->p_p->ps_pgid; nfound = 0; LIST_FOREACH(pr, &q->p_p->ps_children, ps_sibling) { if ((pr->ps_flags & PS_NOZOMBIE) || @@ -491,6 +506,7 @@ loop: *statusp = p->p_xstat; /* convert to int */ if (rusage != NULL) memcpy(rusage, pr->ps_ru, sizeof(*rusage)); + /* Release `proctreelk' for us */ proc_finish_wait(q, p); return (0); } @@ -498,6 +514,7 @@ loop: (pr->ps_flags & PS_WAITED) == 0 && pr->ps_single && pr->ps_single->p_stat == SSTOP && (pr->ps_single->p_flag & P_SUSPSINGLE) == 0) { + rw_exit_write(&proctreelk); single_thread_wait(pr); atomic_setbits_int(&pr->ps_flags, PS_WAITED); @@ -521,6 +538,7 @@ loop: *statusp = W_STOPCODE(p->p_xstat); if (rusage != NULL) memset(rusage, 0, sizeof(*rusage)); + rw_exit_write(&proctreelk); return (0); } if ((options & WCONTINUED) && (p->p_flag & P_CONTINUED)) { @@ -531,16 +549,21 @@ loop: *statusp = _WCONTINUED; if (rusage != NULL) memset(rusage, 0, sizeof(*rusage)); + rw_exit_write(&proctreelk); return (0); } } - if (nfound == 0) + if (nfound == 0) { + rw_exit_write(&proctreelk); return (ECHILD); + } if (options & WNOHANG) { + rw_exit_write(&proctreelk); retval[0] = 0; return (0); } - if ((error = tsleep(q->p_p, PWAIT | PCATCH, "wait", 0)) != 0) + if ((error = rwsleep(q->p_p, &proctreelk, PWAIT | PCATCH | PNORELOCK, + "wait", 0)) != 0) return (error); goto loop; } @@ -551,6 +574,8 @@ proc_finish_wait(struct proc *waiter, struct proc *p) struct process *pr, *tr; struct rusage *rup; + rw_assert_wrlock(&proctreelk); + /* * If we got the child via a ptrace 'attach', * we need to give it back to the old parent. @@ -562,6 +587,7 @@ proc_finish_wait(struct proc *waiter, struct proc *p) proc_reparent(pr, tr); prsignal(tr, SIGCHLD); wakeup(tr); + rw_exit_write(&proctreelk); } else { scheduler_wait_hook(waiter, p); p->p_xstat = 0; @@ -569,6 +595,7 @@ proc_finish_wait(struct proc *waiter, struct proc *p) ruadd(rup, pr->ps_ru); LIST_REMOVE(pr, ps_list); /* off zombprocess */ freepid(pr->ps_pid); + /* Release `proctreelk' for us */ process_zap(pr); } } @@ -580,6 +607,7 @@ void proc_reparent(struct process *child, struct process *parent) { + rw_assert_wrlock(&proctreelk); if (child->ps_pptr == parent) return; @@ -594,12 +622,15 @@ process_zap(struct process *pr) struct vnode *otvp; struct proc *p = pr->ps_mainproc; + rw_assert_wrlock(&proctreelk); + /* * Finally finished with old proc entry. * Unlink it from its process group and free it. */ leavepgrp(pr); LIST_REMOVE(pr, ps_sibling); + rw_exit_write(&proctreelk); /* * Decrement the count of procs running with this uid. diff --git sys/kern/kern_fork.c sys/kern/kern_fork.c index 8d90d91d11b..7bb716f6fa8 100644 --- sys/kern/kern_fork.c +++ sys/kern/kern_fork.c @@ -224,7 +224,6 @@ process_new(struct proc *p, struct process *parent, int flags) (caddr_t)&pr->ps_endcopy - (caddr_t)&pr->ps_startcopy); process_initialize(pr, p); - pr->ps_pid = allocpid(); /* post-copy fixups */ pr->ps_pptr = parent; @@ -237,8 +236,6 @@ process_new(struct proc *p, struct process *parent, int flags) pr->ps_flags = parent->ps_flags & (PS_SUGID | PS_SUGIDEXEC | PS_PLEDGE | PS_EXECPLEDGE | PS_WXNEEDED); - if (parent->ps_session->s_ttyvp != NULL) - pr->ps_flags |= parent->ps_flags & PS_CONTROLT; /* * Duplicate sub-structures as needed. @@ -269,10 +266,11 @@ process_new(struct proc *p, struct process *parent, int flags) /* mark as embryo to protect against others */ pr->ps_flags |= PS_EMBRYO; - /* Force visibility of all of the above changes */ - membar_producer(); - /* it's sufficiently inited to be globally visible */ + rw_enter_write(&proctreelk); + if (parent->ps_session->s_ttyvp != NULL) + pr->ps_flags |= parent->ps_flags & PS_CONTROLT; + pr->ps_pid = allocpid(); LIST_INSERT_HEAD(&allprocess, pr, ps_list); return pr; @@ -373,6 +371,7 @@ fork1(struct proc *curp, int flags, void (*func)(void *), void *arg, /* * From now on, we're committed to the fork and cannot fail. + * process_new() returns with proctreelk held! */ p = thread_new(curp, uaddr); pr = process_new(p, curpr, flags); @@ -447,6 +446,7 @@ fork1(struct proc *curp, int flags, void (*func)(void *), void *arg, pr->ps_ptstat->pe_other_pid = curpr->ps_pid; } } + rw_exit_write(&proctreelk); /* * For new processes, set accounting bits and mark as complete. diff --git sys/kern/kern_ktrace.c sys/kern/kern_ktrace.c index 5bd55d71d5f..59024ac5bf0 100644 --- sys/kern/kern_ktrace.c +++ sys/kern/kern_ktrace.c @@ -448,6 +448,7 @@ doktrace(struct vnode *vp, int ops, int facs, pid_t pid, struct proc *p) /* * do it */ + rw_enter_read(&proctreelk); if (pid < 0) { /* * by process group @@ -455,7 +456,7 @@ doktrace(struct vnode *vp, int ops, int facs, pid_t pid, struct proc *p) pg = pgfind(-pid); if (pg == NULL) { error = ESRCH; - goto done; + goto done2; } LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { if (descend) @@ -471,7 +472,7 @@ doktrace(struct vnode *vp, int ops, int facs, pid_t pid, struct proc *p) pr = prfind(pid); if (pr == NULL) { error = ESRCH; - goto done; + goto done2; } if (descend) ret |= ktrsetchildren(p, pr, ops, facs, vp, cred); @@ -480,6 +481,8 @@ doktrace(struct vnode *vp, int ops, int facs, pid_t pid, struct proc *p) } if (!ret) error = EPERM; +done2: + rw_exit_read(&proctreelk); done: return (error); } @@ -549,6 +552,8 @@ ktrsetchildren(struct proc *curp, struct process *top, int ops, int facs, struct process *pr; int ret = 0; + rw_assert_rdlock(&proctreelk); + pr = top; for (;;) { ret |= ktrops(curp, pr, ops, facs, vp, cred); diff --git sys/kern/kern_proc.c sys/kern/kern_proc.c index 45e84d8462d..112a572a0c7 100644 --- sys/kern/kern_proc.c +++ sys/kern/kern_proc.c @@ -67,6 +67,7 @@ u_long pgrphash; struct processlist allprocess; struct processlist zombprocess; struct proclist allproc; +struct rwlock proctreelk; struct pool proc_pool; struct pool process_pool; @@ -79,9 +80,6 @@ void pgdelete(struct pgrp *); void fixjobc(struct process *, struct pgrp *, int); static void orphanpg(struct pgrp *); -#ifdef DEBUG -void pgrpdump(void); -#endif /* * Initialize global process hashing structures. @@ -93,6 +91,7 @@ procinit(void) LIST_INIT(&zombprocess); LIST_INIT(&allproc); + rw_init(&proctreelk, "proctree"); rw_init(&uidinfolk, "uidinfo"); tidhashtbl = hashinit(maxthread / 4, M_PROC, M_NOWAIT, &tidhash); @@ -180,6 +179,7 @@ int inferior(struct process *pr, struct process *parent) { + rw_assert_wrlock(&proctreelk); for (; pr != parent; pr = pr->ps_pptr) if (pr->ps_pid == 0 || pr->ps_pid == 1) return (0); @@ -222,6 +222,7 @@ pgfind(pid_t pgid) { struct pgrp *pgrp; + rw_assert_anylock(&proctreelk); LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) if (pgrp->pg_id == pgid) return (pgrp); @@ -250,6 +251,8 @@ zombiefind(pid_t pid) void enternewpgrp(struct process *pr, struct pgrp *pgrp, struct session *newsess) { + rw_assert_wrlock(&proctreelk); + #ifdef DIAGNOSTIC if (SESS_LEADER(pr)) panic("%s: session leader attempted setpgrp", __func__); @@ -292,6 +295,8 @@ enterthispgrp(struct process *pr, struct pgrp *pgrp) { struct pgrp *savepgrp = pr->ps_pgrp; + rw_assert_wrlock(&proctreelk); + /* * Adjust eligibility of affected pgrps to participate in job control. * Increment eligibility counts before decrementing, otherwise we @@ -302,6 +307,7 @@ enterthispgrp(struct process *pr, struct pgrp *pgrp) LIST_REMOVE(pr, ps_pglist); pr->ps_pgrp = pgrp; + LIST_INSERT_HEAD(&pgrp->pg_members, pr, ps_pglist); if (LIST_EMPTY(&savepgrp->pg_members)) pgdelete(savepgrp); @@ -314,6 +320,7 @@ void leavepgrp(struct process *pr) { + rw_assert_wrlock(&proctreelk); if (pr->ps_session->s_verauthppid == pr->ps_pid) zapverauth(pr->ps_session); LIST_REMOVE(pr, ps_pglist); @@ -329,6 +336,7 @@ void pgdelete(struct pgrp *pgrp) { + rw_assert_wrlock(&proctreelk); if (pgrp->pg_session->s_ttyp != NULL && pgrp->pg_session->s_ttyp->t_pgrp == pgrp) pgrp->pg_session->s_ttyp->t_pgrp = NULL; @@ -341,6 +349,9 @@ void zapverauth(void *v) { struct session *sess = v; + + rw_assert_wrlock(&proctreelk); + sess->s_verauthuid = 0; sess->s_verauthppid = 0; } @@ -362,6 +373,8 @@ fixjobc(struct process *pr, struct pgrp *pgrp, int entering) struct pgrp *hispgrp; struct session *mysession = pgrp->pg_session; + rw_assert_wrlock(&proctreelk); + /* * Check pr's parent to see whether pr qualifies its own process * group; if so, adjust count for pr's process group. @@ -393,6 +406,7 @@ fixjobc(struct process *pr, struct pgrp *pgrp, int entering) void killjobc(struct process *pr) { + rw_enter_write(&proctreelk); if (SESS_LEADER(pr)) { struct session *sp = pr->ps_session; @@ -408,7 +422,9 @@ killjobc(struct process *pr) if (sp->s_ttyp->t_session == sp) { if (sp->s_ttyp->t_pgrp) pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1); + rw_exit_write(&proctreelk); ttywait(sp->s_ttyp); + rw_enter_write(&proctreelk); /* * The tty could have been revoked * if we blocked. @@ -430,6 +446,7 @@ killjobc(struct process *pr) sp->s_leader = NULL; } fixjobc(pr, pr->ps_pgrp, 0); + rw_exit_write(&proctreelk); } /* @@ -442,6 +459,7 @@ orphanpg(struct pgrp *pg) { struct process *pr; + rw_assert_wrlock(&proctreelk); LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { if (pr->ps_mainproc->p_stat == SSTOP) { LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { @@ -631,29 +649,3 @@ db_show_all_procs(db_expr_t addr, int haddr, db_expr_t count, char *modif) } } #endif - -#ifdef DEBUG -void -pgrpdump(void) -{ - struct pgrp *pgrp; - struct process *pr; - int i; - - for (i = 0; i <= pgrphash; i++) { - if (!LIST_EMPTY(&pgrphashtbl[i])) { - printf("\tindx %d\n", i); - LIST_FOREACH(pgrp, &pgrphashtbl[i], pg_hash) { - printf("\tpgrp %p, pgid %d, sess %p, sesscnt %d, mem %p\n", - pgrp, pgrp->pg_id, pgrp->pg_session, - pgrp->pg_session->s_count, - LIST_FIRST(&pgrp->pg_members)); - LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) { - printf("\t\tpid %d addr %p pgrp %p\n", - pr->ps_pid, pr, pr->ps_pgrp); - } - } - } - } -} -#endif /* DEBUG */ diff --git sys/kern/kern_prot.c sys/kern/kern_prot.c index ec7ac4d4f32..af03e094cb9 100644 --- sys/kern/kern_prot.c +++ sys/kern/kern_prot.c @@ -83,7 +83,9 @@ int sys_getppid(struct proc *p, void *v, register_t *retval) { + rw_enter_read(&proctreelk); *retval = p->p_p->ps_pptr->ps_pid; + rw_exit_read(&proctreelk); return (0); } @@ -92,7 +94,9 @@ int sys_getpgrp(struct proc *p, void *v, register_t *retval) { + rw_enter_read(&proctreelk); *retval = p->p_p->ps_pgrp->pg_id; + rw_exit_read(&proctreelk); return (0); } @@ -106,16 +110,23 @@ sys_getpgid(struct proc *curp, void *v, register_t *retval) syscallarg(pid_t) pid; } */ *uap = v; struct process *targpr = curp->p_p; + int error = 0; - if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid) - goto found; + if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid) { + rw_enter_read(&proctreelk); + *retval = targpr->ps_pgid; + rw_exit_read(&proctreelk); + return 0; + } + rw_enter_read(&proctreelk); if ((targpr = prfind(SCARG(uap, pid))) == NULL) - return (ESRCH); - if (targpr->ps_session != curp->p_p->ps_session) - return (EPERM); -found: - *retval = targpr->ps_pgid; - return (0); + error = ESRCH; + else if (targpr->ps_session != curp->p_p->ps_session) + error = EPERM; + else + *retval = targpr->ps_pgid; + rw_exit_read(&proctreelk); + return error; } int @@ -125,19 +136,28 @@ sys_getsid(struct proc *curp, void *v, register_t *retval) syscallarg(pid_t) pid; } */ *uap = v; struct process *targpr = curp->p_p; + int error = 0; + + rw_enter_read(&proctreelk); + if (SCARG(uap, pid) != 0 && SCARG(uap, pid) != targpr->ps_pid) { + if ((targpr = prfind(SCARG(uap, pid))) == NULL) { + error = ESRCH; + goto out; + } + if (targpr->ps_session != curp->p_p->ps_session) { + error = EPERM; + goto out; + } + } - if (SCARG(uap, pid) == 0 || SCARG(uap, pid) == targpr->ps_pid) - goto found; - if ((targpr = prfind(SCARG(uap, pid))) == NULL) - return (ESRCH); - if (targpr->ps_session != curp->p_p->ps_session) - return (EPERM); -found: /* Skip exiting processes */ if (targpr->ps_pgrp->pg_session->s_leader == NULL) - return (ESRCH); - *retval = targpr->ps_pgrp->pg_session->s_leader->ps_pid; - return (0); + error = ESRCH; + else + *retval = targpr->ps_pgrp->pg_session->s_leader->ps_pid; +out: + rw_exit_read(&proctreelk); + return error; } int @@ -224,12 +244,15 @@ sys_setsid(struct proc *p, void *v, register_t *retval) newsess = pool_get(&session_pool, PR_WAITOK); newpgrp = pool_get(&pgrp_pool, PR_WAITOK); + rw_enter_write(&proctreelk); if (pr->ps_pgid == pid || pgfind(pid) != NULL) { + rw_exit_write(&proctreelk); pool_put(&pgrp_pool, newpgrp); pool_put(&session_pool, newsess); return (EPERM); } else { enternewpgrp(pr, newpgrp, newsess); + rw_exit_write(&proctreelk); *retval = pid; return (0); } @@ -269,6 +292,7 @@ sys_setpgid(struct proc *curp, void *v, register_t *retval) newpgrp = pool_get(&pgrp_pool, PR_WAITOK); + rw_enter_write(&proctreelk); if (pid != 0 && pid != curpr->ps_pid) { if ((targpr = prfind(pid)) == 0 || !inferior(targpr, curpr)) { error = ESRCH; @@ -307,7 +331,8 @@ sys_setpgid(struct proc *curp, void *v, register_t *retval) else enterthispgrp(targpr, pgrp); } - out: +out: + rw_exit_write(&proctreelk); if (newpgrp != NULL) pool_put(&pgrp_pool, newpgrp); return (error); @@ -947,6 +972,12 @@ crget(void) return (cr); } +void +crhold(struct ucred *cr) +{ + atomic_inc_int(&cr->cr_ref); +} + /* * Free a cred structure. * Throws away space when ref count gets to 0. @@ -954,8 +985,7 @@ crget(void) void crfree(struct ucred *cr) { - - if (--cr->cr_ref == 0) + if (atomic_dec_int_nv(&cr->cr_ref) == 0) pool_put(&ucred_pool, cr); } @@ -1018,12 +1048,17 @@ sys_getlogin_r(struct proc *p, void *v, register_t *retval) syscallarg(size_t) namelen; } */ *uap = v; size_t namelen = SCARG(uap, namelen); - struct session *s = p->p_p->ps_pgrp->pg_session; + struct session *s; + char buf[sizeof(s->s_login)]; int error; + rw_enter_read(&proctreelk); + s = p->p_p->ps_pgrp->pg_session; if (namelen > sizeof(s->s_login)) namelen = sizeof(s->s_login); - error = copyoutstr(s->s_login, SCARG(uap, namebuf), namelen, NULL); + namelen = strlcpy(buf, s->s_login, namelen) + 1; + rw_exit_read(&proctreelk); + error = copyoutstr(buf, SCARG(uap, namebuf), namelen, NULL); if (error == ENAMETOOLONG) error = ERANGE; *retval = error; @@ -1039,15 +1074,19 @@ sys_setlogin(struct proc *p, void *v, register_t *retval) struct sys_setlogin_args /* { syscallarg(const char *) namebuf; } */ *uap = v; - struct session *s = p->p_p->ps_pgrp->pg_session; + struct session *s; char buf[sizeof(s->s_login)]; int error; if ((error = suser(p)) != 0) return (error); error = copyinstr(SCARG(uap, namebuf), buf, sizeof(buf), NULL); - if (error == 0) + if (error == 0) { + rw_enter_write(&proctreelk); + s = p->p_p->ps_pgrp->pg_session; strlcpy(s->s_login, buf, sizeof(s->s_login)); + rw_exit_write(&proctreelk); + } else if (error == ENAMETOOLONG) error = EINVAL; return (error); diff --git sys/kern/kern_resource.c sys/kern/kern_resource.c index 184c538d2ef..04c010ef3c9 100644 --- sys/kern/kern_resource.c +++ sys/kern/kern_resource.c @@ -90,13 +90,17 @@ sys_getpriority(struct proc *curp, void *v, register_t *retval) case PRIO_PGRP: { struct pgrp *pg; + rw_enter_read(&proctreelk); if (SCARG(uap, who) == 0) pg = curp->p_p->ps_pgrp; - else if ((pg = pgfind(SCARG(uap, who))) == NULL) + else if ((pg = pgfind(SCARG(uap, who))) == NULL) { + rw_exit_read(&proctreelk); break; + } LIST_FOREACH(pr, &pg->pg_members, ps_pglist) if (pr->ps_nice < low) low = pr->ps_nice; + rw_exit_read(&proctreelk); break; } @@ -145,14 +149,18 @@ sys_setpriority(struct proc *curp, void *v, register_t *retval) case PRIO_PGRP: { struct pgrp *pg; + rw_enter_read(&proctreelk); if (SCARG(uap, who) == 0) pg = curp->p_p->ps_pgrp; - else if ((pg = pgfind(SCARG(uap, who))) == NULL) + else if ((pg = pgfind(SCARG(uap, who))) == NULL) { + rw_exit_read(&proctreelk); break; + } LIST_FOREACH(pr, &pg->pg_members, ps_pglist) { error = donice(curp, pr, SCARG(uap, prio)); found++; } + rw_exit_read(&proctreelk); break; } diff --git sys/kern/kern_sig.c sys/kern/kern_sig.c index 5e8153a90a6..91f0e6220f2 100644 --- sys/kern/kern_sig.c +++ sys/kern/kern_sig.c @@ -107,6 +107,7 @@ cansignal(struct proc *p, struct process *qr, int signum) if (uc == quc) return (1); + rw_assert_rdlock(&proctreelk); if (signum == SIGCONT && qr->ps_session == pr->ps_session) return (1); /* SIGCONT in session */ @@ -568,7 +569,7 @@ sys_kill(struct proc *cp, void *v, register_t *retval) struct process *pr; int pid = SCARG(uap, pid); int signum = SCARG(uap, signum); - int error; + int error, cansig; int zombie = 0; if ((error = pledge_kill(cp, pid)) != 0) @@ -582,7 +583,10 @@ sys_kill(struct proc *cp, void *v, register_t *retval) else zombie = 1; } - if (!cansignal(cp, pr, signum)) + rw_enter_read(&proctreelk); + cansig = cansignal(cp, pr, signum); + rw_exit_read(&proctreelk); + if (!cansig) return (EPERM); /* kill single process */ @@ -652,6 +656,7 @@ killpg1(struct proc *cp, int signum, int pgid, int all) /* * broadcast */ + rw_enter_read(&proctreelk); LIST_FOREACH(pr, &allprocess, ps_list) { if (pr->ps_pid <= 1 || pr->ps_flags & (PS_SYSTEM | PS_NOBROADCASTKILL) || @@ -661,7 +666,9 @@ killpg1(struct proc *cp, int signum, int pgid, int all) if (signum) prsignal(pr, signum); } + rw_exit_read(&proctreelk); } else { + rw_enter_read(&proctreelk); if (pgid == 0) /* * zero pgid means send to my process group. @@ -669,8 +676,10 @@ killpg1(struct proc *cp, int signum, int pgid, int all) pgrp = cp->p_p->ps_pgrp; else { pgrp = pgfind(pgid); - if (pgrp == NULL) + if (pgrp == NULL) { + rw_exit_read(&proctreelk); return (ESRCH); + } } LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) { if (pr->ps_pid <= 1 || pr->ps_flags & PS_SYSTEM || @@ -680,6 +689,7 @@ killpg1(struct proc *cp, int signum, int pgid, int all) if (signum) prsignal(pr, signum); } + rw_exit_read(&proctreelk); } return (nfound ? 0 : ESRCH); } @@ -703,6 +713,12 @@ csignal(pid_t pgid, int signum, uid_t uid, uid_t euid) struct pgrp *pgrp; struct process *pr; + /* + * XXXPT `pg_members' needs to be protected but this can be called + * from interrupt context. + */ + //rw_assert_wrlock(&proctreelk) + if (pgid == 0) return; if (pgid < 0) { @@ -741,6 +757,12 @@ pgsignal(struct pgrp *pgrp, int signum, int checkctty) { struct process *pr; + /* + * XXXPT `pg_members' needs to be protected but this can be called + * from interrupt context. + */ + //rw_assert_wrlock(&proctreelk) + if (pgrp) LIST_FOREACH(pr, &pgrp->pg_members, ps_pglist) if (checkctty == 0 || pr->ps_flags & PS_CONTROLT) @@ -1329,6 +1351,7 @@ proc_stop_sweep(void *v) { struct process *pr; + rw_enter_read(&proctreelk); LIST_FOREACH(pr, &allprocess, ps_list) { if ((pr->ps_flags & PS_STOPPED) == 0) continue; @@ -1338,6 +1361,7 @@ proc_stop_sweep(void *v) prsignal(pr->ps_pptr, SIGCHLD); wakeup(pr->ps_pptr); } + rw_exit_read(&proctreelk); } /* diff --git sys/kern/kern_sysctl.c sys/kern/kern_sysctl.c index c98f9d53d72..144260428ef 100644 --- sys/kern/kern_sysctl.c +++ sys/kern/kern_sysctl.c @@ -1469,6 +1469,7 @@ sysctl_doproc(int *name, u_int namelen, char *where, size_t *sizep) if (where != NULL) kproc = malloc(sizeof(*kproc), M_TEMP, M_WAITOK); + rw_enter_read(&proctreelk); pr = LIST_FIRST(&allprocess); doingzomb = 0; again: @@ -1507,6 +1508,7 @@ again: break; case KERN_PROC_TTY: + /* XXXPT proctreelk? */ if ((pr->ps_flags & PS_CONTROLT) == 0 || pr->ps_session->s_ttyp == NULL || pr->ps_session->s_ttyp->t_dev != (dev_t)arg) @@ -1570,6 +1572,7 @@ again: doingzomb++; goto again; } + rw_exit_read(&proctreelk); if (where != NULL) { *sizep = dp - where; if (needed > *sizep) { @@ -1599,6 +1602,8 @@ fill_kproc(struct process *pr, struct kinfo_proc *ki, struct proc *p, struct timespec ut, st; int isthread; + rw_assert_rdlock(&proctreelk); + isthread = p != NULL; if (!isthread) p = pr->ps_mainproc; /* XXX */ diff --git sys/kern/subr_prf.c sys/kern/subr_prf.c index 3572e809d09..6cb6d62481e 100644 --- sys/kern/subr_prf.c +++ sys/kern/subr_prf.c @@ -362,6 +362,7 @@ uprintf(const char *fmt, ...) struct process *pr = curproc->p_p; va_list ap; + /* XXXPT proctreelk? */ if (pr->ps_flags & PS_CONTROLT && pr->ps_session->s_ttyvp) { va_start(ap, fmt); kprintf(fmt, TOTTY, pr->ps_session->s_ttyp, NULL, ap); diff --git sys/kern/sys_process.c sys/kern/sys_process.c index 08bfb73bf5f..14bedae5d5b 100644 --- sys/kern/sys_process.c +++ sys/kern/sys_process.c @@ -276,13 +276,19 @@ ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data) struct proc *t; /* target thread */ struct process *tr; /* target process */ int error = 0; + int proctree_locked; int s; + /* Lock proctree before looking up the process. */ + rw_enter_write(&proctreelk); + proctree_locked = 1; + switch (req) { case PT_TRACE_ME: /* Just set the trace flag. */ tr = p->p_p; atomic_setbits_int(&tr->ps_flags, PS_TRACED); + rw_exit_write(&proctreelk); tr->ps_oppid = tr->ps_pptr->ps_pid; if (tr->ps_ptstat == NULL) tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat), @@ -447,6 +453,8 @@ ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data) if (error) goto fail; #endif + proctree_locked = 0; + rw_exit_write(&proctreelk); goto sendsig; case PT_DETACH: @@ -486,7 +494,11 @@ ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data) tr->ps_oppid = 0; atomic_clearbits_int(&tr->ps_flags, PS_TRACED|PS_WAITED); + proctree_locked = 0; + rw_exit_write(&proctreelk); sendsig: + KASSERT(proctree_locked == 0); + memset(tr->ps_ptstat, 0, sizeof(*tr->ps_ptstat)); /* Finally, deliver the requested signal (or none). */ @@ -507,6 +519,8 @@ ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data) /* just send the process a KILL signal. */ data = SIGKILL; + proctree_locked = 0; + rw_exit_write(&proctreelk); goto sendsig; /* in PT_CONTINUE, above. */ case PT_ATTACH: @@ -523,6 +537,8 @@ ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data) tr->ps_oppid = tr->ps_pptr->ps_pid; if (tr->ps_pptr != p->p_p) proc_reparent(tr, p->p_p); + proctree_locked = 0; + rw_exit_write(&proctreelk); if (tr->ps_ptstat == NULL) tr->ps_ptstat = malloc(sizeof(*tr->ps_ptstat), M_SUBPROC, M_WAITOK); @@ -534,6 +550,8 @@ ptrace_ctrl(struct proc *p, int req, pid_t pid, caddr_t addr, int data) } fail: + if (proctree_locked) + rw_exit_write(&proctreelk); return error; } diff --git sys/kern/syscalls.master sys/kern/syscalls.master index c9411db3ba1..46f8988c84e 100644 --- sys/kern/syscalls.master +++ sys/kern/syscalls.master @@ -107,7 +107,7 @@ 36 STD { void sys_sync(void); } 37 OBSOL o58_kill 38 STD { int sys_stat(const char *path, struct stat *ub); } -39 STD { pid_t sys_getppid(void); } +39 STD NOLOCK { pid_t sys_getppid(void); } 40 STD { int sys_lstat(const char *path, struct stat *ub); } 41 STD { int sys_dup(int fd); } 42 STD { int sys_fstatat(int fd, const char *path, \ @@ -127,7 +127,7 @@ 47 STD NOLOCK { gid_t sys_getgid(void); } 48 STD NOLOCK { int sys_sigprocmask(int how, sigset_t mask); } 49 OBSOL ogetlogin -50 STD { int sys_setlogin(const char *namebuf); } +50 STD NOLOCK { int sys_setlogin(const char *namebuf); } #ifdef ACCOUNTING 51 STD { int sys_acct(const char *path); } #else @@ -185,7 +185,7 @@ gid_t *gidset); } 80 STD { int sys_setgroups(int gidsetsize, \ const gid_t *gidset); } -81 STD { int sys_getpgrp(void); } +81 STD NOLOCK { int sys_getpgrp(void); } 82 STD { int sys_setpgid(pid_t pid, pid_t pgid); } 83 STD NOLOCK { int sys_futex(uint32_t *f, int op, int val, \ const struct timespec *timeout, uint32_t *g); } @@ -273,7 +273,7 @@ 139 OBSOL 4.2 sigreturn 140 STD { int sys_adjtime(const struct timeval *delta, \ struct timeval *olddelta); } -141 STD { int sys_getlogin_r(char *namebuf, u_int namelen); } +141 STD NOLOCK { int sys_getlogin_r(char *namebuf, u_int namelen); } 142 OBSOL ogethostid 143 OBSOL osethostid 144 OBSOL ogetrlimit diff --git sys/kern/tty.c sys/kern/tty.c index b9fec5b6bb9..95f8f8fb1f0 100644 --- sys/kern/tty.c +++ sys/kern/tty.c @@ -836,7 +836,9 @@ ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) case TIOCGSID: /* get sid of tty */ if (!isctty(pr, tp)) return (ENOTTY); + rw_enter_read(&proctreelk); *(int *)data = tp->t_session->s_leader->ps_pid; + rw_exit_read(&proctreelk); break; #ifdef TIOCHPCL case TIOCHPCL: /* hang up on last close */ @@ -892,10 +894,12 @@ ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) tp->t_cflag = t->c_cflag; tp->t_ispeed = t->c_ispeed; tp->t_ospeed = t->c_ospeed; + rw_enter_read(&proctreelk); if (t->c_ospeed == 0 && tp->t_session && tp->t_session->s_leader) prsignal(tp->t_session->s_leader, SIGHUP); + rw_exit_read(&proctreelk); } ttsetwater(tp); } @@ -973,10 +977,13 @@ ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) break; case TIOCSCTTY: /* become controlling tty */ /* Session ctty vnode pointer set in vnode layer. */ + rw_enter_write(&proctreelk); if (!SESS_LEADER(pr) || ((pr->ps_session->s_ttyvp || tp->t_session) && - (tp->t_session != pr->ps_session))) + (tp->t_session != pr->ps_session))) { + rw_exit_write(&proctreelk); return (EPERM); + } if (tp->t_session) SESSRELE(tp->t_session); SESSHOLD(pr->ps_session); @@ -984,17 +991,25 @@ ttioctl(struct tty *tp, u_long cmd, caddr_t data, int flag, struct proc *p) tp->t_pgrp = pr->ps_pgrp; pr->ps_session->s_ttyp = tp; atomic_setbits_int(&pr->ps_flags, PS_CONTROLT); + rw_exit_write(&proctreelk); break; case TIOCSPGRP: { /* set pgrp of tty */ - struct pgrp *pgrp = pgfind(*(int *)data); + struct pgrp *pgrp; + rw_enter_write(&proctreelk); + pgrp = pgfind(*(int *)data); if (!isctty(pr, tp)) - return (ENOTTY); + error = ENOTTY; else if (pgrp == NULL) - return (EINVAL); + error = EINVAL; else if (pgrp->pg_session != pr->ps_session) - return (EPERM); - tp->t_pgrp = pgrp; + error = EPERM; + else { + tp->t_pgrp = pgrp; + error = 0; + } + rw_exit_write(&proctreelk); + return (error); break; } case TIOCSTAT: /* get load avg stats */ @@ -1385,6 +1400,11 @@ ttymodem(struct tty *tp, int flag) CLR(tp->t_state, TS_CARR_ON); if (ISSET(tp->t_state, TS_ISOPEN) && !ISSET(tp->t_cflag, CLOCAL)) { + /* + * XXXPT `s_leader' needs to be protected but this + * can be called from interrupt context. + */ + //rw_assert_wrlock(&proctreelk) if (tp->t_session && tp->t_session->s_leader) prsignal(tp->t_session->s_leader, SIGHUP); ttyflush(tp, FREAD | FWRITE); @@ -1414,6 +1434,11 @@ nullmodem(struct tty *tp, int flag) CLR(tp->t_state, TS_CARR_ON); if (ISSET(tp->t_state, TS_ISOPEN) && !ISSET(tp->t_cflag, CLOCAL)) { + /* + * XXXPT `s_leader' needs to be protected but this + * can be called from interrupt context. + */ + //rw_assert_wrlock(&proctreelk) if (tp->t_session && tp->t_session->s_leader) prsignal(tp->t_session->s_leader, SIGHUP); ttyflush(tp, FREAD | FWRITE); @@ -2138,6 +2163,12 @@ ttyinfo(struct tty *tp) if (ttycheckoutq(tp,0) == 0) return; + /* + * XXXPT `pg_members' needs to be protected but this can be called + * from interrupt context. + */ + //rw_assert_wrlock(&proctreelk) + /* Print load average. */ tmp = (averunnable.ldavg[0] * 100 + FSCALE / 2) >> FSHIFT; ttyprintf(tp, "load: %d.%02d ", tmp / 100, tmp % 100); diff --git sys/kern/tty_tty.c sys/kern/tty_tty.c index 0f88b8d9b27..5a94d996497 100644 --- sys/kern/tty_tty.c +++ sys/kern/tty_tty.c @@ -45,6 +45,9 @@ #include <sys/fcntl.h> +/* + * XXXPT Must hold `proctreelk' to dereference `ps_session'. + */ #define cttyvp(p) \ ((p)->p_p->ps_flags & PS_CONTROLT ? \ (p)->p_p->ps_session->s_ttyvp : NULL) @@ -105,11 +108,14 @@ cttyioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) if (cmd == TIOCSCTTY) /* XXX */ return (EINVAL); if (cmd == TIOCNOTTY) { + rw_enter_read(&proctreelk); if (!SESS_LEADER(p->p_p)) { atomic_clearbits_int(&p->p_p->ps_flags, PS_CONTROLT); - return (0); + error = 0; } else - return (EINVAL); + error = EINVAL; + rw_exit_read(&proctreelk); + return error; } switch (cmd) { case TIOCSETVERAUTH: @@ -118,15 +124,19 @@ cttyioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) secs = *(int *)addr; if (secs < 1 || secs > 3600) return EINVAL; + rw_enter_write(&proctreelk); sess = p->p_p->ps_pgrp->pg_session; sess->s_verauthuid = p->p_ucred->cr_ruid; sess->s_verauthppid = p->p_p->ps_pptr->ps_pid; timeout_add_sec(&sess->s_verauthto, secs); + rw_exit_write(&proctreelk); return 0; case TIOCCLRVERAUTH: + rw_enter_write(&proctreelk); sess = p->p_p->ps_pgrp->pg_session; timeout_del(&sess->s_verauthto); zapverauth(sess); + rw_exit_write(&proctreelk); return 0; case TIOCCHKVERAUTH: /* @@ -136,11 +146,15 @@ cttyioctl(dev_t dev, u_long cmd, caddr_t addr, int flag, struct proc *p) * Nevertheless, the checks reflect the original intention; * namely, that it be the same user using the same shell. */ + rw_enter_read(&proctreelk); sess = p->p_p->ps_pgrp->pg_session; if (sess->s_verauthuid == p->p_ucred->cr_ruid && sess->s_verauthppid == p->p_p->ps_pptr->ps_pid) - return 0; - return EPERM; + error = 0; + else + error = EPERM; + rw_exit_read(&proctreelk); + return error; } return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, p)); } diff --git sys/sys/proc.h sys/sys/proc.h index edcaf7cb960..2205f111cea 100644 --- sys/sys/proc.h +++ sys/sys/proc.h @@ -44,6 +44,7 @@ #include <sys/selinfo.h> /* For struct selinfo */ #include <sys/syslimits.h> /* For LOGIN_NAME_MAX */ #include <sys/queue.h> +#include <sys/rwlock.h> /* For struct rwlock */ #include <sys/timeout.h> /* For struct timeout */ #include <sys/event.h> /* For struct klist */ #include <sys/mutex.h> /* For struct mutex */ @@ -54,17 +55,26 @@ #define __need_process #endif +/* + * Locks used to protect struct members in this file: + * I immutable after creation + * t proctreelk + * + * If multiple locks are listed then all are required for writes, + * but any one of them is sufficient for reads. + */ + /* * One structure allocated per session. */ struct process; struct session { int s_count; /* Ref cnt; pgrps in session. */ - struct process *s_leader; /* Session leader. */ + struct process *s_leader; /* [t] Session leader. */ struct vnode *s_ttyvp; /* Vnode of controlling terminal. */ - struct tty *s_ttyp; /* Controlling terminal. */ - char s_login[LOGIN_NAME_MAX]; /* Setlogin() name. */ - pid_t s_verauthppid; + struct tty *s_ttyp; /* [t] Controlling terminal. */ + char s_login[LOGIN_NAME_MAX];/* [t] setlogin() name. */ + pid_t s_verauthppid; /* TIOCSETVERAUTH info */ uid_t s_verauthuid; struct timeout s_verauthto; }; @@ -75,10 +85,10 @@ void zapverauth(/* struct session */ void *); * One structure allocated per process group. */ struct pgrp { - LIST_ENTRY(pgrp) pg_hash; /* Hash chain. */ - LIST_HEAD(, process) pg_members;/* Pointer to pgrp members. */ - struct session *pg_session; /* Pointer to session. */ - pid_t pg_id; /* Pgrp id. */ + LIST_ENTRY(pgrp) pg_hash; /* [t] Hash chain. */ + LIST_HEAD(, process) pg_members;/* [t] Pointer to pgrp members. */ + struct session *pg_session; /* [I] Pointer to session. */ + pid_t pg_id; /* [I] Pgrp id. */ int pg_jobc; /* # procs qualifying pgrp for job control */ }; @@ -156,17 +166,17 @@ struct process { LIST_ENTRY(process) ps_list; /* List of all processes. */ TAILQ_HEAD(,proc) ps_threads; /* Threads in this process. */ - LIST_ENTRY(process) ps_pglist; /* List of processes in pgrp. */ - struct process *ps_pptr; /* Pointer to parent process. */ - LIST_ENTRY(process) ps_sibling; /* List of sibling processes. */ - LIST_HEAD(, process) ps_children;/* Pointer to list of children. */ + LIST_ENTRY(process) ps_pglist; /* [t] List of processes in pgrp. */ + struct process *ps_pptr; /* [t] Pointer to parent process. */ + LIST_ENTRY(process) ps_sibling; /* [t] List of sibling processes. */ + LIST_HEAD(, process) ps_children;/* [t] Pointer to list of children. */ LIST_ENTRY(process) ps_hash; /* Hash chain. */ struct sigacts *ps_sigacts; /* Signal actions, state */ struct vnode *ps_textvp; /* Vnode of executable. */ struct filedesc *ps_fd; /* Ptr to open files structure */ struct vmspace *ps_vmspace; /* Address space */ - pid_t ps_pid; /* Process identifier. */ + pid_t ps_pid; /* [I] Process identifier. */ /* The following fields are all zeroed upon creation in process_new. */ #define ps_startzero ps_klist @@ -180,7 +190,7 @@ struct process { struct vnode *ps_tracevp; /* Trace to vnode. */ struct ucred *ps_tracecred; /* Creds for writing trace */ - pid_t ps_oppid; /* Save parent pid during ptrace. */ + pid_t ps_oppid; /* [t] Save parent pid during ptrace. */ int ps_ptmask; /* Ptrace event mask */ struct ptrace_state *ps_ptstat;/* Ptrace state */ @@ -197,7 +207,7 @@ struct process { /* The following fields are all copied upon creation in process_new. */ #define ps_startcopy ps_limit struct plimit *ps_limit; /* Process limits. */ - struct pgrp *ps_pgrp; /* Pointer to process group. */ + struct pgrp *ps_pgrp; /* [t] Pointer to process group. */ struct emul *ps_emul; /* Emulation information */ char ps_comm[MAXCOMLEN+1]; @@ -475,6 +485,7 @@ LIST_HEAD(processlist, process); extern struct processlist allprocess; /* List of all processes. */ extern struct processlist zombprocess; /* List of zombie processes. */ extern struct proclist allproc; /* List of all threads. */ +extern struct rwlock proctreelk; /* parent/child, pgrp, session */ extern struct process *initprocess; /* Process slot for init. */ extern struct proc *reaperproc; /* Thread slot for reaper. */ diff --git sys/sys/ucred.h sys/sys/ucred.h index 03e023dc04a..9a6cb0095f4 100644 --- sys/sys/ucred.h +++ sys/sys/ucred.h @@ -68,12 +68,11 @@ struct xucred { }; #ifdef _KERNEL -#define crhold(cr) (cr)->cr_ref++ - int crfromxucred(struct ucred *, const struct xucred *); void crset(struct ucred *, const struct ucred *); struct ucred *crcopy(struct ucred *cr); struct ucred *crdup(struct ucred *cr); +void crhold(struct ucred *cr); void crfree(struct ucred *cr); struct ucred *crget(void); int suser(struct proc *p);