[BACK]Return to sys_sig.c CVS log [TXT][DIR] Up to [cvs.NetBSD.org] / src / sys / kern

Annotation of src/sys/kern/sys_sig.c, Revision 1.15.2.3

1.15.2.3! wrstuden    1: /*     $NetBSD: sys_sig.c,v 1.15.2.2 2008/05/14 19:54:12 wrstuden Exp $        */
1.2       ad          2:
                      3: /*-
1.14      ad          4:  * Copyright (c) 2006, 2007, 2008 The NetBSD Foundation, Inc.
1.2       ad          5:  * All rights reserved.
                      6:  *
                      7:  * This code is derived from software contributed to The NetBSD Foundation
                      8:  * by Andrew Doran.
                      9:  *
                     10:  * Redistribution and use in source and binary forms, with or without
                     11:  * modification, are permitted provided that the following conditions
                     12:  * are met:
                     13:  * 1. Redistributions of source code must retain the above copyright
                     14:  *    notice, this list of conditions and the following disclaimer.
                     15:  * 2. Redistributions in binary form must reproduce the above copyright
                     16:  *    notice, this list of conditions and the following disclaimer in the
                     17:  *    documentation and/or other materials provided with the distribution.
                     18:  *
                     19:  * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS
                     20:  * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED
                     21:  * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
                     22:  * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS
                     23:  * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
                     24:  * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
                     25:  * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
                     26:  * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
                     27:  * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
                     28:  * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
                     29:  * POSSIBILITY OF SUCH DAMAGE.
                     30:  */
                     31:
                     32: /*
                     33:  * Copyright (c) 1982, 1986, 1989, 1991, 1993
                     34:  *     The Regents of the University of California.  All rights reserved.
                     35:  * (c) UNIX System Laboratories, Inc.
                     36:  * All or some portions of this file are derived from material licensed
                     37:  * to the University of California by American Telephone and Telegraph
                     38:  * Co. or Unix System Laboratories, Inc. and are reproduced herein with
                     39:  * the permission of UNIX System Laboratories, Inc.
                     40:  *
                     41:  * Redistribution and use in source and binary forms, with or without
                     42:  * modification, are permitted provided that the following conditions
                     43:  * are met:
                     44:  * 1. Redistributions of source code must retain the above copyright
                     45:  *    notice, this list of conditions and the following disclaimer.
                     46:  * 2. Redistributions in binary form must reproduce the above copyright
                     47:  *    notice, this list of conditions and the following disclaimer in the
                     48:  *    documentation and/or other materials provided with the distribution.
                     49:  * 3. Neither the name of the University nor the names of its contributors
                     50:  *    may be used to endorse or promote products derived from this software
                     51:  *    without specific prior written permission.
                     52:  *
                     53:  * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND
                     54:  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
                     55:  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
                     56:  * ARE DISCLAIMED.  IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE
                     57:  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
                     58:  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
                     59:  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
                     60:  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
                     61:  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
                     62:  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
                     63:  * SUCH DAMAGE.
                     64:  *
                     65:  *     @(#)kern_sig.c  8.14 (Berkeley) 5/14/95
                     66:  */
                     67:
                     68: #include <sys/cdefs.h>
1.15.2.3! wrstuden   69: __KERNEL_RCSID(0, "$NetBSD: sys_sig.c,v 1.15.2.2 2008/05/14 19:54:12 wrstuden Exp $");
1.2       ad         70:
                     71: #include "opt_ptrace.h"
                     72: #include "opt_compat_netbsd.h"
                     73: #include "opt_compat_netbsd32.h"
                     74:
                     75: #include <sys/param.h>
                     76: #include <sys/kernel.h>
                     77: #include <sys/signalvar.h>
                     78: #include <sys/proc.h>
                     79: #include <sys/pool.h>
                     80: #include <sys/syscallargs.h>
                     81: #include <sys/kauth.h>
                     82: #include <sys/wait.h>
                     83: #include <sys/kmem.h>
                     84:
                     85: #ifdef COMPAT_16
                     86: /* ARGSUSED */
                     87: int
