[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.36.4.1

1.36.4.1! mrg         1: /*     $NetBSD: sys_sig.c,v 1.37 2012/02/19 21:06:57 rmind 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.36.4.1! mrg        69: __KERNEL_RCSID(0, "$NetBSD: sys_sig.c,v 1.37 2012/02/19 21:06:57 rmind Exp $");
1.2       ad         70:
                     71: #include <sys/param.h>
                     72: #include <sys/kernel.h>
                     73: #include <sys/signalvar.h>
                     74: #include <sys/proc.h>
                     75: #include <sys/pool.h>
                     76: #include <sys/syscallargs.h>
                     77: #include <sys/kauth.h>
                     78: #include <sys/wait.h>
                     79: #include <sys/kmem.h>
1.19      ad         80: #include <sys/module.h>
1.2       ad         81:
                     82: int
1.25      rmind      83: sys___sigaction_sigtramp(struct lwp *l,
                     84:     const struct sys___sigaction_sigtramp_args *uap, register_t *retval)
1.2       ad         85: {
1.9       dsl        86:        /* {
1.2       ad         87:                syscallarg(int)                         signum;
                     88:                syscallarg(const struct sigaction *)    nsa;
                     89:                syscallarg(struct sigaction *)          osa;
                     90:                syscallarg(void *)                      tramp;
                     91:                syscallarg(int)                         vers;
1.9       dsl        92:        } */
1.2       ad         93:        struct sigaction nsa, osa;
                     94:        int error;
                     95:
                     96:        if (SCARG(uap, nsa)) {
                     97:                error = copyin(SCARG(uap, nsa), &nsa, sizeof(nsa));
                     98:                if (error)
                     99:                        return (error);
                    100:        }
                    101:        error = sigaction1(l, SCARG(uap, signum),
                    102:            SCARG(uap, nsa) ? &nsa : 0, SCARG(uap, osa) ? &osa : 0,
                    103:            SCARG(uap, tramp), SCARG(uap, vers));
                    104:        if (error)
                    105:                return (error);
                    106:        if (SCARG(uap, osa)) {
                    107:                error = copyout(&osa, SCARG(uap, osa), sizeof(osa));
                    108:                if (error)
                    109:                        return (error);
                    110:        }
1.25      rmind     111:        return 0;
1.2       ad        112: }
                    113:
                    114: /*
                    115:  * Manipulate signal mask.  Note that we receive new mask, not pointer, and
                    116:  * return old mask as return value; the library stub does the rest.
                    117:  */
                    118: int
1.25      rmind     119: sys___sigprocmask14(struct lwp *l, const struct sys___sigprocmask14_args *uap,
                    120:     register_t *retval)
1.2       ad        121: {
1.9       dsl       122:        /* {
1.2       ad        123:                syscallarg(int)                 how;
                    124:                syscallarg(const sigset_t *)    set;
                    125:                syscallarg(sigset_t *)          oset;
1.9       dsl       126:        } */
1.2       ad        127:        struct proc     *p = l->l_proc;
                    128:        sigset_t        nss, oss;
                    129:        int             error;
                    130:
                    131:        if (SCARG(uap, set)) {
                    132:                error = copyin(SCARG(uap, set), &nss, sizeof(nss));
                    133:                if (error)
1.25      rmind     134:                        return error;
1.2       ad        135:        }
1.14      ad        136:        mutex_enter(p->p_lock);
1.2       ad        137:        error = sigprocmask1(l, SCARG(uap, how),
                    138:            SCARG(uap, set) ? &nss : 0, SCARG(uap, oset) ? &oss : 0);
1.14      ad        139:        mutex_exit(p->p_lock);
1.2       ad        140:        if (error)
1.25      rmind     141:                return error;
1.2       ad        142:        if (SCARG(uap, oset)) {
                    143:                error = copyout(&oss, SCARG(uap, oset), sizeof(oss));
                    144:                if (error)
1.25      rmind     145:                        return error;
1.2       ad        146:        }
1.25      rmind     147:        return 0;
1.2       ad        148: }
                    149:
                    150: int
1.25      rmind     151: sys___sigpending14(struct lwp *l, const struct sys___sigpending14_args *uap,
                    152:     register_t *retval)
