1*17153Sbloom /* kern_sig.c 6.7 84/09/04 */ 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 "conf.h" 1617092Sbloom #include "buf.h" 1717092Sbloom #include "mount.h" 1817092Sbloom #include "text.h" 1917092Sbloom #include "seg.h" 2017092Sbloom #include "vm.h" 2117092Sbloom #include "acct.h" 2217092Sbloom #include "uio.h" 2317092Sbloom #include "kernel.h" 247421Sroot 25*17153Sbloom #define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)) 2612951Ssam 2717013Smckusick /* 2817013Smckusick * Quick interface to signal handler. 2917013Smckusick */ 3017013Smckusick signal() 3117013Smckusick { 3217013Smckusick register struct a { 3317013Smckusick int signo; 3417013Smckusick int (*handler)(); /* signal handler */ 3517013Smckusick } *uap = (struct a *)u.u_ap; 3617013Smckusick struct sigvec vec; 3717013Smckusick register struct sigvec *sv = &vec; 3817013Smckusick register int sig; 3917013Smckusick 4017013Smckusick sig = uap->signo; 4117013Smckusick if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP || 4217013Smckusick (sig == SIGCONT && uap->handler == SIG_IGN)) { 4317013Smckusick u.u_error = EINVAL; 4417013Smckusick return; 4517013Smckusick } 4617013Smckusick sv->sv_handler = uap->handler; 4717013Smckusick sv->sv_mask = 0; 4817013Smckusick sv->sv_onstack = 0; 4917013Smckusick u.u_r.r_val1 = (int)u.u_signal[sig]; 5017013Smckusick setsigvec(sig, sv); 5117013Smckusick } 5217013Smckusick 5317013Smckusick /* 5417013Smckusick * Generalized interface signal handler. 5517013Smckusick */ 567499Sroot sigvec() 577421Sroot { 5812951Ssam register struct a { 5912882Ssam int signo; 6012951Ssam struct sigvec *nsv; 6112951Ssam struct sigvec *osv; 6212882Ssam } *uap = (struct a *)u.u_ap; 6312951Ssam struct sigvec vec; 6412951Ssam register struct sigvec *sv; 6512882Ssam register int sig; 667421Sroot 6712882Ssam sig = uap->signo; 6812951Ssam if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { 6912882Ssam u.u_error = EINVAL; 7012882Ssam return; 7112882Ssam } 7212951Ssam sv = &vec; 7312951Ssam if (uap->osv) { 7412951Ssam sv->sv_handler = u.u_signal[sig]; 7512951Ssam sv->sv_mask = u.u_sigmask[sig]; 76*17153Sbloom sv->sv_onstack = (u.u_sigonstack & sigmask(sig)) != 0; 7712951Ssam u.u_error = 7812951Ssam copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); 7912951Ssam if (u.u_error) 8012951Ssam return; 8112951Ssam } 8212951Ssam if (uap->nsv) { 8312951Ssam u.u_error = 8412951Ssam copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); 8512951Ssam if (u.u_error) 8612951Ssam return; 8712951Ssam if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { 8812951Ssam u.u_error = EINVAL; 8912951Ssam return; 9012951Ssam } 9112951Ssam setsigvec(sig, sv); 9212951Ssam } 937421Sroot } 947421Sroot 9512951Ssam setsigvec(sig, sv) 9612951Ssam int sig; 9712951Ssam register struct sigvec *sv; 9812882Ssam { 9912882Ssam register struct proc *p; 10012951Ssam register int bit; 10112882Ssam 102*17153Sbloom bit = sigmask(sig); 10312882Ssam p = u.u_procp; 10412882Ssam /* 10512882Ssam * Change setting atomically. 10612882Ssam */ 107*17153Sbloom (void) splhigh(); 10812951Ssam u.u_signal[sig] = sv->sv_handler; 10912951Ssam u.u_sigmask[sig] = sv->sv_mask &~ cantmask; 11012951Ssam if (sv->sv_onstack) 11112951Ssam u.u_sigonstack |= bit; 11212951Ssam else 11312951Ssam u.u_sigonstack &= ~bit; 11412951Ssam if (sv->sv_handler == SIG_IGN) { 11512951Ssam p->p_sig &= ~bit; /* never to be seen again */ 11612951Ssam p->p_sigignore |= bit; 11712951Ssam p->p_sigcatch &= ~bit; 11812882Ssam } else { 11912951Ssam p->p_sigignore &= ~bit; 12012951Ssam if (sv->sv_handler == SIG_DFL) 12112951Ssam p->p_sigcatch &= ~bit; 12212882Ssam else 12312951Ssam p->p_sigcatch |= bit; 12412882Ssam } 12512882Ssam (void) spl0(); 12612882Ssam } 12712882Ssam 1287499Sroot sigblock() 1297421Sroot { 13012882Ssam struct a { 131*17153Sbloom int mask; 13212882Ssam } *uap = (struct a *)u.u_ap; 13312951Ssam register struct proc *p = u.u_procp; 1347499Sroot 135*17153Sbloom (void) splhigh(); 13612882Ssam u.u_r.r_val1 = p->p_sigmask; 137*17153Sbloom p->p_sigmask |= uap->mask &~ cantmask; 13812882Ssam (void) spl0(); 1397499Sroot } 1407499Sroot 1417499Sroot sigsetmask() 1427499Sroot { 14312882Ssam struct a { 144*17153Sbloom int mask; 14512882Ssam } *uap = (struct a *)u.u_ap; 14612882Ssam register struct proc *p = u.u_procp; 1477499Sroot 148*17153Sbloom (void) splhigh(); 14912882Ssam u.u_r.r_val1 = p->p_sigmask; 150*17153Sbloom p->p_sigmask = uap->mask &~ cantmask; 15112882Ssam (void) spl0(); 1527499Sroot } 1537499Sroot 1547499Sroot sigpause() 1557499Sroot { 15612882Ssam struct a { 157*17153Sbloom int mask; 15812882Ssam } *uap = (struct a *)u.u_ap; 15912882Ssam register struct proc *p = u.u_procp; 1607499Sroot 16112882Ssam /* 16212882Ssam * When returning from sigpause, we want 16312882Ssam * the old mask to be restored after the 16412882Ssam * signal handler has finished. Thus, we 16512882Ssam * save it here and mark the proc structure 16612882Ssam * to indicate this (should be in u.). 16712882Ssam */ 16812882Ssam u.u_oldmask = p->p_sigmask; 16912882Ssam p->p_flag |= SOMASK; 170*17153Sbloom p->p_sigmask = uap->mask &~ cantmask; 17112882Ssam for (;;) 17212882Ssam sleep((caddr_t)&u, PSLEP); 17312882Ssam /*NOTREACHED*/ 1747499Sroot } 17512951Ssam #undef cantmask 1767499Sroot 1777499Sroot sigstack() 1787499Sroot { 17912951Ssam register struct a { 18012951Ssam struct sigstack *nss; 18112951Ssam struct sigstack *oss; 18212882Ssam } *uap = (struct a *)u.u_ap; 18312951Ssam struct sigstack ss; 1847499Sroot 18512951Ssam if (uap->oss) { 18612951Ssam u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, 18712951Ssam sizeof (struct sigstack)); 18812951Ssam if (u.u_error) 18912951Ssam return; 19012951Ssam } 19112951Ssam if (uap->nss) { 19212951Ssam u.u_error = 19312951Ssam copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); 19412951Ssam if (u.u_error == 0) 19512951Ssam u.u_sigstack = ss; 19612951Ssam } 1977499Sroot } 1987499Sroot 19913227Ssam /* KILL SHOULD BE UPDATED */ 20013227Ssam 2018032Sroot kill() 2028032Sroot { 20312882Ssam register struct a { 20412882Ssam int pid; 20512882Ssam int signo; 20612882Ssam } *uap = (struct a *)u.u_ap; 2078032Sroot 20813227Ssam u.u_error = kill1(uap->signo < 0, 20913227Ssam uap->signo < 0 ? -uap->signo : uap->signo, uap->pid); 2108032Sroot } 2118032Sroot 2128032Sroot killpg() 2138032Sroot { 2149989Ssam register struct a { 2159989Ssam int pgrp; 2169989Ssam int signo; 2179989Ssam } *uap = (struct a *)u.u_ap; 2188032Sroot 21912750Ssam u.u_error = kill1(1, uap->signo, uap->pgrp); 2208032Sroot } 2218032Sroot 22212882Ssam /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ 22312882Ssam 22412750Ssam kill1(ispgrp, signo, who) 2259989Ssam int ispgrp, signo, who; 2269989Ssam { 2279989Ssam register struct proc *p; 2289989Ssam int f, priv = 0; 2299989Ssam 23012835Ssam if (signo < 0 || signo > NSIG) 2319989Ssam return (EINVAL); 2329989Ssam if (who > 0 && !ispgrp) { 2339989Ssam p = pfind(who); 23414926Smckusick if (p == 0) 2359989Ssam return (ESRCH); 23614926Smckusick if (u.u_uid && u.u_uid != p->p_uid) 23714926Smckusick return (EPERM); 23812835Ssam if (signo) 23912835Ssam psignal(p, signo); 2409989Ssam return (0); 2417421Sroot } 2429989Ssam if (who == -1 && u.u_uid == 0) 2439989Ssam priv++, who = 0, ispgrp = 1; /* like sending to pgrp */ 2449989Ssam else if (who == 0) { 2457421Sroot /* 2467421Sroot * Zero process id means send to my process group. 2477421Sroot */ 2489989Ssam ispgrp = 1; 2499989Ssam who = u.u_procp->p_pgrp; 2509989Ssam if (who == 0) 2519989Ssam return (EINVAL); 2527421Sroot } 25316531Skarels for (f = 0, p = allproc; p != NULL; p = p->p_nxt) { 2549989Ssam if (!ispgrp) { 2559989Ssam if (p->p_pid != who) 2567421Sroot continue; 2579989Ssam } else if (p->p_pgrp != who && priv == 0 || p->p_ppid == 0 || 2589989Ssam (p->p_flag&SSYS) || (priv && p == u.u_procp)) 2597421Sroot continue; 2607421Sroot if (u.u_uid != 0 && u.u_uid != p->p_uid && 2619989Ssam (signo != SIGCONT || !inferior(p))) 2627421Sroot continue; 2637421Sroot f++; 26412835Ssam if (signo) 26512835Ssam psignal(p, signo); 2667421Sroot } 26712750Ssam return (f == 0 ? ESRCH : 0); 2687421Sroot } 2697421Sroot 2707421Sroot /* 2717421Sroot * Send the specified signal to 2727421Sroot * all processes with 'pgrp' as 2737421Sroot * process group. 2747421Sroot */ 2757421Sroot gsignal(pgrp, sig) 2767421Sroot register int pgrp; 2777421Sroot { 2787421Sroot register struct proc *p; 2797421Sroot 2807421Sroot if (pgrp == 0) 2817421Sroot return; 28216531Skarels for (p = allproc; p != NULL; p = p->p_nxt) 2837421Sroot if (p->p_pgrp == pgrp) 2847421Sroot psignal(p, sig); 2857421Sroot } 2867421Sroot 2877421Sroot /* 2887421Sroot * Send the specified signal to 2897421Sroot * the specified process. 2907421Sroot */ 2917421Sroot psignal(p, sig) 2927421Sroot register struct proc *p; 2937421Sroot register int sig; 2947421Sroot { 2957421Sroot register int s; 2967421Sroot register int (*action)(); 297*17153Sbloom int mask; 2987421Sroot 2997421Sroot if ((unsigned)sig >= NSIG) 3007421Sroot return; 301*17153Sbloom mask = sigmask(sig); 3027421Sroot 3037421Sroot /* 3047421Sroot * If proc is traced, always give parent a chance. 3057421Sroot */ 3067421Sroot if (p->p_flag & STRC) 3077421Sroot action = SIG_DFL; 3087421Sroot else { 3097421Sroot /* 31012882Ssam * If the signal is being ignored, 31112882Ssam * then we forget about it immediately. 3127421Sroot */ 313*17153Sbloom if (p->p_sigignore & mask) 3147421Sroot return; 315*17153Sbloom if (p->p_sigmask & mask) 31612882Ssam action = SIG_HOLD; 317*17153Sbloom else if (p->p_sigcatch & mask) 31812882Ssam action = SIG_CATCH; 31912882Ssam else 32012882Ssam action = SIG_DFL; 3217421Sroot } 322*17153Sbloom #define stops (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \ 323*17153Sbloom sigmask(SIGTTIN)|sigmask(SIGTTOU)) 3247421Sroot if (sig) { 325*17153Sbloom p->p_sig |= mask; 3267421Sroot switch (sig) { 3277421Sroot 3287421Sroot case SIGTERM: 32912882Ssam if ((p->p_flag&STRC) || action != SIG_DFL) 3307421Sroot break; 3317421Sroot /* fall into ... */ 3327421Sroot 3337421Sroot case SIGKILL: 3347421Sroot if (p->p_nice > NZERO) 3357421Sroot p->p_nice = NZERO; 3367421Sroot break; 3377421Sroot 3387421Sroot case SIGCONT: 3397421Sroot p->p_sig &= ~stops; 3407421Sroot break; 3417421Sroot 3427421Sroot case SIGSTOP: 3437421Sroot case SIGTSTP: 3447421Sroot case SIGTTIN: 3457421Sroot case SIGTTOU: 346*17153Sbloom p->p_sig &= ~sigmask(SIGCONT); 3477421Sroot break; 3487421Sroot } 3497421Sroot } 3507421Sroot #undef stops 3517421Sroot /* 3527421Sroot * Defer further processing for signals which are held. 3537421Sroot */ 3547421Sroot if (action == SIG_HOLD) 3557421Sroot return; 356*17153Sbloom s = splhigh(); 3577421Sroot switch (p->p_stat) { 3587421Sroot 3597421Sroot case SSLEEP: 3607421Sroot /* 3617421Sroot * If process is sleeping at negative priority 3627421Sroot * we can't interrupt the sleep... the signal will 3637421Sroot * be noticed when the process returns through 3647421Sroot * trap() or syscall(). 3657421Sroot */ 3667421Sroot if (p->p_pri <= PZERO) 3677421Sroot goto out; 3687421Sroot /* 3697421Sroot * Process is sleeping and traced... make it runnable 3707421Sroot * so it can discover the signal in issig() and stop 3717421Sroot * for the parent. 3727421Sroot */ 3737421Sroot if (p->p_flag&STRC) 3747421Sroot goto run; 3757421Sroot switch (sig) { 3767421Sroot 3777421Sroot case SIGSTOP: 3787421Sroot case SIGTSTP: 3797421Sroot case SIGTTIN: 3807421Sroot case SIGTTOU: 3817421Sroot /* 3827421Sroot * These are the signals which by default 3837421Sroot * stop a process. 3847421Sroot */ 3857421Sroot if (action != SIG_DFL) 3867421Sroot goto run; 3877421Sroot /* 3887421Sroot * Don't clog system with children of init 3897421Sroot * stopped from the keyboard. 3907421Sroot */ 3917421Sroot if (sig != SIGSTOP && p->p_pptr == &proc[1]) { 3927421Sroot psignal(p, SIGKILL); 393*17153Sbloom p->p_sig &= ~mask; 3947421Sroot splx(s); 3957421Sroot return; 3967421Sroot } 3977421Sroot /* 3987421Sroot * If a child in vfork(), stopping could 3997421Sroot * cause deadlock. 4007421Sroot */ 4017421Sroot if (p->p_flag&SVFORK) 4027421Sroot goto out; 403*17153Sbloom p->p_sig &= ~mask; 4047421Sroot p->p_cursig = sig; 4057421Sroot stop(p); 4067421Sroot goto out; 4077421Sroot 4087421Sroot case SIGIO: 4097421Sroot case SIGURG: 4107421Sroot case SIGCHLD: 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; 418*17153Sbloom 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 */ 464*17153Sbloom 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) 4987421Sroot if ((p != u.u_procp || noproc) && p->p_stat == SRUN && 4997421Sroot (p->p_flag & SLOAD)) { 5007421Sroot remrq(p); 5017421Sroot p->p_pri = PUSER; 5027421Sroot setrq(p); 5037421Sroot } else 5047421Sroot p->p_pri = PUSER; 5057421Sroot setrun(p); 5067421Sroot out: 5077421Sroot splx(s); 5087421Sroot } 5097421Sroot 5107421Sroot /* 5117421Sroot * Returns true if the current 5127421Sroot * process has a signal to process. 5137421Sroot * The signal to process is put in p_cursig. 5147421Sroot * This is asked at least once each time a process enters the 5157421Sroot * system (though this can usually be done without actually 5167421Sroot * calling issig by checking the pending signal masks.) 5177421Sroot * A signal does not do anything 5187421Sroot * directly to a process; it sets 5197421Sroot * a flag that asks the process to 5207421Sroot * do something to itself. 5217421Sroot */ 5227421Sroot issig() 5237421Sroot { 5247421Sroot register struct proc *p; 5257421Sroot register int sig; 526*17153Sbloom int sigbits, mask; 5277421Sroot 5287421Sroot p = u.u_procp; 5297421Sroot for (;;) { 53014782Ssam sigbits = p->p_sig &~ p->p_sigmask; 5317421Sroot if ((p->p_flag&STRC) == 0) 53214782Ssam sigbits &= ~p->p_sigignore; 5337421Sroot if (p->p_flag&SVFORK) 5347421Sroot #define bit(a) (1<<(a-1)) 5357421Sroot sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 5367421Sroot if (sigbits == 0) 5377421Sroot break; 53812882Ssam sig = ffs(sigbits); 539*17153Sbloom mask = sigmask(sig); 540*17153Sbloom p->p_sig &= ~mask; /* take the signal! */ 5417421Sroot p->p_cursig = sig; 54212882Ssam if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { 5437421Sroot /* 5447421Sroot * If traced, always stop, and stay 5457421Sroot * stopped until released by the parent. 5467421Sroot */ 5477421Sroot do { 5487421Sroot stop(p); 5497421Sroot swtch(); 5507421Sroot } while (!procxmt() && p->p_flag&STRC); 5517421Sroot 5527421Sroot /* 55314782Ssam * If the traced bit got turned off, 55414782Ssam * then put the signal taken above back into p_sig 55514782Ssam * and go back up to the top to rescan signals. 55614782Ssam * This ensures that p_sig* and u_signal are consistent. 5577421Sroot */ 55814782Ssam if ((p->p_flag&STRC) == 0) { 559*17153Sbloom p->p_sig |= mask; 5607421Sroot continue; 5617421Sroot } 5627421Sroot 5637421Sroot /* 5647421Sroot * If parent wants us to take the signal, 5657421Sroot * then it will leave it in p->p_cursig; 5667421Sroot * otherwise we just look for signals again. 5677421Sroot */ 5687421Sroot sig = p->p_cursig; 5697421Sroot if (sig == 0) 5707421Sroot continue; 57114782Ssam 57214782Ssam /* 57314782Ssam * If signal is being masked put it back 57414782Ssam * into p_sig and look for other signals. 57514782Ssam */ 576*17153Sbloom mask = sigmask(sig); 577*17153Sbloom if (p->p_sigmask & mask) { 578*17153Sbloom p->p_sig |= mask; 57914782Ssam continue; 58014782Ssam } 5817421Sroot } 5827421Sroot switch (u.u_signal[sig]) { 5837421Sroot 5847421Sroot case SIG_DFL: 5857421Sroot /* 5867421Sroot * Don't take default actions on system processes. 5877421Sroot */ 5887421Sroot if (p->p_ppid == 0) 5897421Sroot break; 5907421Sroot switch (sig) { 5917421Sroot 5927421Sroot case SIGTSTP: 5937421Sroot case SIGTTIN: 5947421Sroot case SIGTTOU: 5957421Sroot /* 5967421Sroot * Children of init aren't allowed to stop 5977421Sroot * on signals from the keyboard. 5987421Sroot */ 5997421Sroot if (p->p_pptr == &proc[1]) { 6007421Sroot psignal(p, SIGKILL); 6017421Sroot continue; 6027421Sroot } 6037421Sroot /* fall into ... */ 6047421Sroot 6057421Sroot case SIGSTOP: 6067421Sroot if (p->p_flag&STRC) 6077421Sroot continue; 6087421Sroot stop(p); 6097421Sroot swtch(); 6107421Sroot continue; 6117421Sroot 6127421Sroot case SIGCONT: 6137421Sroot case SIGCHLD: 61412882Ssam case SIGURG: 61512951Ssam case SIGIO: 6167421Sroot /* 6177421Sroot * These signals are normally not 6187421Sroot * sent if the action is the default. 6197421Sroot */ 6207421Sroot continue; /* == ignore */ 6217421Sroot 6227421Sroot default: 6237421Sroot goto send; 6247421Sroot } 6257421Sroot /*NOTREACHED*/ 6267421Sroot 6277421Sroot case SIG_HOLD: 6287421Sroot case SIG_IGN: 6297421Sroot /* 6307421Sroot * Masking above should prevent us 6317421Sroot * ever trying to take action on a held 6327421Sroot * or ignored signal, unless process is traced. 6337421Sroot */ 6347421Sroot if ((p->p_flag&STRC) == 0) 6357421Sroot printf("issig\n"); 6367421Sroot continue; 6377421Sroot 6387421Sroot default: 6397421Sroot /* 6407421Sroot * This signal has an action, let 6417421Sroot * psig process it. 6427421Sroot */ 6437421Sroot goto send; 6447421Sroot } 6457421Sroot /*NOTREACHED*/ 6467421Sroot } 6477421Sroot /* 6487421Sroot * Didn't find a signal to send. 6497421Sroot */ 6507421Sroot p->p_cursig = 0; 6517421Sroot return (0); 6527421Sroot 6537421Sroot send: 6547421Sroot /* 6557421Sroot * Let psig process the signal. 6567421Sroot */ 6577421Sroot return (sig); 6587421Sroot } 6597421Sroot 6607421Sroot /* 6617421Sroot * Put the argument process into the stopped 6627421Sroot * state and notify the parent via wakeup and/or signal. 6637421Sroot */ 6647421Sroot stop(p) 6657421Sroot register struct proc *p; 6667421Sroot { 6677421Sroot 6687421Sroot p->p_stat = SSTOP; 6697421Sroot p->p_flag &= ~SWTED; 6707421Sroot wakeup((caddr_t)p->p_pptr); 6717421Sroot /* 6727421Sroot * Avoid sending signal to parent if process is traced 6737421Sroot */ 6747421Sroot if (p->p_flag&STRC) 6757421Sroot return; 6767421Sroot psignal(p->p_pptr, SIGCHLD); 6777421Sroot } 6787421Sroot 6797421Sroot /* 6807421Sroot * Perform the action specified by 6817421Sroot * the current signal. 6827421Sroot * The usual sequence is: 6837421Sroot * if (issig()) 6847421Sroot * psig(); 6857421Sroot * The signal bit has already been cleared by issig, 6867421Sroot * and the current signal number stored in p->p_cursig. 6877421Sroot */ 6887421Sroot psig() 6897421Sroot { 69012882Ssam register struct proc *p = u.u_procp; 69112882Ssam register int sig = p->p_cursig; 692*17153Sbloom int mask = sigmask(sig), returnmask; 6937421Sroot register int (*action)(); 6947421Sroot 69512882Ssam if (sig == 0) 6967421Sroot panic("psig"); 69712882Ssam action = u.u_signal[sig]; 6987421Sroot if (action != SIG_DFL) { 699*17153Sbloom if (action == SIG_IGN || (p->p_sigmask & mask)) 7007421Sroot panic("psig action"); 7017421Sroot u.u_error = 0; 7027421Sroot /* 70312882Ssam * Set the new mask value and also defer further 70412882Ssam * occurences of this signal (unless we're simulating 70512882Ssam * the old signal facilities). 70612882Ssam * 70712882Ssam * Special case: user has done a sigpause. Here the 70812882Ssam * current mask is not of interest, but rather the 70912882Ssam * mask from before the sigpause is what we want restored 71012882Ssam * after the signal processing is completed. 7117421Sroot */ 712*17153Sbloom (void) splhigh(); 71312882Ssam if (p->p_flag & SOUSIG) { 71412882Ssam if (sig != SIGILL && sig != SIGTRAP) { 71512882Ssam u.u_signal[sig] = SIG_DFL; 716*17153Sbloom p->p_sigcatch &= ~mask; 71712882Ssam } 718*17153Sbloom mask = 0; 7197421Sroot } 72012882Ssam if (p->p_flag & SOMASK) { 72112882Ssam returnmask = u.u_oldmask; 72212882Ssam p->p_flag &= ~SOMASK; 72312882Ssam } else 72412882Ssam returnmask = p->p_sigmask; 725*17153Sbloom p->p_sigmask |= u.u_sigmask[sig] | mask; 72612882Ssam (void) spl0(); 7278032Sroot u.u_ru.ru_nsignals++; 72812882Ssam sendsig(action, sig, returnmask); 72912882Ssam p->p_cursig = 0; 7307421Sroot return; 7317421Sroot } 7327421Sroot u.u_acflag |= AXSIG; 73312882Ssam switch (sig) { 7347421Sroot 7357421Sroot case SIGILL: 7367421Sroot case SIGIOT: 7377421Sroot case SIGBUS: 7387421Sroot case SIGQUIT: 7397421Sroot case SIGTRAP: 7407421Sroot case SIGEMT: 7417421Sroot case SIGFPE: 7427421Sroot case SIGSEGV: 7437421Sroot case SIGSYS: 74412882Ssam u.u_arg[0] = sig; 7457421Sroot if (core()) 74612882Ssam sig += 0200; 7477421Sroot } 74812882Ssam exit(sig); 7497421Sroot } 7507421Sroot 7517421Sroot /* 7527421Sroot * Create a core image on the file "core" 7537421Sroot * If you are looking for protection glitches, 7547421Sroot * there are probably a wealth of them here 7557421Sroot * when this occurs to a suid command. 7567421Sroot * 7577421Sroot * It writes UPAGES block of the 7587421Sroot * user.h area followed by the entire 7597421Sroot * data+stack segments. 7607421Sroot */ 7617421Sroot core() 7627421Sroot { 7637421Sroot register struct inode *ip; 76416692Smckusick register struct nameidata *ndp = &u.u_nd; 7657421Sroot 76612639Ssam if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) 7677818Sroot return (0); 7688032Sroot if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= 7698032Sroot u.u_rlimit[RLIMIT_CORE].rlim_cur) 7707421Sroot return (0); 7717421Sroot u.u_error = 0; 77216692Smckusick ndp->ni_nameiop = CREATE | FOLLOW; 77316692Smckusick ndp->ni_segflg = UIO_SYSSPACE; 77416692Smckusick ndp->ni_dirp = "core"; 77516692Smckusick ip = namei(ndp); 7767421Sroot if (ip == NULL) { 7777421Sroot if (u.u_error) 7787421Sroot return (0); 77916692Smckusick ip = maknode(0644, ndp); 7807421Sroot if (ip==NULL) 7817421Sroot return (0); 7827421Sroot } 7837818Sroot if (access(ip, IWRITE) || 7847818Sroot (ip->i_mode&IFMT) != IFREG || 7857818Sroot ip->i_nlink != 1) { 7867421Sroot u.u_error = EFAULT; 7877818Sroot goto out; 7887818Sroot } 7899160Ssam itrunc(ip, (u_long)0); 7907818Sroot u.u_acflag |= ACORE; 79112882Ssam u.u_error = rdwri(UIO_WRITE, ip, 79212882Ssam (caddr_t)&u, 79312882Ssam ctob(UPAGES), 79412882Ssam 0, 1, (int *)0); 7958101Sroot if (u.u_error == 0) 7968644Sroot u.u_error = rdwri(UIO_WRITE, ip, 7978967Sroot (caddr_t)ctob(dptov(u.u_procp, 0)), 7988967Sroot ctob(u.u_dsize), 7998644Sroot ctob(UPAGES), 0, (int *)0); 8008101Sroot if (u.u_error == 0) 8018644Sroot u.u_error = rdwri(UIO_WRITE, ip, 8028967Sroot (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), 8038967Sroot ctob(u.u_ssize), 8048644Sroot ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); 8057818Sroot out: 8067421Sroot iput(ip); 8077818Sroot return (u.u_error == 0); 8087421Sroot } 809