123374Smckusick /* 237580Smckusick * Copyright (c) 1982, 1986, 1989 Regents of the University of California. 337580Smckusick * All rights reserved. 423374Smckusick * 537580Smckusick * Redistribution and use in source and binary forms are permitted 637580Smckusick * provided that the above copyright notice and this paragraph are 737580Smckusick * duplicated in all such forms and that any documentation, 837580Smckusick * advertising materials, and other materials related to such 937580Smckusick * distribution and use acknowledge that the software was developed 1037580Smckusick * by the University of California, Berkeley. The name of the 1137580Smckusick * University may not be used to endorse or promote products derived 1237580Smckusick * from this software without specific prior written permission. 1337580Smckusick * THIS SOFTWARE IS PROVIDED ``AS IS'' AND WITHOUT ANY EXPRESS OR 1437580Smckusick * IMPLIED WARRANTIES, INCLUDING, WITHOUT LIMITATION, THE IMPLIED 1537580Smckusick * WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE. 1637580Smckusick * 17*37728Smckusick * @(#)kern_sig.c 7.8 (Berkeley) 05/09/89 1823374Smckusick */ 197421Sroot 2017092Sbloom #include "param.h" 2117092Sbloom #include "systm.h" 2217092Sbloom #include "user.h" 2337580Smckusick #include "vnode.h" 2417092Sbloom #include "proc.h" 2517092Sbloom #include "timeb.h" 2617092Sbloom #include "times.h" 2717092Sbloom #include "buf.h" 2817092Sbloom #include "mount.h" 2917092Sbloom #include "text.h" 3017092Sbloom #include "seg.h" 3117092Sbloom #include "vm.h" 3217092Sbloom #include "acct.h" 3317092Sbloom #include "uio.h" 3437580Smckusick #include "file.h" 3517092Sbloom #include "kernel.h" 367421Sroot 3737581Smckusick #include "machine/reg.h" 3837581Smckusick #include "machine/pte.h" 3937581Smckusick #include "machine/psl.h" 4037581Smckusick #include "machine/mtpr.h" 4137581Smckusick 4217153Sbloom #define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)) 4326276Skarels #define stopsigmask (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \ 4426276Skarels sigmask(SIGTTIN)|sigmask(SIGTTOU)) 4512951Ssam 4617013Smckusick /* 4717013Smckusick * Generalized interface signal handler. 4817013Smckusick */ 497499Sroot sigvec() 507421Sroot { 5112951Ssam register struct a { 5212882Ssam int signo; 5312951Ssam struct sigvec *nsv; 5412951Ssam struct sigvec *osv; 5512882Ssam } *uap = (struct a *)u.u_ap; 5612951Ssam struct sigvec vec; 5712951Ssam register struct sigvec *sv; 5812882Ssam register int sig; 5918308Smckusick int bit; 607421Sroot 6112882Ssam sig = uap->signo; 6212951Ssam if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { 6312882Ssam u.u_error = EINVAL; 6412882Ssam return; 6512882Ssam } 6612951Ssam sv = &vec; 6712951Ssam if (uap->osv) { 6812951Ssam sv->sv_handler = u.u_signal[sig]; 6912951Ssam sv->sv_mask = u.u_sigmask[sig]; 7018308Smckusick bit = sigmask(sig); 7118308Smckusick sv->sv_flags = 0; 7218308Smckusick if ((u.u_sigonstack & bit) != 0) 7318308Smckusick sv->sv_flags |= SV_ONSTACK; 7418308Smckusick if ((u.u_sigintr & bit) != 0) 7518308Smckusick sv->sv_flags |= SV_INTERRUPT; 7612951Ssam u.u_error = 7712951Ssam copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); 7812951Ssam if (u.u_error) 7912951Ssam return; 8012951Ssam } 8112951Ssam if (uap->nsv) { 8212951Ssam u.u_error = 8312951Ssam copyin((caddr_t)uap->nsv, (caddr_t)sv, sizeof (vec)); 8412951Ssam if (u.u_error) 8512951Ssam return; 8612951Ssam if (sig == SIGCONT && sv->sv_handler == SIG_IGN) { 8712951Ssam u.u_error = EINVAL; 8812951Ssam return; 8912951Ssam } 9012951Ssam setsigvec(sig, sv); 9112951Ssam } 927421Sroot } 937421Sroot 9412951Ssam setsigvec(sig, sv) 9512951Ssam int sig; 9612951Ssam register struct sigvec *sv; 9712882Ssam { 9812882Ssam register struct proc *p; 9912951Ssam register int bit; 10012882Ssam 10117153Sbloom bit = sigmask(sig); 10212882Ssam p = u.u_procp; 10312882Ssam /* 10412882Ssam * Change setting atomically. 10512882Ssam */ 10617153Sbloom (void) splhigh(); 10712951Ssam u.u_signal[sig] = sv->sv_handler; 10812951Ssam u.u_sigmask[sig] = sv->sv_mask &~ cantmask; 10918308Smckusick if (sv->sv_flags & SV_INTERRUPT) 11018308Smckusick u.u_sigintr |= bit; 11118308Smckusick else 11218308Smckusick u.u_sigintr &= ~bit; 11318308Smckusick if (sv->sv_flags & SV_ONSTACK) 11412951Ssam u.u_sigonstack |= bit; 11512951Ssam else 11612951Ssam u.u_sigonstack &= ~bit; 11712951Ssam if (sv->sv_handler == SIG_IGN) { 11812951Ssam p->p_sig &= ~bit; /* never to be seen again */ 11912951Ssam p->p_sigignore |= bit; 12012951Ssam p->p_sigcatch &= ~bit; 12112882Ssam } else { 12212951Ssam p->p_sigignore &= ~bit; 12312951Ssam if (sv->sv_handler == SIG_DFL) 12412951Ssam p->p_sigcatch &= ~bit; 12512882Ssam else 12612951Ssam p->p_sigcatch |= bit; 12712882Ssam } 12812882Ssam (void) spl0(); 12912882Ssam } 13012882Ssam 1317499Sroot sigblock() 1327421Sroot { 13312882Ssam struct a { 13417153Sbloom int mask; 13512882Ssam } *uap = (struct a *)u.u_ap; 13612951Ssam register struct proc *p = u.u_procp; 1377499Sroot 13817153Sbloom (void) splhigh(); 13912882Ssam u.u_r.r_val1 = p->p_sigmask; 14017153Sbloom p->p_sigmask |= uap->mask &~ cantmask; 14112882Ssam (void) spl0(); 1427499Sroot } 1437499Sroot 1447499Sroot sigsetmask() 1457499Sroot { 14612882Ssam struct a { 14717153Sbloom int mask; 14812882Ssam } *uap = (struct a *)u.u_ap; 14912882Ssam register struct proc *p = u.u_procp; 1507499Sroot 15117153Sbloom (void) splhigh(); 15212882Ssam u.u_r.r_val1 = p->p_sigmask; 15317153Sbloom p->p_sigmask = uap->mask &~ cantmask; 15412882Ssam (void) spl0(); 1557499Sroot } 1567499Sroot 1577499Sroot sigpause() 1587499Sroot { 15912882Ssam struct a { 16017153Sbloom int mask; 16112882Ssam } *uap = (struct a *)u.u_ap; 16212882Ssam register struct proc *p = u.u_procp; 1637499Sroot 16412882Ssam /* 16512882Ssam * When returning from sigpause, we want 16612882Ssam * the old mask to be restored after the 16712882Ssam * signal handler has finished. Thus, we 16812882Ssam * save it here and mark the proc structure 16912882Ssam * to indicate this (should be in u.). 17012882Ssam */ 17112882Ssam u.u_oldmask = p->p_sigmask; 17212882Ssam p->p_flag |= SOMASK; 17317153Sbloom p->p_sigmask = uap->mask &~ cantmask; 17412882Ssam for (;;) 17512882Ssam sleep((caddr_t)&u, PSLEP); 17612882Ssam /*NOTREACHED*/ 1777499Sroot } 17812951Ssam #undef cantmask 1797499Sroot 1807499Sroot sigstack() 1817499Sroot { 18212951Ssam register struct a { 18312951Ssam struct sigstack *nss; 18412951Ssam struct sigstack *oss; 18512882Ssam } *uap = (struct a *)u.u_ap; 18612951Ssam struct sigstack ss; 1877499Sroot 18812951Ssam if (uap->oss) { 18912951Ssam u.u_error = copyout((caddr_t)&u.u_sigstack, (caddr_t)uap->oss, 19012951Ssam sizeof (struct sigstack)); 19112951Ssam if (u.u_error) 19212951Ssam return; 19312951Ssam } 19412951Ssam if (uap->nss) { 19512951Ssam u.u_error = 19612951Ssam copyin((caddr_t)uap->nss, (caddr_t)&ss, sizeof (ss)); 19712951Ssam if (u.u_error == 0) 19812951Ssam u.u_sigstack = ss; 19912951Ssam } 2007499Sroot } 2017499Sroot 2028032Sroot kill() 2038032Sroot { 20412882Ssam register struct a { 20512882Ssam int pid; 20612882Ssam int signo; 20712882Ssam } *uap = (struct a *)u.u_ap; 20818336Smckusick register struct proc *p; 2098032Sroot 21018336Smckusick if (uap->signo < 0 || uap->signo > NSIG) { 21118336Smckusick u.u_error = EINVAL; 21218336Smckusick return; 21318336Smckusick } 21418336Smckusick if (uap->pid > 0) { 21518336Smckusick /* kill single process */ 21618336Smckusick p = pfind(uap->pid); 21718336Smckusick if (p == 0) { 21818336Smckusick u.u_error = ESRCH; 21918336Smckusick return; 22018336Smckusick } 22118336Smckusick if (u.u_uid && u.u_uid != p->p_uid) 22218336Smckusick u.u_error = EPERM; 22318336Smckusick else if (uap->signo) 22418336Smckusick psignal(p, uap->signo); 22518336Smckusick return; 22618336Smckusick } 22718336Smckusick switch (uap->pid) { 22818336Smckusick case -1: /* broadcast signal */ 22920998Smckusick u.u_error = killpg1(uap->signo, 0, 1); 23018336Smckusick break; 23118336Smckusick case 0: /* signal own process group */ 23218336Smckusick u.u_error = killpg1(uap->signo, 0, 0); 23318336Smckusick break; 23418336Smckusick default: /* negative explicit process group */ 23518336Smckusick u.u_error = killpg1(uap->signo, -uap->pid, 0); 23618336Smckusick break; 23718336Smckusick } 23818336Smckusick return; 2398032Sroot } 2408032Sroot 2418032Sroot killpg() 2428032Sroot { 2439989Ssam register struct a { 24437581Smckusick int pgid; 2459989Ssam int signo; 2469989Ssam } *uap = (struct a *)u.u_ap; 2478032Sroot 24818336Smckusick if (uap->signo < 0 || uap->signo > NSIG) { 24918336Smckusick u.u_error = EINVAL; 25018336Smckusick return; 25118336Smckusick } 25237581Smckusick u.u_error = killpg1(uap->signo, uap->pgid, 0); 2538032Sroot } 2548032Sroot 25512882Ssam /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ 25612882Ssam 25737581Smckusick killpg1(signo, pgid, all) 25837581Smckusick int signo, pgid, all; 2599989Ssam { 2609989Ssam register struct proc *p; 26137581Smckusick struct pgrp *pgrp; 26237581Smckusick int f = 0, error = 0; 2639989Ssam 26437581Smckusick 26537581Smckusick if (all) 26637581Smckusick /* 26737581Smckusick * broadcast 2687421Sroot */ 26937581Smckusick for (p = allproc; p != NULL; p = p->p_nxt) { 27037581Smckusick if (p->p_ppid == 0 || p->p_flag&SSYS || 27137581Smckusick p == u.u_procp || 27237581Smckusick (u.u_uid && u.u_uid != p->p_uid && 27337581Smckusick !(signo == SIGCONT && inferior(p)))) 27437581Smckusick continue; 27537581Smckusick f++; 27637581Smckusick if (signo) 27737581Smckusick psignal(p, signo); 27837581Smckusick } 27937581Smckusick else { 28037581Smckusick if (pgid == 0) 28137581Smckusick /* 28237581Smckusick * zero pgid means send to my process group. 28337581Smckusick */ 28437581Smckusick pgrp = u.u_procp->p_pgrp; 28537581Smckusick else { 28637581Smckusick pgrp = pgfind(pgid); 28737581Smckusick if (pgrp == NULL) 28837581Smckusick return(ESRCH); 28937581Smckusick } 29037581Smckusick if (!(pgrp->pg_jobc) && 29137581Smckusick (signo==SIGTTIN || signo==SIGTTOU || signo==SIGTSTP)) 29237581Smckusick return(EPERM); 29337581Smckusick for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) { 29437581Smckusick if (p->p_ppid == 0 || p->p_flag&SSYS) 29537581Smckusick continue; 29637581Smckusick if (u.u_uid && u.u_uid != p->p_uid && 29737581Smckusick !(signo == SIGCONT && inferior(p))) { 29820998Smckusick error = EPERM; 29937581Smckusick continue; 30037581Smckusick } 30137581Smckusick f++; 30237581Smckusick if (signo) 30337581Smckusick psignal(p, signo); 30418336Smckusick } 3057421Sroot } 30624420Skarels return (error ? error : (f == 0 ? ESRCH : 0)); 3077421Sroot } 3087421Sroot 3097421Sroot /* 3107421Sroot * Send the specified signal to 31137581Smckusick * all processes with 'pgid' as 3127421Sroot * process group. 3137421Sroot */ 31437581Smckusick gsignal(pgid, sig) 3157421Sroot { 31637581Smckusick register struct pgrp *pgrp; 3177421Sroot 31837581Smckusick if (!pgid) 3197421Sroot return; 32037581Smckusick if ((pgrp = pgfind(pgid)) == NULL) 32137581Smckusick return; 32237581Smckusick pgsignal(pgrp, sig); 3237421Sroot } 3247421Sroot 32537581Smckusick pgsignal(pgrp, sig) 32637581Smckusick register struct pgrp *pgrp; 32737581Smckusick { 32837581Smckusick register struct proc *p; 32937581Smckusick 33037581Smckusick if (!(pgrp->pg_jobc) && 33137581Smckusick (sig==SIGTTIN || sig==SIGTTOU || sig==SIGTSTP)) 33237581Smckusick return; 33337581Smckusick for (p = pgrp->pg_mem; p != NULL; p = p->p_pgrpnxt) 33437581Smckusick psignal(p, sig); 33537581Smckusick } 33637581Smckusick 3377421Sroot /* 3387421Sroot * Send the specified signal to 3397421Sroot * the specified process. 3407421Sroot */ 3417421Sroot psignal(p, sig) 3427421Sroot register struct proc *p; 3437421Sroot register int sig; 3447421Sroot { 3457421Sroot register int s; 3467421Sroot register int (*action)(); 34717153Sbloom int mask; 3487421Sroot 3497421Sroot if ((unsigned)sig >= NSIG) 3507421Sroot return; 35117153Sbloom mask = sigmask(sig); 3527421Sroot 3537421Sroot /* 3547421Sroot * If proc is traced, always give parent a chance. 3557421Sroot */ 3567421Sroot if (p->p_flag & STRC) 3577421Sroot action = SIG_DFL; 3587421Sroot else { 3597421Sroot /* 36012882Ssam * If the signal is being ignored, 36112882Ssam * then we forget about it immediately. 3627421Sroot */ 36317153Sbloom if (p->p_sigignore & mask) 3647421Sroot return; 36517153Sbloom if (p->p_sigmask & mask) 36612882Ssam action = SIG_HOLD; 36717153Sbloom else if (p->p_sigcatch & mask) 36812882Ssam action = SIG_CATCH; 36912882Ssam else 37012882Ssam action = SIG_DFL; 3717421Sroot } 3727421Sroot if (sig) { 3737421Sroot switch (sig) { 3747421Sroot 3757421Sroot case SIGTERM: 37612882Ssam if ((p->p_flag&STRC) || action != SIG_DFL) 3777421Sroot break; 3787421Sroot /* fall into ... */ 3797421Sroot 3807421Sroot case SIGKILL: 3817421Sroot if (p->p_nice > NZERO) 3827421Sroot p->p_nice = NZERO; 3837421Sroot break; 3847421Sroot 3857421Sroot case SIGCONT: 38626276Skarels p->p_sig &= ~stopsigmask; 3877421Sroot break; 3887421Sroot 3897421Sroot case SIGTSTP: 3907421Sroot case SIGTTIN: 3917421Sroot case SIGTTOU: 39237581Smckusick /*FALLTHROUGH*/ 39337581Smckusick case SIGSTOP: 39417153Sbloom p->p_sig &= ~sigmask(SIGCONT); 3957421Sroot break; 3967421Sroot } 39737581Smckusick p->p_sig |= mask; 3987421Sroot } 3997421Sroot /* 4007421Sroot * Defer further processing for signals which are held. 4017421Sroot */ 4027421Sroot if (action == SIG_HOLD) 4037421Sroot return; 40417153Sbloom s = splhigh(); 4057421Sroot switch (p->p_stat) { 4067421Sroot 4077421Sroot case SSLEEP: 4087421Sroot /* 4097421Sroot * If process is sleeping at negative priority 4107421Sroot * we can't interrupt the sleep... the signal will 4117421Sroot * be noticed when the process returns through 4127421Sroot * trap() or syscall(). 4137421Sroot */ 4147421Sroot if (p->p_pri <= PZERO) 4157421Sroot goto out; 4167421Sroot /* 4177421Sroot * Process is sleeping and traced... make it runnable 4187421Sroot * so it can discover the signal in issig() and stop 4197421Sroot * for the parent. 4207421Sroot */ 4217421Sroot if (p->p_flag&STRC) 4227421Sroot goto run; 4237421Sroot switch (sig) { 4247421Sroot 4257421Sroot case SIGSTOP: 4267421Sroot case SIGTSTP: 4277421Sroot case SIGTTIN: 4287421Sroot case SIGTTOU: 4297421Sroot /* 4307421Sroot * These are the signals which by default 4317421Sroot * stop a process. 4327421Sroot */ 4337421Sroot if (action != SIG_DFL) 4347421Sroot goto run; 4357421Sroot /* 4367421Sroot * If a child in vfork(), stopping could 4377421Sroot * cause deadlock. 4387421Sroot */ 4397421Sroot if (p->p_flag&SVFORK) 4407421Sroot goto out; 44117153Sbloom p->p_sig &= ~mask; 4427421Sroot p->p_cursig = sig; 44318331Skarels psignal(p->p_pptr, SIGCHLD); 4447421Sroot stop(p); 4457421Sroot goto out; 4467421Sroot 4477421Sroot case SIGIO: 4487421Sroot case SIGURG: 4497421Sroot case SIGCHLD: 45017597Sbloom case SIGWINCH: 4517421Sroot /* 4527421Sroot * These signals are special in that they 4537421Sroot * don't get propogated... if the process 4547421Sroot * isn't interested, forget it. 4557421Sroot */ 4567421Sroot if (action != SIG_DFL) 4577421Sroot goto run; 45817153Sbloom p->p_sig &= ~mask; /* take it away */ 4597421Sroot goto out; 4607421Sroot 4617421Sroot default: 4627421Sroot /* 4637421Sroot * All other signals cause the process to run 4647421Sroot */ 4657421Sroot goto run; 4667421Sroot } 4677421Sroot /*NOTREACHED*/ 4687421Sroot 4697421Sroot case SSTOP: 4707421Sroot /* 4717421Sroot * If traced process is already stopped, 4727421Sroot * then no further action is necessary. 4737421Sroot */ 4747421Sroot if (p->p_flag&STRC) 4757421Sroot goto out; 4767421Sroot switch (sig) { 4777421Sroot 4787421Sroot case SIGKILL: 4797421Sroot /* 4807421Sroot * Kill signal always sets processes running. 4817421Sroot */ 4827421Sroot goto run; 4837421Sroot 4847421Sroot case SIGCONT: 4857421Sroot /* 4867421Sroot * If the process catches SIGCONT, let it handle 4877421Sroot * the signal itself. If it isn't waiting on 4887421Sroot * an event, then it goes back to run state. 4897421Sroot * Otherwise, process goes back to sleep state. 4907421Sroot */ 4917421Sroot if (action != SIG_DFL || p->p_wchan == 0) 4927421Sroot goto run; 4937421Sroot p->p_stat = SSLEEP; 4947421Sroot goto out; 4957421Sroot 4967421Sroot case SIGSTOP: 4977421Sroot case SIGTSTP: 4987421Sroot case SIGTTIN: 4997421Sroot case SIGTTOU: 5007421Sroot /* 5017421Sroot * Already stopped, don't need to stop again. 5027421Sroot * (If we did the shell could get confused.) 5037421Sroot */ 50417153Sbloom p->p_sig &= ~mask; /* take it away */ 5057421Sroot goto out; 5067421Sroot 5077421Sroot default: 5087421Sroot /* 5097421Sroot * If process is sleeping interruptibly, then 5107421Sroot * unstick it so that when it is continued 5117421Sroot * it can look at the signal. 5127421Sroot * But don't setrun the process as its not to 5137421Sroot * be unstopped by the signal alone. 5147421Sroot */ 5157421Sroot if (p->p_wchan && p->p_pri > PZERO) 5167421Sroot unsleep(p); 5177421Sroot goto out; 5187421Sroot } 5197421Sroot /*NOTREACHED*/ 5207421Sroot 5217421Sroot default: 5227421Sroot /* 5237421Sroot * SRUN, SIDL, SZOMB do nothing with the signal, 5247421Sroot * other than kicking ourselves if we are running. 5257421Sroot * It will either never be noticed, or noticed very soon. 5267421Sroot */ 5277421Sroot if (p == u.u_procp && !noproc) 5287421Sroot aston(); 5297421Sroot goto out; 5307421Sroot } 5317421Sroot /*NOTREACHED*/ 5327421Sroot run: 5337421Sroot /* 5347421Sroot * Raise priority to at least PUSER. 5357421Sroot */ 5367421Sroot if (p->p_pri > PUSER) 53717399Skarels p->p_pri = PUSER; 5387421Sroot setrun(p); 5397421Sroot out: 5407421Sroot splx(s); 5417421Sroot } 5427421Sroot 5437421Sroot /* 5447421Sroot * Returns true if the current 5457421Sroot * process has a signal to process. 5467421Sroot * The signal to process is put in p_cursig. 5477421Sroot * This is asked at least once each time a process enters the 5487421Sroot * system (though this can usually be done without actually 5497421Sroot * calling issig by checking the pending signal masks.) 5507421Sroot * A signal does not do anything 5517421Sroot * directly to a process; it sets 5527421Sroot * a flag that asks the process to 5537421Sroot * do something to itself. 5547421Sroot */ 5557421Sroot issig() 5567421Sroot { 5577421Sroot register struct proc *p; 5587421Sroot register int sig; 55917153Sbloom int sigbits, mask; 5607421Sroot 5617421Sroot p = u.u_procp; 5627421Sroot for (;;) { 56314782Ssam sigbits = p->p_sig &~ p->p_sigmask; 5647421Sroot if ((p->p_flag&STRC) == 0) 56514782Ssam sigbits &= ~p->p_sigignore; 5667421Sroot if (p->p_flag&SVFORK) 56726276Skarels sigbits &= ~stopsigmask; 5687421Sroot if (sigbits == 0) 5697421Sroot break; 57026354Skarels sig = ffs((long)sigbits); 57117153Sbloom mask = sigmask(sig); 57217153Sbloom p->p_sig &= ~mask; /* take the signal! */ 5737421Sroot p->p_cursig = sig; 57412882Ssam if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { 5757421Sroot /* 5767421Sroot * If traced, always stop, and stay 5777421Sroot * stopped until released by the parent. 5787421Sroot */ 57918331Skarels psignal(p->p_pptr, SIGCHLD); 5807421Sroot do { 5817421Sroot stop(p); 5827421Sroot swtch(); 5837421Sroot } while (!procxmt() && p->p_flag&STRC); 5847421Sroot 5857421Sroot /* 58614782Ssam * If the traced bit got turned off, 58714782Ssam * then put the signal taken above back into p_sig 58814782Ssam * and go back up to the top to rescan signals. 58914782Ssam * This ensures that p_sig* and u_signal are consistent. 5907421Sroot */ 59114782Ssam if ((p->p_flag&STRC) == 0) { 59217153Sbloom p->p_sig |= mask; 5937421Sroot continue; 5947421Sroot } 5957421Sroot 5967421Sroot /* 5977421Sroot * If parent wants us to take the signal, 5987421Sroot * then it will leave it in p->p_cursig; 5997421Sroot * otherwise we just look for signals again. 6007421Sroot */ 6017421Sroot sig = p->p_cursig; 6027421Sroot if (sig == 0) 6037421Sroot continue; 60414782Ssam 60514782Ssam /* 60614782Ssam * If signal is being masked put it back 60714782Ssam * into p_sig and look for other signals. 60814782Ssam */ 60917153Sbloom mask = sigmask(sig); 61017153Sbloom if (p->p_sigmask & mask) { 61117153Sbloom p->p_sig |= mask; 61214782Ssam continue; 61314782Ssam } 6147421Sroot } 61524901Skarels switch ((int)u.u_signal[sig]) { 6167421Sroot 6177421Sroot case SIG_DFL: 6187421Sroot /* 6197421Sroot * Don't take default actions on system processes. 6207421Sroot */ 6217421Sroot if (p->p_ppid == 0) 6227421Sroot break; 6237421Sroot switch (sig) { 6247421Sroot 6257421Sroot case SIGTSTP: 6267421Sroot case SIGTTIN: 6277421Sroot case SIGTTOU: 6287421Sroot case SIGSTOP: 6297421Sroot if (p->p_flag&STRC) 6307421Sroot continue; 63118331Skarels psignal(p->p_pptr, SIGCHLD); 6327421Sroot stop(p); 6337421Sroot swtch(); 6347421Sroot continue; 6357421Sroot 6367421Sroot case SIGCONT: 6377421Sroot case SIGCHLD: 63812882Ssam case SIGURG: 63912951Ssam case SIGIO: 64017597Sbloom case SIGWINCH: 6417421Sroot /* 6427421Sroot * These signals are normally not 6437421Sroot * sent if the action is the default. 6447421Sroot */ 6457421Sroot continue; /* == ignore */ 6467421Sroot 6477421Sroot default: 6487421Sroot goto send; 6497421Sroot } 6507421Sroot /*NOTREACHED*/ 6517421Sroot 6527421Sroot case SIG_HOLD: 6537421Sroot case SIG_IGN: 6547421Sroot /* 6557421Sroot * Masking above should prevent us 6567421Sroot * ever trying to take action on a held 6577421Sroot * or ignored signal, unless process is traced. 6587421Sroot */ 6597421Sroot if ((p->p_flag&STRC) == 0) 6607421Sroot printf("issig\n"); 6617421Sroot continue; 6627421Sroot 6637421Sroot default: 6647421Sroot /* 6657421Sroot * This signal has an action, let 6667421Sroot * psig process it. 6677421Sroot */ 6687421Sroot goto send; 6697421Sroot } 6707421Sroot /*NOTREACHED*/ 6717421Sroot } 6727421Sroot /* 6737421Sroot * Didn't find a signal to send. 6747421Sroot */ 6757421Sroot p->p_cursig = 0; 6767421Sroot return (0); 6777421Sroot 6787421Sroot send: 6797421Sroot /* 6807421Sroot * Let psig process the signal. 6817421Sroot */ 6827421Sroot return (sig); 6837421Sroot } 6847421Sroot 6857421Sroot /* 6867421Sroot * Put the argument process into the stopped 68718331Skarels * state and notify the parent via wakeup. 68818331Skarels * Signals are handled elsewhere. 6897421Sroot */ 6907421Sroot stop(p) 6917421Sroot register struct proc *p; 6927421Sroot { 6937421Sroot 6947421Sroot p->p_stat = SSTOP; 6957421Sroot p->p_flag &= ~SWTED; 6967421Sroot wakeup((caddr_t)p->p_pptr); 6977421Sroot } 6987421Sroot 6997421Sroot /* 7007421Sroot * Perform the action specified by 7017421Sroot * the current signal. 7027421Sroot * The usual sequence is: 7037421Sroot * if (issig()) 7047421Sroot * psig(); 7057421Sroot * The signal bit has already been cleared by issig, 7067421Sroot * and the current signal number stored in p->p_cursig. 7077421Sroot */ 7087421Sroot psig() 7097421Sroot { 71012882Ssam register struct proc *p = u.u_procp; 71112882Ssam register int sig = p->p_cursig; 71217153Sbloom int mask = sigmask(sig), returnmask; 7137421Sroot register int (*action)(); 7147421Sroot 71512882Ssam if (sig == 0) 7167421Sroot panic("psig"); 71712882Ssam action = u.u_signal[sig]; 7187421Sroot if (action != SIG_DFL) { 71917153Sbloom if (action == SIG_IGN || (p->p_sigmask & mask)) 7207421Sroot panic("psig action"); 7217421Sroot u.u_error = 0; 7227421Sroot /* 72312882Ssam * Set the new mask value and also defer further 72412882Ssam * occurences of this signal (unless we're simulating 72512882Ssam * the old signal facilities). 72612882Ssam * 72712882Ssam * Special case: user has done a sigpause. Here the 72812882Ssam * current mask is not of interest, but rather the 72912882Ssam * mask from before the sigpause is what we want restored 73012882Ssam * after the signal processing is completed. 7317421Sroot */ 73217153Sbloom (void) splhigh(); 73312882Ssam if (p->p_flag & SOUSIG) { 73412882Ssam if (sig != SIGILL && sig != SIGTRAP) { 73512882Ssam u.u_signal[sig] = SIG_DFL; 73617153Sbloom p->p_sigcatch &= ~mask; 73712882Ssam } 73817153Sbloom mask = 0; 7397421Sroot } 74012882Ssam if (p->p_flag & SOMASK) { 74112882Ssam returnmask = u.u_oldmask; 74212882Ssam p->p_flag &= ~SOMASK; 74312882Ssam } else 74412882Ssam returnmask = p->p_sigmask; 74517153Sbloom p->p_sigmask |= u.u_sigmask[sig] | mask; 74612882Ssam (void) spl0(); 7478032Sroot u.u_ru.ru_nsignals++; 74812882Ssam sendsig(action, sig, returnmask); 74912882Ssam p->p_cursig = 0; 7507421Sroot return; 7517421Sroot } 7527421Sroot u.u_acflag |= AXSIG; 75312882Ssam switch (sig) { 7547421Sroot 7557421Sroot case SIGILL: 7567421Sroot case SIGIOT: 7577421Sroot case SIGBUS: 7587421Sroot case SIGQUIT: 7597421Sroot case SIGTRAP: 7607421Sroot case SIGEMT: 7617421Sroot case SIGFPE: 7627421Sroot case SIGSEGV: 7637421Sroot case SIGSYS: 76412882Ssam u.u_arg[0] = sig; 76537580Smckusick if (core() == 0) 76612882Ssam sig += 0200; 7677421Sroot } 76812882Ssam exit(sig); 7697421Sroot } 7707421Sroot 7717421Sroot /* 7727421Sroot * Create a core image on the file "core" 7737421Sroot * If you are looking for protection glitches, 7747421Sroot * there are probably a wealth of them here 7757421Sroot * when this occurs to a suid command. 7767421Sroot * 7777421Sroot * It writes UPAGES block of the 7787421Sroot * user.h area followed by the entire 7797421Sroot * data+stack segments. 7807421Sroot */ 7817421Sroot core() 7827421Sroot { 783*37728Smckusick register struct vnode *vp; 78416692Smckusick register struct nameidata *ndp = &u.u_nd; 78537580Smckusick struct vattr vattr; 78637580Smckusick int error; 7877421Sroot 78812639Ssam if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) 78937580Smckusick return (EFAULT); 79037580Smckusick if (ctob(UPAGES + u.u_dsize + u.u_ssize) >= 7918032Sroot u.u_rlimit[RLIMIT_CORE].rlim_cur) 79237580Smckusick return (EFAULT); 79337580Smckusick if (u.u_procp->p_textp) { 794*37728Smckusick VOP_LOCK(u.u_procp->p_textp->x_vptr); 79537580Smckusick error = vn_access(u.u_procp->p_textp->x_vptr, VREAD, u.u_cred); 796*37728Smckusick VOP_UNLOCK(u.u_procp->p_textp->x_vptr); 79737580Smckusick if (error) 79837580Smckusick return (EFAULT); 79937580Smckusick } 80016692Smckusick ndp->ni_segflg = UIO_SYSSPACE; 80116692Smckusick ndp->ni_dirp = "core"; 80237580Smckusick if (error = vn_open(ndp, FCREAT|FWRITE, 0644)) 80337580Smckusick return (error); 80437580Smckusick vp = ndp->ni_vp; 80537580Smckusick if (vp->v_type != VREG || 806*37728Smckusick VOP_GETATTR(vp, &vattr, u.u_cred) || 80737580Smckusick vattr.va_nlink != 1) { 80837580Smckusick error = EFAULT; 8097818Sroot goto out; 8107818Sroot } 81130290Ssam #ifdef MMAP 81230290Ssam { register int fd; 81330290Ssam /* unmasp funky devices in the user's address space */ 81430290Ssam for (fd = 0; fd < u.u_lastfile; fd++) 81530290Ssam if (u.u_ofile[fd] && (u.u_pofile[fd] & UF_MAPPED)) 81630290Ssam munmapfd(fd); 81730290Ssam } 81830290Ssam #endif 81937580Smckusick vattr_null(&vattr); 82037580Smckusick vattr.va_size = 0; 821*37728Smckusick VOP_SETATTR(vp, &vattr, u.u_cred); 8227818Sroot u.u_acflag |= ACORE; 82337580Smckusick error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&u, ctob(UPAGES), (off_t)0, 824*37728Smckusick UIO_SYSSPACE, IO_UNIT, ndp->ni_cred, (int *)0); 82537580Smckusick if (error == 0) 82637580Smckusick error = vn_rdwr(UIO_WRITE, vp, 8278967Sroot (caddr_t)ctob(dptov(u.u_procp, 0)), 82837580Smckusick (int)ctob(u.u_dsize), (off_t)ctob(UPAGES), 829*37728Smckusick UIO_USERSPACE, IO_UNIT, ndp->ni_cred, (int *)0); 83037580Smckusick if (error == 0) 83137580Smckusick error = vn_rdwr(UIO_WRITE, vp, 8328967Sroot (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), 83326354Skarels (int)ctob(u.u_ssize), 83437580Smckusick (off_t)ctob(UPAGES) + ctob(u.u_dsize), 835*37728Smckusick UIO_USERSPACE, IO_UNIT, ndp->ni_cred, (int *)0); 8367818Sroot out: 83737580Smckusick if (vp) 83837580Smckusick vrele(vp); 83937580Smckusick return (error); 8407421Sroot } 841