1.2       ad        153: {
1.9       dsl       154:        /* {
1.2       ad        155:                syscallarg(sigset_t *)  set;
1.9       dsl       156:        } */
1.2       ad        157:        sigset_t ss;
                    158:
                    159:        sigpending1(l, &ss);
1.25      rmind     160:        return copyout(&ss, SCARG(uap, set), sizeof(ss));
1.2       ad        161: }
                    162:
                    163: /*
                    164:  * Suspend process until signal, providing mask to be set in the meantime.
                    165:  * Note nonstandard calling convention: libc stub passes mask, not pointer,
                    166:  * to save a copyin.
                    167:  */
                    168: int
1.25      rmind     169: sys___sigsuspend14(struct lwp *l, const struct sys___sigsuspend14_args *uap,
                    170:     register_t *retval)
1.2       ad        171: {
1.9       dsl       172:        /* {
1.2       ad        173:                syscallarg(const sigset_t *)    set;
1.9       dsl       174:        } */
1.2       ad        175:        sigset_t        ss;
                    176:        int             error;
                    177:
                    178:        if (SCARG(uap, set)) {
                    179:                error = copyin(SCARG(uap, set), &ss, sizeof(ss));
                    180:                if (error)
1.25      rmind     181:                        return error;
1.2       ad        182:        }
1.25      rmind     183:        return sigsuspend1(l, SCARG(uap, set) ? &ss : 0);
1.2       ad        184: }
                    185:
                    186: int
1.25      rmind     187: sys___sigaltstack14(struct lwp *l, const struct sys___sigaltstack14_args *uap,
                    188:     register_t *retval)
1.2       ad        189: {
1.9       dsl       190:        /* {
1.2       ad        191:                syscallarg(const struct sigaltstack *)  nss;
                    192:                syscallarg(struct sigaltstack *)        oss;
1.9       dsl       193:        } */
1.2       ad        194:        struct sigaltstack      nss, oss;
                    195:        int                     error;
                    196:
                    197:        if (SCARG(uap, nss)) {
                    198:                error = copyin(SCARG(uap, nss), &nss, sizeof(nss));
                    199:                if (error)
1.25      rmind     200:                        return error;
1.2       ad        201:        }
                    202:        error = sigaltstack1(l,
                    203:            SCARG(uap, nss) ? &nss : 0, SCARG(uap, oss) ? &oss : 0);
                    204:        if (error)
1.25      rmind     205:                return error;
1.2       ad        206:        if (SCARG(uap, oss)) {
                    207:                error = copyout(&oss, SCARG(uap, oss), sizeof(oss));
                    208:                if (error)
1.25      rmind     209:                        return error;
1.2       ad        210:        }
1.25      rmind     211:        return 0;
1.2       ad        212: }
                    213:
1.30      christos  214:
                    215: static int
                    216: kill1(struct lwp *l, pid_t pid, ksiginfo_t *ksi, register_t *retval)
1.2       ad        217: {
                    218:        int error;
1.30      christos  219:        struct proc *p;
1.2       ad        220:
1.30      christos  221:        if ((u_int)ksi->ksi_signo >= NSIG)
1.25      rmind     222:                return EINVAL;
1.30      christos  223:
1.32      martin    224:        if (pid != l->l_proc->p_pid) {
                    225:                if (ksi->ksi_pid != l->l_proc->p_pid)
                    226:                        return EPERM;
                    227:
                    228:                if (ksi->ksi_uid != kauth_cred_geteuid(l->l_cred))
                    229:                        return EPERM;
                    230:
                    231:                switch (ksi->ksi_code) {
                    232:                case SI_USER:
                    233:                case SI_QUEUE:
                    234:                        break;
                    235:                default:
                    236:                        return EPERM;
                    237:                }
                    238:        }
1.30      christos  239:
                    240:        if (pid > 0) {
1.2       ad        241:                /* kill single process */
1.13      ad        242:                mutex_enter(proc_lock);
1.30      christos  243:                p = proc_find(pid);
1.28      rmind     244:                if (p == NULL) {
1.13      ad        245:                        mutex_exit(proc_lock);
1.25      rmind     246:                        return ESRCH;
1.13      ad        247:                }
1.14      ad        248:                mutex_enter(p->p_lock);
1.2       ad        249:                error = kauth_authorize_process(l->l_cred,
1.30      christos  250:                    KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(ksi->ksi_signo),
1.2       ad        251:                    NULL, NULL);
1.30      christos  252:                if (!error && ksi->ksi_signo) {
                    253:                        kpsignal2(p, ksi);
1.2       ad        254:                }
1.14      ad        255:                mutex_exit(p->p_lock);
1.13      ad        256:                mutex_exit(proc_lock);
1.25      rmind     257:                return error;
1.2       ad        258:        }
1.30      christos  259:
                    260:        switch (pid) {
1.2       ad        261:        case -1:                /* broadcast signal */
1.30      christos  262:                return killpg1(l, ksi, 0, 1);
1.2       ad        263:        case 0:                 /* signal own process group */
1.30      christos  264:                return killpg1(l, ksi, 0, 0);
1.2       ad        265:        default:                /* negative explicit process group */
1.30      christos  266:                return killpg1(l, ksi, -pid, 0);
1.2       ad        267:        }
                    268:        /* NOTREACHED */
                    269: }
                    270:
                    271: int
