linux32_signal.c revision 1.20.8.1 1 /* $NetBSD: linux32_signal.c,v 1.20.8.1 2020/12/17 03:00:28 thorpej 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.20.8.1 2020/12/17 03:00:28 thorpej 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
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
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
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
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
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
218 linux32_to_native_sigaction(struct sigaction *bsa, const struct linux32_sigaction *lsa)
219 {
220 bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler);
221 linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask);
222 bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags);
223 }
224
225 void
226 native_to_linux32_sigaction(struct linux32_sigaction *lsa, const struct sigaction *bsa)
227 {
228 NETBSD32PTR32(lsa->linux_sa_handler, bsa->sa_handler);
229 native_to_linux32_sigset(&lsa->linux_sa_mask, &bsa->sa_mask);
230 lsa->linux_sa_flags = native_to_linux32_sigflags(bsa->sa_flags);
231 NETBSD32PTR32(lsa->linux_sa_restorer, NULL);
232 }
233
234 void
235 native_to_linux32_sigaltstack(struct linux32_sigaltstack *lss, const struct sigaltstack *bss)
236 {
237 memset(lss, 0, sizeof(*lss));
238 NETBSD32PTR32(lss->ss_sp, bss->ss_sp);
239 lss->ss_size = bss->ss_size;
240 if (bss->ss_flags & SS_ONSTACK)
241 lss->ss_flags = LINUX32_SS_ONSTACK;
242 else if (bss->ss_flags & SS_DISABLE)
243 lss->ss_flags = LINUX32_SS_DISABLE;
244 else
245 lss->ss_flags = 0;
246 }
247
248
249 void
250 native_to_linux32_old_sigset(linux32_old_sigset_t *lss, const sigset_t *bss)
251 {
252 linux32_sigset_t lsnew;
253
254 native_to_linux32_sigset(&lsnew, bss);
255
256 /* convert new sigset to old sigset */
257 *lss = lsnew.sig[0];
258 }
259
260 void
261 linux32_old_to_native_sigset(sigset_t *bss, const linux32_old_sigset_t *lss)
262 {
263 linux32_sigset_t ls;
264
265 memset(&ls, 0, sizeof(ls));
266 ls.sig[0] = *lss;
267
268 linux32_to_native_sigset(bss, &ls);
269 }
270
271 int
272 linux32_sys_rt_sigaction(struct lwp *l, const struct linux32_sys_rt_sigaction_args *uap, register_t *retval)
273 {
274 /* {
275 syscallarg(int) signum;
276 syscallarg(const linux32_sigactionp_t) nsa;
277 syscallarg(linux32_sigactionp_t) osa;
278 syscallarg(netbsd32_size_t) sigsetsize;
279 } */
280 struct linux32_sigaction nls32;
281 struct linux32_sigaction ols32;
282 struct sigaction ns;
283 struct sigaction os;
284 int error;
285 int sig;
286 int vers = 0;
287 void *tramp = NULL;
288
289 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) {
290 DPRINTF(("rt_sigaction: Inconsistent sigsetsize %u %zu\n",
291 SCARG(uap, sigsetsize), sizeof(linux32_sigset_t)));
292 return EINVAL;
293 }
294
295 if (SCARG_P32(uap, nsa) != NULL) {
296 if ((error = copyin(SCARG_P32(uap, nsa),
297 &nls32, sizeof(nls32))) != 0) {
298 DPRINTF(("rt_sigaction: Copyin %d\n", error));
299 return error;
300 }
301 linux32_to_native_sigaction(&ns, &nls32);
302 }
303
304 sig = SCARG(uap, signum);
305 /*
306 * XXX: Linux has 33 realtime signals, the go binary wants to
307 * reset all of them; nothing else uses the last RT signal, so for
308 * now ignore it.
309 */
310 if (sig == LINUX__NSIG) {
311 uprintf("%s: setting signal %d ignored\n", __func__, sig);
312 sig--; /* back to 63 which is ignored */
313 }
314 if (sig < 0 || sig >= LINUX32__NSIG) {
315 DPRINTF(("rt_sigaction: Bad signal number %d %d\n",
316 sig, LINUX32__NSIG));
317 return EINVAL;
318 }
319 if (sig > 0 && !linux32_to_native_signo[sig]) {
320 /* unknown signal... */
321 os.sa_handler = SIG_IGN;
322 sigemptyset(&os.sa_mask);
323 os.sa_flags = 0;
324 } else {
325 if ((error = sigaction1(l,
326 linux32_to_native_signo[sig],
327 SCARG_P32(uap, nsa) ? &ns : NULL,
328 SCARG_P32(uap, osa) ? &os : NULL,
329 tramp, vers)) != 0) {
330 DPRINTF(("rt_sigaction: sigaction %d\n", error));
331 return error;
332 }
333 }
334
335 if (SCARG_P32(uap, osa) != NULL) {
336 native_to_linux32_sigaction(&ols32, &os);
337
338 if ((error = copyout(&ols32, SCARG_P32(uap, osa),
339 sizeof(ols32))) != 0) {
340 DPRINTF(("rt_sigaction: Copyout %d\n", error));
341 return error;
342 }
343 }
344
345 return 0;
346 }
347
348 int
349 linux32_sys_rt_sigprocmask(struct lwp *l, const struct linux32_sys_rt_sigprocmask_args *uap, register_t *retval)
350 {
351 /* {
352 syscallarg(int) how;
353 syscallarg(const linux32_sigsetp_t) set;
354 syscallarg(linux32_sigsetp_t) oset;
355 syscallarg(netbsd32_size_t) sigsetsize;
356 } */
357 struct proc *p = l->l_proc;
358 linux32_sigset_t nls32, ols32;
359 sigset_t ns, os;
360 int error;
361 int how;
362
363 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
364 return EINVAL;
365
366 switch (SCARG(uap, how)) {
367 case LINUX32_SIG_BLOCK:
368 how = SIG_BLOCK;
369 break;
370 case LINUX32_SIG_UNBLOCK:
371 how = SIG_UNBLOCK;
372 break;
373 case LINUX32_SIG_SETMASK:
374 how = SIG_SETMASK;
375 break;
376 default:
377 return EINVAL;
378 break;
379 }
380
381 if (SCARG_P32(uap, set) != NULL) {
382 if ((error = copyin(SCARG_P32(uap, set),
383 &nls32, sizeof(nls32))) != 0)
384 return error;
385 linux32_to_native_sigset(&ns, &nls32);
386 }
387
388 mutex_enter(p->p_lock);
389 error = sigprocmask1(l, how,
390 SCARG_P32(uap, set) ? &ns : NULL,
391 SCARG_P32(uap, oset) ? &os : NULL);
392 mutex_exit(p->p_lock);
393
394 if (error != 0)
395 return error;
396
397 if (SCARG_P32(uap, oset) != NULL) {
398 native_to_linux32_sigset(&ols32, &os);
399 if ((error = copyout(&ols32,
400 SCARG_P32(uap, oset), sizeof(ols32))) != 0)
401 return error;
402 }
403
404 return 0;
405 }
406
407 int
408 linux32_sys_kill(struct lwp *l, const struct linux32_sys_kill_args *uap, register_t *retval)
409 {
410 /* {
411 syscallarg(int) pid;
412 syscallarg(int) signum;
413 } */
414
415 struct sys_kill_args ka;
416 int sig;
417
418 SCARG(&ka, pid) = SCARG(uap, pid);
419 sig = SCARG(uap, signum);
420 if (sig < 0 || sig >= LINUX32__NSIG)
421 return (EINVAL);
422 SCARG(&ka, signum) = linux32_to_native_signo[sig];
423 return sys_kill(l, &ka, retval);
424 }
425
426 int
427 linux32_sys_rt_sigsuspend(struct lwp *l, const struct linux32_sys_rt_sigsuspend_args *uap, register_t *retval)
428 {
429 /* {
430 syscallarg(linux32_sigsetp_t) unewset;
431 syscallarg(netbsd32_size_t) sigsetsize;
432 } */
433 linux32_sigset_t lss;
434 sigset_t bss;
435 int error;
436
437 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
438 return EINVAL;
439
440 if ((error = copyin(SCARG_P32(uap, unewset),
441 &lss, sizeof(linux32_sigset_t))) != 0)
442 return error;
443
444 linux32_to_native_sigset(&bss, &lss);
445
446 return sigsuspend1(l, &bss);
447 }
448
449 static int
450 fetchss(const void *u, void *s, size_t len)
451 {
452 int error;
453 linux32_sigset_t lss;
454
455 if ((error = copyin(u, &lss, sizeof(lss))) != 0)
456 return error;
457
458 linux32_to_native_sigset(s, &lss);
459 return 0;
460 }
461
462 static int
463 fetchts(const void *u, void *s, size_t len)
464 {
465 int error;
466 struct linux32_timespec lts;
467
468 if ((error = copyin(u, <s, sizeof(lts))) != 0)
469 return error;
470
471 linux32_to_native_timespec(s, <s);
472 return 0;
473 }
474
475 static int
476 fakestorets(const void *u, void *s, size_t len)
477 {
478 /* Do nothing, sigtimedwait does not alter timeout like ours */
479 return 0;
480 }
481
482 static int
483 storeinfo(const void *s, void *u, size_t len)
484 {
485 linux32_siginfo_t lsi;
486
487
488 native_to_linux32_siginfo(&lsi, &((const siginfo_t *)s)->_info);
489 return copyout(&lsi, u, sizeof(lsi));
490 }
491
492 int
493 linux32_sys_rt_sigtimedwait(struct lwp *l,
494 const struct linux32_sys_rt_sigtimedwait_args *uap, register_t *retval)
495 {
496 /* {
497 syscallarg(const linux32_sigset_t *) set;
498 syscallarg(linux32_siginfo_t *) info);
499 syscallarg(const struct linux32_timespec *) timeout;
500 } */
501 struct sys_____sigtimedwait50_args ap;
502
503 SCARG(&ap, set) = SCARG_P32(uap, set);
504 SCARG(&ap, info) = SCARG_P32(uap, info);
505 SCARG(&ap, timeout) = SCARG_P32(uap, timeout);
506
507 return sigtimedwait1(l, &ap,
508 retval, fetchss, storeinfo, fetchts, fakestorets);
509 }
510
511 int
512 linux32_sys_signal(struct lwp *l, const struct linux32_sys_signal_args *uap, register_t *retval)
513 {
514 /* {
515 syscallarg(int) signum;
516 syscallarg(linux32_handlerp_t) handler;
517 } */
518 struct sigaction nbsa, obsa;
519 int error, sig;
520
521 *retval = -1;
522
523 sig = SCARG(uap, signum);
524 if (sig < 0 || sig >= LINUX32__NSIG)
525 return EINVAL;
526
527 nbsa.sa_handler = SCARG_P32(uap, handler);
528 sigemptyset(&nbsa.sa_mask);
529 nbsa.sa_flags = SA_RESETHAND | SA_NODEFER;
530
531 if ((error = sigaction1(l, linux32_to_native_signo[sig],
532 &nbsa, &obsa, NULL, 0)) != 0)
533 return error;
534
535 *retval = (int)(long)obsa.sa_handler;
536 return 0;
537 }
538
539 int
540 linux32_sys_rt_sigpending(struct lwp *l, const struct linux32_sys_rt_sigpending_args *uap, register_t *retval)
541 {
542 /* {
543 syscallarg(linux32_sigsetp_t) set;
544 syscallarg(netbsd32_size_t) sigsetsize;
545 } */
546 sigset_t bss;
547 linux32_sigset_t lss;
548
549 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t))
550 return EINVAL;
551
552 sigpending1(l, &bss);
553 native_to_linux32_sigset(&lss, &bss);
554 return copyout(&lss, SCARG_P32(uap, set), sizeof(lss));
555 }
556
557 int
558 linux32_sys_siggetmask(struct lwp *l, const void *v, register_t *retval)
559 {
560 struct proc *p = l->l_proc;
561 sigset_t bss;
562 linux32_old_sigset_t lss;
563 int error;
564
565 mutex_enter(p->p_lock);
566 error = sigprocmask1(l, SIG_SETMASK, 0, &bss);
567 mutex_exit(p->p_lock);
568 if (error)
569 return error;
570 native_to_linux32_old_sigset(&lss, &bss);
571 *retval = lss;
572 return 0;
573 }
574
575 int
576 linux32_sys_sigsetmask(struct lwp *l, const struct linux32_sys_sigsetmask_args *uap, register_t *retval)
577 {
578 /* {
579 syscallarg(linux32_old_sigset_t) mask;
580 } */
581 sigset_t nbss, obss;
582 linux32_old_sigset_t nlss, olss;
583 struct proc *p = l->l_proc;
584 int error;
585
586 nlss = SCARG(uap, mask);
587 linux32_old_to_native_sigset(&nbss, &nlss);
588 mutex_enter(p->p_lock);
589 error = sigprocmask1(l, SIG_SETMASK, &nbss, &obss);
590 mutex_exit(p->p_lock);
591 if (error)
592 return error;
593 native_to_linux32_old_sigset(&olss, &obss);
594 *retval = olss;
595 return 0;
596 }
597
598 int
599 linux32_sys_rt_queueinfo(struct lwp *l, const struct linux32_sys_rt_queueinfo_args *uap, register_t *retval)
600 {
601 /*
602 syscallarg(int) pid;
603 syscallarg(int) sig;
604 syscallarg(linux32_siginfop_t) uinfo;
605 */
606 int error;
607 linux32_siginfo_t info;
608
609 error = copyin(SCARG_P32(uap, uinfo), &info, sizeof(info));
610 if (error)
611 return error;
612 if (info.lsi_code >= 0)
613 return EPERM;
614
615 /* XXX To really implement this we need to */
616 /* XXX keep a list of queued signals somewhere. */
617 return linux32_sys_kill(l, (const void *)uap, retval);
618 }
619
620 int
621 native_to_linux32_si_code(int code)
622 {
623 int si_codes[] = {
624 LINUX32_SI_USER, LINUX32_SI_QUEUE, LINUX32_SI_TIMER,
625 LINUX32_SI_ASYNCIO, LINUX32_SI_MESGQ, LINUX32_SI_TKILL /* SI_LWP */
626 };
627
628 if (code <= 0 && -code < __arraycount(si_codes))
629 return si_codes[-code];
630
631 return code;
632 }
633
634 int
635 native_to_linux32_si_status(int code, int status)
636 {
637 int sts;
638
639 switch (code) {
640 case CLD_CONTINUED:
641 sts = LINUX_SIGCONT;
642 break;
643 case CLD_EXITED:
644 sts = WEXITSTATUS(status);
645 break;
646 case CLD_STOPPED:
647 case CLD_TRAPPED:
648 case CLD_DUMPED:
649 case CLD_KILLED:
650 default:
651 sts = native_to_linux32_signo[WTERMSIG(status)];
652 break;
653 }
654
655 return sts;
656 }
657
658 int
659 linux32_to_native_sigevent(struct sigevent *nsep,
660 const struct linux32_sigevent *lsep)
661 {
662 memset(nsep, 0, sizeof(*nsep));
663
664 switch (lsep->sigev_notify) {
665 case LINUX_SIGEV_SIGNAL:
666 nsep->sigev_notify = SIGEV_SIGNAL;
667 break;
668
669 case LINUX_SIGEV_NONE:
670 nsep->sigev_notify = SIGEV_NONE;
671 break;
672
673 case LINUX_SIGEV_THREAD:
674 case LINUX_SIGEV_THREAD_ID:
675 default:
676 return ENOTSUP;
677 }
678
679 #if _BYTE_ORDER == _LITTLE_ENDIAN
680 nsep->sigev_value.sival_ptr =
681 NETBSD32PTR64(lsep->sigev_value.sival_ptr);
682 #else
683 #error This is probably broken on big-endian platforms.
684 #endif
685
686 if (lsep->sigev_signo < 0 || lsep->sigev_signo >= LINUX32__NSIG) {
687 return EINVAL;
688 }
689 nsep->sigev_signo = linux32_to_native_signo[lsep->sigev_signo];
690
691 return 0;
692 }
693
694 int
695 linux32_sigevent_copyin(const void *src, void *dst, size_t size)
696 {
697 struct linux32_sigevent lse;
698 struct sigevent *sep = dst;
699 int error;
700
701 KASSERT(size == sizeof(*sep));
702
703 error = copyin(src, &lse, sizeof(lse));
704 if (error) {
705 return error;
706 }
707
708 return linux32_to_native_sigevent(sep, &lse);
709 }
710