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