1 | /* $NetBSD: linux32_signal.c,v 1.18 2015/03/08 17:10:44 christos Exp $ */ |
2 | |
3 | /*- |
4 | * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. |
5 | * |
6 | * Redistribution and use in source and binary forms, with or without |
7 | * modification, are permitted provided that the following conditions |
8 | * are met: |
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 |
19 | * permission. |
20 | * |
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. |
32 | */ |
33 | |
34 | #include <sys/cdefs.h> |
35 | __KERNEL_RCSID(0, "$NetBSD: linux32_signal.c,v 1.18 2015/03/08 17:10:44 christos Exp $" ); |
36 | |
37 | #include <sys/param.h> |
38 | #include <sys/ucred.h> |
39 | #include <sys/signalvar.h> |
40 | #include <sys/lwp.h> |
41 | #include <sys/time.h> |
42 | #include <sys/proc.h> |
43 | #include <sys/wait.h> |
44 | |
45 | #include <compat/netbsd32/netbsd32.h> |
46 | |
47 | #include <compat/linux/common/linux_types.h> |
48 | #include <compat/linux/common/linux_signal.h> |
49 | |
50 | #include <compat/linux32/common/linux32_types.h> |
51 | #include <compat/linux32/common/linux32_signal.h> |
52 | #include <compat/linux32/common/linux32_siginfo.h> |
53 | #include <compat/linux32/linux32_syscallargs.h> |
54 | #include <compat/linux32/common/linux32_errno.h> |
55 | #include <compat/linux32/common/linux32_sched.h> |
56 | |
57 | #define linux32_sigemptyset(s) memset((s), 0, sizeof(*(s))) |
58 | #define linux32_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \ |
59 | & (1 << ((n) - 1) % LINUX32__NSIG_BPW)) |
60 | #define linux32_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \ |
61 | |= (1 << ((n) - 1) % LINUX32__NSIG_BPW)) |
62 | |
63 | extern const int native_to_linux32_signo[]; |
64 | extern const int linux32_to_native_signo[]; |
65 | |
66 | #ifdef DEBUG_LINUX |
67 | #define DPRINTF(a) uprintf a |
68 | #else |
69 | #define DPRINTF(a) |
70 | #endif |
71 | |
72 | void |
73 | linux32_to_native_sigset(sigset_t *bss, const linux32_sigset_t *lss) |
74 | { |
75 | int i, newsig; |
76 | |
77 | sigemptyset(bss); |
78 | for (i = 1; i < LINUX32__NSIG; i++) { |
79 | if (linux32_sigismember(lss, i)) { |
80 | newsig = linux32_to_native_signo[i]; |
81 | if (newsig) |
82 | sigaddset(bss, newsig); |
83 | } |
84 | } |
85 | } |
86 | |
87 | void |
88 | native_to_linux32_sigset(linux32_sigset_t *lss, const sigset_t *bss) |
89 | { |
90 | int i, newsig; |
91 | |
92 | linux32_sigemptyset(lss); |
93 | for (i = 1; i < NSIG; i++) { |
94 | if (sigismember(bss, i)) { |
95 | newsig = native_to_linux32_signo[i]; |
96 | if (newsig) |
97 | linux32_sigaddset(lss, newsig); |
98 | } |
99 | } |
100 | } |
101 | |
102 | void |
103 | native_to_linux32_siginfo(linux32_siginfo_t *lsi, const struct _ksiginfo *ksi) |
104 | { |
105 | memset(lsi, 0, sizeof(*lsi)); |
106 | |
107 | lsi->lsi_signo = native_to_linux32_signo[ksi->_signo]; |
108 | lsi->lsi_errno = native_to_linux32_errno[ksi->_errno]; |
109 | lsi->lsi_code = native_to_linux32_si_code(ksi->_code); |
110 | |
111 | switch (ksi->_code) { |
112 | case SI_NOINFO: |
113 | break; |
114 | |
115 | case SI_USER: |
116 | lsi->lsi_pid = ksi->_reason._rt._pid; |
117 | lsi->lsi_uid = ksi->_reason._rt._uid; |
118 | if (lsi->lsi_signo == LINUX_SIGALRM || |
119 | lsi->lsi_signo >= LINUX_SIGRTMIN) |
120 | NETBSD32PTR32(lsi->lsi_value.sival_ptr, |
121 | ksi->_reason._rt._value.sival_ptr); |
122 | break; |
123 | |
124 | case SI_TIMER: |
125 | case SI_QUEUE: |
126 | lsi->lsi_uid = ksi->_reason._rt._uid; |
127 | lsi->lsi_uid = ksi->_reason._rt._uid; |
128 | NETBSD32PTR32(lsi->lsi_value.sival_ptr, |
129 | ksi->_reason._rt._value.sival_ptr); |
130 | break; |
131 | |
132 | case SI_ASYNCIO: |
133 | case SI_MESGQ: |
134 | NETBSD32PTR32(lsi->lsi_value.sival_ptr, |
135 | ksi->_reason._rt._value.sival_ptr); |
136 | break; |
137 | |
138 | default: |
139 | switch (ksi->_signo) { |
140 | case SIGCHLD: |
141 | lsi->lsi_uid = ksi->_reason._child._uid; |
142 | lsi->lsi_pid = ksi->_reason._child._pid; |
143 | lsi->lsi_status = native_to_linux32_si_status( |
144 | ksi->_code, ksi->_reason._child._status); |
145 | lsi->lsi_utime = ksi->_reason._child._utime; |
146 | lsi->lsi_stime = ksi->_reason._child._stime; |
147 | break; |
148 | |
149 | case SIGILL: |
150 | case SIGFPE: |
151 | case SIGSEGV: |
152 | case SIGBUS: |
153 | case SIGTRAP: |
154 | NETBSD32PTR32(lsi->lsi_addr, ksi->_reason._fault._addr); |
155 | break; |
156 | |
157 | case SIGIO: |
158 | lsi->lsi_fd = ksi->_reason._poll._fd; |
159 | lsi->lsi_band = ksi->_reason._poll._band; |
160 | break; |
161 | default: |
162 | break; |
163 | } |
164 | } |
165 | } |
166 | |
167 | unsigned int |
168 | native_to_linux32_sigflags(const int bsf) |
169 | { |
170 | unsigned int lsf = 0; |
171 | if ((bsf & SA_NOCLDSTOP) != 0) |
172 | lsf |= LINUX32_SA_NOCLDSTOP; |
173 | if ((bsf & SA_NOCLDWAIT) != 0) |
174 | lsf |= LINUX32_SA_NOCLDWAIT; |
175 | if ((bsf & SA_ONSTACK) != 0) |
176 | lsf |= LINUX32_SA_ONSTACK; |
177 | if ((bsf & SA_RESTART) != 0) |
178 | lsf |= LINUX32_SA_RESTART; |
179 | if ((bsf & SA_NODEFER) != 0) |
180 | lsf |= LINUX32_SA_NOMASK; |
181 | if ((bsf & SA_RESETHAND) != 0) |
182 | lsf |= LINUX32_SA_ONESHOT; |
183 | if ((bsf & SA_SIGINFO) != 0) |
184 | lsf |= LINUX32_SA_SIGINFO; |
185 | return lsf; |
186 | } |
187 | |
188 | int |
189 | linux32_to_native_sigflags(const unsigned long lsf) |
190 | { |
191 | int bsf = 0; |
192 | if ((lsf & LINUX32_SA_NOCLDSTOP) != 0) |
193 | bsf |= SA_NOCLDSTOP; |
194 | if ((lsf & LINUX32_SA_NOCLDWAIT) != 0) |
195 | bsf |= SA_NOCLDWAIT; |
196 | if ((lsf & LINUX32_SA_ONSTACK) != 0) |
197 | bsf |= SA_ONSTACK; |
198 | if ((lsf & LINUX32_SA_RESTART) != 0) |
199 | bsf |= SA_RESTART; |
200 | if ((lsf & LINUX32_SA_ONESHOT) != 0) |
201 | bsf |= SA_RESETHAND; |
202 | if ((lsf & LINUX32_SA_NOMASK) != 0) |
203 | bsf |= SA_NODEFER; |
204 | if ((lsf & LINUX32_SA_SIGINFO) != 0) |
205 | bsf |= SA_SIGINFO; |
206 | if ((lsf & ~LINUX32_SA_ALLBITS) != 0) { |
207 | #ifdef DEBUG_LINUX |
208 | printf("linux32_old_to_native_sigflags: " |
209 | "%lx extra bits ignored\n" , lsf); |
210 | #endif |
211 | } |
212 | return bsf; |
213 | } |
214 | |
215 | void |
216 | linux32_to_native_sigaction(struct sigaction *bsa, const struct linux32_sigaction *lsa) |
217 | { |
218 | bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler); |
219 | linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); |
220 | bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags); |
221 | } |
222 | |
223 | void |
224 | native_to_linux32_sigaction(struct linux32_sigaction *lsa, const struct sigaction *bsa) |
225 | { |
226 | NETBSD32PTR32(lsa->linux_sa_handler, bsa->sa_handler); |
227 | native_to_linux32_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); |
228 | lsa->linux_sa_flags = native_to_linux32_sigflags(bsa->sa_flags); |
229 | NETBSD32PTR32(lsa->linux_sa_restorer, NULL); |
230 | } |
231 | |
232 | void |
233 | native_to_linux32_sigaltstack(struct linux32_sigaltstack *lss, const struct sigaltstack *bss) |
234 | { |
235 | NETBSD32PTR32(lss->ss_sp, bss->ss_sp); |
236 | lss->ss_size = bss->ss_size; |
237 | if (bss->ss_flags & SS_ONSTACK) |
238 | lss->ss_flags = LINUX32_SS_ONSTACK; |
239 | else if (bss->ss_flags & SS_DISABLE) |
240 | lss->ss_flags = LINUX32_SS_DISABLE; |
241 | else |
242 | lss->ss_flags = 0; |
243 | } |
244 | |
245 | |
246 | void |
247 | native_to_linux32_old_sigset(linux32_old_sigset_t *lss, const sigset_t *bss) |
248 | { |
249 | linux32_sigset_t lsnew; |
250 | |
251 | native_to_linux32_sigset(&lsnew, bss); |
252 | |
253 | /* convert new sigset to old sigset */ |
254 | *lss = lsnew.sig[0]; |
255 | } |
256 | |
257 | void |
258 | linux32_old_to_native_sigset(sigset_t *bss, const linux32_old_sigset_t *lss) |
259 | { |
260 | linux32_sigset_t ls; |
261 | |
262 | memset(&ls, 0, sizeof(ls)); |
263 | ls.sig[0] = *lss; |
264 | |
265 | linux32_to_native_sigset(bss, &ls); |
266 | } |
267 | |
268 | int |
269 | linux32_sys_rt_sigaction(struct lwp *l, const struct linux32_sys_rt_sigaction_args *uap, register_t *retval) |
270 | { |
271 | /* { |
272 | syscallarg(int) signum; |
273 | syscallarg(const linux32_sigactionp_t) nsa; |
274 | syscallarg(linux32_sigactionp_t) osa; |
275 | syscallarg(netbsd32_size_t) sigsetsize; |
276 | } */ |
277 | struct linux32_sigaction nls32; |
278 | struct linux32_sigaction ols32; |
279 | struct sigaction ns; |
280 | struct sigaction os; |
281 | int error; |
282 | int sig; |
283 | int vers = 0; |
284 | void *tramp = NULL; |
285 | |
286 | if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) { |
287 | DPRINTF(("rt_sigaction: Inconsistent sigsetsize %u %zu\n" , |
288 | SCARG(uap, sigsetsize), sizeof(linux32_sigset_t))); |
289 | return EINVAL; |
290 | } |
291 | |
292 | if (SCARG_P32(uap, nsa) != NULL) { |
293 | if ((error = copyin(SCARG_P32(uap, nsa), |
294 | &nls32, sizeof(nls32))) != 0) { |
295 | DPRINTF(("rt_sigaction: Copyin %d\n" , error)); |
296 | return error; |
297 | } |
298 | linux32_to_native_sigaction(&ns, &nls32); |
299 | } |
300 | |
301 | sig = SCARG(uap, signum); |
302 | if (sig < 0 || sig >= LINUX32__NSIG) { |
303 | DPRINTF(("rt_sigaction: Bad signal number %d %d\n" , |
304 | sig, LINUX32__NSIG)); |
305 | return EINVAL; |
306 | } |
307 | if (sig > 0 && !linux32_to_native_signo[sig]) { |
308 | /* unknown signal... */ |
309 | os.sa_handler = SIG_IGN; |
310 | sigemptyset(&os.sa_mask); |
311 | os.sa_flags = 0; |
312 | } else { |
313 | if ((error = sigaction1(l, |
314 | linux32_to_native_signo[sig], |
315 | SCARG_P32(uap, nsa) ? &ns : NULL, |
316 | SCARG_P32(uap, osa) ? &os : NULL, |
317 | tramp, vers)) != 0) { |
318 | DPRINTF(("rt_sigaction: sigaction %d\n" , error)); |
319 | return error; |
320 | } |
321 | } |
322 | |
323 | if (SCARG_P32(uap, osa) != NULL) { |
324 | native_to_linux32_sigaction(&ols32, &os); |
325 | |
326 | if ((error = copyout(&ols32, SCARG_P32(uap, osa), |
327 | sizeof(ols32))) != 0) { |
328 | DPRINTF(("rt_sigaction: Copyout %d\n" , error)); |
329 | return error; |
330 | } |
331 | } |
332 | |
333 | return 0; |
334 | } |
335 | |
336 | int |
337 | linux32_sys_rt_sigprocmask(struct lwp *l, const struct linux32_sys_rt_sigprocmask_args *uap, register_t *retval) |
338 | { |
339 | /* { |
340 | syscallarg(int) how; |
341 | syscallarg(const linux32_sigsetp_t) set; |
342 | syscallarg(linux32_sigsetp_t) oset; |
343 | syscallarg(netbsd32_size_t) sigsetsize; |
344 | } */ |
345 | struct proc *p = l->l_proc; |
346 | linux32_sigset_t nls32, ols32; |
347 | sigset_t ns, os; |
348 | int error; |
349 | int how; |
350 | |
351 | if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) |
352 | return EINVAL; |
353 | |
354 | switch (SCARG(uap, how)) { |
355 | case LINUX32_SIG_BLOCK: |
356 | how = SIG_BLOCK; |
357 | break; |
358 | case LINUX32_SIG_UNBLOCK: |
359 | how = SIG_UNBLOCK; |
360 | break; |
361 | case LINUX32_SIG_SETMASK: |
362 | how = SIG_SETMASK; |
363 | break; |
364 | default: |
365 | return EINVAL; |
366 | break; |
367 | } |
368 | |
369 | if (SCARG_P32(uap, set) != NULL) { |
370 | if ((error = copyin(SCARG_P32(uap, set), |
371 | &nls32, sizeof(nls32))) != 0) |
372 | return error; |
373 | linux32_to_native_sigset(&ns, &nls32); |
374 | } |
375 | |
376 | mutex_enter(p->p_lock); |
377 | error = sigprocmask1(l, how, |
378 | SCARG_P32(uap, set) ? &ns : NULL, |
379 | SCARG_P32(uap, oset) ? &os : NULL); |
380 | mutex_exit(p->p_lock); |
381 | |
382 | if (error != 0) |
383 | return error; |
384 | |
385 | if (SCARG_P32(uap, oset) != NULL) { |
386 | native_to_linux32_sigset(&ols32, &os); |
387 | if ((error = copyout(&ols32, |
388 | SCARG_P32(uap, oset), sizeof(ols32))) != 0) |
389 | return error; |
390 | } |
391 | |
392 | return 0; |
393 | } |
394 | |
395 | int |
396 | linux32_sys_kill(struct lwp *l, const struct linux32_sys_kill_args *uap, register_t *retval) |
397 | { |
398 | /* { |
399 | syscallarg(int) pid; |
400 | syscallarg(int) signum; |
401 | } */ |
402 | |
403 | struct sys_kill_args ka; |
404 | int sig; |
405 | |
406 | SCARG(&ka, pid) = SCARG(uap, pid); |
407 | sig = SCARG(uap, signum); |
408 | if (sig < 0 || sig >= LINUX32__NSIG) |
409 | return (EINVAL); |
410 | SCARG(&ka, signum) = linux32_to_native_signo[sig]; |
411 | return sys_kill(l, &ka, retval); |
412 | } |
413 | |
414 | int |
415 | linux32_sys_rt_sigsuspend(struct lwp *l, const struct linux32_sys_rt_sigsuspend_args *uap, register_t *retval) |
416 | { |
417 | /* { |
418 | syscallarg(linux32_sigsetp_t) unewset; |
419 | syscallarg(netbsd32_size_t) sigsetsize; |
420 | } */ |
421 | linux32_sigset_t lss; |
422 | sigset_t bss; |
423 | int error; |
424 | |
425 | if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) |
426 | return EINVAL; |
427 | |
428 | if ((error = copyin(SCARG_P32(uap, unewset), |
429 | &lss, sizeof(linux32_sigset_t))) != 0) |
430 | return error; |
431 | |
432 | linux32_to_native_sigset(&bss, &lss); |
433 | |
434 | return sigsuspend1(l, &bss); |
435 | } |
436 | |
437 | static int |
438 | fetchss(const void *u, void *s, size_t len) |
439 | { |
440 | int error; |
441 | linux32_sigset_t lss; |
442 | |
443 | if ((error = copyin(u, &lss, sizeof(lss))) != 0) |
444 | return error; |
445 | |
446 | linux32_to_native_sigset(s, &lss); |
447 | return 0; |
448 | } |
449 | |
450 | static int |
451 | fetchts(const void *u, void *s, size_t len) |
452 | { |
453 | int error; |
454 | struct linux32_timespec lts; |
455 | |
456 | if ((error = copyin(u, <s, sizeof(lts))) != 0) |
457 | return error; |
458 | |
459 | linux32_to_native_timespec(s, <s); |
460 | return 0; |
461 | } |
462 | |
463 | static int |
464 | fakestorets(const void *u, void *s, size_t len) |
465 | { |
466 | /* Do nothing, sigtimedwait does not alter timeout like ours */ |
467 | return 0; |
468 | } |
469 | |
470 | static int |
471 | storeinfo(const void *s, void *u, size_t len) |
472 | { |
473 | linux32_siginfo_t lsi; |
474 | |
475 | |
476 | native_to_linux32_siginfo(&lsi, &((const siginfo_t *)s)->_info); |
477 | return copyout(&lsi, u, sizeof(lsi)); |
478 | } |
479 | |
480 | int |
481 | linux32_sys_rt_sigtimedwait(struct lwp *l, |
482 | const struct linux32_sys_rt_sigtimedwait_args *uap, register_t *retval) |
483 | { |
484 | /* { |
485 | syscallarg(const linux32_sigset_t *) set; |
486 | syscallarg(linux32_siginfo_t *) info); |
487 | syscallarg(const struct linux32_timespec *) timeout; |
488 | } */ |
489 | struct sys_____sigtimedwait50_args ap; |
490 | |
491 | SCARG(&ap, set) = SCARG_P32(uap, set); |
492 | SCARG(&ap, info) = SCARG_P32(uap, info); |
493 | SCARG(&ap, timeout) = SCARG_P32(uap, timeout); |
494 | |
495 | return sigtimedwait1(l, &ap, |
496 | retval, fetchss, storeinfo, fetchts, fakestorets); |
497 | } |
498 | |
499 | int |
500 | linux32_sys_signal(struct lwp *l, const struct linux32_sys_signal_args *uap, register_t *retval) |
501 | { |
502 | /* { |
503 | syscallarg(int) signum; |
504 | syscallarg(linux32_handlerp_t) handler; |
505 | } */ |
506 | struct sigaction nbsa, obsa; |
507 | int error, sig; |
508 | |
509 | *retval = -1; |
510 | |
511 | sig = SCARG(uap, signum); |
512 | if (sig < 0 || sig >= LINUX32__NSIG) |
513 | return EINVAL; |
514 | |
515 | nbsa.sa_handler = SCARG_P32(uap, handler); |
516 | sigemptyset(&nbsa.sa_mask); |
517 | nbsa.sa_flags = SA_RESETHAND | SA_NODEFER; |
518 | |
519 | if ((error = sigaction1(l, linux32_to_native_signo[sig], |
520 | &nbsa, &obsa, NULL, 0)) != 0) |
521 | return error; |
522 | |
523 | *retval = (int)(long)obsa.sa_handler; |
524 | return 0; |
525 | } |
526 | |
527 | int |
528 | linux32_sys_rt_sigpending(struct lwp *l, const struct linux32_sys_rt_sigpending_args *uap, register_t *retval) |
529 | { |
530 | /* { |
531 | syscallarg(linux32_sigsetp_t) set; |
532 | syscallarg(netbsd32_size_t) sigsetsize; |
533 | } */ |
534 | sigset_t bss; |
535 | linux32_sigset_t lss; |
536 | |
537 | if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) |
538 | return EINVAL; |
539 | |
540 | sigpending1(l, &bss); |
541 | native_to_linux32_sigset(&lss, &bss); |
542 | return copyout(&lss, SCARG_P32(uap, set), sizeof(lss)); |
543 | } |
544 | |
545 | int |
546 | linux32_sys_siggetmask(struct lwp *l, const void *v, register_t *retval) |
547 | { |
548 | struct proc *p = l->l_proc; |
549 | sigset_t bss; |
550 | linux32_old_sigset_t lss; |
551 | int error; |
552 | |
553 | mutex_enter(p->p_lock); |
554 | error = sigprocmask1(l, SIG_SETMASK, 0, &bss); |
555 | mutex_exit(p->p_lock); |
556 | if (error) |
557 | return error; |
558 | native_to_linux32_old_sigset(&lss, &bss); |
559 | *retval = lss; |
560 | return 0; |
561 | } |
562 | |
563 | int |
564 | linux32_sys_sigsetmask(struct lwp *l, const struct linux32_sys_sigsetmask_args *uap, register_t *retval) |
565 | { |
566 | /* { |
567 | syscallarg(linux32_old_sigset_t) mask; |
568 | } */ |
569 | sigset_t nbss, obss; |
570 | linux32_old_sigset_t nlss, olss; |
571 | struct proc *p = l->l_proc; |
572 | int error; |
573 | |
574 | nlss = SCARG(uap, mask); |
575 | linux32_old_to_native_sigset(&nbss, &nlss); |
576 | mutex_enter(p->p_lock); |
577 | error = sigprocmask1(l, SIG_SETMASK, &nbss, &obss); |
578 | mutex_exit(p->p_lock); |
579 | if (error) |
580 | return error; |
581 | native_to_linux32_old_sigset(&olss, &obss); |
582 | *retval = olss; |
583 | return 0; |
584 | } |
585 | |
586 | int |
587 | linux32_sys_rt_queueinfo(struct lwp *l, const struct linux32_sys_rt_queueinfo_args *uap, register_t *retval) |
588 | { |
589 | /* |
590 | syscallarg(int) pid; |
591 | syscallarg(int) sig; |
592 | syscallarg(linux32_siginfop_t) uinfo; |
593 | */ |
594 | int error; |
595 | linux32_siginfo_t info; |
596 | |
597 | error = copyin(SCARG_P32(uap, uinfo), &info, sizeof(info)); |
598 | if (error) |
599 | return error; |
600 | if (info.lsi_code >= 0) |
601 | return EPERM; |
602 | |
603 | /* XXX To really implement this we need to */ |
604 | /* XXX keep a list of queued signals somewhere. */ |
605 | return linux32_sys_kill(l, (const void *)uap, retval); |
606 | } |
607 | |
608 | int |
609 | native_to_linux32_si_code(int code) |
610 | { |
611 | int si_codes[] = { |
612 | LINUX32_SI_USER, LINUX32_SI_QUEUE, LINUX32_SI_TIMER, |
613 | LINUX32_SI_ASYNCIO, LINUX32_SI_MESGQ, LINUX32_SI_TKILL /* SI_LWP */ |
614 | }; |
615 | |
616 | if (code <= 0 && -code < __arraycount(si_codes)) |
617 | return si_codes[-code]; |
618 | |
619 | return code; |
620 | } |
621 | |
622 | int |
623 | native_to_linux32_si_status(int code, int status) |
624 | { |
625 | int sts; |
626 | |
627 | switch (code) { |
628 | case CLD_CONTINUED: |
629 | sts = LINUX_SIGCONT; |
630 | break; |
631 | case CLD_EXITED: |
632 | sts = WEXITSTATUS(status); |
633 | break; |
634 | case CLD_STOPPED: |
635 | case CLD_TRAPPED: |
636 | case CLD_DUMPED: |
637 | case CLD_KILLED: |
638 | default: |
639 | sts = native_to_linux32_signo[WTERMSIG(status)]; |
640 | break; |
641 | } |
642 | |
643 | return sts; |
644 | } |
645 | |