summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/dev/drm/drm_drv.h2
-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
-rw-r--r--sys/net/bpf.c2
-rw-r--r--sys/net/if_tap.c2
-rw-r--r--sys/net/if_tun.c2
-rw-r--r--sys/sys/filedesc.h2
13 files changed, 56 insertions, 43 deletions
diff --git a/sys/dev/drm/drm_drv.h b/sys/dev/drm/drm_drv.h
index 9524499..7013955 100644
--- a/sys/dev/drm/drm_drv.h
+++ b/sys/dev/drm/drm_drv.h
@@ -1098,7 +1098,7 @@ int DRM( close)(dev_t kdev, int flags, int fmt, DRM_OS_STRUCTPROC *p)
DRM(fasync)( -1, filp, 0 );
#endif /* __linux__ */
#ifdef __FreeBSD__
- funsetown(dev->buf_sigio);
+ funsetown(&dev->buf_sigio);
#endif /* __FreeBSD__ */
DRM_OS_LOCK;
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;
diff --git a/sys/net/bpf.c b/sys/net/bpf.c
index 325af54..1476498 100644
--- a/sys/net/bpf.c
+++ b/sys/net/bpf.c
@@ -368,7 +368,7 @@ bpfclose(dev, flags, fmt, td)
callout_stop(&d->bd_callout);
d->bd_state = BPF_IDLE;
BPFD_UNLOCK(d);
- funsetown(d->bd_sigio);
+ funsetown(&d->bd_sigio);
mtx_lock(&bpf_mtx);
if (d->bd_bif)
bpf_detachd(d);
diff --git a/sys/net/if_tap.c b/sys/net/if_tap.c
index 45ce21f..ef0a36d 100644
--- a/sys/net/if_tap.c
+++ b/sys/net/if_tap.c
@@ -491,7 +491,7 @@ tapclose(dev, foo, bar, td)
splx(s);
}
- funsetown(tp->tap_sigio);
+ funsetown(&tp->tap_sigio);
selwakeup(&tp->tap_rsel);
tp->tap_flags &= ~TAP_OPEN;
diff --git a/sys/net/if_tun.c b/sys/net/if_tun.c
index a6c89fb..18435fd 100644
--- a/sys/net/if_tun.c
+++ b/sys/net/if_tun.c
@@ -335,7 +335,7 @@ tunclose(dev_t dev, int foo, int bar, struct thread *td)
splx(s);
}
- funsetown(tp->tun_sigio);
+ funsetown(&tp->tun_sigio);
selwakeup(&tp->tun_rsel);
TUNDEBUG ("%s%d: closed\n", ifp->if_name, ifp->if_unit);
diff --git a/sys/sys/filedesc.h b/sys/sys/filedesc.h
index d2d108c..ecda574 100644
--- a/sys/sys/filedesc.h
+++ b/sys/sys/filedesc.h
@@ -156,7 +156,7 @@ void ffree(struct file *fp);
static __inline struct file * fget_locked(struct filedesc *fdp, int fd);
pid_t fgetown(struct sigio *sigio);
int fsetown(pid_t pgid, struct sigio **sigiop);
-void funsetown(struct sigio *sigio);
+void funsetown(struct sigio **sigiop);
void funsetownlst(struct sigiolst *sigiolst);
int getvnode(struct filedesc *fdp, int fd, struct file **fpp);
void setugidsafety(struct thread *td);
OpenPOWER on IntegriCloud