1 /* $NetBSD: linux_signal.c,v 1.64 2008/10/19 09:44:31 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.64 2008/10/19 09:44:31 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 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_exec.h> /* For emul_linux */ 72 #include <compat/linux/common/linux_machdep.h> /* For LINUX_NPTL */ 73 #include <compat/linux/common/linux_emuldata.h> /* for linux_emuldata */ 74 #include <compat/linux/common/linux_siginfo.h> 75 #include <compat/linux/common/linux_sigevent.h> 76 #include <compat/linux/common/linux_util.h> 77 #include <compat/linux/common/linux_ipc.h> 78 #include <compat/linux/common/linux_sem.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 unsigned int 163 native_to_linux_sigflags(const int bsf) 164 { 165 unsigned int lsf = 0; 166 if ((bsf & SA_NOCLDSTOP) != 0) 167 lsf |= LINUX_SA_NOCLDSTOP; 168 if ((bsf & SA_NOCLDWAIT) != 0) 169 lsf |= LINUX_SA_NOCLDWAIT; 170 if ((bsf & SA_ONSTACK) != 0) 171 lsf |= LINUX_SA_ONSTACK; 172 if ((bsf & SA_RESTART) != 0) 173 lsf |= LINUX_SA_RESTART; 174 if ((bsf & SA_NODEFER) != 0) 175 lsf |= LINUX_SA_NOMASK; 176 if ((bsf & SA_RESETHAND) != 0) 177 lsf |= LINUX_SA_ONESHOT; 178 if ((bsf & SA_SIGINFO) != 0) 179 lsf |= LINUX_SA_SIGINFO; 180 return lsf; 181 } 182 183 int 184 linux_to_native_sigflags(const unsigned long lsf) 185 { 186 int bsf = 0; 187 if ((lsf & LINUX_SA_NOCLDSTOP) != 0) 188 bsf |= SA_NOCLDSTOP; 189 if ((lsf & LINUX_SA_NOCLDWAIT) != 0) 190 bsf |= SA_NOCLDWAIT; 191 if ((lsf & LINUX_SA_ONSTACK) != 0) 192 bsf |= SA_ONSTACK; 193 if ((lsf & LINUX_SA_RESTART) != 0) 194 bsf |= SA_RESTART; 195 if ((lsf & LINUX_SA_ONESHOT) != 0) 196 bsf |= SA_RESETHAND; 197 if ((lsf & LINUX_SA_NOMASK) != 0) 198 bsf |= SA_NODEFER; 199 if ((lsf & LINUX_SA_SIGINFO) != 0) 200 bsf |= SA_SIGINFO; 201 if ((lsf & ~LINUX_SA_ALLBITS) != 0) { 202 DPRINTF(("linux_old_to_native_sigflags: " 203 "%lx extra bits ignored\n", lsf)); 204 } 205 return bsf; 206 } 207 208 /* 209 * Convert between Linux and BSD sigaction structures. 210 */ 211 void 212 linux_old_to_native_sigaction(struct sigaction *bsa, const struct linux_old_sigaction *lsa) 213 { 214 bsa->sa_handler = lsa->linux_sa_handler; 215 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 216 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 217 } 218 219 void 220 native_to_linux_old_sigaction(struct linux_old_sigaction *lsa, const struct sigaction *bsa) 221 { 222 lsa->linux_sa_handler = bsa->sa_handler; 223 native_to_linux_old_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 224 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 225 #ifndef __alpha__ 226 lsa->linux_sa_restorer = NULL; 227 #endif 228 } 229 230 /* ...and the new sigaction conversion funcs. */ 231 void 232 linux_to_native_sigaction(struct sigaction *bsa, const struct linux_sigaction *lsa) 233 { 234 bsa->sa_handler = lsa->linux_sa_handler; 235 linux_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 236 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 237 } 238 239 void 240 native_to_linux_sigaction(struct linux_sigaction *lsa, const struct sigaction *bsa) 241 { 242 lsa->linux_sa_handler = bsa->sa_handler; 243 native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 244 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 245 #ifndef __alpha__ 246 lsa->linux_sa_restorer = NULL; 247 #endif 248 } 249 250 /* ----------------------------------------------------------------------- */ 251 252 /* 253 * The Linux sigaction() system call. Do the usual conversions, 254 * and just call sigaction(). Some flags and values are silently 255 * ignored (see above). 256 */ 257 int 258 linux_sys_rt_sigaction(struct lwp *l, const struct linux_sys_rt_sigaction_args *uap, register_t *retval) 259 { 260 /* { 261 syscallarg(int) signum; 262 syscallarg(const struct linux_sigaction *) nsa; 263 syscallarg(struct linux_sigaction *) osa; 264 syscallarg(size_t) sigsetsize; 265 } */ 266 struct linux_sigaction nlsa, olsa; 267 struct sigaction nbsa, obsa; 268 int error, sig; 269 void *tramp = NULL; 270 int vers = 0; 271 #if defined __amd64__ 272 struct sigacts *ps = l->l_proc->p_sigacts; 273 #endif 274 275 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 276 return (EINVAL); 277 278 if (SCARG(uap, nsa)) { 279 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 280 if (error) 281 return (error); 282 linux_to_native_sigaction(&nbsa, &nlsa); 283 } 284 285 sig = SCARG(uap, signum); 286 if (sig < 0 || sig >= LINUX__NSIG) 287 return (EINVAL); 288 if (sig > 0 && !linux_to_native_signo[sig]) { 289 /* Pretend that we did something useful for unknown signals. */ 290 obsa.sa_handler = SIG_IGN; 291 sigemptyset(&obsa.sa_mask); 292 obsa.sa_flags = 0; 293 } else { 294 #if defined __amd64__ 295 if (nlsa.linux_sa_flags & LINUX_SA_RESTORER) { 296 if ((tramp = nlsa.linux_sa_restorer) != NULL) 297 vers = 2; /* XXX arch dependant */ 298 } 299 #endif 300 301 error = sigaction1(l, linux_to_native_signo[sig], 302 SCARG(uap, nsa) ? &nbsa : NULL, 303 SCARG(uap, osa) ? &obsa : NULL, 304 tramp, vers); 305 if (error) 306 return (error); 307 } 308 if (SCARG(uap, osa)) { 309 native_to_linux_sigaction(&olsa, &obsa); 310 311 #if defined __amd64__ 312 if (ps->sa_sigdesc[sig].sd_vers != 0) { 313 olsa.linux_sa_restorer = ps->sa_sigdesc[sig].sd_tramp; 314 olsa.linux_sa_flags |= LINUX_SA_RESTORER; 315 } 316 #endif 317 318 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 319 if (error) 320 return (error); 321 } 322 return (0); 323 } 324 325 int 326 linux_sigprocmask1(struct lwp *l, int how, const linux_old_sigset_t *set, linux_old_sigset_t *oset) 327 { 328 struct proc *p = l->l_proc; 329 linux_old_sigset_t nlss, olss; 330 sigset_t nbss, obss; 331 int error; 332 333 switch (how) { 334 case LINUX_SIG_BLOCK: 335 how = SIG_BLOCK; 336 break; 337 case LINUX_SIG_UNBLOCK: 338 how = SIG_UNBLOCK; 339 break; 340 case LINUX_SIG_SETMASK: 341 how = SIG_SETMASK; 342 break; 343 default: 344 return (EINVAL); 345 } 346 347 if (set) { 348 error = copyin(set, &nlss, sizeof(nlss)); 349 if (error) 350 return (error); 351 linux_old_to_native_sigset(&nbss, &nlss); 352 } 353 mutex_enter(p->p_lock); 354 error = sigprocmask1(l, how, 355 set ? &nbss : NULL, oset ? &obss : NULL); 356 mutex_exit(p->p_lock); 357 if (error) 358 return (error); 359 if (oset) { 360 native_to_linux_old_sigset(&olss, &obss); 361 error = copyout(&olss, oset, sizeof(olss)); 362 if (error) 363 return (error); 364 } 365 return (error); 366 } 367 368 int 369 linux_sys_rt_sigprocmask(struct lwp *l, const struct linux_sys_rt_sigprocmask_args *uap, register_t *retval) 370 { 371 /* { 372 syscallarg(int) how; 373 syscallarg(const linux_sigset_t *) set; 374 syscallarg(linux_sigset_t *) oset; 375 syscallarg(size_t) sigsetsize; 376 } */ 377 linux_sigset_t nlss, olss, *oset; 378 const linux_sigset_t *set; 379 struct proc *p = l->l_proc; 380 sigset_t nbss, obss; 381 int error, how; 382 383 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 384 return (EINVAL); 385 386 switch (SCARG(uap, how)) { 387 case LINUX_SIG_BLOCK: 388 how = SIG_BLOCK; 389 break; 390 case LINUX_SIG_UNBLOCK: 391 how = SIG_UNBLOCK; 392 break; 393 case LINUX_SIG_SETMASK: 394 how = SIG_SETMASK; 395 break; 396 default: 397 return (EINVAL); 398 } 399 400 set = SCARG(uap, set); 401 oset = SCARG(uap, oset); 402 403 if (set) { 404 error = copyin(set, &nlss, sizeof(nlss)); 405 if (error) 406 return (error); 407 linux_to_native_sigset(&nbss, &nlss); 408 } 409 mutex_enter(p->p_lock); 410 error = sigprocmask1(l, how, 411 set ? &nbss : NULL, oset ? &obss : NULL); 412 mutex_exit(p->p_lock); 413 if (!error && oset) { 414 native_to_linux_sigset(&olss, &obss); 415 error = copyout(&olss, oset, sizeof(olss)); 416 } 417 return (error); 418 } 419 420 int 421 linux_sys_rt_sigpending(struct lwp *l, const struct linux_sys_rt_sigpending_args *uap, register_t *retval) 422 { 423 /* { 424 syscallarg(linux_sigset_t *) set; 425 syscallarg(size_t) sigsetsize; 426 } */ 427 sigset_t bss; 428 linux_sigset_t lss; 429 430 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 431 return (EINVAL); 432 433 sigpending1(l, &bss); 434 native_to_linux_sigset(&lss, &bss); 435 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 436 } 437 438 #ifndef __amd64__ 439 int 440 linux_sys_sigpending(struct lwp *l, const struct linux_sys_sigpending_args *uap, register_t *retval) 441 { 442 /* { 443 syscallarg(linux_old_sigset_t *) mask; 444 } */ 445 sigset_t bss; 446 linux_old_sigset_t lss; 447 448 sigpending1(l, &bss); 449 native_to_linux_old_sigset(&lss, &bss); 450 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 451 } 452 453 int 454 linux_sys_sigsuspend(struct lwp *l, const struct linux_sys_sigsuspend_args *uap, register_t *retval) 455 { 456 /* { 457 syscallarg(void *) restart; 458 syscallarg(int) oldmask; 459 syscallarg(int) mask; 460 } */ 461 linux_old_sigset_t lss; 462 sigset_t bss; 463 464 lss = SCARG(uap, mask); 465 linux_old_to_native_sigset(&bss, &lss); 466 return (sigsuspend1(l, &bss)); 467 } 468 #endif /* __amd64__ */ 469 470 int 471 linux_sys_rt_sigsuspend(struct lwp *l, const struct linux_sys_rt_sigsuspend_args *uap, register_t *retval) 472 { 473 /* { 474 syscallarg(linux_sigset_t *) unewset; 475 syscallarg(size_t) sigsetsize; 476 } */ 477 linux_sigset_t lss; 478 sigset_t bss; 479 int error; 480 481 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 482 return (EINVAL); 483 484 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 485 if (error) 486 return (error); 487 488 linux_to_native_sigset(&bss, &lss); 489 490 return (sigsuspend1(l, &bss)); 491 } 492 493 /* 494 * Once more: only a signal conversion is needed. 495 * Note: also used as sys_rt_queueinfo. The info field is ignored. 496 */ 497 int 498 linux_sys_rt_queueinfo(struct lwp *l, const struct linux_sys_rt_queueinfo_args *uap, register_t *retval) 499 { 500 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */ 501 #if 0 502 struct linux_sys_rt_queueinfo_args /* { 503 syscallarg(int) pid; 504 syscallarg(int) signum; 505 syscallarg(siginfo_t *) uinfo; 506 } */ *uap = v; 507 #endif 508 509 /* XXX To really implement this we need to */ 510 /* XXX keep a list of queued signals somewhere. */ 511 return (linux_sys_kill(l, (const void *)uap, retval)); 512 } 513 514 int 515 linux_sys_kill(struct lwp *l, const struct linux_sys_kill_args *uap, register_t *retval) 516 { 517 /* { 518 syscallarg(int) pid; 519 syscallarg(int) signum; 520 } */ 521 522 struct sys_kill_args ka; 523 int sig; 524 525 SCARG(&ka, pid) = SCARG(uap, pid); 526 sig = SCARG(uap, signum); 527 if (sig < 0 || sig >= LINUX__NSIG) 528 return (EINVAL); 529 SCARG(&ka, signum) = linux_to_native_signo[sig]; 530 return sys_kill(l, &ka, retval); 531 } 532 533 #ifdef LINUX_SS_ONSTACK 534 static void linux_to_native_sigaltstack(struct sigaltstack *, 535 const struct linux_sigaltstack *); 536 537 static void 538 linux_to_native_sigaltstack(struct sigaltstack *bss, const struct linux_sigaltstack *lss) 539 { 540 bss->ss_sp = lss->ss_sp; 541 bss->ss_size = lss->ss_size; 542 if (lss->ss_flags & LINUX_SS_ONSTACK) 543 bss->ss_flags = SS_ONSTACK; 544 else if (lss->ss_flags & LINUX_SS_DISABLE) 545 bss->ss_flags = SS_DISABLE; 546 else 547 bss->ss_flags = 0; 548 } 549 550 void 551 native_to_linux_sigaltstack(struct linux_sigaltstack *lss, const struct sigaltstack *bss) 552 { 553 lss->ss_sp = bss->ss_sp; 554 lss->ss_size = bss->ss_size; 555 if (bss->ss_flags & SS_ONSTACK) 556 lss->ss_flags = LINUX_SS_ONSTACK; 557 else if (bss->ss_flags & SS_DISABLE) 558 lss->ss_flags = LINUX_SS_DISABLE; 559 else 560 lss->ss_flags = 0; 561 } 562 563 int 564 linux_sys_sigaltstack(struct lwp *l, const struct linux_sys_sigaltstack_args *uap, register_t *retval) 565 { 566 /* { 567 syscallarg(const struct linux_sigaltstack *) ss; 568 syscallarg(struct linux_sigaltstack *) oss; 569 } */ 570 struct linux_sigaltstack ss; 571 struct sigaltstack nss; 572 struct proc *p = l->l_proc; 573 int error = 0; 574 575 if (SCARG(uap, oss)) { 576 native_to_linux_sigaltstack(&ss, &l->l_sigstk); 577 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0) 578 return error; 579 } 580 581 if (SCARG(uap, ss) != NULL) { 582 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0) 583 return error; 584 linux_to_native_sigaltstack(&nss, &ss); 585 586 mutex_enter(p->p_lock); 587 588 if (nss.ss_flags & ~SS_ALLBITS) 589 error = EINVAL; 590 else if (nss.ss_flags & SS_DISABLE) { 591 if (l->l_sigstk.ss_flags & SS_ONSTACK) 592 error = EINVAL; 593 } else if (nss.ss_size < LINUX_MINSIGSTKSZ) 594 error = ENOMEM; 595 596 if (error == 0) 597 l->l_sigstk = nss; 598 599 mutex_exit(p->p_lock); 600 } 601 602 return error; 603 } 604 #endif /* LINUX_SS_ONSTACK */ 605 606 #ifdef LINUX_NPTL 607 int 608 linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, register_t *retval) 609 { 610 /* { 611 syscallarg(int) tid; 612 syscallarg(int) sig; 613 } */ 614 struct linux_sys_kill_args cup; 615 616 /* We use the PID as the TID ... */ 617 SCARG(&cup, pid) = SCARG(uap, tid); 618 SCARG(&cup, signum) = SCARG(uap, sig); 619 620 return linux_sys_kill(l, &cup, retval); 621 } 622 623 int 624 linux_sys_tgkill(struct lwp *l, const struct linux_sys_tgkill_args *uap, register_t *retval) 625 { 626 /* { 627 syscallarg(int) tgid; 628 syscallarg(int) tid; 629 syscallarg(int) sig; 630 } */ 631 struct linux_sys_kill_args cup; 632 struct linux_emuldata *led; 633 struct proc *p; 634 635 SCARG(&cup, pid) = SCARG(uap, tid); 636 SCARG(&cup, signum) = SCARG(uap, sig); 637 638 if (SCARG(uap, tgid) == -1) 639 return linux_sys_kill(l, &cup, retval); 640 641 /* We use the PID as the TID, but make sure the group ID is right */ 642 /* XXX racy */ 643 mutex_enter(proc_lock); 644 if ((p = p_find(SCARG(uap, tid), PFIND_LOCKED)) == NULL || 645 p->p_emul != &emul_linux) { 646 mutex_exit(proc_lock); 647 return ESRCH; 648 } 649 led = p->p_emuldata; 650 if (led->s->group_pid != SCARG(uap, tgid)) { 651 mutex_exit(proc_lock); 652 return ESRCH; 653 } 654 mutex_exit(proc_lock); 655 656 return linux_sys_kill(l, &cup, retval); 657 } 658 #endif /* LINUX_NPTL */ 659 660 int 661 native_to_linux_si_code(int code) 662 { 663 int si_codes[] = { 664 LINUX_SI_USER, LINUX_SI_QUEUE, LINUX_SI_TIMER, LINUX_SI_ASYNCIO, 665 LINUX_SI_MESGQ, LINUX_SI_TKILL /* SI_LWP */ 666 }; 667 668 if (code <= 0 && -code < __arraycount(si_codes)) 669 return si_codes[-code]; 670 671 return code; 672 } 673