1 /* $NetBSD: linux32_signal.c,v 1.21 2021/09/07 11:43:04 riastradh 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.21 2021/09/07 11:43:04 riastradh 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 memset(bsa, 0, sizeof(*bsa)); 219 bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler); 220 linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 221 bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags); 222 } 223 224 void 225 native_to_linux32_sigaction(struct linux32_sigaction *lsa, const struct sigaction *bsa) 226 { 227 memset(lsa, 0, sizeof(*lsa)); 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