--- //depot/vendor/freebsd/src/sys/fs/procfs/procfs_ctl.c 2005/10/14 12:45:32 +++ //depot/projects/smpng/sys/fs/procfs/procfs_ctl.c 2006/02/17 16:14:19 @@ -245,9 +245,8 @@ * What does it mean to single step a threaded program? */ case PROCFS_CTL_STEP: + error = proc_sstep(FIRST_THREAD_IN_PROC(p)); /* XXXKSE */ PROC_UNLOCK(p); - error = proc_sstep(FIRST_THREAD_IN_PROC(p)); /* XXXKSE */ - PRELE(p); if (error) return (error); break; --- //depot/vendor/freebsd/src/sys/fs/pseudofs/pseudofs_vnops.c 2005/08/12 12:25:25 +++ //depot/projects/smpng/sys/fs/pseudofs/pseudofs_vnops.c 2006/02/17 18:55:16 @@ -81,13 +81,14 @@ #endif /* - * Returns non-zero if given file is visible to given process + * Returns non-zero if given file is visible to given process. If the 'p' + * parameter is non-NULL, then it will hold a pointer to the process the + * given file belongs to on return and the process will be locked. */ static int -pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid) +pfs_visible(struct thread *td, struct pfs_node *pn, pid_t pid, struct proc **p) { struct proc *proc; - int r; PFS_TRACE(("%s (pid: %d, req: %d)", pn->pn_name, pid, td->td_proc->p_pid)); @@ -95,16 +96,27 @@ if (pn->pn_flags & PFS_DISABLED) PFS_RETURN (0); - r = 1; if (pid != NO_PID) { if ((proc = pfind(pid)) == NULL) PFS_RETURN (0); + if (proc->p_flag & P_WEXIT) { + PROC_UNLOCK(proc); + PFS_RETURN (0); + } if (p_cansee(td, proc) != 0 || - (pn->pn_vis != NULL && !(pn->pn_vis)(td, proc, pn))) - r = 0; - PROC_UNLOCK(proc); - } - PFS_RETURN (r); + (pn->pn_vis != NULL && !(pn->pn_vis)(td, proc, pn))) { + PROC_UNLOCK(proc); + PFS_RETURN (0); + } + if (p) { + /* We return with the process locked to avoid races. */ + *p = proc; + } else + PROC_UNLOCK(proc); + } else + if (p) + *p = NULL; + PFS_RETURN (1); } /* @@ -176,8 +188,8 @@ PFS_TRACE((pn->pn_name)); - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) - PFS_RETURN (ENOENT); + if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) + PFS_RETURN (ENOENT); VATTR_NULL(vap); vap->va_type = vn->v_type; @@ -206,9 +218,7 @@ break; } - if (pvd->pvd_pid != NO_PID) { - if ((proc = pfind(pvd->pvd_pid)) == NULL) - PFS_RETURN (ENOENT); + if (proc != NULL) { vap->va_uid = proc->p_ucred->cr_ruid; vap->va_gid = proc->p_ucred->cr_rgid; if (pn->pn_attr != NULL) @@ -231,7 +241,7 @@ struct vnode *vn = va->a_vp; struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; struct pfs_node *pn = pvd->pvd_pn; - struct proc *proc = NULL; + struct proc *proc; int error; PFS_TRACE(("%s: %lx", pn->pn_name, va->a_command)); @@ -246,13 +256,10 @@ * This is necessary because process' privileges may * have changed since the open() call. */ - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) + if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) PFS_RETURN (EIO); - /* XXX duplicates bits of pfs_visible() */ - if (pvd->pvd_pid != NO_PID) { - if ((proc = pfind(pvd->pvd_pid)) == NULL) - PFS_RETURN (EIO); + if (proc != NULL) { _PHOLD(proc); PROC_UNLOCK(proc); } @@ -274,28 +281,25 @@ struct vnode *vn = va->a_vp; struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; struct pfs_node *pn = pvd->pvd_pn; - struct proc *proc = NULL; + struct proc *proc; int error; PFS_TRACE((pn->pn_name)); - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) - PFS_RETURN (ENOENT); - - if (pn->pn_getextattr == NULL) - PFS_RETURN (EOPNOTSUPP); - /* * This is necessary because either process' privileges may * have changed since the open() call. */ - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) + if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) PFS_RETURN (EIO); - /* XXX duplicates bits of pfs_visible() */ - if (pvd->pvd_pid != NO_PID) { - if ((proc = pfind(pvd->pvd_pid)) == NULL) - PFS_RETURN (EIO); + if (pn->pn_getextattr == NULL) { + if (proc != NULL) + PROC_UNLOCK(proc); + PFS_RETURN (EOPNOTSUPP); + } + + if (proc != NULL) { _PHOLD(proc); PROC_UNLOCK(proc); } @@ -347,8 +351,8 @@ if (cnp->cn_namelen >= PFS_NAMELEN) PFS_RETURN (ENOENT); - /* check that parent directory is visisble... */ - if (!pfs_visible(curthread, pd, pvd->pvd_pid)) + /* check that parent directory is visible... */ + if (!pfs_visible(curthread, pd, pvd->pvd_pid, NULL)) PFS_RETURN (ENOENT); /* self */ @@ -404,7 +408,7 @@ got_pnode: if (pn != pd->pn_parent && !pn->pn_parent) pn->pn_parent = pd; - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) { + if (!pfs_visible(curthread, pn, pvd->pvd_pid, NULL)) { error = ENOENT; goto failed; } @@ -447,7 +451,7 @@ * XXX and the only consequence of that race is an EIO further * XXX down the line. */ - if (!pfs_visible(va->a_td, pn, pvd->pvd_pid)) + if (!pfs_visible(va->a_td, pn, pvd->pvd_pid, NULL)) PFS_RETURN (ENOENT); /* check if the requested mode is permitted */ @@ -472,7 +476,7 @@ struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; struct pfs_node *pn = pvd->pvd_pn; struct uio *uio = va->a_uio; - struct proc *proc = NULL; + struct proc *proc; struct sbuf *sb = NULL; int error; unsigned int buflen, offset, resid; @@ -492,13 +496,10 @@ * This is necessary because either process' privileges may * have changed since the open() call. */ - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) + if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) PFS_RETURN (EIO); - /* XXX duplicates bits of pfs_visible() */ - if (pvd->pvd_pid != NO_PID) { - if ((proc = pfind(pvd->pvd_pid)) == NULL) - PFS_RETURN (EIO); + if (proc != NULL) { _PHOLD(proc); PROC_UNLOCK(proc); } @@ -554,7 +555,7 @@ pfs_iterate(struct thread *td, pid_t pid, struct pfs_node *pd, struct pfs_node **pn, struct proc **p) { - sx_assert(&allproc_lock, SX_LOCKED); + sx_assert(&allproc_lock, SX_SLOCKED); again: if (*pn == NULL) { /* first node */ @@ -577,7 +578,7 @@ if ((*pn) == NULL) return (-1); - if (!pfs_visible(td, *pn, *p ? (*p)->p_pid : pid)) + if (!pfs_visible(td, *pn, *p ? (*p)->p_pid : pid, NULL)) goto again; return (0); @@ -609,7 +610,7 @@ uio = va->a_uio; /* check if the directory is visible to the caller */ - if (!pfs_visible(curthread, pd, pid)) + if (!pfs_visible(curthread, pd, pid, NULL)) PFS_RETURN (ENOENT); /* only allow reading entire entries */ @@ -709,6 +710,10 @@ if (pvd->pvd_pid != NO_PID) { if ((proc = pfind(pvd->pvd_pid)) == NULL) PFS_RETURN (EIO); + if (proc->p_flag & P_WEXIT) { + PROC_UNLOCK(proc); + PFS_RETURN (EIO); + } _PHOLD(proc); PROC_UNLOCK(proc); } @@ -764,7 +769,7 @@ struct pfs_vdata *pvd = (struct pfs_vdata *)vn->v_data; struct pfs_node *pn = pvd->pvd_pn; struct uio *uio = va->a_uio; - struct proc *proc = NULL; + struct proc *proc; struct sbuf sb; int error; @@ -783,13 +788,10 @@ * This is necessary because either process' privileges may * have changed since the open() call. */ - if (!pfs_visible(curthread, pn, pvd->pvd_pid)) + if (!pfs_visible(curthread, pn, pvd->pvd_pid, &proc)) PFS_RETURN (EIO); - /* XXX duplicates bits of pfs_visible() */ - if (pvd->pvd_pid != NO_PID) { - if ((proc = pfind(pvd->pvd_pid)) == NULL) - PFS_RETURN (EIO); + if (proc != NULL) { _PHOLD(proc); PROC_UNLOCK(proc); } --- //depot/vendor/freebsd/src/sys/i386/linux/linux_ptrace.c 2005/07/02 20:12:12 +++ //depot/projects/smpng/sys/i386/linux/linux_ptrace.c 2006/02/08 16:54:49 @@ -356,6 +356,12 @@ break; } + /* Exiting processes can't be debugged. */ + if ((p->p_flag & P_WEXIT) != 0) { + error = ESRCH; + goto fail; + } + if ((error = p_candebug(td, p)) != 0) goto fail; --- //depot/vendor/freebsd/src/sys/kern/kern_exit.c 2006/01/23 19:15:32 +++ //depot/projects/smpng/sys/kern/kern_exit.c 2006/02/17 16:49:17 @@ -173,8 +173,30 @@ */ } + /* + * Wakeup anyone in procfs' PIOCWAIT. They should have a hold + * on our vmspace, so we should block below until they have + * released their reference to us. Note that if they have + * requested S_EXIT stops we will block here until they ack + * via PIOCCONT. + */ + _STOPEVENT(p, S_EXIT, rv); + + /* + * Note that we are exiting and do another wakeup of anyone in + * PIOCWAIT in case they aren't listening for S_EXIT stops or + * decided to wait again after we told them we are exiting. + */ p->p_flag |= P_WEXIT; + wakeup(&p->p_stype); + /* + * Wait for any processes that have a hold on our vmspace to + * release their reference. + */ + while (p->p_lock > 0) + msleep(&p->p_lock, &p->p_mtx, PWAIT, "exithold", 0); + PROC_LOCK(p->p_pptr); sigqueue_take(p->p_ksi); PROC_UNLOCK(p->p_pptr); @@ -196,11 +218,6 @@ mtx_unlock(&ppeers_lock); } - PROC_LOCK(p); - _STOPEVENT(p, S_EXIT, rv); - wakeup(&p->p_stype); /* Wakeup anyone in procfs' PIOCWAIT */ - PROC_UNLOCK(p); - /* * Check if any loadable modules need anything done at process exit. * E.g. SYSV IPC stuff --- //depot/vendor/freebsd/src/sys/kern/kern_kthread.c 2005/01/06 23:37:37 +++ //depot/projects/smpng/sys/kern/kern_kthread.c 2006/02/03 23:09:54 @@ -98,7 +98,6 @@ mtx_lock(&p2->p_sigacts->ps_mtx); p2->p_sigacts->ps_flag |= PS_NOCLDWAIT; mtx_unlock(&p2->p_sigacts->ps_mtx); - _PHOLD(p2); PROC_UNLOCK(p2); /* set up arg0 for 'ps', et al */ --- //depot/vendor/freebsd/src/sys/kern/sys_process.c 2005/12/24 03:00:35 +++ //depot/projects/smpng/sys/kern/sys_process.c 2006/02/17 18:27:53 @@ -551,6 +546,11 @@ pid = p->p_pid; } } + + if ((p->p_flag & P_WEXIT) != 0) { + error = ESRCH; + goto fail; + } if ((error = p_cansee(td, p)) != 0) goto fail; @@ -844,6 +836,7 @@ /* FALLTHROUGH */ case PT_READ_I: case PT_READ_D: + _PHOLD(p); PROC_UNLOCK(p); tmp = 0; /* write = 0 set above */ @@ -857,6 +850,7 @@ uio.uio_rw = write ? UIO_WRITE : UIO_READ; uio.uio_td = td; error = proc_rwmem(p, &uio); + PRELE(p); if (uio.uio_resid != 0) { /* * XXX proc_rwmem() doesn't currently return ENOSPC, @@ -875,6 +869,7 @@ return (error); case PT_IO: + _PHOLD(p); PROC_UNLOCK(p); #ifdef COMPAT_IA32 if (wrap32) { @@ -911,9 +906,11 @@ uio.uio_rw = UIO_WRITE; break; default: + PRELE(p); return (EINVAL); } error = proc_rwmem(p, &uio); + PRELE(p); #ifdef COMPAT_IA32 if (wrap32) piod32->piod_len -= uio.uio_resid; @@ -969,10 +966,11 @@ return (error); case PT_LWPINFO: - if (data == 0 || data > sizeof(*pl)) - return (EINVAL); + if (data == 0 || data > sizeof(*pl)) { + error = EINVAL; + goto fail; + } pl = addr; - _PHOLD(p); pl->pl_lwpid = td2->td_tid; if (td2->td_flags & TDF_XSIG) pl->pl_event = PL_EVENT_SIGNAL; @@ -985,7 +983,6 @@ } else { pl->pl_flags = 0; } - _PRELE(p); PROC_UNLOCK(p); return (0); @@ -996,10 +993,11 @@ case PT_GETLWPLIST: if (data <= 0) { - PROC_UNLOCK(p); - return (EINVAL); + error = EINVAL; + goto fail; } num = imin(p->p_numthreads, data); + _PHOLD(p); PROC_UNLOCK(p); buf = malloc(num * sizeof(lwpid_t), M_TEMP, M_WAITOK); tmp = 0; @@ -1011,6 +1009,7 @@ buf[tmp++] = td2->td_tid; } mtx_unlock_spin(&sched_lock); + _PRELE(p); PROC_UNLOCK(p); error = copyout(buf, addr, tmp * sizeof(lwpid_t)); free(buf, M_TEMP); @@ -1036,7 +1035,6 @@ fail: PROC_UNLOCK(p); -fail_noproc: if (proctree_locked) sx_xunlock(&proctree_lock); return (error); --- //depot/vendor/freebsd/src/sys/sys/proc.h 2006/01/27 23:05:37 +++ //depot/projects/smpng/sys/sys/proc.h 2006/02/03 21:34:55 @@ -785,6 +785,7 @@ } while (0) #define _PHOLD(p) do { \ PROC_LOCK_ASSERT((p), MA_OWNED); \ + KASSERT(!((p)->p_flag & P_WEXIT), ("PHOLD of exiting process"));\ (p)->p_lock++; \ if (((p)->p_sflag & PS_INMEM) == 0) \ faultin((p)); \ @@ -798,6 +799,8 @@ #define _PRELE(p) do { \ PROC_LOCK_ASSERT((p), MA_OWNED); \ (--(p)->p_lock); \ + if (((p)->p_flag & P_WEXIT) && (p)->p_lock == 0) \ + wakeup(&(p)->p_lock); \ } while (0) /* Check whether a thread is safe to be swapped out. */