1.9       dsl        88: compat_16_sys___sigaction14(struct lwp *l, const struct compat_16_sys___sigaction14_args *uap, register_t *retval)
1.2       ad         89: {
1.9       dsl        90:        /* {
1.2       ad         91:                syscallarg(int)                         signum;
                     92:                syscallarg(const struct sigaction *)    nsa;
                     93:                syscallarg(struct sigaction *)          osa;
1.9       dsl        94:        } */
1.2       ad         95:        struct sigaction        nsa, osa;
                     96:        int                     error;
                     97:
                     98:        if (SCARG(uap, nsa)) {
                     99:                error = copyin(SCARG(uap, nsa), &nsa, sizeof(nsa));
                    100:                if (error)
                    101:                        return (error);
                    102:        }
                    103:        error = sigaction1(l, SCARG(uap, signum),
                    104:            SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0,
                    105:            NULL, 0);
                    106:        if (error)
                    107:                return (error);
                    108:        if (SCARG(uap, osa)) {
                    109:                error = copyout(&osa, SCARG(uap, osa), sizeof(osa));
                    110:                if (error)
                    111:                        return (error);
                    112:        }
                    113:        return (0);
                    114: }
                    115: #endif
                    116:
                    117: /* ARGSUSED */
                    118: int
1.9       dsl       119: sys___sigaction_sigtramp(struct lwp *l, const struct sys___sigaction_sigtramp_args *uap, register_t *retval)
1.2       ad        120: {
1.9       dsl       121:        /* {
1.2       ad        122:                syscallarg(int)                         signum;
                    123:                syscallarg(const struct sigaction *)    nsa;
                    124:                syscallarg(struct sigaction *)          osa;
                    125:                syscallarg(void *)                      tramp;
                    126:                syscallarg(int)                         vers;
1.9       dsl       127:        } */
1.2       ad        128:        struct sigaction nsa, osa;
                    129:        int error;
                    130:
                    131:        if (SCARG(uap, nsa)) {
                    132:                error = copyin(SCARG(uap, nsa), &nsa, sizeof(nsa));
                    133:                if (error)
                    134:                        return (error);
                    135:        }
                    136:        error = sigaction1(l, SCARG(uap, signum),
                    137:            SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0,
                    138:            SCARG(uap, tramp), SCARG(uap, vers));
                    139:        if (error)
                    140:                return (error);
                    141:        if (SCARG(uap, osa)) {
                    142:                error = copyout(&osa, SCARG(uap, osa), sizeof(osa));
                    143:                if (error)
                    144:                        return (error);
                    145:        }
                    146:        return (0);
                    147: }
                    148:
                    149: /*
                    150:  * Manipulate signal mask.  Note that we receive new mask, not pointer, and
                    151:  * return old mask as return value; the library stub does the rest.
                    152:  */
                    153: int
1.9       dsl       154: sys___sigprocmask14(struct lwp *l, const struct sys___sigprocmask14_args *uap, register_t *retval)
1.2       ad        155: {
1.9       dsl       156:        /* {
1.2       ad        157:                syscallarg(int)                 how;
                    158:                syscallarg(const sigset_t *)    set;
                    159:                syscallarg(sigset_t *)          oset;
1.9       dsl       160:        } */
1.2       ad        161:        struct proc     *p = l->l_proc;
                    162:        sigset_t        nss, oss;
                    163:        int             error;
                    164:
                    165:        if (SCARG(uap, set)) {
                    166:                error = copyin(SCARG(uap, set), &nss, sizeof(nss));
                    167:                if (error)
                    168:                        return (error);
                    169:        }
1.14      ad        170:        mutex_enter(p->p_lock);
1.2       ad        171:        error = sigprocmask1(l, SCARG(uap, how),
                    172:            SCARG(uap, set) ? &nss : 0, SCARG(uap, oset) ? &oss : 0);
1.14      ad        173:        mutex_exit(p->p_lock);
1.2       ad        174:        if (error)
                    175:                return (error);
                    176:        if (SCARG(uap, oset)) {
                    177:                error = copyout(&oss, SCARG(uap, oset), sizeof(oss));
                    178:                if (error)
                    179:                        return (error);
                    180:        }
                    181:        return (0);
                    182: }
                    183:
                    184: /* ARGSUSED */
                    185: int
