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>