1 /* $NetBSD: linux_signal.c,v 1.31 2001/01/18 20:28:27 jdolecek 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 const 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 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, sig; 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 sig = SCARG(uap, signum); 345 if (sig < 0 || sig >= LINUX__NSIG) 346 return (EINVAL); 347 if (sig > 0 && !linux_to_native_sig[sig]) { 348 /* Pretend that we did something useful for unknown signals. */ 349 obsa.sa_handler = SIG_IGN; 350 sigemptyset(&obsa.sa_mask); 351 obsa.sa_flags = 0; 352 } else { 353 error = sigaction1(p, linux_to_native_sig[sig], 354 SCARG(uap, nsa) ? &nbsa : NULL, SCARG(uap, osa) ? &obsa : NULL); 355 if (error) 356 return (error); 357 } 358 if (SCARG(uap, osa)) { 359 native_to_linux_sigaction(&obsa, &olsa); 360 error = copyout(&olsa, SCARG(uap, osa), sizeof(olsa)); 361 if (error) 362 return (error); 363 } 364 return (0); 365 } 366 367 int 368 linux_sigprocmask1(p, how, set, oset) 369 struct proc *p; 370 int how; 371 const linux_old_sigset_t *set; 372 linux_old_sigset_t *oset; 373 { 374 linux_old_sigset_t nlss, olss; 375 sigset_t nbss, obss; 376 int error; 377 378 switch (how) { 379 case LINUX_SIG_BLOCK: 380 how = SIG_BLOCK; 381 break; 382 case LINUX_SIG_UNBLOCK: 383 how = SIG_UNBLOCK; 384 break; 385 case LINUX_SIG_SETMASK: 386 how = SIG_SETMASK; 387 break; 388 default: 389 return (EINVAL); 390 } 391 392 if (set) { 393 error = copyin(set, &nlss, sizeof(nlss)); 394 if (error) 395 return (error); 396 linux_old_to_native_sigset(&nlss, &nbss); 397 } 398 error = sigprocmask1(p, how, 399 set ? &nbss : NULL, oset ? &obss : NULL); 400 if (error) 401 return (error); 402 if (oset) { 403 native_to_linux_old_sigset(&obss, &olss); 404 error = copyout(&olss, oset, sizeof(olss)); 405 if (error) 406 return (error); 407 } 408 return (error); 409 } 410 411 int 412 linux_sys_rt_sigprocmask(p, v, retval) 413 struct proc *p; 414 void *v; 415 register_t *retval; 416 { 417 struct linux_sys_rt_sigprocmask_args /* { 418 syscallarg(int) how; 419 syscallarg(const linux_sigset_t *) set; 420 syscallarg(linux_sigset_t *) oset; 421 syscallarg(size_t) sigsetsize; 422 } */ *uap = v; 423 424 linux_sigset_t nlss, olss, *oset; 425 const linux_sigset_t *set; 426 sigset_t nbss, obss; 427 int error, how; 428 429 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 430 return (EINVAL); 431 432 switch (SCARG(uap, how)) { 433 case LINUX_SIG_BLOCK: 434 how = SIG_BLOCK; 435 break; 436 case LINUX_SIG_UNBLOCK: 437 how = SIG_UNBLOCK; 438 break; 439 case LINUX_SIG_SETMASK: 440 how = SIG_SETMASK; 441 break; 442 default: 443 return (EINVAL); 444 } 445 446 set = SCARG(uap, set); 447 oset = SCARG(uap, oset); 448 449 if (set) { 450 error = copyin(set, &nlss, sizeof(nlss)); 451 if (error) 452 return (error); 453 linux_to_native_sigset(&nlss, &nbss); 454 } 455 error = sigprocmask1(p, how, 456 set ? &nbss : NULL, oset ? &obss : NULL); 457 if (!error && oset) { 458 native_to_linux_sigset(&obss, &olss); 459 error = copyout(&olss, oset, sizeof(olss)); 460 } 461 return (error); 462 } 463 464 int 465 linux_sys_rt_sigpending(p, v, retval) 466 struct proc *p; 467 void *v; 468 register_t *retval; 469 { 470 struct linux_sys_rt_sigpending_args /* { 471 syscallarg(linux_sigset_t *) set; 472 syscallarg(size_t) sigsetsize; 473 } */ *uap = v; 474 sigset_t bss; 475 linux_sigset_t lss; 476 477 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 478 return (EINVAL); 479 480 sigpending1(p, &bss); 481 native_to_linux_sigset(&bss, &lss); 482 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 483 } 484 485 int 486 linux_sys_sigpending(p, v, retval) 487 struct proc *p; 488 void *v; 489 register_t *retval; 490 { 491 struct linux_sys_sigpending_args /* { 492 syscallarg(linux_old_sigset_t *) mask; 493 } */ *uap = v; 494 sigset_t bss; 495 linux_old_sigset_t lss; 496 497 sigpending1(p, &bss); 498 native_to_linux_old_sigset(&bss, &lss); 499 return copyout(&lss, SCARG(uap, set), sizeof(lss)); 500 } 501 502 int 503 linux_sys_sigsuspend(p, v, retval) 504 struct proc *p; 505 void *v; 506 register_t *retval; 507 { 508 struct linux_sys_sigsuspend_args /* { 509 syscallarg(caddr_t) restart; 510 syscallarg(int) oldmask; 511 syscallarg(int) mask; 512 } */ *uap = v; 513 linux_old_sigset_t lss; 514 sigset_t bss; 515 516 lss = SCARG(uap, mask); 517 linux_old_to_native_sigset(&lss, &bss); 518 return (sigsuspend1(p, &bss)); 519 } 520 int 521 linux_sys_rt_sigsuspend(p, v, retval) 522 struct proc *p; 523 void *v; 524 register_t *retval; 525 { 526 struct linux_sys_rt_sigsuspend_args /* { 527 syscallarg(linux_sigset_t *) unewset; 528 syscallarg(size_t) sigsetsize; 529 } */ *uap = v; 530 linux_sigset_t lss; 531 sigset_t bss; 532 int error; 533 534 if (SCARG(uap, sigsetsize) != sizeof(linux_sigset_t)) 535 return (EINVAL); 536 537 error = copyin(SCARG(uap, unewset), &lss, sizeof(linux_sigset_t)); 538 if (error) 539 return (error); 540 541 linux_to_native_sigset(&lss, &bss); 542 543 return (sigsuspend1(p, &bss)); 544 } 545 546 /* 547 * Once more: only a signal conversion is needed. 548 * Note: also used as sys_rt_queueinfo. The info field is ignored. 549 */ 550 int 551 linux_sys_rt_queueinfo(p, v, retval) 552 struct proc *p; 553 void *v; 554 register_t *retval; 555 { 556 /* XXX XAX This isn't this really int, int, siginfo_t *, is it? */ 557 #if 0 558 struct linux_sys_rt_queueinfo_args /* { 559 syscallarg(int) pid; 560 syscallarg(int) signum; 561 syscallarg(siginfo_t *) uinfo; 562 } */ *uap = v; 563 #endif 564 565 /* XXX To really implement this we need to */ 566 /* XXX keep a list of queued signals somewhere. */ 567 return (linux_sys_kill(p, v, retval)); 568 } 569 570 int 571 linux_sys_kill(p, v, retval) 572 struct proc *p; 573 void *v; 574 register_t *retval; 575 { 576 struct linux_sys_kill_args /* { 577 syscallarg(int) pid; 578 syscallarg(int) signum; 579 } */ *uap = v; 580 struct sys_kill_args ka; 581 int sig; 582 583 SCARG(&ka, pid) = SCARG(uap, pid); 584 sig = SCARG(uap, signum); 585 if (sig < 0 || sig >= LINUX__NSIG) 586 return (EINVAL); 587 SCARG(&ka, signum) = linux_to_native_sig[sig]; 588 return sys_kill(p, &ka, retval); 589 } 590 591 #ifdef LINUX_SS_ONSTACK 592 static void linux_to_native_sigaltstack __P((struct sigaltstack *, 593 const struct linux_sigaltstack *)); 594 static void native_to_linux_sigaltstack __P((struct linux_sigaltstack *, 595 const struct sigaltstack *)); 596 597 static void 598 linux_to_native_sigaltstack(bss, lss) 599 struct sigaltstack *bss; 600 const struct linux_sigaltstack *lss; 601 { 602 bss->ss_sp = lss->ss_sp; 603 bss->ss_size = lss->ss_size; 604 if (lss->ss_flags & LINUX_SS_ONSTACK) 605 bss->ss_flags = SS_ONSTACK; 606 else if (lss->ss_flags & LINUX_SS_DISABLE) 607 bss->ss_flags = SS_DISABLE; 608 else 609 bss->ss_flags = 0; 610 } 611 612 static void 613 native_to_linux_sigaltstack(lss, bss) 614 struct linux_sigaltstack *lss; 615 const struct sigaltstack *bss; 616 { 617 lss->ss_sp = bss->ss_sp; 618 lss->ss_size = bss->ss_size; 619 if (bss->ss_flags & SS_ONSTACK) 620 lss->ss_flags = LINUX_SS_ONSTACK; 621 else if (bss->ss_flags & SS_DISABLE) 622 lss->ss_flags = LINUX_SS_DISABLE; 623 else 624 lss->ss_flags = 0; 625 } 626 627 int 628 linux_sys_sigaltstack(p, v, retval) 629 struct proc *p; 630 void *v; 631 register_t *retval; 632 { 633 struct linux_sys_sigaltstack_args /* { 634 syscallarg(const struct linux_sigaltstack *) ss; 635 syscallarg(struct linux_sigaltstack *) oss; 636 } */ *uap = v; 637 struct linux_sigaltstack ss; 638 struct sigaltstack nss, oss; 639 int error; 640 641 if (SCARG(uap, ss) != NULL) { 642 if ((error = copyin(SCARG(uap, ss), &ss, sizeof(ss))) != 0) 643 return error; 644 linux_to_native_sigaltstack(&nss, &ss); 645 } 646 647 error = sigaltstack1(p, 648 SCARG(uap, ss) ? &nss : NULL, SCARG(uap, oss) ? &oss : NULL); 649 if (error) 650 return error; 651 652 if (SCARG(uap, oss) != NULL) { 653 native_to_linux_sigaltstack(&ss, &oss); 654 if ((error = copyout(&ss, SCARG(uap, oss), sizeof(ss))) != 0) 655 return error; 656 } 657 return 0; 658 } 659 #endif 660