1.9       dsl       186: sys___sigpending14(struct lwp *l, const struct sys___sigpending14_args *uap, register_t *retval)
1.2       ad        187: {
1.9       dsl       188:        /* {
1.2       ad        189:                syscallarg(sigset_t *)  set;
1.9       dsl       190:        } */
1.2       ad        191:        sigset_t ss;
                    192:
                    193:        sigpending1(l, &ss);
                    194:        return (copyout(&ss, SCARG(uap, set), sizeof(ss)));
                    195: }
                    196:
                    197: /*
                    198:  * Suspend process until signal, providing mask to be set in the meantime.
                    199:  * Note nonstandard calling convention: libc stub passes mask, not pointer,
                    200:  * to save a copyin.
                    201:  */
                    202: /* ARGSUSED */
                    203: int
1.9       dsl       204: sys___sigsuspend14(struct lwp *l, const struct sys___sigsuspend14_args *uap, register_t *retval)
1.2       ad        205: {
1.9       dsl       206:        /* {
1.2       ad        207:                syscallarg(const sigset_t *)    set;
1.9       dsl       208:        } */
1.2       ad        209:        sigset_t        ss;
                    210:        int             error;
                    211:
                    212:        if (SCARG(uap, set)) {
                    213:                error = copyin(SCARG(uap, set), &ss, sizeof(ss));
                    214:                if (error)
                    215:                        return (error);
                    216:        }
                    217:
                    218:        return (sigsuspend1(l, SCARG(uap, set) ? &ss : 0));
                    219: }
                    220:
                    221: /* ARGSUSED */
                    222: int
1.9       dsl       223: sys___sigaltstack14(struct lwp *l, const struct sys___sigaltstack14_args *uap, register_t *retval)
1.2       ad        224: {
1.9       dsl       225:        /* {
1.2       ad        226:                syscallarg(const struct sigaltstack *)  nss;
                    227:                syscallarg(struct sigaltstack *)        oss;
1.9       dsl       228:        } */
1.2       ad        229:        struct sigaltstack      nss, oss;
                    230:        int                     error;
                    231:
                    232:        if (SCARG(uap, nss)) {
                    233:                error = copyin(SCARG(uap, nss), &nss, sizeof(nss));
                    234:                if (error)
                    235:                        return (error);
                    236:        }
                    237:        error = sigaltstack1(l,
                    238:            SCARG(uap, nss) ? &nss : 0, SCARG(uap, oss) ? &oss : 0);
                    239:        if (error)
                    240:                return (error);
                    241:        if (SCARG(uap, oss)) {
                    242:                error = copyout(&oss, SCARG(uap, oss), sizeof(oss));
                    243:                if (error)
                    244:                        return (error);
                    245:        }
                    246:        return (0);
                    247: }
                    248:
                    249: /* ARGSUSED */
                    250: int
1.9       dsl       251: sys_kill(struct lwp *l, const struct sys_kill_args *uap, register_t *retval)
1.2       ad        252: {
1.9       dsl       253:        /* {
1.2       ad        254:                syscallarg(int) pid;
                    255:                syscallarg(int) signum;
1.9       dsl       256:        } */
1.2       ad        257:        struct proc     *p;
                    258:        ksiginfo_t      ksi;
                    259:        int signum = SCARG(uap, signum);
                    260:        int error;
                    261:
                    262:        if ((u_int)signum >= NSIG)
                    263:                return (EINVAL);
                    264:        KSI_INIT(&ksi);
                    265:        ksi.ksi_signo = signum;
                    266:        ksi.ksi_code = SI_USER;
                    267:        ksi.ksi_pid = l->l_proc->p_pid;
                    268:        ksi.ksi_uid = kauth_cred_geteuid(l->l_cred);
                    269:        if (SCARG(uap, pid) > 0) {
                    270:                /* kill single process */
1.13      ad        271:                mutex_enter(proc_lock);
                    272:                if ((p = p_find(SCARG(uap, pid), PFIND_LOCKED)) == NULL) {
                    273:                        mutex_exit(proc_lock);
1.2       ad        274:                        return (ESRCH);
1.13      ad        275:                }
1.14      ad        276:                mutex_enter(p->p_lock);
1.2       ad        277:                error = kauth_authorize_process(l->l_cred,
1.11      elad      278:                    KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum),
1.2       ad        279:                    NULL, NULL);
                    280:                if (!error && signum) {
                    281:                        kpsignal2(p, &ksi);
                    282:                }
1.14      ad        283:                mutex_exit(p->p_lock);
1.13      ad        284:                mutex_exit(proc_lock);
1.2       ad        285:                return (error);
                    286:        }
                    287:        switch (SCARG(uap, pid)) {
                    288:        case -1:                /* broadcast signal */
                    289:                return (killpg1(l, &ksi, 0, 1));
                    290:        case 0:                 /* signal own process group */
                    291:                return (killpg1(l, &ksi, 0, 0));
                    292:        default:                /* negative explicit process group */
                    293:                return (killpg1(l, &ksi, -SCARG(uap, pid), 0));
                    294:        }
                    295:        /* NOTREACHED */
                    296: }
                    297:
                    298: /* ARGSUSED */
                    299: int
