1 /* 2 * CDDL HEADER START 3 * 4 * The contents of this file are subject to the terms of the 5 * Common Development and Distribution License, Version 1.0 only 6 * (the "License"). You may not use this file except in compliance 7 * with the License. 8 * 9 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE 10 * or http://www.opensolaris.org/os/licensing. 11 * See the License for the specific language governing permissions 12 * and limitations under the License. 13 * 14 * When distributing Covered Code, include this CDDL HEADER in each 15 * file and include the License file at usr/src/OPENSOLARIS.LICENSE. 16 * If applicable, add the following below this CDDL HEADER, with the 17 * fields enclosed by brackets "[]" replaced with your own identifying 18 * information: Portions Copyright [yyyy] [name of copyright owner] 19 * 20 * CDDL HEADER END 21 */ 22 /* 23 * Copyright 2004 Sun Microsystems, Inc. All rights reserved. 24 * Use is subject to license terms. 25 */ 26 27 /* Copyright (c) 1983, 1984, 1985, 1986, 1987, 1988, 1989 AT&T */ 28 /* All Rights Reserved */ 29 30 /* 31 * Portions of this source code were derived from Berkeley 4.3 BSD 32 * under license from the Regents of the University of California. 33 */ 34 35 #pragma ident "%Z%%M% %I% %E% SMI" 36 37 /*LINTLIBRARY*/ 38 39 /* 40 * 4.3BSD signal compatibility functions 41 * 42 * the implementation interprets signal masks equal to -1 as "all of the 43 * signals in the signal set", thereby allowing signals with numbers 44 * above 32 to be blocked when referenced in code such as: 45 * 46 * for (i = 0; i < NSIG; i++) 47 * mask |= sigmask(i) 48 */ 49 50 #include <sys/types.h> 51 #include <ucontext.h> 52 #include <signal.h> 53 #include <errno.h> 54 55 #undef BUS_OBJERR /* namespace conflict */ 56 #include <sys/siginfo.h> 57 #include "libc.h" 58 59 #pragma weak sigvechandler = _sigvechandler 60 #pragma weak sigsetmask = _sigsetmask 61 #pragma weak sigblock = _sigblock 62 #pragma weak sigpause = usigpause 63 #pragma weak sigvec = _sigvec 64 #pragma weak sigstack = _sigstack 65 #pragma weak signal = usignal 66 #pragma weak siginterrupt = _siginterrupt 67 68 /* 69 * DO NOT remove the _ from these 3 functions or the subsequent 70 * calls to them below. The non _ versions of these functions 71 * are the wrong functions to call. This is BCP. Extra 72 * care should be taken when modifying this code. 73 */ 74 extern int _sigfillset(sigset_t *); 75 extern int _sigemptyset(sigset_t *); 76 extern int _sigprocmask(int, const sigset_t *, sigset_t *); 77 78 #define set2mask(setp) ((setp)->__sigbits[0]) 79 #define mask2set(mask, setp) \ 80 ((mask) == -1 ? _sigfillset(setp) : \ 81 ((void) _sigemptyset(setp), (((setp)->__sigbits[0]) = (int)(mask)))) 82 83 void (*_siguhandler[NSIG])() = { 0 }; 84 85 /* 86 * forward declarations 87 */ 88 int ucbsiginterrupt(int, int); 89 int ucbsigvec(int, struct sigvec *, struct sigvec *); 90 int ucbsigpause(int); 91 int ucbsigblock(int); 92 int ucbsigsetmask(int); 93 static void ucbsigvechandler(int, siginfo_t *, ucontext_t *); 94 95 /* 96 * sigvechandler is the real signal handler installed for all 97 * signals handled in the 4.3BSD compatibility interface - it translates 98 * SVR4 signal hander arguments into 4.3BSD signal handler arguments 99 * and then calls the real handler 100 */ 101 102 int 103 _sigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp) 104 { 105 ucbsigvechandler(sig, sip, ucp); 106 return (0); /* keep the same as the original prototype */ 107 } 108 109 static void 110 ucbsigvechandler(int sig, siginfo_t *sip, ucontext_t *ucp) 111 { 112 struct sigcontext sc; 113 int code; 114 char *addr; 115 #ifdef NEVER 116 int gwinswitch = 0; 117 #endif 118 119 sc.sc_onstack = ((ucp->uc_stack.ss_flags & SS_ONSTACK) != 0); 120 sc.sc_mask = set2mask(&ucp->uc_sigmask); 121 122 #if defined(__sparc) 123 if (sig == SIGFPE && sip != NULL && SI_FROMKERNEL(sip) && 124 (sip->si_code == FPE_INTDIV || sip->si_code == FPE_INTOVF)) { 125 /* 126 * Hack to emulate the 4.x kernel behavior of incrementing 127 * the PC on integer divide by zero and integer overflow 128 * on sparc machines. (5.x does not increment the PC.) 129 */ 130 ucp->uc_mcontext.gregs[REG_PC] = 131 ucp->uc_mcontext.gregs[REG_nPC]; 132 ucp->uc_mcontext.gregs[REG_nPC] += 4; 133 } 134 sc.sc_sp = ucp->uc_mcontext.gregs[REG_SP]; 135 sc.sc_pc = ucp->uc_mcontext.gregs[REG_PC]; 136 sc.sc_npc = ucp->uc_mcontext.gregs[REG_nPC]; 137 138 /* XX64 There is no REG_PSR for sparcv9, we map in REG_CCR for now */ 139 #if defined(__sparcv9) 140 sc.sc_psr = ucp->uc_mcontext.gregs[REG_CCR]; 141 #else 142 sc.sc_psr = ucp->uc_mcontext.gregs[REG_PSR]; 143 #endif 144 145 sc.sc_g1 = ucp->uc_mcontext.gregs[REG_G1]; 146 sc.sc_o0 = ucp->uc_mcontext.gregs[REG_O0]; 147 148 /* 149 * XXX - What a kludge! 150 * Store a pointer to the original ucontext_t in the sigcontext 151 * so that it's available to the sigcleanup call that needs to 152 * return from the signal handler. Otherwise, vital information 153 * (e.g., the "out" registers) that's only saved in the 154 * ucontext_t isn't available to sigcleanup. 155 */ 156 sc.sc_wbcnt = (int)(sizeof (*ucp)); 157 sc.sc_spbuf[0] = (char *)(uintptr_t)sig; 158 sc.sc_spbuf[1] = (char *)ucp; 159 #ifdef NEVER 160 /* 161 * XXX - Sorry, we can never pass the saved register windows 162 * on in the sigcontext because we use that space to save the 163 * ucontext_t. 164 */ 165 if (ucp->uc_mcontext.gwins != (gwindows_t *)0) { 166 int i, j; 167 168 gwinswitch = 1; 169 sc.sc_wbcnt = ucp->uc_mcontext.gwins->wbcnt; 170 /* XXX - should use bcopy to move this in bulk */ 171 for (i = 0; i < ucp->uc_mcontext.gwins; i++) { 172 sc.sc_spbuf[i] = ucp->uc_mcontext.gwins->spbuf[i]; 173 for (j = 0; j < 8; j++) 174 sc.sc_wbuf[i][j] = 175 ucp->uc_mcontext.gwins->wbuf[i].rw_local[j]; 176 for (j = 0; j < 8; j++) 177 sc.sc_wbuf[i][j+8] = 178 ucp->uc_mcontext.gwins->wbuf[i].rw_in[j]; 179 } 180 } 181 #endif 182 #endif 183 184 /* 185 * Translate signal codes from new to old. 186 * /usr/include/sys/siginfo.h contains new codes. 187 * /usr/ucbinclude/sys/signal.h contains old codes. 188 */ 189 code = 0; 190 addr = SIG_NOADDR; 191 if (sip != NULL && SI_FROMKERNEL(sip)) { 192 addr = sip->si_addr; 193 194 switch (sig) { 195 case SIGILL: 196 switch (sip->si_code) { 197 case ILL_PRVOPC: 198 code = ILL_PRIVINSTR_FAULT; 199 break; 200 case ILL_BADSTK: 201 code = ILL_STACK; 202 break; 203 case ILL_ILLTRP: 204 code = ILL_TRAP_FAULT(sip->si_trapno); 205 break; 206 default: 207 code = ILL_ILLINSTR_FAULT; 208 break; 209 } 210 break; 211 212 case SIGEMT: 213 code = EMT_TAG; 214 break; 215 216 case SIGFPE: 217 switch (sip->si_code) { 218 case FPE_INTDIV: 219 code = FPE_INTDIV_TRAP; 220 break; 221 case FPE_INTOVF: 222 code = FPE_INTOVF_TRAP; 223 break; 224 case FPE_FLTDIV: 225 code = FPE_FLTDIV_TRAP; 226 break; 227 case FPE_FLTOVF: 228 code = FPE_FLTOVF_TRAP; 229 break; 230 case FPE_FLTUND: 231 code = FPE_FLTUND_TRAP; 232 break; 233 case FPE_FLTRES: 234 code = FPE_FLTINEX_TRAP; 235 break; 236 default: 237 code = FPE_FLTOPERR_TRAP; 238 break; 239 } 240 break; 241 242 case SIGBUS: 243 switch (sip->si_code) { 244 case BUS_ADRALN: 245 code = BUS_ALIGN; 246 break; 247 case BUS_ADRERR: 248 code = BUS_HWERR; 249 break; 250 default: /* BUS_OBJERR */ 251 code = FC_MAKE_ERR(sip->si_errno); 252 break; 253 } 254 break; 255 256 case SIGSEGV: 257 switch (sip->si_code) { 258 case SEGV_MAPERR: 259 code = SEGV_NOMAP; 260 break; 261 case SEGV_ACCERR: 262 code = SEGV_PROT; 263 break; 264 default: 265 code = FC_MAKE_ERR(sip->si_errno); 266 break; 267 } 268 break; 269 270 default: 271 addr = SIG_NOADDR; 272 break; 273 } 274 } 275 276 (*_siguhandler[sig])(sig, code, &sc, addr); 277 278 if (sc.sc_onstack) 279 ucp->uc_stack.ss_flags |= SS_ONSTACK; 280 else 281 ucp->uc_stack.ss_flags &= ~SS_ONSTACK; 282 mask2set(sc.sc_mask, &ucp->uc_sigmask); 283 284 #if defined(__sparc) 285 ucp->uc_mcontext.gregs[REG_SP] = sc.sc_sp; 286 ucp->uc_mcontext.gregs[REG_PC] = sc.sc_pc; 287 ucp->uc_mcontext.gregs[REG_nPC] = sc.sc_npc; 288 #if defined(__sparcv9) 289 ucp->uc_mcontext.gregs[REG_CCR] = sc.sc_psr; 290 #else 291 ucp->uc_mcontext.gregs[REG_PSR] = sc.sc_psr; 292 #endif 293 ucp->uc_mcontext.gregs[REG_G1] = sc.sc_g1; 294 ucp->uc_mcontext.gregs[REG_O0] = sc.sc_o0; 295 #ifdef NEVER 296 if (gwinswitch == 1) { 297 int i, j; 298 299 ucp->uc_mcontext.gwins->wbcnt = sc.sc_wbcnt; 300 /* XXX - should use bcopy to move this in bulk */ 301 for (i = 0; i < sc.sc_wbcnt; i++) { 302 ucp->uc_mcontext.gwins->spbuf[i] = sc.sc_spbuf[i]; 303 for (j = 0; j < 8; j++) 304 ucp->uc_mcontext.gwins->wbuf[i].rw_local[j] = 305 sc.sc_wbuf[i][j]; 306 for (j = 0; j < 8; j++) 307 ucp->uc_mcontext.gwins->wbuf[i].rw_in[j] = 308 sc.sc_wbuf[i][j+8]; 309 } 310 } 311 #endif 312 313 if (sig == SIGFPE) { 314 if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) { 315 ucp->uc_mcontext.fpregs.fpu_qcnt--; 316 ucp->uc_mcontext.fpregs.fpu_q++; 317 } 318 } 319 #endif 320 321 (void) setcontext(ucp); 322 } 323 324 #if defined(__sparc) 325 /* 326 * Emulate the special sigcleanup trap. 327 * This is only used by statically linked 4.x applications 328 * and thus is only called by the static BCP support. 329 * It lives here because of its close relationship with 330 * the ucbsigvechandler code above. 331 * 332 * It's used by 4.x applications to: 333 * 1. return from a signal handler (in __sigtramp) 334 * 2. [sig]longjmp 335 * 3. context switch, in the old 4.x liblwp 336 */ 337 338 void 339 __sigcleanup(struct sigcontext *scp) 340 { 341 ucontext_t uc, *ucp; 342 int sig; 343 344 /* 345 * If there's a pointer to a ucontext_t hiding in the sigcontext, 346 * we *must* use that to return, since it contains important data 347 * such as the original "out" registers when the signal occurred. 348 */ 349 if (scp->sc_wbcnt == sizeof (*ucp)) { 350 sig = (int)(uintptr_t)scp->sc_spbuf[0]; 351 ucp = (ucontext_t *)scp->sc_spbuf[1]; 352 } else { 353 /* 354 * Otherwise, use a local ucontext_t and 355 * initialize it with getcontext. 356 */ 357 sig = 0; 358 ucp = &uc; 359 (void) getcontext(ucp); 360 } 361 362 if (scp->sc_onstack) { 363 ucp->uc_stack.ss_flags |= SS_ONSTACK; 364 } else 365 ucp->uc_stack.ss_flags &= ~SS_ONSTACK; 366 mask2set(scp->sc_mask, &ucp->uc_sigmask); 367 368 ucp->uc_mcontext.gregs[REG_SP] = scp->sc_sp; 369 ucp->uc_mcontext.gregs[REG_PC] = scp->sc_pc; 370 ucp->uc_mcontext.gregs[REG_nPC] = scp->sc_npc; 371 #if defined(__sparcv9) 372 ucp->uc_mcontext.gregs[REG_CCR] = scp->sc_psr; 373 #else 374 ucp->uc_mcontext.gregs[REG_PSR] = scp->sc_psr; 375 #endif 376 ucp->uc_mcontext.gregs[REG_G1] = scp->sc_g1; 377 ucp->uc_mcontext.gregs[REG_O0] = scp->sc_o0; 378 379 if (sig == SIGFPE) { 380 if (ucp->uc_mcontext.fpregs.fpu_qcnt > 0) { 381 ucp->uc_mcontext.fpregs.fpu_qcnt--; 382 ucp->uc_mcontext.fpregs.fpu_q++; 383 } 384 } 385 (void) setcontext(ucp); 386 /* NOTREACHED */ 387 } 388 #endif 389 390 int 391 _sigsetmask(int mask) 392 { 393 return (ucbsigsetmask(mask)); 394 } 395 396 int 397 ucbsigsetmask(int mask) 398 { 399 sigset_t oset; 400 sigset_t nset; 401 402 (void) _sigprocmask(0, (sigset_t *)0, &nset); 403 mask2set(mask, &nset); 404 (void) _sigprocmask(SIG_SETMASK, &nset, &oset); 405 return (set2mask(&oset)); 406 } 407 408 int 409 _sigblock(int mask) 410 { 411 return (ucbsigblock(mask)); 412 } 413 414 int 415 ucbsigblock(int mask) 416 { 417 sigset_t oset; 418 sigset_t nset; 419 420 (void) _sigprocmask(0, (sigset_t *)0, &nset); 421 mask2set(mask, &nset); 422 (void) _sigprocmask(SIG_BLOCK, &nset, &oset); 423 return (set2mask(&oset)); 424 } 425 426 int 427 usigpause(int mask) 428 { 429 return (ucbsigpause(mask)); 430 } 431 432 int 433 ucbsigpause(int mask) 434 { 435 sigset_t set, oset; 436 int ret; 437 438 (void) _sigprocmask(0, (sigset_t *)0, &set); 439 oset = set; 440 mask2set(mask, &set); 441 ret = sigsuspend(&set); 442 (void) _sigprocmask(SIG_SETMASK, &oset, (sigset_t *)0); 443 return (ret); 444 } 445 446 int 447 _sigvec(int sig, struct sigvec *nvec, struct sigvec *ovec) 448 { 449 return (ucbsigvec(sig, nvec, ovec)); 450 } 451 452 int 453 ucbsigvec(int sig, struct sigvec *nvec, struct sigvec *ovec) 454 { 455 struct sigaction nact; 456 struct sigaction oact; 457 struct sigaction *nactp; 458 void (*ohandler)(int, int, struct sigcontext *, char *); 459 void (*nhandler)(int, int, struct sigcontext *, char *); 460 461 if (sig <= 0 || sig >= NSIG) { 462 errno = EINVAL; 463 return (-1); 464 } 465 466 if ((long)ovec == -1L || (long)nvec == -1L) { 467 errno = EFAULT; 468 return (-1); 469 } 470 471 ohandler = _siguhandler[sig]; 472 473 if (nvec) { 474 (void) _sigaction(sig, (struct sigaction *)0, &nact); 475 nhandler = nvec->sv_handler; 476 /* 477 * To be compatible with the behavior of SunOS 4.x: 478 * If the new signal handler is SIG_IGN or SIG_DFL, 479 * do not change the signal's entry in the handler array. 480 * This allows a child of vfork(2) to set signal handlers 481 * to SIG_IGN or SIG_DFL without affecting the parent. 482 */ 483 if ((void (*)(int))nhandler != SIG_DFL && 484 (void (*)(int))nhandler != SIG_IGN) { 485 _siguhandler[sig] = nhandler; 486 nact.sa_handler = (void (*)(int))ucbsigvechandler; 487 } else { 488 nact.sa_handler = (void (*)(int))nhandler; 489 } 490 mask2set(nvec->sv_mask, &nact.sa_mask); 491 if (sig == SIGKILL || sig == SIGSTOP) 492 nact.sa_handler = SIG_DFL; 493 nact.sa_flags = SA_SIGINFO; 494 if (!(nvec->sv_flags & SV_INTERRUPT)) 495 nact.sa_flags |= SA_RESTART; 496 if (nvec->sv_flags & SV_RESETHAND) 497 nact.sa_flags |= SA_RESETHAND; 498 if (nvec->sv_flags & SV_ONSTACK) 499 nact.sa_flags |= SA_ONSTACK; 500 nactp = &nact; 501 } else 502 nactp = (struct sigaction *)0; 503 504 if (_sigaction(sig, nactp, &oact) < 0) { 505 _siguhandler[sig] = ohandler; 506 return (-1); 507 } 508 509 if (ovec) { 510 if (oact.sa_handler == SIG_DFL || oact.sa_handler == SIG_IGN) 511 ovec->sv_handler = 512 (void (*) (int, int, struct sigcontext *, char *)) 513 oact.sa_handler; 514 else 515 ovec->sv_handler = ohandler; 516 ovec->sv_mask = set2mask(&oact.sa_mask); 517 ovec->sv_flags = 0; 518 if (oact.sa_flags & SA_ONSTACK) 519 ovec->sv_flags |= SV_ONSTACK; 520 if (oact.sa_flags & SA_RESETHAND) 521 ovec->sv_flags |= SV_RESETHAND; 522 if (!(oact.sa_flags & SA_RESTART)) 523 ovec->sv_flags |= SV_INTERRUPT; 524 } 525 526 return (0); 527 } 528 529 int 530 _sigstack(struct sigstack *nss, struct sigstack *oss) 531 { 532 struct sigaltstack nalt; 533 struct sigaltstack oalt; 534 struct sigaltstack *naltp; 535 536 if (nss) { 537 /* 538 * XXX: assumes stack growth is down (like sparc) 539 */ 540 nalt.ss_sp = nss->ss_sp - SIGSTKSZ; 541 nalt.ss_size = SIGSTKSZ; 542 nalt.ss_flags = 0; 543 naltp = &nalt; 544 } else 545 naltp = (struct sigaltstack *)0; 546 547 if (sigaltstack(naltp, &oalt) < 0) 548 return (-1); 549 550 if (oss) { 551 /* 552 * XXX: assumes stack growth is down (like sparc) 553 */ 554 oss->ss_sp = oalt.ss_sp + oalt.ss_size; 555 oss->ss_onstack = ((oalt.ss_flags & SS_ONSTACK) != 0); 556 } 557 558 return (0); 559 } 560 561 void (* 562 ucbsignal(int s, void (*a)(int)))(int) 563 { 564 struct sigvec osv; 565 struct sigvec nsv; 566 static int mask[NSIG]; 567 static int flags[NSIG]; 568 569 nsv.sv_handler = (void (*) (int, int, struct sigcontext *, char *)) a; 570 nsv.sv_mask = mask[s]; 571 nsv.sv_flags = flags[s]; 572 if (ucbsigvec(s, &nsv, &osv) < 0) 573 return (SIG_ERR); 574 if (nsv.sv_mask != osv.sv_mask || nsv.sv_flags != osv.sv_flags) { 575 mask[s] = nsv.sv_mask = osv.sv_mask; 576 flags[s] = nsv.sv_flags = 577 osv.sv_flags & ~(SV_RESETHAND|SV_INTERRUPT); 578 if (ucbsigvec(s, &nsv, (struct sigvec *)0) < 0) 579 return (SIG_ERR); 580 } 581 return ((void (*) (int)) osv.sv_handler); 582 } 583 584 void (* 585 usignal(int s, void (*a) (int)))(int) 586 { 587 return (ucbsignal(s, a)); 588 } 589 590 /* 591 * Set signal state to prevent restart of system calls 592 * after an instance of the indicated signal. 593 */ 594 595 int 596 _siginterrupt(int sig, int flag) 597 { 598 return (ucbsiginterrupt(sig, flag)); 599 } 600 601 int 602 ucbsiginterrupt(int sig, int flag) 603 { 604 struct sigvec sv; 605 int ret; 606 607 if ((ret = ucbsigvec(sig, 0, &sv)) < 0) 608 return (ret); 609 if (flag) 610 sv.sv_flags |= SV_INTERRUPT; 611 else 612 sv.sv_flags &= ~SV_INTERRUPT; 613 return (ucbsigvec(sig, &sv, 0)); 614 } 615