1.30      christos  272: sys_sigqueueinfo(struct lwp *l, const struct sys_sigqueueinfo_args *uap,
                    273:     register_t *retval)
                    274: {
                    275:        /* {
                    276:                syscallarg(pid_t int)   pid;
                    277:                syscallarg(const siginfo_t *)   info;
                    278:        } */
                    279:        ksiginfo_t      ksi;
                    280:        int error;
                    281:
                    282:        KSI_INIT(&ksi);
                    283:
                    284:        if ((error = copyin(&SCARG(uap, info)->_info, &ksi.ksi_info,
                    285:            sizeof(ksi.ksi_info))) != 0)
                    286:                return error;
                    287:
                    288:        return kill1(l, SCARG(uap, pid), &ksi, retval);
                    289: }
                    290:
                    291: int
                    292: sys_kill(struct lwp *l, const struct sys_kill_args *uap, register_t *retval)
                    293: {
                    294:        /* {
                    295:                syscallarg(pid_t)       pid;
                    296:                syscallarg(int) signum;
                    297:        } */
                    298:        ksiginfo_t      ksi;
                    299:
                    300:        KSI_INIT(&ksi);
                    301:
                    302:        ksi.ksi_signo = SCARG(uap, signum);
                    303:        ksi.ksi_code = SI_USER;
                    304:        ksi.ksi_pid = l->l_proc->p_pid;
                    305:        ksi.ksi_uid = kauth_cred_geteuid(l->l_cred);
                    306:
                    307:        return kill1(l, SCARG(uap, pid), &ksi, retval);
                    308: }
                    309:
                    310: int
1.25      rmind     311: sys_getcontext(struct lwp *l, const struct sys_getcontext_args *uap,
                    312:     register_t *retval)
1.2       ad        313: {
1.9       dsl       314:        /* {
1.2       ad        315:                syscallarg(struct __ucontext *) ucp;
1.9       dsl       316:        } */
1.2       ad        317:        struct proc *p = l->l_proc;
                    318:        ucontext_t uc;
                    319:
1.31      joerg     320:        memset(&uc, 0, sizeof(uc));
                    321:
1.14      ad        322:        mutex_enter(p->p_lock);
1.2       ad        323:        getucontext(l, &uc);
1.14      ad        324:        mutex_exit(p->p_lock);
1.2       ad        325:
1.25      rmind     326:        return copyout(&uc, SCARG(uap, ucp), sizeof (*SCARG(uap, ucp)));
1.2       ad        327: }
                    328:
                    329: int
1.25      rmind     330: sys_setcontext(struct lwp *l, const struct sys_setcontext_args *uap,
                    331:     register_t *retval)
1.2       ad        332: {
1.9       dsl       333:        /* {
1.2       ad        334:                syscallarg(const ucontext_t *) ucp;
1.9       dsl       335:        } */
1.2       ad        336:        struct proc *p = l->l_proc;
                    337:        ucontext_t uc;
                    338:        int error;
                    339:
                    340:        error = copyin(SCARG(uap, ucp), &uc, sizeof (uc));
                    341:        if (error)
1.25      rmind     342:                return error;
                    343:        if ((uc.uc_flags & _UC_CPU) == 0)
                    344:                return EINVAL;
1.14      ad        345:        mutex_enter(p->p_lock);
1.2       ad        346:        error = setucontext(l, &uc);
1.14      ad        347:        mutex_exit(p->p_lock);
1.2       ad        348:        if (error)
1.25      rmind     349:                return error;
1.2       ad        350:
1.25      rmind     351:        return EJUSTRETURN;
1.2       ad        352: }
                    353:
                    354: /*
                    355:  * sigtimedwait(2) system call, used also for implementation
                    356:  * of sigwaitinfo() and sigwait().
                    357:  *
                    358:  * This only handles single LWP in signal wait. libpthread provides
                    359:  * it's own sigtimedwait() wrapper to DTRT WRT individual threads.
                    360:  */
                    361: int
