summaryrefslogtreecommitdiffstats
path: root/sys/kern
diff options
context:
space:
mode:
authoralfred <alfred@FreeBSD.org>2002-05-06 19:31:28 +0000
committeralfred <alfred@FreeBSD.org>2002-05-06 19:31:28 +0000
commitd1e340364b9883eebdfb4928891b438172fe13fb (patch)
tree2b65f57e5ea93f67973ae506e853d0b56f0f9adc /sys/kern
parent06d090201082aed150ddddb16d8da5721b05c296 (diff)
downloadFreeBSD-src-d1e340364b9883eebdfb4928891b438172fe13fb.zip
FreeBSD-src-d1e340364b9883eebdfb4928891b438172fe13fb.tar.gz
Make funsetown() take a 'struct sigio **' so that the locking can
be done internally. Ensure that no one can fsetown() to a dying process/pgrp. We need to check the process for P_WEXIT to see if it's exiting. Process groups are already safe because there is no such thing as a pgrp zombie, therefore the proctree lock completely protects the pgrp from having sigio structures associated with it after it runs funsetownlst. Add sigio lock to witness list under proctree and allproc, but over proc and pgrp. Seigo Tanimura helped with this.
Diffstat (limited to 'sys/kern')
-rw-r--r--sys/kern/kern_descrip.c71
-rw-r--r--sys/kern/kern_exit.c4
-rw-r--r--sys/kern/kern_proc.c5
-rw-r--r--sys/kern/subr_log.c2
-rw-r--r--sys/kern/subr_witness.c1
-rw-r--r--sys/kern/sys_pipe.c2
-rw-r--r--sys/kern/tty.c2
-rw-r--r--sys/kern/uipc_socket.c2
8 files changed, 51 insertions, 38 deletions
diff --git a/sys/kern/kern_descrip.c b/sys/kern/kern_descrip.c
index 3e15012..e03c09f 100644
--- a/sys/kern/kern_descrip.c
+++ b/sys/kern/kern_descrip.c
@@ -534,17 +534,18 @@ do_dup(fdp, old, new, retval, td)
* free sigio.
*/
void
-funsetown(sigio)
- struct sigio *sigio;
+funsetown(sigiop)
+ struct sigio **sigiop;
{
+ struct sigio *sigio;
SIGIO_LOCK();
+ sigio = *sigiop;
if (sigio == NULL) {
SIGIO_UNLOCK();
return;
}
*(sigio->sio_myref) = NULL;
- SIGIO_UNLOCK();
if ((sigio)->sio_pgid < 0) {
struct pgrp *pg = (sigio)->sio_pgrp;
PGRP_LOCK(pg);
@@ -558,11 +559,17 @@ funsetown(sigio)
sigio, sio_pgsigio);
PROC_UNLOCK(p);
}
+ SIGIO_UNLOCK();
crfree(sigio->sio_ucred);
FREE(sigio, M_SIGIO);
}
-/* Free a list of sigio structures. */
+/*
+ * Free a list of sigio structures.
+ * We only need to lock the SIGIO_LOCK because we have made ourselves
+ * inaccessable to callers of fsetown and therefore do not need to lock
+ * the proc or pgrp struct for the list manipulation.
+ */
void
funsetownlst(sigiolst)
struct sigiolst *sigiolst;
@@ -571,8 +578,6 @@ funsetownlst(sigiolst)
struct proc *p;
struct pgrp *pg;
- SIGIO_ASSERT(MA_OWNED);
-
sigio = SLIST_FIRST(sigiolst);
if (sigio == NULL)
return;
@@ -586,36 +591,40 @@ funsetownlst(sigiolst)
*/
if (sigio->sio_pgid < 0) {
pg = sigio->sio_pgrp;
- PGRP_LOCK_ASSERT(pg, MA_OWNED);
+ PGRP_LOCK_ASSERT(pg, MA_NOTOWNED);
} else /* if (sigio->sio_pgid > 0) */ {
p = sigio->sio_proc;
- PROC_LOCK_ASSERT(p, MA_OWNED);
+ PROC_LOCK_ASSERT(p, MA_NOTOWNED);
}
+ SIGIO_LOCK();
while ((sigio = SLIST_FIRST(sigiolst)) != NULL) {
*(sigio->sio_myref) = NULL;
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);
- SIGIO_UNLOCK();
- crfree(sigio->sio_ucred);
- FREE(sigio, M_SIGIO);
- SIGIO_LOCK();
+ KASSERT(sigio->sio_pgid < 0,
+ ("Proc sigio in pgrp sigio list"));
+ KASSERT(sigio->sio_pgrp == pg,
+ ("Bogus pgrp in sigio list"));
PGRP_LOCK(pg);
+ SLIST_REMOVE(&pg->pg_sigiolst, sigio, sigio,
+ sio_pgsigio);
+ PGRP_UNLOCK(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);
- SIGIO_UNLOCK();
- crfree(sigio->sio_ucred);
- FREE(sigio, M_SIGIO);
- SIGIO_LOCK();
+ KASSERT(sigio->sio_pgid > 0,
+ ("Pgrp sigio in proc sigio list"));
+ KASSERT(sigio->sio_proc == p,
+ ("Bogus proc in sigio list"));
PROC_LOCK(p);
+ SLIST_REMOVE(&p->p_sigiolst, sigio, sigio,
+ sio_pgsigio);
+ PROC_UNLOCK(p);
}
+ SIGIO_UNLOCK();
+ crfree(sigio->sio_ucred);
+ FREE(sigio, M_SIGIO);
+ SIGIO_LOCK();
}
+ SIGIO_UNLOCK();
}
/*
@@ -635,7 +644,7 @@ fsetown(pgid, sigiop)
int ret;
if (pgid == 0) {
- funsetown(*sigiop);
+ funsetown(sigiop);
return (0);
}
@@ -693,9 +702,19 @@ fsetown(pgid, sigiop)
proc = NULL;
}
- funsetown(*sigiop);
+ funsetown(sigiop);
if (pgid > 0) {
PROC_LOCK(proc);
+ /*
+ * since funsetownlst() is called without the proctree
+ * locked we need to check for P_WEXIT.
+ * XXX: is ESRCH correct?
+ */
+ if ((proc->p_flag & P_WEXIT) != 0) {
+ PROC_UNLOCK(proc);
+ ret = ESRCH;
+ goto fail;
+ }
SLIST_INSERT_HEAD(&proc->p_sigiolst, sigio, sio_pgsigio);
sigio->sio_proc = proc;
PROC_UNLOCK(proc);
diff --git a/sys/kern/kern_exit.c b/sys/kern/kern_exit.c
index f23c756..ecaed6f 100644
--- a/sys/kern/kern_exit.c
+++ b/sys/kern/kern_exit.c
@@ -192,11 +192,7 @@ exit1(td, rv)
* Reset any sigio structures pointing to us as a result of
* F_SETOWN with our pid.
*/
- SIGIO_LOCK();
- PROC_LOCK(p);
funsetownlst(&p->p_sigiolst);
- PROC_UNLOCK(p);
- SIGIO_UNLOCK();
/*
* Close open files and release open-file table.
diff --git a/sys/kern/kern_proc.c b/sys/kern/kern_proc.c
index 2dde108..8f92331 100644
--- a/sys/kern/kern_proc.c
+++ b/sys/kern/kern_proc.c
@@ -474,16 +474,13 @@ pgdelete(pgrp)
PGRP_LOCK_ASSERT(pgrp, MA_NOTOWNED);
SESS_LOCK_ASSERT(pgrp->pg_session, MA_NOTOWNED);
- SIGIO_LOCK();
- PGRP_LOCK(pgrp);
-
/*
* Reset any sigio structures pointing to us as a result of
* F_SETOWN with our pgid.
*/
funsetownlst(&pgrp->pg_sigiolst);
- SIGIO_UNLOCK();
+ PGRP_LOCK(pgrp);
if (pgrp->pg_session->s_ttyp != NULL &&
pgrp->pg_session->s_ttyp->t_pgrp == pgrp)
pgrp->pg_session->s_ttyp->t_pgrp = NULL;
diff --git a/sys/kern/subr_log.c b/sys/kern/subr_log.c
index 568b3fe..2c01568 100644
--- a/sys/kern/subr_log.c
+++ b/sys/kern/subr_log.c
@@ -118,7 +118,7 @@ logclose(dev_t dev, int flag, int mode, struct thread *td)
log_open = 0;
callout_stop(&logsoftc.sc_callout);
logsoftc.sc_state = 0;
- funsetown(logsoftc.sc_sigio);
+ funsetown(&logsoftc.sc_sigio);
return (0);
}
diff --git a/sys/kern/subr_witness.c b/sys/kern/subr_witness.c
index 59cf2ca..fcc9b53 100644
--- a/sys/kern/subr_witness.c
+++ b/sys/kern/subr_witness.c
@@ -189,6 +189,7 @@ static struct witness_order_list_entry order_lists[] = {
{ "Giant", &lock_class_mtx_sleep },
{ "proctree", &lock_class_sx },
{ "allproc", &lock_class_sx },
+ { "sigio lock", &lock_class_mtx_sleep },
{ "process group", &lock_class_mtx_sleep },
{ "process lock", &lock_class_mtx_sleep },
{ "session", &lock_class_mtx_sleep },
diff --git a/sys/kern/sys_pipe.c b/sys/kern/sys_pipe.c
index d0682fa..c79f9ec 100644
--- a/sys/kern/sys_pipe.c
+++ b/sys/kern/sys_pipe.c
@@ -1246,7 +1246,7 @@ pipe_close(fp, td)
fp->f_ops = &badfileops;
fp->f_data = NULL;
- funsetown(cpipe->pipe_sigio);
+ funsetown(&cpipe->pipe_sigio);
pipeclose(cpipe);
return (0);
}
diff --git a/sys/kern/tty.c b/sys/kern/tty.c
index 7b3459a..5c7719b 100644
--- a/sys/kern/tty.c
+++ b/sys/kern/tty.c
@@ -246,7 +246,7 @@ ttyclose(tp)
{
int s;
- funsetown(tp->t_sigio);
+ funsetown(&tp->t_sigio);
s = spltty();
if (constty == tp)
constty = NULL;
diff --git a/sys/kern/uipc_socket.c b/sys/kern/uipc_socket.c
index 33f8a4d..4bbc6e2 100644
--- a/sys/kern/uipc_socket.c
+++ b/sys/kern/uipc_socket.c
@@ -305,7 +305,7 @@ soclose(so)
int s = splnet(); /* conservative */
int error = 0;
- funsetown(so->so_sigio);
+ funsetown(&so->so_sigio);
if (so->so_options & SO_ACCEPTCONN) {
struct socket *sp, *sonext;
OpenPOWER on IntegriCloud