1 /* $NetBSD: linux_signal.c,v 1.24 1999/10/04 17:46:37 fvdl 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 #define COMPAT_LINUX 1 57 58 #include <sys/param.h> 59 #include <sys/systm.h> 60 #include <sys/namei.h> 61 #include <sys/proc.h> 62 #include <sys/filedesc.h> 63 #include <sys/ioctl.h> 64 #include <sys/mount.h> 65 #include <sys/kernel.h> 66 #include <sys/signal.h> 67 #include <sys/signalvar.h> 68 #include <sys/malloc.h> 69 70 #include <sys/syscallargs.h> 71 72 #include <compat/linux/common/linux_types.h> 73 #include <compat/linux/common/linux_signal.h> 74 #include <compat/linux/common/linux_siginfo.h> 75 #include <compat/linux/common/linux_util.h> 76 77 #include <compat/linux/linux_syscallargs.h> 78 79 /* Locally used defines (in bsd<->linux conversion functions): */ 80 #define linux_sigemptyset(s) memset((s), 0, sizeof(*(s))) 81 #define linux_sigismember(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 82 & (1 << ((n) - 1) % LINUX__NSIG_BPW)) 83 #define linux_sigaddset(s, n) ((s)->sig[((n) - 1) / LINUX__NSIG_BPW] \ 84 |= (1 << ((n) - 1) % LINUX__NSIG_BPW)) 85 86 /* Note: linux_to_native_sig[] is in <arch>/linux_sigarray.c */ 87 int native_to_linux_sig[NSIG] = { 88 0, 89 LINUX_SIGHUP, 90 LINUX_SIGINT, 91 LINUX_SIGQUIT, 92 LINUX_SIGILL, 93 LINUX_SIGTRAP, 94 LINUX_SIGABRT, 95 0, /* SIGEMT */ 96 LINUX_SIGFPE, 97 LINUX_SIGKILL, 98 LINUX_SIGBUS, 99 LINUX_SIGSEGV, 100 0, /* SIGSYS */ 101 LINUX_SIGPIPE, 102 LINUX_SIGALRM, 103 LINUX_SIGTERM, 104 LINUX_SIGURG, 105 LINUX_SIGSTOP, 106 LINUX_SIGTSTP, 107 LINUX_SIGCONT, 108 LINUX_SIGCHLD, 109 LINUX_SIGTTIN, 110 LINUX_SIGTTOU, 111 LINUX_SIGIO, 112 LINUX_SIGXCPU, 113 LINUX_SIGXFSZ, 114 LINUX_SIGVTALRM, 115 LINUX_SIGPROF, 116 LINUX_SIGWINCH, 117 0, /* SIGINFO */ 118 LINUX_SIGUSR1, 119 LINUX_SIGUSR2, 120 LINUX_SIGPWR, 121 }; 122 123 /* 124 * Convert between Linux and BSD signal sets. 125 */ 126 #if LINUX__NSIG_WORDS > 1 127 void 128 linux_old_extra_to_native_sigset(lss, extra, bss) 129 const linux_old_sigset_t *lss; 130 const unsigned long *extra; 131 sigset_t *bss; 132 { 133 linux_sigset_t lsnew; 134 135 /* convert old sigset to new sigset */ 136 linux_sigemptyset(&lsnew); 137 lsnew.sig[0] = *lss; 138 if (extra) 139 bcopy(extra, &lsnew.sig[1], 140 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 141 142 linux_to_native_sigset(&lsnew, bss); 143 } 144 145 void 146 native_to_linux_old_extra_sigset(bss, lss, extra) 147 const sigset_t *bss; 148 linux_old_sigset_t *lss; 149 unsigned long *extra; 150 { 151 linux_sigset_t lsnew; 152 153 native_to_linux_sigset(bss, &lsnew); 154 155 /* convert new sigset to old sigset */ 156 *lss = lsnew.sig[0]; 157 if (extra) 158 bcopy(&lsnew.sig[1], extra, 159 sizeof(linux_sigset_t) - sizeof(linux_old_sigset_t)); 160 } 161 #endif 162 163 void 164 linux_to_native_sigset(lss, bss) 165 const linux_sigset_t *lss; 166 sigset_t *bss; 167 { 168 int i, newsig; 169 170 sigemptyset(bss); 171 for (i = 1; i < LINUX__NSIG; i++) { 172 if (linux_sigismember(lss, i)) { 173 newsig = linux_to_native_sig[i]; 174 if (newsig) 175 sigaddset(bss, newsig); 176 } 177 } 178 } 179 180 void 181 native_to_linux_sigset(bss, lss) 182 const sigset_t *bss; 183 linux_sigset_t *lss; 184 { 185 int i, newsig; 186 187 linux_sigemptyset(lss); 188 for (i = 1; i < NSIG; i++) { 189 if (sigismember(bss, i)) { 190 newsig = native_to_linux_sig[i]; 191 if (newsig) 192 linux_sigaddset(lss, newsig); 193 } 194 } 195 } 196 197 /* 198 * Convert between Linux and BSD sigaction structures. Linux sometimes 199 * has one extra field (sa_restorer) which we don't support. 200 */ 201 void 202 linux_old_to_native_sigaction(lsa, bsa) 203 struct linux_old_sigaction *lsa; 204 struct sigaction *bsa; 205 { 206 207 bsa->sa_handler = lsa->sa_handler; 208 linux_old_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask); 209 bsa->sa_flags = 0; 210 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0) 211 bsa->sa_flags |= SA_NOCLDSTOP; 212 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0) 213 bsa->sa_flags |= SA_ONSTACK; 214 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0) 215 bsa->sa_flags |= SA_RESTART; 216 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0) 217 bsa->sa_flags |= SA_RESETHAND; 218 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0) 219 bsa->sa_flags |= SA_NODEFER; 220 if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0) 221 bsa->sa_flags |= SA_SIGINFO; 222 #ifdef DEBUG_LINUX 223 if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0) 224 /*XXX*/ printf("linux_old_to_native_sigaction: extra bits ignored\n"); 225 if (lsa->sa_restorer != 0) 226 /*XXX*/ printf("linux_old_to_native_sigaction: sa_restorer ignored\n"); 227 #endif 228 } 229 230 void 231 native_to_linux_old_sigaction(bsa, lsa) 232 struct sigaction *bsa; 233 struct linux_old_sigaction *lsa; 234 { 235 236 /* Clear sa_flags and sa_restorer (if it exists) */ 237 bzero(lsa, sizeof(struct linux_old_sigaction)); 238 239 /* ...and fill in the mask and flags */ 240 native_to_linux_old_sigset(&bsa->sa_mask, &lsa->sa_mask); 241 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 242 lsa->sa_flags |= LINUX_SA_NOCLDSTOP; 243 if ((bsa->sa_flags & SA_ONSTACK) != 0) 244 lsa->sa_flags |= LINUX_SA_ONSTACK; 245 if ((bsa->sa_flags & SA_RESTART) != 0) 246 lsa->sa_flags |= LINUX_SA_RESTART; 247 if ((bsa->sa_flags & SA_NODEFER) != 0) 248 lsa->sa_flags |= LINUX_SA_NOMASK; 249 if ((bsa->sa_flags & SA_RESETHAND) != 0) 250 lsa->sa_flags |= LINUX_SA_ONESHOT; 251 if ((bsa->sa_flags & SA_SIGINFO) != 0) 252 lsa->sa_flags |= LINUX_SA_SIGINFO; 253 lsa->sa_handler = bsa->sa_handler; 254 } 255 256 /* ...and the new sigaction conversion funcs. */ 257 void 258 linux_to_native_sigaction(lsa, bsa) 259 struct linux_sigaction *lsa; 260 struct sigaction *bsa; 261 { 262 263 bsa->sa_handler = lsa->sa_handler; 264 linux_to_native_sigset(&lsa->sa_mask, &bsa->sa_mask); 265 bsa->sa_flags = 0; 266 if ((lsa->sa_flags & LINUX_SA_NOCLDSTOP) != 0) 267 bsa->sa_flags |= SA_NOCLDSTOP; 268 if ((lsa->sa_flags & LINUX_SA_ONSTACK) != 0) 269 bsa->sa_flags |= SA_ONSTACK; 270 if ((lsa->sa_flags & LINUX_SA_RESTART) != 0) 271 bsa->sa_flags |= SA_RESTART; 272 if ((lsa->sa_flags & LINUX_SA_ONESHOT) != 0) 273 bsa->sa_flags |= SA_RESETHAND; 274 if ((lsa->sa_flags & LINUX_SA_NOMASK) != 0) 275 bsa->sa_flags |= SA_NODEFER; 276 if ((lsa->sa_flags & LINUX_SA_SIGINFO) != 0) 277 bsa->sa_flags |= SA_SIGINFO; 278 #ifdef DEBUG_LINUX 279 if ((lsa->sa_flags & ~LINUX_SA_ALLBITS) != 0) 280 /*XXX*/ printf("linux_to_native_sigaction: extra bits ignored\n"); 281 if (lsa->sa_restorer != 0) 282 /*XXX*/ printf("linux_to_native_sigaction: sa_restorer ignored\n"); 283 #endif 284 } 285 286 void 287 native_to_linux_sigaction(bsa, lsa) 288 struct sigaction *bsa; 289 struct linux_sigaction *lsa; 290 { 291 292 /* Clear sa_flags and sa_restorer (if it exists) */ 293 bzero(lsa, sizeof(struct linux_sigaction)); 294 295 /* ...and fill in the mask and flags */ 296 native_to_linux_sigset(&bsa->sa_mask, &lsa->sa_mask); 297 if ((bsa->sa_flags & SA_NOCLDSTOP) != 0) 298 lsa->sa_flags |= LINUX_SA_NOCLDSTOP; 299 if ((bsa->sa_flags & SA_ONSTACK) != 0) 300 lsa->sa_flags |= LINUX_SA_ONSTACK; 301 if ((bsa->sa_flags & SA_RESTART) != 0) 302 lsa->sa_flags |= LINUX_SA_RESTART; 303 if ((bsa->sa_flags & SA_NODEFER) != 0) 304 lsa->sa_flags |= LINUX_SA_NOMASK; 305 if ((bsa->sa_flags & SA_RESETHAND) != 0) 306 lsa->sa_flags |= LINUX_SA_ONESHOT; 307 if ((bsa->sa_flags & SA_SIGINFO) != 0) 308 lsa->sa_flags |= LINUX_SA_SIGINFO; 309 lsa->sa_handler = bsa->sa_handler; 310 } 311 312 /* ----------------------------------------------------------------------- */ 313 314 /* 315 * The Linux sigaction() system call. Do the usual conversions, 316 * and just call sigaction(). Some flags and values are silently 317 * ignored (see above). 318 */ 319 int 320 linux_sys_rt_sigaction(p, v, retval) 321 register struct proc *p; 322 void *v; 323 register_t *retval; 324 { 325 struct linux_sys_rt_sigaction_args /* { 326 syscallarg(int) signum; 327 syscallarg(const struct linux_sigaction *) nsa; 328 syscallarg(struct linux_sigaction *) osa; 329 syscallarg(size_t) sigsetsize; 330 } */ *uap = v; 331 struct linux_sigaction nlsa, olsa; 332 struct sigaction nbsa, obsa; 333 int error; 334 335 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 336 return (EINVAL); 337 338 if (SCARG(uap, nsa)) { 339 error = copyin(SCARG(uap, nsa), &nlsa, sizeof(nlsa)); 340 if (error) 341 return (error); 342 linux_to_native_sigaction(&nlsa, &nbsa); 343 } 344 error = sigaction1(p, linux_to_native_sig[SCARG(uap, signum)], 345 SCARG(uap, nsa) ? &nbsa : 0, SCARG(uap, osa) ? &obsa : 0); 346 if (error) 347 return (error); 348 if (SCARG(uap, osa)) { 349 native_to_linux_sigaction(&obsa, &olsa); 350 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 351 if (error) 352 return (error); 353 } 354 return (0); 355 } 356 357 int 358 linux_sigprocmask1(p, how, set, oset) 359 register struct proc *p; 360 int how; 361 const linux_old_sigset_t *set; 362 linux_old_sigset_t *oset; 363 { 364 linux_old_sigset_t nlss, olss; 365 sigset_t nbss, obss; 366 int error; 367 368 switch (how) { 369 case LINUX_SIG_BLOCK: 370 how = SIG_BLOCK; 371 break; 372 case LINUX_SIG_UNBLOCK: 373 how = SIG_UNBLOCK; 374 break; 375 case LINUX_SIG_SETMASK: 376 how = SIG_SETMASK; 377 break; 378 default: 379 return (EINVAL); 380 } 381 382 if (set) { 383 error = copyin(set, &nlss, sizeof(nlss)); 384 if (error) 385 return (error); 386 linux_old_to_native_sigset(&nlss, &nbss); 387 } 388 error = sigprocmask1(p, how, 389 set ? &nbss : 0, oset ? &obss : 0); 390 if (error) 391 return (error); 392 if (oset) { 393 native_to_linux_old_sigset(&obss, &olss); 394 error = copyout(&olss, oset, sizeof(olss)); 395 if (error) 396 return (error); 397 } 398 return (error); 399 } 400 401 int 402 linux_sys_rt_sigprocmask(p, v, retval) 403 register struct proc *p; 404 void *v; 405 register_t *retval; 406 { 407 struct linux_sys_rt_sigprocmask_args /* { 408 syscallarg(int) how; 409 syscallarg(const linux_sigset_t *) set; 410 syscallarg(linux_sigset_t *) oset; 411 syscallarg(size_t) sigsetsize; 412 } */ *uap = v; 413 414 linux_sigset_t nlss, olss, *oset; 415 const linux_sigset_t *set; 416 sigset_t nbss, obss; 417 int error, how; 418 419 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 420 return (EINVAL); 421 422 switch (SCARG(uap, how)) { 423 case LINUX_SIG_BLOCK: 424 how = SIG_BLOCK; 425 break; 426 case LINUX_SIG_UNBLOCK: 427 how = SIG_UNBLOCK; 428 break; 429 case LINUX_SIG_SETMASK: 430 how = SIG_SETMASK; 431 break; 432 default: 433 return (EINVAL); 434 } 435 436 set = SCARG(uap, set); 437 oset = SCARG(uap, oset); 438 439 if (set) { 440 error = copyin(set, &nlss, sizeof(nlss)); 441 if (error) 442 return (error); 443 linux_to_native_sigset(&nlss, &nbss); 444 } 445 error = sigprocmask1(p, how, 446 set ? &nbss : 0, oset ? &obss : 0); 447 if (error) 448 return (error); 449 if (oset) { 450 native_to_linux_sigset(&obss, &olss); 451 error = copyout(&olss, oset, sizeof(olss)); 452 if (error) 453 return (error); 454 } 455 return (error); 456 } 457 458 int 459 linux_sys_rt_sigpending(p, v, retval) 460 register struct proc *p; 461 void *v; 462 register_t *retval; 463 { 464 struct linux_sys_rt_sigpending_args /* { 465 syscallarg(linux_sigset_t *) set; 466 syscallarg(size_t) sigsetsize; 467 } */ *uap = v; 468 sigset_t bss; 469 linux_sigset_t lss; 470 471 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 472 return (EINVAL); 473 474 sigpending1(p, &bss); 475 native_to_linux_sigset(&bss, &lss); 476 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 477 } 478 479 int 480 linux_sys_sigpending(p, v, retval) 481 register struct proc *p; 482 void *v; 483 register_t *retval; 484 { 485 struct linux_sys_sigpending_args /* { 486 syscallarg(linux_old_sigset_t *) mask; 487 } */ *uap = v; 488 sigset_t bss; 489 linux_old_sigset_t lss; 490 491 sigpending1(p, &bss); 492 native_to_linux_old_sigset(&bss, &lss); 493 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 494 } 495 496 int 497 linux_sys_sigsuspend(p, v, retval) 498 register struct proc *p; 499 void *v; 500 register_t *retval; 501 { 502 struct linux_sys_sigsuspend_args /* { 503 syscallarg(caddr_t) restart; 504 syscallarg(int) oldmask; 505 syscallarg(int) mask; 506 } */ *uap = v; 507 linux_old_sigset_t lss; 508 sigset_t bss; 509 510 lss = SCARG(uap, mask); 511 linux_old_to_native_sigset(&lss, &bss); 512 return (sigsuspend1(p, &bss)); 513 } 514 int 515 linux_sys_rt_sigsuspend(p, v, retval) 516 register struct proc *p; 517 void *v; 518 register_t *retval; 519 { 520 struct linux_sys_rt_sigsuspend_args /* { 521 syscallarg(linux_sigset_t *) unewset; 522 syscallarg(size_t) sigsetsize; 523 } */ *uap = v; 524 linux_sigset_t lss; 525 sigset_t bss; 526 int error; 527 528 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 529 return (EINVAL); 530 531 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 532 if (error) 533 return (error); 534 535 linux_to_native_sigset(&lss, &bss); 536 537 return (sigsuspend1(p, &bss)); 538 } 539 540 /* 541 * Once more: only a signal conversion is needed. 542 * Note: also used as sys_rt_queueinfo. The info field is ignored. 543 */ 544 int 545 linux_sys_rt_queueinfo(p, v, retval) 546 register struct proc *p; 547 void *v; 548 register_t *retval; 549 { 550 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */ 551 #if 0 552 struct linux_sys_rt_queueinfo_args /* { 553 syscallarg(int) pid; 554 syscallarg(int) signum; 555 syscallarg(siginfo_t *) uinfo; 556 } */ *uap = v; 557 #endif 558 559 /* XXX To really implement this we need to */ 560 /* XXX keep a list of queued signals somewhere. */ 561 return (linux_sys_kill(p, v, retval)); 562 } 563 564 int 565 linux_sys_kill(p, v, retval) 566 register struct proc *p; 567 void *v; 568 register_t *retval; 569 { 570 struct linux_sys_kill_args /* { 571 syscallarg(int) pid; 572 syscallarg(int) signum; 573 } */ *uap = v; 574 struct sys_kill_args ka; 575 576 SCARG(&ka, pid) = SCARG(uap, pid); 577 SCARG(&ka, signum) = linux_to_native_sig[SCARG(uap, signum)]; 578 return sys_kill(p, &ka, retval); 579 } 580