1.21      christos  362: sys_____sigtimedwait50(struct lwp *l,
                    363:     const struct sys_____sigtimedwait50_args *uap, register_t *retval)
1.2       ad        364: {
                    365:
1.36      christos  366:        return sigtimedwait1(l, uap, retval, copyin, copyout, copyin, copyout);
1.2       ad        367: }
                    368:
                    369: int
                    370: sigaction1(struct lwp *l, int signum, const struct sigaction *nsa,
                    371:        struct sigaction *osa, const void *tramp, int vers)
                    372: {
                    373:        struct proc *p;
                    374:        struct sigacts *ps;
                    375:        sigset_t tset;
                    376:        int prop, error;
                    377:        ksiginfoq_t kq;
1.20      ad        378:        static bool v0v1valid;
1.2       ad        379:
                    380:        if (signum <= 0 || signum >= NSIG)
1.25      rmind     381:                return EINVAL;
1.2       ad        382:
                    383:        p = l->l_proc;
                    384:        error = 0;
                    385:        ksiginfo_queue_init(&kq);
                    386:
                    387:        /*
                    388:         * Trampoline ABI version 0 is reserved for the legacy kernel
                    389:         * provided on-stack trampoline.  Conversely, if we are using a
                    390:         * non-0 ABI version, we must have a trampoline.  Only validate the
                    391:         * vers if a new sigaction was supplied. Emulations use legacy
                    392:         * kernel trampolines with version 0, alternatively check for that
                    393:         * too.
1.19      ad        394:         *
                    395:         * If version < 2, we try to autoload the compat module.  Note
                    396:         * that we interlock with the unload check in compat_modcmd()
1.29      pgoyette  397:         * using kernconfig_lock.  If the autoload fails, we don't try it
1.19      ad        398:         * again for this process.
                    399:         */
1.20      ad        400:        if (nsa != NULL) {
                    401:                if (__predict_false(vers < 2) &&
                    402:                    (p->p_lflag & PL_SIGCOMPAT) == 0) {
1.29      pgoyette  403:                        kernconfig_lock();
1.20      ad        404:                        if (sendsig_sigcontext_vec == NULL) {
                    405:                                (void)module_autoload("compat",
                    406:                                    MODULE_CLASS_ANY);
                    407:                        }
                    408:                        if (sendsig_sigcontext_vec != NULL) {
                    409:                                /*
                    410:                                 * We need to remember if the
                    411:                                 * sigcontext method may be useable,
                    412:                                 * because libc may use it even
                    413:                                 * if siginfo is available.
                    414:                                 */
                    415:                                v0v1valid = true;
                    416:                        }
                    417:                        mutex_enter(proc_lock);
                    418:                        /*
                    419:                         * Prevent unload of compat module while
                    420:                         * this process remains.
                    421:                         */
                    422:                        p->p_lflag |= PL_SIGCOMPAT;
                    423:                        mutex_exit(proc_lock);
1.29      pgoyette  424:                        kernconfig_unlock();
1.19      ad        425:                }
                    426:
1.20      ad        427:                switch (vers) {
                    428:                case 0:
                    429:                        /* sigcontext, kernel supplied trampoline. */
                    430:                        if (tramp != NULL || !v0v1valid) {
                    431:                                return EINVAL;
                    432:                        }
                    433:                        break;
                    434:                case 1:
                    435:                        /* sigcontext, user supplied trampoline. */
                    436:                        if (tramp == NULL || !v0v1valid) {
                    437:                                return EINVAL;
                    438:                        }
                    439:                        break;
                    440:                case 2:
                    441:                case 3:
                    442:                        /* siginfo, user supplied trampoline. */
                    443:                        if (tramp == NULL) {
                    444:                                return EINVAL;
                    445:                        }
                    446:                        break;
                    447:                default:
                    448:                        return EINVAL;
                    449:                }
1.2       ad        450:        }
                    451:
1.14      ad        452:        mutex_enter(p->p_lock);
1.2       ad        453:
                    454:        ps = p->p_sigacts;
                    455:        if (osa)
                    456:                *osa = SIGACTION_PS(ps, signum);
                    457:        if (!nsa)
                    458:                goto out;
                    459:
                    460:        prop = sigprop[signum];
                    461:        if ((nsa->sa_flags & ~SA_ALLBITS) || (prop & SA_CANTMASK)) {
                    462:                error = EINVAL;
                    463:                goto out;
                    464:        }
                    465:
                    466:        SIGACTION_PS(ps, signum) = *nsa;
                    467:        ps->sa_sigdesc[signum].sd_tramp = tramp;
                    468:        ps->sa_sigdesc[signum].sd_vers = vers;
                    469:        sigminusset(&sigcantmask, &SIGACTION_PS(ps, signum).sa_mask);
                    470:
                    471:        if ((prop & SA_NORESET) != 0)
                    472:                SIGACTION_PS(ps, signum).sa_flags &= ~SA_RESETHAND;
                    473:
                    474:        if (signum == SIGCHLD) {
                    475:                if (nsa->sa_flags & SA_NOCLDSTOP)
                    476:                        p->p_sflag |= PS_NOCLDSTOP;
                    477:                else
                    478:                        p->p_sflag &= ~PS_NOCLDSTOP;
                    479:                if (nsa->sa_flags & SA_NOCLDWAIT) {
                    480:                        /*
                    481:                         * Paranoia: since SA_NOCLDWAIT is implemented by
                    482:                         * reparenting the dying child to PID 1 (and trust
                    483:                         * it to reap the zombie), PID 1 itself is forbidden
                    484:                         * to set SA_NOCLDWAIT.
                    485:                         */
                    486:                        if (p->p_pid == 1)
1.4       pavel     487:                                p->p_flag &= ~PK_NOCLDWAIT;
1.2       ad        488:                        else
1.4       pavel     489:                                p->p_flag |= PK_NOCLDWAIT;
1.2       ad        490:                } else
1.4       pavel     491:                        p->p_flag &= ~PK_NOCLDWAIT;
1.2       ad        492:
                    493:                if (nsa->sa_handler == SIG_IGN) {
                    494:                        /*
                    495:                         * Paranoia: same as above.
                    496:                         */
                    497:                        if (p->p_pid == 1)
1.4       pavel     498:                                p->p_flag &= ~PK_CLDSIGIGN;
1.2       ad        499:                        else
1.4       pavel     500:                                p->p_flag |= PK_CLDSIGIGN;
1.2       ad        501:                } else
1.4       pavel     502:                        p->p_flag &= ~PK_CLDSIGIGN;
1.2       ad        503:        }
                    504:
                    505:        if ((nsa->sa_flags & SA_NODEFER) == 0)
                    506:                sigaddset(&SIGACTION_PS(ps, signum).sa_mask, signum);
                    507:        else
                    508:                sigdelset(&SIGACTION_PS(ps, signum).sa_mask, signum);
                    509:
                    510:        /*
                    511:         * Set bit in p_sigctx.ps_sigignore for signals that are set to
                    512:         * SIG_IGN, and for signals set to SIG_DFL where the default is to
                    513:         * ignore. However, don't put SIGCONT in p_sigctx.ps_sigignore, as
                    514:         * we have to restart the process.
                    515:         */
                    516:        if (nsa->sa_handler == SIG_IGN ||
                    517:            (nsa->sa_handler == SIG_DFL && (prop & SA_IGNORE) != 0)) {
                    518:                /* Never to be seen again. */
                    519:                sigemptyset(&tset);
                    520:                sigaddset(&tset, signum);
                    521:                sigclearall(p, &tset, &kq);
                    522:                if (signum != SIGCONT) {
                    523:                        /* Easier in psignal */
                    524:                        sigaddset(&p->p_sigctx.ps_sigignore, signum);
                    525:                }
                    526:                sigdelset(&p->p_sigctx.ps_sigcatch, signum);
                    527:        } else {
                    528:                sigdelset(&p->p_sigctx.ps_sigignore, signum);
                    529:                if (nsa->sa_handler == SIG_DFL)
                    530:                        sigdelset(&p->p_sigctx.ps_sigcatch, signum);
                    531:                else
                    532:                        sigaddset(&p->p_sigctx.ps_sigcatch, signum);
                    533:        }
                    534:
                    535:        /*
                    536:         * Previously held signals may now have become visible.  Ensure that
                    537:         * we check for them before returning to userspace.
                    538:         */
1.6       ad        539:        if (sigispending(l, 0)) {
                    540:                lwp_lock(l);
                    541:                l->l_flag |= LW_PENDSIG;
                    542:                lwp_unlock(l);
                    543:        }
1.25      rmind     544: out:
1.14      ad        545:        mutex_exit(p->p_lock);
1.2       ad        546:        ksiginfo_queue_drain(&kq);
                    547:
1.25      rmind     548:        return error;
1.2       ad        549: }
                    550:
                    551: int
                    552: sigprocmask1(struct lwp *l, int how, const sigset_t *nss, sigset_t *oss)
                    553: {
1.36.4.1! mrg       554:        sigset_t *mask = &l->l_sigmask;
        !           555:        bool more;
1.2       ad        556:
1.36.4.1! mrg       557:        KASSERT(mutex_owned(l->l_proc->p_lock));
1.2       ad        558:
1.36.4.1! mrg       559:        if (oss) {
1.17      wrstuden  560:                *oss = *mask;
1.2       ad        561:        }
                    562:
1.36.4.1! mrg       563:        if (nss == NULL) {
        !           564:                return 0;
        !           565:        }
        !           566:
        !           567:        switch (how) {
        !           568:        case SIG_BLOCK:
        !           569:                sigplusset(nss, mask);
        !           570:                more = false;
        !           571:                break;
        !           572:        case SIG_UNBLOCK:
        !           573:                sigminusset(nss, mask);
        !           574:                more = true;
        !           575:                break;
        !           576:        case SIG_SETMASK:
        !           577:                *mask = *nss;
        !           578:                more = true;
        !           579:                break;
        !           580:        default:
        !           581:                return EINVAL;
        !           582:        }
        !           583:        sigminusset(&sigcantmask, mask);
        !           584:        if (more && sigispending(l, 0)) {
        !           585:                /*
        !           586:                 * Check for pending signals on return to user.
        !           587:                 */
        !           588:                lwp_lock(l);
        !           589:                l->l_flag |= LW_PENDSIG;
        !           590:                lwp_unlock(l);
        !           591:        }
1.25      rmind     592:        return 0;
1.2       ad        593: }
                    594:
                    595: void
                    596: sigpending1(struct lwp *l, sigset_t *ss)
                    597: {
                    598:        struct proc *p = l->l_proc;
                    599:
1.14      ad        600:        mutex_enter(p->p_lock);
1.2       ad        601:        *ss = l->l_sigpend.sp_set;
                    602:        sigplusset(&p->p_sigpend.sp_set, ss);
1.14      ad        603:        mutex_exit(p->p_lock);
1.2       ad        604: }
                    605:
