1 /* $NetBSD: linux_signal.c,v 1.71 2010/07/07 01:30:35 chs 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.71 2010/07/07 01:30:35 chs 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/malloc.h> 66 #include <sys/wait.h> 67 68 #include <sys/syscallargs.h> 69 70 #include <compat/linux/common/linux_types.h> 71 #include <compat/linux/common/linux_signal.h> 72 #include <compat/linux/common/linux_emuldata.h> 73 #include <compat/linux/common/linux_siginfo.h> 74 #include <compat/linux/common/linux_sigevent.h> 75 #include <compat/linux/common/linux_util.h> 76 #include <compat/linux/common/linux_ipc.h> 77 #include <compat/linux/common/linux_sem.h> 78 79 #include <compat/linux/linux_syscallargs.h> 80 81 /* Locally used defines (in bsd<->linux conversion functions): */ 82 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s))) 83 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 84 & (1L << ((n) - 1) % LINUX__NSIG_BPW)) 85 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 86 |= (1L << ((n) - 1) % LINUX__NSIG_BPW)) 87 88 #ifdef DEBUG_LINUX 89 #define DPRINTF(a) uprintf a 90 #else 91 #define DPRINTF(a) 92 #endif 93 94 extern const int native_to_linux_signo[]; 95 extern const int linux_to_native_signo[]; 96 97 /* 98 * Convert between Linux and BSD signal sets. 99 */ 100 #if LINUX__NSIG_WORDS > 1 101 void 102 linux_old_extra_to_native_sigset(sigset_t *bss, const linux_old_sigset_t *lss, const unsigned long *extra) 103 { 104 linux_sigset_t lsnew; 105 106 /* convert old sigset to new sigset */ 107 linux_sigemptyset(&lsnew); 108 lsnew.sig[0] = *lss; 109 if (extra) 110 memcpy(&lsnew.sig[1], extra, 111 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 112 113 linux_to_native_sigset(bss, &lsnew); 114 } 115 116 void 117 native_to_linux_old_extra_sigset(linux_old_sigset_t *lss, unsigned long *extra, const sigset_t *bss) 118 { 119 linux_sigset_t lsnew; 120 121 native_to_linux_sigset(&lsnew, bss); 122 123 /* convert new sigset to old sigset */ 124 *lss = lsnew.sig[0]; 125 if (extra) 126 memcpy(extra, &lsnew.sig[1], 127 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 128 } 129 #endif /* LINUX__NSIG_WORDS > 1 */ 130 131 void 132 linux_to_native_sigset(sigset_t *bss, const linux_sigset_t *lss) 133 { 134 int i, newsig; 135 136 sigemptyset(bss); 137 for (i = 1; i < LINUX__NSIG; i++) { 138 if (linux_sigismember(lss, i)) { 139 newsig = linux_to_native_signo[i]; 140 if (newsig) 141 sigaddset(bss, newsig); 142 } 143 } 144 } 145 146 void 147 native_to_linux_sigset(linux_sigset_t *lss, const sigset_t *bss) 148 { 149 int i, newsig; 150 151 linux_sigemptyset(lss); 152 for (i = 1; i < NSIG; i++) { 153 if (sigismember(bss, i)) { 154 newsig = native_to_linux_signo[i]; 155 if (newsig) 156 linux_sigaddset(lss, newsig); 157 } 158 } 159 } 160 161 unsigned int 162 native_to_linux_sigflags(const int bsf) 163 { 164 unsigned int lsf = 0; 165 if ((bsf & SA_NOCLDSTOP) != 0) 166 lsf |= LINUX_SA_NOCLDSTOP; 167 if ((bsf & SA_NOCLDWAIT) != 0) 168 lsf |= LINUX_SA_NOCLDWAIT; 169 if ((bsf & SA_ONSTACK) != 0) 170 lsf |= LINUX_SA_ONSTACK; 171 if ((bsf & SA_RESTART) != 0) 172 lsf |= LINUX_SA_RESTART; 173 if ((bsf & SA_NODEFER) != 0) 174 lsf |= LINUX_SA_NOMASK; 175 if ((bsf & SA_RESETHAND) != 0) 176 lsf |= LINUX_SA_ONESHOT; 177 if ((bsf & SA_SIGINFO) != 0) 178 lsf |= LINUX_SA_SIGINFO; 179 return lsf; 180 } 181 182 int 183 linux_to_native_sigflags(const unsigned long lsf) 184 { 185 int bsf = 0; 186 if ((lsf & LINUX_SA_NOCLDSTOP) != 0) 187 bsf |= SA_NOCLDSTOP; 188 if ((lsf & LINUX_SA_NOCLDWAIT) != 0) 189 bsf |= SA_NOCLDWAIT; 190 if ((lsf & LINUX_SA_ONSTACK) != 0) 191 bsf |= SA_ONSTACK; 192 if ((lsf & LINUX_SA_RESTART) != 0) 193 bsf |= SA_RESTART; 194 if ((lsf & LINUX_SA_ONESHOT) != 0) 195 bsf |= SA_RESETHAND; 196 if ((lsf & LINUX_SA_NOMASK) != 0) 197 bsf |= SA_NODEFER; 198 if ((lsf & LINUX_SA_SIGINFO) != 0) 199 bsf |= SA_SIGINFO; 200 if ((lsf & ~LINUX_SA_ALLBITS) != 0) { 201 DPRINTF(("linux_old_to_native_sigflags: " 202 "%lx extra bits ignored\n", lsf)); 203 } 204 return bsf; 205 } 206 207 /* 208 * Convert between Linux and BSD sigaction structures. 209 */ 210 void 211 linux_old_to_native_sigaction(struct sigaction *bsa, const struct linux_old_sigaction *lsa) 212 { 213 bsa->sa_handler = lsa->linux_sa_handler; 214 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 215 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 216 } 217 218 void 219 native_to_linux_old_sigaction(struct linux_old_sigaction *lsa, const struct sigaction *bsa) 220 { 221 lsa->linux_sa_handler = bsa->sa_handler; 222 native_to_linux_old_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 223 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 224 #ifndef __alpha__ 225 lsa->linux_sa_restorer = NULL; 226 #endif 227 } 228 229 /* ...and the new sigaction conversion funcs. */ 230 void 231 linux_to_native_sigaction(struct sigaction *bsa, const struct linux_sigaction *lsa) 232 { 233 bsa->sa_handler = lsa->linux_sa_handler; 234 linux_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 235 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 236 } 237 238 void 239 native_to_linux_sigaction(struct linux_sigaction *lsa, const struct sigaction *bsa) 240 { 241 lsa->linux_sa_handler = bsa->sa_handler; 242 native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 243 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 244 #ifndef __alpha__ 245 lsa->linux_sa_restorer = NULL; 246 #endif 247 } 248 249 /* ----------------------------------------------------------------------- */ 250 251 /* 252 * The Linux sigaction() system call. Do the usual conversions, 253 * and just call sigaction(). Some flags and values are silently 254 * ignored (see above). 255 */ 256 int 257 linux_sys_rt_sigaction(struct lwp *l, const struct linux_sys_rt_sigaction_args *uap, register_t *retval) 258 { 259 /* { 260 syscallarg(int) signum; 261 syscallarg(const struct linux_sigaction *) nsa; 262 syscallarg(struct linux_sigaction *) osa; 263 syscallarg(size_t) sigsetsize; 264 } */ 265 struct linux_sigaction nlsa, olsa; 266 struct sigaction nbsa, obsa; 267 int error, sig; 268 void *tramp = NULL; 269 int vers = 0; 270 #if defined __amd64__ 271 struct sigacts *ps = l->l_proc->p_sigacts; 272 #endif 273 274 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 275 return (EINVAL); 276 277 if (SCARG(uap, nsa)) { 278 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 279 if (error) 280 return (error); 281 linux_to_native_sigaction(&nbsa, &nlsa); 282 } 283 284 sig = SCARG(uap, signum); 285 if (sig < 0 || sig >= LINUX__NSIG) 286 return (EINVAL); 287 if (sig > 0 && !linux_to_native_signo[sig]) { 288 /* Pretend that we did something useful for unknown signals. */ 289 obsa.sa_handler = SIG_IGN; 290 sigemptyset(&obsa.sa_mask); 291 obsa.sa_flags = 0; 292 } else { 293 #if defined __amd64__ 294 if (nlsa.linux_sa_flags & LINUX_SA_RESTORER) { 295 if ((tramp = nlsa.linux_sa_restorer) != NULL) 296 vers = 2; /* XXX arch dependant */ 297 } 298 #endif 299 300 error = sigaction1(l, linux_to_native_signo[sig], 301 SCARG(uap, nsa) ? &nbsa : NULL, 302 SCARG(uap, osa) ? &obsa : NULL, 303 tramp, vers); 304 if (error) 305 return (error); 306 } 307 if (SCARG(uap, osa)) { 308 native_to_linux_sigaction(&olsa, &obsa); 309 310 #if defined __amd64__ 311 if (ps->sa_sigdesc[sig].sd_vers != 0) { 312 olsa.linux_sa_restorer = ps->sa_sigdesc[sig].sd_tramp; 313 olsa.linux_sa_flags |= LINUX_SA_RESTORER; 314 } 315 #endif 316 317 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 318 if (error) 319 return (error); 320 } 321 return (0); 322 } 323 324 int 325 linux_sigprocmask1(struct lwp *l, int how, const linux_old_sigset_t *set, linux_old_sigset_t *oset) 326 { 327 struct proc *p = l->l_proc; 328 linux_old_sigset_t nlss, olss; 329 sigset_t nbss, obss; 330 int error; 331 332 switch (how) { 333 case LINUX_SIG_BLOCK: 334 how = SIG_BLOCK; 335 break; 336 case LINUX_SIG_UNBLOCK: 337 how = SIG_UNBLOCK; 338 break; 339 case LINUX_SIG_SETMASK: 340 how = SIG_SETMASK; 341 break; 342 default: 343 return (EINVAL); 344 } 345 346 if (set) { 347 error = copyin(set, &nlss, sizeof(nlss)); 348 if (error) 349 return (error); 350 linux_old_to_native_sigset(&nbss, &nlss); 351 } 352 mutex_enter(p->p_lock); 353 error = sigprocmask1(l, how, 354 set ? &nbss : NULL, oset ? &obss : NULL); 355 mutex_exit(p->p_lock); 356 if (error) 357 return (error); 358 if (oset) { 359 native_to_linux_old_sigset(&olss, &obss); 360 error = copyout(&olss, oset, sizeof(olss)); 361 if (error) 362 return (error); 363 } 364 return (error); 365 } 366 367 int 368 linux_sys_rt_sigprocmask(struct lwp *l, const struct linux_sys_rt_sigprocmask_args *uap, register_t *retval) 369 { 370 /* { 371 syscallarg(int) how; 372 syscallarg(const linux_sigset_t *) set; 373 syscallarg(linux_sigset_t *) oset; 374 syscallarg(size_t) sigsetsize; 375 } */ 376 linux_sigset_t nlss, olss, *oset; 377 const linux_sigset_t *set; 378 struct proc *p = l->l_proc; 379 sigset_t nbss, obss; 380 int error, how; 381 382 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 383 return (EINVAL); 384 385 switch (SCARG(uap, how)) { 386 case LINUX_SIG_BLOCK: 387 how = SIG_BLOCK; 388 break; 389 case LINUX_SIG_UNBLOCK: 390 how = SIG_UNBLOCK; 391 break; 392 case LINUX_SIG_SETMASK: 393 how = SIG_SETMASK; 394 break; 395 default: 396 return (EINVAL); 397 } 398 399 set = SCARG(uap, set); 400 oset = SCARG(uap, oset); 401 402 if (set) { 403 error = copyin(set, &nlss, sizeof(nlss)); 404 if (error) 405 return (error); 406 linux_to_native_sigset(&nbss, &nlss); 407 } 408 mutex_enter(p->p_lock); 409 error = sigprocmask1(l, how, 410 set ? &nbss : NULL, oset ? &obss : NULL); 411 mutex_exit(p->p_lock); 412 if (!error && oset) { 413 native_to_linux_sigset(&olss, &obss); 414 error = copyout(&olss, oset, sizeof(olss)); 415 } 416 return (error); 417 } 418 419 int 420 linux_sys_rt_sigpending(struct lwp *l, const struct linux_sys_rt_sigpending_args *uap, register_t *retval) 421 { 422 /* { 423 syscallarg(linux_sigset_t *) set; 424 syscallarg(size_t) sigsetsize; 425 } */ 426 sigset_t bss; 427 linux_sigset_t lss; 428 429 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 430 return (EINVAL); 431 432 sigpending1(l, &bss); 433 native_to_linux_sigset(&lss, &bss); 434 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 435 } 436 437 #ifndef __amd64__ 438 int 439 linux_sys_sigpending(struct lwp *l, const struct linux_sys_sigpending_args *uap, register_t *retval) 440 { 441 /* { 442 syscallarg(linux_old_sigset_t *) mask; 443 } */ 444 sigset_t bss; 445 linux_old_sigset_t lss; 446 447 sigpending1(l, &bss); 448 native_to_linux_old_sigset(&lss, &bss); 449 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 450 } 451 452 int 453 linux_sys_sigsuspend(struct lwp *l, const struct linux_sys_sigsuspend_args *uap, register_t *retval) 454 { 455 /* { 456 syscallarg(void *) restart; 457 syscallarg(int) oldmask; 458 syscallarg(int) mask; 459 } */ 460 linux_old_sigset_t lss; 461 sigset_t bss; 462 463 lss = SCARG(uap, mask); 464 linux_old_to_native_sigset(&bss, &lss); 465 return (sigsuspend1(l, &bss)); 466 } 467 #endif /* __amd64__ */ 468 469 int 470 linux_sys_rt_sigsuspend(struct lwp *l, const struct linux_sys_rt_sigsuspend_args *uap, register_t *retval) 471 { 472 /* { 473 syscallarg(linux_sigset_t *) unewset; 474 syscallarg(size_t) sigsetsize; 475 } */ 476 linux_sigset_t lss; 477 sigset_t bss; 478 int error; 479 480 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 481 return (EINVAL); 482 483 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 484 if (error) 485 return (error); 486 487 linux_to_native_sigset(&bss, &lss); 488 489 return (sigsuspend1(l, &bss)); 490 } 491 492 /* 493 * Once more: only a signal conversion is needed. 494 * Note: also used as sys_rt_queueinfo. The info field is ignored. 495 */ 496 int 497 linux_sys_rt_queueinfo(struct lwp *l, const struct linux_sys_rt_queueinfo_args *uap, register_t *retval) 498 { 499 /* 500 syscallarg(int) pid; 501 syscallarg(int) signum; 502 syscallarg(linix_siginfo_t *) uinfo; 503 */ 504 int error; 505 linux_siginfo_t info; 506 507 error = copyin(SCARG(uap, uinfo), &info, sizeof(info)); 508 if (error) 509 return error; 510 if (info.lsi_code >= 0) 511 return EPERM; 512 513 /* XXX To really implement this we need to */ 514 /* XXX keep a list of queued signals somewhere. */ 515 return (linux_sys_kill(l, (const void *)uap, retval)); 516 } 517 518 int 519 linux_sys_kill(struct lwp *l, const struct linux_sys_kill_args *uap, register_t *retval) 520 { 521 /* { 522 syscallarg(int) pid; 523 syscallarg(int) signum; 524 } */ 525 526 struct sys_kill_args ka; 527 int sig; 528 529 SCARG(&ka, pid) = SCARG(uap, pid); 530 sig = SCARG(uap, signum); 531 if (sig < 0 || sig >= LINUX__NSIG) 532 return (EINVAL); 533 SCARG(&ka, signum) = linux_to_native_signo[sig]; 534 return sys_kill(l, &ka, retval); 535 } 536 537 #ifdef LINUX_SS_ONSTACK 538 static void linux_to_native_sigaltstack(struct sigaltstack *, 539 const struct linux_sigaltstack *); 540 541 static void 542 linux_to_native_sigaltstack(struct sigaltstack *bss, const struct linux_sigaltstack *lss) 543 { 544 bss->ss_sp = lss->ss_sp; 545 bss->ss_size = lss->ss_size; 546 if (lss->ss_flags & LINUX_SS_ONSTACK) 547 bss->ss_flags = SS_ONSTACK; 548 else if (lss->ss_flags & LINUX_SS_DISABLE) 549 bss->ss_flags = SS_DISABLE; 550 else 551 bss->ss_flags = 0; 552 } 553 554 void 555 native_to_linux_sigaltstack(struct linux_sigaltstack *lss, const struct sigaltstack *bss) 556 { 557 lss->ss_sp = bss->ss_sp; 558 lss->ss_size = bss->ss_size; 559 if (bss->ss_flags & SS_ONSTACK) 560 lss->ss_flags = LINUX_SS_ONSTACK; 561 else if (bss->ss_flags & SS_DISABLE) 562 lss->ss_flags = LINUX_SS_DISABLE; 563 else 564 lss->ss_flags = 0; 565 } 566 567 int 568 linux_sys_sigaltstack(struct lwp *l, const struct linux_sys_sigaltstack_args *uap, register_t *retval) 569 { 570 /* { 571 syscallarg(const struct linux_sigaltstack *) ss; 572 syscallarg(struct linux_sigaltstack *) oss; 573 } */ 574 struct linux_sigaltstack ss; 575 struct sigaltstack nss; 576 struct proc *p = l->l_proc; 577 int error = 0; 578 579 if (SCARG(uap, oss)) { 580 native_to_linux_sigaltstack(&ss, &l->l_sigstk); 581 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0) 582 return error; 583 } 584 585 if (SCARG(uap, ss) != NULL) { 586 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0) 587 return error; 588 linux_to_native_sigaltstack(&nss, &ss); 589 590 mutex_enter(p->p_lock); 591 592 if (nss.ss_flags & ~SS_ALLBITS) 593 error = EINVAL; 594 else if (nss.ss_flags & SS_DISABLE) { 595 if (l->l_sigstk.ss_flags & SS_ONSTACK) 596 error = EINVAL; 597 } else if (nss.ss_size < LINUX_MINSIGSTKSZ) 598 error = ENOMEM; 599 600 if (error == 0) 601 l->l_sigstk = nss; 602 603 mutex_exit(p->p_lock); 604 } 605 606 return error; 607 } 608 #endif /* LINUX_SS_ONSTACK */ 609 610 static int 611 linux_do_tkill(struct lwp *l, int tgid, int tid, int signum) 612 { 613 struct proc *p; 614 struct lwp *t; 615 ksiginfo_t ksi; 616 int error; 617 618 if (signum < 0 || signum >= LINUX__NSIG) 619 return EINVAL; 620 signum = linux_to_native_signo[signum]; 621 622 if (tgid == -1) { 623 tgid = tid; 624 } 625 626 KSI_INIT(&ksi); 627 ksi.ksi_signo = signum; 628 ksi.ksi_code = SI_LWP; 629 ksi.ksi_pid = l->l_proc->p_pid; 630 ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); 631 ksi.ksi_lid = tid; 632 633 mutex_enter(proc_lock); 634 p = proc_find(tgid); 635 if (p == NULL) { 636 mutex_exit(proc_lock); 637 return ESRCH; 638 } 639 mutex_enter(p->p_lock); 640 error = kauth_authorize_process(l->l_cred, 641 KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum), NULL, NULL); 642 if ((t = lwp_find(p, ksi.ksi_lid)) == NULL) 643 error = ESRCH; 644 else if (signum != 0) 645 kpsignal2(p, &ksi); 646 mutex_exit(p->p_lock); 647 mutex_exit(proc_lock); 648 649 return error; 650 } 651 652 int 653 linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, register_t *retval) 654 { 655 /* { 656 syscallarg(int) tid; 657 syscallarg(int) sig; 658 } */ 659 660 if (SCARG(uap, tid) <= 0) 661 return EINVAL; 662 663 return linux_do_tkill(l, -1, SCARG(uap, tid), SCARG(uap, sig)); 664 } 665 666 int 667 linux_sys_tgkill(struct lwp *l, const struct linux_sys_tgkill_args *uap, register_t *retval) 668 { 669 /* { 670 syscallarg(int) tgid; 671 syscallarg(int) tid; 672 syscallarg(int) sig; 673 } */ 674 675 if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) < -1) 676 return EINVAL; 677 678 return linux_do_tkill(l, SCARG(uap, tgid), SCARG(uap, tid), SCARG(uap, sig)); 679 } 680 681 int 682 native_to_linux_si_code(int code) 683 { 684 int si_codes[] = { 685 LINUX_SI_USER, LINUX_SI_QUEUE, LINUX_SI_TIMER, LINUX_SI_ASYNCIO, 686 LINUX_SI_MESGQ, LINUX_SI_TKILL /* SI_LWP */ 687 }; 688 689 if (code <= 0 && -code < __arraycount(si_codes)) 690 return si_codes[-code]; 691 692 return code; 693 } 694 695 int 696 native_to_linux_si_status(int code, int status) 697 { 698 int sts; 699 700 switch (code) { 701 case CLD_CONTINUED: 702 sts = LINUX_SIGCONT; 703 break; 704 case CLD_EXITED: 705 sts = WEXITSTATUS(status); 706 break; 707 case CLD_STOPPED: 708 case CLD_TRAPPED: 709 case CLD_DUMPED: 710 case CLD_KILLED: 711 default: 712 sts = native_to_linux_signo[WTERMSIG(status)]; 713 break; 714 } 715 716 return sts; 717 } 718