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