summaryrefslogtreecommitdiffstats
path: root/sys
diff options
context:
space:
mode:
authortanimura <tanimura@FreeBSD.org>2002-02-23 11:12:57 +0000
committertanimura <tanimura@FreeBSD.org>2002-02-23 11:12:57 +0000
commita09da298590e8c11ebafa37f79e0046814665237 (patch)
tree2289c653c0f7aa23498f82b603c33107952652ec /sys
parent33e8ee5265ca2838260ab581a9cebdedb1e1e29b (diff)
downloadFreeBSD-src-a09da298590e8c11ebafa37f79e0046814665237.zip
FreeBSD-src-a09da298590e8c11ebafa37f79e0046814665237.tar.gz
Lock struct pgrp, session and sigio.
New locks are: - pgrpsess_lock which locks the whole pgrps and sessions, - pg_mtx which protects the pgrp members, and - s_mtx which protects the session members. Please refer to sys/proc.h for the coverage of these locks. Changes on the pgrp/session interface: - pgfind() needs the pgrpsess_lock held. - The caller of enterpgrp() is responsible to allocate a new pgrp and session. - Call enterthispgrp() in order to enter an existing pgrp. - pgsignal() requires a pgrp lock held. Reviewed by: jhb, alfred Tested on: cvsup.jp.FreeBSD.org (which is a quad-CPU machine running -current)
Diffstat (limited to 'sys')
-rw-r--r--sys/coda/coda_venus.c6
-rw-r--r--sys/compat/linprocfs/linprocfs.c2
-rw-r--r--sys/compat/linux/linux_file.c3
-rw-r--r--sys/compat/svr4/svr4_misc.c10
-rw-r--r--sys/dev/syscons/scvidctl.c23
-rw-r--r--sys/fs/coda/coda_venus.c6
-rw-r--r--sys/fs/procfs/procfs_ctl.c4
-rw-r--r--sys/fs/procfs/procfs_status.c6
-rw-r--r--sys/fs/specfs/spec_vnops.c13
-rw-r--r--sys/i386/ibcs2/ibcs2_ioctl.c2
-rw-r--r--sys/i386/isa/pcvt/pcvt_out.c10
-rw-r--r--sys/i386/isa/pcvt/pcvt_sup.c5
-rw-r--r--sys/kern/init_main.c2
-rw-r--r--sys/kern/kern_acct.c4
-rw-r--r--sys/kern/kern_descrip.c109
-rw-r--r--sys/kern/kern_exit.c64
-rw-r--r--sys/kern/kern_fork.c8
-rw-r--r--sys/kern/kern_ktrace.c8
-rw-r--r--sys/kern/kern_proc.c290
-rw-r--r--sys/kern/kern_prot.c162
-rw-r--r--sys/kern/kern_resource.c34
-rw-r--r--sys/kern/kern_sig.c44
-rw-r--r--sys/kern/subr_prf.c60
-rw-r--r--sys/kern/subr_witness.c4
-rw-r--r--sys/kern/sys_process.c6
-rw-r--r--sys/kern/tty.c195
-rw-r--r--sys/kern/tty_pty.c19
-rw-r--r--sys/kern/tty_tty.c56
-rw-r--r--sys/kern/vfs_aio.c10
-rw-r--r--sys/kern/vfs_vnops.c21
-rw-r--r--sys/net/if_sl.c11
-rw-r--r--sys/netkey/key.c18
-rw-r--r--sys/sys/file.h4
-rw-r--r--sys/sys/filedesc.h17
-rw-r--r--sys/sys/proc.h82
35 files changed, 1004 insertions, 314 deletions
diff --git a/sys/coda/coda_venus.c b/sys/coda/coda_venus.c
index 022009e..e223617 100644
--- a/sys/coda/coda_venus.c
+++ b/sys/coda/coda_venus.c
@@ -94,13 +94,11 @@
#define INIT_IN(in, op, ident, p) \
(in)->opcode = (op); \
- if (p) \
- PROC_LOCK(p); \
+ PGRPSESS_SLOCK(); \
(in)->pid = p ? p->p_pid : -1; \
(in)->pgid = p ? p->p_pgid : -1; \
(in)->sid = (p && p->p_session && p->p_session->s_leader) ? (p->p_session->s_leader->p_pid) : -1; \
- if (p) \
- PROC_UNLOCK(p); \
+ PGRPSESS_SUNLOCK(); \
if (ident != NOCRED) { \
(in)->cred.cr_uid = ident->cr_uid; \
(in)->cred.cr_groupid = ident->cr_gid; \
diff --git a/sys/compat/linprocfs/linprocfs.c b/sys/compat/linprocfs/linprocfs.c
index 06f0f38..ae21891 100644
--- a/sys/compat/linprocfs/linprocfs.c
+++ b/sys/compat/linprocfs/linprocfs.c
@@ -494,9 +494,9 @@ linprocfs_doprocstat(PFS_FILL_ARGS)
PS_ADD("statr", "%c", '0'); /* XXX */
PROC_LOCK(p);
PS_ADD("ppid", "%d", p->p_pptr ? p->p_pptr->p_pid : 0);
- PROC_UNLOCK(p);
PS_ADD("pgrp", "%d", p->p_pgid);
PS_ADD("session", "%d", p->p_session->s_sid);
+ PROC_UNLOCK(p);
PS_ADD("tty", "%d", 0); /* XXX */
PS_ADD("tpgid", "%d", 0); /* XXX */
PS_ADD("flags", "%u", 0); /* XXX */
diff --git a/sys/compat/linux/linux_file.c b/sys/compat/linux/linux_file.c
index 1dfa4a1..dd4f219 100644
--- a/sys/compat/linux/linux_file.c
+++ b/sys/compat/linux/linux_file.c
@@ -144,12 +144,13 @@ linux_open(struct thread *td, struct linux_open_args *args)
fo_ioctl(fp, TIOCSCTTY, (caddr_t) 0, td);
fdrop(fp, td);
}
- } else
+ } else {
PROC_UNLOCK(p);
#ifdef DEBUG
if (ldebug(open))
printf(LMSG("open returns error %d"), error);
#endif
+ }
return error;
}
diff --git a/sys/compat/svr4/svr4_misc.c b/sys/compat/svr4/svr4_misc.c
index 4771d90..9dcfa7f 100644
--- a/sys/compat/svr4/svr4_misc.c
+++ b/sys/compat/svr4/svr4_misc.c
@@ -1017,7 +1017,9 @@ svr4_sys_pgrpsys(td, uap)
/*FALLTHROUGH*/
case 0: /* getpgrp() */
+ PROC_LOCK(p);
*retval = p->p_pgrp->pg_id;
+ PROC_UNLOCK(p);
return 0;
case 2: /* getsid(pid) */
@@ -1222,7 +1224,9 @@ svr4_sys_waitsys(td, uap)
break;
case SVR4_P_PGID:
+ PROC_LOCK(td->td_proc);
SCARG(uap, id) = -td->td_proc->p_pgid;
+ PROC_UNLOCK(td->td_proc);
break;
case SVR4_P_ALL:
@@ -1283,8 +1287,12 @@ loop:
if (q->p_oppid != q->p_pptr->p_pid) {
PROC_UNLOCK(q);
t = pfind(q->p_oppid);
+ if (t == NULL) {
+ t = initproc;
+ PROC_LOCK(initproc);
+ }
PROC_LOCK(q);
- proc_reparent(q, t ? t : initproc);
+ proc_reparent(q, t);
q->p_oppid = 0;
q->p_flag &= ~(P_TRACED | P_WAITED);
PROC_UNLOCK(q);
diff --git a/sys/dev/syscons/scvidctl.c b/sys/dev/syscons/scvidctl.c
index b28752b..9e142d0 100644
--- a/sys/dev/syscons/scvidctl.c
+++ b/sys/dev/syscons/scvidctl.c
@@ -36,6 +36,11 @@
#include <sys/kernel.h>
#include <sys/fbio.h>
#include <sys/consio.h>
+#include <sys/filedesc.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
+#include <sys/mutex.h>
+#include <sys/proc.h>
#include <dev/fb/fbreg.h>
#include <dev/syscons/syscons.h>
@@ -228,7 +233,11 @@ sc_set_text_mode(scr_stat *scp, struct tty *tp, int mode, int xsize, int ysize,
|| tp->t_winsize.ws_row != scp->ysize) {
tp->t_winsize.ws_col = scp->xsize;
tp->t_winsize.ws_row = scp->ysize;
- pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
}
return 0;
@@ -291,7 +300,11 @@ sc_set_graphics_mode(scr_stat *scp, struct tty *tp, int mode)
|| tp->t_winsize.ws_ypixel != scp->ypixel) {
tp->t_winsize.ws_xpixel = scp->xpixel;
tp->t_winsize.ws_ypixel = scp->ypixel;
- pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
}
return 0;
@@ -423,7 +436,11 @@ sc_set_pixel_mode(scr_stat *scp, struct tty *tp, int xsize, int ysize,
|| tp->t_winsize.ws_row != scp->ysize) {
tp->t_winsize.ws_col = scp->xsize;
tp->t_winsize.ws_row = scp->ysize;
- pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
}
return 0;
diff --git a/sys/fs/coda/coda_venus.c b/sys/fs/coda/coda_venus.c
index 022009e..e223617 100644
--- a/sys/fs/coda/coda_venus.c
+++ b/sys/fs/coda/coda_venus.c
@@ -94,13 +94,11 @@
#define INIT_IN(in, op, ident, p) \
(in)->opcode = (op); \
- if (p) \
- PROC_LOCK(p); \
+ PGRPSESS_SLOCK(); \
(in)->pid = p ? p->p_pid : -1; \
(in)->pgid = p ? p->p_pgid : -1; \
(in)->sid = (p && p->p_session && p->p_session->s_leader) ? (p->p_session->s_leader->p_pid) : -1; \
- if (p) \
- PROC_UNLOCK(p); \
+ PGRPSESS_SUNLOCK(); \
if (ident != NOCRED) { \
(in)->cred.cr_uid = ident->cr_uid; \
(in)->cred.cr_groupid = ident->cr_gid; \
diff --git a/sys/fs/procfs/procfs_ctl.c b/sys/fs/procfs/procfs_ctl.c
index 154eaa6..3a73980 100644
--- a/sys/fs/procfs/procfs_ctl.c
+++ b/sys/fs/procfs/procfs_ctl.c
@@ -230,8 +230,10 @@ out:
pp = pfind(p->p_oppid);
PROC_LOCK(p);
- if (pp)
+ if (pp) {
+ PROC_UNLOCK(pp);
proc_reparent(p, pp);
+ }
} else
PROC_LOCK(p);
p->p_oppid = 0;
diff --git a/sys/fs/procfs/procfs_status.c b/sys/fs/procfs/procfs_status.c
index 0f8e343..9238dfe 100644
--- a/sys/fs/procfs/procfs_status.c
+++ b/sys/fs/procfs/procfs_status.c
@@ -48,6 +48,8 @@
#include <sys/mutex.h>
#include <sys/jail.h>
#include <sys/malloc.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
#include <sys/proc.h>
#include <sys/resourcevar.h>
#include <sys/sbuf.h>
@@ -75,9 +77,9 @@ procfs_doprocstatus(PFS_FILL_ARGS)
pid = p->p_pid;
PROC_LOCK(p);
ppid = p->p_pptr ? p->p_pptr->p_pid : 0;
- PROC_UNLOCK(p);
pgid = p->p_pgrp->pg_id;
sess = p->p_pgrp->pg_session;
+ SESS_LOCK(sess);
sid = sess->s_leader ? sess->s_leader->p_pid : 0;
/* comm pid ppid pgid sid maj,min ctty,sldr start ut st wmsg
@@ -106,6 +108,8 @@ procfs_doprocstatus(PFS_FILL_ARGS)
sbuf_printf(sb, "%ssldr", sep);
sep = ",";
}
+ SESS_UNLOCK(sess);
+ PROC_UNLOCK(p);
if (*sep != ',') {
sbuf_printf(sb, "noflags");
}
diff --git a/sys/fs/specfs/spec_vnops.c b/sys/fs/specfs/spec_vnops.c
index 9de659c..7887ddb 100644
--- a/sys/fs/specfs/spec_vnops.c
+++ b/sys/fs/specfs/spec_vnops.c
@@ -35,6 +35,8 @@
*/
#include <sys/param.h>
+#include <sys/lock.h>
+#include <sys/sx.h>
#include <sys/proc.h>
#include <sys/systm.h>
#include <sys/kernel.h>
@@ -568,7 +570,7 @@ spec_close(ap)
struct thread *a_td;
} */ *ap;
{
- struct vnode *vp = ap->a_vp;
+ struct vnode *vp = ap->a_vp, *oldvp;
struct thread *td = ap->a_td;
dev_t dev = vp->v_rdev;
@@ -581,11 +583,18 @@ spec_close(ap)
* if the reference count is 2 (this last descriptor
* plus the session), release the reference from the session.
*/
+ oldvp = NULL;
+ PGRPSESS_XLOCK();
if (vcount(vp) == 2 && td && (vp->v_flag & VXLOCK) == 0 &&
vp == td->td_proc->p_session->s_ttyvp) {
- vrele(vp);
+ SESS_LOCK(td->td_proc->p_session);
td->td_proc->p_session->s_ttyvp = NULL;
+ SESS_UNLOCK(td->td_proc->p_session);
+ oldvp = vp;
}
+ PGRPSESS_XUNLOCK();
+ if (oldvp != NULL)
+ vrele(oldvp);
/*
* We do not want to really close the device if it
* is still in use unless we are trying to close it
diff --git a/sys/i386/ibcs2/ibcs2_ioctl.c b/sys/i386/ibcs2/ibcs2_ioctl.c
index 2755b01..cb5d5ae 100644
--- a/sys/i386/ibcs2/ibcs2_ioctl.c
+++ b/sys/i386/ibcs2/ibcs2_ioctl.c
@@ -552,6 +552,7 @@ ibcs2_ioctl(td, uap)
} ibcs2_jwinsize;
PROC_LOCK(p);
+ SESS_LOCK(p->p_session);
ibcs2_jwinsize.bytex = 80;
/* p->p_session->s_ttyp->t_winsize.ws_col; XXX */
ibcs2_jwinsize.bytey = 25;
@@ -560,6 +561,7 @@ ibcs2_ioctl(td, uap)
p->p_session->s_ttyp->t_winsize.ws_xpixel;
ibcs2_jwinsize.bity =
p->p_session->s_ttyp->t_winsize.ws_ypixel;
+ SESS_UNLOCK(p->p_session);
PROC_UNLOCK(p);
error = copyout((caddr_t)&ibcs2_jwinsize, SCARG(uap, data),
sizeof(ibcs2_jwinsize));
diff --git a/sys/i386/isa/pcvt/pcvt_out.c b/sys/i386/isa/pcvt/pcvt_out.c
index e891b4c..8c77933 100644
--- a/sys/i386/isa/pcvt/pcvt_out.c
+++ b/sys/i386/isa/pcvt/pcvt_out.c
@@ -1582,8 +1582,11 @@ set_emulation_mode(struct video_state *svsp, int mode)
svsp->scrr_end = svsp->scrr_len - 1;
}
- if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
+ if (svsp->vs_tty && svsp->vs_tty->t_pgrp) {
+ PGRP_LOCK(svsp->vs_tty->t_pgrp);
pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(svsp->vs_tty->t_pgrp);
+ }
}
/*---------------------------------------------------------------------------*
@@ -1867,8 +1870,11 @@ vt_col(struct video_state *svsp, int cols)
(cols == SCR_COL80)? 720: 1056;
svsp->vs_tty->t_winsize.ws_ypixel = 400;
- if(svsp->vs_tty->t_pgrp)
+ if(svsp->vs_tty->t_pgrp) {
+ PGRP_LOCK(svsp->vs_tty->t_pgrp);
pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(svsp->vs_tty->t_pgrp);
+ }
}
reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
diff --git a/sys/i386/isa/pcvt/pcvt_sup.c b/sys/i386/isa/pcvt/pcvt_sup.c
index 7fde462..4df2971 100644
--- a/sys/i386/isa/pcvt/pcvt_sup.c
+++ b/sys/i386/isa/pcvt/pcvt_sup.c
@@ -703,8 +703,11 @@ set_screen_size(struct video_state *svsp, int size)
svsp->scrr_len = svsp->screen_rows;
svsp->scrr_end = svsp->scrr_len - 1;
- if (svsp->vs_tty && svsp->vs_tty->t_pgrp)
+ if (svsp->vs_tty && svsp->vs_tty->t_pgrp) {
+ PGRP_LOCK(svsp->vs_tty->t_pgrp);
pgsignal(svsp->vs_tty->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(svsp->vs_tty->t_pgrp);
+ }
reallocate_scrollbuffer(svsp, svsp->scrollback_pages);
break;
diff --git a/sys/kern/init_main.c b/sys/kern/init_main.c
index 6b698e4..6de34ef 100644
--- a/sys/kern/init_main.c
+++ b/sys/kern/init_main.c
@@ -305,12 +305,14 @@ proc0_init(void *dummy __unused)
*/
LIST_INSERT_HEAD(&allproc, p, p_list);
LIST_INSERT_HEAD(PIDHASH(0), p, p_hash);
+ mtx_init(&pgrp0.pg_mtx, "process group", MTX_DEF);
p->p_pgrp = &pgrp0;
LIST_INSERT_HEAD(PGRPHASH(0), &pgrp0, pg_hash);
LIST_INIT(&pgrp0.pg_members);
LIST_INSERT_HEAD(&pgrp0.pg_members, p, p_pglist);
pgrp0.pg_session = &session0;
+ mtx_init(&session0.s_mtx, "session", MTX_DEF);
session0.s_count = 1;
session0.s_leader = p;
diff --git a/sys/kern/kern_acct.c b/sys/kern/kern_acct.c
index cd191d5..e859057 100644
--- a/sys/kern/kern_acct.c
+++ b/sys/kern/kern_acct.c
@@ -233,10 +233,14 @@ acct_process(td)
acct.ac_gid = p->p_ucred->cr_rgid;
/* (7) The terminal from which the process was started */
+ PROC_LOCK(p);
+ SESS_LOCK(p->p_session);
if ((p->p_flag & P_CONTROLT) && p->p_pgrp->pg_session->s_ttyp)
acct.ac_tty = dev2udev(p->p_pgrp->pg_session->s_ttyp->t_dev);
else
acct.ac_tty = NOUDEV;
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
/* (8) The boolean flags that tell how the process terminated, etc. */
acct.ac_flag = p->p_acflag;
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index ea7fa2d..8e4726e 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -535,15 +535,22 @@ funsetown(sigio)
if (sigio == NULL)
return;
+
s = splhigh();
*(sigio->sio_myref) = NULL;
splx(s);
- if (sigio->sio_pgid < 0) {
+ if ((sigio)->sio_pgid < 0) {
+ struct pgrp *pg = (sigio)->sio_pgrp;
+ PGRP_LOCK(pg);
SLIST_REMOVE(&sigio->sio_pgrp->pg_sigiolst, sigio,
sigio, sio_pgsigio);
- } else /* if ((*sigiop)->sio_pgid > 0) */ {
+ PGRP_UNLOCK(pg);
+ } else {
+ struct proc *p = (sigio)->sio_proc;
+ PROC_LOCK(p);
SLIST_REMOVE(&sigio->sio_proc->p_sigiolst, sigio,
sigio, sio_pgsigio);
+ PROC_UNLOCK(p);
}
crfree(sigio->sio_ucred);
FREE(sigio, M_SIGIO);
@@ -554,10 +561,52 @@ void
funsetownlst(sigiolst)
struct sigiolst *sigiolst;
{
+ int s;
struct sigio *sigio;
+ struct proc *p;
+ struct pgrp *pg;
+
+ sigio = SLIST_FIRST(sigiolst);
+ if (sigio == NULL)
+ return;
+
+ p = NULL;
+ pg = NULL;
+
+ /*
+ * Every entry of the list should belong
+ * to a single proc or pgrp.
+ */
+ if (sigio->sio_pgid < 0) {
+ pg = sigio->sio_pgrp;
+ PGRP_LOCK_ASSERT(pg, MA_OWNED);
+ } else /* if (sigio->sio_pgid > 0) */ {
+ p = sigio->sio_proc;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
+ }
- while ((sigio = SLIST_FIRST(sigiolst)) != NULL)
- funsetown(sigio);
+ while ((sigio = SLIST_FIRST(sigiolst)) != NULL) {
+ s = splhigh();
+ *(sigio->sio_myref) = NULL;
+ splx(s);
+ if (pg != NULL) {
+ KASSERT(sigio->sio_pgid < 0, ("Proc sigio in pgrp sigio list"));
+ KASSERT(sigio->sio_pgrp == pg, ("Bogus pgrp in sigio list"));
+ SLIST_REMOVE(&pg->pg_sigiolst, sigio, sigio, sio_pgsigio);
+ PGRP_UNLOCK(pg);
+ crfree(sigio->sio_ucred);
+ FREE(sigio, M_SIGIO);
+ PGRP_LOCK(pg);
+ } else /* if (p != NULL) */ {
+ KASSERT(sigio->sio_pgid > 0, ("Pgrp sigio in proc sigio list"));
+ KASSERT(sigio->sio_proc == p, ("Bogus proc in sigio list"));
+ SLIST_REMOVE(&p->p_sigiolst, sigio, sigio, sio_pgsigio);
+ PROC_UNLOCK(p);
+ crfree(sigio->sio_ucred);
+ FREE(sigio, M_SIGIO);
+ PROC_LOCK(p);
+ }
+ }
}
/*
@@ -574,16 +623,28 @@ fsetown(pgid, sigiop)
struct proc *proc;
struct pgrp *pgrp;
struct sigio *sigio;
- int s;
+ int s, ret;
if (pgid == 0) {
funsetown(*sigiop);
return (0);
}
+
+ ret = 0;
+
+ /* Allocate and fill in the new sigio out of locks. */
+ MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, M_WAITOK);
+ sigio->sio_pgid = pgid;
+ sigio->sio_ucred = crhold(curthread->td_proc->p_ucred);
+ sigio->sio_myref = sigiop;
+
+ PGRPSESS_SLOCK();
if (pgid > 0) {
proc = pfind(pgid);
- if (proc == NULL)
- return (ESRCH);
+ if (proc == NULL) {
+ ret = ESRCH;
+ goto fail;
+ }
/*
* Policy - Don't allow a process to FSETOWN a process
@@ -593,17 +654,20 @@ fsetown(pgid, sigiop)
* restrict FSETOWN to the current process or process
* group for maximum safety.
*/
+ PROC_UNLOCK(proc);
if (proc->p_session != curthread->td_proc->p_session) {
- PROC_UNLOCK(proc);
- return (EPERM);
+ ret = EPERM;
+ goto fail;
}
- PROC_UNLOCK(proc);
pgrp = NULL;
} else /* if (pgid < 0) */ {
pgrp = pgfind(-pgid);
- if (pgrp == NULL)
- return (ESRCH);
+ if (pgrp == NULL) {
+ ret = ESRCH;
+ goto fail;
+ }
+ PGRP_UNLOCK(pgrp);
/*
* Policy - Don't allow a process to FSETOWN a process
@@ -613,27 +677,36 @@ fsetown(pgid, sigiop)
* restrict FSETOWN to the current process or process
* group for maximum safety.
*/
- if (pgrp->pg_session != curthread->td_proc->p_session)
- return (EPERM);
+ if (pgrp->pg_session != curthread->td_proc->p_session) {
+ ret = EPERM;
+ goto fail;
+ }
proc = NULL;
}
funsetown(*sigiop);
- MALLOC(sigio, struct sigio *, sizeof(struct sigio), M_SIGIO, M_WAITOK);
if (pgid > 0) {
+ PROC_LOCK(proc);
SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio, sio_pgsigio);
sigio->sio_proc = proc;
+ PROC_UNLOCK(proc);
} else {
+ PGRP_LOCK(pgrp);
SLIST_INSERT_HEAD(&pgrp->pg_sigiolst, sigio, sio_pgsigio);
sigio->sio_pgrp = pgrp;
+ PGRP_UNLOCK(pgrp);
}
- sigio->sio_pgid = pgid;
- sigio->sio_ucred = crhold(curthread->td_proc->p_ucred);
- sigio->sio_myref = sigiop;
+ PGRPSESS_SUNLOCK();
s = splhigh();
*sigiop = sigio;
splx(s);
return (0);
+
+fail:
+ PGRPSESS_SUNLOCK();
+ crfree(sigio->sio_ucred);
+ FREE(sigio, M_SIGIO);
+ return (ret);
}
/*
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index c8503ca..37d2ab1 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -125,6 +125,8 @@ exit1(td, rv)
register struct vmspace *vm;
struct vnode *vtmp;
struct exitlist *ep;
+ struct vnode *ttyvp;
+ struct tty *tp;
GIANT_REQUIRED;
@@ -186,7 +188,9 @@ exit1(td, rv)
* Reset any sigio structures pointing to us as a result of
* F_SETOWN with our pid.
*/
+ PROC_LOCK(p);
funsetownlst(&p->p_sigiolst);
+ PROC_UNLOCK(p);
/*
* Close open files and release open-file table.
@@ -227,11 +231,11 @@ exit1(td, rv)
vm->vm_freer = p;
}
- PROC_LOCK(p);
+ PGRPSESS_XLOCK();
if (SESS_LEADER(p)) {
- register struct session *sp = p->p_session;
+ register struct session *sp;
- PROC_UNLOCK(p);
+ sp = p->p_session;
if (sp->s_ttyvp) {
/*
* Controlling process.
@@ -240,29 +244,48 @@ exit1(td, rv)
* and revoke access to controlling terminal.
*/
if (sp->s_ttyp && (sp->s_ttyp->t_session == sp)) {
- if (sp->s_ttyp->t_pgrp)
+ tp = sp->s_ttyp;
+ if (sp->s_ttyp->t_pgrp) {
+ PGRP_LOCK(sp->s_ttyp->t_pgrp);
pgsignal(sp->s_ttyp->t_pgrp, SIGHUP, 1);
- (void) ttywait(sp->s_ttyp);
+ PGRP_UNLOCK(sp->s_ttyp->t_pgrp);
+ }
+ /* XXX tp should be locked. */
+ (void) ttywait(tp);
/*
* The tty could have been revoked
* if we blocked.
*/
- if (sp->s_ttyvp)
- VOP_REVOKE(sp->s_ttyvp, REVOKEALL);
+ if (sp->s_ttyvp) {
+ ttyvp = sp->s_ttyvp;
+ SESS_LOCK(p->p_session);
+ sp->s_ttyvp = NULL;
+ SESS_UNLOCK(p->p_session);
+ PGRPSESS_XUNLOCK();
+ VOP_REVOKE(ttyvp, REVOKEALL);
+ PGRPSESS_XLOCK();
+ vrele(ttyvp);
+ }
+ }
+ if (sp->s_ttyvp) {
+ ttyvp = sp->s_ttyvp;
+ SESS_LOCK(p->p_session);
+ sp->s_ttyvp = NULL;
+ SESS_UNLOCK(p->p_session);
+ vrele(ttyvp);
}
- if (sp->s_ttyvp)
- vrele(sp->s_ttyvp);
- sp->s_ttyvp = NULL;
/*
* s_ttyp is not zero'd; we use this to indicate
* that the session once had a controlling terminal.
* (for logging and informational purposes)
*/
}
+ SESS_LOCK(p->p_session);
sp->s_leader = NULL;
- } else
- PROC_UNLOCK(p);
+ SESS_UNLOCK(p->p_session);
+ }
fixjobc(p, p->p_pgrp, 0);
+ PGRPSESS_XUNLOCK();
(void)acct_process(td);
#ifdef KTRACE
/*
@@ -309,7 +332,7 @@ exit1(td, rv)
q->p_flag &= ~P_TRACED;
psignal(q, SIGKILL);
}
- PROC_UNLOCK(q);
+ PROC_UNLOCK(q);
}
/*
@@ -338,6 +361,7 @@ exit1(td, rv)
* notify interested parties of our demise.
*/
PROC_LOCK(p);
+ PROC_LOCK(p->p_pptr);
KNOTE(&p->p_klist, NOTE_EXIT);
/*
@@ -347,7 +371,9 @@ exit1(td, rv)
*/
if (p->p_pptr->p_procsig->ps_flag & PS_NOCLDWAIT) {
struct proc *pp = p->p_pptr;
+ PROC_UNLOCK(pp);
proc_reparent(p, initproc);
+ PROC_LOCK(p->p_pptr);
/*
* If this was the last child of our parent, notify
* parent, so in case he was wait(2)ing, he will
@@ -357,7 +383,6 @@ exit1(td, rv)
wakeup((caddr_t)pp);
}
- PROC_LOCK(p->p_pptr);
if (p->p_sigparent && p->p_pptr != initproc)
psignal(p->p_pptr, p->p_sigparent);
else
@@ -480,8 +505,11 @@ wait1(td, uap, compat)
mtx_lock(&Giant);
q = td->td_proc;
- if (uap->pid == 0)
+ if (uap->pid == 0) {
+ PROC_LOCK(q);
uap->pid = -q->p_pgid;
+ PROC_UNLOCK(q);
+ }
if (uap->options &~ (WUNTRACED|WNOHANG|WLINUXCLONE)) {
error = EINVAL;
goto done2;
@@ -490,9 +518,12 @@ loop:
nfound = 0;
sx_slock(&proctree_lock);
LIST_FOREACH(p, &q->p_children, p_sibling) {
+ PROC_LOCK(p);
if (uap->pid != WAIT_ANY &&
- p->p_pid != uap->pid && p->p_pgid != -uap->pid)
+ p->p_pid != uap->pid && p->p_pgid != -uap->pid) {
+ PROC_UNLOCK(p);
continue;
+ }
/*
* This special case handles a kthread spawned by linux_clone
@@ -502,7 +533,6 @@ loop:
* p_sigparent is not SIGCHLD, and the WLINUXCLONE option
* signifies we want to wait for threads and not processes.
*/
- PROC_LOCK(p);
if ((p->p_sigparent != SIGCHLD) ^
((uap->options & WLINUXCLONE) != 0)) {
PROC_UNLOCK(p);
diff --git a/sys/kern/kern_fork.c b/sys/kern/kern_fork.c
index 8fe1006..69071a1 100644
--- a/sys/kern/kern_fork.c
+++ b/sys/kern/kern_fork.c
@@ -382,12 +382,15 @@ retry:
p2 = LIST_FIRST(&allproc);
again:
for (; p2 != NULL; p2 = LIST_NEXT(p2, p_list)) {
+ PROC_LOCK(p2);
while (p2->p_pid == trypid ||
p2->p_pgrp->pg_id == trypid ||
p2->p_session->s_sid == trypid) {
trypid++;
- if (trypid >= pidchecked)
+ if (trypid >= pidchecked) {
+ PROC_UNLOCK(p2);
goto retry;
+ }
}
if (p2->p_pid > trypid && pidchecked > p2->p_pid)
pidchecked = p2->p_pid;
@@ -397,6 +400,7 @@ again:
if (p2->p_session->s_sid > trypid &&
pidchecked > p2->p_session->s_sid)
pidchecked = p2->p_session->s_sid;
+ PROC_UNLOCK(p2);
}
if (!doingzomb) {
doingzomb = 1;
@@ -559,8 +563,10 @@ again:
* been preserved.
*/
p2->p_flag |= p1->p_flag & (P_SUGID | P_ALTSTACK);
+ SESS_LOCK(p1->p_session);
if (p1->p_session->s_ttyvp != NULL && p1->p_flag & P_CONTROLT)
p2->p_flag |= P_CONTROLT;
+ SESS_UNLOCK(p1->p_session);
if (flags & RFPPWAIT)
p2->p_flag |= P_PPWAIT;
diff --git a/sys/kern/kern_ktrace.c b/sys/kern/kern_ktrace.c
index db44873..6fc46d6 100644
--- a/sys/kern/kern_ktrace.c
+++ b/sys/kern/kern_ktrace.c
@@ -350,16 +350,24 @@ ktrace(td, uap)
/*
* by process group
*/
+ PGRPSESS_SLOCK();
pg = pgfind(-uap->pid);
if (pg == NULL) {
+ PGRPSESS_SUNLOCK();
error = ESRCH;
goto done;
}
+ /*
+ * ktrops() may call vrele(). Lock pg_members
+ * by the pgrpsess_lock rather than pg_mtx.
+ */
+ PGRP_UNLOCK(pg);
LIST_FOREACH(p, &pg->pg_members, p_pglist)
if (descend)
ret |= ktrsetchildren(curp, p, ops, facs, vp);
else
ret |= ktrops(curp, p, ops, facs, vp);
+ PGRPSESS_SUNLOCK();
} else {
/*
* by pid
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index b11c23b..27222fa 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -55,14 +55,18 @@
#include <vm/vm_map.h>
#include <vm/vm_zone.h>
-static MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
+MALLOC_DEFINE(M_PGRP, "pgrp", "process group header");
MALLOC_DEFINE(M_SESSION, "session", "session header");
static MALLOC_DEFINE(M_PROC, "proc", "Proc structures");
MALLOC_DEFINE(M_SUBPROC, "subproc", "Proc sub-structures");
+static struct proc *dopfind __P((register pid_t));
+
+static void doenterpgrp __P((struct proc *, struct pgrp *));
+
static void pgdelete __P((struct pgrp *));
-static void orphanpg __P((struct pgrp *pg));
+static void orphanpg __P((struct pgrp *pg));
/*
* Other process lists
@@ -75,6 +79,7 @@ struct proclist allproc;
struct proclist zombproc;
struct sx allproc_lock;
struct sx proctree_lock;
+struct sx pgrpsess_lock;
vm_zone_t proc_zone;
vm_zone_t ithread_zone;
@@ -88,6 +93,7 @@ procinit()
sx_init(&allproc_lock, "allproc");
sx_init(&proctree_lock, "proctree");
+ sx_init(&pgrpsess_lock, "pgrpsess");
LIST_INIT(&allproc);
LIST_INIT(&zombproc);
pidhashtbl = hashinit(maxproc / 4, M_PROC, &pidhash);
@@ -265,17 +271,30 @@ pfind(pid)
register struct proc *p;
sx_slock(&allproc_lock);
+ p = dopfind(pid);
+ sx_sunlock(&allproc_lock);
+ return (p);
+}
+
+static struct proc *
+dopfind(pid)
+ register pid_t pid;
+{
+ register struct proc *p;
+
+ sx_assert(&allproc_lock, SX_LOCKED);
+
LIST_FOREACH(p, PIDHASH(pid), p_hash)
if (p->p_pid == pid) {
PROC_LOCK(p);
break;
}
- sx_sunlock(&allproc_lock);
return (p);
}
/*
- * Locate a process group by number
+ * Locate a process group by number.
+ * The caller must hold pgrpsess_lock.
*/
struct pgrp *
pgfind(pgid)
@@ -283,77 +302,132 @@ pgfind(pgid)
{
register struct pgrp *pgrp;
- LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash)
- if (pgrp->pg_id == pgid)
+ PGRPSESS_LOCK_ASSERT(SX_LOCKED);
+
+ LIST_FOREACH(pgrp, PGRPHASH(pgid), pg_hash) {
+ if (pgrp->pg_id == pgid) {
+ PGRP_LOCK(pgrp);
return (pgrp);
+ }
+ }
return (NULL);
}
/*
- * Move p to a new or existing process group (and session)
+ * Create a new process group.
+ * pgid must be equal to the pid of p.
+ * Begin a new session if required.
*/
int
-enterpgrp(p, pgid, mksess)
+enterpgrp(p, pgid, pgrp, sess)
register struct proc *p;
pid_t pgid;
- int mksess;
+ struct pgrp *pgrp;
+ struct session *sess;
{
- register struct pgrp *pgrp = pgfind(pgid);
- struct pgrp *savegrp;
+ struct pgrp *pgrp2;
- KASSERT(pgrp == NULL || !mksess,
- ("enterpgrp: setsid into non-empty pgrp"));
+ PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
+
+ KASSERT(pgrp != NULL, ("enterpgrp: pgrp == NULL"));
+ KASSERT(p->p_pid == pgid,
+ ("enterpgrp: new pgrp and pid != pgid"));
+
+ pgrp2 = pgfind(pgid);
+
+ KASSERT(pgrp2 == NULL,
+ ("enterpgrp: pgrp with pgid exists"));
KASSERT(!SESS_LEADER(p),
("enterpgrp: session leader attempted setpgrp"));
- if (pgrp == NULL) {
- pid_t savepid = p->p_pid;
- struct proc *np;
+ mtx_init(&pgrp->pg_mtx, "process group", MTX_DEF);
+
+ if (sess != NULL) {
/*
- * new process group
+ * new session
*/
- KASSERT(p->p_pid == pgid,
- ("enterpgrp: new pgrp and pid != pgid"));
- if ((np = pfind(savepid)) == NULL || np != p) {
- if (np != NULL)
- PROC_UNLOCK(np);
- return (ESRCH);
- }
- PROC_UNLOCK(np);
- MALLOC(pgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP,
- M_WAITOK);
- if (mksess) {
- register struct session *sess;
-
- /*
- * new session
- */
- MALLOC(sess, struct session *, sizeof(struct session),
- M_SESSION, M_WAITOK);
- sess->s_leader = p;
- sess->s_sid = p->p_pid;
- sess->s_count = 1;
- sess->s_ttyvp = NULL;
- sess->s_ttyp = NULL;
- bcopy(p->p_session->s_login, sess->s_login,
+ mtx_init(&sess->s_mtx, "session", MTX_DEF);
+ PROC_LOCK(p);
+ p->p_flag &= ~P_CONTROLT;
+ PROC_UNLOCK(p);
+ PGRP_LOCK(pgrp);
+ sess->s_leader = p;
+ sess->s_sid = p->p_pid;
+ sess->s_count = 1;
+ sess->s_ttyvp = NULL;
+ sess->s_ttyp = NULL;
+ bcopy(p->p_session->s_login, sess->s_login,
sizeof(sess->s_login));
- PROC_LOCK(p);
- p->p_flag &= ~P_CONTROLT;
- PROC_UNLOCK(p);
- pgrp->pg_session = sess;
- KASSERT(p == curproc,
- ("enterpgrp: mksession and p != curproc"));
- } else {
- pgrp->pg_session = p->p_session;
- pgrp->pg_session->s_count++;
- }
- pgrp->pg_id = pgid;
- LIST_INIT(&pgrp->pg_members);
- LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
- pgrp->pg_jobc = 0;
- SLIST_INIT(&pgrp->pg_sigiolst);
- } else if (pgrp == p->p_pgrp)
- return (0);
+ pgrp->pg_session = sess;
+ KASSERT(p == curproc,
+ ("enterpgrp: mksession and p != curproc"));
+ } else {
+ pgrp->pg_session = p->p_session;
+ SESS_LOCK(pgrp->pg_session);
+ pgrp->pg_session->s_count++;
+ SESS_UNLOCK(pgrp->pg_session);
+ PGRP_LOCK(pgrp);
+ }
+ pgrp->pg_id = pgid;
+ LIST_INIT(&pgrp->pg_members);
+
+ /*
+ * As we have an exclusive lock of pgrpsess_lock,
+ * this should not deadlock.
+ */
+ LIST_INSERT_HEAD(PGRPHASH(pgid), pgrp, pg_hash);
+ pgrp->pg_jobc = 0;
+ SLIST_INIT(&pgrp->pg_sigiolst);
+ PGRP_UNLOCK(pgrp);
+
+ doenterpgrp(p, pgrp);
+
+ return (0);
+}
+
+/*
+ * Move p to an existing process group
+ */
+int
+enterthispgrp(p, pgrp)
+ register struct proc *p;
+ struct pgrp *pgrp;
+{
+ PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
+ PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
+ PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED);
+ SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
+ KASSERT(pgrp->pg_session == p->p_session,
+ ("%s: pgrp's session %p, p->p_session %p.\n",
+ __func__,
+ pgrp->pg_session,
+ p->p_session));
+ KASSERT(pgrp != p->p_pgrp,
+ ("%s: p belongs to pgrp.", __func__));
+
+ doenterpgrp(p, pgrp);
+
+ return (0);
+}
+
+/*
+ * Move p to a process group
+ */
+static void
+doenterpgrp(p, pgrp)
+ struct proc *p;
+ struct pgrp *pgrp;
+{
+ struct pgrp *savepgrp;
+
+ PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
+ PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
+ PGRP_LOCK_ASSERT(p->p_pgrp, MA_NOTOWNED);
+ SESS_LOCK_ASSERT(p->p_session, MA_NOTOWNED);
+
+ savepgrp = p->p_pgrp;
/*
* Adjust eligibility of affected pgrps to participate in job control.
@@ -363,15 +437,17 @@ enterpgrp(p, pgid, mksess)
fixjobc(p, pgrp, 1);
fixjobc(p, p->p_pgrp, 0);
+ PGRP_LOCK(pgrp);
+ PGRP_LOCK(savepgrp);
PROC_LOCK(p);
LIST_REMOVE(p, p_pglist);
- savegrp = p->p_pgrp;
p->p_pgrp = pgrp;
- LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
PROC_UNLOCK(p);
- if (LIST_EMPTY(&savegrp->pg_members))
- pgdelete(savegrp);
- return (0);
+ LIST_INSERT_HEAD(&pgrp->pg_members, p, p_pglist);
+ PGRP_UNLOCK(savepgrp);
+ PGRP_UNLOCK(pgrp);
+ if (LIST_EMPTY(&savepgrp->pg_members))
+ pgdelete(savepgrp);
}
/*
@@ -381,15 +457,19 @@ int
leavepgrp(p)
register struct proc *p;
{
- struct pgrp *savegrp;
+ struct pgrp *savepgrp;
+ PGRPSESS_XLOCK();
+ savepgrp = p->p_pgrp;
+ PGRP_LOCK(savepgrp);
PROC_LOCK(p);
LIST_REMOVE(p, p_pglist);
- savegrp = p->p_pgrp;
p->p_pgrp = NULL;
PROC_UNLOCK(p);
- if (LIST_EMPTY(&savegrp->pg_members))
- pgdelete(savegrp);
+ PGRP_UNLOCK(savepgrp);
+ if (LIST_EMPTY(&savepgrp->pg_members))
+ pgdelete(savepgrp);
+ PGRPSESS_XUNLOCK();
return (0);
}
@@ -400,6 +480,13 @@ static void
pgdelete(pgrp)
register struct pgrp *pgrp;
{
+ struct session *savesess;
+
+ PGRPSESS_LOCK_ASSERT(SX_XLOCKED);
+ PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
+ SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
+
+ PGRP_LOCK(pgrp);
/*
* Reset any sigio structures pointing to us as a result of
@@ -411,8 +498,16 @@ pgdelete(pgrp)
pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
pgrp->pg_session->s_ttyp->t_pgrp = NULL;
LIST_REMOVE(pgrp, pg_hash);
- if (--pgrp->pg_session->s_count == 0)
+ savesess = pgrp->pg_session;
+ SESS_LOCK(savesess);
+ savesess->s_count--;
+ SESS_UNLOCK(savesess);
+ PGRP_UNLOCK(pgrp);
+ if (savesess->s_count == 0) {
+ mtx_destroy(&savesess->s_mtx);
FREE(pgrp->pg_session, M_SESSION);
+ }
+ mtx_destroy(&pgrp->pg_mtx);
FREE(pgrp, M_PGRP);
}
@@ -433,19 +528,30 @@ fixjobc(p, pgrp, entering)
int entering;
{
register struct pgrp *hispgrp;
- register struct session *mysession = pgrp->pg_session;
+ register struct session *mysession;
+
+ PGRPSESS_LOCK_ASSERT(SX_LOCKED);
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
+ PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
+ SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
/*
* Check p's parent to see whether p qualifies its own process
* group; if so, adjust count for p's process group.
*/
+ mysession = pgrp->pg_session;
sx_slock(&proctree_lock);
if ((hispgrp = p->p_pptr->p_pgrp) != pgrp &&
hispgrp->pg_session == mysession) {
+ PGRP_LOCK(pgrp);
if (entering)
pgrp->pg_jobc++;
- else if (--pgrp->pg_jobc == 0)
- orphanpg(pgrp);
+ else {
+ --pgrp->pg_jobc;
+ if (pgrp->pg_jobc == 0)
+ orphanpg(pgrp);
+ }
+ PGRP_UNLOCK(pgrp);
}
/*
@@ -453,15 +559,21 @@ fixjobc(p, pgrp, entering)
* their process groups; if so, adjust counts for children's
* process groups.
*/
- LIST_FOREACH(p, &p->p_children, p_sibling)
+ LIST_FOREACH(p, &p->p_children, p_sibling) {
if ((hispgrp = p->p_pgrp) != pgrp &&
hispgrp->pg_session == mysession &&
p->p_stat != SZOMB) {
+ PGRP_LOCK(hispgrp);
if (entering)
hispgrp->pg_jobc++;
- else if (--hispgrp->pg_jobc == 0)
- orphanpg(hispgrp);
+ else {
+ --hispgrp->pg_jobc;
+ if (hispgrp->pg_jobc == 0)
+ orphanpg(hispgrp);
+ }
+ PGRP_UNLOCK(hispgrp);
}
+ }
sx_sunlock(&proctree_lock);
}
@@ -476,6 +588,8 @@ orphanpg(pg)
{
register struct proc *p;
+ PGRP_LOCK_ASSERT(pg, MA_OWNED);
+
mtx_lock_spin(&sched_lock);
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
if (p->p_stat == SSTOP) {
@@ -619,6 +733,7 @@ fill_kinfo_proc(p, kp)
/* ^^^ XXXKSE */
mtx_unlock_spin(&sched_lock);
sp = NULL;
+ tp = NULL;
if (p->p_pgrp) {
kp->ki_pgid = p->p_pgrp->pg_id;
kp->ki_jobc = p->p_pgrp->pg_jobc;
@@ -626,15 +741,18 @@ fill_kinfo_proc(p, kp)
if (sp != NULL) {
kp->ki_sid = sp->s_sid;
+ SESS_LOCK(sp);
strncpy(kp->ki_login, sp->s_login,
sizeof(kp->ki_login) - 1);
if (sp->s_ttyvp)
kp->ki_kiflag |= KI_CTTY;
if (SESS_LEADER(p))
kp->ki_kiflag |= KI_SLEADER;
+ tp = sp->s_ttyp;
+ SESS_UNLOCK(sp);
}
}
- if ((p->p_flag & P_CONTROLT) && sp && ((tp = sp->s_ttyp) != NULL)) {
+ if ((p->p_flag & P_CONTROLT) && tp != NULL) {
kp->ki_tdev = dev2udev(tp->t_dev);
kp->ki_tpgid = tp->t_pgrp ? tp->t_pgrp->pg_id : NO_PID;
if (tp->t_session)
@@ -768,18 +886,32 @@ sysctl_kern_proc(SYSCTL_HANDLER_ARGS)
case KERN_PROC_PGRP:
/* could do this by traversing pgrp */
+ PROC_LOCK(p);
if (p->p_pgrp == NULL ||
- p->p_pgrp->pg_id != (pid_t)name[0])
+ p->p_pgrp->pg_id != (pid_t)name[0]) {
+ PROC_UNLOCK(p);
continue;
+ }
+ PROC_UNLOCK(p);
break;
case KERN_PROC_TTY:
+ PROC_LOCK(p);
if ((p->p_flag & P_CONTROLT) == 0 ||
- p->p_session == NULL ||
- p->p_session->s_ttyp == NULL ||
+ p->p_session == NULL) {
+ PROC_UNLOCK(p);
+ continue;
+ }
+ SESS_LOCK(p->p_session);
+ if (p->p_session->s_ttyp == NULL ||
dev2udev(p->p_session->s_ttyp->t_dev) !=
- (udev_t)name[0])
+ (udev_t)name[0]) {
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
continue;
+ }
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
break;
case KERN_PROC_UID:
diff --git a/sys/kern/kern_prot.c b/sys/kern/kern_prot.c
index 76b0c72..615709e 100644
--- a/sys/kern/kern_prot.c
+++ b/sys/kern/kern_prot.c
@@ -51,12 +51,12 @@
#include <sys/acct.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/malloc.h>
#include <sys/mutex.h>
-#include <sys/proc.h>
#include <sys/sx.h>
+#include <sys/proc.h>
#include <sys/sysproto.h>
#include <sys/jail.h>
-#include <sys/malloc.h>
#include <sys/pioctl.h>
#include <sys/resourcevar.h>
#include <sys/sysctl.h>
@@ -137,10 +137,13 @@ getpgrp(td, uap)
struct getpgrp_args *uap;
{
struct proc *p = td->td_proc;
+ int s;
- mtx_lock(&Giant);
+ s = mtx_lock_giant(kern_giant_proc);
+ PROC_LOCK(p);
td->td_retval[0] = p->p_pgrp->pg_id;
- mtx_unlock(&Giant);
+ PROC_UNLOCK(p);
+ mtx_unlock_giant(s);
return (0);
}
@@ -164,9 +167,11 @@ getpgid(td, uap)
s = mtx_lock_giant(kern_giant_proc);
error = 0;
- if (uap->pid == 0)
+ if (uap->pid == 0) {
+ PROC_LOCK(p);
td->td_retval[0] = p->p_pgrp->pg_id;
- else if ((pt = pfind(uap->pid)) == NULL)
+ PROC_UNLOCK(p);
+ } else if ((pt = pfind(uap->pid)) == NULL)
error = ESRCH;
else {
error = p_cansee(p, pt);
@@ -197,12 +202,15 @@ getsid(td, uap)
struct proc *p = td->td_proc;
struct proc *pt;
int error;
+ int s;
- mtx_lock(&Giant);
+ s = mtx_lock_giant(kern_giant_proc);
error = 0;
- if (uap->pid == 0)
+ if (uap->pid == 0) {
+ PROC_LOCK(p);
td->td_retval[0] = p->p_session->s_sid;
- else if ((pt = pfind(uap->pid)) == NULL)
+ PROC_UNLOCK(p);
+ } else if ((pt = pfind(uap->pid)) == NULL)
error = ESRCH;
else {
error = p_cansee(p, pt);
@@ -210,7 +218,7 @@ getsid(td, uap)
td->td_retval[0] = pt->p_session->s_sid;
PROC_UNLOCK(pt);
}
- mtx_unlock(&Giant);
+ mtx_unlock_giant(s);
return (error);
}
@@ -365,19 +373,44 @@ setsid(td, uap)
register struct thread *td;
struct setsid_args *uap;
{
+ struct pgrp *pgrp;
int error;
struct proc *p = td->td_proc;
+ struct pgrp *newpgrp;
+ struct session *newsess;
+
+ error = 0;
+ pgrp = NULL;
mtx_lock(&Giant);
- if (p->p_pgid == p->p_pid || pgfind(p->p_pid))
+
+ MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
+ MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
+
+ PGRPSESS_XLOCK();
+
+ if (p->p_pgid == p->p_pid || (pgrp = pgfind(p->p_pid)) != NULL) {
+ if (pgrp != NULL)
+ PGRP_UNLOCK(pgrp);
error = EPERM;
- else {
- (void)enterpgrp(p, p->p_pid, 1);
+ goto fail;
+ } else {
+ (void)enterpgrp(p, p->p_pid, newpgrp, newsess);
td->td_retval[0] = p->p_pid;
error = 0;
}
+ PGRPSESS_XUNLOCK();
mtx_unlock(&Giant);
- return (error);
+ return (0);
+
+fail:
+ PGRPSESS_XUNLOCK();
+
+ FREE(newpgrp, M_PGRP);
+ FREE(newsess, M_SESSION);
+
+ mtx_unlock(&Giant);
+ return (0);
}
/*
@@ -412,57 +445,92 @@ setpgid(td, uap)
register struct proc *targp; /* target process */
register struct pgrp *pgrp; /* target pgrp */
int error;
+ struct pgrp *newpgrp;
if (uap->pgid < 0)
return (EINVAL);
+
+ error = 0;
+
mtx_lock(&Giant);
- sx_slock(&proctree_lock);
+
+ MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
+
+ PGRPSESS_XLOCK();
+
if (uap->pid != 0 && uap->pid != curp->p_pid) {
- if ((targp = pfind(uap->pid)) == NULL || !inferior(targp)) {
+ sx_slock(&proctree_lock);
+ if ((targp = pfind(uap->pid)) == NULL) {
if (targp)
PROC_UNLOCK(targp);
+ sx_sunlock(&proctree_lock);
error = ESRCH;
- goto done2;
+ goto fail;
+ }
+ if (!inferior(targp)) {
+ PROC_UNLOCK(targp);
+ sx_sunlock(&proctree_lock);
+ goto fail;
}
+ sx_sunlock(&proctree_lock);
if ((error = p_cansee(curproc, targp))) {
PROC_UNLOCK(targp);
- goto done2;
+ goto fail;
}
if (targp->p_pgrp == NULL ||
targp->p_session != curp->p_session) {
PROC_UNLOCK(targp);
error = EPERM;
- goto done2;
+ goto fail;
}
if (targp->p_flag & P_EXEC) {
PROC_UNLOCK(targp);
error = EACCES;
- goto done2;
+ goto fail;
}
- } else {
+ PROC_UNLOCK(targp);
+ } else
targp = curp;
- PROC_LOCK(curp); /* XXX: not needed */
- }
if (SESS_LEADER(targp)) {
- PROC_UNLOCK(targp);
error = EPERM;
- goto done2;
+ goto fail;
}
if (uap->pgid == 0)
uap->pgid = targp->p_pid;
- else if (uap->pgid != targp->p_pid) {
- if ((pgrp = pgfind(uap->pgid)) == 0 ||
+ if (uap->pgid == targp->p_pid) {
+ if (targp->p_pgid == uap->pgid)
+ goto done;
+ error = enterpgrp(targp, uap->pgid, newpgrp, NULL);
+ if (error == 0)
+ newpgrp = NULL;
+ } else {
+ if ((pgrp = pgfind(uap->pgid)) == NULL ||
pgrp->pg_session != curp->p_session) {
- PROC_UNLOCK(targp);
+ if (pgrp != NULL)
+ PGRP_UNLOCK(pgrp);
error = EPERM;
- goto done2;
+ goto fail;
+ }
+ if (pgrp == targp->p_pgrp) {
+ PGRP_UNLOCK(pgrp);
+ goto done;
}
+ PGRP_UNLOCK(pgrp);
+ error = enterthispgrp(targp, pgrp);
}
- /* XXX: We should probably hold the lock across enterpgrp. */
- PROC_UNLOCK(targp);
- error = enterpgrp(targp, uap->pgid, 0);
-done2:
- sx_sunlock(&proctree_lock);
+done:
+ PGRPSESS_XUNLOCK();
+ if (newpgrp != NULL)
+ FREE(newpgrp, M_PGRP);
+ mtx_unlock(&Giant);
+ return (0);
+
+fail:
+ PGRPSESS_XUNLOCK();
+
+ KASSERT(newpgrp != NULL, ("setpgid failed and newpgrp is null."));
+ FREE(newpgrp, M_PGRP);
+
mtx_unlock(&Giant);
return (error);
}
@@ -1134,7 +1202,9 @@ issetugid(td, uap)
* a user without an exec - programs cannot know *everything*
* that libc *might* have put in their data segment.
*/
+ PROC_LOCK(p);
td->td_retval[0] = (p->p_flag & P_SUGID) ? 1 : 0;
+ PROC_UNLOCK(p);
return (0);
}
@@ -1153,10 +1223,14 @@ __setugid(td, uap)
error = 0;
switch (uap->flag) {
case 0:
+ PROC_LOCK(td->td_proc);
td->td_proc->p_flag &= ~P_SUGID;
+ PROC_UNLOCK(td->td_proc);
break;
case 1:
+ PROC_LOCK(td->td_proc);
td->td_proc->p_flag |= P_SUGID;
+ PROC_UNLOCK(td->td_proc);
break;
default:
error = EINVAL;
@@ -1725,13 +1799,18 @@ getlogin(td, uap)
struct getlogin_args *uap;
{
int error;
+ char login[MAXLOGNAME];
struct proc *p = td->td_proc;
mtx_lock(&Giant);
if (uap->namelen > MAXLOGNAME)
uap->namelen = MAXLOGNAME;
- error = copyout((caddr_t) p->p_pgrp->pg_session->s_login,
- (caddr_t) uap->namebuf, uap->namelen);
+ PROC_LOCK(p);
+ SESS_LOCK(p->p_session);
+ bcopy(p->p_session->s_login, login, uap->namelen);
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
+ error = copyout((caddr_t) login, (caddr_t) uap->namebuf, uap->namelen);
mtx_unlock(&Giant);
return(error);
}
@@ -1764,9 +1843,16 @@ setlogin(td, uap)
sizeof(logintmp), (size_t *)0);
if (error == ENAMETOOLONG)
error = EINVAL;
- else if (!error)
- (void)memcpy(p->p_pgrp->pg_session->s_login, logintmp,
+ else if (!error) {
+ PGRPSESS_XLOCK();
+ PROC_LOCK(p);
+ SESS_LOCK(p->p_session);
+ (void) memcpy(p->p_session->s_login, logintmp,
sizeof(logintmp));
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
+ PGRPSESS_XUNLOCK();
+ }
done2:
mtx_unlock(&Giant);
return (error);
diff --git a/sys/kern/kern_resource.c b/sys/kern/kern_resource.c
index ffcd488..c15c631 100644
--- a/sys/kern/kern_resource.c
+++ b/sys/kern/kern_resource.c
@@ -111,14 +111,25 @@ getpriority(td, uap)
case PRIO_PGRP: {
register struct pgrp *pg;
- if (uap->who == 0)
+ PGRPSESS_SLOCK();
+ if (uap->who == 0) {
pg = curp->p_pgrp;
- else if ((pg = pgfind(uap->who)) == NULL)
- break;
+ PGRP_LOCK(pg);
+ } else {
+ pg = pgfind(uap->who);
+ if (pg == NULL) {
+ PGRPSESS_SUNLOCK();
+ break;
+ }
+ }
+ PGRPSESS_SUNLOCK();
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
+ PROC_LOCK(p);
if (!p_cansee(curp, p) && p->p_ksegrp.kg_nice /* XXXKSE */ < low)
low = p->p_ksegrp.kg_nice /* XXXKSE */ ;
+ PROC_UNLOCK(p);
}
+ PGRP_UNLOCK(pg);
break;
}
@@ -185,16 +196,27 @@ setpriority(td, uap)
case PRIO_PGRP: {
register struct pgrp *pg;
- if (uap->who == 0)
+ PGRPSESS_SLOCK();
+ if (uap->who == 0) {
pg = curp->p_pgrp;
- else if ((pg = pgfind(uap->who)) == NULL)
- break;
+ PGRP_LOCK(pg);
+ } else {
+ pg = pgfind(uap->who);
+ if (pg == NULL) {
+ PGRPSESS_SUNLOCK();
+ break;
+ }
+ }
+ PGRPSESS_SUNLOCK();
LIST_FOREACH(p, &pg->pg_members, p_pglist) {
+ PROC_LOCK(p);
if (!p_cansee(curp, p)) {
error = donice(curp, p, uap->prio);
found++;
}
+ PROC_UNLOCK(p);
}
+ PGRP_UNLOCK(pg);
break;
}
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 27acc64..f871cd5 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1001,16 +1001,21 @@ killpg1(cp, sig, pgid, all)
}
sx_sunlock(&allproc_lock);
} else {
- if (pgid == 0)
+ PGRPSESS_SLOCK();
+ if (pgid == 0) {
/*
* zero pgid means send to my process group.
*/
pgrp = cp->p_pgrp;
- else {
+ PGRP_LOCK(pgrp);
+ } else {
pgrp = pgfind(pgid);
- if (pgrp == NULL)
+ if (pgrp == NULL) {
+ PGRPSESS_SUNLOCK();
return (ESRCH);
+ }
}
+ PGRPSESS_SUNLOCK();
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
PROC_LOCK(p);
if (p->p_pid <= 1 || p->p_flag & P_SYSTEM) {
@@ -1031,6 +1036,7 @@ killpg1(cp, sig, pgid, all)
}
PROC_UNLOCK(p);
}
+ PGRP_UNLOCK(pgrp);
}
return (nfound ? 0 : ESRCH);
}
@@ -1124,8 +1130,15 @@ gsignal(pgid, sig)
{
struct pgrp *pgrp;
- if (pgid && (pgrp = pgfind(pgid)))
- pgsignal(pgrp, sig, 0);
+ if (pgid != 0) {
+ PGRPSESS_SLOCK();
+ pgrp = pgfind(pgid);
+ PGRPSESS_SUNLOCK();
+ if (pgrp != NULL) {
+ pgsignal(pgrp, sig, 0);
+ PGRP_UNLOCK(pgrp);
+ }
+ }
}
/*
@@ -1140,6 +1153,7 @@ pgsignal(pgrp, sig, checkctty)
register struct proc *p;
if (pgrp) {
+ PGRP_LOCK_ASSERT(pgrp, MA_OWNED);
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
PROC_LOCK(p);
if (checkctty == 0 || p->p_flag & P_CONTROLT)
@@ -1351,11 +1365,10 @@ psignal(p, sig)
goto out;
SIGDELSET(p->p_siglist, sig);
p->p_xstat = sig;
- if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) {
- PROC_LOCK(p->p_pptr);
+ PROC_LOCK(p->p_pptr);
+ if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0)
psignal(p->p_pptr, SIGCHLD);
- PROC_UNLOCK(p->p_pptr);
- }
+ PROC_UNLOCK(p->p_pptr);
mtx_lock_spin(&sched_lock);
stop(p);
mtx_unlock_spin(&sched_lock);
@@ -1629,14 +1642,13 @@ issignal(p)
if (prop & SA_STOP) {
if (p->p_flag & P_TRACED ||
(p->p_pgrp->pg_jobc == 0 &&
- prop & SA_TTYSTOP))
+ prop & SA_TTYSTOP))
break; /* == ignore */
p->p_xstat = sig;
- if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) {
- PROC_LOCK(p->p_pptr);
+ PROC_LOCK(p->p_pptr);
+ if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0)
psignal(p->p_pptr, SIGCHLD);
- PROC_UNLOCK(p->p_pptr);
- }
+ PROC_UNLOCK(p->p_pptr);
mtx_lock_spin(&sched_lock);
stop(p);
PROC_UNLOCK(p);
@@ -2074,7 +2086,7 @@ pgsigio(sigio, sig, checkctty)
{
if (sigio == NULL)
return;
-
+
if (sigio->sio_pgid > 0) {
PROC_LOCK(sigio->sio_proc);
if (CANSIGIO(sigio->sio_ucred, sigio->sio_proc->p_ucred))
@@ -2083,6 +2095,7 @@ pgsigio(sigio, sig, checkctty)
} else if (sigio->sio_pgid < 0) {
struct proc *p;
+ PGRP_LOCK(sigio->sio_pgrp);
LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) {
PROC_LOCK(p);
if (CANSIGIO(sigio->sio_ucred, p->p_ucred) &&
@@ -2090,6 +2103,7 @@ pgsigio(sigio, sig, checkctty)
psignal(p, sig);
PROC_UNLOCK(p);
}
+ PGRP_UNLOCK(sigio->sio_pgrp);
}
}
diff --git a/sys/kern/subr_prf.c b/sys/kern/subr_prf.c
index daa38e4..034a63c 100644
--- a/sys/kern/subr_prf.c
+++ b/sys/kern/subr_prf.c
@@ -41,6 +41,9 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
#include <sys/kernel.h>
#include <sys/msgbuf.h>
#include <sys/malloc.h>
@@ -113,16 +116,28 @@ uprintf(const char *fmt, ...)
struct proc *p = td->td_proc;
va_list ap;
struct putchar_arg pca;
- int retval = 0;
+ int retval;
+
+ if (td == NULL || td == PCPU_GET(idlethread))
+ return (0);
- if (td && td != PCPU_GET(idlethread) && p->p_flag & P_CONTROLT &&
- p->p_session->s_ttyvp) {
- va_start(ap, fmt);
- pca.tty = p->p_session->s_ttyp;
- pca.flags = TOTTY;
- retval = kvprintf(fmt, putchar, &pca, 10, ap);
- va_end(ap);
+ p = td->td_proc;
+ PROC_LOCK(p);
+ if ((p->p_flag & P_CONTROLT) == 0) {
+ PROC_UNLOCK(p);
+ return (0);
}
+ SESS_LOCK(p->p_session);
+ pca.tty = p->p_session->s_ttyp;
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
+ if (pca.tty == NULL)
+ return (0);
+ pca.flags = TOTTY;
+ va_start(ap, fmt);
+ retval = kvprintf(fmt, putchar, &pca, 10, ap);
+ va_end(ap);
+
return (retval);
}
@@ -141,13 +156,23 @@ tprintf(struct proc *p, int pri, const char *fmt, ...)
if (pri != -1)
flags |= TOLOG;
- if (p && p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
- SESSHOLD(p->p_session);
- shld++;
- if (ttycheckoutq(p->p_session->s_ttyp, 0)) {
- flags |= TOTTY;
+ if (p != NULL) {
+ PGRPSESS_XLOCK();
+ PROC_LOCK(p);
+ if (p->p_flag & P_CONTROLT && p->p_session->s_ttyvp) {
+ SESS_LOCK(p->p_session);
+ SESSHOLD(p->p_session);
tp = p->p_session->s_ttyp;
- }
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
+ shld++;
+ if (ttycheckoutq(tp, 0))
+ flags |= TOTTY;
+ else
+ tp = NULL;
+ } else
+ PROC_UNLOCK(p);
+ PGRPSESS_XUNLOCK();
}
pca.pri = pri;
pca.tty = tp;
@@ -155,8 +180,13 @@ tprintf(struct proc *p, int pri, const char *fmt, ...)
va_start(ap, fmt);
retval = kvprintf(fmt, putchar, &pca, 10, ap);
va_end(ap);
- if (shld)
+ if (shld) {
+ PGRPSESS_XLOCK();
+ SESS_LOCK(p->p_session);
SESSRELE(p->p_session);
+ SESS_UNLOCK(p->p_session);
+ PGRPSESS_XUNLOCK();
+ }
msgbuftrigger = 1;
}
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 4bb6a70..39e3243 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -188,9 +188,12 @@ static struct lock_list_entry w_locklistdata[LOCK_CHILDCOUNT];
static struct witness_order_list_entry order_lists[] = {
{ "Giant", &lock_class_mtx_sleep },
+ { "pgrpsess", &lock_class_sx },
{ "proctree", &lock_class_sx },
{ "allproc", &lock_class_sx },
+ { "process group", &lock_class_mtx_sleep },
{ "process lock", &lock_class_mtx_sleep },
+ { "session", &lock_class_mtx_sleep },
{ "uidinfo hash", &lock_class_mtx_sleep },
{ "uidinfo struct", &lock_class_mtx_sleep },
{ NULL, NULL },
@@ -227,6 +230,7 @@ static struct witness_order_list_entry order_lists[] = {
static const char *dup_list[] = {
"process lock",
+ "process group",
NULL
};
diff --git a/sys/kern/sys_process.c b/sys/kern/sys_process.c
index 018734e..e15f191 100644
--- a/sys/kern/sys_process.c
+++ b/sys/kern/sys_process.c
@@ -515,10 +515,10 @@ ptrace(struct thread *td, struct ptrace_args *uap)
struct proc *pp;
pp = pfind(p->p_oppid);
- if (pp != NULL)
- PROC_UNLOCK(pp);
- else
+ if (pp == NULL)
pp = initproc;
+ else
+ PROC_UNLOCK(pp);
PROC_LOCK(p);
proc_reparent(p, pp);
} else
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 5c778b7..2ca162a 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -75,6 +75,7 @@
#include <sys/filio.h>
#include <sys/lock.h>
#include <sys/mutex.h>
+#include <sys/sx.h>
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
#include <sys/ioctl_compat.h>
#endif
@@ -328,7 +329,11 @@ ttyinput(c, tp)
return (0);
if (ISSET(iflag, BRKINT)) {
ttyflush(tp, FREAD | FWRITE);
- pgsignal(tp->t_pgrp, SIGINT, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGINT, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
goto endcase;
}
if (ISSET(iflag, PARMRK))
@@ -406,15 +411,23 @@ parmrk:
if (!ISSET(lflag, NOFLSH))
ttyflush(tp, FREAD | FWRITE);
ttyecho(c, tp);
- pgsignal(tp->t_pgrp,
- CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp,
+ CCEQ(cc[VINTR], c) ? SIGINT : SIGQUIT, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
goto endcase;
}
if (CCEQ(cc[VSUSP], c)) {
if (!ISSET(lflag, NOFLSH))
ttyflush(tp, FREAD);
ttyecho(c, tp);
- pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
goto endcase;
}
}
@@ -532,8 +545,11 @@ parmrk:
* ^T - kernel info and generate SIGINFO
*/
if (CCEQ(cc[VSTATUS], c) && ISSET(lflag, IEXTEN)) {
- if (ISSET(lflag, ISIG))
+ if (ISSET(lflag, ISIG) && tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
pgsignal(tp->t_pgrp, SIGINFO, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
if (!ISSET(lflag, NOKERNINFO))
ttyinfo(tp);
goto endcase;
@@ -752,17 +768,30 @@ ttioctl(tp, cmd, data, flag)
case TIOCSETP:
case TIOCSLTC:
#endif
+ PGRPSESS_SLOCK();
+ PROC_LOCK(p);
while (isbackground(p, tp) && !(p->p_flag & P_PPWAIT) &&
!SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
!SIGISMEMBER(p->p_sigmask, SIGTTOU)) {
- if (p->p_pgrp->pg_jobc == 0)
+ if (p->p_pgrp->pg_jobc == 0) {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
return (EIO);
+ }
+ PROC_UNLOCK(p);
+ PGRP_LOCK(p->p_pgrp);
pgsignal(p->p_pgrp, SIGTTOU, 1);
+ PGRP_UNLOCK(p->p_pgrp);
error = ttysleep(tp, &lbolt, TTOPRI | PCATCH, "ttybg1",
0);
- if (error)
+ if (error) {
+ PGRPSESS_SUNLOCK();
return (error);
+ }
+ PROC_LOCK(p);
}
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
break;
}
@@ -1012,22 +1041,44 @@ ttioctl(tp, cmd, data, flag)
break;
case TIOCSCTTY: /* become controlling tty */
/* Session ctty vnode pointer set in vnode layer. */
+ PGRPSESS_XLOCK();
if (!SESS_LEADER(p) ||
((p->p_session->s_ttyvp || tp->t_session) &&
- (tp->t_session != p->p_session)))
+ (tp->t_session != p->p_session))) {
+ PGRPSESS_XUNLOCK();
return (EPERM);
+ }
tp->t_session = p->p_session;
tp->t_pgrp = p->p_pgrp;
+ SESS_LOCK(p->p_session);
p->p_session->s_ttyp = tp;
+ SESS_UNLOCK(p->p_session);
+ PROC_LOCK(p);
p->p_flag |= P_CONTROLT;
+ PROC_UNLOCK(p);
+ PGRPSESS_XUNLOCK();
break;
case TIOCSPGRP: { /* set pgrp of tty */
- register struct pgrp *pgrp = pgfind(*(int *)data);
-
- if (!isctty(p, tp))
+ register struct pgrp *pgrp;
+
+ PGRPSESS_SLOCK();
+ pgrp = pgfind(*(int *)data);
+ if (!isctty(p, tp)) {
+ if (pgrp != NULL)
+ PGRP_UNLOCK(pgrp);
+ PGRPSESS_SUNLOCK();
return (ENOTTY);
- else if (pgrp == NULL || pgrp->pg_session != p->p_session)
+ }
+ if (pgrp == NULL) {
+ PGRPSESS_SUNLOCK();
return (EPERM);
+ }
+ PGRP_UNLOCK(pgrp);
+ if (pgrp->pg_session != p->p_session) {
+ PGRPSESS_SUNLOCK();
+ return (EPERM);
+ }
+ PGRPSESS_SUNLOCK();
tp->t_pgrp = pgrp;
break;
}
@@ -1040,7 +1091,11 @@ ttioctl(tp, cmd, data, flag)
if (bcmp((caddr_t)&tp->t_winsize, data,
sizeof (struct winsize))) {
tp->t_winsize = *(struct winsize *)data;
- pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGWINCH, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
}
break;
case TIOCSDRAINWAIT:
@@ -1459,13 +1514,17 @@ ttymodem(tp, flag)
!ISSET(tp->t_cflag, CLOCAL)) {
SET(tp->t_state, TS_ZOMBIE);
CLR(tp->t_state, TS_CONNECTED);
- if (tp->t_session && tp->t_session->s_leader) {
- struct proc *p;
-
- p = tp->t_session->s_leader;
- PROC_LOCK(p);
- psignal(p, SIGHUP);
- PROC_UNLOCK(p);
+ if (tp->t_session) {
+ PGRPSESS_SLOCK();
+ if (tp->t_session->s_leader) {
+ struct proc *p;
+
+ p = tp->t_session->s_leader;
+ PROC_LOCK(p);
+ psignal(p, SIGHUP);
+ PROC_UNLOCK(p);
+ }
+ PGRPSESS_SUNLOCK();
}
ttyflush(tp, FREAD | FWRITE);
return (0);
@@ -1549,11 +1608,20 @@ loop:
*/
if (isbackground(p, tp)) {
splx(s);
+ PGRPSESS_SLOCK();
+ PROC_LOCK(p);
if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
- (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0)
+ (p->p_flag & P_PPWAIT) || p->p_pgrp->pg_jobc == 0) {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
return (EIO);
+ }
+ PROC_UNLOCK(p);
+ PGRP_LOCK(p->p_pgrp);
+ PGRPSESS_SUNLOCK();
pgsignal(p->p_pgrp, SIGTTIN, 1);
+ PGRP_UNLOCK(p->p_pgrp);
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg2", 0);
if (error)
return (error);
@@ -1727,7 +1795,11 @@ slowcase:
*/
if (CCEQ(cc[VDSUSP], c) &&
ISSET(lflag, IEXTEN | ISIG) == (IEXTEN | ISIG)) {
- pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, SIGTSTP, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
if (first) {
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH,
"ttybg3", 0);
@@ -1855,19 +1927,30 @@ loop:
* Hang the process if it's in the background.
*/
p = curproc;
+ PGRPSESS_SLOCK();
+ PROC_LOCK(p);
if (isbackground(p, tp) &&
ISSET(tp->t_lflag, TOSTOP) && !(p->p_flag & P_PPWAIT) &&
!SIGISMEMBER(p->p_sigignore, SIGTTOU) &&
!SIGISMEMBER(p->p_sigmask, SIGTTOU)) {
if (p->p_pgrp->pg_jobc == 0) {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
error = EIO;
goto out;
}
+ PROC_UNLOCK(p);
+ PGRP_LOCK(p->p_pgrp);
+ PGRPSESS_SUNLOCK();
pgsignal(p->p_pgrp, SIGTTOU, 1);
+ PGRP_UNLOCK(p->p_pgrp);
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ttybg4", 0);
if (error)
goto out;
goto loop;
+ } else {
+ PROC_UNLOCK(p);
+ PGRPSESS_SUNLOCK();
}
/*
* Process the user's data in at most OBUFSIZ chunks. Perform any
@@ -2328,38 +2411,44 @@ ttyinfo(tp)
ttyprintf(tp, "not a controlling terminal\n");
else if (tp->t_pgrp == NULL)
ttyprintf(tp, "no foreground process group\n");
- else if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0)
- ttyprintf(tp, "empty foreground process group\n");
else {
- mtx_lock_spin(&sched_lock);
-
- /* Pick interesting process. */
- for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
- if (proc_compare(pick, p))
- pick = p;
-
- td = FIRST_THREAD_IN_PROC(pick);
- stmp = pick->p_stat == SRUN ? "running" : /* XXXKSE */
- td->td_wmesg ? td->td_wmesg : "iowait";
- calcru(pick, &utime, &stime, NULL);
- ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT ||
- pick->p_stat == SZOMB ? 0 :
- pgtok(vmspace_resident_count(pick->p_vmspace));
- mtx_unlock_spin(&sched_lock);
-
- ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
- stmp);
-
- /* Print user time. */
- ttyprintf(tp, "%ld.%02ldu ",
- (long)utime.tv_sec, utime.tv_usec / 10000);
-
- /* Print system time. */
- ttyprintf(tp, "%ld.%02lds ",
- (long)stime.tv_sec, stime.tv_usec / 10000);
-
- /* Print percentage cpu, resident set size. */
- ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp);
+ PGRP_LOCK(tp->t_pgrp);
+ if ((p = LIST_FIRST(&tp->t_pgrp->pg_members)) == 0) {
+ PGRP_UNLOCK(tp->t_pgrp);
+ ttyprintf(tp, "empty foreground process group\n");
+ } else {
+ PGRP_UNLOCK(tp->t_pgrp);
+ mtx_lock_spin(&sched_lock);
+
+ /* Pick interesting process. */
+ for (pick = NULL; p != 0; p = LIST_NEXT(p, p_pglist))
+ if (proc_compare(pick, p))
+ pick = p;
+
+ td = FIRST_THREAD_IN_PROC(pick);
+ stmp = pick->p_stat == SRUN ? "running" : /* XXXKSE */
+ td->td_wmesg ? td->td_wmesg : "iowait";
+ calcru(pick, &utime, &stime, NULL);
+ ltmp = pick->p_stat == SIDL || pick->p_stat == SWAIT ||
+ pick->p_stat == SZOMB ? 0 :
+ pgtok(vmspace_resident_count(pick->p_vmspace));
+ mtx_unlock_spin(&sched_lock);
+
+ ttyprintf(tp, " cmd: %s %d [%s] ", pick->p_comm, pick->p_pid,
+ stmp);
+
+ /* Print user time. */
+ ttyprintf(tp, "%lld.%02ldu ",
+ utime.tv_sec, utime.tv_usec / 10000);
+
+ /* Print system time. */
+ ttyprintf(tp, "%ld.%02lds ",
+ (long)stime.tv_sec, stime.tv_usec / 10000);
+
+ /* Print percentage cpu, resident set size. */
+ ttyprintf(tp, "%d%% %ldk\n", tmp / 100, ltmp);
+
+ }
}
tp->t_rocount = 0; /* so pending input will be retyped if BS */
}
diff --git a/sys/kern/tty_pty.c b/sys/kern/tty_pty.c
index 6f1c0db..b3fcc8d 100644
--- a/sys/kern/tty_pty.c
+++ b/sys/kern/tty_pty.c
@@ -41,6 +41,9 @@
#include "opt_compat.h"
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
#if defined(COMPAT_43) || defined(COMPAT_SUNOS)
#include <sys/ioctl_compat.h>
#endif
@@ -237,11 +240,19 @@ ptsread(dev, uio, flag)
again:
if (pti->pt_flags & PF_REMOTE) {
while (isbackground(p, tp)) {
+ PGRPSESS_SLOCK();
+ PROC_LOCK(p);
if (SIGISMEMBER(p->p_sigignore, SIGTTIN) ||
SIGISMEMBER(p->p_sigmask, SIGTTIN) ||
- p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT)
+ p->p_pgrp->pg_jobc == 0 || p->p_flag & P_PPWAIT) {
+ PROC_UNLOCK(p);
return (EIO);
+ }
+ PROC_UNLOCK(p);
+ PGRP_LOCK(p->p_pgrp);
+ PGRPSESS_SUNLOCK();
pgsignal(p->p_pgrp, SIGTTIN, 1);
+ PGRP_UNLOCK(p->p_pgrp);
error = ttysleep(tp, &lbolt, TTIPRI | PCATCH, "ptsbg",
0);
if (error)
@@ -715,7 +726,11 @@ ptyioctl(dev, cmd, data, flag, td)
return(EINVAL);
if ((tp->t_lflag&NOFLSH) == 0)
ttyflush(tp, FREAD|FWRITE);
- pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
+ if (tp->t_pgrp != NULL) {
+ PGRP_LOCK(tp->t_pgrp);
+ pgsignal(tp->t_pgrp, *(unsigned int *)data, 1);
+ PGRP_UNLOCK(tp->t_pgrp);
+ }
if ((*(unsigned int *)data == SIGINFO) &&
((tp->t_lflag&NOKERNINFO) == 0))
ttyinfo(tp);
diff --git a/sys/kern/tty_tty.c b/sys/kern/tty_tty.c
index 1c6635c..931da01 100644
--- a/sys/kern/tty_tty.c
+++ b/sys/kern/tty_tty.c
@@ -43,6 +43,8 @@
#include <sys/conf.h>
#include <sys/kernel.h>
#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
#include <sys/proc.h>
#include <sys/ttycom.h>
#include <sys/vnode.h>
@@ -80,9 +82,15 @@ cttyopen(dev, flag, mode, td)
int flag, mode;
struct thread *td;
{
- struct vnode *ttyvp = cttyvp(td);
+ struct vnode *ttyvp;
int error;
+ PROC_LOCK(td->td_proc);
+ SESS_LOCK(td->td_proc->p_session);
+ ttyvp = cttyvp(td);
+ SESS_UNLOCK(td->td_proc->p_session);
+ PROC_UNLOCK(td->td_proc);
+
if (ttyvp == NULL)
return (ENXIO);
vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
@@ -99,9 +107,15 @@ cttyread(dev, uio, flag)
int flag;
{
struct thread *td = uio->uio_td;
- register struct vnode *ttyvp = cttyvp(td);
+ register struct vnode *ttyvp;
int error;
+ PROC_LOCK(td->td_proc);
+ SESS_LOCK(td->td_proc->p_session);
+ ttyvp = cttyvp(td);
+ SESS_UNLOCK(td->td_proc->p_session);
+ PROC_UNLOCK(td->td_proc);
+
if (ttyvp == NULL)
return (EIO);
vn_lock(ttyvp, LK_EXCLUSIVE | LK_RETRY, td);
@@ -118,10 +132,16 @@ cttywrite(dev, uio, flag)
int flag;
{
struct thread *td = uio->uio_td;
- struct vnode *ttyvp = cttyvp(uio->uio_td);
+ struct vnode *ttyvp;
struct mount *mp;
int error;
+ PROC_LOCK(td->td_proc);
+ SESS_LOCK(td->td_proc->p_session);
+ ttyvp = cttyvp(td);
+ SESS_UNLOCK(td->td_proc->p_session);
+ PROC_UNLOCK(td->td_proc);
+
if (ttyvp == NULL)
return (EIO);
mp = NULL;
@@ -144,18 +164,30 @@ cttyioctl(dev, cmd, addr, flag, td)
int flag;
struct thread *td;
{
- struct vnode *ttyvp = cttyvp(td);
+ struct vnode *ttyvp;
+ int error;
+
+ PROC_LOCK(td->td_proc);
+ SESS_LOCK(td->td_proc->p_session);
+ ttyvp = cttyvp(td);
+ SESS_UNLOCK(td->td_proc->p_session);
+ PROC_UNLOCK(td->td_proc);
if (ttyvp == NULL)
return (EIO);
if (cmd == TIOCSCTTY) /* don't allow controlling tty to be set */
return EINVAL; /* to controlling tty -- infinite recursion */
if (cmd == TIOCNOTTY) {
- if (!SESS_LEADER(td->td_proc)) {
+ PROC_LOCK(td->td_proc);
+ SESS_LOCK(td->td_proc->p_session);
+ error = 0;
+ if (!SESS_LEADER(td->td_proc))
td->td_proc->p_flag &= ~P_CONTROLT;
- return (0);
- } else
- return (EINVAL);
+ else
+ error = EINVAL;
+ SESS_UNLOCK(td->td_proc->p_session);
+ PROC_UNLOCK(td->td_proc);
+ return (error);
}
return (VOP_IOCTL(ttyvp, cmd, addr, flag, NOCRED, td));
}
@@ -167,7 +199,13 @@ cttypoll(dev, events, td)
int events;
struct thread *td;
{
- struct vnode *ttyvp = cttyvp(td);
+ struct vnode *ttyvp;
+
+ PROC_LOCK(td->td_proc);
+ SESS_LOCK(td->td_proc->p_session);
+ ttyvp = cttyvp(td);
+ SESS_UNLOCK(td->td_proc->p_session);
+ PROC_UNLOCK(td->td_proc);
if (ttyvp == NULL)
/* try operation to get EOF/failure */
diff --git a/sys/kern/vfs_aio.c b/sys/kern/vfs_aio.c
index 3acdf2b..84c1408 100644
--- a/sys/kern/vfs_aio.c
+++ b/sys/kern/vfs_aio.c
@@ -22,6 +22,7 @@
#include <sys/param.h>
#include <sys/systm.h>
+#include <sys/malloc.h>
#include <sys/bio.h>
#include <sys/buf.h>
#include <sys/sysproto.h>
@@ -741,6 +742,8 @@ aio_daemon(void *uproc)
struct proc *curcp, *mycp, *userp;
struct vmspace *myvm, *tmpvm;
struct thread *td = curthread;
+ struct pgrp *newpgrp;
+ struct session *newsess;
mtx_lock(&Giant);
/*
@@ -781,7 +784,12 @@ aio_daemon(void *uproc)
mycp->p_fd = NULL;
/* The daemon resides in its own pgrp. */
- enterpgrp(mycp, mycp->p_pid, 1);
+ MALLOC(newpgrp, struct pgrp *, sizeof(struct pgrp), M_PGRP, M_WAITOK | M_ZERO);
+ MALLOC(newsess, struct session *, sizeof(struct session), M_SESSION, M_WAITOK | M_ZERO);
+
+ PGRPSESS_XLOCK();
+ enterpgrp(mycp, mycp->p_pid, newpgrp, newsess);
+ PGRPSESS_XUNLOCK();
/* Mark special process type. */
mycp->p_flag |= P_SYSTEM;
diff --git a/sys/kern/vfs_vnops.c b/sys/kern/vfs_vnops.c
index aba87d4..ab3e3c9 100644
--- a/sys/kern/vfs_vnops.c
+++ b/sys/kern/vfs_vnops.c
@@ -619,6 +619,7 @@ vn_ioctl(fp, com, data, td)
struct thread *td;
{
register struct vnode *vp = ((struct vnode *)fp->f_data);
+ struct vnode *vpold;
struct vattr vattr;
int error;
@@ -656,15 +657,23 @@ vn_ioctl(fp, com, data, td)
if (error == 0 && com == TIOCSCTTY) {
/* Do nothing if reassigning same control tty */
- if (td->td_proc->p_session->s_ttyvp == vp)
+ PGRPSESS_XLOCK();
+ if (td->td_proc->p_session->s_ttyvp == vp) {
+ PGRPSESS_XUNLOCK();
return (0);
+ }
- /* Get rid of reference to old control tty */
- if (td->td_proc->p_session->s_ttyvp)
- vrele(td->td_proc->p_session->s_ttyvp);
-
- td->td_proc->p_session->s_ttyvp = vp;
+ vpold = td->td_proc->p_session->s_ttyvp;
VREF(vp);
+ SESS_LOCK(td->td_proc->p_session);
+ td->td_proc->p_session->s_ttyvp = vp;
+ SESS_UNLOCK(td->td_proc->p_session);
+
+ PGRPSESS_XUNLOCK();
+
+ /* Get rid of reference to old control tty */
+ if (vpold)
+ vrele(vpold);
}
return (error);
}
diff --git a/sys/net/if_sl.c b/sys/net/if_sl.c
index 228f396..c2e0e17 100644
--- a/sys/net/if_sl.c
+++ b/sys/net/if_sl.c
@@ -83,6 +83,7 @@
#include <sys/kernel.h>
#include <sys/conf.h>
#include <sys/module.h>
+#include <sys/proc.h>
#include <net/if.h>
#include <net/if_types.h>
@@ -1076,9 +1077,13 @@ sl_keepalive(chan)
struct sl_softc *sc = chan;
if (sc->sc_keepalive) {
- if (sc->sc_flags & SC_KEEPALIVE)
- pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1);
- else
+ if (sc->sc_flags & SC_KEEPALIVE) {
+ if (sc->sc_ttyp->t_pgrp != NULL) {
+ PGRP_LOCK(sc->sc_ttyp->t_pgrp);
+ pgsignal (sc->sc_ttyp->t_pgrp, SIGURG, 1);
+ PGRP_UNLOCK(sc->sc_ttyp->t_pgrp);
+ }
+ } else
sc->sc_flags |= SC_KEEPALIVE;
sc->sc_kahandle = timeout(sl_keepalive, sc, sc->sc_keepalive);
} else {
diff --git a/sys/netkey/key.c b/sys/netkey/key.c
index 4236081..12b9401 100644
--- a/sys/netkey/key.c
+++ b/sys/netkey/key.c
@@ -7306,14 +7306,24 @@ key_getuserfqdn()
struct proc *p = curproc;
char *q;
- if (!p || !p->p_pgrp || !p->p_pgrp->pg_session)
+ if (p == NULL)
return NULL;
- if (!(host = key_getfqdn()))
+ bzero(userfqdn, sizeof(userfqdn));
+ if (!(host = key_getfqdn())) {
+ PROC_UNLOCK(p);
+ return NULL;
+ }
+ PROC_LOCK(p);
+ if (!p->p_pgrp || !p->p_pgrp->pg_session) {
+ PROC_UNLOCK(p);
return NULL;
+ }
/* NOTE: s_login may not be-NUL terminated. */
- bzero(userfqdn, sizeof(userfqdn));
- bcopy(p->p_pgrp->pg_session->s_login, userfqdn, MAXLOGNAME);
+ SESS_LOCK(p->p_session);
+ bcopy(p->p_session->s_login, userfqdn, MAXLOGNAME);
+ SESS_UNLOCK(p->p_session);
+ PROC_UNLOCK(p);
userfqdn[MAXLOGNAME] = '\0'; /* safeguard */
q = userfqdn + strlen(userfqdn);
*q++ = '@';
diff --git a/sys/sys/file.h b/sys/sys/file.h
index b8a17c2..fac4848 100644
--- a/sys/sys/file.h
+++ b/sys/sys/file.h
@@ -37,6 +37,10 @@
#ifndef _SYS_FILE_H_
#define _SYS_FILE_H_
+#include <sys/systm.h>
+#include <sys/lock.h>
+#include <sys/mutex.h>
+#include <sys/sx.h>
#ifndef _KERNEL
#include <sys/fcntl.h>
#include <sys/unistd.h>
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index ae2ea4e..ef833fbf 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -110,17 +110,20 @@ struct filedesc0 {
* on a device or socket. The structure is placed on an SLIST belonging
* to the proc or pgrp so that the entire list may be revoked when the
* process exits or the process group disappears.
+ *
+ * (c) const
+ * (pg) locked by either the process or process group lock
*/
struct sigio {
union {
- struct proc *siu_proc; /* process to receive SIGIO/SIGURG */
- struct pgrp *siu_pgrp; /* process group to receive ... */
+ struct proc *siu_proc; /* (c) process to receive SIGIO/SIGURG */
+ struct pgrp *siu_pgrp; /* (c) process group to receive ... */
} sio_u;
- SLIST_ENTRY(sigio) sio_pgsigio; /* sigio's for process or group */
- struct sigio **sio_myref; /* location of the pointer that holds
- * the reference to this structure */
- struct ucred *sio_ucred; /* current credentials */
- pid_t sio_pgid; /* pgid for signals */
+ SLIST_ENTRY(sigio) sio_pgsigio; /* (pg) sigio's for process or group */
+ struct sigio **sio_myref; /* (c) location of the pointer that holds
+ * the reference to this structure */
+ struct ucred *sio_ucred; /* (c) current credentials */
+ pid_t sio_pgid; /* (c) pgid for signals */
};
#define sio_proc sio_u.siu_proc
#define sio_pgrp sio_u.siu_pgrp
diff --git a/sys/sys/proc.h b/sys/sys/proc.h
index fd18f1b..02ddfe4 100644
--- a/sys/sys/proc.h
+++ b/sys/sys/proc.h
@@ -60,27 +60,39 @@
/*
* One structure allocated per session.
+ *
+ * List of locks
+ * (m) locked by s_mtx mtx
+ * (ps) locked by pgrpsess_lock sx
+ * (c) const until freeing
*/
struct session {
- int s_count; /* Ref cnt; pgrps in session. */
- struct proc *s_leader; /* Session leader. */
- struct vnode *s_ttyvp; /* Vnode of controlling terminal. */
- struct tty *s_ttyp; /* Controlling terminal. */
- pid_t s_sid; /* Session ID. */
- /* Setlogin() name: */
+ int s_count; /* (m) Ref cnt; pgrps in session. */
+ struct proc *s_leader; /* (m, ps) Session leader. */
+ struct vnode *s_ttyvp; /* (m) Vnode of controlling terminal. */
+ struct tty *s_ttyp; /* (m) Controlling terminal. */
+ pid_t s_sid; /* (c) Session ID. */
+ /* (m) Setlogin() name: */
char s_login[roundup(MAXLOGNAME, sizeof(long))];
+ struct mtx s_mtx; /* Mutex to protect members */
};
/*
* One structure allocated per process group.
+ *
+ * List of locks
+ * (m) locked by pg_mtx mtx
+ * (ps) locked by pgrpsess_lock sx
+ * (c) const until freeing
*/
struct pgrp {
- LIST_ENTRY(pgrp) pg_hash; /* Hash chain. */
- LIST_HEAD(, proc) pg_members; /* Pointer to pgrp members. */
- struct session *pg_session; /* Pointer to session. */
- struct sigiolst pg_sigiolst; /* List of sigio sources. */
- pid_t pg_id; /* Pgrp id. */
- int pg_jobc; /* # procs qualifying pgrp for job control */
+ LIST_ENTRY(pgrp) pg_hash; /* (ps) Hash chain. */
+ LIST_HEAD(, proc) pg_members; /* (m, ps) Pointer to pgrp members. */
+ struct session *pg_session; /* (c) Pointer to session. */
+ struct sigiolst pg_sigiolst; /* (m) List of sigio sources. */
+ pid_t pg_id; /* (c) Pgrp id. */
+ int pg_jobc; /* (m) # procs qualifying pgrp for job control */
+ struct mtx pg_mtx; /* Mutex to protect members */
};
struct procsig {
@@ -134,6 +146,7 @@ struct pargs {
* l - the attaching proc or attaching proc parent
* m - Giant
* n - not locked, lazy
+ * o - locked by pgrpsess_lock sx
*
* If the locking key specifies two identifiers (for example, p_pptr) then
* either lock is sufficient for read access, but both locks must be held
@@ -388,7 +401,7 @@ struct proc {
pid_t p_pid; /* (b) Process identifier. */
LIST_ENTRY(proc) p_hash; /* (d) Hash chain. */
- LIST_ENTRY(proc) p_pglist; /* (c) List of processes in pgrp. */
+ LIST_ENTRY(proc) p_pglist; /* (g + o) List of processes in pgrp. */
struct proc *p_pptr; /* (c + e) Pointer to parent process. */
LIST_ENTRY(proc) p_sibling; /* (e) List of sibling processes. */
LIST_HEAD(, proc) p_children; /* (e) Pointer to list of children. */
@@ -406,7 +419,7 @@ struct proc {
struct vnode *p_textvp; /* (b) Vnode of executable. */
struct mtx p_mtx; /* (k) Lock for this struct. */
char p_lock; /* (c) Proclock (prevent swap) count. */
- struct klist p_klist; /* (c) Knotes attached to this proc. */
+ struct klist p_klist; /* (c) Knotes attached to this proc. */
struct sigiolst p_sigiolst; /* (c) List of sigio sources. */
int p_sigparent; /* (c) Signal to parent on exit. */
sigset_t p_oldsigmask; /* (c) Saved mask from pre sigpause. */
@@ -427,7 +440,7 @@ struct proc {
stack_t p_sigstk; /* (c) Stack ptr and on-stack flag. */
int p_magic; /* (b) Magic number. */
char p_comm[MAXCOMLEN + 1]; /* (b) Process name. */
- struct pgrp *p_pgrp; /* (e?/c?) Pointer to process group. */
+ struct pgrp *p_pgrp; /* (c + o) Pointer to process group. */
struct sysentvec *p_sysent; /* (b) Syscall dispatch info. */
struct pargs *p_args; /* (c) Process arguments. */
/* End area that is copied on creation. */
@@ -515,6 +528,7 @@ struct proc {
#ifdef MALLOC_DECLARE
MALLOC_DECLARE(M_PARGS);
+MALLOC_DECLARE(M_PGRP);
MALLOC_DECLARE(M_SESSION);
MALLOC_DECLARE(M_SUBPROC);
MALLOC_DECLARE(M_ZOMBIE);
@@ -599,6 +613,40 @@ sigonstack(size_t sp)
#define PROC_LOCKED(p) mtx_owned(&(p)->p_mtx)
#define PROC_LOCK_ASSERT(p, type) mtx_assert(&(p)->p_mtx, (type))
+#define PGRPSESS_SLOCK() sx_slock(&pgrpsess_lock)
+#define PGRPSESS_XLOCK() sx_xlock(&pgrpsess_lock)
+#define PGRPSESS_SUNLOCK() sx_sunlock(&pgrpsess_lock)
+#define PGRPSESS_XUNLOCK() sx_xunlock(&pgrpsess_lock)
+#define PGRPSESS_LOCK_ASSERT(type) sx_assert(&pgrpsess_lock, (type))
+
+/* Lock and unlock a process group. */
+#define PGRP_LOCK(pg) mtx_lock(&(pg)->pg_mtx)
+#define PGRP_UNLOCK(pg) mtx_unlock(&(pg)->pg_mtx)
+#define PGRP_UNLOCK_NOSWITCH(pg) \
+ mtx_unlock_flags(&(pg)->pg_mtx, MTX_NOSWITCH)
+#define PGRP_LOCKED(pg) mtx_owned(&(pg)->pg_mtx)
+#define PGRP_LOCK_ASSERT(pg, type) mtx_assert(&(pg)->pg_mtx, (type))
+
+#define PGRP_LOCK_PGSIGNAL(pg) \
+ do { \
+ if ((pg) != NULL) \
+ PGRP_LOCK(pg); \
+ } while (0);
+
+#define PGRP_UNLOCK_PGSIGNAL(pg) \
+ do { \
+ if ((pg) != NULL) \
+ PGRP_UNLOCK(pg); \
+ } while (0);
+
+/* Lock and unlock a session. */
+#define SESS_LOCK(s) mtx_lock(&(s)->s_mtx)
+#define SESS_UNLOCK(s) mtx_unlock(&(s)->s_mtx)
+#define SESS_UNLOCK_NOSWITCH(s) \
+ mtx_unlock_flags(&(s)->s_mtx, MTX_NOSWITCH)
+#define SESS_LOCKED(s) mtx_owned(&(s)->s_mtx)
+#define SESS_LOCK_ASSERT(s, type) mtx_assert(&(s)->s_mtx, (type))
+
/* Hold process U-area in memory, normally for ptrace/procfs work. */
#define PHOLD(p) do { \
PROC_LOCK(p); \
@@ -631,6 +679,7 @@ extern u_long pgrphash;
extern struct sx allproc_lock;
extern struct sx proctree_lock;
+extern struct sx pgrpsess_lock;
extern struct proc proc0; /* Process slot for swapper. */
extern struct thread thread0; /* Primary thread in proc0 */
extern int hogticks; /* Limit on kernel cpu hogs. */
@@ -672,7 +721,8 @@ struct proc *zpfind(pid_t); /* Find zombie process by id. */
void ast(struct trapframe *framep);
struct thread *choosethread(void);
int cr_cansignal(struct ucred *cred, struct proc *proc, int signum);
-int enterpgrp(struct proc *p, pid_t pgid, int mksess);
+int enterpgrp __P((struct proc *p, pid_t pgid, struct pgrp *pgrp, struct session *sess));
+int enterthispgrp __P((struct proc *p, struct pgrp *pgrp));
void faultin(struct proc *p);
void fixjobc(struct proc *p, struct pgrp *pgrp, int entering);
int fork1(struct thread *, int, struct proc **);
OpenPOWER on IntegriCloud