| 1 | /* |
| 2 | * Copyright (c) 1982, 1986, 1989 Regents of the University of California. |
| 3 | * All rights reserved. |
| 4 | * |
| 5 | * Redistribution and use in source and binary forms are permitted |
| 6 | * provided that the above copyright notice and this paragraph are |
| 7 | * duplicated in all such forms and that any documentation, |
| 8 | * advertising materials, and other materials related to such |
| 9 | * distribution and use acknowledge that the software was developed |
| 10 | * by the University of California, Berkeley. The name of the |
| 11 | * University may not be used to endorse or promote products derived |
| 12 | * from this software without specific prior written permission. |
| 13 | * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR |
| 14 | * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED |
| 15 | * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. |
| 16 | * |
| 17 | * @(#)kern_sig.c 7.10 (Berkeley) %G% |
| 18 | */ |
| 19 | |
| 20 | #include "param.h" |
| 21 | #include "systm.h" |
| 22 | #include "user.h" |
| 23 | #include "vnode.h" |
| 24 | #include "proc.h" |
| 25 | #include "timeb.h" |
| 26 | #include "times.h" |
| 27 | #include "buf.h" |
| 28 | #include "mount.h" |
| 29 | #include "text.h" |
| 30 | #include "seg.h" |
| 31 | #include "vm.h" |
| 32 | #include "acct.h" |
| 33 | #include "uio.h" |
| 34 | #include "file.h" |
| 35 | #include "kernel.h" |
| 36 | |
| 37 | #include "machine/reg.h" |
| 38 | #include "machine/pte.h" |
| 39 | #include "machine/psl.h" |
| 40 | #include "machine/mtpr.h" |
| 41 | |
| 42 | #define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)) |
| 43 | #define stopsigmask (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \ |
| 44 | sigmask(SIGTTIN)|sigmask(SIGTTOU)) |
| 45 | |
| 46 | /* |
| 47 | * Generalized interface signal handler. |
| 48 | */ |
| 49 | sigvec() |
| 50 | { |
| 51 | register struct a { |
| 52 | int signo; |
| 53 | struct sigvec *nsv; |
| 54 | struct sigvec *osv; |
| 55 | } *uap = (struct a *)u.u_ap; |
| 56 | struct sigvec vec; |
| 57 | register struct sigvec *sv; |
| 58 | register int sig; |
| 59 | int bit; |
| 60 | |
| 61 | sig = uap->signo; |
| 62 | if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { |
| 63 | u.u_error = EINVAL; |
| 64 | return; |
| 65 | } |
| 66 | sv = &vec; |
| 67 | if (uap->osv) { |
| 68 | sv->sv_handler = u.u_signal[sig]; |
| 69 | sv->sv_mask = u.u_sigmask[sig]; |
| 70 | bit = sigmask(sig); |
| 71 | sv->sv_flags = 0; |
| 72 | if ((u.u_sigonstack & bit) != 0) |
| 73 | sv->sv_flags |= SV_ONSTACK; |
| 74 | if ((u.u_sigintr & bit) != 0) |
| 75 | sv->sv_flags |= SV_INTERRUPT; |
| 76 | u.u_error = |
| 77 | copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); |
| 78 | if (u.u_error) |
| 79 | return; |
| 80 | } |
| 81 | if (uap->nsv) { |
| 82 | u.u_error = |
| 83 | copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); |
| 84 | if (u.u_error) |
| 85 | return; |
| 86 | if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { |
| 87 | u.u_error = EINVAL; |
| 88 | return; |
| 89 | } |
| 90 | setsigvec(sig, sv); |
| 91 | } |
| 92 | } |
| 93 | |
| 94 | setsigvec(sig, sv) |
| 95 | int sig; |
| 96 | register struct sigvec *sv; |
| 97 | { |
| 98 | register struct proc *p; |
| 99 | register int bit; |
| 100 | |
| 101 | bit = sigmask(sig); |
| 102 | p = u.u_procp; |
| 103 | /* |
| 104 | * Change setting atomically. |
| 105 | */ |
| 106 | (void) splhigh(); |
| 107 | u.u_signal[sig] = sv->sv_handler; |
| 108 | u.u_sigmask[sig] = sv->sv_mask &~ cantmask; |
| 109 | if (sv->sv_flags & SV_INTERRUPT) |
| 110 | u.u_sigintr |= bit; |
| 111 | else |
| 112 | u.u_sigintr &= ~bit; |
| 113 | if (sv->sv_flags & SV_ONSTACK) |
| 114 | u.u_sigonstack |= bit; |
| 115 | else |
| 116 | u.u_sigonstack &= ~bit; |
| 117 | if (sv->sv_handler == SIG_IGN) { |
| 118 | p->p_sig &= ~bit; /* never to be seen again */ |
| 119 | p->p_sigignore |= bit; |
| 120 | p->p_sigcatch &= ~bit; |
| 121 | } else { |
| 122 | p->p_sigignore &= ~bit; |
| 123 | if (sv->sv_handler == SIG_DFL) |
| 124 | p->p_sigcatch &= ~bit; |
| 125 | else |
| 126 | p->p_sigcatch |= bit; |
| 127 | } |
| 128 | (void) spl0(); |
| 129 | } |
| 130 | |
| 131 | sigblock() |
| 132 | { |
| 133 | struct a { |
| 134 | int mask; |
| 135 | } *uap = (struct a *)u.u_ap; |
| 136 | register struct proc *p = u.u_procp; |
| 137 | |
| 138 | (void) splhigh(); |
| 139 | u.u_r.r_val1 = p->p_sigmask; |
| 140 | p->p_sigmask |= uap->mask &~ cantmask; |
| 141 | (void) spl0(); |
| 142 | } |
| 143 | |
| 144 | sigsetmask() |
| 145 | { |
| 146 | struct a { |
| 147 | int mask; |
| 148 | } *uap = (struct a *)u.u_ap; |
| 149 | register struct proc *p = u.u_procp; |
| 150 | |
| 151 | (void) splhigh(); |
| 152 | u.u_r.r_val1 = p->p_sigmask; |
| 153 | p->p_sigmask = uap->mask &~ cantmask; |
| 154 | (void) spl0(); |
| 155 | } |
| 156 | |
| 157 | sigpause() |
| 158 | { |
| 159 | struct a { |
| 160 | int mask; |
| 161 | } *uap = (struct a *)u.u_ap; |
| 162 | register struct proc *p = u.u_procp; |
| 163 | |
| 164 | /* |
| 165 | * When returning from sigpause, we want |
| 166 | * the old mask to be restored after the |
| 167 | * signal handler has finished. Thus, we |
| 168 | * save it here and mark the proc structure |
| 169 | * to indicate this (should be in u.). |
| 170 | */ |
| 171 | u.u_oldmask = p->p_sigmask; |
| 172 | p->p_flag |= SOMASK; |
| 173 | p->p_sigmask = uap->mask &~ cantmask; |
| 174 | for (;;) |
| 175 | sleep((caddr_t)&u, PSLEP); |
| 176 | /*NOTREACHED*/ |
| 177 | } |
| 178 | #undef cantmask |
| 179 | |
| 180 | sigstack() |
| 181 | { |
| 182 | register struct a { |
| 183 | struct sigstack *nss; |
| 184 | struct sigstack *oss; |
| 185 | } *uap = (struct a *)u.u_ap; |
| 186 | struct sigstack ss; |
| 187 | |
| 188 | if (uap->oss) { |
| 189 | u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, |
| 190 | sizeof (struct sigstack)); |
| 191 | if (u.u_error) |
| 192 | return; |
| 193 | } |
| 194 | if (uap->nss) { |
| 195 | u.u_error = |
| 196 | copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); |
| 197 | if (u.u_error == 0) |
| 198 | u.u_sigstack = ss; |
| 199 | } |
| 200 | } |
| 201 | |
| 202 | kill() |
| 203 | { |
| 204 | register struct a { |
| 205 | int pid; |
| 206 | int signo; |
| 207 | } *uap = (struct a *)u.u_ap; |
| 208 | register struct proc *p; |
| 209 | |
| 210 | if (uap->signo < 0 || uap->signo > NSIG) { |
| 211 | u.u_error = EINVAL; |
| 212 | return; |
| 213 | } |
| 214 | if (uap->pid > 0) { |
| 215 | /* kill single process */ |
| 216 | p = pfind(uap->pid); |
| 217 | if (p == 0) { |
| 218 | u.u_error = ESRCH; |
| 219 | return; |
| 220 | } |
| 221 | if (u.u_uid && u.u_uid != p->p_uid) |
| 222 | u.u_error = EPERM; |
| 223 | else if (uap->signo) |
| 224 | psignal(p, uap->signo); |
| 225 | return; |
| 226 | } |
| 227 | switch (uap->pid) { |
| 228 | case -1: /* broadcast signal */ |
| 229 | u.u_error = killpg1(uap->signo, 0, 1); |
| 230 | break; |
| 231 | case 0: /* signal own process group */ |
| 232 | u.u_error = killpg1(uap->signo, 0, 0); |
| 233 | break; |
| 234 | default: /* negative explicit process group */ |
| 235 | u.u_error = killpg1(uap->signo, -uap->pid, 0); |
| 236 | break; |
| 237 | } |
| 238 | return; |
| 239 | } |
| 240 | |
| 241 | killpg() |
| 242 | { |
| 243 | register struct a { |
| 244 | int pgid; |
| 245 | int signo; |
| 246 | } *uap = (struct a *)u.u_ap; |
| 247 | |
| 248 | if (uap->signo < 0 || uap->signo > NSIG) { |
| 249 | u.u_error = EINVAL; |
| 250 | return; |
| 251 | } |
| 252 | u.u_error = killpg1(uap->signo, uap->pgid, 0); |
| 253 | } |
| 254 | |
| 255 | /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ |
| 256 | |
| 257 | killpg1(signo, pgid, all) |
| 258 | int signo, pgid, all; |
| 259 | { |
| 260 | register struct proc *p; |
| 261 | struct pgrp *pgrp; |
| 262 | int f = 0, error = 0; |
| 263 | |
| 264 | |
| 265 | if (all) |
| 266 | /* |
| 267 | * broadcast |
| 268 | */ |
| 269 | for (p = allproc; p != NULL; p = p->p_nxt) { |
| 270 | if (p->p_ppid == 0 || p->p_flag&SSYS || |
| 271 | p == u.u_procp || |
| 272 | (u.u_uid && u.u_uid != p->p_uid && |
| 273 | !(signo == SIGCONT && inferior(p)))) |
| 274 | continue; |
| 275 | f++; |
| 276 | if (signo) |
| 277 | psignal(p, signo); |
| 278 | } |
| 279 | else { |
| 280 | if (pgid == 0) |
| 281 | /* |
| 282 | * zero pgid means send to my process group. |
| 283 | */ |
| 284 | pgrp = u.u_procp->p_pgrp; |
| 285 | else { |
| 286 | pgrp = pgfind(pgid); |
| 287 | if (pgrp == NULL) |
| 288 | return(ESRCH); |
| 289 | } |
| 290 | if (!(pgrp->pg_jobc) && |
| 291 | (signo==SIGTTIN || signo==SIGTTOU || signo==SIGTSTP)) |
| 292 | return(EPERM); |
| 293 | for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) { |
| 294 | if (p->p_ppid == 0 || p->p_flag&SSYS) |
| 295 | continue; |
| 296 | if (u.u_uid && u.u_uid != p->p_uid && |
| 297 | !(signo == SIGCONT && inferior(p))) { |
| 298 | error = EPERM; |
| 299 | continue; |
| 300 | } |
| 301 | f++; |
| 302 | if (signo) |
| 303 | psignal(p, signo); |
| 304 | } |
| 305 | } |
| 306 | return (error ? error : (f == 0 ? ESRCH : 0)); |
| 307 | } |
| 308 | |
| 309 | /* |
| 310 | * Send the specified signal to |
| 311 | * all processes with 'pgid' as |
| 312 | * process group. |
| 313 | */ |
| 314 | gsignal(pgid, sig) |
| 315 | { |
| 316 | register struct pgrp *pgrp; |
| 317 | |
| 318 | if (!pgid) |
| 319 | return; |
| 320 | if ((pgrp = pgfind(pgid)) == NULL) |
| 321 | return; |
| 322 | pgsignal(pgrp, sig); |
| 323 | } |
| 324 | |
| 325 | pgsignal(pgrp, sig) |
| 326 | register struct pgrp *pgrp; |
| 327 | { |
| 328 | register struct proc *p; |
| 329 | |
| 330 | if (!(pgrp->pg_jobc) && |
| 331 | (sig==SIGTTIN || sig==SIGTTOU || sig==SIGTSTP)) |
| 332 | return; |
| 333 | for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) |
| 334 | psignal(p, sig); |
| 335 | } |
| 336 | |
| 337 | /* |
| 338 | * Send the specified signal to |
| 339 | * the specified process. |
| 340 | */ |
| 341 | psignal(p, sig) |
| 342 | register struct proc *p; |
| 343 | register int sig; |
| 344 | { |
| 345 | register int s; |
| 346 | register int (*action)(); |
| 347 | int mask; |
| 348 | |
| 349 | if ((unsigned)sig >= NSIG) |
| 350 | return; |
| 351 | mask = sigmask(sig); |
| 352 | |
| 353 | /* |
| 354 | * If proc is traced, always give parent a chance. |
| 355 | */ |
| 356 | if (p->p_flag & STRC) |
| 357 | action = SIG_DFL; |
| 358 | else { |
| 359 | /* |
| 360 | * If the signal is being ignored, |
| 361 | * then we forget about it immediately. |
| 362 | */ |
| 363 | if (p->p_sigignore & mask) |
| 364 | return; |
| 365 | if (p->p_sigmask & mask) |
| 366 | action = SIG_HOLD; |
| 367 | else if (p->p_sigcatch & mask) |
| 368 | action = SIG_CATCH; |
| 369 | else |
| 370 | action = SIG_DFL; |
| 371 | } |
| 372 | if (sig) { |
| 373 | switch (sig) { |
| 374 | |
| 375 | case SIGTERM: |
| 376 | if ((p->p_flag&STRC) || action != SIG_DFL) |
| 377 | break; |
| 378 | /* fall into ... */ |
| 379 | |
| 380 | case SIGKILL: |
| 381 | if (p->p_nice > NZERO) |
| 382 | p->p_nice = NZERO; |
| 383 | break; |
| 384 | |
| 385 | case SIGCONT: |
| 386 | p->p_sig &= ~stopsigmask; |
| 387 | break; |
| 388 | |
| 389 | case SIGTSTP: |
| 390 | case SIGTTIN: |
| 391 | case SIGTTOU: |
| 392 | /*FALLTHROUGH*/ |
| 393 | case SIGSTOP: |
| 394 | p->p_sig &= ~sigmask(SIGCONT); |
| 395 | break; |
| 396 | } |
| 397 | p->p_sig |= mask; |
| 398 | } |
| 399 | /* |
| 400 | * Defer further processing for signals which are held. |
| 401 | */ |
| 402 | if (action == SIG_HOLD) |
| 403 | return; |
| 404 | s = splhigh(); |
| 405 | switch (p->p_stat) { |
| 406 | |
| 407 | case SSLEEP: |
| 408 | /* |
| 409 | * If process is sleeping at negative priority |
| 410 | * we can't interrupt the sleep... the signal will |
| 411 | * be noticed when the process returns through |
| 412 | * trap() or syscall(). |
| 413 | */ |
| 414 | if (p->p_pri <= PZERO) |
| 415 | goto out; |
| 416 | /* |
| 417 | * Process is sleeping and traced... make it runnable |
| 418 | * so it can discover the signal in issig() and stop |
| 419 | * for the parent. |
| 420 | */ |
| 421 | if (p->p_flag&STRC) |
| 422 | goto run; |
| 423 | switch (sig) { |
| 424 | |
| 425 | case SIGSTOP: |
| 426 | case SIGTSTP: |
| 427 | case SIGTTIN: |
| 428 | case SIGTTOU: |
| 429 | /* |
| 430 | * These are the signals which by default |
| 431 | * stop a process. |
| 432 | */ |
| 433 | if (action != SIG_DFL) |
| 434 | goto run; |
| 435 | /* |
| 436 | * If a child in vfork(), stopping could |
| 437 | * cause deadlock. |
| 438 | */ |
| 439 | if (p->p_flag&SVFORK) |
| 440 | goto out; |
| 441 | p->p_sig &= ~mask; |
| 442 | p->p_cursig = sig; |
| 443 | psignal(p->p_pptr, SIGCHLD); |
| 444 | stop(p); |
| 445 | goto out; |
| 446 | |
| 447 | case SIGIO: |
| 448 | case SIGURG: |
| 449 | case SIGCHLD: |
| 450 | case SIGWINCH: |
| 451 | /* |
| 452 | * These signals are special in that they |
| 453 | * don't get propogated... if the process |
| 454 | * isn't interested, forget it. |
| 455 | */ |
| 456 | if (action != SIG_DFL) |
| 457 | goto run; |
| 458 | p->p_sig &= ~mask; /* take it away */ |
| 459 | goto out; |
| 460 | |
| 461 | default: |
| 462 | /* |
| 463 | * All other signals cause the process to run |
| 464 | */ |
| 465 | goto run; |
| 466 | } |
| 467 | /*NOTREACHED*/ |
| 468 | |
| 469 | case SSTOP: |
| 470 | /* |
| 471 | * If traced process is already stopped, |
| 472 | * then no further action is necessary. |
| 473 | */ |
| 474 | if (p->p_flag&STRC) |
| 475 | goto out; |
| 476 | switch (sig) { |
| 477 | |
| 478 | case SIGKILL: |
| 479 | /* |
| 480 | * Kill signal always sets processes running. |
| 481 | */ |
| 482 | goto run; |
| 483 | |
| 484 | case SIGCONT: |
| 485 | /* |
| 486 | * If the process catches SIGCONT, let it handle |
| 487 | * the signal itself. If it isn't waiting on |
| 488 | * an event, then it goes back to run state. |
| 489 | * Otherwise, process goes back to sleep state. |
| 490 | */ |
| 491 | if (action != SIG_DFL || p->p_wchan == 0) |
| 492 | goto run; |
| 493 | p->p_stat = SSLEEP; |
| 494 | goto out; |
| 495 | |
| 496 | case SIGSTOP: |
| 497 | case SIGTSTP: |
| 498 | case SIGTTIN: |
| 499 | case SIGTTOU: |
| 500 | /* |
| 501 | * Already stopped, don't need to stop again. |
| 502 | * (If we did the shell could get confused.) |
| 503 | */ |
| 504 | p->p_sig &= ~mask; /* take it away */ |
| 505 | goto out; |
| 506 | |
| 507 | default: |
| 508 | /* |
| 509 | * If process is sleeping interruptibly, then |
| 510 | * unstick it so that when it is continued |
| 511 | * it can look at the signal. |
| 512 | * But don't setrun the process as its not to |
| 513 | * be unstopped by the signal alone. |
| 514 | */ |
| 515 | if (p->p_wchan && p->p_pri > PZERO) |
| 516 | unsleep(p); |
| 517 | goto out; |
| 518 | } |
| 519 | /*NOTREACHED*/ |
| 520 | |
| 521 | default: |
| 522 | /* |
| 523 | * SRUN, SIDL, SZOMB do nothing with the signal, |
| 524 | * other than kicking ourselves if we are running. |
| 525 | * It will either never be noticed, or noticed very soon. |
| 526 | */ |
| 527 | if (p == u.u_procp && !noproc) |
| 528 | aston(); |
| 529 | goto out; |
| 530 | } |
| 531 | /*NOTREACHED*/ |
| 532 | run: |
| 533 | /* |
| 534 | * Raise priority to at least PUSER. |
| 535 | */ |
| 536 | if (p->p_pri > PUSER) |
| 537 | p->p_pri = PUSER; |
| 538 | setrun(p); |
| 539 | out: |
| 540 | splx(s); |
| 541 | } |
| 542 | |
| 543 | /* |
| 544 | * Returns true if the current |
| 545 | * process has a signal to process. |
| 546 | * The signal to process is put in p_cursig. |
| 547 | * This is asked at least once each time a process enters the |
| 548 | * system (though this can usually be done without actually |
| 549 | * calling issig by checking the pending signal masks.) |
| 550 | * A signal does not do anything |
| 551 | * directly to a process; it sets |
| 552 | * a flag that asks the process to |
| 553 | * do something to itself. |
| 554 | */ |
| 555 | issig() |
| 556 | { |
| 557 | register struct proc *p; |
| 558 | register int sig; |
| 559 | int sigbits, mask; |
| 560 | |
| 561 | p = u.u_procp; |
| 562 | for (;;) { |
| 563 | sigbits = p->p_sig &~ p->p_sigmask; |
| 564 | if ((p->p_flag&STRC) == 0) |
| 565 | sigbits &= ~p->p_sigignore; |
| 566 | if (p->p_flag&SVFORK) |
| 567 | sigbits &= ~stopsigmask; |
| 568 | if (sigbits == 0) |
| 569 | break; |
| 570 | sig = ffs((long)sigbits); |
| 571 | mask = sigmask(sig); |
| 572 | p->p_sig &= ~mask; /* take the signal! */ |
| 573 | p->p_cursig = sig; |
| 574 | if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { |
| 575 | /* |
| 576 | * If traced, always stop, and stay |
| 577 | * stopped until released by the parent. |
| 578 | */ |
| 579 | psignal(p->p_pptr, SIGCHLD); |
| 580 | do { |
| 581 | stop(p); |
| 582 | swtch(); |
| 583 | } while (!procxmt() && p->p_flag&STRC); |
| 584 | |
| 585 | /* |
| 586 | * If the traced bit got turned off, |
| 587 | * then put the signal taken above back into p_sig |
| 588 | * and go back up to the top to rescan signals. |
| 589 | * This ensures that p_sig* and u_signal are consistent. |
| 590 | */ |
| 591 | if ((p->p_flag&STRC) == 0) { |
| 592 | p->p_sig |= mask; |
| 593 | continue; |
| 594 | } |
| 595 | |
| 596 | /* |
| 597 | * If parent wants us to take the signal, |
| 598 | * then it will leave it in p->p_cursig; |
| 599 | * otherwise we just look for signals again. |
| 600 | */ |
| 601 | sig = p->p_cursig; |
| 602 | if (sig == 0) |
| 603 | continue; |
| 604 | |
| 605 | /* |
| 606 | * If signal is being masked put it back |
| 607 | * into p_sig and look for other signals. |
| 608 | */ |
| 609 | mask = sigmask(sig); |
| 610 | if (p->p_sigmask & mask) { |
| 611 | p->p_sig |= mask; |
| 612 | continue; |
| 613 | } |
| 614 | } |
| 615 | switch ((int)u.u_signal[sig]) { |
| 616 | |
| 617 | case SIG_DFL: |
| 618 | /* |
| 619 | * Don't take default actions on system processes. |
| 620 | */ |
| 621 | if (p->p_ppid == 0) |
| 622 | break; |
| 623 | switch (sig) { |
| 624 | |
| 625 | case SIGTSTP: |
| 626 | case SIGTTIN: |
| 627 | case SIGTTOU: |
| 628 | case SIGSTOP: |
| 629 | if (p->p_flag&STRC) |
| 630 | continue; |
| 631 | psignal(p->p_pptr, SIGCHLD); |
| 632 | stop(p); |
| 633 | swtch(); |
| 634 | continue; |
| 635 | |
| 636 | case SIGCONT: |
| 637 | case SIGCHLD: |
| 638 | case SIGURG: |
| 639 | case SIGIO: |
| 640 | case SIGWINCH: |
| 641 | /* |
| 642 | * These signals are normally not |
| 643 | * sent if the action is the default. |
| 644 | */ |
| 645 | continue; /* == ignore */ |
| 646 | |
| 647 | default: |
| 648 | goto send; |
| 649 | } |
| 650 | /*NOTREACHED*/ |
| 651 | |
| 652 | case SIG_HOLD: |
| 653 | case SIG_IGN: |
| 654 | /* |
| 655 | * Masking above should prevent us |
| 656 | * ever trying to take action on a held |
| 657 | * or ignored signal, unless process is traced. |
| 658 | */ |
| 659 | if ((p->p_flag&STRC) == 0) |
| 660 | printf("issig\n"); |
| 661 | continue; |
| 662 | |
| 663 | default: |
| 664 | /* |
| 665 | * This signal has an action, let |
| 666 | * psig process it. |
| 667 | */ |
| 668 | goto send; |
| 669 | } |
| 670 | /*NOTREACHED*/ |
| 671 | } |
| 672 | /* |
| 673 | * Didn't find a signal to send. |
| 674 | */ |
| 675 | p->p_cursig = 0; |
| 676 | return (0); |
| 677 | |
| 678 | send: |
| 679 | /* |
| 680 | * Let psig process the signal. |
| 681 | */ |
| 682 | return (sig); |
| 683 | } |
| 684 | |
| 685 | /* |
| 686 | * Put the argument process into the stopped |
| 687 | * state and notify the parent via wakeup. |
| 688 | * Signals are handled elsewhere. |
| 689 | */ |
| 690 | stop(p) |
| 691 | register struct proc *p; |
| 692 | { |
| 693 | |
| 694 | p->p_stat = SSTOP; |
| 695 | p->p_flag &= ~SWTED; |
| 696 | wakeup((caddr_t)p->p_pptr); |
| 697 | } |
| 698 | |
| 699 | /* |
| 700 | * Perform the action specified by |
| 701 | * the current signal. |
| 702 | * The usual sequence is: |
| 703 | * if (issig()) |
| 704 | * psig(); |
| 705 | * The signal bit has already been cleared by issig, |
| 706 | * and the current signal number stored in p->p_cursig. |
| 707 | */ |
| 708 | psig() |
| 709 | { |
| 710 | register struct proc *p = u.u_procp; |
| 711 | register int sig = p->p_cursig; |
| 712 | int mask = sigmask(sig), returnmask; |
| 713 | register int (*action)(); |
| 714 | |
| 715 | if (sig == 0) |
| 716 | panic("psig"); |
| 717 | action = u.u_signal[sig]; |
| 718 | if (action != SIG_DFL) { |
| 719 | if (action == SIG_IGN || (p->p_sigmask & mask)) |
| 720 | panic("psig action"); |
| 721 | u.u_error = 0; |
| 722 | /* |
| 723 | * Set the new mask value and also defer further |
| 724 | * occurences of this signal (unless we're simulating |
| 725 | * the old signal facilities). |
| 726 | * |
| 727 | * Special case: user has done a sigpause. Here the |
| 728 | * current mask is not of interest, but rather the |
| 729 | * mask from before the sigpause is what we want restored |
| 730 | * after the signal processing is completed. |
| 731 | */ |
| 732 | (void) splhigh(); |
| 733 | if (p->p_flag & SOUSIG) { |
| 734 | if (sig != SIGILL && sig != SIGTRAP) { |
| 735 | u.u_signal[sig] = SIG_DFL; |
| 736 | p->p_sigcatch &= ~mask; |
| 737 | } |
| 738 | mask = 0; |
| 739 | } |
| 740 | if (p->p_flag & SOMASK) { |
| 741 | returnmask = u.u_oldmask; |
| 742 | p->p_flag &= ~SOMASK; |
| 743 | } else |
| 744 | returnmask = p->p_sigmask; |
| 745 | p->p_sigmask |= u.u_sigmask[sig] | mask; |
| 746 | (void) spl0(); |
| 747 | u.u_ru.ru_nsignals++; |
| 748 | sendsig(action, sig, returnmask); |
| 749 | p->p_cursig = 0; |
| 750 | return; |
| 751 | } |
| 752 | u.u_acflag |= AXSIG; |
| 753 | switch (sig) { |
| 754 | |
| 755 | case SIGILL: |
| 756 | case SIGIOT: |
| 757 | case SIGBUS: |
| 758 | case SIGQUIT: |
| 759 | case SIGTRAP: |
| 760 | case SIGEMT: |
| 761 | case SIGFPE: |
| 762 | case SIGSEGV: |
| 763 | case SIGSYS: |
| 764 | u.u_arg[0] = sig; |
| 765 | if (core() == 0) |
| 766 | sig += 0200; |
| 767 | } |
| 768 | exit(sig); |
| 769 | } |
| 770 | |
| 771 | /* |
| 772 | * Create a core image on the file "core" |
| 773 | * If you are looking for protection glitches, |
| 774 | * there are probably a wealth of them here |
| 775 | * when this occurs to a suid command. |
| 776 | * |
| 777 | * It writes UPAGES block of the |
| 778 | * user.h area followed by the entire |
| 779 | * data+stack segments. |
| 780 | */ |
| 781 | core() |
| 782 | { |
| 783 | register struct vnode *vp; |
| 784 | register struct nameidata *ndp = &u.u_nd; |
| 785 | struct vattr vattr; |
| 786 | int error; |
| 787 | |
| 788 | if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) |
| 789 | return (EFAULT); |
| 790 | if (ctob(UPAGES + u.u_dsize + u.u_ssize) >= |
| 791 | u.u_rlimit[RLIMIT_CORE].rlim_cur) |
| 792 | return (EFAULT); |
| 793 | if (u.u_procp->p_textp) { |
| 794 | VOP_LOCK(u.u_procp->p_textp->x_vptr); |
| 795 | error = VOP_ACCESS(u.u_procp->p_textp->x_vptr, VREAD, u.u_cred); |
| 796 | VOP_UNLOCK(u.u_procp->p_textp->x_vptr); |
| 797 | if (error) |
| 798 | return (EFAULT); |
| 799 | } |
| 800 | ndp->ni_segflg = UIO_SYSSPACE; |
| 801 | ndp->ni_dirp = "core"; |
| 802 | if (error = vn_open(ndp, FCREAT|FWRITE, 0644)) |
| 803 | return (error); |
| 804 | vp = ndp->ni_vp; |
| 805 | VOP_LOCK(vp); |
| 806 | if (vp->v_type != VREG || |
| 807 | VOP_GETATTR(vp, &vattr, u.u_cred) || |
| 808 | vattr.va_nlink != 1) { |
| 809 | vput(vp); |
| 810 | return (EFAULT); |
| 811 | } |
| 812 | #ifdef MMAP |
| 813 | { register int fd; |
| 814 | /* unmap funky devices in the user's address space */ |
| 815 | for (fd = 0; fd < u.u_lastfile; fd++) |
| 816 | if (u.u_ofile[fd] && (u.u_pofile[fd] & UF_MAPPED)) |
| 817 | munmapfd(fd); |
| 818 | } |
| 819 | #endif |
| 820 | vattr_null(&vattr); |
| 821 | vattr.va_size = 0; |
| 822 | VOP_SETATTR(vp, &vattr, u.u_cred); |
| 823 | u.u_acflag |= ACORE; |
| 824 | error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&u, ctob(UPAGES), (off_t)0, |
| 825 | UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, ndp->ni_cred, (int *)0); |
| 826 | if (error == 0) |
| 827 | error = vn_rdwr(UIO_WRITE, vp, |
| 828 | (caddr_t)ctob(dptov(u.u_procp, 0)), |
| 829 | (int)ctob(u.u_dsize), (off_t)ctob(UPAGES), UIO_USERSPACE, |
| 830 | IO_NODELOCKED|IO_UNIT, ndp->ni_cred, (int *)0); |
| 831 | if (error == 0) |
| 832 | error = vn_rdwr(UIO_WRITE, vp, |
| 833 | (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), |
| 834 | (int)ctob(u.u_ssize), |
| 835 | (off_t)ctob(UPAGES) + ctob(u.u_dsize), UIO_USERSPACE, |
| 836 | IO_NODELOCKED|IO_UNIT, ndp->ni_cred, (int *)0); |
| 837 | vput(vp); |
| 838 | return (error); |
| 839 | } |