summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_descrip.c
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/kern/kern_descrip.c
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/kern/kern_descrip.c')
-rw-r--r--sys/kern/kern_descrip.c109
1 files changed, 91 insertions, 18 deletions
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);
}
/*
OpenPOWER on IntegriCloud