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