1 /* $NetBSD: linux_signal.c,v 1.34 2002/02/18 22:24:18 christos Exp $ */ 2 /*- 3 * Copyright (c) 1995, 1998 The NetBSD Foundation, Inc. 4 * All rights reserved. 5 * 6 * This code is derived from software contributed to The NetBSD Foundation 7 * by Frank van der Linden and Eric Haszlakiewicz. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: 12 * 1. Redistributions of source code must retain the above copyright 13 * notice, this list of conditions and the following disclaimer. 14 * 2. Redistributions in binary form must reproduce the above copyright 15 * notice, this list of conditions and the following disclaimer in the 16 * documentation and/or other materials provided with the distribution. 17 * 3. All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by the NetBSD 20 * Foundation, Inc. and its contributors. 21 * 4. Neither the name of The NetBSD Foundation nor the names of its 22 * contributors may be used to endorse or promote products derived 23 * from this software without specific prior written permission. 24 * 25 * THIS SOFTWARE IS PROVIDED BY THE NETBSD FOUNDATION, INC. AND CONTRIBUTORS 26 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED 27 * TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 28 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE FOUNDATION OR CONTRIBUTORS 29 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 30 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 31 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 32 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 33 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 34 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 35 * POSSIBILITY OF SUCH DAMAGE. 36 */ 37 /* 38 * heavily from: svr4_signal.c,v 1.7 1995/01/09 01:04:21 christos Exp 39 */ 40 41 /* 42 * Functions in multiarch: 43 * linux_sys_signal : linux_sig_notalpha.c 44 * linux_sys_siggetmask : linux_sig_notalpha.c 45 * linux_sys_sigsetmask : linux_sig_notalpha.c 46 * linux_sys_pause : linux_sig_notalpha.c 47 * linux_sys_sigaction : linux_sigaction.c 48 * 49 */ 50 51 /* 52 * Unimplemented: 53 * linux_sys_rt_sigtimedwait : sigsuspend w/timeout. 54 */ 55 56 #include <sys/cdefs.h> 57 __KERNEL_RCSID(0, "$NetBSD: linux_signal.c,v 1.34 2002/02/18 22:24:18 christos Exp $"); 58 59 #define COMPAT_LINUX 1 60 61 #include <sys/param.h> 62 #include <sys/systm.h> 63 #include <sys/namei.h> 64 #include <sys/proc.h> 65 #include <sys/filedesc.h> 66 #include <sys/ioctl.h> 67 #include <sys/mount.h> 68 #include <sys/kernel.h> 69 #include <sys/signal.h> 70 #include <sys/signalvar.h> 71 #include <sys/malloc.h> 72 73 #include <sys/syscallargs.h> 74 75 #include <compat/linux/common/linux_types.h> 76 #include <compat/linux/common/linux_signal.h> 77 #include <compat/linux/common/linux_siginfo.h> 78 #include <compat/linux/common/linux_util.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 & (1 << ((n) - 1) % LINUX__NSIG_BPW)) 86 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 87 |= (1 << ((n) - 1) % LINUX__NSIG_BPW)) 88 89 /* Note: linux_to_native_sig[] is in <arch>/linux_sigarray.c */ 90 const int native_to_linux_sig[NSIG] = { 91 0, 92 LINUX_SIGHUP, 93 LINUX_SIGINT, 94 LINUX_SIGQUIT, 95 LINUX_SIGILL, 96 LINUX_SIGTRAP, 97 LINUX_SIGABRT, 98 0, /* SIGEMT */ 99 LINUX_SIGFPE, 100 LINUX_SIGKILL, 101 LINUX_SIGBUS, 102 LINUX_SIGSEGV, 103 0, /* SIGSYS */ 104 LINUX_SIGPIPE, 105 LINUX_SIGALRM, 106 LINUX_SIGTERM, 107 LINUX_SIGURG, 108 LINUX_SIGSTOP, 109 LINUX_SIGTSTP, 110 LINUX_SIGCONT, 111 LINUX_SIGCHLD, 112 LINUX_SIGTTIN, 113 LINUX_SIGTTOU, 114 LINUX_SIGIO, 115 LINUX_SIGXCPU, 116 LINUX_SIGXFSZ, 117 LINUX_SIGVTALRM, 118 LINUX_SIGPROF, 119 LINUX_SIGWINCH, 120 0, /* SIGINFO */ 121 LINUX_SIGUSR1, 122 LINUX_SIGUSR2, 123 LINUX_SIGPWR, 124 }; 125 126 /* 127 * Convert between Linux and BSD signal sets. 128 */ 129 #if LINUX__NSIG_WORDS > 1 130 void 131 linux_old_extra_to_native_sigset(bss, lss, extra) 132 sigset_t *bss; 133 const linux_old_sigset_t *lss; 134 const unsigned long *extra; 135 { 136 linux_sigset_t lsnew; 137 138 /* convert old sigset to new sigset */ 139 linux_sigemptyset(&lsnew); 140 lsnew.sig[0] = *lss; 141 if (extra) 142 memcpy(&lsnew.sig[1], extra, 143 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 144 145 linux_to_native_sigset(bss, &lsnew); 146 } 147 148 void 149 native_to_linux_old_extra_sigset(lss, extra, bss) 150 linux_old_sigset_t *lss; 151 unsigned long *extra; 152 const sigset_t *bss; 153 { 154 linux_sigset_t lsnew; 155 156 native_to_linux_sigset(&lsnew, bss); 157 158 /* convert new sigset to old sigset */ 159 *lss = lsnew.sig[0]; 160 if (extra) 161 memcpy(extra, &lsnew.sig[1], 162 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 163 } 164 #endif 165 166 void 167 linux_to_native_sigset(bss, lss) 168 sigset_t *bss; 169 const linux_sigset_t *lss; 170 { 171 int i, newsig; 172 173 sigemptyset(bss); 174 for (i = 1; i < LINUX__NSIG; i++) { 175 if (linux_sigismember(lss, i)) { 176 newsig = linux_to_native_sig[i]; 177 if (newsig) 178 sigaddset(bss, newsig); 179 } 180 } 181 } 182 183 void 184 native_to_linux_sigset(lss, bss) 185 linux_sigset_t *lss; 186 const sigset_t *bss; 187 { 188 int i, newsig; 189 190 linux_sigemptyset(lss); 191 for (i = 1; i < NSIG; i++) { 192 if (sigismember(bss, i)) { 193 newsig = native_to_linux_sig[i]; 194 if (newsig) 195 linux_sigaddset(lss, newsig); 196 } 197 } 198 } 199 200 unsigned int 201 native_to_linux_sigflags(bsf) 202 const int bsf; 203 { 204 unsigned int lsf = 0; 205 if ((bsf & SA_NOCLDSTOP) != 0) 206 lsf |= LINUX_SA_NOCLDSTOP; 207 if ((bsf & SA_NOCLDWAIT) != 0) 208 lsf |= LINUX_SA_NOCLDWAIT; 209 if ((bsf & SA_ONSTACK) != 0) 210 lsf |= LINUX_SA_ONSTACK; 211 if ((bsf & SA_RESTART) != 0) 212 lsf |= LINUX_SA_RESTART; 213 if ((bsf & SA_NODEFER) != 0) 214 lsf |= LINUX_SA_NOMASK; 215 if ((bsf & SA_RESETHAND) != 0) 216 lsf |= LINUX_SA_ONESHOT; 217 if ((bsf & SA_SIGINFO) != 0) 218 lsf |= LINUX_SA_SIGINFO; 219 return lsf; 220 } 221 222 int 223 linux_to_native_sigflags(lsf) 224 const unsigned long lsf; 225 { 226 int bsf = 0; 227 if ((lsf & LINUX_SA_NOCLDSTOP) != 0) 228 bsf |= SA_NOCLDSTOP; 229 if ((lsf & LINUX_SA_NOCLDWAIT) != 0) 230 bsf |= SA_NOCLDWAIT; 231 if ((lsf & LINUX_SA_ONSTACK) != 0) 232 bsf |= SA_ONSTACK; 233 if ((lsf & LINUX_SA_RESTART) != 0) 234 bsf |= SA_RESTART; 235 if ((lsf & LINUX_SA_ONESHOT) != 0) 236 bsf |= SA_RESETHAND; 237 if ((lsf & LINUX_SA_NOMASK) != 0) 238 bsf |= SA_NODEFER; 239 if ((lsf & LINUX_SA_SIGINFO) != 0) 240 bsf |= SA_SIGINFO; 241 #ifdef DEBUG_LINUX 242 if ((lsf & ~LINUX_SA_ALLBITS) != 0) 243 uprintf( 244 "linux_old_to_native_sigflags: %lx extra bits ignored\n", 245 lsf); 246 #endif 247 return bsf; 248 } 249 250 /* 251 * Convert between Linux and BSD sigaction structures. Linux sometimes 252 * has one extra field (sa_restorer) which we don't support. 253 */ 254 void 255 linux_old_to_native_sigaction(bsa, lsa) 256 struct sigaction *bsa; 257 const struct linux_old_sigaction *lsa; 258 { 259 bsa->sa_handler = lsa->sa_handler; 260 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->sa_mask); 261 bsa->sa_flags = linux_to_native_sigflags(lsa->sa_flags); 262 #ifndef __alpha__ 263 /* 264 * XXX: On the alpha sa_restorer is elsewhere. 265 */ 266 #ifdef DEBUG_LINUX 267 if (lsa->sa_restorer != NULL) 268 uprintf("linux_old_to_native_sigaction: sa_restorer ignored\n"); 269 #endif 270 #endif 271 } 272 273 void 274 native_to_linux_old_sigaction(lsa, bsa) 275 struct linux_old_sigaction *lsa; 276 const struct sigaction *bsa; 277 { 278 lsa->sa_handler = bsa->sa_handler; 279 native_to_linux_old_sigset(&lsa->sa_mask, &bsa->sa_mask); 280 lsa->sa_flags = native_to_linux_sigflags(bsa->sa_flags); 281 #ifndef __alpha__ 282 lsa->sa_restorer = NULL; 283 #endif 284 } 285 286 /* ...and the new sigaction conversion funcs. */ 287 void 288 linux_to_native_sigaction(bsa, lsa) 289 struct sigaction *bsa; 290 const struct linux_sigaction *lsa; 291 { 292 bsa->sa_handler = lsa->sa_handler; 293 linux_to_native_sigset(&bsa->sa_mask, &lsa->sa_mask); 294 bsa->sa_flags = linux_to_native_sigflags(lsa->sa_flags); 295 #ifndef __alpha__ 296 #ifdef DEBUG_LINUX 297 if (lsa->sa_restorer != 0) 298 uprintf("linux_to_native_sigaction: sa_restorer ignored\n"); 299 #endif 300 #endif 301 } 302 303 void 304 native_to_linux_sigaction(lsa, bsa) 305 struct linux_sigaction *lsa; 306 const struct sigaction *bsa; 307 { 308 lsa->sa_handler = bsa->sa_handler; 309 native_to_linux_sigset(&lsa->sa_mask, &bsa->sa_mask); 310 lsa->sa_flags = native_to_linux_sigflags(bsa->sa_flags); 311 #ifndef __alpha__ 312 lsa->sa_restorer = NULL; 313 #endif 314 } 315 316 /* ----------------------------------------------------------------------- */ 317 318 /* 319 * The Linux sigaction() system call. Do the usual conversions, 320 * and just call sigaction(). Some flags and values are silently 321 * ignored (see above). 322 */ 323 int 324 linux_sys_rt_sigaction(p, v, retval) 325 struct proc *p; 326 void *v; 327 register_t *retval; 328 { 329 struct linux_sys_rt_sigaction_args /* { 330 syscallarg(int) signum; 331 syscallarg(const struct linux_sigaction *) nsa; 332 syscallarg(struct linux_sigaction *) osa; 333 syscallarg(size_t) sigsetsize; 334 } */ *uap = v; 335 struct linux_sigaction nlsa, olsa; 336 struct sigaction nbsa, obsa; 337 int error, sig; 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 sig = SCARG(uap, signum); 349 if (sig < 0 || sig >= LINUX__NSIG) 350 return (EINVAL); 351 if (sig > 0 && !linux_to_native_sig[sig]) { 352 /* Pretend that we did something useful for unknown signals. */ 353 obsa.sa_handler = SIG_IGN; 354 sigemptyset(&obsa.sa_mask); 355 obsa.sa_flags = 0; 356 } else { 357 error = sigaction1(p, linux_to_native_sig[sig], 358 SCARG(uap, nsa) ? &nbsa : NULL, SCARG(uap, osa) ? &obsa : NULL); 359 if (error) 360 return (error); 361 } 362 if (SCARG(uap, osa)) { 363 native_to_linux_sigaction(&olsa, &obsa); 364 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 365 if (error) 366 return (error); 367 } 368 return (0); 369 } 370 371 int 372 linux_sigprocmask1(p, how, set, oset) 373 struct proc *p; 374 int how; 375 const linux_old_sigset_t *set; 376 linux_old_sigset_t *oset; 377 { 378 linux_old_sigset_t nlss, olss; 379 sigset_t nbss, obss; 380 int error; 381 382 switch (how) { 383 case LINUX_SIG_BLOCK: 384 how = SIG_BLOCK; 385 break; 386 case LINUX_SIG_UNBLOCK: 387 how = SIG_UNBLOCK; 388 break; 389 case LINUX_SIG_SETMASK: 390 how = SIG_SETMASK; 391 break; 392 default: 393 return (EINVAL); 394 } 395 396 if (set) { 397 error = copyin(set, &nlss, sizeof(nlss)); 398 if (error) 399 return (error); 400 linux_old_to_native_sigset(&nbss, &nlss); 401 } 402 error = sigprocmask1(p, how, 403 set ? &nbss : NULL, oset ? &obss : NULL); 404 if (error) 405 return (error); 406 if (oset) { 407 native_to_linux_old_sigset(&olss, &obss); 408 error = copyout(&olss, oset, sizeof(olss)); 409 if (error) 410 return (error); 411 } 412 return (error); 413 } 414 415 int 416 linux_sys_rt_sigprocmask(p, v, retval) 417 struct proc *p; 418 void *v; 419 register_t *retval; 420 { 421 struct linux_sys_rt_sigprocmask_args /* { 422 syscallarg(int) how; 423 syscallarg(const linux_sigset_t *) set; 424 syscallarg(linux_sigset_t *) oset; 425 syscallarg(size_t) sigsetsize; 426 } */ *uap = v; 427 428 linux_sigset_t nlss, olss, *oset; 429 const linux_sigset_t *set; 430 sigset_t nbss, obss; 431 int error, how; 432 433 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 434 return (EINVAL); 435 436 switch (SCARG(uap, how)) { 437 case LINUX_SIG_BLOCK: 438 how = SIG_BLOCK; 439 break; 440 case LINUX_SIG_UNBLOCK: 441 how = SIG_UNBLOCK; 442 break; 443 case LINUX_SIG_SETMASK: 444 how = SIG_SETMASK; 445 break; 446 default: 447 return (EINVAL); 448 } 449 450 set = SCARG(uap, set); 451 oset = SCARG(uap, oset); 452 453 if (set) { 454 error = copyin(set, &nlss, sizeof(nlss)); 455 if (error) 456 return (error); 457 linux_to_native_sigset(&nbss, &nlss); 458 } 459 error = sigprocmask1(p, how, 460 set ? &nbss : NULL, oset ? &obss : NULL); 461 if (!error && oset) { 462 native_to_linux_sigset(&olss, &obss); 463 error = copyout(&olss, oset, sizeof(olss)); 464 } 465 return (error); 466 } 467 468 int 469 linux_sys_rt_sigpending(p, v, retval) 470 struct proc *p; 471 void *v; 472 register_t *retval; 473 { 474 struct linux_sys_rt_sigpending_args /* { 475 syscallarg(linux_sigset_t *) set; 476 syscallarg(size_t) sigsetsize; 477 } */ *uap = v; 478 sigset_t bss; 479 linux_sigset_t lss; 480 481 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 482 return (EINVAL); 483 484 sigpending1(p, &bss); 485 native_to_linux_sigset(&lss, &bss); 486 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 487 } 488 489 int 490 linux_sys_sigpending(p, v, retval) 491 struct proc *p; 492 void *v; 493 register_t *retval; 494 { 495 struct linux_sys_sigpending_args /* { 496 syscallarg(linux_old_sigset_t *) mask; 497 } */ *uap = v; 498 sigset_t bss; 499 linux_old_sigset_t lss; 500 501 sigpending1(p, &bss); 502 native_to_linux_old_sigset(&lss, &bss); 503 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 504 } 505 506 int 507 linux_sys_sigsuspend(p, v, retval) 508 struct proc *p; 509 void *v; 510 register_t *retval; 511 { 512 struct linux_sys_sigsuspend_args /* { 513 syscallarg(caddr_t) restart; 514 syscallarg(int) oldmask; 515 syscallarg(int) mask; 516 } */ *uap = v; 517 linux_old_sigset_t lss; 518 sigset_t bss; 519 520 lss = SCARG(uap, mask); 521 linux_old_to_native_sigset(&bss, &lss); 522 return (sigsuspend1(p, &bss)); 523 } 524 int 525 linux_sys_rt_sigsuspend(p, v, retval) 526 struct proc *p; 527 void *v; 528 register_t *retval; 529 { 530 struct linux_sys_rt_sigsuspend_args /* { 531 syscallarg(linux_sigset_t *) unewset; 532 syscallarg(size_t) sigsetsize; 533 } */ *uap = v; 534 linux_sigset_t lss; 535 sigset_t bss; 536 int error; 537 538 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 539 return (EINVAL); 540 541 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 542 if (error) 543 return (error); 544 545 linux_to_native_sigset(&bss, &lss); 546 547 return (sigsuspend1(p, &bss)); 548 } 549 550 /* 551 * Once more: only a signal conversion is needed. 552 * Note: also used as sys_rt_queueinfo. The info field is ignored. 553 */ 554 int 555 linux_sys_rt_queueinfo(p, v, retval) 556 struct proc *p; 557 void *v; 558 register_t *retval; 559 { 560 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */ 561 #if 0 562 struct linux_sys_rt_queueinfo_args /* { 563 syscallarg(int) pid; 564 syscallarg(int) signum; 565 syscallarg(siginfo_t *) uinfo; 566 } */ *uap = v; 567 #endif 568 569 /* XXX To really implement this we need to */ 570 /* XXX keep a list of queued signals somewhere. */ 571 return (linux_sys_kill(p, v, retval)); 572 } 573 574 int 575 linux_sys_kill(p, v, retval) 576 struct proc *p; 577 void *v; 578 register_t *retval; 579 { 580 struct linux_sys_kill_args /* { 581 syscallarg(int) pid; 582 syscallarg(int) signum; 583 } */ *uap = v; 584 struct sys_kill_args ka; 585 int sig; 586 587 SCARG(&ka, pid) = SCARG(uap, pid); 588 sig = SCARG(uap, signum); 589 if (sig < 0 || sig >= LINUX__NSIG) 590 return (EINVAL); 591 SCARG(&ka, signum) = linux_to_native_sig[sig]; 592 return sys_kill(p, &ka, retval); 593 } 594 595 #ifdef LINUX_SS_ONSTACK 596 static void linux_to_native_sigaltstack __P((struct sigaltstack *, 597 const struct linux_sigaltstack *)); 598 static void native_to_linux_sigaltstack __P((struct linux_sigaltstack *, 599 const struct sigaltstack *)); 600 601 static void 602 linux_to_native_sigaltstack(bss, lss) 603 struct sigaltstack *bss; 604 const struct linux_sigaltstack *lss; 605 { 606 bss->ss_sp = lss->ss_sp; 607 bss->ss_size = lss->ss_size; 608 if (lss->ss_flags & LINUX_SS_ONSTACK) 609 bss->ss_flags = SS_ONSTACK; 610 else if (lss->ss_flags & LINUX_SS_DISABLE) 611 bss->ss_flags = SS_DISABLE; 612 else 613 bss->ss_flags = 0; 614 } 615 616 static void 617 native_to_linux_sigaltstack(lss, bss) 618 struct linux_sigaltstack *lss; 619 const struct sigaltstack *bss; 620 { 621 lss->ss_sp = bss->ss_sp; 622 lss->ss_size = bss->ss_size; 623 if (bss->ss_flags & SS_ONSTACK) 624 lss->ss_flags = LINUX_SS_ONSTACK; 625 else if (bss->ss_flags & SS_DISABLE) 626 lss->ss_flags = LINUX_SS_DISABLE; 627 else 628 lss->ss_flags = 0; 629 } 630 631 int 632 linux_sys_sigaltstack(p, v, retval) 633 struct proc *p; 634 void *v; 635 register_t *retval; 636 { 637 struct linux_sys_sigaltstack_args /* { 638 syscallarg(const struct linux_sigaltstack *) ss; 639 syscallarg(struct linux_sigaltstack *) oss; 640 } */ *uap = v; 641 struct linux_sigaltstack ss; 642 struct sigaltstack nss, oss; 643 int error; 644 645 if (SCARG(uap, ss) != NULL) { 646 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0) 647 return error; 648 linux_to_native_sigaltstack(&nss, &ss); 649 } 650 651 error = sigaltstack1(p, 652 SCARG(uap, ss) ? &nss : NULL, SCARG(uap, oss) ? &oss : NULL); 653 if (error) 654 return error; 655 656 if (SCARG(uap, oss) != NULL) { 657 native_to_linux_sigaltstack(&ss, &oss); 658 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0) 659 return error; 660 } 661 return 0; 662 } 663 #endif 664