1 /* $NetBSD: linux_signal.c,v 1.68 2009/05/29 14:19:13 njoly Exp $ */
4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc.
7 * This code is derived from software contributed to The NetBSD Foundation
8 * by Frank van der Linden and Eric Haszlakiewicz.
10 * Redistribution and use in source and binary forms, with or without
11 * modification, are permitted provided that the following conditions
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.
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.
32 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp
36 * Functions in multiarch:
37 * linux_sys_signal : linux_sig_notalpha.c
38 * linux_sys_siggetmask : linux_sig_notalpha.c
39 * linux_sys_sigsetmask : linux_sig_notalpha.c
40 * linux_sys_pause : linux_sig_notalpha.c
41 * linux_sys_sigaction : linux_sigaction.c
47 * linux_sys_rt_sigtimedwait : sigsuspend w/timeout.
50 #include <sys/cdefs.h>
51 __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.68 2009/05/29 14:19:13 njoly Exp $");
53 #define COMPAT_LINUX 1
55 #include <sys/param.h>
56 #include <sys/systm.h>
57 #include <sys/namei.h>
59 #include <sys/filedesc.h>
60 #include <sys/ioctl.h>
61 #include <sys/mount.h>
62 #include <sys/kernel.h>
63 #include <sys/signal.h>
64 #include <sys/signalvar.h>
65 #include <sys/malloc.h>
68 #include <sys/syscallargs.h>
70 #include <compat/linux/common/linux_types.h>
71 #include <compat/linux/common/linux_signal.h>
72 #include <compat/linux/common/linux_exec.h> /* For emul_linux */
73 #include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */
74 #include <compat/linux/common/linux_emuldata.h> /* for linux_emuldata */
75 #include <compat/linux/common/linux_siginfo.h>
76 #include <compat/linux/common/linux_sigevent.h>
77 #include <compat/linux/common/linux_util.h>
78 #include <compat/linux/common/linux_ipc.h>
79 #include <compat/linux/common/linux_sem.h>
81 #include <compat/linux/linux_syscallargs.h>
83 /* Locally used defines (in bsd<->linux conversion functions): */
84 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s)))
85 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
86 & (1L << ((n) - 1) % LINUX__NSIG_BPW))
87 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \
88 |= (1L << ((n) - 1) % LINUX__NSIG_BPW))
91 #define DPRINTF(a) uprintf a
96 extern const int native_to_linux_signo
[];
97 extern const int linux_to_native_signo
[];
100 * Convert between Linux and BSD signal sets.
102 #if LINUX__NSIG_WORDS > 1
104 linux_old_extra_to_native_sigset(sigset_t
*bss
, const linux_old_sigset_t
*lss
, const unsigned long *extra
)
106 linux_sigset_t lsnew
;
108 /* convert old sigset to new sigset */
109 linux_sigemptyset(&lsnew
);
112 memcpy(&lsnew
.sig
[1], extra
,
113 sizeof(linux_sigset_t
) - sizeof(linux_old_sigset_t
));
115 linux_to_native_sigset(bss
, &lsnew
);
119 native_to_linux_old_extra_sigset(linux_old_sigset_t
*lss
, unsigned long *extra
, const sigset_t
*bss
)
121 linux_sigset_t lsnew
;
123 native_to_linux_sigset(&lsnew
, bss
);
125 /* convert new sigset to old sigset */
128 memcpy(extra
, &lsnew
.sig
[1],
129 sizeof(linux_sigset_t
) - sizeof(linux_old_sigset_t
));
131 #endif /* LINUX__NSIG_WORDS > 1 */
134 linux_to_native_sigset(sigset_t
*bss
, const linux_sigset_t
*lss
)
139 for (i
= 1; i
< LINUX__NSIG
; i
++) {
140 if (linux_sigismember(lss
, i
)) {
141 newsig
= linux_to_native_signo
[i
];
143 sigaddset(bss
, newsig
);
149 native_to_linux_sigset(linux_sigset_t
*lss
, const sigset_t
*bss
)
153 linux_sigemptyset(lss
);
154 for (i
= 1; i
< NSIG
; i
++) {
155 if (sigismember(bss
, i
)) {
156 newsig
= native_to_linux_signo
[i
];
158 linux_sigaddset(lss
, newsig
);
164 native_to_linux_sigflags(const int bsf
)
166 unsigned int lsf
= 0;
167 if ((bsf
& SA_NOCLDSTOP
) != 0)
168 lsf
|= LINUX_SA_NOCLDSTOP
;
169 if ((bsf
& SA_NOCLDWAIT
) != 0)
170 lsf
|= LINUX_SA_NOCLDWAIT
;
171 if ((bsf
& SA_ONSTACK
) != 0)
172 lsf
|= LINUX_SA_ONSTACK
;
173 if ((bsf
& SA_RESTART
) != 0)
174 lsf
|= LINUX_SA_RESTART
;
175 if ((bsf
& SA_NODEFER
) != 0)
176 lsf
|= LINUX_SA_NOMASK
;
177 if ((bsf
& SA_RESETHAND
) != 0)
178 lsf
|= LINUX_SA_ONESHOT
;
179 if ((bsf
& SA_SIGINFO
) != 0)
180 lsf
|= LINUX_SA_SIGINFO
;
185 linux_to_native_sigflags(const unsigned long lsf
)
188 if ((lsf
& LINUX_SA_NOCLDSTOP
) != 0)
190 if ((lsf
& LINUX_SA_NOCLDWAIT
) != 0)
192 if ((lsf
& LINUX_SA_ONSTACK
) != 0)
194 if ((lsf
& LINUX_SA_RESTART
) != 0)
196 if ((lsf
& LINUX_SA_ONESHOT
) != 0)
198 if ((lsf
& LINUX_SA_NOMASK
) != 0)
200 if ((lsf
& LINUX_SA_SIGINFO
) != 0)
202 if ((lsf
& ~LINUX_SA_ALLBITS
) != 0) {
203 DPRINTF(("linux_old_to_native_sigflags: "
204 "%lx extra bits ignored\n", lsf
));
210 * Convert between Linux and BSD sigaction structures.
213 linux_old_to_native_sigaction(struct sigaction
*bsa
, const struct linux_old_sigaction
*lsa
)
215 bsa
->sa_handler
= lsa
->linux_sa_handler
;
216 linux_old_to_native_sigset(&bsa
->sa_mask
, &lsa
->linux_sa_mask
);
217 bsa
->sa_flags
= linux_to_native_sigflags(lsa
->linux_sa_flags
);
221 native_to_linux_old_sigaction(struct linux_old_sigaction
*lsa
, const struct sigaction
*bsa
)
223 lsa
->linux_sa_handler
= bsa
->sa_handler
;
224 native_to_linux_old_sigset(&lsa
->linux_sa_mask
, &bsa
->sa_mask
);
225 lsa
->linux_sa_flags
= native_to_linux_sigflags(bsa
->sa_flags
);
227 lsa
->linux_sa_restorer
= NULL
;
231 /* ...and the new sigaction conversion funcs. */
233 linux_to_native_sigaction(struct sigaction
*bsa
, const struct linux_sigaction
*lsa
)
235 bsa
->sa_handler
= lsa
->linux_sa_handler
;
236 linux_to_native_sigset(&bsa
->sa_mask
, &lsa
->linux_sa_mask
);
237 bsa
->sa_flags
= linux_to_native_sigflags(lsa
->linux_sa_flags
);
241 native_to_linux_sigaction(struct linux_sigaction
*lsa
, const struct sigaction
*bsa
)
243 lsa
->linux_sa_handler
= bsa
->sa_handler
;
244 native_to_linux_sigset(&lsa
->linux_sa_mask
, &bsa
->sa_mask
);
245 lsa
->linux_sa_flags
= native_to_linux_sigflags(bsa
->sa_flags
);
247 lsa
->linux_sa_restorer
= NULL
;
251 /* ----------------------------------------------------------------------- */
254 * The Linux sigaction() system call. Do the usual conversions,
255 * and just call sigaction(). Some flags and values are silently
256 * ignored (see above).
259 linux_sys_rt_sigaction(struct lwp
*l
, const struct linux_sys_rt_sigaction_args
*uap
, register_t
*retval
)
262 syscallarg(int) signum;
263 syscallarg(const struct linux_sigaction *) nsa;
264 syscallarg(struct linux_sigaction *) osa;
265 syscallarg(size_t) sigsetsize;
267 struct linux_sigaction nlsa
, olsa
;
268 struct sigaction nbsa
, obsa
;
272 #if defined __amd64__
273 struct sigacts
*ps
= l
->l_proc
->p_sigacts
;
276 if (SCARG(uap
, sigsetsize
) != sizeof(linux_sigset_t
))
279 if (SCARG(uap
, nsa
)) {
280 error
= copyin(SCARG(uap
, nsa
), &nlsa
, sizeof(nlsa
));
283 linux_to_native_sigaction(&nbsa
, &nlsa
);
286 sig
= SCARG(uap
, signum
);
287 if (sig
< 0 || sig
>= LINUX__NSIG
)
289 if (sig
> 0 && !linux_to_native_signo
[sig
]) {
290 /* Pretend that we did something useful for unknown signals. */
291 obsa
.sa_handler
= SIG_IGN
;
292 sigemptyset(&obsa
.sa_mask
);
295 #if defined __amd64__
296 if (nlsa
.linux_sa_flags
& LINUX_SA_RESTORER
) {
297 if ((tramp
= nlsa
.linux_sa_restorer
) != NULL
)
298 vers
= 2; /* XXX arch dependant */
302 error
= sigaction1(l
, linux_to_native_signo
[sig
],
303 SCARG(uap
, nsa
) ? &nbsa
: NULL
,
304 SCARG(uap
, osa
) ? &obsa
: NULL
,
309 if (SCARG(uap
, osa
)) {
310 native_to_linux_sigaction(&olsa
, &obsa
);
312 #if defined __amd64__
313 if (ps
->sa_sigdesc
[sig
].sd_vers
!= 0) {
314 olsa
.linux_sa_restorer
= ps
->sa_sigdesc
[sig
].sd_tramp
;
315 olsa
.linux_sa_flags
|= LINUX_SA_RESTORER
;
319 error
= copyout(&olsa
, SCARG(uap
, osa
), sizeof(olsa
));
327 linux_sigprocmask1(struct lwp
*l
, int how
, const linux_old_sigset_t
*set
, linux_old_sigset_t
*oset
)
329 struct proc
*p
= l
->l_proc
;
330 linux_old_sigset_t nlss
, olss
;
335 case LINUX_SIG_BLOCK
:
338 case LINUX_SIG_UNBLOCK
:
341 case LINUX_SIG_SETMASK
:
349 error
= copyin(set
, &nlss
, sizeof(nlss
));
352 linux_old_to_native_sigset(&nbss
, &nlss
);
354 mutex_enter(p
->p_lock
);
355 error
= sigprocmask1(l
, how
,
356 set
? &nbss
: NULL
, oset
? &obss
: NULL
);
357 mutex_exit(p
->p_lock
);
361 native_to_linux_old_sigset(&olss
, &obss
);
362 error
= copyout(&olss
, oset
, sizeof(olss
));
370 linux_sys_rt_sigprocmask(struct lwp
*l
, const struct linux_sys_rt_sigprocmask_args
*uap
, register_t
*retval
)
374 syscallarg(const linux_sigset_t *) set;
375 syscallarg(linux_sigset_t *) oset;
376 syscallarg(size_t) sigsetsize;
378 linux_sigset_t nlss
, olss
, *oset
;
379 const linux_sigset_t
*set
;
380 struct proc
*p
= l
->l_proc
;
384 if (SCARG(uap
, sigsetsize
) != sizeof(linux_sigset_t
))
387 switch (SCARG(uap
, how
)) {
388 case LINUX_SIG_BLOCK
:
391 case LINUX_SIG_UNBLOCK
:
394 case LINUX_SIG_SETMASK
:
401 set
= SCARG(uap
, set
);
402 oset
= SCARG(uap
, oset
);
405 error
= copyin(set
, &nlss
, sizeof(nlss
));
408 linux_to_native_sigset(&nbss
, &nlss
);
410 mutex_enter(p
->p_lock
);
411 error
= sigprocmask1(l
, how
,
412 set
? &nbss
: NULL
, oset
? &obss
: NULL
);
413 mutex_exit(p
->p_lock
);
414 if (!error
&& oset
) {
415 native_to_linux_sigset(&olss
, &obss
);
416 error
= copyout(&olss
, oset
, sizeof(olss
));
422 linux_sys_rt_sigpending(struct lwp
*l
, const struct linux_sys_rt_sigpending_args
*uap
, register_t
*retval
)
425 syscallarg(linux_sigset_t *) set;
426 syscallarg(size_t) sigsetsize;
431 if (SCARG(uap
, sigsetsize
) != sizeof(linux_sigset_t
))
434 sigpending1(l
, &bss
);
435 native_to_linux_sigset(&lss
, &bss
);
436 return copyout(&lss
, SCARG(uap
, set
), sizeof(lss
));
441 linux_sys_sigpending(struct lwp
*l
, const struct linux_sys_sigpending_args
*uap
, register_t
*retval
)
444 syscallarg(linux_old_sigset_t *) mask;
447 linux_old_sigset_t lss
;
449 sigpending1(l
, &bss
);
450 native_to_linux_old_sigset(&lss
, &bss
);
451 return copyout(&lss
, SCARG(uap
, set
), sizeof(lss
));
455 linux_sys_sigsuspend(struct lwp
*l
, const struct linux_sys_sigsuspend_args
*uap
, register_t
*retval
)
458 syscallarg(void *) restart;
459 syscallarg(int) oldmask;
460 syscallarg(int) mask;
462 linux_old_sigset_t lss
;
465 lss
= SCARG(uap
, mask
);
466 linux_old_to_native_sigset(&bss
, &lss
);
467 return (sigsuspend1(l
, &bss
));
469 #endif /* __amd64__ */
472 linux_sys_rt_sigsuspend(struct lwp
*l
, const struct linux_sys_rt_sigsuspend_args
*uap
, register_t
*retval
)
475 syscallarg(linux_sigset_t *) unewset;
476 syscallarg(size_t) sigsetsize;
482 if (SCARG(uap
, sigsetsize
) != sizeof(linux_sigset_t
))
485 error
= copyin(SCARG(uap
, unewset
), &lss
, sizeof(linux_sigset_t
));
489 linux_to_native_sigset(&bss
, &lss
);
491 return (sigsuspend1(l
, &bss
));
495 * Once more: only a signal conversion is needed.
496 * Note: also used as sys_rt_queueinfo. The info field is ignored.
499 linux_sys_rt_queueinfo(struct lwp
*l
, const struct linux_sys_rt_queueinfo_args
*uap
, register_t
*retval
)
503 syscallarg(int) signum;
504 syscallarg(linix_siginfo_t *) uinfo;
507 linux_siginfo_t info
;
509 error
= copyin(SCARG(uap
, uinfo
), &info
, sizeof(info
));
512 if (info
.lsi_code
>= 0)
515 /* XXX To really implement this we need to */
516 /* XXX keep a list of queued signals somewhere. */
517 return (linux_sys_kill(l
, (const void *)uap
, retval
));
521 linux_sys_kill(struct lwp
*l
, const struct linux_sys_kill_args
*uap
, register_t
*retval
)
525 syscallarg(int) signum;
528 struct sys_kill_args ka
;
531 SCARG(&ka
, pid
) = SCARG(uap
, pid
);
532 sig
= SCARG(uap
, signum
);
533 if (sig
< 0 || sig
>= LINUX__NSIG
)
535 SCARG(&ka
, signum
) = linux_to_native_signo
[sig
];
536 return sys_kill(l
, &ka
, retval
);
539 #ifdef LINUX_SS_ONSTACK
540 static void linux_to_native_sigaltstack(struct sigaltstack
*,
541 const struct linux_sigaltstack
*);
544 linux_to_native_sigaltstack(struct sigaltstack
*bss
, const struct linux_sigaltstack
*lss
)
546 bss
->ss_sp
= lss
->ss_sp
;
547 bss
->ss_size
= lss
->ss_size
;
548 if (lss
->ss_flags
& LINUX_SS_ONSTACK
)
549 bss
->ss_flags
= SS_ONSTACK
;
550 else if (lss
->ss_flags
& LINUX_SS_DISABLE
)
551 bss
->ss_flags
= SS_DISABLE
;
557 native_to_linux_sigaltstack(struct linux_sigaltstack
*lss
, const struct sigaltstack
*bss
)
559 lss
->ss_sp
= bss
->ss_sp
;
560 lss
->ss_size
= bss
->ss_size
;
561 if (bss
->ss_flags
& SS_ONSTACK
)
562 lss
->ss_flags
= LINUX_SS_ONSTACK
;
563 else if (bss
->ss_flags
& SS_DISABLE
)
564 lss
->ss_flags
= LINUX_SS_DISABLE
;
570 linux_sys_sigaltstack(struct lwp
*l
, const struct linux_sys_sigaltstack_args
*uap
, register_t
*retval
)
573 syscallarg(const struct linux_sigaltstack *) ss;
574 syscallarg(struct linux_sigaltstack *) oss;
576 struct linux_sigaltstack ss
;
577 struct sigaltstack nss
;
578 struct proc
*p
= l
->l_proc
;
581 if (SCARG(uap
, oss
)) {
582 native_to_linux_sigaltstack(&ss
, &l
->l_sigstk
);
583 if ((error
= copyout(&ss
, SCARG(uap
, oss
), sizeof(ss
))) != 0)
587 if (SCARG(uap
, ss
) != NULL
) {
588 if ((error
= copyin(SCARG(uap
, ss
), &ss
, sizeof(ss
))) != 0)
590 linux_to_native_sigaltstack(&nss
, &ss
);
592 mutex_enter(p
->p_lock
);
594 if (nss
.ss_flags
& ~SS_ALLBITS
)
596 else if (nss
.ss_flags
& SS_DISABLE
) {
597 if (l
->l_sigstk
.ss_flags
& SS_ONSTACK
)
599 } else if (nss
.ss_size
< LINUX_MINSIGSTKSZ
)
605 mutex_exit(p
->p_lock
);
610 #endif /* LINUX_SS_ONSTACK */
614 linux_do_tkill(struct lwp
*l
, int tgid
, int tid
, int signum
)
619 struct linux_emuldata
*led
;
621 if (signum
< 0 || signum
>= LINUX__NSIG
)
623 signum
= linux_to_native_signo
[signum
];
626 ksi
.ksi_signo
= signum
;
627 ksi
.ksi_code
= SI_LWP
;
628 ksi
.ksi_pid
= l
->l_proc
->p_pid
;
629 ksi
.ksi_uid
= kauth_cred_geteuid(l
->l_cred
);
631 mutex_enter(proc_lock
);
632 if ((p
= p_find(tid
, PFIND_LOCKED
)) == NULL
) {
633 mutex_exit(proc_lock
);
637 if (tgid
> 0 && led
->s
->group_pid
!= tgid
) {
638 mutex_exit(proc_lock
);
641 mutex_enter(p
->p_lock
);
642 error
= kauth_authorize_process(l
->l_cred
,
643 KAUTH_PROCESS_SIGNAL
, p
, KAUTH_ARG(signum
), NULL
, NULL
);
644 if (!error
&& signum
)
646 mutex_exit(p
->p_lock
);
647 mutex_exit(proc_lock
);
653 linux_sys_tkill(struct lwp
*l
, const struct linux_sys_tkill_args
*uap
, register_t
*retval
)
660 if (SCARG(uap
, tid
) <= 0)
663 return linux_do_tkill(l
, 0, SCARG(uap
, tid
), SCARG(uap
, sig
));
667 linux_sys_tgkill(struct lwp
*l
, const struct linux_sys_tgkill_args
*uap
, register_t
*retval
)
670 syscallarg(int) tgid;
675 if (SCARG(uap
, tid
) <= 0 || SCARG(uap
, tgid
) <= 0)
678 return linux_do_tkill(l
, SCARG(uap
, tgid
), SCARG(uap
, tid
), SCARG(uap
, sig
));
680 #endif /* LINUX_NPTL */
683 native_to_linux_si_code(int code
)
686 LINUX_SI_USER
, LINUX_SI_QUEUE
, LINUX_SI_TIMER
, LINUX_SI_ASYNCIO
,
687 LINUX_SI_MESGQ
, LINUX_SI_TKILL
/* SI_LWP */
690 if (code
<= 0 && -code
< __arraycount(si_codes
))
691 return si_codes
[-code
];
697 native_to_linux_si_status(int code
, int status
)
706 sts
= WEXITSTATUS(status
);
713 sts
= native_to_linux_signo
[WTERMSIG(status
)];