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>