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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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 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