1.33      christos  606: void
                    607: sigsuspendsetup(struct lwp *l, const sigset_t *ss)
1.2       ad        608: {
1.25      rmind     609:        struct proc *p = l->l_proc;
1.2       ad        610:
1.33      christos  611:        /*
                    612:         * When returning from sigsuspend/pselect/pollts, we want
                    613:         * the old mask to be restored after the
                    614:         * signal handler has finished.  Thus, we
                    615:         * save it here and mark the sigctx structure
                    616:         * to indicate this.
                    617:         */
                    618:        mutex_enter(p->p_lock);
                    619:        l->l_sigrestore = 1;
                    620:        l->l_sigoldmask = l->l_sigmask;
                    621:        l->l_sigmask = *ss;
                    622:        sigminusset(&sigcantmask, &l->l_sigmask);
1.2       ad        623:
1.33      christos  624:        /* Check for pending signals when sleeping. */
                    625:        if (sigispending(l, 0)) {
                    626:                lwp_lock(l);
                    627:                l->l_flag |= LW_PENDSIG;
                    628:                lwp_unlock(l);
1.2       ad        629:        }
1.33      christos  630:        mutex_exit(p->p_lock);
                    631: }
                    632:
1.34      christos  633: void
                    634: sigsuspendteardown(struct lwp *l)
                    635: {
                    636:        struct proc *p = l->l_proc;
                    637:
                    638:        mutex_enter(p->p_lock);
1.35      christos  639:        /* Check for pending signals when sleeping. */
1.34      christos  640:        if (l->l_sigrestore) {
1.35      christos  641:                if (sigispending(l, 0)) {
                    642:                        lwp_lock(l);
                    643:                        l->l_flag |= LW_PENDSIG;
                    644:                        lwp_unlock(l);
                    645:                } else {
                    646:                        l->l_sigrestore = 0;
                    647:                        l->l_sigmask = l->l_sigoldmask;
                    648:                }
1.34      christos  649:        }
                    650:        mutex_exit(p->p_lock);
                    651: }
                    652:
