summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c232
1 files changed, 162 insertions, 70 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 3be205c..b212359 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -178,17 +178,18 @@ int
CURSIG(struct proc *p)
{
sigset_t tmpset;
- int r;
+ int r = 0;
+ PROC_LOCK(p);
if (SIGISEMPTY(p->p_siglist))
- return (0);
+ goto out;
tmpset = p->p_siglist;
SIGSETNAND(tmpset, p->p_sigmask);
if (SIGISEMPTY(tmpset) && (p->p_flag & P_TRACED) == 0)
- return (0);
- mtx_lock(&Giant);
+ goto out;
r = issignal(p);
- mtx_unlock(&Giant);
+out:
+ PROC_UNLOCK(p);
return (r);
}
@@ -224,11 +225,13 @@ do_sigaction(p, sig, act, oact, old)
struct sigaction *act, *oact;
int old;
{
- register struct sigacts *ps = p->p_sigacts;
+ register struct sigacts *ps;
if (sig <= 0 || sig > _SIG_MAXSIG)
return (EINVAL);
+ PROC_LOCK(p);
+ ps = p->p_sigacts;
if (oact) {
oact->sa_handler = ps->ps_sigact[_SIG_IDX(sig)];
oact->sa_mask = ps->ps_catchmask[_SIG_IDX(sig)];
@@ -250,13 +253,14 @@ do_sigaction(p, sig, act, oact, old)
}
if (act) {
if ((sig == SIGKILL || sig == SIGSTOP) &&
- act->sa_handler != SIG_DFL)
+ act->sa_handler != SIG_DFL) {
+ PROC_UNLOCK(p);
return (EINVAL);
+ }
/*
* Change setting atomically.
*/
- (void) splhigh();
ps->ps_catchmask[_SIG_IDX(sig)] = act->sa_mask;
SIG_CANTMASK(ps->ps_catchmask[_SIG_IDX(sig)]);
@@ -336,9 +340,8 @@ do_sigaction(p, sig, act, oact, old)
SIGDELSET(ps->ps_osigset, sig);
else
SIGADDSET(ps->ps_osigset, sig);
-
- (void) spl0();
}
+ PROC_UNLOCK(p);
return (0);
}
@@ -425,9 +428,11 @@ siginit(p)
{
register int i;
+ PROC_LOCK(p);
for (i = 1; i <= NSIG; i++)
if (sigprop(i) & SA_IGNORE && i != SIGCONT)
SIGADDSET(p->p_sigignore, i);
+ PROC_UNLOCK(p);
}
/*
@@ -437,7 +442,7 @@ void
execsigs(p)
register struct proc *p;
{
- register struct sigacts *ps = p->p_sigacts;
+ register struct sigacts *ps;
register int sig;
/*
@@ -445,6 +450,8 @@ execsigs(p)
* through p_sigmask (unless they were caught,
* and are now ignored by default).
*/
+ PROC_LOCK(p);
+ ps = p->p_sigacts;
while (SIGNOTEMPTY(p->p_sigcatch)) {
sig = sig_ffs(&p->p_sigcatch);
SIGDELSET(p->p_sigcatch, sig);
@@ -466,14 +473,13 @@ execsigs(p)
* Reset no zombies if child dies flag as Solaris does.
*/
p->p_procsig->ps_flag &= ~PS_NOCLDWAIT;
+ PROC_UNLOCK(p);
}
/*
- * do_sigprocmask() - MP SAFE ONLY IF p == curproc
+ * do_sigprocmask()
*
- * Manipulate signal mask. This routine is MP SAFE *ONLY* if
- * p == curproc. Also remember that in order to remain MP SAFE
- * no spl*() calls may be made.
+ * Manipulate signal mask.
*/
static int
do_sigprocmask(p, how, set, oset, old)
@@ -484,6 +490,7 @@ do_sigprocmask(p, how, set, oset, old)
{
int error;
+ PROC_LOCK(p);
if (oset != NULL)
*oset = p->p_sigmask;
@@ -509,6 +516,7 @@ do_sigprocmask(p, how, set, oset, old)
break;
}
}
+ PROC_UNLOCK(p);
return (error);
}
@@ -582,8 +590,12 @@ sigpending(p, uap)
struct proc *p;
struct sigpending_args *uap;
{
+ sigset_t siglist;
- return (copyout(&p->p_siglist, uap->set, sizeof(sigset_t)));
+ PROC_LOCK(p);
+ siglist = p->p_siglist;
+ PROC_UNLOCK(p);
+ return (copyout(&siglist, uap->set, sizeof(sigset_t)));
}
#ifdef COMPAT_43 /* XXX - COMPAT_FBSD3 */
@@ -599,7 +611,9 @@ osigpending(p, uap)
struct osigpending_args *uap;
{
+ PROC_LOCK(p);
SIG2OSIG(p->p_siglist, p->p_retval[0]);
+ PROC_UNLOCK(p);
return (0);
}
#endif /* COMPAT_43 */
@@ -671,10 +685,10 @@ osigblock(p, uap)
OSIG2SIG(uap->mask, set);
SIG_CANTMASK(set);
- (void) splhigh();
+ PROC_LOCK(p);
SIG2OSIG(p->p_sigmask, p->p_retval[0]);
SIGSETOR(p->p_sigmask, set);
- (void) spl0();
+ PROC_UNLOCK(p);
return (0);
}
@@ -692,10 +706,10 @@ osigsetmask(p, uap)
OSIG2SIG(uap->mask, set);
SIG_CANTMASK(set);
- (void) splhigh();
+ PROC_LOCK(p);
SIG2OSIG(p->p_sigmask, p->p_retval[0]);
SIGSETLO(p->p_sigmask, set);
- (void) spl0();
+ PROC_UNLOCK(p);
return (0);
}
#endif /* COMPAT_43 || COMPAT_SUNOS */
@@ -717,7 +731,7 @@ sigsuspend(p, uap)
struct sigsuspend_args *uap;
{
sigset_t mask;
- register struct sigacts *ps = p->p_sigacts;
+ register struct sigacts *ps;
int error;
error = copyin(uap->sigmask, &mask, sizeof(mask));
@@ -731,13 +745,16 @@ sigsuspend(p, uap)
* save it here and mark the sigacts structure
* to indicate this.
*/
+ PROC_LOCK(p);
+ ps = p->p_sigacts;
p->p_oldsigmask = p->p_sigmask;
p->p_flag |= P_OLDMASK;
SIG_CANTMASK(mask);
p->p_sigmask = mask;
- while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "pause", 0) == 0)
+ while (msleep((caddr_t) ps, &p->p_mtx, PPAUSE|PCATCH, "pause", 0) == 0)
/* void */;
+ PROC_UNLOCK(p);
/* always return EINTR rather than ERESTART... */
return (EINTR);
}
@@ -755,15 +772,18 @@ osigsuspend(p, uap)
struct osigsuspend_args *uap;
{
sigset_t mask;
- register struct sigacts *ps = p->p_sigacts;
+ register struct sigacts *ps;
+ PROC_LOCK(p);
+ ps = p->p_sigacts;
p->p_oldsigmask = p->p_sigmask;
p->p_flag |= P_OLDMASK;
OSIG2SIG(uap->mask, mask);
SIG_CANTMASK(mask);
SIGSETLO(p->p_sigmask, mask);
- while (tsleep((caddr_t) ps, PPAUSE|PCATCH, "opause", 0) == 0)
+ while (msleep((caddr_t) ps, &p->p_mtx, PPAUSE|PCATCH, "opause", 0) == 0)
/* void */;
+ PROC_UNLOCK(p);
/* always return EINTR rather than ERESTART... */
return (EINTR);
}
@@ -786,8 +806,10 @@ osigstack(p, uap)
int error;
if (uap->oss != NULL) {
+ PROC_LOCK(p);
ss.ss_sp = p->p_sigstk.ss_sp;
ss.ss_onstack = sigonstack(cpu_getstack(p));
+ PROC_UNLOCK(p);
error = copyout(&ss, uap->oss, sizeof(struct sigstack));
if (error)
return (error);
@@ -796,10 +818,12 @@ osigstack(p, uap)
if (uap->nss != NULL) {
if ((error = copyin(uap->nss, &ss, sizeof(ss))) != 0)
return (error);
+ PROC_LOCK(p);
p->p_sigstk.ss_sp = ss.ss_sp;
p->p_sigstk.ss_size = 0;
p->p_sigstk.ss_flags |= ss.ss_onstack & SS_ONSTACK;
p->p_flag |= P_ALTSTACK;
+ PROC_UNLOCK(p);
}
return (0);
}
@@ -823,9 +847,11 @@ sigaltstack(p, uap)
oonstack = sigonstack(cpu_getstack(p));
if (uap->oss != NULL) {
+ PROC_LOCK(p);
ss = p->p_sigstk;
ss.ss_flags = (p->p_flag & P_ALTSTACK)
? ((oonstack) ? SS_ONSTACK : 0) : SS_DISABLE;
+ PROC_UNLOCK(p);
if ((error = copyout(&ss, uap->oss, sizeof(stack_t))) != 0)
return (error);
}
@@ -840,10 +866,15 @@ sigaltstack(p, uap)
if (!(ss.ss_flags & SS_DISABLE)) {
if (ss.ss_size < p->p_sysent->sv_minsigstksz)
return (ENOMEM);
+ PROC_LOCK(p);
p->p_sigstk = ss;
p->p_flag |= P_ALTSTACK;
- } else
+ PROC_UNLOCK(p);
+ } else {
+ PROC_LOCK(p);
p->p_flag &= ~P_ALTSTACK;
+ PROC_UNLOCK(p);
+ }
}
return (0);
}
@@ -867,12 +898,24 @@ killpg1(cp, sig, pgid, all)
*/
ALLPROC_LOCK(AP_SHARED);
LIST_FOREACH(p, &allproc, p_list) {
- if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
- p == cp || !CANSIGNAL(cp, p, sig))
+ PROC_LOCK(p);
+ if (p->p_pid <= 1 || p->p_flag & P_SYSTEM || p == cp) {
+ PROC_UNLOCK(p);
+ continue;
+ }
+ PROC_UNLOCK(p);
+ /*
+ * XXX: this locking needs work.. specifically the
+ * session checks..
+ */
+ if (!CANSIGNAL(cp, p, sig))
continue;
nfound++;
- if (sig)
+ if (sig) {
+ PROC_LOCK(p);
psignal(p, sig);
+ PROC_UNLOCK(p);
+ }
}
ALLPROC_LOCK(AP_RELEASE);
} else {
@@ -887,13 +930,27 @@ killpg1(cp, sig, pgid, all)
return (ESRCH);
}
LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
- if (p->p_pid <= 1 || p->p_flag & P_SYSTEM ||
- p->p_stat == SZOMB ||
- !CANSIGNAL(cp, p, sig))
+ PROC_LOCK(p);
+ if (p->p_pid <= 1 || p->p_flag & P_SYSTEM) {
+ PROC_UNLOCK(p);
+ continue;
+ }
+ PROC_UNLOCK(p);
+ mtx_lock_spin(&sched_lock);
+ if (p->p_stat == SZOMB) {
+ mtx_unlock_spin(&sched_lock);
+ continue;
+ }
+ mtx_unlock_spin(&sched_lock);
+ /* XXX: locking b0rked */
+ if (!CANSIGNAL(cp, p, sig))
continue;
nfound++;
- if (sig)
+ if (sig) {
+ PROC_LOCK(p);
psignal(p, sig);
+ PROC_UNLOCK(p);
+ }
}
}
return (nfound ? 0 : ESRCH);
@@ -919,10 +976,14 @@ kill(cp, uap)
/* kill single process */
if ((p = pfind(uap->pid)) == NULL)
return (ESRCH);
+ /* XXX: locking b0rked */
if (!CANSIGNAL(cp, p, uap->signum))
return (EPERM);
- if (uap->signum)
+ if (uap->signum) {
+ PROC_LOCK(p);
psignal(p, uap->signum);
+ PROC_UNLOCK(p);
+ }
return (0);
}
switch (uap->pid) {
@@ -980,10 +1041,14 @@ pgsignal(pgrp, sig, checkctty)
{
register struct proc *p;
- if (pgrp)
- LIST_FOREACH(p, &pgrp->pg_members, p_pglist)
+ if (pgrp) {
+ LIST_FOREACH(p, &pgrp->pg_members, p_pglist) {
+ PROC_LOCK(p);
if (checkctty == 0 || p->p_flag & P_CONTROLT)
psignal(p, sig);
+ PROC_UNLOCK(p);
+ }
+ }
}
/*
@@ -999,6 +1064,7 @@ trapsignal(p, sig, code)
{
register struct sigacts *ps = p->p_sigacts;
+ PROC_LOCK(p);
if ((p->p_flag & P_TRACED) == 0 && SIGISMEMBER(p->p_sigcatch, sig) &&
!SIGISMEMBER(p->p_sigmask, sig)) {
p->p_stats->p_ru.ru_nsignals++;
@@ -1007,8 +1073,10 @@ trapsignal(p, sig, code)
ktrpsig(p->p_tracep, sig, ps->ps_sigact[_SIG_IDX(sig)],
&p->p_sigmask, code);
#endif
+ PROC_UNLOCK(p); /* XXX ??? */
(*p->p_sysent->sv_sendsig)(ps->ps_sigact[_SIG_IDX(sig)], sig,
&p->p_sigmask, code);
+ PROC_LOCK(p);
SIGSETOR(p->p_sigmask, ps->ps_catchmask[_SIG_IDX(sig)]);
if (!SIGISMEMBER(ps->ps_signodefer, sig))
SIGADDSET(p->p_sigmask, sig);
@@ -1027,6 +1095,7 @@ trapsignal(p, sig, code)
p->p_sig = sig; /* XXX to verify code */
psignal(p, sig);
}
+ PROC_UNLOCK(p);
}
/*
@@ -1055,7 +1124,7 @@ psignal(p, sig)
panic("psignal signal number");
}
- PROC_LOCK(p);
+ PROC_LOCK_ASSERT(p, MA_OWNED);
KNOTE(&p->p_klist, NOTE_SIGNAL | sig);
prop = sigprop(sig);
@@ -1075,10 +1144,8 @@ psignal(p, sig)
* and if it is set to SIG_IGN,
* action will be SIG_DFL here.)
*/
- if (SIGISMEMBER(p->p_sigignore, sig) || (p->p_flag & P_WEXIT)) {
- PROC_UNLOCK(p);
+ if (SIGISMEMBER(p->p_sigignore, sig) || (p->p_flag & P_WEXIT))
return;
- }
if (SIGISMEMBER(p->p_sigmask, sig))
action = SIG_HOLD;
else if (SIGISMEMBER(p->p_sigcatch, sig))
@@ -1104,10 +1171,8 @@ psignal(p, sig)
* and don't clear any pending SIGCONT.
*/
if (prop & SA_TTYSTOP && p->p_pgrp->pg_jobc == 0 &&
- action == SIG_DFL) {
- PROC_UNLOCK(p);
+ action == SIG_DFL)
return;
- }
SIG_CONTSIGMASK(p->p_siglist);
}
SIGADDSET(p->p_siglist, sig);
@@ -1119,7 +1184,6 @@ psignal(p, sig)
mtx_lock_spin(&sched_lock);
if (action == SIG_HOLD && (!(prop & SA_CONT) || p->p_stat != SSTOP)) {
mtx_unlock_spin(&sched_lock);
- PROC_UNLOCK(p);
return;
}
switch (p->p_stat) {
@@ -1169,13 +1233,12 @@ psignal(p, sig)
goto out;
SIGDELSET(p->p_siglist, sig);
p->p_xstat = sig;
- PROC_UNLOCK(p);
- PROCTREE_LOCK(PT_SHARED);
- if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0)
+ if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) {
+ PROC_LOCK(p->p_pptr);
psignal(p->p_pptr, SIGCHLD);
+ PROC_UNLOCK(p->p_pptr);
+ }
stop(p);
- PROCTREE_LOCK(PT_RELEASE);
- PROC_LOCK(p);
goto out;
} else
goto runfast;
@@ -1277,7 +1340,6 @@ run:
out:
/* If we jump here, sched_lock should not be owned. */
mtx_assert(&sched_lock, MA_NOTOWNED);
- PROC_UNLOCK(p);
}
/*
@@ -1299,6 +1361,7 @@ issignal(p)
sigset_t mask;
register int sig, prop;
+ PROC_LOCK_ASSERT(p, MA_OWNED);
for (;;) {
int traced = (p->p_flag & P_TRACED) || (p->p_stops & S_SIG);
@@ -1306,12 +1369,12 @@ issignal(p)
SIGSETNAND(mask, p->p_sigmask);
if (p->p_flag & P_PPWAIT)
SIG_STOPSIGMASK(mask);
- if (!SIGNOTEMPTY(mask)) /* no signal to send */
+ if (!SIGNOTEMPTY(mask)) /* no signal to send */
return (0);
sig = sig_ffs(&mask);
prop = sigprop(sig);
- STOPEVENT(p, S_SIG, sig);
+ _STOPEVENT(p, S_SIG, sig);
/*
* We should see pending but ignored signals
@@ -1327,20 +1390,20 @@ issignal(p)
* stopped until released by the parent.
*/
p->p_xstat = sig;
- PROCTREE_LOCK(PT_SHARED);
+ PROC_LOCK(p->p_pptr);
psignal(p->p_pptr, SIGCHLD);
+ PROC_UNLOCK(p->p_pptr);
do {
stop(p);
- PROCTREE_LOCK(PT_RELEASE);
mtx_lock_spin(&sched_lock);
+ PROC_UNLOCK_NOSWITCH(p);
DROP_GIANT_NOSWITCH();
mi_switch();
mtx_unlock_spin(&sched_lock);
PICKUP_GIANT();
- PROCTREE_LOCK(PT_SHARED);
+ PROC_LOCK(p);
} while (!trace_req(p)
&& p->p_flag & P_TRACED);
- PROCTREE_LOCK(PT_RELEASE);
/*
* If the traced bit got turned off, go back up
@@ -1404,16 +1467,19 @@ issignal(p)
prop & SA_TTYSTOP))
break; /* == ignore */
p->p_xstat = sig;
- PROCTREE_LOCK(PT_SHARED);
stop(p);
- if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0)
+ if ((p->p_pptr->p_procsig->ps_flag & PS_NOCLDSTOP) == 0) {
+ PROC_LOCK(p->p_pptr);
psignal(p->p_pptr, SIGCHLD);
- PROCTREE_LOCK(PT_RELEASE);
+ PROC_UNLOCK(p->p_pptr);
+ }
mtx_lock_spin(&sched_lock);
+ PROC_UNLOCK_NOSWITCH(p);
DROP_GIANT_NOSWITCH();
mi_switch();
mtx_unlock_spin(&sched_lock);
PICKUP_GIANT();
+ PROC_LOCK(p);
break;
} else if (prop & SA_IGNORE) {
/*
@@ -1459,7 +1525,7 @@ stop(p)
register struct proc *p;
{
- PROCTREE_ASSERT(PT_SHARED);
+ PROC_LOCK_ASSERT(p, MA_OWNED);
mtx_lock_spin(&sched_lock);
p->p_stat = SSTOP;
p->p_flag &= ~P_WAITED;
@@ -1476,13 +1542,15 @@ postsig(sig)
register int sig;
{
register struct proc *p = curproc;
- struct sigacts *ps = p->p_sigacts;
+ struct sigacts *ps;
sig_t action;
sigset_t returnmask;
int code;
KASSERT(sig != 0, ("postsig"));
+ PROC_LOCK(p);
+ ps = p->p_sigacts;
SIGDELSET(p->p_siglist, sig);
action = ps->ps_sigact[_SIG_IDX(sig)];
#ifdef KTRACE
@@ -1490,7 +1558,7 @@ postsig(sig)
ktrpsig(p->p_tracep, sig, action, p->p_flag & P_OLDMASK ?
&p->p_oldsigmask : &p->p_sigmask, 0);
#endif
- STOPEVENT(p, S_SIG, sig);
+ _STOPEVENT(p, S_SIG, sig);
if (action == SIG_DFL) {
/*
@@ -1514,7 +1582,6 @@ postsig(sig)
* mask from before the sigsuspend is what we want
* restored after the signal processing is completed.
*/
- (void) splhigh();
if (p->p_flag & P_OLDMASK) {
returnmask = p->p_oldsigmask;
p->p_flag &= ~P_OLDMASK;
@@ -1535,7 +1602,6 @@ postsig(sig)
SIGADDSET(p->p_sigignore, sig);
ps->ps_sigact[_SIG_IDX(sig)] = SIG_DFL;
}
- (void) spl0();
p->p_stats->p_ru.ru_nsignals++;
if (p->p_sig != sig) {
code = 0;
@@ -1544,6 +1610,7 @@ postsig(sig)
p->p_code = 0;
p->p_sig = 0;
}
+ PROC_UNLOCK(p);
(*p->p_sysent->sv_sendsig)(action, sig, &returnmask, code);
}
}
@@ -1560,7 +1627,9 @@ killproc(p, why)
p, p->p_pid, p->p_comm);
log(LOG_ERR, "pid %d (%s), uid %d, was killed: %s\n", p->p_pid, p->p_comm,
p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1, why);
+ PROC_LOCK(p);
psignal(p, SIGKILL);
+ PROC_UNLOCK(p);
}
/*
@@ -1577,6 +1646,7 @@ sigexit(p, sig)
int sig;
{
+ PROC_LOCK_ASSERT(p, MA_OWNED);
p->p_acflag |= AXSIG;
if (sigprop(sig) & SA_CORE) {
p->p_sig = sig;
@@ -1586,6 +1656,7 @@ sigexit(p, sig)
* these messages.)
* XXX : Todo, as well as euid, write out ruid too
*/
+ PROC_UNLOCK(p);
if (coredump(p) == 0)
sig |= WCOREFLAG;
if (kern_logsigexit)
@@ -1595,7 +1666,10 @@ sigexit(p, sig)
p->p_cred && p->p_ucred ? p->p_ucred->cr_uid : -1,
sig &~ WCOREFLAG,
sig & WCOREFLAG ? " (core dumped)" : "");
- }
+ } else
+ PROC_UNLOCK(p);
+ if (!mtx_owned(&Giant))
+ mtx_lock(&Giant);
exit1(p, W_EXITCODE(0, sig));
/* NOTREACHED */
}
@@ -1702,11 +1776,14 @@ coredump(p)
struct mount *mp;
char *name; /* name of corefile */
off_t limit;
-
- STOPEVENT(p, S_CORE, 0);
- if (((sugid_coredump == 0) && p->p_flag & P_SUGID) || do_coredump == 0)
+ PROC_LOCK(p);
+ _STOPEVENT(p, S_CORE, 0);
+
+ if (((sugid_coredump == 0) && p->p_flag & P_SUGID) || do_coredump == 0) {
+ PROC_UNLOCK(p);
return (EFAULT);
+ }
/*
* Note that the bulk of limit checking is done after
@@ -1717,8 +1794,11 @@ coredump(p)
* if it is larger than the limit.
*/
limit = p->p_rlimit[RLIMIT_CORE].rlim_cur;
- if (limit == 0)
+ if (limit == 0) {
+ PROC_UNLOCK(p);
return 0;
+ }
+ PROC_UNLOCK(p);
restart:
name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
@@ -1749,7 +1829,9 @@ restart:
vattr.va_size = 0;
VOP_LEASE(vp, p, cred, LEASE_WRITE);
VOP_SETATTR(vp, &vattr, cred, p);
+ PROC_LOCK(p);
p->p_acflag |= ACORE;
+ PROC_UNLOCK(p);
error = p->p_sysent->sv_coredump ?
p->p_sysent->sv_coredump(p, vp, limit) :
@@ -1780,7 +1862,9 @@ nosys(p, args)
struct nosys_args *args;
{
+ PROC_LOCK(p);
psignal(p, SIGSYS);
+ PROC_UNLOCK(p);
return (EINVAL);
}
@@ -1797,16 +1881,21 @@ pgsigio(sigio, sig, checkctty)
return;
if (sigio->sio_pgid > 0) {
+ PROC_LOCK(sigio->sio_proc);
if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred,
sigio->sio_proc))
psignal(sigio->sio_proc, sig);
+ PROC_UNLOCK(sigio->sio_proc);
} else if (sigio->sio_pgid < 0) {
struct proc *p;
- LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist)
+ LIST_FOREACH(p, &sigio->sio_pgrp->pg_members, p_pglist) {
+ PROC_LOCK(p);
if (CANSIGIO(sigio->sio_ruid, sigio->sio_ucred, p) &&
(checkctty == 0 || (p->p_flag & P_CONTROLT)))
psignal(p, sig);
+ PROC_UNLOCK(p);
+ }
}
}
@@ -1818,8 +1907,9 @@ filt_sigattach(struct knote *kn)
kn->kn_ptr.p_proc = p;
kn->kn_flags |= EV_CLEAR; /* automatically set */
- /* XXX lock the proc here while adding to the list? */
+ PROC_LOCK(p);
SLIST_INSERT_HEAD(&p->p_klist, kn, kn_selnext);
+ PROC_UNLOCK(p);
return (0);
}
@@ -1829,7 +1919,9 @@ filt_sigdetach(struct knote *kn)
{
struct proc *p = kn->kn_ptr.p_proc;
+ PROC_LOCK(p);
SLIST_REMOVE(&p->p_klist, kn, knote, kn_selnext);
+ PROC_UNLOCK(p);
}
/*
OpenPOWER on IntegriCloud