1.9       dsl       300: sys_getcontext(struct lwp *l, const struct sys_getcontext_args *uap, register_t *retval)
1.2       ad        301: {
1.9       dsl       302:        /* {
1.2       ad        303:                syscallarg(struct __ucontext *) ucp;
1.9       dsl       304:        } */
1.2       ad        305:        struct proc *p = l->l_proc;
                    306:        ucontext_t uc;
                    307:
1.14      ad        308:        mutex_enter(p->p_lock);
1.2       ad        309:        getucontext(l, &uc);
1.14      ad        310:        mutex_exit(p->p_lock);
1.2       ad        311:
                    312:        return (copyout(&uc, SCARG(uap, ucp), sizeof (*SCARG(uap, ucp))));
                    313: }
                    314:
                    315: /* ARGSUSED */
                    316: int
1.9       dsl       317: sys_setcontext(struct lwp *l, const struct sys_setcontext_args *uap, register_t *retval)
1.2       ad        318: {
1.9       dsl       319:        /* {
1.2       ad        320:                syscallarg(const ucontext_t *) ucp;
1.9       dsl       321:        } */
1.2       ad        322:        struct proc *p = l->l_proc;
                    323:        ucontext_t uc;
                    324:        int error;
                    325:
                    326:        error = copyin(SCARG(uap, ucp), &uc, sizeof (uc));
                    327:        if (error)
                    328:                return (error);
                    329:        if (!(uc.uc_flags & _UC_CPU))
                    330:                return (EINVAL);
1.14      ad        331:        mutex_enter(p->p_lock);
1.2       ad        332:        error = setucontext(l, &uc);
1.14      ad        333:        mutex_exit(p->p_lock);
1.2       ad        334:        if (error)
                    335:                return (error);
                    336:
                    337:        return (EJUSTRETURN);
                    338: }
                    339:
                    340: /*
                    341:  * sigtimedwait(2) system call, used also for implementation
                    342:  * of sigwaitinfo() and sigwait().
                    343:  *
                    344:  * This only handles single LWP in signal wait. libpthread provides
                    345:  * it's own sigtimedwait() wrapper to DTRT WRT individual threads.
                    346:  */
                    347: int