1.33      christos  653: int
                    654: sigsuspend1(struct lwp *l, const sigset_t *ss)
                    655: {
                    656:
                    657:        if (ss)
                    658:                sigsuspendsetup(l, ss);
1.2       ad        659:
1.5       thorpej   660:        while (kpause("pause", true, 0, NULL) == 0)
1.2       ad        661:                ;
                    662:
                    663:        /* always return EINTR rather than ERESTART... */
1.25      rmind     664:        return EINTR;
1.2       ad        665: }
                    666:
                    667: int
                    668: sigaltstack1(struct lwp *l, const struct sigaltstack *nss,
1.25      rmind     669:     struct sigaltstack *oss)
1.2       ad        670: {
                    671:        struct proc *p = l->l_proc;
                    672:        int error = 0;
                    673:
1.14      ad        674:        mutex_enter(p->p_lock);
1.2       ad        675:
                    676:        if (oss)
                    677:                *oss = l->l_sigstk;
                    678:
                    679:        if (nss) {
                    680:                if (nss->ss_flags & ~SS_ALLBITS)
                    681:                        error = EINVAL;
                    682:                else if (nss->ss_flags & SS_DISABLE) {
                    683:                        if (l->l_sigstk.ss_flags & SS_ONSTACK)
                    684:                                error = EINVAL;
                    685:                } else if (nss->ss_size < MINSIGSTKSZ)
                    686:                        error = ENOMEM;
                    687:
                    688:                if (!error)
                    689:                        l->l_sigstk = *nss;
                    690:        }
                    691:
1.14      ad        692:        mutex_exit(p->p_lock);
1.2       ad        693:
1.25      rmind     694:        return error;
1.2       ad        695: }
                    696:
                    697: int
