1 /* $NetBSD: linux32_signal.c,v 1.12 2009/06/02 16:54:39 njoly Exp $ */
4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved.
6 * Redistribution and use in source and binary forms, with or without
7 * modification, are permitted provided that the following conditions
9 * 1. Redistributions of source code must retain the above copyright
10 * notice, this list of conditions and the following disclaimer.
11 * 2. Redistributions in binary form must reproduce the above copyright
12 * notice, this list of conditions and the following disclaimer in the
13 * documentation and/or other materials provided with the distribution.
14 * 3. All advertising materials mentioning features or use of this software
15 * must display the following acknowledgement:
16 * This product includes software developed by Emmanuel Dreyfus
17 * 4. The name of the author may not be used to endorse or promote
18 * products derived from this software without specific prior written
21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS''
22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO,
23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS
25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
31 * POSSIBILITY OF SUCH DAMAGE.
34 #include <sys/cdefs.h>
35 __KERNEL_RCSID(0, "$NetBSD: linux32_signal.c,v 1.12 2009/06/02 16:54:39 njoly Exp $");
37 #include <sys/param.h>
38 #include <sys/ucred.h>
39 #include <sys/signalvar.h>
44 #include <compat/netbsd32/netbsd32.h>
46 #include <compat/linux32/common/linux32_types.h>
47 #include <compat/linux32/common/linux32_signal.h>
48 #include <compat/linux32/linux32_syscallargs.h>
50 #define linux32_sigemptyset(s) memset((s), 0, sizeof(*(s)))
51 #define linux32_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \
52 & (1 << ((n) - 1) % LINUX32__NSIG_BPW))
53 #define linux32_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \
54 |= (1 << ((n) - 1) % LINUX32__NSIG_BPW))
56 extern const int native_to_linux32_signo
[];
57 extern const int linux32_to_native_signo
[];
60 #define DPRINTF(a) uprintf a
66 linux32_to_native_sigset(sigset_t
*bss
, const linux32_sigset_t
*lss
)
71 for (i
= 1; i
< LINUX32__NSIG
; i
++) {
72 if (linux32_sigismember(lss
, i
)) {
73 newsig
= linux32_to_native_signo
[i
];
75 sigaddset(bss
, newsig
);
81 native_to_linux32_sigset(linux32_sigset_t
*lss
, const sigset_t
*bss
)
85 linux32_sigemptyset(lss
);
86 for (i
= 1; i
< NSIG
; i
++) {
87 if (sigismember(bss
, i
)) {
88 newsig
= native_to_linux32_signo
[i
];
90 linux32_sigaddset(lss
, newsig
);
96 native_to_linux32_sigflags(const int bsf
)
99 if ((bsf
& SA_NOCLDSTOP
) != 0)
100 lsf
|= LINUX32_SA_NOCLDSTOP
;
101 if ((bsf
& SA_NOCLDWAIT
) != 0)
102 lsf
|= LINUX32_SA_NOCLDWAIT
;
103 if ((bsf
& SA_ONSTACK
) != 0)
104 lsf
|= LINUX32_SA_ONSTACK
;
105 if ((bsf
& SA_RESTART
) != 0)
106 lsf
|= LINUX32_SA_RESTART
;
107 if ((bsf
& SA_NODEFER
) != 0)
108 lsf
|= LINUX32_SA_NOMASK
;
109 if ((bsf
& SA_RESETHAND
) != 0)
110 lsf
|= LINUX32_SA_ONESHOT
;
111 if ((bsf
& SA_SIGINFO
) != 0)
112 lsf
|= LINUX32_SA_SIGINFO
;
117 linux32_to_native_sigflags(const unsigned long lsf
)
120 if ((lsf
& LINUX32_SA_NOCLDSTOP
) != 0)
122 if ((lsf
& LINUX32_SA_NOCLDWAIT
) != 0)
124 if ((lsf
& LINUX32_SA_ONSTACK
) != 0)
126 if ((lsf
& LINUX32_SA_RESTART
) != 0)
128 if ((lsf
& LINUX32_SA_ONESHOT
) != 0)
130 if ((lsf
& LINUX32_SA_NOMASK
) != 0)
132 if ((lsf
& LINUX32_SA_SIGINFO
) != 0)
134 if ((lsf
& ~LINUX32_SA_ALLBITS
) != 0) {
136 printf("linux32_old_to_native_sigflags: "
137 "%lx extra bits ignored\n", lsf
);
144 linux32_to_native_sigaction(struct sigaction
*bsa
, const struct linux32_sigaction
*lsa
)
146 bsa
->sa_handler
= NETBSD32PTR64(lsa
->linux_sa_handler
);
147 linux32_to_native_sigset(&bsa
->sa_mask
, &lsa
->linux_sa_mask
);
148 bsa
->sa_flags
= linux32_to_native_sigflags(lsa
->linux_sa_flags
);
152 native_to_linux32_sigaction(struct linux32_sigaction
*lsa
, const struct sigaction
*bsa
)
154 NETBSD32PTR32(lsa
->linux_sa_handler
, bsa
->sa_handler
);
155 native_to_linux32_sigset(&lsa
->linux_sa_mask
, &bsa
->sa_mask
);
156 lsa
->linux_sa_flags
= native_to_linux32_sigflags(bsa
->sa_flags
);
157 NETBSD32PTR32(lsa
->linux_sa_restorer
, NULL
);
161 native_to_linux32_sigaltstack(struct linux32_sigaltstack
*lss
, const struct sigaltstack
*bss
)
163 NETBSD32PTR32(lss
->ss_sp
, bss
->ss_sp
);
164 lss
->ss_size
= bss
->ss_size
;
165 if (bss
->ss_flags
& SS_ONSTACK
)
166 lss
->ss_flags
= LINUX32_SS_ONSTACK
;
167 else if (bss
->ss_flags
& SS_DISABLE
)
168 lss
->ss_flags
= LINUX32_SS_DISABLE
;
175 native_to_linux32_old_sigset(linux32_old_sigset_t
*lss
, const sigset_t
*bss
)
177 linux32_sigset_t lsnew
;
179 native_to_linux32_sigset(&lsnew
, bss
);
181 /* convert new sigset to old sigset */
186 linux32_old_to_native_sigset(sigset_t
*bss
, const linux32_old_sigset_t
*lss
)
190 memset(&ls
, 0, sizeof(ls
));
193 linux32_to_native_sigset(bss
, &ls
);
197 linux32_sys_rt_sigaction(struct lwp
*l
, const struct linux32_sys_rt_sigaction_args
*uap
, register_t
*retval
)
200 syscallarg(int) signum;
201 syscallarg(const linux32_sigactionp_t) nsa;
202 syscallarg(linux32_sigactionp_t) osa;
203 syscallarg(netbsd32_size_t) sigsetsize;
205 struct linux32_sigaction nls32
;
206 struct linux32_sigaction ols32
;
214 if (SCARG(uap
, sigsetsize
) != sizeof(linux32_sigset_t
)) {
215 DPRINTF(("rt_sigaction: Inconsistent sigsetsize %u %zu\n",
216 SCARG(uap
, sigsetsize
), sizeof(linux32_sigset_t
)));
220 if (SCARG_P32(uap
, nsa
) != NULL
) {
221 if ((error
= copyin(SCARG_P32(uap
, nsa
),
222 &nls32
, sizeof(nls32
))) != 0) {
223 DPRINTF(("rt_sigaction: Copyin %d\n", error
));
226 linux32_to_native_sigaction(&ns
, &nls32
);
229 sig
= SCARG(uap
, signum
);
230 if (sig
< 0 || sig
>= LINUX32__NSIG
) {
231 DPRINTF(("rt_sigaction: Bad signal number %d %d\n",
232 sig
, LINUX32__NSIG
));
235 if (sig
> 0 && !linux32_to_native_signo
[sig
]) {
236 /* unknown signal... */
237 os
.sa_handler
= SIG_IGN
;
238 sigemptyset(&os
.sa_mask
);
241 if ((error
= sigaction1(l
,
242 linux32_to_native_signo
[sig
],
243 SCARG_P32(uap
, nsa
) ? &ns
: NULL
,
244 SCARG_P32(uap
, osa
) ? &os
: NULL
,
245 tramp
, vers
)) != 0) {
246 DPRINTF(("rt_sigaction: sigaction %d\n", error
));
251 if (SCARG_P32(uap
, osa
) != NULL
) {
252 native_to_linux32_sigaction(&ols32
, &os
);
254 if ((error
= copyout(&ols32
, SCARG_P32(uap
, osa
),
255 sizeof(ols32
))) != 0) {
256 DPRINTF(("rt_sigaction: Copyout %d\n", error
));
265 linux32_sys_rt_sigprocmask(struct lwp
*l
, const struct linux32_sys_rt_sigprocmask_args
*uap
, register_t
*retval
)
269 syscallarg(const linux32_sigsetp_t) set;
270 syscallarg(linux32_sigsetp_t) oset;
271 syscallarg(netbsd32_size_t) sigsetsize;
273 struct proc
*p
= l
->l_proc
;
274 linux32_sigset_t nls32
, ols32
;
279 if (SCARG(uap
, sigsetsize
) != sizeof(linux32_sigset_t
))
282 switch (SCARG(uap
, how
)) {
283 case LINUX32_SIG_BLOCK
:
286 case LINUX32_SIG_UNBLOCK
:
289 case LINUX32_SIG_SETMASK
:
297 if (SCARG_P32(uap
, set
) != NULL
) {
298 if ((error
= copyin(SCARG_P32(uap
, set
),
299 &nls32
, sizeof(nls32
))) != 0)
301 linux32_to_native_sigset(&ns
, &nls32
);
304 mutex_enter(p
->p_lock
);
305 error
= sigprocmask1(l
, how
,
306 SCARG_P32(uap
, set
) ? &ns
: NULL
,
307 SCARG_P32(uap
, oset
) ? &os
: NULL
);
308 mutex_exit(p
->p_lock
);
313 if (SCARG_P32(uap
, oset
) != NULL
) {
314 native_to_linux32_sigset(&ols32
, &os
);
315 if ((error
= copyout(&ols32
,
316 SCARG_P32(uap
, oset
), sizeof(ols32
))) != 0)
324 linux32_sys_kill(struct lwp
*l
, const struct linux32_sys_kill_args
*uap
, register_t
*retval
)
328 syscallarg(int) signum;
331 struct sys_kill_args ka
;
334 SCARG(&ka
, pid
) = SCARG(uap
, pid
);
335 sig
= SCARG(uap
, signum
);
336 if (sig
< 0 || sig
>= LINUX32__NSIG
)
338 SCARG(&ka
, signum
) = linux32_to_native_signo
[sig
];
339 return sys_kill(l
, &ka
, retval
);
343 linux32_sys_rt_sigsuspend(struct lwp
*l
, const struct linux32_sys_rt_sigsuspend_args
*uap
, register_t
*retval
)
346 syscallarg(linux32_sigsetp_t) unewset;
347 syscallarg(netbsd32_size_t) sigsetsize;
349 linux32_sigset_t lss
;
353 if (SCARG(uap
, sigsetsize
) != sizeof(linux32_sigset_t
))
356 if ((error
= copyin(SCARG_P32(uap
, unewset
),
357 &lss
, sizeof(linux32_sigset_t
))) != 0)
360 linux32_to_native_sigset(&bss
, &lss
);
362 return sigsuspend1(l
, &bss
);
366 linux32_sys_signal(struct lwp
*l
, const struct linux32_sys_signal_args
*uap
, register_t
*retval
)
369 syscallarg(int) signum;
370 syscallarg(linux32_handler_t) handler;
372 struct sigaction nbsa
, obsa
;
377 sig
= SCARG(uap
, signum
);
378 if (sig
< 0 || sig
>= LINUX32__NSIG
)
381 nbsa
.sa_handler
= SCARG_P32(uap
, handler
);
382 sigemptyset(&nbsa
.sa_mask
);
383 nbsa
.sa_flags
= SA_RESETHAND
| SA_NODEFER
;
385 if ((error
= sigaction1(l
, linux32_to_native_signo
[sig
],
386 &nbsa
, &obsa
, NULL
, 0)) != 0)
389 *retval
= (int)(long)obsa
.sa_handler
;
394 linux32_sys_rt_sigpending(struct lwp
*l
, const struct linux32_sys_rt_sigpending_args
*uap
, register_t
*retval
)
397 syscallarg(linux32_sigsetp_t) set;
398 syscallarg(netbsd32_size_t) sigsetsize;
401 linux32_sigset_t lss
;
403 if (SCARG(uap
, sigsetsize
) != sizeof(linux32_sigset_t
))
406 sigpending1(l
, &bss
);
407 native_to_linux32_sigset(&lss
, &bss
);
408 return copyout(&lss
, SCARG_P32(uap
, set
), sizeof(lss
));
412 linux32_sys_siggetmask(struct lwp
*l
, const void *v
, register_t
*retval
)
414 struct proc
*p
= l
->l_proc
;
416 linux32_old_sigset_t lss
;
419 mutex_enter(p
->p_lock
);
420 error
= sigprocmask1(l
, SIG_SETMASK
, 0, &bss
);
421 mutex_exit(p
->p_lock
);
424 native_to_linux32_old_sigset(&lss
, &bss
);
430 linux32_sys_sigsetmask(struct lwp
*l
, const struct linux32_sys_sigsetmask_args
*uap
, register_t
*retval
)
433 syscallarg(linux32_old_sigset_t) mask;
436 linux32_old_sigset_t nlss
, olss
;
437 struct proc
*p
= l
->l_proc
;
440 nlss
= SCARG(uap
, mask
);
441 linux32_old_to_native_sigset(&nbss
, &nlss
);
442 mutex_enter(p
->p_lock
);
443 error
= sigprocmask1(l
, SIG_SETMASK
, &nbss
, &obss
);
444 mutex_exit(p
->p_lock
);
447 native_to_linux32_old_sigset(&olss
, &obss
);
453 linux32_sys_rt_queueinfo(struct lwp
*l
, const struct linux32_sys_rt_queueinfo_args
*uap
, register_t
*retval
)
458 syscallarg(linux32_siginfop_t) uinfo;
461 linux32_siginfo_t info
;
463 error
= copyin(SCARG_P32(uap
, uinfo
), &info
, sizeof(info
));
466 if (info
.lsi_code
>= 0)
469 /* XXX To really implement this we need to */
470 /* XXX keep a list of queued signals somewhere. */
471 return linux32_sys_kill(l
, (const void *)uap
, retval
);