1 /* $NetBSD: linux32_signal.c,v 1.16 2012/05/10 19:40:46 christos Exp $ */ 2 3 /*- 4 * Copyright (c) 2006 Emmanuel Dreyfus, all rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 3. All advertising materials mentioning features or use of this software 15 * must display the following acknowledgement: 16 * This product includes software developed by Emmanuel Dreyfus 17 * 4. The name of the author may not be used to endorse or promote 18 * products derived from this software without specific prior written 19 * permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE THE AUTHOR AND CONTRIBUTORS ``AS IS'' 22 * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, 23 * THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR 24 * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS 25 * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 26 * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 27 * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 28 * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 29 * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 30 * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 31 * POSSIBILITY OF SUCH DAMAGE. 32 */ 33 34 #include <sys/cdefs.h> 35 __KERNEL_RCSID(0, "$NetBSD: linux32_signal.c,v 1.16 2012/05/10 19:40:46 christos Exp $"); 36 37 #include <sys/param.h> 38 #include <sys/ucred.h> 39 #include <sys/signalvar.h> 40 #include <sys/lwp.h> 41 #include <sys/time.h> 42 #include <sys/proc.h> 43 #include <sys/wait.h> 44 45 #include <compat/netbsd32/netbsd32.h> 46 47 #include <compat/linux/common/linux_signal.h> 48 #include <compat/linux32/common/linux32_types.h> 49 #include <compat/linux32/common/linux32_signal.h> 50 #include <compat/linux32/common/linux32_siginfo.h> 51 #include <compat/linux32/linux32_syscallargs.h> 52 #include <compat/linux32/common/linux32_errno.h> 53 #include <compat/linux32/common/linux32_sched.h> 54 55 #define linux32_sigemptyset(s) memset((s), 0, sizeof(*(s))) 56 #define linux32_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \ 57 & (1 << ((n) - 1) % LINUX32__NSIG_BPW)) 58 #define linux32_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX32__NSIG_BPW] \ 59 |= (1 << ((n) - 1) % LINUX32__NSIG_BPW)) 60 61 extern const int native_to_linux32_signo[]; 62 extern const int linux32_to_native_signo[]; 63 64 #ifdef DEBUG_LINUX 65 #define DPRINTF(a) uprintf a 66 #else 67 #define DPRINTF(a) 68 #endif 69 70 void 71 linux32_to_native_sigset(sigset_t *bss, const linux32_sigset_t *lss) 72 { 73 int i, newsig; 74 75 sigemptyset(bss); 76 for (i = 1; i < LINUX32__NSIG; i++) { 77 if (linux32_sigismember(lss, i)) { 78 newsig = linux32_to_native_signo[i]; 79 if (newsig) 80 sigaddset(bss, newsig); 81 } 82 } 83 } 84 85 void 86 native_to_linux32_sigset(linux32_sigset_t *lss, const sigset_t *bss) 87 { 88 int i, newsig; 89 90 linux32_sigemptyset(lss); 91 for (i = 1; i < NSIG; i++) { 92 if (sigismember(bss, i)) { 93 newsig = native_to_linux32_signo[i]; 94 if (newsig) 95 linux32_sigaddset(lss, newsig); 96 } 97 } 98 } 99 100 void 101 native_to_linux32_siginfo(linux32_siginfo_t *lsi, const struct _ksiginfo *ksi) 102 { 103 memset(lsi, 0, sizeof(*lsi)); 104 105 lsi->lsi_signo = native_to_linux32_signo[ksi->_signo]; 106 lsi->lsi_errno = native_to_linux32_errno[ksi->_errno]; 107 lsi->lsi_code = native_to_linux32_si_code(ksi->_code); 108 109 switch (ksi->_code) { 110 case SI_NOINFO: 111 break; 112 113 case SI_USER: 114 lsi->lsi_pid = ksi->_reason._rt._pid; 115 lsi->lsi_uid = ksi->_reason._rt._uid; 116 if (lsi->lsi_signo == LINUX_SIGALRM || 117 lsi->lsi_signo >= LINUX_SIGRTMIN) 118 NETBSD32PTR32(lsi->lsi_value.sival_ptr, 119 ksi->_reason._rt._value.sival_ptr); 120 break; 121 122 case SI_TIMER: 123 case SI_QUEUE: 124 lsi->lsi_uid = ksi->_reason._rt._uid; 125 lsi->lsi_uid = ksi->_reason._rt._uid; 126 NETBSD32PTR32(lsi->lsi_value.sival_ptr, 127 ksi->_reason._rt._value.sival_ptr); 128 break; 129 130 case SI_ASYNCIO: 131 case SI_MESGQ: 132 NETBSD32PTR32(lsi->lsi_value.sival_ptr, 133 ksi->_reason._rt._value.sival_ptr); 134 break; 135 136 default: 137 switch (ksi->_signo) { 138 case SIGCHLD: 139 lsi->lsi_uid = ksi->_reason._child._uid; 140 lsi->lsi_pid = ksi->_reason._child._pid; 141 lsi->lsi_status = native_to_linux32_si_status( 142 ksi->_code, ksi->_reason._child._status); 143 lsi->lsi_utime = ksi->_reason._child._utime; 144 lsi->lsi_stime = ksi->_reason._child._stime; 145 break; 146 147 case SIGILL: 148 case SIGFPE: 149 case SIGSEGV: 150 case SIGBUS: 151 case SIGTRAP: 152 NETBSD32PTR32(lsi->lsi_addr, ksi->_reason._fault._addr); 153 break; 154 155 case SIGIO: 156 lsi->lsi_fd = ksi->_reason._poll._fd; 157 lsi->lsi_band = ksi->_reason._poll._band; 158 break; 159 default: 160 break; 161 } 162 } 163 } 164 165 unsigned int 166 native_to_linux32_sigflags(const int bsf) 167 { 168 unsigned int lsf = 0; 169 if ((bsf & SA_NOCLDSTOP) != 0) 170 lsf |= LINUX32_SA_NOCLDSTOP; 171 if ((bsf & SA_NOCLDWAIT) != 0) 172 lsf |= LINUX32_SA_NOCLDWAIT; 173 if ((bsf & SA_ONSTACK) != 0) 174 lsf |= LINUX32_SA_ONSTACK; 175 if ((bsf & SA_RESTART) != 0) 176 lsf |= LINUX32_SA_RESTART; 177 if ((bsf & SA_NODEFER) != 0) 178 lsf |= LINUX32_SA_NOMASK; 179 if ((bsf & SA_RESETHAND) != 0) 180 lsf |= LINUX32_SA_ONESHOT; 181 if ((bsf & SA_SIGINFO) != 0) 182 lsf |= LINUX32_SA_SIGINFO; 183 return lsf; 184 } 185 186 int 187 linux32_to_native_sigflags(const unsigned long lsf) 188 { 189 int bsf = 0; 190 if ((lsf & LINUX32_SA_NOCLDSTOP) != 0) 191 bsf |= SA_NOCLDSTOP; 192 if ((lsf & LINUX32_SA_NOCLDWAIT) != 0) 193 bsf |= SA_NOCLDWAIT; 194 if ((lsf & LINUX32_SA_ONSTACK) != 0) 195 bsf |= SA_ONSTACK; 196 if ((lsf & LINUX32_SA_RESTART) != 0) 197 bsf |= SA_RESTART; 198 if ((lsf & LINUX32_SA_ONESHOT) != 0) 199 bsf |= SA_RESETHAND; 200 if ((lsf & LINUX32_SA_NOMASK) != 0) 201 bsf |= SA_NODEFER; 202 if ((lsf & LINUX32_SA_SIGINFO) != 0) 203 bsf |= SA_SIGINFO; 204 if ((lsf & ~LINUX32_SA_ALLBITS) != 0) { 205 #ifdef DEBUG_LINUX 206 printf("linux32_old_to_native_sigflags: " 207 "%lx extra bits ignored\n", lsf); 208 #endif 209 } 210 return bsf; 211 } 212 213 void 214 linux32_to_native_sigaction(struct sigaction *bsa, const struct linux32_sigaction *lsa) 215 { 216 bsa->sa_handler = NETBSD32PTR64(lsa->linux_sa_handler); 217 linux32_to_native_sigset(&bsa->sa_mask, &lsa->linux_sa_mask); 218 bsa->sa_flags = linux32_to_native_sigflags(lsa->linux_sa_flags); 219 } 220 221 void 222 native_to_linux32_sigaction(struct linux32_sigaction *lsa, const struct sigaction *bsa) 223 { 224 NETBSD32PTR32(lsa->linux_sa_handler, bsa->sa_handler); 225 native_to_linux32_sigset(&lsa->linux_sa_mask, &bsa->sa_mask); 226 lsa->linux_sa_flags = native_to_linux32_sigflags(bsa->sa_flags); 227 NETBSD32PTR32(lsa->linux_sa_restorer, NULL); 228 } 229 230 void 231 native_to_linux32_sigaltstack(struct linux32_sigaltstack *lss, const struct sigaltstack *bss) 232 { 233 NETBSD32PTR32(lss->ss_sp, bss->ss_sp); 234 lss->ss_size = bss->ss_size; 235 if (bss->ss_flags & SS_ONSTACK) 236 lss->ss_flags = LINUX32_SS_ONSTACK; 237 else if (bss->ss_flags & SS_DISABLE) 238 lss->ss_flags = LINUX32_SS_DISABLE; 239 else 240 lss->ss_flags = 0; 241 } 242 243 244 void 245 native_to_linux32_old_sigset(linux32_old_sigset_t *lss, const sigset_t *bss) 246 { 247 linux32_sigset_t lsnew; 248 249 native_to_linux32_sigset(&lsnew, bss); 250 251 /* convert new sigset to old sigset */ 252 *lss = lsnew.sig[0]; 253 } 254 255 void 256 linux32_old_to_native_sigset(sigset_t *bss, const linux32_old_sigset_t *lss) 257 { 258 linux32_sigset_t ls; 259 260 memset(&ls, 0, sizeof(ls)); 261 ls.sig[0] = *lss; 262 263 linux32_to_native_sigset(bss, &ls); 264 } 265 266 int 267 linux32_sys_rt_sigaction(struct lwp *l, const struct linux32_sys_rt_sigaction_args *uap, register_t *retval) 268 { 269 /* { 270 syscallarg(int) signum; 271 syscallarg(const linux32_sigactionp_t) nsa; 272 syscallarg(linux32_sigactionp_t) osa; 273 syscallarg(netbsd32_size_t) sigsetsize; 274 } */ 275 struct linux32_sigaction nls32; 276 struct linux32_sigaction ols32; 277 struct sigaction ns; 278 struct sigaction os; 279 int error; 280 int sig; 281 int vers = 0; 282 void *tramp = NULL; 283 284 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) { 285 DPRINTF(("rt_sigaction: Inconsistent sigsetsize %u %zu\n", 286 SCARG(uap, sigsetsize), sizeof(linux32_sigset_t))); 287 return EINVAL; 288 } 289 290 if (SCARG_P32(uap, nsa) != NULL) { 291 if ((error = copyin(SCARG_P32(uap, nsa), 292 &nls32, sizeof(nls32))) != 0) { 293 DPRINTF(("rt_sigaction: Copyin %d\n", error)); 294 return error; 295 } 296 linux32_to_native_sigaction(&ns, &nls32); 297 } 298 299 sig = SCARG(uap, signum); 300 if (sig < 0 || sig >= LINUX32__NSIG) { 301 DPRINTF(("rt_sigaction: Bad signal number %d %d\n", 302 sig, LINUX32__NSIG)); 303 return EINVAL; 304 } 305 if (sig > 0 && !linux32_to_native_signo[sig]) { 306 /* unknown signal... */ 307 os.sa_handler = SIG_IGN; 308 sigemptyset(&os.sa_mask); 309 os.sa_flags = 0; 310 } else { 311 if ((error = sigaction1(l, 312 linux32_to_native_signo[sig], 313 SCARG_P32(uap, nsa) ? &ns : NULL, 314 SCARG_P32(uap, osa) ? &os : NULL, 315 tramp, vers)) != 0) { 316 DPRINTF(("rt_sigaction: sigaction %d\n", error)); 317 return error; 318 } 319 } 320 321 if (SCARG_P32(uap, osa) != NULL) { 322 native_to_linux32_sigaction(&ols32, &os); 323 324 if ((error = copyout(&ols32, SCARG_P32(uap, osa), 325 sizeof(ols32))) != 0) { 326 DPRINTF(("rt_sigaction: Copyout %d\n", error)); 327 return error; 328 } 329 } 330 331 return 0; 332 } 333 334 int 335 linux32_sys_rt_sigprocmask(struct lwp *l, const struct linux32_sys_rt_sigprocmask_args *uap, register_t *retval) 336 { 337 /* { 338 syscallarg(int) how; 339 syscallarg(const linux32_sigsetp_t) set; 340 syscallarg(linux32_sigsetp_t) oset; 341 syscallarg(netbsd32_size_t) sigsetsize; 342 } */ 343 struct proc *p = l->l_proc; 344 linux32_sigset_t nls32, ols32; 345 sigset_t ns, os; 346 int error; 347 int how; 348 349 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) 350 return EINVAL; 351 352 switch (SCARG(uap, how)) { 353 case LINUX32_SIG_BLOCK: 354 how = SIG_BLOCK; 355 break; 356 case LINUX32_SIG_UNBLOCK: 357 how = SIG_UNBLOCK; 358 break; 359 case LINUX32_SIG_SETMASK: 360 how = SIG_SETMASK; 361 break; 362 default: 363 return EINVAL; 364 break; 365 } 366 367 if (SCARG_P32(uap, set) != NULL) { 368 if ((error = copyin(SCARG_P32(uap, set), 369 &nls32, sizeof(nls32))) != 0) 370 return error; 371 linux32_to_native_sigset(&ns, &nls32); 372 } 373 374 mutex_enter(p->p_lock); 375 error = sigprocmask1(l, how, 376 SCARG_P32(uap, set) ? &ns : NULL, 377 SCARG_P32(uap, oset) ? &os : NULL); 378 mutex_exit(p->p_lock); 379 380 if (error != 0) 381 return error; 382 383 if (SCARG_P32(uap, oset) != NULL) { 384 native_to_linux32_sigset(&ols32, &os); 385 if ((error = copyout(&ols32, 386 SCARG_P32(uap, oset), sizeof(ols32))) != 0) 387 return error; 388 } 389 390 return 0; 391 } 392 393 int 394 linux32_sys_kill(struct lwp *l, const struct linux32_sys_kill_args *uap, register_t *retval) 395 { 396 /* { 397 syscallarg(int) pid; 398 syscallarg(int) signum; 399 } */ 400 401 struct sys_kill_args ka; 402 int sig; 403 404 SCARG(&ka, pid) = SCARG(uap, pid); 405 sig = SCARG(uap, signum); 406 if (sig < 0 || sig >= LINUX32__NSIG) 407 return (EINVAL); 408 SCARG(&ka, signum) = linux32_to_native_signo[sig]; 409 return sys_kill(l, &ka, retval); 410 } 411 412 int 413 linux32_sys_rt_sigsuspend(struct lwp *l, const struct linux32_sys_rt_sigsuspend_args *uap, register_t *retval) 414 { 415 /* { 416 syscallarg(linux32_sigsetp_t) unewset; 417 syscallarg(netbsd32_size_t) sigsetsize; 418 } */ 419 linux32_sigset_t lss; 420 sigset_t bss; 421 int error; 422 423 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) 424 return EINVAL; 425 426 if ((error = copyin(SCARG_P32(uap, unewset), 427 &lss, sizeof(linux32_sigset_t))) != 0) 428 return error; 429 430 linux32_to_native_sigset(&bss, &lss); 431 432 return sigsuspend1(l, &bss); 433 } 434 435 static int 436 fetchss(const void *u, void *s, size_t len) 437 { 438 int error; 439 linux32_sigset_t lss; 440 441 if ((error = copyin(u, &lss, sizeof(lss))) != 0) 442 return error; 443 444 linux32_to_native_sigset(s, &lss); 445 return 0; 446 } 447 448 static int 449 fetchts(const void *u, void *s, size_t len) 450 { 451 int error; 452 struct linux32_timespec lts; 453 454 if ((error = copyin(u, <s, sizeof(lts))) != 0) 455 return error; 456 457 linux32_to_native_timespec(s, <s); 458 return 0; 459 } 460 461 static int 462 fakestorets(const void *u, void *s, size_t len) 463 { 464 /* Do nothing, sigtimedwait does not alter timeout like ours */ 465 return 0; 466 } 467 468 static int 469 storeinfo(const void *s, void *u, size_t len) 470 { 471 linux32_siginfo_t lsi; 472 473 474 native_to_linux32_siginfo(&lsi, &((const siginfo_t *)s)->_info); 475 return copyout(&lsi, u, sizeof(lsi)); 476 } 477 478 int 479 linux32_sys_rt_sigtimedwait(struct lwp *l, 480 const struct linux32_sys_rt_sigtimedwait_args *uap, register_t *retval) 481 { 482 /* { 483 syscallarg(const linux32_sigset_t *) set; 484 syscallarg(linux32_siginfo_t *) info); 485 syscallarg(const struct linux32_timespec *) timeout; 486 } */ 487 struct sys_____sigtimedwait50_args ap; 488 489 SCARG(&ap, set) = SCARG_P32(uap, set); 490 SCARG(&ap, info) = SCARG_P32(uap, info); 491 SCARG(&ap, timeout) = SCARG_P32(uap, timeout); 492 493 return sigtimedwait1(l, &ap, 494 retval, fetchss, storeinfo, fetchts, fakestorets); 495 } 496 497 int 498 linux32_sys_signal(struct lwp *l, const struct linux32_sys_signal_args *uap, register_t *retval) 499 { 500 /* { 501 syscallarg(int) signum; 502 syscallarg(linux32_handler_t) handler; 503 } */ 504 struct sigaction nbsa, obsa; 505 int error, sig; 506 507 *retval = -1; 508 509 sig = SCARG(uap, signum); 510 if (sig < 0 || sig >= LINUX32__NSIG) 511 return EINVAL; 512 513 nbsa.sa_handler = SCARG_P32(uap, handler); 514 sigemptyset(&nbsa.sa_mask); 515 nbsa.sa_flags = SA_RESETHAND | SA_NODEFER; 516 517 if ((error = sigaction1(l, linux32_to_native_signo[sig], 518 &nbsa, &obsa, NULL, 0)) != 0) 519 return error; 520 521 *retval = (int)(long)obsa.sa_handler; 522 return 0; 523 } 524 525 int 526 linux32_sys_rt_sigpending(struct lwp *l, const struct linux32_sys_rt_sigpending_args *uap, register_t *retval) 527 { 528 /* { 529 syscallarg(linux32_sigsetp_t) set; 530 syscallarg(netbsd32_size_t) sigsetsize; 531 } */ 532 sigset_t bss; 533 linux32_sigset_t lss; 534 535 if (SCARG(uap, sigsetsize) != sizeof(linux32_sigset_t)) 536 return EINVAL; 537 538 sigpending1(l, &bss); 539 native_to_linux32_sigset(&lss, &bss); 540 return copyout(&lss, SCARG_P32(uap, set), sizeof(lss)); 541 } 542 543 int 544 linux32_sys_siggetmask(struct lwp *l, const void *v, register_t *retval) 545 { 546 struct proc *p = l->l_proc; 547 sigset_t bss; 548 linux32_old_sigset_t lss; 549 int error; 550 551 mutex_enter(p->p_lock); 552 error = sigprocmask1(l, SIG_SETMASK, 0, &bss); 553 mutex_exit(p->p_lock); 554 if (error) 555 return error; 556 native_to_linux32_old_sigset(&lss, &bss); 557 *retval = lss; 558 return 0; 559 } 560 561 int 562 linux32_sys_sigsetmask(struct lwp *l, const struct linux32_sys_sigsetmask_args *uap, register_t *retval) 563 { 564 /* { 565 syscallarg(linux32_old_sigset_t) mask; 566 } */ 567 sigset_t nbss, obss; 568 linux32_old_sigset_t nlss, olss; 569 struct proc *p = l->l_proc; 570 int error; 571 572 nlss = SCARG(uap, mask); 573 linux32_old_to_native_sigset(&nbss, &nlss); 574 mutex_enter(p->p_lock); 575 error = sigprocmask1(l, SIG_SETMASK, &nbss, &obss); 576 mutex_exit(p->p_lock); 577 if (error) 578 return error; 579 native_to_linux32_old_sigset(&olss, &obss); 580 *retval = olss; 581 return 0; 582 } 583 584 int 585 linux32_sys_rt_queueinfo(struct lwp *l, const struct linux32_sys_rt_queueinfo_args *uap, register_t *retval) 586 { 587 /* 588 syscallarg(int) pid; 589 syscallarg(int) sig; 590 syscallarg(linux32_siginfop_t) uinfo; 591 */ 592 int error; 593 linux32_siginfo_t info; 594 595 error = copyin(SCARG_P32(uap, uinfo), &info, sizeof(info)); 596 if (error) 597 return error; 598 if (info.lsi_code >= 0) 599 return EPERM; 600 601 /* XXX To really implement this we need to */ 602 /* XXX keep a list of queued signals somewhere. */ 603 return linux32_sys_kill(l, (const void *)uap, retval); 604 } 605 606 int 607 native_to_linux32_si_code(int code) 608 { 609 int si_codes[] = { 610 LINUX32_SI_USER, LINUX32_SI_QUEUE, LINUX32_SI_TIMER, 611 LINUX32_SI_ASYNCIO, LINUX32_SI_MESGQ, LINUX32_SI_TKILL /* SI_LWP */ 612 }; 613 614 if (code <= 0 && -code < __arraycount(si_codes)) 615 return si_codes[-code]; 616 617 return code; 618 } 619 620 int 621 native_to_linux32_si_status(int code, int status) 622 { 623 int sts; 624 625 switch (code) { 626 case CLD_CONTINUED: 627 sts = LINUX_SIGCONT; 628 break; 629 case CLD_EXITED: 630 sts = WEXITSTATUS(status); 631 break; 632 case CLD_STOPPED: 633 case CLD_TRAPPED: 634 case CLD_DUMPED: 635 case CLD_KILLED: 636 default: 637 sts = native_to_linux32_signo[WTERMSIG(status)]; 638 break; 639 } 640 641 return sts; 642 } 643