1.26      pooka     698: sigtimedwait1(struct lwp *l, const struct sys_____sigtimedwait50_args *uap,
1.36      christos  699:     register_t *retval, copyin_t fetchss, copyout_t storeinf, copyin_t fetchts,
                    700:     copyout_t storets)
1.2       ad        701: {
1.9       dsl       702:        /* {
1.2       ad        703:                syscallarg(const sigset_t *) set;
                    704:                syscallarg(siginfo_t *) info;
                    705:                syscallarg(struct timespec *) timeout;
1.9       dsl       706:        } */
1.2       ad        707:        struct proc *p = l->l_proc;
1.25      rmind     708:        int error, signum, timo;
1.2       ad        709:        struct timespec ts, tsstart, tsnow;
1.24      rmind     710:        ksiginfo_t ksi;
1.2       ad        711:
                    712:        /*
                    713:         * Calculate timeout, if it was specified.
                    714:         */
                    715:        if (SCARG(uap, timeout)) {
1.25      rmind     716:                error = (*fetchts)(SCARG(uap, timeout), &ts, sizeof(ts));
1.23      christos  717:                if (error)
                    718:                        return error;
1.2       ad        719:
1.23      christos  720:                if ((error = itimespecfix(&ts)) != 0)
                    721:                        return error;
1.2       ad        722:
1.23      christos  723:                timo = tstohz(&ts);
                    724:                if (timo == 0 && ts.tv_sec == 0 && ts.tv_nsec != 0)
                    725:                        timo++;
1.2       ad        726:
                    727:                /*
                    728:                 * Remember current uptime, it would be used in
                    729:                 * ECANCELED/ERESTART case.
                    730:                 */
                    731:                getnanouptime(&tsstart);
1.25      rmind     732:        } else {
                    733:                memset(&tsstart, 0, sizeof(tsstart)); /* XXXgcc */
                    734:                timo = 0;
1.2       ad        735:        }
                    736:
1.36      christos  737:        error = (*fetchss)(SCARG(uap, set), &l->l_sigwaitset,
1.2       ad        738:            sizeof(l->l_sigwaitset));
1.25      rmind     739:        if (error)
                    740:                return error;
1.2       ad        741:
                    742:        /*
                    743:         * Silently ignore SA_CANTMASK signals. psignal1() would ignore
                    744:         * SA_CANTMASK signals in waitset, we do this only for the below
                    745:         * siglist check.
                    746:         */
                    747:        sigminusset(&sigcantmask, &l->l_sigwaitset);
                    748:
1.14      ad        749:        mutex_enter(p->p_lock);
1.2       ad        750:
1.25      rmind     751:        /* Check for pending signals in the process, if no - then in LWP. */
1.24      rmind     752:        if ((signum = sigget(&p->p_sigpend, &ksi, 0, &l->l_sigwaitset)) == 0)
                    753:                signum = sigget(&l->l_sigpend, &ksi, 0, &l->l_sigwaitset);
1.2       ad        754:
                    755:        if (signum != 0) {
1.25      rmind     756:                /* If found a pending signal, just copy it out to the user. */
1.14      ad        757:                mutex_exit(p->p_lock);
1.2       ad        758:                goto out;
                    759:        }
                    760:
                    761:        /*
1.25      rmind     762:         * Set up the sigwait list and wait for signal to arrive.
                    763:         * We can either be woken up or time out.
1.2       ad        764:         */
1.24      rmind     765:        l->l_sigwaited = &ksi;
1.2       ad        766:        LIST_INSERT_HEAD(&p->p_sigwaiters, l, l_sigwaiter);
1.14      ad        767:        error = cv_timedwait_sig(&l->l_sigcv, p->p_lock, timo);
1.2       ad        768:
                    769:        /*
1.25      rmind     770:         * Need to find out if we woke as a result of _lwp_wakeup() or a
1.2       ad        771:         * signal outside our wait set.
                    772:         */
                    773:        if (l->l_sigwaited != NULL) {
                    774:                if (error == EINTR) {
1.25      rmind     775:                        /* Wakeup via _lwp_wakeup(). */
1.2       ad        776:                        error = ECANCELED;
                    777:                } else if (!error) {
1.25      rmind     778:                        /* Spurious wakeup - arrange for syscall restart. */
1.2       ad        779:                        error = ERESTART;
                    780:                }
                    781:                l->l_sigwaited = NULL;
                    782:                LIST_REMOVE(l, l_sigwaiter);
                    783:        }
1.14      ad        784:        mutex_exit(p->p_lock);
1.2       ad        785:
                    786:        /*
                    787:         * If the sleep was interrupted (either by signal or wakeup), update
                    788:         * the timeout and copyout new value back.  It would be used when
                    789:         * the syscall would be restarted or called again.
                    790:         */
                    791:        if (timo && (error == ERESTART || error == ECANCELED)) {
                    792:                getnanouptime(&tsnow);
                    793:
1.25      rmind     794:                /* Compute how much time has passed since start. */
1.2       ad        795:                timespecsub(&tsnow, &tsstart, &tsnow);
1.25      rmind     796:
                    797:                /* Substract passed time from timeout. */
1.2       ad        798:                timespecsub(&ts, &tsnow, &ts);
                    799:
                    800:                if (ts.tv_sec < 0)
                    801:                        error = EAGAIN;
                    802:                else {
1.25      rmind     803:                        /* Copy updated timeout to userland. */
                    804:                        error = (*storets)(&ts, SCARG(uap, timeout),
1.2       ad        805:                            sizeof(ts));
                    806:                }
                    807:        }
1.25      rmind     808: out:
1.2       ad        809:        /*
                    810:         * If a signal from the wait set arrived, copy it to userland.
                    811:         * Copy only the used part of siginfo, the padding part is
                    812:         * left unchanged (userland is not supposed to touch it anyway).
                    813:         */
1.27      drochner  814:        if (error == 0 && SCARG(uap, info)) {
1.25      rmind     815:                error = (*storeinf)(&ksi.ksi_info, SCARG(uap, info),
1.24      rmind     816:                    sizeof(ksi.ksi_info));
1.25      rmind     817:        }
1.27      drochner  818:        if (error == 0)
                    819:                *retval = ksi.ksi_info._signo;
1.2       ad        820:        return error;
                    821: }

CVSweb <webmaster@jp.NetBSD.org>