1/* $NetBSD: linux_signal.c,v 1.74 2011/11/18 15:45:47 christos 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.74 2011/11/18 15:45:47 christos 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#include <compat/linux/common/linux_errno.h> 79#include <compat/linux/common/linux_sched.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 96extern const int native_to_linux_signo[]; 97extern const int linux_to_native_signo[]; 98 99/* 100 * Convert between Linux and BSD signal sets. 101 */ 102#if LINUX__NSIG_WORDS > 1 103void 104linux_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 118void 119native_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 133void 134linux_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 148void 149native_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 163void 164native_to_linux_siginfo(linux_siginfo_t *lsi, const struct _ksiginfo *ksi) 165{ 166 memset(lsi, 0, sizeof(*lsi)); 167 168 lsi->lsi_signo = native_to_linux_signo[ksi->_signo]; 169 lsi->lsi_errno = native_to_linux_errno[ksi->_errno]; 170 lsi->lsi_code = native_to_linux_si_code(ksi->_code); 171 172 switch (ksi->_code) { 173 case SI_NOINFO: 174 break; 175 176 case SI_USER: 177 lsi->lsi_pid = ksi->_reason._rt._pid; 178 lsi->lsi_uid = ksi->_reason._rt._uid; 179 if (lsi->lsi_signo == LINUX_SIGALRM || 180 lsi->lsi_signo >= LINUX_SIGRTMIN) 181 lsi->lsi_value.sival_ptr = 182 ksi->_reason._rt._value.sival_ptr; 183 break; 184 185 case SI_TIMER: 186 case SI_QUEUE: 187 lsi->lsi_uid = ksi->_reason._rt._uid; 188 lsi->lsi_uid = ksi->_reason._rt._uid; 189 lsi->lsi_value.sival_ptr = ksi->_reason._rt._value.sival_ptr; 190 break; 191 192 case SI_ASYNCIO: 193 case SI_MESGQ: 194 lsi->lsi_value.sival_ptr = ksi->_reason._rt._value.sival_ptr; 195 break; 196 197 default: 198 switch (ksi->_signo) { 199 case SIGCHLD: 200 lsi->lsi_uid = ksi->_reason._child._uid; 201 lsi->lsi_pid = ksi->_reason._child._pid; 202 lsi->lsi_status = native_to_linux_si_status( 203 ksi->_code, ksi->_reason._child._status); 204 lsi->lsi_utime = ksi->_reason._child._utime; 205 lsi->lsi_stime = ksi->_reason._child._stime; 206 break; 207 208 case SIGILL: 209 case SIGFPE: 210 case SIGSEGV: 211 case SIGBUS: 212 case SIGTRAP: 213 lsi->lsi_addr = ksi->_reason._fault._addr; 214 break; 215 216 case SIGIO: 217 lsi->lsi_fd = ksi->_reason._poll._fd; 218 lsi->lsi_band = ksi->_reason._poll._band; 219 break; 220 default: 221 break; 222 } 223 } 224} 225 226unsigned int 227native_to_linux_sigflags(const int bsf) 228{ 229 unsigned int lsf = 0; 230 if ((bsf & SA_NOCLDSTOP) != 0) 231 lsf |= LINUX_SA_NOCLDSTOP; 232 if ((bsf & SA_NOCLDWAIT) != 0) 233 lsf |= LINUX_SA_NOCLDWAIT; 234 if ((bsf & SA_ONSTACK) != 0) 235 lsf |= LINUX_SA_ONSTACK; 236 if ((bsf & SA_RESTART) != 0) 237 lsf |= LINUX_SA_RESTART; 238 if ((bsf & SA_NODEFER) != 0) 239 lsf |= LINUX_SA_NOMASK; 240 if ((bsf & SA_RESETHAND) != 0) 241 lsf |= LINUX_SA_ONESHOT; 242 if ((bsf & SA_SIGINFO) != 0) 243 lsf |= LINUX_SA_SIGINFO; 244 return lsf; 245} 246 247int 248linux_to_native_sigflags(const unsigned long lsf) 249{ 250 int bsf = 0; 251 if ((lsf & LINUX_SA_NOCLDSTOP) != 0) 252 bsf |= SA_NOCLDSTOP; 253 if ((lsf & LINUX_SA_NOCLDWAIT) != 0) 254 bsf |= SA_NOCLDWAIT; 255 if ((lsf & LINUX_SA_ONSTACK) != 0) 256 bsf |= SA_ONSTACK; 257 if ((lsf & LINUX_SA_RESTART) != 0) 258 bsf |= SA_RESTART; 259 if ((lsf & LINUX_SA_ONESHOT) != 0) 260 bsf |= SA_RESETHAND; 261 if ((lsf & LINUX_SA_NOMASK) != 0) 262 bsf |= SA_NODEFER; 263 if ((lsf & LINUX_SA_SIGINFO) != 0) 264 bsf |= SA_SIGINFO; 265 if ((lsf & ~LINUX_SA_ALLBITS) != 0) { 266 DPRINTF(("linux_old_to_native_sigflags: " 267 "%lx extra bits ignored\n", lsf)); 268 } 269 return bsf; 270} 271 272/* 273 * Convert between Linux and BSD sigaction structures. 274 */ 275void 276linux_old_to_native_sigaction(struct sigaction *bsa, const struct linux_old_sigaction *lsa) 277{ 278 bsa->sa_handler = lsa->linux_sa_handler; 279 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 280 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 281} 282 283void 284native_to_linux_old_sigaction(struct linux_old_sigaction *lsa, const struct sigaction *bsa) 285{ 286 lsa->linux_sa_handler = bsa->sa_handler; 287 native_to_linux_old_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 288 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 289#ifndef __alpha__ 290 lsa->linux_sa_restorer = NULL; 291#endif 292} 293 294/* ...and the new sigaction conversion funcs. */ 295void 296linux_to_native_sigaction(struct sigaction *bsa, const struct linux_sigaction *lsa) 297{ 298 bsa->sa_handler = lsa->linux_sa_handler; 299 linux_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 300 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 301} 302 303void 304native_to_linux_sigaction(struct linux_sigaction *lsa, const struct sigaction *bsa) 305{ 306 lsa->linux_sa_handler = bsa->sa_handler; 307 native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 308 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 309#ifndef __alpha__ 310 lsa->linux_sa_restorer = NULL; 311#endif 312} 313 314/* ----------------------------------------------------------------------- */ 315 316/* 317 * The Linux sigaction() system call. Do the usual conversions, 318 * and just call sigaction(). Some flags and values are silently 319 * ignored (see above). 320 */ 321int 322linux_sys_rt_sigaction(struct lwp *l, const struct linux_sys_rt_sigaction_args *uap, register_t *retval) 323{ 324 /* { 325 syscallarg(int) signum; 326 syscallarg(const struct linux_sigaction *) nsa; 327 syscallarg(struct linux_sigaction *) osa; 328 syscallarg(size_t) sigsetsize; 329 } */ 330 struct linux_sigaction nlsa, olsa; 331 struct sigaction nbsa, obsa; 332 int error, sig; 333 void *tramp = NULL; 334 int vers = 0; 335#if defined __amd64__ 336 struct sigacts *ps = l->l_proc->p_sigacts; 337#endif 338 339 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 340 return (EINVAL); 341 342 if (SCARG(uap, nsa)) { 343 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 344 if (error) 345 return (error); 346 linux_to_native_sigaction(&nbsa, &nlsa); 347 } 348 349 sig = SCARG(uap, signum); 350 if (sig < 0 || sig >= LINUX__NSIG) 351 return (EINVAL); 352 if (sig > 0 && !linux_to_native_signo[sig]) { 353 /* Pretend that we did something useful for unknown signals. */ 354 obsa.sa_handler = SIG_IGN; 355 sigemptyset(&obsa.sa_mask); 356 obsa.sa_flags = 0; 357 } else { 358#if defined __amd64__ 359 if (nlsa.linux_sa_flags & LINUX_SA_RESTORER) { 360 if ((tramp = nlsa.linux_sa_restorer) != NULL) 361 vers = 2; /* XXX arch dependent */ 362 } 363#endif 364 365 error = sigaction1(l, linux_to_native_signo[sig], 366 SCARG(uap, nsa) ? &nbsa : NULL, 367 SCARG(uap, osa) ? &obsa : NULL, 368 tramp, vers); 369 if (error) 370 return (error); 371 } 372 if (SCARG(uap, osa)) { 373 native_to_linux_sigaction(&olsa, &obsa); 374 375#if defined __amd64__ 376 if (ps->sa_sigdesc[sig].sd_vers != 0) { 377 olsa.linux_sa_restorer = ps->sa_sigdesc[sig].sd_tramp; 378 olsa.linux_sa_flags |= LINUX_SA_RESTORER; 379 } 380#endif 381 382 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 383 if (error) 384 return (error); 385 } 386 return (0); 387} 388 389int 390linux_sigprocmask1(struct lwp *l, int how, const linux_old_sigset_t *set, linux_old_sigset_t *oset) 391{ 392 struct proc *p = l->l_proc; 393 linux_old_sigset_t nlss, olss; 394 sigset_t nbss, obss; 395 int error; 396 397 switch (how) { 398 case LINUX_SIG_BLOCK: 399 how = SIG_BLOCK; 400 break; 401 case LINUX_SIG_UNBLOCK: 402 how = SIG_UNBLOCK; 403 break; 404 case LINUX_SIG_SETMASK: 405 how = SIG_SETMASK; 406 break; 407 default: 408 return (EINVAL); 409 } 410 411 if (set) { 412 error = copyin(set, &nlss, sizeof(nlss)); 413 if (error) 414 return (error); 415 linux_old_to_native_sigset(&nbss, &nlss); 416 } 417 mutex_enter(p->p_lock); 418 error = sigprocmask1(l, how, 419 set ? &nbss : NULL, oset ? &obss : NULL); 420 mutex_exit(p->p_lock); 421 if (error) 422 return (error); 423 if (oset) { 424 native_to_linux_old_sigset(&olss, &obss); 425 error = copyout(&olss, oset, sizeof(olss)); 426 if (error) 427 return (error); 428 } 429 return (error); 430} 431 432int 433linux_sys_rt_sigprocmask(struct lwp *l, const struct linux_sys_rt_sigprocmask_args *uap, register_t *retval) 434{ 435 /* { 436 syscallarg(int) how; 437 syscallarg(const linux_sigset_t *) set; 438 syscallarg(linux_sigset_t *) oset; 439 syscallarg(size_t) sigsetsize; 440 } */ 441 linux_sigset_t nlss, olss, *oset; 442 const linux_sigset_t *set; 443 struct proc *p = l->l_proc; 444 sigset_t nbss, obss; 445 int error, how; 446 447 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 448 return (EINVAL); 449 450 switch (SCARG(uap, how)) { 451 case LINUX_SIG_BLOCK: 452 how = SIG_BLOCK; 453 break; 454 case LINUX_SIG_UNBLOCK: 455 how = SIG_UNBLOCK; 456 break; 457 case LINUX_SIG_SETMASK: 458 how = SIG_SETMASK; 459 break; 460 default: 461 return (EINVAL); 462 } 463 464 set = SCARG(uap, set); 465 oset = SCARG(uap, oset); 466 467 if (set) { 468 error = copyin(set, &nlss, sizeof(nlss)); 469 if (error) 470 return (error); 471 linux_to_native_sigset(&nbss, &nlss); 472 } 473 mutex_enter(p->p_lock); 474 error = sigprocmask1(l, how, 475 set ? &nbss : NULL, oset ? &obss : NULL); 476 mutex_exit(p->p_lock); 477 if (!error && oset) { 478 native_to_linux_sigset(&olss, &obss); 479 error = copyout(&olss, oset, sizeof(olss)); 480 } 481 return (error); 482} 483 484int 485linux_sys_rt_sigpending(struct lwp *l, const struct linux_sys_rt_sigpending_args *uap, register_t *retval) 486{ 487 /* { 488 syscallarg(linux_sigset_t *) set; 489 syscallarg(size_t) sigsetsize; 490 } */ 491 sigset_t bss; 492 linux_sigset_t lss; 493 494 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 495 return (EINVAL); 496 497 sigpending1(l, &bss); 498 native_to_linux_sigset(&lss, &bss); 499 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 500} 501 502#ifndef __amd64__ 503int 504linux_sys_sigpending(struct lwp *l, const struct linux_sys_sigpending_args *uap, register_t *retval) 505{ 506 /* { 507 syscallarg(linux_old_sigset_t *) mask; 508 } */ 509 sigset_t bss; 510 linux_old_sigset_t lss; 511 512 sigpending1(l, &bss); 513 native_to_linux_old_sigset(&lss, &bss); 514 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 515} 516 517int 518linux_sys_sigsuspend(struct lwp *l, const struct linux_sys_sigsuspend_args *uap, register_t *retval) 519{ 520 /* { 521 syscallarg(void *) restart; 522 syscallarg(int) oldmask; 523 syscallarg(int) mask; 524 } */ 525 linux_old_sigset_t lss; 526 sigset_t bss; 527 528 lss = SCARG(uap, mask); 529 linux_old_to_native_sigset(&bss, &lss); 530 return (sigsuspend1(l, &bss)); 531} 532#endif /* __amd64__ */ 533 534int 535linux_sys_rt_sigsuspend(struct lwp *l, const struct linux_sys_rt_sigsuspend_args *uap, register_t *retval) 536{ 537 /* { 538 syscallarg(linux_sigset_t *) unewset; 539 syscallarg(size_t) sigsetsize; 540 } */ 541 linux_sigset_t lss; 542 sigset_t bss; 543 int error; 544 545 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 546 return (EINVAL); 547 548 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 549 if (error) 550 return (error); 551 552 linux_to_native_sigset(&bss, &lss); 553 554 return (sigsuspend1(l, &bss)); 555} 556 557static int 558fetchss(const void *u, void *s, size_t len) 559{ 560 int error; 561 linux_sigset_t lss; 562 563 if ((error = copyin(u, &lss, sizeof(lss))) != 0) 564 return error; 565 566 linux_to_native_sigset(s, &lss); 567 return 0; 568} 569 570static int 571fetchts(const void *u, void *s, size_t len) 572{ 573 int error; 574 struct linux_timespec lts; 575 576 if ((error = copyin(u, <s, sizeof(lts))) != 0) 577 return error; 578 579 linux_to_native_timespec(s, <s); 580 return 0; 581} 582 583static int 584fakestorets(const void *u, void *s, size_t len) 585{ 586 /* Do nothing, sigtimedwait does not alter timeout like ours */ 587 return 0; 588} 589 590static int 591storeinfo(const void *s, void *u, size_t len) 592{ 593 struct linux_siginfo lsi; 594 595 native_to_linux_siginfo(&lsi, &((const siginfo_t *)s)->_info); 596 return copyout(&lsi, u, sizeof(lsi)); 597} 598 599int 600linux_sys_rt_sigtimedwait(struct lwp *l, 601 const struct linux_sys_rt_sigtimedwait_args *uap, register_t *retval) 602{ 603 /* { 604 syscallarg(const linux_sigset_t *) set; 605 syscallarg(linux_siginfo_t *) info); 606 syscallarg(const struct linux_timespec *) timeout; 607 } */ 608 609 return sigtimedwait1(l, (const struct sys_____sigtimedwait50_args *)uap, 610 retval, fetchss, storeinfo, fetchts, fakestorets); 611} 612 613/* 614 * Once more: only a signal conversion is needed. 615 * Note: also used as sys_rt_queueinfo. The info field is ignored. 616 */ 617int 618linux_sys_rt_queueinfo(struct lwp *l, const struct linux_sys_rt_queueinfo_args *uap, register_t *retval) 619{ 620 /* 621 syscallarg(int) pid; 622 syscallarg(int) signum; 623 syscallarg(linix_siginfo_t *) uinfo; 624 */ 625 int error; 626 linux_siginfo_t info; 627 628 error = copyin(SCARG(uap, uinfo), &info, sizeof(info)); 629 if (error) 630 return error; 631 if (info.lsi_code >= 0) 632 return EPERM; 633 634 /* XXX To really implement this we need to */ 635 /* XXX keep a list of queued signals somewhere. */ 636 return (linux_sys_kill(l, (const void *)uap, retval)); 637} 638 639int 640linux_sys_kill(struct lwp *l, const struct linux_sys_kill_args *uap, register_t *retval) 641{ 642 /* { 643 syscallarg(int) pid; 644 syscallarg(int) signum; 645 } */ 646 647 struct sys_kill_args ka; 648 int sig; 649 650 SCARG(&ka, pid) = SCARG(uap, pid); 651 sig = SCARG(uap, signum); 652 if (sig < 0 || sig >= LINUX__NSIG) 653 return (EINVAL); 654 SCARG(&ka, signum) = linux_to_native_signo[sig]; 655 return sys_kill(l, &ka, retval); 656} 657 658#ifdef LINUX_SS_ONSTACK 659static void linux_to_native_sigaltstack(struct sigaltstack *, 660 const struct linux_sigaltstack *); 661 662static void 663linux_to_native_sigaltstack(struct sigaltstack *bss, const struct linux_sigaltstack *lss) 664{ 665 bss->ss_sp = lss->ss_sp; 666 bss->ss_size = lss->ss_size; 667 if (lss->ss_flags & LINUX_SS_ONSTACK) 668 bss->ss_flags = SS_ONSTACK; 669 else if (lss->ss_flags & LINUX_SS_DISABLE) 670 bss->ss_flags = SS_DISABLE; 671 else 672 bss->ss_flags = 0; 673} 674 675void 676native_to_linux_sigaltstack(struct linux_sigaltstack *lss, const struct sigaltstack *bss) 677{ 678 lss->ss_sp = bss->ss_sp; 679 lss->ss_size = bss->ss_size; 680 if (bss->ss_flags & SS_ONSTACK) 681 lss->ss_flags = LINUX_SS_ONSTACK; 682 else if (bss->ss_flags & SS_DISABLE) 683 lss->ss_flags = LINUX_SS_DISABLE; 684 else 685 lss->ss_flags = 0; 686} 687 688int 689linux_sys_sigaltstack(struct lwp *l, const struct linux_sys_sigaltstack_args *uap, register_t *retval) 690{ 691 /* { 692 syscallarg(const struct linux_sigaltstack *) ss; 693 syscallarg(struct linux_sigaltstack *) oss; 694 } */ 695 struct linux_sigaltstack ss; 696 struct sigaltstack nss; 697 struct proc *p = l->l_proc; 698 int error = 0; 699 700 if (SCARG(uap, oss)) { 701 native_to_linux_sigaltstack(&ss, &l->l_sigstk); 702 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0) 703 return error; 704 } 705 706 if (SCARG(uap, ss) != NULL) { 707 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0) 708 return error; 709 linux_to_native_sigaltstack(&nss, &ss); 710 711 mutex_enter(p->p_lock); 712 713 if (nss.ss_flags & ~SS_ALLBITS) 714 error = EINVAL; 715 else if (nss.ss_flags & SS_DISABLE) { 716 if (l->l_sigstk.ss_flags & SS_ONSTACK) 717 error = EINVAL; 718 } else if (nss.ss_size < LINUX_MINSIGSTKSZ) 719 error = ENOMEM; 720 721 if (error == 0) 722 l->l_sigstk = nss; 723 724 mutex_exit(p->p_lock); 725 } 726 727 return error; 728} 729#endif /* LINUX_SS_ONSTACK */ 730 731static int 732linux_do_tkill(struct lwp *l, int tgid, int tid, int signum) 733{ 734 struct proc *p; 735 struct lwp *t; 736 ksiginfo_t ksi; 737 int error; 738 739 if (signum < 0 || signum >= LINUX__NSIG) 740 return EINVAL; 741 signum = linux_to_native_signo[signum]; 742 743 if (tgid == -1) { 744 tgid = tid; 745 } 746 747 KSI_INIT(&ksi); 748 ksi.ksi_signo = signum; 749 ksi.ksi_code = SI_LWP; 750 ksi.ksi_pid = l->l_proc->p_pid; 751 ksi.ksi_uid = kauth_cred_geteuid(l->l_cred); 752 ksi.ksi_lid = tid; 753 754 mutex_enter(proc_lock); 755 p = proc_find(tgid); 756 if (p == NULL) { 757 mutex_exit(proc_lock); 758 return ESRCH; 759 } 760 mutex_enter(p->p_lock); 761 error = kauth_authorize_process(l->l_cred, 762 KAUTH_PROCESS_SIGNAL, p, KAUTH_ARG(signum), NULL, NULL); 763 if ((t = lwp_find(p, ksi.ksi_lid)) == NULL) 764 error = ESRCH; 765 else if (signum != 0) 766 kpsignal2(p, &ksi); 767 mutex_exit(p->p_lock); 768 mutex_exit(proc_lock); 769 770 return error; 771} 772 773int 774linux_sys_tkill(struct lwp *l, const struct linux_sys_tkill_args *uap, register_t *retval) 775{ 776 /* { 777 syscallarg(int) tid; 778 syscallarg(int) sig; 779 } */ 780 781 if (SCARG(uap, tid) <= 0) 782 return EINVAL; 783 784 return linux_do_tkill(l, -1, SCARG(uap, tid), SCARG(uap, sig)); 785} 786 787int 788linux_sys_tgkill(struct lwp *l, const struct linux_sys_tgkill_args *uap, register_t *retval) 789{ 790 /* { 791 syscallarg(int) tgid; 792 syscallarg(int) tid; 793 syscallarg(int) sig; 794 } */ 795 796 if (SCARG(uap, tid) <= 0 || SCARG(uap, tgid) < -1) 797 return EINVAL; 798 799 return linux_do_tkill(l, SCARG(uap, tgid), SCARG(uap, tid), SCARG(uap, sig)); 800} 801 802int 803native_to_linux_si_code(int code) 804{ 805 int si_codes[] = { 806 LINUX_SI_USER, LINUX_SI_QUEUE, LINUX_SI_TIMER, LINUX_SI_ASYNCIO, 807 LINUX_SI_MESGQ, LINUX_SI_TKILL /* SI_LWP */ 808 }; 809 810 if (code <= 0 && -code < __arraycount(si_codes)) 811 return si_codes[-code]; 812 813 return code; 814} 815 816int 817native_to_linux_si_status(int code, int status) 818{ 819 int sts; 820 821 switch (code) { 822 case CLD_CONTINUED: 823 sts = LINUX_SIGCONT; 824 break; 825 case CLD_EXITED: 826 sts = WEXITSTATUS(status); 827 break; 828 case CLD_STOPPED: 829 case CLD_TRAPPED: 830 case CLD_DUMPED: 831 case CLD_KILLED: 832 default: 833 sts = native_to_linux_signo[WTERMSIG(status)]; 834 break; 835 } 836 837 return sts; 838} 839