1*21016Smckusick /* kern_sig.c 6.16 85/05/22 */ 27421Sroot 39755Ssam #include "../machine/reg.h" 49755Ssam #include "../machine/pte.h" 59755Ssam #include "../machine/psl.h" 69755Ssam 717092Sbloom #include "param.h" 817092Sbloom #include "systm.h" 917092Sbloom #include "dir.h" 1017092Sbloom #include "user.h" 1117092Sbloom #include "inode.h" 1217092Sbloom #include "proc.h" 1317092Sbloom #include "timeb.h" 1417092Sbloom #include "times.h" 1517092Sbloom #include "buf.h" 1617092Sbloom #include "mount.h" 1717092Sbloom #include "text.h" 1817092Sbloom #include "seg.h" 1917092Sbloom #include "vm.h" 2017092Sbloom #include "acct.h" 2117092Sbloom #include "uio.h" 2217092Sbloom #include "kernel.h" 237421Sroot 2417153Sbloom #define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)) 2512951Ssam 2617013Smckusick /* 2717013Smckusick * Generalized interface signal handler. 2817013Smckusick */ 297499Sroot sigvec() 307421Sroot { 3112951Ssam register struct a { 3212882Ssam int signo; 3312951Ssam struct sigvec *nsv; 3412951Ssam struct sigvec *osv; 3512882Ssam } *uap = (struct a *)u.u_ap; 3612951Ssam struct sigvec vec; 3712951Ssam register struct sigvec *sv; 3812882Ssam register int sig; 3918308Smckusick int bit; 407421Sroot 4112882Ssam sig = uap->signo; 4212951Ssam if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { 4312882Ssam u.u_error = EINVAL; 4412882Ssam return; 4512882Ssam } 4612951Ssam sv = &vec; 4712951Ssam if (uap->osv) { 4812951Ssam sv->sv_handler = u.u_signal[sig]; 4912951Ssam sv->sv_mask = u.u_sigmask[sig]; 5018308Smckusick bit = sigmask(sig); 5118308Smckusick sv->sv_flags = 0; 5218308Smckusick if ((u.u_sigonstack & bit) != 0) 5318308Smckusick sv->sv_flags |= SV_ONSTACK; 5418308Smckusick if ((u.u_sigintr & bit) != 0) 5518308Smckusick sv->sv_flags |= SV_INTERRUPT; 5612951Ssam u.u_error = 5712951Ssam copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); 5812951Ssam if (u.u_error) 5912951Ssam return; 6012951Ssam } 6112951Ssam if (uap->nsv) { 6212951Ssam u.u_error = 6312951Ssam copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); 6412951Ssam if (u.u_error) 6512951Ssam return; 6612951Ssam if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { 6712951Ssam u.u_error = EINVAL; 6812951Ssam return; 6912951Ssam } 7012951Ssam setsigvec(sig, sv); 7112951Ssam } 727421Sroot } 737421Sroot 7412951Ssam setsigvec(sig, sv) 7512951Ssam int sig; 7612951Ssam register struct sigvec *sv; 7712882Ssam { 7812882Ssam register struct proc *p; 7912951Ssam register int bit; 8012882Ssam 8117153Sbloom bit = sigmask(sig); 8212882Ssam p = u.u_procp; 8312882Ssam /* 8412882Ssam * Change setting atomically. 8512882Ssam */ 8617153Sbloom (void) splhigh(); 8712951Ssam u.u_signal[sig] = sv->sv_handler; 8812951Ssam u.u_sigmask[sig] = sv->sv_mask &~ cantmask; 8918308Smckusick if (sv->sv_flags & SV_INTERRUPT) 9018308Smckusick u.u_sigintr |= bit; 9118308Smckusick else 9218308Smckusick u.u_sigintr &= ~bit; 9318308Smckusick if (sv->sv_flags & SV_ONSTACK) 9412951Ssam u.u_sigonstack |= bit; 9512951Ssam else 9612951Ssam u.u_sigonstack &= ~bit; 9712951Ssam if (sv->sv_handler == SIG_IGN) { 9812951Ssam p->p_sig &= ~bit; /* never to be seen again */ 9912951Ssam p->p_sigignore |= bit; 10012951Ssam p->p_sigcatch &= ~bit; 10112882Ssam } else { 10212951Ssam p->p_sigignore &= ~bit; 10312951Ssam if (sv->sv_handler == SIG_DFL) 10412951Ssam p->p_sigcatch &= ~bit; 10512882Ssam else 10612951Ssam p->p_sigcatch |= bit; 10712882Ssam } 10812882Ssam (void) spl0(); 10912882Ssam } 11012882Ssam 1117499Sroot sigblock() 1127421Sroot { 11312882Ssam struct a { 11417153Sbloom int mask; 11512882Ssam } *uap = (struct a *)u.u_ap; 11612951Ssam register struct proc *p = u.u_procp; 1177499Sroot 11817153Sbloom (void) splhigh(); 11912882Ssam u.u_r.r_val1 = p->p_sigmask; 12017153Sbloom p->p_sigmask |= uap->mask &~ cantmask; 12112882Ssam (void) spl0(); 1227499Sroot } 1237499Sroot 1247499Sroot sigsetmask() 1257499Sroot { 12612882Ssam struct a { 12717153Sbloom int mask; 12812882Ssam } *uap = (struct a *)u.u_ap; 12912882Ssam register struct proc *p = u.u_procp; 1307499Sroot 13117153Sbloom (void) splhigh(); 13212882Ssam u.u_r.r_val1 = p->p_sigmask; 13317153Sbloom p->p_sigmask = uap->mask &~ cantmask; 13412882Ssam (void) spl0(); 1357499Sroot } 1367499Sroot 1377499Sroot sigpause() 1387499Sroot { 13912882Ssam struct a { 14017153Sbloom int mask; 14112882Ssam } *uap = (struct a *)u.u_ap; 14212882Ssam register struct proc *p = u.u_procp; 1437499Sroot 14412882Ssam /* 14512882Ssam * When returning from sigpause, we want 14612882Ssam * the old mask to be restored after the 14712882Ssam * signal handler has finished. Thus, we 14812882Ssam * save it here and mark the proc structure 14912882Ssam * to indicate this (should be in u.). 15012882Ssam */ 15112882Ssam u.u_oldmask = p->p_sigmask; 15212882Ssam p->p_flag |= SOMASK; 15317153Sbloom p->p_sigmask = uap->mask &~ cantmask; 15412882Ssam for (;;) 15512882Ssam sleep((caddr_t)&u, PSLEP); 15612882Ssam /*NOTREACHED*/ 1577499Sroot } 15812951Ssam #undef cantmask 1597499Sroot 1607499Sroot sigstack() 1617499Sroot { 16212951Ssam register struct a { 16312951Ssam struct sigstack *nss; 16412951Ssam struct sigstack *oss; 16512882Ssam } *uap = (struct a *)u.u_ap; 16612951Ssam struct sigstack ss; 1677499Sroot 16812951Ssam if (uap->oss) { 16912951Ssam u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, 17012951Ssam sizeof (struct sigstack)); 17112951Ssam if (u.u_error) 17212951Ssam return; 17312951Ssam } 17412951Ssam if (uap->nss) { 17512951Ssam u.u_error = 17612951Ssam copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); 17712951Ssam if (u.u_error == 0) 17812951Ssam u.u_sigstack = ss; 17912951Ssam } 1807499Sroot } 1817499Sroot 1828032Sroot kill() 1838032Sroot { 18412882Ssam register struct a { 18512882Ssam int pid; 18612882Ssam int signo; 18712882Ssam } *uap = (struct a *)u.u_ap; 18818336Smckusick register struct proc *p; 1898032Sroot 19018336Smckusick if (uap->signo < 0 || uap->signo > NSIG) { 19118336Smckusick u.u_error = EINVAL; 19218336Smckusick return; 19318336Smckusick } 19418336Smckusick if (uap->pid > 0) { 19518336Smckusick /* kill single process */ 19618336Smckusick p = pfind(uap->pid); 19718336Smckusick if (p == 0) { 19818336Smckusick u.u_error = ESRCH; 19918336Smckusick return; 20018336Smckusick } 20118336Smckusick if (u.u_uid && u.u_uid != p->p_uid) 20218336Smckusick u.u_error = EPERM; 20318336Smckusick else if (uap->signo) 20418336Smckusick psignal(p, uap->signo); 20518336Smckusick return; 20618336Smckusick } 20718336Smckusick switch (uap->pid) { 20818336Smckusick case -1: /* broadcast signal */ 20920998Smckusick u.u_error = killpg1(uap->signo, 0, 1); 21018336Smckusick break; 21118336Smckusick case 0: /* signal own process group */ 21218336Smckusick u.u_error = killpg1(uap->signo, 0, 0); 21318336Smckusick break; 21418336Smckusick default: /* negative explicit process group */ 21518336Smckusick u.u_error = killpg1(uap->signo, -uap->pid, 0); 21618336Smckusick break; 21718336Smckusick } 21818336Smckusick return; 2198032Sroot } 2208032Sroot 2218032Sroot killpg() 2228032Sroot { 2239989Ssam register struct a { 2249989Ssam int pgrp; 2259989Ssam int signo; 2269989Ssam } *uap = (struct a *)u.u_ap; 2278032Sroot 22818336Smckusick if (uap->signo < 0 || uap->signo > NSIG) { 22918336Smckusick u.u_error = EINVAL; 23018336Smckusick return; 23118336Smckusick } 23218336Smckusick u.u_error = killpg1(uap->signo, uap->pgrp, 0); 2338032Sroot } 2348032Sroot 23512882Ssam /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ 23612882Ssam 23718336Smckusick killpg1(signo, pgrp, all) 23818336Smckusick int signo, pgrp, all; 2399989Ssam { 2409989Ssam register struct proc *p; 24118336Smckusick int f, error = 0; 2429989Ssam 24318336Smckusick if (!all && pgrp == 0) { 2447421Sroot /* 2457421Sroot * Zero process id means send to my process group. 2467421Sroot */ 24718336Smckusick pgrp = u.u_procp->p_pgrp; 24818336Smckusick if (pgrp == 0) 24920998Smckusick return (ESRCH); 2507421Sroot } 25116531Skarels for (f = 0, p = allproc; p != NULL; p = p->p_nxt) { 25218336Smckusick if ((p->p_pgrp != pgrp && !all) || p->p_ppid == 0 || 25318336Smckusick (p->p_flag&SSYS) || (all && p == u.u_procp)) 2547421Sroot continue; 2557421Sroot if (u.u_uid != 0 && u.u_uid != p->p_uid && 25618336Smckusick (signo != SIGCONT || !inferior(p))) { 25720998Smckusick if (!all) 25820998Smckusick error = EPERM; 2597421Sroot continue; 26018336Smckusick } 26120998Smckusick f++; 26212835Ssam if (signo) 26312835Ssam psignal(p, signo); 2647421Sroot } 26518336Smckusick return (f == 0 ? ESRCH : error); 2667421Sroot } 2677421Sroot 2687421Sroot /* 2697421Sroot * Send the specified signal to 2707421Sroot * all processes with 'pgrp' as 2717421Sroot * process group. 2727421Sroot */ 2737421Sroot gsignal(pgrp, sig) 2747421Sroot register int pgrp; 2757421Sroot { 2767421Sroot register struct proc *p; 2777421Sroot 2787421Sroot if (pgrp == 0) 2797421Sroot return; 28016531Skarels for (p = allproc; p != NULL; p = p->p_nxt) 2817421Sroot if (p->p_pgrp == pgrp) 2827421Sroot psignal(p, sig); 2837421Sroot } 2847421Sroot 2857421Sroot /* 2867421Sroot * Send the specified signal to 2877421Sroot * the specified process. 2887421Sroot */ 2897421Sroot psignal(p, sig) 2907421Sroot register struct proc *p; 2917421Sroot register int sig; 2927421Sroot { 2937421Sroot register int s; 2947421Sroot register int (*action)(); 29517153Sbloom int mask; 2967421Sroot 2977421Sroot if ((unsigned)sig >= NSIG) 2987421Sroot return; 29917153Sbloom mask = sigmask(sig); 3007421Sroot 3017421Sroot /* 3027421Sroot * If proc is traced, always give parent a chance. 3037421Sroot */ 3047421Sroot if (p->p_flag & STRC) 3057421Sroot action = SIG_DFL; 3067421Sroot else { 3077421Sroot /* 30812882Ssam * If the signal is being ignored, 30912882Ssam * then we forget about it immediately. 3107421Sroot */ 31117153Sbloom if (p->p_sigignore & mask) 3127421Sroot return; 31317153Sbloom if (p->p_sigmask & mask) 31412882Ssam action = SIG_HOLD; 31517153Sbloom else if (p->p_sigcatch & mask) 31612882Ssam action = SIG_CATCH; 31712882Ssam else 31812882Ssam action = SIG_DFL; 3197421Sroot } 32017153Sbloom #define stops (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \ 32117153Sbloom sigmask(SIGTTIN)|sigmask(SIGTTOU)) 3227421Sroot if (sig) { 32317153Sbloom p->p_sig |= mask; 3247421Sroot switch (sig) { 3257421Sroot 3267421Sroot case SIGTERM: 32712882Ssam if ((p->p_flag&STRC) || action != SIG_DFL) 3287421Sroot break; 3297421Sroot /* fall into ... */ 3307421Sroot 3317421Sroot case SIGKILL: 3327421Sroot if (p->p_nice > NZERO) 3337421Sroot p->p_nice = NZERO; 3347421Sroot break; 3357421Sroot 3367421Sroot case SIGCONT: 3377421Sroot p->p_sig &= ~stops; 3387421Sroot break; 3397421Sroot 3407421Sroot case SIGSTOP: 3417421Sroot case SIGTSTP: 3427421Sroot case SIGTTIN: 3437421Sroot case SIGTTOU: 34417153Sbloom p->p_sig &= ~sigmask(SIGCONT); 3457421Sroot break; 3467421Sroot } 3477421Sroot } 3487421Sroot #undef stops 3497421Sroot /* 3507421Sroot * Defer further processing for signals which are held. 3517421Sroot */ 3527421Sroot if (action == SIG_HOLD) 3537421Sroot return; 35417153Sbloom s = splhigh(); 3557421Sroot switch (p->p_stat) { 3567421Sroot 3577421Sroot case SSLEEP: 3587421Sroot /* 3597421Sroot * If process is sleeping at negative priority 3607421Sroot * we can't interrupt the sleep... the signal will 3617421Sroot * be noticed when the process returns through 3627421Sroot * trap() or syscall(). 3637421Sroot */ 3647421Sroot if (p->p_pri <= PZERO) 3657421Sroot goto out; 3667421Sroot /* 3677421Sroot * Process is sleeping and traced... make it runnable 3687421Sroot * so it can discover the signal in issig() and stop 3697421Sroot * for the parent. 3707421Sroot */ 3717421Sroot if (p->p_flag&STRC) 3727421Sroot goto run; 3737421Sroot switch (sig) { 3747421Sroot 3757421Sroot case SIGSTOP: 3767421Sroot case SIGTSTP: 3777421Sroot case SIGTTIN: 3787421Sroot case SIGTTOU: 3797421Sroot /* 3807421Sroot * These are the signals which by default 3817421Sroot * stop a process. 3827421Sroot */ 3837421Sroot if (action != SIG_DFL) 3847421Sroot goto run; 3857421Sroot /* 3867421Sroot * Don't clog system with children of init 3877421Sroot * stopped from the keyboard. 3887421Sroot */ 3897421Sroot if (sig != SIGSTOP && p->p_pptr == &proc[1]) { 3907421Sroot psignal(p, SIGKILL); 39117153Sbloom p->p_sig &= ~mask; 3927421Sroot splx(s); 3937421Sroot return; 3947421Sroot } 3957421Sroot /* 3967421Sroot * If a child in vfork(), stopping could 3977421Sroot * cause deadlock. 3987421Sroot */ 3997421Sroot if (p->p_flag&SVFORK) 4007421Sroot goto out; 40117153Sbloom p->p_sig &= ~mask; 4027421Sroot p->p_cursig = sig; 40318331Skarels psignal(p->p_pptr, SIGCHLD); 4047421Sroot stop(p); 4057421Sroot goto out; 4067421Sroot 4077421Sroot case SIGIO: 4087421Sroot case SIGURG: 4097421Sroot case SIGCHLD: 41017597Sbloom case SIGWINCH: 4117421Sroot /* 4127421Sroot * These signals are special in that they 4137421Sroot * don't get propogated... if the process 4147421Sroot * isn't interested, forget it. 4157421Sroot */ 4167421Sroot if (action != SIG_DFL) 4177421Sroot goto run; 41817153Sbloom p->p_sig &= ~mask; /* take it away */ 4197421Sroot goto out; 4207421Sroot 4217421Sroot default: 4227421Sroot /* 4237421Sroot * All other signals cause the process to run 4247421Sroot */ 4257421Sroot goto run; 4267421Sroot } 4277421Sroot /*NOTREACHED*/ 4287421Sroot 4297421Sroot case SSTOP: 4307421Sroot /* 4317421Sroot * If traced process is already stopped, 4327421Sroot * then no further action is necessary. 4337421Sroot */ 4347421Sroot if (p->p_flag&STRC) 4357421Sroot goto out; 4367421Sroot switch (sig) { 4377421Sroot 4387421Sroot case SIGKILL: 4397421Sroot /* 4407421Sroot * Kill signal always sets processes running. 4417421Sroot */ 4427421Sroot goto run; 4437421Sroot 4447421Sroot case SIGCONT: 4457421Sroot /* 4467421Sroot * If the process catches SIGCONT, let it handle 4477421Sroot * the signal itself. If it isn't waiting on 4487421Sroot * an event, then it goes back to run state. 4497421Sroot * Otherwise, process goes back to sleep state. 4507421Sroot */ 4517421Sroot if (action != SIG_DFL || p->p_wchan == 0) 4527421Sroot goto run; 4537421Sroot p->p_stat = SSLEEP; 4547421Sroot goto out; 4557421Sroot 4567421Sroot case SIGSTOP: 4577421Sroot case SIGTSTP: 4587421Sroot case SIGTTIN: 4597421Sroot case SIGTTOU: 4607421Sroot /* 4617421Sroot * Already stopped, don't need to stop again. 4627421Sroot * (If we did the shell could get confused.) 4637421Sroot */ 46417153Sbloom p->p_sig &= ~mask; /* take it away */ 4657421Sroot goto out; 4667421Sroot 4677421Sroot default: 4687421Sroot /* 4697421Sroot * If process is sleeping interruptibly, then 4707421Sroot * unstick it so that when it is continued 4717421Sroot * it can look at the signal. 4727421Sroot * But don't setrun the process as its not to 4737421Sroot * be unstopped by the signal alone. 4747421Sroot */ 4757421Sroot if (p->p_wchan && p->p_pri > PZERO) 4767421Sroot unsleep(p); 4777421Sroot goto out; 4787421Sroot } 4797421Sroot /*NOTREACHED*/ 4807421Sroot 4817421Sroot default: 4827421Sroot /* 4837421Sroot * SRUN, SIDL, SZOMB do nothing with the signal, 4847421Sroot * other than kicking ourselves if we are running. 4857421Sroot * It will either never be noticed, or noticed very soon. 4867421Sroot */ 4877421Sroot if (p == u.u_procp && !noproc) 4888444Sroot #include "../vax/mtpr.h" 4897421Sroot aston(); 4907421Sroot goto out; 4917421Sroot } 4927421Sroot /*NOTREACHED*/ 4937421Sroot run: 4947421Sroot /* 4957421Sroot * Raise priority to at least PUSER. 4967421Sroot */ 4977421Sroot if (p->p_pri > PUSER) 49817399Skarels p->p_pri = PUSER; 4997421Sroot setrun(p); 5007421Sroot out: 5017421Sroot splx(s); 5027421Sroot } 5037421Sroot 5047421Sroot /* 5057421Sroot * Returns true if the current 5067421Sroot * process has a signal to process. 5077421Sroot * The signal to process is put in p_cursig. 5087421Sroot * This is asked at least once each time a process enters the 5097421Sroot * system (though this can usually be done without actually 5107421Sroot * calling issig by checking the pending signal masks.) 5117421Sroot * A signal does not do anything 5127421Sroot * directly to a process; it sets 5137421Sroot * a flag that asks the process to 5147421Sroot * do something to itself. 5157421Sroot */ 5167421Sroot issig() 5177421Sroot { 5187421Sroot register struct proc *p; 5197421Sroot register int sig; 52017153Sbloom int sigbits, mask; 5217421Sroot 5227421Sroot p = u.u_procp; 5237421Sroot for (;;) { 52414782Ssam sigbits = p->p_sig &~ p->p_sigmask; 5257421Sroot if ((p->p_flag&STRC) == 0) 52614782Ssam sigbits &= ~p->p_sigignore; 5277421Sroot if (p->p_flag&SVFORK) 5287421Sroot #define bit(a) (1<<(a-1)) 5297421Sroot sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 5307421Sroot if (sigbits == 0) 5317421Sroot break; 53212882Ssam sig = ffs(sigbits); 53317153Sbloom mask = sigmask(sig); 53417153Sbloom p->p_sig &= ~mask; /* take the signal! */ 5357421Sroot p->p_cursig = sig; 53612882Ssam if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { 5377421Sroot /* 5387421Sroot * If traced, always stop, and stay 5397421Sroot * stopped until released by the parent. 5407421Sroot */ 54118331Skarels psignal(p->p_pptr, SIGCHLD); 5427421Sroot do { 5437421Sroot stop(p); 5447421Sroot swtch(); 5457421Sroot } while (!procxmt() && p->p_flag&STRC); 5467421Sroot 5477421Sroot /* 54814782Ssam * If the traced bit got turned off, 54914782Ssam * then put the signal taken above back into p_sig 55014782Ssam * and go back up to the top to rescan signals. 55114782Ssam * This ensures that p_sig* and u_signal are consistent. 5527421Sroot */ 55314782Ssam if ((p->p_flag&STRC) == 0) { 55417153Sbloom p->p_sig |= mask; 5557421Sroot continue; 5567421Sroot } 5577421Sroot 5587421Sroot /* 5597421Sroot * If parent wants us to take the signal, 5607421Sroot * then it will leave it in p->p_cursig; 5617421Sroot * otherwise we just look for signals again. 5627421Sroot */ 5637421Sroot sig = p->p_cursig; 5647421Sroot if (sig == 0) 5657421Sroot continue; 56614782Ssam 56714782Ssam /* 56814782Ssam * If signal is being masked put it back 56914782Ssam * into p_sig and look for other signals. 57014782Ssam */ 57117153Sbloom mask = sigmask(sig); 57217153Sbloom if (p->p_sigmask & mask) { 57317153Sbloom p->p_sig |= mask; 57414782Ssam continue; 57514782Ssam } 5767421Sroot } 5777421Sroot switch (u.u_signal[sig]) { 5787421Sroot 5797421Sroot case SIG_DFL: 5807421Sroot /* 5817421Sroot * Don't take default actions on system processes. 5827421Sroot */ 5837421Sroot if (p->p_ppid == 0) 5847421Sroot break; 5857421Sroot switch (sig) { 5867421Sroot 5877421Sroot case SIGTSTP: 5887421Sroot case SIGTTIN: 5897421Sroot case SIGTTOU: 5907421Sroot /* 5917421Sroot * Children of init aren't allowed to stop 5927421Sroot * on signals from the keyboard. 5937421Sroot */ 5947421Sroot if (p->p_pptr == &proc[1]) { 5957421Sroot psignal(p, SIGKILL); 5967421Sroot continue; 5977421Sroot } 5987421Sroot /* fall into ... */ 5997421Sroot 6007421Sroot case SIGSTOP: 6017421Sroot if (p->p_flag&STRC) 6027421Sroot continue; 60318331Skarels psignal(p->p_pptr, SIGCHLD); 6047421Sroot stop(p); 6057421Sroot swtch(); 6067421Sroot continue; 6077421Sroot 6087421Sroot case SIGCONT: 6097421Sroot case SIGCHLD: 61012882Ssam case SIGURG: 61112951Ssam case SIGIO: 61217597Sbloom case SIGWINCH: 6137421Sroot /* 6147421Sroot * These signals are normally not 6157421Sroot * sent if the action is the default. 6167421Sroot */ 6177421Sroot continue; /* == ignore */ 6187421Sroot 6197421Sroot default: 6207421Sroot goto send; 6217421Sroot } 6227421Sroot /*NOTREACHED*/ 6237421Sroot 6247421Sroot case SIG_HOLD: 6257421Sroot case SIG_IGN: 6267421Sroot /* 6277421Sroot * Masking above should prevent us 6287421Sroot * ever trying to take action on a held 6297421Sroot * or ignored signal, unless process is traced. 6307421Sroot */ 6317421Sroot if ((p->p_flag&STRC) == 0) 6327421Sroot printf("issig\n"); 6337421Sroot continue; 6347421Sroot 6357421Sroot default: 6367421Sroot /* 6377421Sroot * This signal has an action, let 6387421Sroot * psig process it. 6397421Sroot */ 6407421Sroot goto send; 6417421Sroot } 6427421Sroot /*NOTREACHED*/ 6437421Sroot } 6447421Sroot /* 6457421Sroot * Didn't find a signal to send. 6467421Sroot */ 6477421Sroot p->p_cursig = 0; 6487421Sroot return (0); 6497421Sroot 6507421Sroot send: 6517421Sroot /* 6527421Sroot * Let psig process the signal. 6537421Sroot */ 6547421Sroot return (sig); 6557421Sroot } 6567421Sroot 6577421Sroot /* 6587421Sroot * Put the argument process into the stopped 65918331Skarels * state and notify the parent via wakeup. 66018331Skarels * Signals are handled elsewhere. 6617421Sroot */ 6627421Sroot stop(p) 6637421Sroot register struct proc *p; 6647421Sroot { 6657421Sroot 6667421Sroot p->p_stat = SSTOP; 6677421Sroot p->p_flag &= ~SWTED; 6687421Sroot wakeup((caddr_t)p->p_pptr); 6697421Sroot } 6707421Sroot 6717421Sroot /* 6727421Sroot * Perform the action specified by 6737421Sroot * the current signal. 6747421Sroot * The usual sequence is: 6757421Sroot * if (issig()) 6767421Sroot * psig(); 6777421Sroot * The signal bit has already been cleared by issig, 6787421Sroot * and the current signal number stored in p->p_cursig. 6797421Sroot */ 6807421Sroot psig() 6817421Sroot { 68212882Ssam register struct proc *p = u.u_procp; 68312882Ssam register int sig = p->p_cursig; 68417153Sbloom int mask = sigmask(sig), returnmask; 6857421Sroot register int (*action)(); 6867421Sroot 68712882Ssam if (sig == 0) 6887421Sroot panic("psig"); 68912882Ssam action = u.u_signal[sig]; 6907421Sroot if (action != SIG_DFL) { 69117153Sbloom if (action == SIG_IGN || (p->p_sigmask & mask)) 6927421Sroot panic("psig action"); 6937421Sroot u.u_error = 0; 6947421Sroot /* 69512882Ssam * Set the new mask value and also defer further 69612882Ssam * occurences of this signal (unless we're simulating 69712882Ssam * the old signal facilities). 69812882Ssam * 69912882Ssam * Special case: user has done a sigpause. Here the 70012882Ssam * current mask is not of interest, but rather the 70112882Ssam * mask from before the sigpause is what we want restored 70212882Ssam * after the signal processing is completed. 7037421Sroot */ 70417153Sbloom (void) splhigh(); 70512882Ssam if (p->p_flag & SOUSIG) { 70612882Ssam if (sig != SIGILL && sig != SIGTRAP) { 70712882Ssam u.u_signal[sig] = SIG_DFL; 70817153Sbloom p->p_sigcatch &= ~mask; 70912882Ssam } 71017153Sbloom mask = 0; 7117421Sroot } 71212882Ssam if (p->p_flag & SOMASK) { 71312882Ssam returnmask = u.u_oldmask; 71412882Ssam p->p_flag &= ~SOMASK; 71512882Ssam } else 71612882Ssam returnmask = p->p_sigmask; 71717153Sbloom p->p_sigmask |= u.u_sigmask[sig] | mask; 71812882Ssam (void) spl0(); 7198032Sroot u.u_ru.ru_nsignals++; 72012882Ssam sendsig(action, sig, returnmask); 72112882Ssam p->p_cursig = 0; 7227421Sroot return; 7237421Sroot } 7247421Sroot u.u_acflag |= AXSIG; 72512882Ssam switch (sig) { 7267421Sroot 7277421Sroot case SIGILL: 7287421Sroot case SIGIOT: 7297421Sroot case SIGBUS: 7307421Sroot case SIGQUIT: 7317421Sroot case SIGTRAP: 7327421Sroot case SIGEMT: 7337421Sroot case SIGFPE: 7347421Sroot case SIGSEGV: 7357421Sroot case SIGSYS: 73612882Ssam u.u_arg[0] = sig; 7377421Sroot if (core()) 73812882Ssam sig += 0200; 7397421Sroot } 74012882Ssam exit(sig); 7417421Sroot } 7427421Sroot 7437421Sroot /* 7447421Sroot * Create a core image on the file "core" 7457421Sroot * If you are looking for protection glitches, 7467421Sroot * there are probably a wealth of them here 7477421Sroot * when this occurs to a suid command. 7487421Sroot * 7497421Sroot * It writes UPAGES block of the 7507421Sroot * user.h area followed by the entire 7517421Sroot * data+stack segments. 7527421Sroot */ 7537421Sroot core() 7547421Sroot { 7557421Sroot register struct inode *ip; 75616692Smckusick register struct nameidata *ndp = &u.u_nd; 7577421Sroot 75812639Ssam if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) 7597818Sroot return (0); 7608032Sroot if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= 7618032Sroot u.u_rlimit[RLIMIT_CORE].rlim_cur) 7627421Sroot return (0); 763*21016Smckusick if (u.u_procp->p_textp && access(u.u_procp->p_textp->x_iptr, IREAD)) 764*21016Smckusick return (0); 7657421Sroot u.u_error = 0; 76616692Smckusick ndp->ni_nameiop = CREATE | FOLLOW; 76716692Smckusick ndp->ni_segflg = UIO_SYSSPACE; 76816692Smckusick ndp->ni_dirp = "core"; 76916692Smckusick ip = namei(ndp); 7707421Sroot if (ip == NULL) { 7717421Sroot if (u.u_error) 7727421Sroot return (0); 77316692Smckusick ip = maknode(0644, ndp); 7747421Sroot if (ip==NULL) 7757421Sroot return (0); 7767421Sroot } 7777818Sroot if (access(ip, IWRITE) || 7787818Sroot (ip->i_mode&IFMT) != IFREG || 7797818Sroot ip->i_nlink != 1) { 7807421Sroot u.u_error = EFAULT; 7817818Sroot goto out; 7827818Sroot } 7839160Ssam itrunc(ip, (u_long)0); 7847818Sroot u.u_acflag |= ACORE; 78512882Ssam u.u_error = rdwri(UIO_WRITE, ip, 78612882Ssam (caddr_t)&u, 78712882Ssam ctob(UPAGES), 78812882Ssam 0, 1, (int *)0); 7898101Sroot if (u.u_error == 0) 7908644Sroot u.u_error = rdwri(UIO_WRITE, ip, 7918967Sroot (caddr_t)ctob(dptov(u.u_procp, 0)), 7928967Sroot ctob(u.u_dsize), 7938644Sroot ctob(UPAGES), 0, (int *)0); 7948101Sroot if (u.u_error == 0) 7958644Sroot u.u_error = rdwri(UIO_WRITE, ip, 7968967Sroot (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), 7978967Sroot ctob(u.u_ssize), 7988644Sroot ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); 7997818Sroot out: 8007421Sroot iput(ip); 8017818Sroot return (u.u_error == 0); 8027421Sroot } 803