1 /* $NetBSD: linux_signal.c,v 1.92 2026/09/20 13:43:51 riastradh Exp $ */ 2 3 /*- 4 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. 5 * All rights reserved. 6 * 7 * This code is derived from software contributed to The NetBSD Foundation 8 * by Frank van der Linden and Eric Haszlakiewicz. 9 * 10 * Redistribution and use in source and binary forms, with or without 11 * modification, are permitted provided that the following conditions 12 * are met: 13 * 1. Redistributions of source code must retain the above copyright 14 * notice, this list of conditions and the following disclaimer. 15 * 2. Redistributions in binary form must reproduce the above copyright 16 * notice, this list of conditions and the following disclaimer in the 17 * documentation and/or other materials provided with the distribution. 18 * 19 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 20 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 21 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 22 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 23 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 24 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 25 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 26 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 27 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 28 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 29 * POSSIBILITY OF SUCH DAMAGE. 30 */ 31 /* 32 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp 33 */ 34 35 /* 36 * Functions in multiarch: 37 * linux_sys_signal : linux_sig_notalpha.c 38 * linux_sys_siggetmask : linux_sig_notalpha.c 39 * linux_sys_sigsetmask : linux_sig_notalpha.c 40 * linux_sys_pause : linux_sig_notalpha.c 41 * linux_sys_sigaction : linux_sigaction.c 42 * 43 */ 44 45 /* 46 * Unimplemented: 47 * linux_sys_rt_sigtimedwait : sigsuspend w/timeout. 48 */ 49 50 #include <sys/cdefs.h> 51 __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.92 2026/09/20 13:43:51 riastradh Exp $"); 52 53 #define COMPAT_LINUX 1 54 55 #include <sys/param.h> 56 #include <sys/systm.h> 57 #include <sys/namei.h> 58 #include <sys/proc.h> 59 #include <sys/filedesc.h> 60 #include <sys/ioctl.h> 61 #include <sys/mount.h> 62 #include <sys/kernel.h> 63 #include <sys/signal.h> 64 #include <sys/signalvar.h> 65 #include <sys/wait.h> 66 67 #include <sys/syscallargs.h> 68 69 #include <compat/linux/common/linux_types.h> 70 #include <compat/linux/common/linux_signal.h> 71 #include <compat/linux/common/linux_emuldata.h> 72 #include <compat/linux/common/linux_siginfo.h> 73 #include <compat/linux/common/linux_sigevent.h> 74 #include <compat/linux/common/linux_util.h> 75 #include <compat/linux/common/linux_ipc.h> 76 #include <compat/linux/common/linux_sem.h> 77 #include <compat/linux/common/linux_errno.h> 78 #include <compat/linux/common/linux_sched.h> 79 80 #include <compat/linux/linux_syscallargs.h> 81 82 /* Locally used defines (in bsd<->linux conversion functions): */ 83 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s))) 84 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 85 & (1L << ((n) - 1) % LINUX__NSIG_BPW)) 86 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 87 |= (1L << ((n) - 1) % LINUX__NSIG_BPW)) 88 89 #ifdef DEBUG_LINUX 90 #define DPRINTF(a) uprintf a 91 #else 92 #define DPRINTF(a) 93 #endif 94 95 extern const int native_to_linux_signo[]; 96 extern const int linux_to_native_signo[]; 97 98 /* 99 * Convert between Linux and BSD signal sets. 100 */ 101 #if LINUX__NSIG_WORDS > 1 102 void 103 linux_old_extra_to_native_sigset(sigset_t *bss, const linux_old_sigset_t *lss, const unsigned long *extra) 104 { 105 linux_sigset_t lsnew; 106 107 /* convert old sigset to new sigset */ 108 linux_sigemptyset(&lsnew); 109 lsnew.sig[0] = *lss; 110 if (extra) 111 memcpy(&lsnew.sig[1], extra, 112 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 113 114 linux_to_native_sigset(bss, &lsnew); 115 } 116 117 void 118 native_to_linux_old_extra_sigset(linux_old_sigset_t *lss, unsigned long *extra, const sigset_t *bss) 119 { 120 linux_sigset_t lsnew; 121 122 native_to_linux_sigset(&lsnew, bss); 123 124 /* convert new sigset to old sigset */ 125 *lss = lsnew.sig[0]; 126 if (extra) 127 memcpy(extra, &lsnew.sig[1], 128 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 129 } 130 #endif /* LINUX__NSIG_WORDS > 1 */ 131 132 void 133 linux_to_native_sigset(sigset_t *bss, const linux_sigset_t *lss) 134 { 135 int i, newsig; 136 137 sigemptyset(bss); 138 for (i = 1; i < LINUX__NSIG; i++) { 139 if (linux_sigismember(lss, i)) { 140 newsig = linux_to_native_signo[i]; 141 if (newsig) 142 sigaddset(bss, newsig); 143 } 144 } 145 } 146 147 void 148 native_to_linux_sigset(linux_sigset_t *lss, const sigset_t *bss) 149 { 150 int i, newsig; 151 152 linux_sigemptyset(lss); 153 for (i = 1; i < NSIG; i++) { 154 if (sigismember(bss, i)) { 155 newsig = native_to_linux_signo[i]; 156 if (newsig) 157 linux_sigaddset(lss, newsig); 158 } 159 } 160 } 161 162 void 163 native_to_linux_siginfo(linux_siginfo_t *lsi, const struct _ksiginfo *ksi) 164 { 165 memset(lsi, 0, sizeof(*lsi)); 166 167 lsi->lsi_signo = native_to_linux_signo[ksi->_signo]; 168 lsi->lsi_errno = native_to_linux_errno[ksi->_errno]; 169 lsi->lsi_code = native_to_linux_si_code(ksi->_code); 170 171 switch (ksi->_code) { 172 case SI_NOINFO: 173 break; 174 175 case SI_USER: 176 lsi->lsi_pid = ksi->_reason._rt._pid; 177 lsi->lsi_uid = ksi->_reason._rt._uid; 178 if (lsi->lsi_signo == LINUX_SIGALRM || 179 lsi->lsi_signo >= LINUX_SIGRTMIN) 180 lsi->lsi_value.sival_ptr = 181 ksi->_reason._rt._value.sival_ptr; 182 break; 183 184 case SI_TIMER: 185 case SI_QUEUE: 186 lsi->lsi_uid = ksi->_reason._rt._uid; 187 lsi->lsi_uid = ksi->_reason._rt._uid; 188 lsi->lsi_value.sival_ptr = ksi->_reason._rt._value.sival_ptr; 189 break; 190 191 case SI_ASYNCIO: 192 case SI_MESGQ: 193 lsi->lsi_value.sival_ptr = ksi->_reason._rt._value.sival_ptr; 194 break; 195 196 default: 197 switch (ksi->_signo) { 198 case SIGCHLD: 199 lsi->lsi_uid = ksi->_reason._child._uid; 200 lsi->lsi_pid = ksi->_reason._child._pid; 201 lsi->lsi_status = native_to_linux_si_status( 202 ksi->_code, ksi->_reason._child._status); 203 lsi->lsi_utime = ksi->_reason._child._utime; 204 lsi->lsi_stime = ksi->_reason._child._stime; 205 break; 206 207 case SIGILL: 208 case SIGFPE: 209 case SIGSEGV: 210 case SIGBUS: 211 case SIGTRAP: 212 lsi->lsi_addr = ksi->_reason._fault._addr; 213 break; 214 215 case SIGIO: 216 lsi->lsi_fd = ksi->_reason._poll._fd; 217 lsi->lsi_band = ksi->_reason._poll._band; 218 break; 219 default: 220 break; 221 } 222 } 223 } 224 225 unsigned int 226 native_to_linux_sigflags(const int bsf) 227 { 228 unsigned int lsf = 0; 229 if ((bsf & SA_NOCLDSTOP) != 0) 230 lsf |= LINUX_SA_NOCLDSTOP; 231 if ((bsf & SA_NOCLDWAIT) != 0) 232 lsf |= LINUX_SA_NOCLDWAIT; 233 if ((bsf & SA_ONSTACK) != 0) 234 lsf |= LINUX_SA_ONSTACK; 235 if ((bsf & SA_RESTART) != 0) 236 lsf |= LINUX_SA_RESTART; 237 if ((bsf & SA_NODEFER) != 0) 238 lsf |= LINUX_SA_NOMASK; 239 if ((bsf & SA_RESETHAND) != 0) 240 lsf |= LINUX_SA_ONESHOT; 241 if ((bsf & SA_SIGINFO) != 0) 242 lsf |= LINUX_SA_SIGINFO; 243 return lsf; 244 } 245 246 int 247 linux_to_native_sigflags(const unsigned long lsf) 248 { 249 int bsf = 0; 250 if ((lsf & LINUX_SA_NOCLDSTOP) != 0) 251 bsf |= SA_NOCLDSTOP; 252 if ((lsf & LINUX_SA_NOCLDWAIT) != 0) 253 bsf |= SA_NOCLDWAIT; 254 if ((lsf & LINUX_SA_ONSTACK) != 0) 255 bsf |= SA_ONSTACK; 256 if ((lsf & LINUX_SA_RESTART) != 0) 257 bsf |= SA_RESTART; 258 if ((lsf & LINUX_SA_ONESHOT) != 0) 259 bsf |= SA_RESETHAND; 260 if ((lsf & LINUX_SA_NOMASK) != 0) 261 bsf |= SA_NODEFER; 262 if ((lsf & LINUX_SA_SIGINFO) != 0) 263 bsf |= SA_SIGINFO; 264 if ((lsf & ~LINUX_SA_ALLBITS) != 0) { 265 DPRINTF(("linux_old_to_native_sigflags: " 266 "%lx extra bits ignored\n", lsf)); 267 } 268 return bsf; 269 } 270 271 #if !defined(__aarch64__) 272 /* 273 * Convert between Linux and BSD sigaction structures. 274 */ 275 void 276 linux_old_to_native_sigaction(struct sigaction *bsa, const struct linux_old_sigaction *lsa) 277 { 278 279 memset(bsa, 0, sizeof(*bsa)); 280 bsa->sa_handler = lsa->linux_sa_handler; 281 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 282 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 283 } 284 285 void 286 native_to_linux_old_sigaction(struct linux_old_sigaction *lsa, const struct sigaction *bsa) 287 { 288 289 memset(lsa, 0, sizeof(*lsa)); 290 lsa->linux_sa_handler = bsa->sa_handler; 291 native_to_linux_old_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 292 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 293 #ifndef __alpha__ 294 lsa->linux_sa_restorer = NULL; 295 #endif 296 } 297 #endif 298 299 /* ...and the new sigaction conversion funcs. */ 300 void 301 linux_to_native_sigaction(struct sigaction *bsa, const struct linux_sigaction *lsa) 302 { 303 304 memset(bsa, 0, sizeof(*bsa)); 305 bsa->sa_handler = lsa->linux_sa_handler; 306 linux_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 307 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 308 } 309 310 void 311 native_to_linux_sigaction(struct linux_sigaction *lsa, const struct sigaction *bsa) 312 { 313 314 memset(lsa, 0, sizeof(*lsa)); 315 lsa->linux_sa_handler = bsa->sa_handler; 316 native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 317 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 318 #ifndef __alpha__ 319 lsa->linux_sa_restorer = NULL; 320 #endif 321 } 322 323 /* ----------------------------------------------------------------------- */ 324 325 /* 326 * The Linux sigaction() system call. Do the usual conversions, 327 * and just call sigaction(). Some flags and values are silently 328 * ignored (see above). 329 */ 330 int 331 linux_sys_rt_sigaction(struct lwp *l, const struct linux_sys_rt_sigaction_args *uap, register_t *retval) 332 { 333 /* { 334 syscallarg(int) signum; 335 syscallarg(const struct linux_sigaction *) nsa; 336 syscallarg(struct linux_sigaction *) osa; 337 syscallarg(size_t) sigsetsize; 338 } */ 339 struct linux_sigaction nlsa, olsa; 340 struct sigaction nbsa, obsa; 341 int error, sig; 342 void *tramp = NULL; 343 int vers = 0; 344 #ifdef LINUX_SA_RESTORER 345 struct sigacts *ps = l->l_proc->p_sigacts; 346 #endif 347 348 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 349 return EINVAL; 350 351 if (SCARG(uap, nsa)) { 352 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 353 if (error) 354 return error; 355 linux_to_native_sigaction(&nbsa, &nlsa); 356 } 357 358 sig = SCARG(uap, signum); 359 /* 360 * XXX: Linux has 33 realtime signals, the go binary wants to 361 * reset all of them; nothing else uses the last RT signal, so for 362 * now ignore it. 363 */ 364 if (sig == LINUX__NSIG) { 365 uprintf("%s: setting signal %d ignored\n", __func__, sig); 366 sig--; /* back to 63 which is ignored */ 367 } 368 if (sig < 0 || sig >= LINUX__NSIG) 369 return EINVAL; 370 if (sig > 0 && !linux_to_native_signo[sig]) { 371 /* Pretend that we did something useful for unknown signals. */ 372 obsa.sa_handler = SIG_IGN; 373 sigemptyset(&obsa.sa_mask); 374 obsa.sa_flags = 0; 375 } else { 376 #ifdef LINUX_SA_RESTORER 377 if (SCARG(uap, nsa) && 378 (nlsa.linux_sa_flags & LINUX_SA_RESTORER) && 379 (tramp = nlsa.linux_sa_restorer) != NULL) 380 vers = 2; 381 #endif 382 383 error = sigaction1(l, linux_to_native_signo[sig], 384 SCARG(uap, nsa) ? &nbsa : NULL, 385 SCARG(uap, osa) ? &obsa : NULL, 386 tramp, vers); 387 if (error) 388 return error; 389 } 390 if (SCARG(uap, osa)) { 391 native_to_linux_sigaction(&olsa, &obsa); 392 393 #ifdef LINUX_SA_RESTORER 394 if (ps->sa_sigdesc[sig].sd_vers != __SIGTRAMP_SIGCODE_VERSION) { 395 olsa.linux_sa_restorer = ps->sa_sigdesc[sig].sd_tramp; 396 olsa.linux_sa_flags |= LINUX_SA_RESTORER; 397 } 398 #endif 399 400 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 401 if (error) 402 return error; 403 } 404 return 0; 405 } 406 407 #if !defined(__aarch64__) 408 int 409 linux_sigprocmask1(struct lwp *l, int how, const linux_old_sigset_t *set, linux_old_sigset_t *oset) 410 { 411 struct proc *p = l->l_proc; 412 linux_old_sigset_t nlss, olss; 413 sigset_t nbss, obss; 414 int error; 415 416 switch (how) { 417 case LINUX_SIG_BLOCK: 418 how = SIG_BLOCK; 419 break; 420 case LINUX_SIG_UNBLOCK: 421 how = SIG_UNBLOCK; 422 break; 423 case LINUX_SIG_SETMASK: 424 how = SIG_SETMASK; 425 break; 426 default: 427 return EINVAL; 428 } 429 430 if (set) { 431 error = copyin(set, &nlss, sizeof(nlss)); 432 if (error) 433 return error; 434 linux_old_to_native_sigset(&nbss, &nlss); 435 } 436 mutex_enter(p->p_lock); 437 error = sigprocmask1(l, how, 438 set ? &nbss : NULL, oset ? &obss : NULL); 439 mutex_exit(p->p_lock); 440 if (error) 441 return error; 442 if (oset) { 443 native_to_linux_old_sigset(&olss, &obss); 444 error = copyout(&olss, oset, sizeof(olss)); 445 if (error) 446 return error; 447 } 448 return error; 449 } 450 #endif 451 452 int 453 linux_sys_rt_sigprocmask(struct lwp *l, const struct linux_sys_rt_sigprocmask_args *uap, register_t *retval) 454 { 455 /* { 456 syscallarg(int) how; 457 syscallarg(const linux_sigset_t *) set; 458 syscallarg(linux_sigset_t *) oset; 459 syscallarg(size_t) sigsetsize; 460 } */ 461 linux_sigset_t nlss, olss, *oset; 462 const linux_sigset_t *set; 463 struct proc *p = l->l_proc; 464 sigset_t nbss, obss; 465 int error, how; 466 467 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 468 return EINVAL; 469 470 switch (SCARG(uap, how)) { 471 case LINUX_SIG_BLOCK: 472 how = SIG_BLOCK; 473 break; 474 case LINUX_SIG_UNBLOCK: 475 how = SIG_UNBLOCK; 476 break; 477 case LINUX_SIG_SETMASK: 478 how = SIG_SETMASK; 479 break; 480 default: 481 return EINVAL; 482 } 483 484 set = SCARG(uap, set); 485 oset = SCARG(uap, oset); 486 487 if (set) { 488 error = copyin(set, &nlss, sizeof(nlss)); 489 if (error) 490 return error; 491 linux_to_native_sigset(&nbss, &nlss); 492 } 493 mutex_enter(p->p_lock); 494 error = sigprocmask1(l, how, 495 set ? &nbss : NULL, oset ? &obss : NULL); 496 mutex_exit(p->p_lock); 497 if (!error && oset) { 498 native_to_linux_sigset(&olss, &obss); 499 error = copyout(&olss, oset, sizeof(olss)); 500 } 501 return error; 502 } 503 504 int 505 linux_sys_rt_sigpending(struct lwp *l, const struct linux_sys_rt_sigpending_args *uap, register_t *retval) 506 { 507 /* { 508 syscallarg(linux_sigset_t *) set; 509 syscallarg(size_t) sigsetsize; 510 } */ 511 sigset_t bss; 512 linux_sigset_t lss; 513 514 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 515 return EINVAL; 516 517 sigpending1(l, &bss); 518 native_to_linux_sigset(&lss, &bss); 519 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 520 } 521 522 #if !defined(__aarch64__) && !defined(__amd64__) 523 int 524 linux_sys_sigpending(struct lwp *l, const struct linux_sys_sigpending_args *uap, register_t *retval) 525 { 526 /* { 527 syscallarg(linux_old_sigset_t *) mask; 528 } */ 529 sigset_t bss; 530 linux_old_sigset_t lss; 531 532 sigpending1(l, &bss); 533 native_to_linux_old_sigset(&lss, &bss); 534 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 535 } 536 537 int 538 linux_sys_sigsuspend(struct lwp *l, const struct linux_sys_sigsuspend_args *uap, register_t *retval) 539 { 540 /* { 541 syscallarg(void *) restart; 542 syscallarg(int) oldmask; 543 syscallarg(int) mask; 544 } */ 545 linux_old_sigset_t lss; 546 sigset_t bss; 547 548 lss = SCARG(uap, mask); 549 linux_old_to_native_sigset(&bss, &lss); 550 return sigsuspend1(l, &bss); 551 } 552 #endif /* !__aarch64__ && !__amd64__ */ 553 554 int 555 linux_sys_rt_sigsuspend(struct lwp *l, const struct linux_sys_rt_sigsuspend_args *uap, register_t *retval) 556 { 557 /* { 558 syscallarg(linux_sigset_t *) unewset; 559 syscallarg(size_t) sigsetsize; 560 } */ 561 linux_sigset_t lss; 562 sigset_t bss; 563 int error; 564 565 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 566 return EINVAL; 567 568 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 569 if (error) 570 return error; 571 572 linux_to_native_sigset(&bss, &lss); 573 574 return sigsuspend1(l, &bss); 575 } 576 577 static int 578 fetchss(const void *u, void *s, size_t len) 579 { 580 int error; 581 linux_sigset_t lss; 582 583 if ((error = copyin(u, &lss, sizeof(lss))) != 0) 584 return error; 585 586 linux_to_native_sigset(s, &lss); 587 return 0; 588 } 589 590 static int 591 fetchts(const void *u, void *s, size_t len) 592 { 593 int error; 594 struct linux_timespec lts; 595 596 if ((error = copyin(u, <s, sizeof(lts))) != 0) 597 return error; 598 599 linux_to_native_timespec(s, <s); 600 return 0; 601 } 602 603 static int 604 fakestorets(const void *u, void *s, size_t len) 605 { 606 /* Do nothing, sigtimedwait does not alter timeout like ours */ 607 return 0; 608 } 609 610 static int 611 storeinfo(const void *s, void *u, size_t len) 612 { 613 struct linux_siginfo lsi; 614 615 native_to_linux_siginfo(&lsi, &((const siginfo_t *)s)->_info); 616 return copyout(&lsi, u, sizeof(lsi)); 617 } 618 619 int 620 linux_sys_rt_sigtimedwait(struct lwp *l, 621 const struct linux_sys_rt_sigtimedwait_args *uap, register_t *retval) 622 { 623 /* { 624 syscallarg(const linux_sigset_t *) set; 625 syscallarg(linux_siginfo_t *) info); 626 syscallarg(const struct linux_timespec *) timeout; 627 } */ 628 629 return sigtimedwait1(l, (const struct sys_____sigtimedwait50_args *)uap, 630 retval, fetchss, storeinfo, fetchts, fakestorets); 631 } 632 633 #if !defined(__aarch64__) 634 /* 635 * Once more: only a signal conversion is needed. 636 * Note: also used as sys_rt_queueinfo. The info field is ignored. 637 */ 638 int 639 linux_sys_rt_queueinfo(struct lwp *l, const struct linux_sys_rt_queueinfo_args *uap, register_t *retval) 640 { 641 /* 642 syscallarg(int) pid; 643 syscallarg(int) signum; 644 syscallarg(linix_siginfo_t *) uinfo; 645 */ 646 int error; 647 linux_siginfo_t info; 648 649 int pid = SCARG(uap, pid); 650 651 if (pid <= 0) { 652 error = ESRCH; 653 return error; 654 } 655 656 error = copyin(SCARG(uap, uinfo), &info, sizeof(info)); 657 if (error) 658 return error; 659 if (info.lsi_code >= 0) 660 return EPERM; 661 662 /* XXX To really implement this we need to */ 663 /* XXX keep a list of queued signals somewhere. */ 664 return linux_sys_kill(l, (const void *)uap, retval); 665 } 666 #endif 667 668 int 669 linux_sys_kill(struct lwp *l, const struct linux_sys_kill_args *uap, register_t *retval) 670 { 671 /* { 672 syscallarg(int) pid; 673 syscallarg(int) signum; 674 } */ 675 676 struct sys_kill_args ka; 677 int sig; 678 679 memset(&ka, 0, sizeof(ka)); 680 SCARG(&ka, pid) = SCARG(uap, pid); 681 sig = SCARG(uap, signum); 682 if (sig < 0 || sig >= LINUX__NSIG) 683 return EINVAL; 684 SCARG(&ka, signum) = linux_to_native_signo[sig]; 685 return sys_kill(l, &ka, retval); 686 } 687 688 #ifdef LINUX_SS_ONSTACK 689 static void linux_to_native_sigaltstack(stack_t *, 690 const struct linux_sigaltstack *); 691 692 static void 693 linux_to_native_sigaltstack(stack_t *bss, const struct linux_sigaltstack *lss) 694 { 695 bss->ss_sp = lss->ss_sp; 696 bss->ss_size = lss->ss_size; 697 if (lss->ss_flags & LINUX_SS_ONSTACK) 698 bss->ss_flags = SS_ONSTACK; 699 else if (lss->ss_flags & LINUX_SS_DISABLE) 700 bss->ss_flags = SS_DISABLE; 701 else 702 bss->ss_flags = 0; 703 } 704 705 void 706 native_to_linux_sigaltstack(struct linux_sigaltstack *lss, const stack_t *bss) 707 { 708 memset(lss, 0, sizeof(*lss)); 709 lss->ss_sp = bss->ss_sp; 710 lss->ss_size = bss->ss_size; 711 if (bss->ss_flags & SS_ONSTACK) 712 lss->ss_flags = LINUX_SS_ONSTACK; 713 else if (bss->ss_flags & SS_DISABLE) 714 lss->ss_flags = LINUX_SS_DISABLE; 715 else 716 lss->ss_flags = 0; 717 } 718 719 int 720 linux_sys_sigaltstack(struct lwp *l, const struct linux_sys_sigaltstack_args *uap, register_t *retval) 721 { 722 /* { 723 syscallarg(const struct linux_sigaltstack *) ss; 724 syscallarg(struct linux_sigaltstack *) oss; 725 } */ 726 struct linux_sigaltstack ss; 727 stack_t nss; 728 struct proc *p = l->l_proc; 729 int error = 0; 730 731 if (SCARG(uap, oss)) { 732 native_to_linux_sigaltstack(&ss, &l->l_sigstk); 733 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0) 734 return error; 735 } 736 737 if (SCARG(uap, ss) != NULL) { 738 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0) 739 return error; 740 linux_to_native_sigaltstack(&nss, &ss); 741 742 mutex_enter(p->p_lock); 743 744 if (nss.ss_flags & ~SS_ALLBITS) 745 error = EINVAL; 746 else if (nss.ss_flags & SS_DISABLE) { 747 if (l->l_sigstk.ss_flags & SS_ONSTACK) 748 error = EINVAL; 749 } else if (nss.ss_size < LINUX_MINSIGSTKSZ) 750 error = ENOMEM; 751 752 if (error == 0) 753 l->l_sigstk = nss; 754 755 mutex_exit(p->p_lock); 756 } 757 758 return error; 759 } 760 #endif /* LINUX_SS_ONSTACK */ 761 762 static int 763 linux_do_tkill(struct lwp *l, int tgid, int tid, int signum) 764 { 765 struct proc *p; 766 struct lwp *t; 767 ksiginfo_t ksi; 768 int error; 769 770 if (signum < 0 || signum >= LINUX__NSIG) 771 return EINVAL; 772 signum = linux_to_native_signo[signum]; 773 774 KSI_INIT(&ksi); 775 ksi.ksi_signo = signum; 776 ksi.ksi_code = SI_LWP; 777 ksi.ksi_pid = l->l_proc->p_pid; 778 ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); 779 ksi.ksi_lid = tid; 780 781 mutex_enter(&proc_lock); 782 if (tgid != -1) 783 p = proc_find(tgid); 784 else 785 p = proc_find_lwpid(tid); 786 if (p == NULL) { 787 mutex_exit(&proc_lock); 788 return ESRCH; 789 } 790 mutex_enter(p->p_lock); 791 error = kauth_authorize_process(l->l_cred, 792 KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum), NULL, NULL); 793 if ((t = lwp_find(p, ksi.ksi_lid)) == NULL) 794 error = ESRCH; 795 else if (signum != 0) 796 kpsignal2(p, &ksi); 797 mutex_exit(p->p_lock); 798 mutex_exit(&proc_lock); 799 800 return error; 801 } 802 803 int 804 linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, register_t *retval) 805 { 806 /* { 807 syscallarg(int) tid; 808 syscallarg(int) sig; 809 } */ 810 811 if (SCARG(uap, tid) <= 0) 812 return EINVAL; 813 814 return linux_do_tkill(l, -1, SCARG(uap, tid), SCARG(uap, sig)); 815 } 816 817 int 818 linux_sys_tgkill(struct lwp *l, const struct linux_sys_tgkill_args *uap, register_t *retval) 819 { 820 /* { 821 syscallarg(int) tgid; 822 syscallarg(int) tid; 823 syscallarg(int) sig; 824 } */ 825 826 if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) < -1) 827 return EINVAL; 828 829 return linux_do_tkill(l, SCARG(uap, tgid), SCARG(uap, tid), SCARG(uap, sig)); 830 } 831 832 int 833 native_to_linux_si_code(int code) 834 { 835 int si_codes[] = { 836 LINUX_SI_USER, LINUX_SI_QUEUE, LINUX_SI_TIMER, LINUX_SI_ASYNCIO, 837 LINUX_SI_MESGQ, LINUX_SI_TKILL /* SI_LWP */ 838 }; 839 840 if (code <= 0 && -code < __arraycount(si_codes)) 841 return si_codes[-code]; 842 843 return code; 844 } 845 846 int 847 native_to_linux_si_status(int code, int status) 848 { 849 int sts; 850 851 switch (code) { 852 case CLD_CONTINUED: 853 sts = LINUX_SIGCONT; 854 break; 855 case CLD_EXITED: 856 sts = status; 857 break; 858 case CLD_STOPPED: 859 case CLD_TRAPPED: 860 case CLD_DUMPED: 861 case CLD_KILLED: 862 default: 863 sts = native_to_linux_signo[WTERMSIG(status)]; 864 break; 865 } 866 867 return sts; 868 } 869 870 int 871 linux_to_native_sigevent(struct sigevent *nsep, 872 const struct linux_sigevent *lsep) 873 { 874 memset(nsep, 0, sizeof(*nsep)); 875 876 switch (lsep->sigev_notify) { 877 case LINUX_SIGEV_SIGNAL: 878 nsep->sigev_notify = SIGEV_SIGNAL; 879 break; 880 881 case LINUX_SIGEV_NONE: 882 nsep->sigev_notify = SIGEV_NONE; 883 break; 884 885 case LINUX_SIGEV_THREAD: 886 case LINUX_SIGEV_THREAD_ID: 887 default: 888 return ENOTSUP; 889 } 890 891 nsep->sigev_value = lsep->sigev_value; 892 if (lsep->sigev_signo < 0 || lsep->sigev_signo >= LINUX__NSIG) { 893 return EINVAL; 894 } 895 nsep->sigev_signo = linux_to_native_signo[lsep->sigev_signo]; 896 897 return 0; 898 } 899 900 int 901 linux_sigevent_copyin(const void *src, void *dst, size_t size) 902 { 903 struct linux_sigevent lse; 904 struct sigevent *sep = dst; 905 int error; 906 907 KASSERT(size == sizeof(*sep)); 908 909 error = copyin(src, &lse, sizeof(lse)); 910 if (error) { 911 return error; 912 } 913 914 return linux_to_native_sigevent(sep, &lse); 915 } 916