diff options
author | Patrick Mooney <pmooney@pfmooney.com> | 2016-12-05 23:14:19 +0000 |
---|---|---|
committer | Jason King <jason.king@joyent.com> | 2020-04-08 19:41:51 -0500 |
commit | 72a6dc127431d372b6b6136087c736300544f8b7 (patch) | |
tree | de4356a799418ec5bcae77b1f7c11971e4f367ac | |
parent | a47ab03e261661b7326ab0b642649034886be632 (diff) | |
download | illumos-joyent-72a6dc127431d372b6b6136087c736300544f8b7.tar.gz |
7637 restorecontext(ucontext_t *ucp) leaves all maskable signals blocked in curthread->t_hold
Reviewed by: Robert Mustacchi <rm@joyent.com>
Reviewed by: Jerry Jelinek <jerry.jelinek@joyent.com>
Reviewed by: Toomas Soome <tsoome@me.com>
Approved by: Dan McDonald <danmcd@joyent.com>
-rw-r--r-- | usr/src/uts/common/fs/proc/prdata.h | 1 | ||||
-rw-r--r-- | usr/src/uts/common/fs/proc/prioctl.c | 22 | ||||
-rw-r--r-- | usr/src/uts/common/fs/proc/prsubr.c | 32 | ||||
-rw-r--r-- | usr/src/uts/common/os/schedctl.c | 18 |
4 files changed, 45 insertions, 28 deletions
diff --git a/usr/src/uts/common/fs/proc/prdata.h b/usr/src/uts/common/fs/proc/prdata.h index b010d6a37e..59315368d7 100644 --- a/usr/src/uts/common/fs/proc/prdata.h +++ b/usr/src/uts/common/fs/proc/prdata.h @@ -381,6 +381,7 @@ extern int clear_watched_area(proc_t *, struct watched_area *); extern void pr_free_watchpoints(proc_t *); extern proc_t *pr_cancel_watch(prnode_t *); extern struct seg *break_seg(proc_t *); +extern void prgethold(kthread_t *, sigset_t *); /* * Machine-dependent routines (defined in prmachdep.c). diff --git a/usr/src/uts/common/fs/proc/prioctl.c b/usr/src/uts/common/fs/proc/prioctl.c index 8202e49df0..630ab0b2e3 100644 --- a/usr/src/uts/common/fs/proc/prioctl.c +++ b/usr/src/uts/common/fs/proc/prioctl.c @@ -930,8 +930,7 @@ startover: } case PIOCGHOLD: /* get signal-hold mask */ - schedctl_finish_sigblock(t); - sigktou(&t->t_hold, &un.holdmask); + prgethold(t, &un.holdmask); prunlock(pnp); if (copyout(&un.holdmask, cmaddr, sizeof (un.holdmask))) error = EFAULT; @@ -1395,8 +1394,7 @@ oprgetstatus32(kthread_t *t, prstatus32_t *sp, zone_t *zp) sp->pr_cursig = lwp->lwp_cursig; prassignset(&sp->pr_sigpend, &p->p_sig); prassignset(&sp->pr_lwppend, &t->t_sig); - schedctl_finish_sigblock(t); - prassignset(&sp->pr_sighold, &t->t_hold); + prgethold(t, &sp->pr_sighold); sp->pr_altstack.ss_sp = (caddr32_t)(uintptr_t)lwp->lwp_sigaltstack.ss_sp; sp->pr_altstack.ss_size = (size32_t)lwp->lwp_sigaltstack.ss_size; @@ -1673,14 +1671,8 @@ oprgetpsinfo32(proc_t *p, prpsinfo32_t *psp, kthread_t *tp) /*ARGSUSED*/ static int -prioctl32( - struct vnode *vp, - int cmd, - intptr_t arg, - int flag, - cred_t *cr, - int *rvalp, - caller_context_t *ct) +prioctl32(struct vnode *vp, int cmd, intptr_t arg, int flag, cred_t *cr, + int *rvalp, caller_context_t *ct) { int nsig = PROC_IS_BRANDED(curproc)? BROP(curproc)->b_nsig : NSIG; caddr_t cmaddr = (caddr_t)arg; @@ -2557,8 +2549,7 @@ startover: } case PIOCGHOLD: /* get signal-hold mask */ - schedctl_finish_sigblock(t); - sigktou(&t->t_hold, &un32.holdmask); + prgethold(t, &un32.holdmask); prunlock(pnp); if (copyout(&un32.holdmask, cmaddr, sizeof (un32.holdmask))) error = EFAULT; @@ -3235,8 +3226,7 @@ oprgetstatus(kthread_t *t, prstatus_t *sp, zone_t *zp) sp->pr_cursig = lwp->lwp_cursig; prassignset(&sp->pr_sigpend, &p->p_sig); prassignset(&sp->pr_lwppend, &t->t_sig); - schedctl_finish_sigblock(t); - prassignset(&sp->pr_sighold, &t->t_hold); + prgethold(t, &sp->pr_sighold); sp->pr_altstack = lwp->lwp_sigaltstack; prgetaction(p, up, lwp->lwp_cursig, &sp->pr_action); sp->pr_pid = p->p_pid; diff --git a/usr/src/uts/common/fs/proc/prsubr.c b/usr/src/uts/common/fs/proc/prsubr.c index 26e33330fb..8cda5f57b3 100644 --- a/usr/src/uts/common/fs/proc/prsubr.c +++ b/usr/src/uts/common/fs/proc/prsubr.c @@ -931,6 +931,29 @@ prgetstatus(proc_t *p, pstatus_t *sp, zone_t *zp) sp->pr_flags = sp->pr_lwp.pr_flags; } +/* + * Query mask of held signals for a given thread. + * + * This makes use of schedctl_sigblock() to query if userspace has requested + * that all maskable signals be held. While it would be tempting to call + * schedctl_finish_sigblock() and apply that update to t->t_hold, it cannot be + * done safely without the risk of racing with the thread under consideration. + */ +void +prgethold(kthread_t *t, sigset_t *sp) +{ + k_sigset_t set; + + if (schedctl_sigblock(t)) { + set.__sigbits[0] = FILLSET0 & ~CANTMASK0; + set.__sigbits[1] = FILLSET1 & ~CANTMASK1; + set.__sigbits[2] = FILLSET2 & ~CANTMASK2; + } else { + set = t->t_hold; + } + sigktou(&set, sp); +} + #ifdef _SYSCALL32_IMPL void prgetlwpstatus32(kthread_t *t, lwpstatus32_t *sp, zone_t *zp) @@ -992,8 +1015,7 @@ prgetlwpstatus32(kthread_t *t, lwpstatus32_t *sp, zone_t *zp) sp->pr_lwpid = t->t_tid; sp->pr_cursig = lwp->lwp_cursig; prassignset(&sp->pr_lwppend, &t->t_sig); - schedctl_finish_sigblock(t); - prassignset(&sp->pr_lwphold, &t->t_hold); + prgethold(t, &sp->pr_lwphold); if (t->t_whystop == PR_FAULTED) { siginfo_kto32(&lwp->lwp_siginfo, &sp->pr_info); if (t->t_whatstop == FLTPAGE) @@ -1224,8 +1246,7 @@ prgetlwpstatus(kthread_t *t, lwpstatus_t *sp, zone_t *zp) sp->pr_lwpid = t->t_tid; sp->pr_cursig = lwp->lwp_cursig; prassignset(&sp->pr_lwppend, &t->t_sig); - schedctl_finish_sigblock(t); - prassignset(&sp->pr_lwphold, &t->t_hold); + prgethold(t, &sp->pr_lwphold); if (t->t_whystop == PR_FAULTED) bcopy(&lwp->lwp_siginfo, &sp->pr_info, sizeof (k_siginfo_t)); @@ -3197,7 +3218,6 @@ prgetlwpsinfo(kthread_t *t, lwpsinfo_t *psp) void prgetlwpsinfo32(kthread_t *t, lwpsinfo32_t *psp) { - proc_t *p = ttoproc(t); klwp_t *lwp = ttolwp(t); sobj_ops_t *sobj; char c, state; @@ -3205,7 +3225,7 @@ prgetlwpsinfo32(kthread_t *t, lwpsinfo32_t *psp) int retval, niceval; hrtime_t hrutime, hrstime; - ASSERT(MUTEX_HELD(&p->p_lock)); + ASSERT(MUTEX_HELD(&ttoproc(t)->p_lock)); bzero(psp, sizeof (*psp)); diff --git a/usr/src/uts/common/os/schedctl.c b/usr/src/uts/common/os/schedctl.c index 5721083751..18b396a765 100644 --- a/usr/src/uts/common/os/schedctl.c +++ b/usr/src/uts/common/os/schedctl.c @@ -22,6 +22,7 @@ /* * Copyright 2010 Sun Microsystems, Inc. All rights reserved. * Use is subject to license terms. + * Copyright 2016 Joyent, Inc. */ #include <sys/types.h> @@ -327,12 +328,17 @@ schedctl_sigblock(kthread_t *t) /* - * If the sc_sigblock field is set for the specified thread, set - * its signal mask to block all maskable signals, then clear the - * sc_sigblock field. This finishes what user-level code requested - * to be done when it set tdp->sc_shared->sc_sigblock non-zero. - * Called from signal-related code either by the current thread for - * itself or by a thread that holds the process's p_lock (/proc code). + * If the sc_sigblock field is set for the specified thread, set its signal + * mask to block all maskable signals, then clear the sc_sigblock field. This + * accomplishes what user-level code requested to be done when it set + * tdp->sc_shared->sc_sigblock non-zero. + * + * This is generally called by signal-related code in the current thread. In + * order to call against a thread other than curthread, p_lock for the + * containing process must be held. Even then, the caller is not protected + * from races with the thread in question updating its own fields. It is the + * responsibility of the caller to perform additional synchronization. + * */ void schedctl_finish_sigblock(kthread_t *t) |