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.
This commit is contained in:
Alfred Perlstein 2002-05-06 19:31:28 +00:00
parent 567f4af63d
commit e649887b1e
Notes: svn2git 2020-12-20 02:59:44 +00:00
svn path=/head/; revision=96122
13 changed files with 56 additions and 43 deletions

View File

@ -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;

View File

@ -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);

View File

@ -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.

View File

@ -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;

View File

@ -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);
}

View File

@ -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 },

View File

@ -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);
}

View File

@ -246,7 +246,7 @@ ttyclose(tp)
{
int s;
funsetown(tp->t_sigio);
funsetown(&tp->t_sigio);
s = spltty();
if (constty == tp)
constty = NULL;

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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);

View File

@ -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);