1*17092Sbloom /* kern_sig.c 6.6 84/08/29 */ 27421Sroot 39755Ssam #include "../machine/reg.h" 49755Ssam #include "../machine/pte.h" 59755Ssam #include "../machine/psl.h" 69755Ssam 7*17092Sbloom #include "param.h" 8*17092Sbloom #include "systm.h" 9*17092Sbloom #include "dir.h" 10*17092Sbloom #include "user.h" 11*17092Sbloom #include "inode.h" 12*17092Sbloom #include "proc.h" 13*17092Sbloom #include "timeb.h" 14*17092Sbloom #include "times.h" 15*17092Sbloom #include "conf.h" 16*17092Sbloom #include "buf.h" 17*17092Sbloom #include "mount.h" 18*17092Sbloom #include "text.h" 19*17092Sbloom #include "seg.h" 20*17092Sbloom #include "vm.h" 21*17092Sbloom #include "acct.h" 22*17092Sbloom #include "uio.h" 23*17092Sbloom #include "kernel.h" 247421Sroot 2512951Ssam #define mask(s) (1 << ((s)-1)) 2612951Ssam #define cantmask (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP)) 2712951Ssam 2817013Smckusick /* 2917013Smckusick * Quick interface to signal handler. 3017013Smckusick */ 3117013Smckusick signal() 3217013Smckusick { 3317013Smckusick register struct a { 3417013Smckusick int signo; 3517013Smckusick int (*handler)(); /* signal handler */ 3617013Smckusick } *uap = (struct a *)u.u_ap; 3717013Smckusick struct sigvec vec; 3817013Smckusick register struct sigvec *sv = &vec; 3917013Smckusick register int sig; 4017013Smckusick 4117013Smckusick sig = uap->signo; 4217013Smckusick if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP || 4317013Smckusick (sig == SIGCONT && uap->handler == SIG_IGN)) { 4417013Smckusick u.u_error = EINVAL; 4517013Smckusick return; 4617013Smckusick } 4717013Smckusick sv->sv_handler = uap->handler; 4817013Smckusick sv->sv_mask = 0; 4917013Smckusick sv->sv_onstack = 0; 5017013Smckusick u.u_r.r_val1 = (int)u.u_signal[sig]; 5117013Smckusick setsigvec(sig, sv); 5217013Smckusick } 5317013Smckusick 5417013Smckusick /* 5517013Smckusick * Generalized interface signal handler. 5617013Smckusick */ 577499Sroot sigvec() 587421Sroot { 5912951Ssam register struct a { 6012882Ssam int signo; 6112951Ssam struct sigvec *nsv; 6212951Ssam struct sigvec *osv; 6312882Ssam } *uap = (struct a *)u.u_ap; 6412951Ssam struct sigvec vec; 6512951Ssam register struct sigvec *sv; 6612882Ssam register int sig; 677421Sroot 6812882Ssam sig = uap->signo; 6912951Ssam if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { 7012882Ssam u.u_error = EINVAL; 7112882Ssam return; 7212882Ssam } 7312951Ssam sv = &vec; 7412951Ssam if (uap->osv) { 7512951Ssam sv->sv_handler = u.u_signal[sig]; 7612951Ssam sv->sv_mask = u.u_sigmask[sig]; 7712951Ssam sv->sv_onstack = (u.u_sigonstack & mask(sig)) != 0; 7812951Ssam u.u_error = 7912951Ssam copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); 8012951Ssam if (u.u_error) 8112951Ssam return; 8212951Ssam } 8312951Ssam if (uap->nsv) { 8412951Ssam u.u_error = 8512951Ssam copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); 8612951Ssam if (u.u_error) 8712951Ssam return; 8812951Ssam if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { 8912951Ssam u.u_error = EINVAL; 9012951Ssam return; 9112951Ssam } 9212951Ssam setsigvec(sig, sv); 9312951Ssam } 947421Sroot } 957421Sroot 9612951Ssam setsigvec(sig, sv) 9712951Ssam int sig; 9812951Ssam register struct sigvec *sv; 9912882Ssam { 10012882Ssam register struct proc *p; 10112951Ssam register int bit; 10212882Ssam 10312951Ssam bit = mask(sig); 10412882Ssam p = u.u_procp; 10512882Ssam /* 10612882Ssam * Change setting atomically. 10712882Ssam */ 10812882Ssam (void) spl6(); 10912951Ssam u.u_signal[sig] = sv->sv_handler; 11012951Ssam u.u_sigmask[sig] = sv->sv_mask &~ cantmask; 11112951Ssam if (sv->sv_onstack) 11212951Ssam u.u_sigonstack |= bit; 11312951Ssam else 11412951Ssam u.u_sigonstack &= ~bit; 11512951Ssam if (sv->sv_handler == SIG_IGN) { 11612951Ssam p->p_sig &= ~bit; /* never to be seen again */ 11712951Ssam p->p_sigignore |= bit; 11812951Ssam p->p_sigcatch &= ~bit; 11912882Ssam } else { 12012951Ssam p->p_sigignore &= ~bit; 12112951Ssam if (sv->sv_handler == SIG_DFL) 12212951Ssam p->p_sigcatch &= ~bit; 12312882Ssam else 12412951Ssam p->p_sigcatch |= bit; 12512882Ssam } 12612882Ssam (void) spl0(); 12712882Ssam } 12812882Ssam 1297499Sroot sigblock() 1307421Sroot { 13112882Ssam struct a { 13212951Ssam int sigmask; 13312882Ssam } *uap = (struct a *)u.u_ap; 13412951Ssam register struct proc *p = u.u_procp; 1357499Sroot 13612882Ssam (void) spl6(); 13712882Ssam u.u_r.r_val1 = p->p_sigmask; 13812951Ssam p->p_sigmask |= uap->sigmask &~ cantmask; 13912882Ssam (void) spl0(); 1407499Sroot } 1417499Sroot 1427499Sroot sigsetmask() 1437499Sroot { 14412882Ssam struct a { 14512951Ssam int sigmask; 14612882Ssam } *uap = (struct a *)u.u_ap; 14712882Ssam register struct proc *p = u.u_procp; 1487499Sroot 14912882Ssam (void) spl6(); 15012882Ssam u.u_r.r_val1 = p->p_sigmask; 15112951Ssam p->p_sigmask = uap->sigmask &~ cantmask; 15212882Ssam (void) spl0(); 1537499Sroot } 1547499Sroot 1557499Sroot sigpause() 1567499Sroot { 15712882Ssam struct a { 15812951Ssam int sigmask; 15912882Ssam } *uap = (struct a *)u.u_ap; 16012882Ssam register struct proc *p = u.u_procp; 1617499Sroot 16212882Ssam /* 16312882Ssam * When returning from sigpause, we want 16412882Ssam * the old mask to be restored after the 16512882Ssam * signal handler has finished. Thus, we 16612882Ssam * save it here and mark the proc structure 16712882Ssam * to indicate this (should be in u.). 16812882Ssam */ 16912882Ssam u.u_oldmask = p->p_sigmask; 17012882Ssam p->p_flag |= SOMASK; 17112951Ssam p->p_sigmask = uap->sigmask &~ cantmask; 17212882Ssam for (;;) 17312882Ssam sleep((caddr_t)&u, PSLEP); 17412882Ssam /*NOTREACHED*/ 1757499Sroot } 17612951Ssam #undef cantmask 17712951Ssam #undef mask 1787499Sroot 1797499Sroot sigstack() 1807499Sroot { 18112951Ssam register struct a { 18212951Ssam struct sigstack *nss; 18312951Ssam struct sigstack *oss; 18412882Ssam } *uap = (struct a *)u.u_ap; 18512951Ssam struct sigstack ss; 1867499Sroot 18712951Ssam if (uap->oss) { 18812951Ssam u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, 18912951Ssam sizeof (struct sigstack)); 19012951Ssam if (u.u_error) 19112951Ssam return; 19212951Ssam } 19312951Ssam if (uap->nss) { 19412951Ssam u.u_error = 19512951Ssam copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); 19612951Ssam if (u.u_error == 0) 19712951Ssam u.u_sigstack = ss; 19812951Ssam } 1997499Sroot } 2007499Sroot 20113227Ssam /* KILL SHOULD BE UPDATED */ 20213227Ssam 2038032Sroot kill() 2048032Sroot { 20512882Ssam register struct a { 20612882Ssam int pid; 20712882Ssam int signo; 20812882Ssam } *uap = (struct a *)u.u_ap; 2098032Sroot 21013227Ssam u.u_error = kill1(uap->signo < 0, 21113227Ssam uap->signo < 0 ? -uap->signo : uap->signo, uap->pid); 2128032Sroot } 2138032Sroot 2148032Sroot killpg() 2158032Sroot { 2169989Ssam register struct a { 2179989Ssam int pgrp; 2189989Ssam int signo; 2199989Ssam } *uap = (struct a *)u.u_ap; 2208032Sroot 22112750Ssam u.u_error = kill1(1, uap->signo, uap->pgrp); 2228032Sroot } 2238032Sroot 22412882Ssam /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ 22512882Ssam 22612750Ssam kill1(ispgrp, signo, who) 2279989Ssam int ispgrp, signo, who; 2289989Ssam { 2299989Ssam register struct proc *p; 2309989Ssam int f, priv = 0; 2319989Ssam 23212835Ssam if (signo < 0 || signo > NSIG) 2339989Ssam return (EINVAL); 2349989Ssam if (who > 0 && !ispgrp) { 2359989Ssam p = pfind(who); 23614926Smckusick if (p == 0) 2379989Ssam return (ESRCH); 23814926Smckusick if (u.u_uid && u.u_uid != p->p_uid) 23914926Smckusick return (EPERM); 24012835Ssam if (signo) 24112835Ssam psignal(p, signo); 2429989Ssam return (0); 2437421Sroot } 2449989Ssam if (who == -1 && u.u_uid == 0) 2459989Ssam priv++, who = 0, ispgrp = 1; /* like sending to pgrp */ 2469989Ssam else if (who == 0) { 2477421Sroot /* 2487421Sroot * Zero process id means send to my process group. 2497421Sroot */ 2509989Ssam ispgrp = 1; 2519989Ssam who = u.u_procp->p_pgrp; 2529989Ssam if (who == 0) 2539989Ssam return (EINVAL); 2547421Sroot } 25516531Skarels for (f = 0, p = allproc; p != NULL; p = p->p_nxt) { 2569989Ssam if (!ispgrp) { 2579989Ssam if (p->p_pid != who) 2587421Sroot continue; 2599989Ssam } else if (p->p_pgrp != who && priv == 0 || p->p_ppid == 0 || 2609989Ssam (p->p_flag&SSYS) || (priv && p == u.u_procp)) 2617421Sroot continue; 2627421Sroot if (u.u_uid != 0 && u.u_uid != p->p_uid && 2639989Ssam (signo != SIGCONT || !inferior(p))) 2647421Sroot continue; 2657421Sroot f++; 26612835Ssam if (signo) 26712835Ssam psignal(p, signo); 2687421Sroot } 26912750Ssam return (f == 0 ? ESRCH : 0); 2707421Sroot } 2717421Sroot 2727421Sroot /* 2737421Sroot * Send the specified signal to 2747421Sroot * all processes with 'pgrp' as 2757421Sroot * process group. 2767421Sroot */ 2777421Sroot gsignal(pgrp, sig) 2787421Sroot register int pgrp; 2797421Sroot { 2807421Sroot register struct proc *p; 2817421Sroot 2827421Sroot if (pgrp == 0) 2837421Sroot return; 28416531Skarels for (p = allproc; p != NULL; p = p->p_nxt) 2857421Sroot if (p->p_pgrp == pgrp) 2867421Sroot psignal(p, sig); 2877421Sroot } 2887421Sroot 2897421Sroot /* 2907421Sroot * Send the specified signal to 2917421Sroot * the specified process. 2927421Sroot */ 2937421Sroot psignal(p, sig) 2947421Sroot register struct proc *p; 2957421Sroot register int sig; 2967421Sroot { 2977421Sroot register int s; 2987421Sroot register int (*action)(); 29912882Ssam int sigmask; 3007421Sroot 3017421Sroot if ((unsigned)sig >= NSIG) 3027421Sroot return; 30312882Ssam sigmask = 1 << (sig-1); 3047421Sroot 3057421Sroot /* 3067421Sroot * If proc is traced, always give parent a chance. 3077421Sroot */ 3087421Sroot if (p->p_flag & STRC) 3097421Sroot action = SIG_DFL; 3107421Sroot else { 3117421Sroot /* 31212882Ssam * If the signal is being ignored, 31312882Ssam * then we forget about it immediately. 3147421Sroot */ 31512882Ssam if (p->p_sigignore & sigmask) 3167421Sroot return; 31712882Ssam if (p->p_sigmask & sigmask) 31812882Ssam action = SIG_HOLD; 31912882Ssam else if (p->p_sigcatch & sigmask) 32012882Ssam action = SIG_CATCH; 32112882Ssam else 32212882Ssam action = SIG_DFL; 3237421Sroot } 3247421Sroot #define mask(sig) (1<<(sig-1)) 3257421Sroot #define stops (mask(SIGSTOP)|mask(SIGTSTP)|mask(SIGTTIN)|mask(SIGTTOU)) 3267421Sroot if (sig) { 3277421Sroot p->p_sig |= sigmask; 3287421Sroot switch (sig) { 3297421Sroot 3307421Sroot case SIGTERM: 33112882Ssam if ((p->p_flag&STRC) || action != SIG_DFL) 3327421Sroot break; 3337421Sroot /* fall into ... */ 3347421Sroot 3357421Sroot case SIGKILL: 3367421Sroot if (p->p_nice > NZERO) 3377421Sroot p->p_nice = NZERO; 3387421Sroot break; 3397421Sroot 3407421Sroot case SIGCONT: 3417421Sroot p->p_sig &= ~stops; 3427421Sroot break; 3437421Sroot 3447421Sroot case SIGSTOP: 3457421Sroot case SIGTSTP: 3467421Sroot case SIGTTIN: 3477421Sroot case SIGTTOU: 3487421Sroot p->p_sig &= ~mask(SIGCONT); 3497421Sroot break; 3507421Sroot } 3517421Sroot } 3527421Sroot #undef mask 3537421Sroot #undef stops 3547421Sroot /* 3557421Sroot * Defer further processing for signals which are held. 3567421Sroot */ 3577421Sroot if (action == SIG_HOLD) 3587421Sroot return; 3597421Sroot s = spl6(); 3607421Sroot switch (p->p_stat) { 3617421Sroot 3627421Sroot case SSLEEP: 3637421Sroot /* 3647421Sroot * If process is sleeping at negative priority 3657421Sroot * we can't interrupt the sleep... the signal will 3667421Sroot * be noticed when the process returns through 3677421Sroot * trap() or syscall(). 3687421Sroot */ 3697421Sroot if (p->p_pri <= PZERO) 3707421Sroot goto out; 3717421Sroot /* 3727421Sroot * Process is sleeping and traced... make it runnable 3737421Sroot * so it can discover the signal in issig() and stop 3747421Sroot * for the parent. 3757421Sroot */ 3767421Sroot if (p->p_flag&STRC) 3777421Sroot goto run; 3787421Sroot switch (sig) { 3797421Sroot 3807421Sroot case SIGSTOP: 3817421Sroot case SIGTSTP: 3827421Sroot case SIGTTIN: 3837421Sroot case SIGTTOU: 3847421Sroot /* 3857421Sroot * These are the signals which by default 3867421Sroot * stop a process. 3877421Sroot */ 3887421Sroot if (action != SIG_DFL) 3897421Sroot goto run; 3907421Sroot /* 3917421Sroot * Don't clog system with children of init 3927421Sroot * stopped from the keyboard. 3937421Sroot */ 3947421Sroot if (sig != SIGSTOP && p->p_pptr == &proc[1]) { 3957421Sroot psignal(p, SIGKILL); 3967421Sroot p->p_sig &= ~sigmask; 3977421Sroot splx(s); 3987421Sroot return; 3997421Sroot } 4007421Sroot /* 4017421Sroot * If a child in vfork(), stopping could 4027421Sroot * cause deadlock. 4037421Sroot */ 4047421Sroot if (p->p_flag&SVFORK) 4057421Sroot goto out; 4067421Sroot p->p_sig &= ~sigmask; 4077421Sroot p->p_cursig = sig; 4087421Sroot stop(p); 4097421Sroot goto out; 4107421Sroot 4117421Sroot case SIGIO: 4127421Sroot case SIGURG: 4137421Sroot case SIGCHLD: 4147421Sroot /* 4157421Sroot * These signals are special in that they 4167421Sroot * don't get propogated... if the process 4177421Sroot * isn't interested, forget it. 4187421Sroot */ 4197421Sroot if (action != SIG_DFL) 4207421Sroot goto run; 4217421Sroot p->p_sig &= ~sigmask; /* take it away */ 4227421Sroot goto out; 4237421Sroot 4247421Sroot default: 4257421Sroot /* 4267421Sroot * All other signals cause the process to run 4277421Sroot */ 4287421Sroot goto run; 4297421Sroot } 4307421Sroot /*NOTREACHED*/ 4317421Sroot 4327421Sroot case SSTOP: 4337421Sroot /* 4347421Sroot * If traced process is already stopped, 4357421Sroot * then no further action is necessary. 4367421Sroot */ 4377421Sroot if (p->p_flag&STRC) 4387421Sroot goto out; 4397421Sroot switch (sig) { 4407421Sroot 4417421Sroot case SIGKILL: 4427421Sroot /* 4437421Sroot * Kill signal always sets processes running. 4447421Sroot */ 4457421Sroot goto run; 4467421Sroot 4477421Sroot case SIGCONT: 4487421Sroot /* 4497421Sroot * If the process catches SIGCONT, let it handle 4507421Sroot * the signal itself. If it isn't waiting on 4517421Sroot * an event, then it goes back to run state. 4527421Sroot * Otherwise, process goes back to sleep state. 4537421Sroot */ 4547421Sroot if (action != SIG_DFL || p->p_wchan == 0) 4557421Sroot goto run; 4567421Sroot p->p_stat = SSLEEP; 4577421Sroot goto out; 4587421Sroot 4597421Sroot case SIGSTOP: 4607421Sroot case SIGTSTP: 4617421Sroot case SIGTTIN: 4627421Sroot case SIGTTOU: 4637421Sroot /* 4647421Sroot * Already stopped, don't need to stop again. 4657421Sroot * (If we did the shell could get confused.) 4667421Sroot */ 4677421Sroot p->p_sig &= ~sigmask; /* take it away */ 4687421Sroot goto out; 4697421Sroot 4707421Sroot default: 4717421Sroot /* 4727421Sroot * If process is sleeping interruptibly, then 4737421Sroot * unstick it so that when it is continued 4747421Sroot * it can look at the signal. 4757421Sroot * But don't setrun the process as its not to 4767421Sroot * be unstopped by the signal alone. 4777421Sroot */ 4787421Sroot if (p->p_wchan && p->p_pri > PZERO) 4797421Sroot unsleep(p); 4807421Sroot goto out; 4817421Sroot } 4827421Sroot /*NOTREACHED*/ 4837421Sroot 4847421Sroot default: 4857421Sroot /* 4867421Sroot * SRUN, SIDL, SZOMB do nothing with the signal, 4877421Sroot * other than kicking ourselves if we are running. 4887421Sroot * It will either never be noticed, or noticed very soon. 4897421Sroot */ 4907421Sroot if (p == u.u_procp && !noproc) 4918444Sroot #include "../vax/mtpr.h" 4927421Sroot aston(); 4937421Sroot goto out; 4947421Sroot } 4957421Sroot /*NOTREACHED*/ 4967421Sroot run: 4977421Sroot /* 4987421Sroot * Raise priority to at least PUSER. 4997421Sroot */ 5007421Sroot if (p->p_pri > PUSER) 5017421Sroot if ((p != u.u_procp || noproc) && p->p_stat == SRUN && 5027421Sroot (p->p_flag & SLOAD)) { 5037421Sroot remrq(p); 5047421Sroot p->p_pri = PUSER; 5057421Sroot setrq(p); 5067421Sroot } else 5077421Sroot p->p_pri = PUSER; 5087421Sroot setrun(p); 5097421Sroot out: 5107421Sroot splx(s); 5117421Sroot } 5127421Sroot 5137421Sroot /* 5147421Sroot * Returns true if the current 5157421Sroot * process has a signal to process. 5167421Sroot * The signal to process is put in p_cursig. 5177421Sroot * This is asked at least once each time a process enters the 5187421Sroot * system (though this can usually be done without actually 5197421Sroot * calling issig by checking the pending signal masks.) 5207421Sroot * A signal does not do anything 5217421Sroot * directly to a process; it sets 5227421Sroot * a flag that asks the process to 5237421Sroot * do something to itself. 5247421Sroot */ 5257421Sroot issig() 5267421Sroot { 5277421Sroot register struct proc *p; 5287421Sroot register int sig; 52912882Ssam int sigbits, sigmask; 5307421Sroot 5317421Sroot p = u.u_procp; 5327421Sroot for (;;) { 53314782Ssam sigbits = p->p_sig &~ p->p_sigmask; 5347421Sroot if ((p->p_flag&STRC) == 0) 53514782Ssam sigbits &= ~p->p_sigignore; 5367421Sroot if (p->p_flag&SVFORK) 5377421Sroot #define bit(a) (1<<(a-1)) 5387421Sroot sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 5397421Sroot if (sigbits == 0) 5407421Sroot break; 54112882Ssam sig = ffs(sigbits); 54212882Ssam sigmask = 1 << (sig-1); 5437421Sroot p->p_sig &= ~sigmask; /* take the signal! */ 5447421Sroot p->p_cursig = sig; 54512882Ssam if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { 5467421Sroot /* 5477421Sroot * If traced, always stop, and stay 5487421Sroot * stopped until released by the parent. 5497421Sroot */ 5507421Sroot do { 5517421Sroot stop(p); 5527421Sroot swtch(); 5537421Sroot } while (!procxmt() && p->p_flag&STRC); 5547421Sroot 5557421Sroot /* 55614782Ssam * If the traced bit got turned off, 55714782Ssam * then put the signal taken above back into p_sig 55814782Ssam * and go back up to the top to rescan signals. 55914782Ssam * This ensures that p_sig* and u_signal are consistent. 5607421Sroot */ 56114782Ssam if ((p->p_flag&STRC) == 0) { 5627421Sroot p->p_sig |= sigmask; 5637421Sroot continue; 5647421Sroot } 5657421Sroot 5667421Sroot /* 5677421Sroot * If parent wants us to take the signal, 5687421Sroot * then it will leave it in p->p_cursig; 5697421Sroot * otherwise we just look for signals again. 5707421Sroot */ 5717421Sroot sig = p->p_cursig; 5727421Sroot if (sig == 0) 5737421Sroot continue; 57414782Ssam 57514782Ssam /* 57614782Ssam * If signal is being masked put it back 57714782Ssam * into p_sig and look for other signals. 57814782Ssam */ 57914782Ssam sigmask = 1 << (sig-1); 58014782Ssam if (p->p_sigmask & sigmask) { 58114782Ssam p->p_sig |= sigmask; 58214782Ssam continue; 58314782Ssam } 5847421Sroot } 5857421Sroot switch (u.u_signal[sig]) { 5867421Sroot 5877421Sroot case SIG_DFL: 5887421Sroot /* 5897421Sroot * Don't take default actions on system processes. 5907421Sroot */ 5917421Sroot if (p->p_ppid == 0) 5927421Sroot break; 5937421Sroot switch (sig) { 5947421Sroot 5957421Sroot case SIGTSTP: 5967421Sroot case SIGTTIN: 5977421Sroot case SIGTTOU: 5987421Sroot /* 5997421Sroot * Children of init aren't allowed to stop 6007421Sroot * on signals from the keyboard. 6017421Sroot */ 6027421Sroot if (p->p_pptr == &proc[1]) { 6037421Sroot psignal(p, SIGKILL); 6047421Sroot continue; 6057421Sroot } 6067421Sroot /* fall into ... */ 6077421Sroot 6087421Sroot case SIGSTOP: 6097421Sroot if (p->p_flag&STRC) 6107421Sroot continue; 6117421Sroot stop(p); 6127421Sroot swtch(); 6137421Sroot continue; 6147421Sroot 6157421Sroot case SIGCONT: 6167421Sroot case SIGCHLD: 61712882Ssam case SIGURG: 61812951Ssam case SIGIO: 6197421Sroot /* 6207421Sroot * These signals are normally not 6217421Sroot * sent if the action is the default. 6227421Sroot */ 6237421Sroot continue; /* == ignore */ 6247421Sroot 6257421Sroot default: 6267421Sroot goto send; 6277421Sroot } 6287421Sroot /*NOTREACHED*/ 6297421Sroot 6307421Sroot case SIG_HOLD: 6317421Sroot case SIG_IGN: 6327421Sroot /* 6337421Sroot * Masking above should prevent us 6347421Sroot * ever trying to take action on a held 6357421Sroot * or ignored signal, unless process is traced. 6367421Sroot */ 6377421Sroot if ((p->p_flag&STRC) == 0) 6387421Sroot printf("issig\n"); 6397421Sroot continue; 6407421Sroot 6417421Sroot default: 6427421Sroot /* 6437421Sroot * This signal has an action, let 6447421Sroot * psig process it. 6457421Sroot */ 6467421Sroot goto send; 6477421Sroot } 6487421Sroot /*NOTREACHED*/ 6497421Sroot } 6507421Sroot /* 6517421Sroot * Didn't find a signal to send. 6527421Sroot */ 6537421Sroot p->p_cursig = 0; 6547421Sroot return (0); 6557421Sroot 6567421Sroot send: 6577421Sroot /* 6587421Sroot * Let psig process the signal. 6597421Sroot */ 6607421Sroot return (sig); 6617421Sroot } 6627421Sroot 6637421Sroot /* 6647421Sroot * Put the argument process into the stopped 6657421Sroot * state and notify the parent via wakeup and/or signal. 6667421Sroot */ 6677421Sroot stop(p) 6687421Sroot register struct proc *p; 6697421Sroot { 6707421Sroot 6717421Sroot p->p_stat = SSTOP; 6727421Sroot p->p_flag &= ~SWTED; 6737421Sroot wakeup((caddr_t)p->p_pptr); 6747421Sroot /* 6757421Sroot * Avoid sending signal to parent if process is traced 6767421Sroot */ 6777421Sroot if (p->p_flag&STRC) 6787421Sroot return; 6797421Sroot psignal(p->p_pptr, SIGCHLD); 6807421Sroot } 6817421Sroot 6827421Sroot /* 6837421Sroot * Perform the action specified by 6847421Sroot * the current signal. 6857421Sroot * The usual sequence is: 6867421Sroot * if (issig()) 6877421Sroot * psig(); 6887421Sroot * The signal bit has already been cleared by issig, 6897421Sroot * and the current signal number stored in p->p_cursig. 6907421Sroot */ 6917421Sroot psig() 6927421Sroot { 69312882Ssam register struct proc *p = u.u_procp; 69412882Ssam register int sig = p->p_cursig; 69512882Ssam int sigmask = 1 << (sig - 1), returnmask; 6967421Sroot register int (*action)(); 6977421Sroot 69812882Ssam if (sig == 0) 6997421Sroot panic("psig"); 70012882Ssam action = u.u_signal[sig]; 7017421Sroot if (action != SIG_DFL) { 70212882Ssam if (action == SIG_IGN || (p->p_sigmask & sigmask)) 7037421Sroot panic("psig action"); 7047421Sroot u.u_error = 0; 7057421Sroot /* 70612882Ssam * Set the new mask value and also defer further 70712882Ssam * occurences of this signal (unless we're simulating 70812882Ssam * the old signal facilities). 70912882Ssam * 71012882Ssam * Special case: user has done a sigpause. Here the 71112882Ssam * current mask is not of interest, but rather the 71212882Ssam * mask from before the sigpause is what we want restored 71312882Ssam * after the signal processing is completed. 7147421Sroot */ 71512882Ssam (void) spl6(); 71612882Ssam if (p->p_flag & SOUSIG) { 71712882Ssam if (sig != SIGILL && sig != SIGTRAP) { 71812882Ssam u.u_signal[sig] = SIG_DFL; 71912882Ssam p->p_sigcatch &= ~sigmask; 72012882Ssam } 72112882Ssam sigmask = 0; 7227421Sroot } 72312882Ssam if (p->p_flag & SOMASK) { 72412882Ssam returnmask = u.u_oldmask; 72512882Ssam p->p_flag &= ~SOMASK; 72612882Ssam } else 72712882Ssam returnmask = p->p_sigmask; 72812951Ssam p->p_sigmask |= u.u_sigmask[sig] | sigmask; 72912882Ssam (void) spl0(); 7308032Sroot u.u_ru.ru_nsignals++; 73112882Ssam sendsig(action, sig, returnmask); 73212882Ssam p->p_cursig = 0; 7337421Sroot return; 7347421Sroot } 7357421Sroot u.u_acflag |= AXSIG; 73612882Ssam switch (sig) { 7377421Sroot 7387421Sroot case SIGILL: 7397421Sroot case SIGIOT: 7407421Sroot case SIGBUS: 7417421Sroot case SIGQUIT: 7427421Sroot case SIGTRAP: 7437421Sroot case SIGEMT: 7447421Sroot case SIGFPE: 7457421Sroot case SIGSEGV: 7467421Sroot case SIGSYS: 74712882Ssam u.u_arg[0] = sig; 7487421Sroot if (core()) 74912882Ssam sig += 0200; 7507421Sroot } 75112882Ssam exit(sig); 7527421Sroot } 7537421Sroot 7547421Sroot /* 7557421Sroot * Create a core image on the file "core" 7567421Sroot * If you are looking for protection glitches, 7577421Sroot * there are probably a wealth of them here 7587421Sroot * when this occurs to a suid command. 7597421Sroot * 7607421Sroot * It writes UPAGES block of the 7617421Sroot * user.h area followed by the entire 7627421Sroot * data+stack segments. 7637421Sroot */ 7647421Sroot core() 7657421Sroot { 7667421Sroot register struct inode *ip; 76716692Smckusick register struct nameidata *ndp = &u.u_nd; 7687421Sroot 76912639Ssam if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) 7707818Sroot return (0); 7718032Sroot if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= 7728032Sroot u.u_rlimit[RLIMIT_CORE].rlim_cur) 7737421Sroot return (0); 7747421Sroot u.u_error = 0; 77516692Smckusick ndp->ni_nameiop = CREATE | FOLLOW; 77616692Smckusick ndp->ni_segflg = UIO_SYSSPACE; 77716692Smckusick ndp->ni_dirp = "core"; 77816692Smckusick ip = namei(ndp); 7797421Sroot if (ip == NULL) { 7807421Sroot if (u.u_error) 7817421Sroot return (0); 78216692Smckusick ip = maknode(0644, ndp); 7837421Sroot if (ip==NULL) 7847421Sroot return (0); 7857421Sroot } 7867818Sroot if (access(ip, IWRITE) || 7877818Sroot (ip->i_mode&IFMT) != IFREG || 7887818Sroot ip->i_nlink != 1) { 7897421Sroot u.u_error = EFAULT; 7907818Sroot goto out; 7917818Sroot } 7929160Ssam itrunc(ip, (u_long)0); 7937818Sroot u.u_acflag |= ACORE; 79412882Ssam u.u_error = rdwri(UIO_WRITE, ip, 79512882Ssam (caddr_t)&u, 79612882Ssam ctob(UPAGES), 79712882Ssam 0, 1, (int *)0); 7988101Sroot if (u.u_error == 0) 7998644Sroot u.u_error = rdwri(UIO_WRITE, ip, 8008967Sroot (caddr_t)ctob(dptov(u.u_procp, 0)), 8018967Sroot ctob(u.u_dsize), 8028644Sroot ctob(UPAGES), 0, (int *)0); 8038101Sroot if (u.u_error == 0) 8048644Sroot u.u_error = rdwri(UIO_WRITE, ip, 8058967Sroot (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), 8068967Sroot ctob(u.u_ssize), 8078644Sroot ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); 8087818Sroot out: 8097421Sroot iput(ip); 8107818Sroot return (u.u_error == 0); 8117421Sroot } 812