1 /* $NetBSD: linux_signal.c,v 1.41 2003/07/03 21:22:32 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.41 2003/07/03 21:22:32 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/sa.h> 74 #include <sys/syscallargs.h> 75 76 #include <compat/linux/common/linux_types.h> 77 #include <compat/linux/common/linux_signal.h> 78 #include <compat/linux/common/linux_siginfo.h> 79 #include <compat/linux/common/linux_util.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 & (1 << ((n) - 1) % LINUX__NSIG_BPW)) 87 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 88 |= (1 << ((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(bss, lss, extra) 105 sigset_t *bss; 106 const linux_old_sigset_t *lss; 107 const unsigned long *extra; 108 { 109 linux_sigset_t lsnew; 110 111 /* convert old sigset to new sigset */ 112 linux_sigemptyset(&lsnew); 113 lsnew.sig[0] = *lss; 114 if (extra) 115 memcpy(&lsnew.sig[1], extra, 116 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 117 118 linux_to_native_sigset(bss, &lsnew); 119 } 120 121 void 122 native_to_linux_old_extra_sigset(lss, extra, bss) 123 linux_old_sigset_t *lss; 124 unsigned long *extra; 125 const sigset_t *bss; 126 { 127 linux_sigset_t lsnew; 128 129 native_to_linux_sigset(&lsnew, bss); 130 131 /* convert new sigset to old sigset */ 132 *lss = lsnew.sig[0]; 133 if (extra) 134 memcpy(extra, &lsnew.sig[1], 135 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 136 } 137 #endif 138 139 void 140 linux_to_native_sigset(bss, lss) 141 sigset_t *bss; 142 const linux_sigset_t *lss; 143 { 144 int i, newsig; 145 146 sigemptyset(bss); 147 for (i = 1; i < LINUX__NSIG; i++) { 148 if (linux_sigismember(lss, i)) { 149 newsig = linux_to_native_signo[i]; 150 if (newsig) 151 sigaddset(bss, newsig); 152 } 153 } 154 } 155 156 void 157 native_to_linux_sigset(lss, bss) 158 linux_sigset_t *lss; 159 const sigset_t *bss; 160 { 161 int i, newsig; 162 163 linux_sigemptyset(lss); 164 for (i = 1; i < NSIG; i++) { 165 if (sigismember(bss, i)) { 166 newsig = native_to_linux_signo[i]; 167 if (newsig) 168 linux_sigaddset(lss, newsig); 169 } 170 } 171 } 172 173 unsigned int 174 native_to_linux_sigflags(bsf) 175 const int bsf; 176 { 177 unsigned int lsf = 0; 178 if ((bsf & SA_NOCLDSTOP) != 0) 179 lsf |= LINUX_SA_NOCLDSTOP; 180 if ((bsf & SA_NOCLDWAIT) != 0) 181 lsf |= LINUX_SA_NOCLDWAIT; 182 if ((bsf & SA_ONSTACK) != 0) 183 lsf |= LINUX_SA_ONSTACK; 184 if ((bsf & SA_RESTART) != 0) 185 lsf |= LINUX_SA_RESTART; 186 if ((bsf & SA_NODEFER) != 0) 187 lsf |= LINUX_SA_NOMASK; 188 if ((bsf & SA_RESETHAND) != 0) 189 lsf |= LINUX_SA_ONESHOT; 190 if ((bsf & SA_SIGINFO) != 0) 191 lsf |= LINUX_SA_SIGINFO; 192 return lsf; 193 } 194 195 int 196 linux_to_native_sigflags(lsf) 197 const unsigned long lsf; 198 { 199 int bsf = 0; 200 if ((lsf & LINUX_SA_NOCLDSTOP) != 0) 201 bsf |= SA_NOCLDSTOP; 202 if ((lsf & LINUX_SA_NOCLDWAIT) != 0) 203 bsf |= SA_NOCLDWAIT; 204 if ((lsf & LINUX_SA_ONSTACK) != 0) 205 bsf |= SA_ONSTACK; 206 if ((lsf & LINUX_SA_RESTART) != 0) 207 bsf |= SA_RESTART; 208 if ((lsf & LINUX_SA_ONESHOT) != 0) 209 bsf |= SA_RESETHAND; 210 if ((lsf & LINUX_SA_NOMASK) != 0) 211 bsf |= SA_NODEFER; 212 if ((lsf & LINUX_SA_SIGINFO) != 0) 213 bsf |= SA_SIGINFO; 214 if ((lsf & ~LINUX_SA_ALLBITS) != 0) 215 DPRINTF(("linux_old_to_native_sigflags: " 216 "%lx extra bits ignored\n", lsf)); 217 return bsf; 218 } 219 220 /* 221 * Convert between Linux and BSD sigaction structures. Linux sometimes 222 * has one extra field (sa_restorer) which we don't support. 223 */ 224 void 225 linux_old_to_native_sigaction(bsa, lsa) 226 struct sigaction *bsa; 227 const struct linux_old_sigaction *lsa; 228 { 229 bsa->sa_handler = lsa->linux_sa_handler; 230 linux_old_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 231 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 232 #ifndef __alpha__ 233 /* 234 * XXX: On the alpha sa_restorer is elsewhere. 235 */ 236 if (lsa->linux_sa_restorer != NULL) 237 DPRINTF(("linux_old_to_native_sigaction: " 238 "sa_restorer ignored\n")); 239 #endif 240 } 241 242 void 243 native_to_linux_old_sigaction(lsa, bsa) 244 struct linux_old_sigaction *lsa; 245 const struct sigaction *bsa; 246 { 247 lsa->linux_sa_handler = bsa->sa_handler; 248 native_to_linux_old_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 249 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 250 #ifndef __alpha__ 251 lsa->linux_sa_restorer = NULL; 252 #endif 253 } 254 255 /* ...and the new sigaction conversion funcs. */ 256 void 257 linux_to_native_sigaction(bsa, lsa) 258 struct sigaction *bsa; 259 const struct linux_sigaction *lsa; 260 { 261 bsa->sa_handler = lsa->linux_sa_handler; 262 linux_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 263 bsa->sa_flags = linux_to_native_sigflags(lsa->linux_sa_flags); 264 #ifndef __alpha__ 265 if (lsa->linux_sa_restorer != 0) 266 DPRINTF(("linux_to_native_sigaction: sa_restorer ignored\n")); 267 #endif 268 } 269 270 void 271 native_to_linux_sigaction(lsa, bsa) 272 struct linux_sigaction *lsa; 273 const struct sigaction *bsa; 274 { 275 lsa->linux_sa_handler = bsa->sa_handler; 276 native_to_linux_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 277 lsa->linux_sa_flags = native_to_linux_sigflags(bsa->sa_flags); 278 #ifndef __alpha__ 279 lsa->linux_sa_restorer = NULL; 280 #endif 281 } 282 283 /* ----------------------------------------------------------------------- */ 284 285 /* 286 * The Linux sigaction() system call. Do the usual conversions, 287 * and just call sigaction(). Some flags and values are silently 288 * ignored (see above). 289 */ 290 int 291 linux_sys_rt_sigaction(l, v, retval) 292 struct lwp *l; 293 void *v; 294 register_t *retval; 295 { 296 struct linux_sys_rt_sigaction_args /* { 297 syscallarg(int) signum; 298 syscallarg(const struct linux_sigaction *) nsa; 299 syscallarg(struct linux_sigaction *) osa; 300 syscallarg(size_t) sigsetsize; 301 } */ *uap = v; 302 struct proc *p = l->l_proc; 303 struct linux_sigaction nlsa, olsa; 304 struct sigaction nbsa, obsa; 305 int error, sig; 306 307 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 308 return (EINVAL); 309 310 if (SCARG(uap, nsa)) { 311 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 312 if (error) 313 return (error); 314 linux_to_native_sigaction(&nbsa, &nlsa); 315 } 316 sig = SCARG(uap, signum); 317 if (sig < 0 || sig >= LINUX__NSIG) 318 return (EINVAL); 319 if (sig > 0 && !linux_to_native_signo[sig]) { 320 /* Pretend that we did something useful for unknown signals. */ 321 obsa.sa_handler = SIG_IGN; 322 sigemptyset(&obsa.sa_mask); 323 obsa.sa_flags = 0; 324 } else { 325 error = sigaction1(p, linux_to_native_signo[sig], 326 SCARG(uap, nsa) ? &nbsa : NULL, 327 SCARG(uap, osa) ? &obsa : NULL, 328 NULL, 0); 329 if (error) 330 return (error); 331 } 332 if (SCARG(uap, osa)) { 333 native_to_linux_sigaction(&olsa, &obsa); 334 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 335 if (error) 336 return (error); 337 } 338 return (0); 339 } 340 341 int 342 linux_sigprocmask1(p, how, set, oset) 343 struct proc *p; 344 int how; 345 const linux_old_sigset_t *set; 346 linux_old_sigset_t *oset; 347 { 348 linux_old_sigset_t nlss, olss; 349 sigset_t nbss, obss; 350 int error; 351 352 switch (how) { 353 case LINUX_SIG_BLOCK: 354 how = SIG_BLOCK; 355 break; 356 case LINUX_SIG_UNBLOCK: 357 how = SIG_UNBLOCK; 358 break; 359 case LINUX_SIG_SETMASK: 360 how = SIG_SETMASK; 361 break; 362 default: 363 return (EINVAL); 364 } 365 366 if (set) { 367 error = copyin(set, &nlss, sizeof(nlss)); 368 if (error) 369 return (error); 370 linux_old_to_native_sigset(&nbss, &nlss); 371 } 372 error = sigprocmask1(p, how, 373 set ? &nbss : NULL, oset ? &obss : NULL); 374 if (error) 375 return (error); 376 if (oset) { 377 native_to_linux_old_sigset(&olss, &obss); 378 error = copyout(&olss, oset, sizeof(olss)); 379 if (error) 380 return (error); 381 } 382 return (error); 383 } 384 385 int 386 linux_sys_rt_sigprocmask(l, v, retval) 387 struct lwp *l; 388 void *v; 389 register_t *retval; 390 { 391 struct linux_sys_rt_sigprocmask_args /* { 392 syscallarg(int) how; 393 syscallarg(const linux_sigset_t *) set; 394 syscallarg(linux_sigset_t *) oset; 395 syscallarg(size_t) sigsetsize; 396 } */ *uap = v; 397 struct proc *p = l->l_proc; 398 linux_sigset_t nlss, olss, *oset; 399 const linux_sigset_t *set; 400 sigset_t nbss, obss; 401 int error, how; 402 403 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 404 return (EINVAL); 405 406 switch (SCARG(uap, how)) { 407 case LINUX_SIG_BLOCK: 408 how = SIG_BLOCK; 409 break; 410 case LINUX_SIG_UNBLOCK: 411 how = SIG_UNBLOCK; 412 break; 413 case LINUX_SIG_SETMASK: 414 how = SIG_SETMASK; 415 break; 416 default: 417 return (EINVAL); 418 } 419 420 set = SCARG(uap, set); 421 oset = SCARG(uap, oset); 422 423 if (set) { 424 error = copyin(set, &nlss, sizeof(nlss)); 425 if (error) 426 return (error); 427 linux_to_native_sigset(&nbss, &nlss); 428 } 429 error = sigprocmask1(p, how, 430 set ? &nbss : NULL, oset ? &obss : NULL); 431 if (!error && oset) { 432 native_to_linux_sigset(&olss, &obss); 433 error = copyout(&olss, oset, sizeof(olss)); 434 } 435 return (error); 436 } 437 438 int 439 linux_sys_rt_sigpending(l, v, retval) 440 struct lwp *l; 441 void *v; 442 register_t *retval; 443 { 444 struct linux_sys_rt_sigpending_args /* { 445 syscallarg(linux_sigset_t *) set; 446 syscallarg(size_t) sigsetsize; 447 } */ *uap = v; 448 struct proc *p = l->l_proc; 449 sigset_t bss; 450 linux_sigset_t lss; 451 452 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 453 return (EINVAL); 454 455 sigpending1(p, &bss); 456 native_to_linux_sigset(&lss, &bss); 457 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 458 } 459 460 int 461 linux_sys_sigpending(l, v, retval) 462 struct lwp *l; 463 void *v; 464 register_t *retval; 465 { 466 struct linux_sys_sigpending_args /* { 467 syscallarg(linux_old_sigset_t *) mask; 468 } */ *uap = v; 469 struct proc *p = l->l_proc; 470 sigset_t bss; 471 linux_old_sigset_t lss; 472 473 sigpending1(p, &bss); 474 native_to_linux_old_sigset(&lss, &bss); 475 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 476 } 477 478 int 479 linux_sys_sigsuspend(l, v, retval) 480 struct lwp *l; 481 void *v; 482 register_t *retval; 483 { 484 struct linux_sys_sigsuspend_args /* { 485 syscallarg(caddr_t) restart; 486 syscallarg(int) oldmask; 487 syscallarg(int) mask; 488 } */ *uap = v; 489 struct proc *p = l->l_proc; 490 linux_old_sigset_t lss; 491 sigset_t bss; 492 493 lss = SCARG(uap, mask); 494 linux_old_to_native_sigset(&bss, &lss); 495 return (sigsuspend1(p, &bss)); 496 } 497 int 498 linux_sys_rt_sigsuspend(l, v, retval) 499 struct lwp *l; 500 void *v; 501 register_t *retval; 502 { 503 struct linux_sys_rt_sigsuspend_args /* { 504 syscallarg(linux_sigset_t *) unewset; 505 syscallarg(size_t) sigsetsize; 506 } */ *uap = v; 507 struct proc *p = l->l_proc; 508 linux_sigset_t lss; 509 sigset_t bss; 510 int error; 511 512 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 513 return (EINVAL); 514 515 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 516 if (error) 517 return (error); 518 519 linux_to_native_sigset(&bss, &lss); 520 521 return (sigsuspend1(p, &bss)); 522 } 523 524 /* 525 * Once more: only a signal conversion is needed. 526 * Note: also used as sys_rt_queueinfo. The info field is ignored. 527 */ 528 int 529 linux_sys_rt_queueinfo(l, v, retval) 530 struct lwp *l; 531 void *v; 532 register_t *retval; 533 { 534 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */ 535 #if 0 536 struct linux_sys_rt_queueinfo_args /* { 537 syscallarg(int) pid; 538 syscallarg(int) signum; 539 syscallarg(siginfo_t *) uinfo; 540 } */ *uap = v; 541 #endif 542 543 /* XXX To really implement this we need to */ 544 /* XXX keep a list of queued signals somewhere. */ 545 return (linux_sys_kill(l, v, retval)); 546 } 547 548 int 549 linux_sys_kill(l, v, retval) 550 struct lwp *l; 551 void *v; 552 register_t *retval; 553 { 554 struct linux_sys_kill_args /* { 555 syscallarg(int) pid; 556 syscallarg(int) signum; 557 } */ *uap = v; 558 559 struct sys_kill_args ka; 560 int sig; 561 562 SCARG(&ka, pid) = SCARG(uap, pid); 563 sig = SCARG(uap, signum); 564 if (sig < 0 || sig >= LINUX__NSIG) 565 return (EINVAL); 566 SCARG(&ka, signum) = linux_to_native_signo[sig]; 567 return sys_kill(l, &ka, retval); 568 } 569 570 #ifdef LINUX_SS_ONSTACK 571 static void linux_to_native_sigaltstack __P((struct sigaltstack *, 572 const struct linux_sigaltstack *)); 573 574 static void 575 linux_to_native_sigaltstack(bss, lss) 576 struct sigaltstack *bss; 577 const struct linux_sigaltstack *lss; 578 { 579 bss->ss_sp = lss->ss_sp; 580 bss->ss_size = lss->ss_size; 581 if (lss->ss_flags & LINUX_SS_ONSTACK) 582 bss->ss_flags = SS_ONSTACK; 583 else if (lss->ss_flags & LINUX_SS_DISABLE) 584 bss->ss_flags = SS_DISABLE; 585 else 586 bss->ss_flags = 0; 587 } 588 589 void 590 native_to_linux_sigaltstack(lss, bss) 591 struct linux_sigaltstack *lss; 592 const struct sigaltstack *bss; 593 { 594 lss->ss_sp = bss->ss_sp; 595 lss->ss_size = bss->ss_size; 596 if (bss->ss_flags & SS_ONSTACK) 597 lss->ss_flags = LINUX_SS_ONSTACK; 598 else if (bss->ss_flags & SS_DISABLE) 599 lss->ss_flags = LINUX_SS_DISABLE; 600 else 601 lss->ss_flags = 0; 602 } 603 604 int 605 linux_sys_sigaltstack(l, v, retval) 606 struct lwp *l; 607 void *v; 608 register_t *retval; 609 { 610 struct linux_sys_sigaltstack_args /* { 611 syscallarg(const struct linux_sigaltstack *) ss; 612 syscallarg(struct linux_sigaltstack *) oss; 613 } */ *uap = v; 614 struct proc *p = l->l_proc; 615 struct linux_sigaltstack ss; 616 struct sigaltstack nss, oss; 617 int error; 618 619 if (SCARG(uap, ss) != NULL) { 620 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0) 621 return error; 622 linux_to_native_sigaltstack(&nss, &ss); 623 } 624 625 error = sigaltstack1(p, 626 SCARG(uap, ss) ? &nss : NULL, SCARG(uap, oss) ? &oss : NULL); 627 if (error) 628 return error; 629 630 if (SCARG(uap, oss) != NULL) { 631 native_to_linux_sigaltstack(&ss, &oss); 632 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0) 633 return error; 634 } 635 return 0; 636 } 637 #endif 638