1.9       dsl       348: sys___sigtimedwait(struct lwp *l, const struct sys___sigtimedwait_args *uap, register_t *retval)
1.2       ad        349: {
                    350:
1.9       dsl       351:        return __sigtimedwait1(l, uap, retval, copyout, copyin, copyout);
1.2       ad        352: }
                    353:
                    354: int
                    355: sigaction1(struct lwp *l, int signum, const struct sigaction *nsa,
                    356:        struct sigaction *osa, const void *tramp, int vers)
                    357: {
                    358:        struct proc *p;
                    359:        struct sigacts *ps;
                    360:        sigset_t tset;
                    361:        int prop, error;
                    362:        ksiginfoq_t kq;
                    363:
                    364:        if (signum <= 0 || signum >= NSIG)
                    365:                return (EINVAL);
                    366:
                    367:        p = l->l_proc;
                    368:        error = 0;
                    369:        ksiginfo_queue_init(&kq);
                    370:
                    371:        /*
                    372:         * Trampoline ABI version 0 is reserved for the legacy kernel
                    373:         * provided on-stack trampoline.  Conversely, if we are using a
                    374:         * non-0 ABI version, we must have a trampoline.  Only validate the
                    375:         * vers if a new sigaction was supplied. Emulations use legacy
                    376:         * kernel trampolines with version 0, alternatively check for that
                    377:         * too.
                    378:         */
                    379:        if ((vers != 0 && tramp == NULL) ||
                    380: #ifdef SIGTRAMP_VALID
                    381:            (nsa != NULL &&
                    382:            ((vers == 0) ?
                    383:                (p->p_emul->e_sigcode == NULL) :
                    384:                !SIGTRAMP_VALID(vers))) ||
                    385: #endif
                    386:            (vers == 0 && tramp != NULL)) {
                    387:                return (EINVAL);
                    388:        }
                    389:
1.14      ad        390:        mutex_enter(p->p_lock);
1.2       ad        391:
                    392:        ps = p->p_sigacts;
                    393:        if (osa)
                    394:                *osa = SIGACTION_PS(ps, signum);
                    395:        if (!nsa)
                    396:                goto out;
                    397:
                    398:        prop = sigprop[signum];
                    399:        if ((nsa->sa_flags & ~SA_ALLBITS) || (prop & SA_CANTMASK)) {
                    400:                error = EINVAL;
                    401:                goto out;
                    402:        }
                    403:
                    404:        SIGACTION_PS(ps, signum) = *nsa;
                    405:        ps->sa_sigdesc[signum].sd_tramp = tramp;
                    406:        ps->sa_sigdesc[signum].sd_vers = vers;
                    407:        sigminusset(&sigcantmask, &SIGACTION_PS(ps, signum).sa_mask);
                    408:
                    409:        if ((prop & SA_NORESET) != 0)
                    410:                SIGACTION_PS(ps, signum).sa_flags &= ~SA_RESETHAND;
                    411:
                    412:        if (signum == SIGCHLD) {
                    413:                if (nsa->sa_flags & SA_NOCLDSTOP)
                    414:                        p->p_sflag |= PS_NOCLDSTOP;
                    415:                else
                    416:                        p->p_sflag &= ~PS_NOCLDSTOP;
                    417:                if (nsa->sa_flags & SA_NOCLDWAIT) {
                    418:                        /*
                    419:                         * Paranoia: since SA_NOCLDWAIT is implemented by
                    420:                         * reparenting the dying child to PID 1 (and trust
                    421:                         * it to reap the zombie), PID 1 itself is forbidden
                    422:                         * to set SA_NOCLDWAIT.
                    423:                         */
                    424:                        if (p->p_pid == 1)
1.4       pavel     425:                                p->p_flag &= ~PK_NOCLDWAIT;
1.2       ad        426:                        else
1.4       pavel     427:                                p->p_flag |= PK_NOCLDWAIT;
1.2       ad        428:                } else
1.4       pavel     429:                        p->p_flag &= ~PK_NOCLDWAIT;
1.2       ad        430:
                    431:                if (nsa->sa_handler == SIG_IGN) {
                    432:                        /*
                    433:                         * Paranoia: same as above.
                    434:                         */
                    435:                        if (p->p_pid == 1)
1.4       pavel     436:                                p->p_flag &= ~PK_CLDSIGIGN;
1.2       ad        437:                        else
1.4       pavel     438:                                p->p_flag |= PK_CLDSIGIGN;
1.2       ad        439:                } else
1.4       pavel     440:                        p->p_flag &= ~PK_CLDSIGIGN;
1.2       ad        441:        }
                    442:
                    443:        if ((nsa->sa_flags & SA_NODEFER) == 0)
                    444:                sigaddset(&SIGACTION_PS(ps, signum).sa_mask, signum);
                    445:        else
                    446:                sigdelset(&SIGACTION_PS(ps, signum).sa_mask, signum);
                    447:
                    448:        /*
                    449:         * Set bit in p_sigctx.ps_sigignore for signals that are set to
                    450:         * SIG_IGN, and for signals set to SIG_DFL where the default is to
                    451:         * ignore. However, don't put SIGCONT in p_sigctx.ps_sigignore, as
                    452:         * we have to restart the process.
                    453:         */
                    454:        if (nsa->sa_handler == SIG_IGN ||
                    455:            (nsa->sa_handler == SIG_DFL && (prop & SA_IGNORE) != 0)) {
                    456:                /* Never to be seen again. */
                    457:                sigemptyset(&tset);
                    458:                sigaddset(&tset, signum);
                    459:                sigclearall(p, &tset, &kq);
                    460:                if (signum != SIGCONT) {
                    461:                        /* Easier in psignal */
                    462:                        sigaddset(&p->p_sigctx.ps_sigignore, signum);
                    463:                }
                    464:                sigdelset(&p->p_sigctx.ps_sigcatch, signum);
                    465:        } else {
                    466:                sigdelset(&p->p_sigctx.ps_sigignore, signum);
                    467:                if (nsa->sa_handler == SIG_DFL)
                    468:                        sigdelset(&p->p_sigctx.ps_sigcatch, signum);
                    469:                else
                    470:                        sigaddset(&p->p_sigctx.ps_sigcatch, signum);
                    471:        }
                    472:
                    473:        /*
                    474:         * Previously held signals may now have become visible.  Ensure that
                    475:         * we check for them before returning to userspace.
                    476:         */
1.6       ad        477:        if (sigispending(l, 0)) {
                    478:                lwp_lock(l);
                    479:                l->l_flag |= LW_PENDSIG;
                    480:                lwp_unlock(l);
                    481:        }
1.2       ad        482:  out:
1.14      ad        483:        mutex_exit(p->p_lock);
1.2       ad        484:        ksiginfo_queue_drain(&kq);
                    485:
                    486:        return (error);
                    487: }
                    488:
                    489: int
                    490: sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss)
                    491: {
                    492:        int more;
                    493:
1.14      ad        494:        KASSERT(mutex_owned(l->l_proc->p_lock));
1.2       ad        495:
                    496:        if (oss)
1.15.2.2  wrstuden  497:                *oss = l->l_sigmask;
1.2       ad        498:        if (nss) {
                    499:                switch (how) {
                    500:                case SIG_BLOCK:
1.15.2.2  wrstuden  501:                        sigplusset(nss, &l->l_sigmask);
1.2       ad        502:                        more = 0;
                    503:                        break;
                    504:                case SIG_UNBLOCK:
1.15.2.2  wrstuden  505:                        sigminusset(nss, &l->l_sigmask);
1.2       ad        506:                        more = 1;
                    507:                        break;
                    508:                case SIG_SETMASK:
1.15.2.2  wrstuden  509:                        l->l_sigmask = *nss;
1.2       ad        510:                        more = 1;
                    511:                        break;
                    512:                default:
                    513:                        return (EINVAL);
                    514:                }
1.15.2.2  wrstuden  515:                sigminusset(&sigcantmask, &l->l_sigmask);
1.6       ad        516:                if (more && sigispending(l, 0)) {
1.2       ad        517:                        /*
                    518:                         * Check for pending signals on return to user.
                    519:                         */
                    520:                        lwp_lock(l);
1.4       pavel     521:                        l->l_flag |= LW_PENDSIG;
1.2       ad        522:                        lwp_unlock(l);
                    523:                }
                    524:        }
                    525:
                    526:        return (0);
                    527: }
                    528:
                    529: void
                    530: sigpending1(struct lwp *l, sigset_t *ss)
                    531: {
                    532:        struct proc *p = l->l_proc;
                    533:
1.14      ad        534:        mutex_enter(p->p_lock);
1.2       ad        535:        *ss = l->l_sigpend.sp_set;
                    536:        sigplusset(&p->p_sigpend.sp_set, ss);
1.15.2.2  wrstuden  537:        sigminusset(&l->l_sigmask, ss);
1.14      ad        538:        mutex_exit(p->p_lock);
1.2       ad        539: }
                    540:
                    541: int
                    542: sigsuspend1(struct lwp *l, const sigset_t *ss)
                    543: {
                    544:        struct proc *p;
                    545:
                    546:        p = l->l_proc;
                    547:
                    548:        if (ss) {
                    549:                /*
1.12      yamt      550:                 * When returning from sigsuspend, we want
1.2       ad        551:                 * the old mask to be restored after the
                    552:                 * signal handler has finished.  Thus, we
                    553:                 * save it here and mark the sigctx structure
                    554:                 * to indicate this.
                    555:                 */
1.14      ad        556:                mutex_enter(p->p_lock);
1.2       ad        557:                l->l_sigrestore = 1;
1.15.2.2  wrstuden  558:                l->l_sigoldmask = l->l_sigmask;
                    559:                l->l_sigmask = *ss;
                    560:                sigminusset(&sigcantmask, &l->l_sigmask);
1.2       ad        561:
                    562:                /* Check for pending signals when sleeping. */
1.6       ad        563:                if (sigispending(l, 0)) {
                    564:                        lwp_lock(l);
                    565:                        l->l_flag |= LW_PENDSIG;
                    566:                        lwp_unlock(l);
                    567:                }
1.14      ad        568:                mutex_exit(p->p_lock);
1.2       ad        569:        }
                    570:
1.5       thorpej   571:        while (kpause("pause", true, 0, NULL) == 0)
1.2       ad        572:                ;
                    573:
                    574:        /* always return EINTR rather than ERESTART... */
                    575:        return (EINTR);
                    576: }
                    577:
                    578: int
                    579: sigaltstack1(struct lwp *l, const struct sigaltstack *nss,
                    580:             struct sigaltstack *oss)
                    581: {
                    582:        struct proc *p = l->l_proc;
                    583:        int error = 0;
                    584:
1.14      ad        585:        mutex_enter(p->p_lock);
1.2       ad        586:
                    587:        if (oss)
1.15.2.2  wrstuden  588:                *oss = l->l_sigstk;
1.2       ad        589:
                    590:        if (nss) {
                    591:                if (nss->ss_flags & ~SS_ALLBITS)
                    592:                        error = EINVAL;
                    593:                else if (nss->ss_flags & SS_DISABLE) {
1.15.2.2  wrstuden  594:                        if (l->l_sigstk.ss_flags & SS_ONSTACK)
1.2       ad        595:                                error = EINVAL;
                    596:                } else if (nss->ss_size < MINSIGSTKSZ)
                    597:                        error = ENOMEM;
                    598:
                    599:                if (!error)
1.15.2.2  wrstuden  600:                        l->l_sigstk = *nss;
1.2       ad        601:        }
                    602:
1.14      ad        603:        mutex_exit(p->p_lock);
1.2       ad        604:
                    605:        return (error);
                    606: }
                    607:
                    608: int
1.9       dsl       609: __sigtimedwait1(struct lwp *l, const struct sys___sigtimedwait_args *uap, register_t *retval,
1.2       ad        610:     copyout_t put_info, copyin_t fetch_timeout, copyout_t put_timeout)
                    611: {
1.9       dsl       612:        /* {
1.2       ad        613:                syscallarg(const sigset_t *) set;
                    614:                syscallarg(siginfo_t *) info;
                    615:                syscallarg(struct timespec *) timeout;
1.9       dsl       616:        } */
1.2       ad        617:        struct proc *p = l->l_proc;
                    618:        int error, signum;
                    619:        int timo = 0;
                    620:        struct timespec ts, tsstart, tsnow;
                    621:        ksiginfo_t *ksi;
                    622:
                    623:        memset(&tsstart, 0, sizeof tsstart);     /* XXX gcc */
                    624:
                    625:        /*
                    626:         * Calculate timeout, if it was specified.
                    627:         */
                    628:        if (SCARG(uap, timeout)) {
                    629:                uint64_t ms;
                    630:
                    631:                if ((error = (*fetch_timeout)(SCARG(uap, timeout), &ts, sizeof(ts))))
                    632:                        return (error);
                    633:
                    634:                ms = (ts.tv_sec * 1000) + (ts.tv_nsec / 1000000);
                    635:                timo = mstohz(ms);
                    636:                if (timo == 0 && ts.tv_sec == 0 && ts.tv_nsec > 0)
                    637:                        timo = 1;
                    638:                if (timo <= 0)
                    639:                        return (EAGAIN);
                    640:
                    641:                /*
                    642:                 * Remember current uptime, it would be used in
                    643:                 * ECANCELED/ERESTART case.
                    644:                 */
                    645:                getnanouptime(&tsstart);
                    646:        }
                    647:
                    648:        error = copyin(SCARG(uap, set), &l->l_sigwaitset,
                    649:            sizeof(l->l_sigwaitset));
                    650:        if (error != 0)
                    651:                return (error);
                    652:
                    653:        /*
                    654:         * Silently ignore SA_CANTMASK signals. psignal1() would ignore
                    655:         * SA_CANTMASK signals in waitset, we do this only for the below
                    656:         * siglist check.
                    657:         */
                    658:        sigminusset(&sigcantmask, &l->l_sigwaitset);
                    659:
                    660:        /*
                    661:         * Allocate a ksi up front.  We can't sleep with the mutex held.
                    662:         */
                    663:        ksi = ksiginfo_alloc(p, NULL, PR_WAITOK);
                    664:        if (ksi == NULL)
                    665:                return (ENOMEM);
                    666:
1.14      ad        667:        mutex_enter(p->p_lock);
1.2       ad        668:
1.15.2.3! wrstuden  669:        /*
        !           670:         * SA processes can have no more than 1 sigwaiter.
        !           671:         */
        !           672:        if ((p->p_sflag & PS_SA) != 0 && !LIST_EMPTY(&p->p_sigwaiters)) {
        !           673:                mutex_exit(p->p_lock);
        !           674:                error = EINVAL;
        !           675:                goto out;
        !           676:        }
        !           677:
1.2       ad        678:        if ((signum = sigget(&p->p_sigpend, ksi, 0, &l->l_sigwaitset)) == 0)
                    679:                signum = sigget(&l->l_sigpend, ksi, 0, &l->l_sigwaitset);
                    680:
                    681:        if (signum != 0) {
                    682:                /*
                    683:                 * We found a pending signal - copy it out to the user.
                    684:                 */
1.14      ad        685:                mutex_exit(p->p_lock);
1.2       ad        686:                goto out;
                    687:        }
                    688:
                    689:        /*
                    690:         * Set up the sigwait list.
                    691:         */
                    692:        l->l_sigwaited = ksi;
                    693:        LIST_INSERT_HEAD(&p->p_sigwaiters, l, l_sigwaiter);
                    694:
                    695:        /*
                    696:         * Wait for signal to arrive. We can either be woken up or time out.
                    697:         */
1.14      ad        698:        error = cv_timedwait_sig(&l->l_sigcv, p->p_lock, timo);
1.2       ad        699:
                    700:        /*
                    701:         * Need to find out if we woke as a result of lwp_wakeup() or a
                    702:         * signal outside our wait set.
                    703:         */
                    704:        if (l->l_sigwaited != NULL) {
                    705:                if (error == EINTR) {
                    706:                        /* wakeup via _lwp_wakeup() */
                    707:                        error = ECANCELED;
                    708:                } else if (!error) {
                    709:                        /* spurious wakeup - arrange for syscall restart */
                    710:                        error = ERESTART;
                    711:                }
                    712:                l->l_sigwaited = NULL;
                    713:                LIST_REMOVE(l, l_sigwaiter);
                    714:        }
                    715:
1.14      ad        716:        mutex_exit(p->p_lock);
1.2       ad        717:
                    718:        /*
                    719:         * If the sleep was interrupted (either by signal or wakeup), update
                    720:         * the timeout and copyout new value back.  It would be used when
                    721:         * the syscall would be restarted or called again.
                    722:         */
                    723:        if (timo && (error == ERESTART || error == ECANCELED)) {
                    724:                getnanouptime(&tsnow);
                    725:
                    726:                /* compute how much time has passed since start */
                    727:                timespecsub(&tsnow, &tsstart, &tsnow);
                    728:                /* substract passed time from timeout */
                    729:                timespecsub(&ts, &tsnow, &ts);
                    730:
                    731:                if (ts.tv_sec < 0)
                    732:                        error = EAGAIN;
                    733:                else {
                    734:                        /* copy updated timeout to userland */
                    735:                        error = (*put_timeout)(&ts, SCARG(uap, timeout),
                    736:                            sizeof(ts));
                    737:                }
                    738:        }
                    739:
                    740:        /*
                    741:         * If a signal from the wait set arrived, copy it to userland.
                    742:         * Copy only the used part of siginfo, the padding part is
                    743:         * left unchanged (userland is not supposed to touch it anyway).
                    744:         */
                    745:  out:
                    746:        if (error == 0)
                    747:                error = (*put_info)(&ksi->ksi_info, SCARG(uap, info),
                    748:                    sizeof(ksi->ksi_info));
                    749:
                    750:        ksiginfo_free(ksi);
                    751:
                    752:        return error;
                    753: }

CVSweb <webmaster@jp.NetBSD.org>