1*9858Ssam /* kern_sig.c 5.14 82/12/19 */ 27421Sroot 39755Ssam #include "../machine/reg.h" 49755Ssam #include "../machine/pte.h" 59755Ssam #include "../machine/psl.h" 69755Ssam 77421Sroot #include "../h/param.h" 87421Sroot #include "../h/systm.h" 97421Sroot #include "../h/dir.h" 107421Sroot #include "../h/user.h" 117421Sroot #include "../h/inode.h" 127421Sroot #include "../h/proc.h" 137421Sroot #include "../h/timeb.h" 147421Sroot #include "../h/times.h" 157421Sroot #include "../h/conf.h" 167421Sroot #include "../h/buf.h" 177421Sroot #include "../h/mount.h" 187421Sroot #include "../h/text.h" 197421Sroot #include "../h/seg.h" 207421Sroot #include "../h/vm.h" 217421Sroot #include "../h/acct.h" 227818Sroot #include "../h/uio.h" 238117Sroot #include "../h/kernel.h" 249160Ssam #include "../h/nami.h" 257421Sroot 267499Sroot /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ 277499Sroot 287499Sroot sigvec() 297421Sroot { 307421Sroot 317421Sroot } 327421Sroot 337499Sroot sigblock() 347421Sroot { 357499Sroot 367499Sroot } 377499Sroot 387499Sroot sigsetmask() 397499Sroot { 407499Sroot 417499Sroot } 427499Sroot 437499Sroot sigpause() 447499Sroot { 457499Sroot 467499Sroot } 477499Sroot 487499Sroot sigstack() 497499Sroot { 507499Sroot 517499Sroot } 527499Sroot 538764Sroot #ifdef notdef 548032Sroot kill() 558032Sroot { 568032Sroot 578032Sroot } 588764Sroot #endif 598032Sroot 608032Sroot killpg() 618032Sroot { 628032Sroot 638032Sroot } 648032Sroot 657499Sroot /* BEGIN DEFUNCT */ 667499Sroot okill() 677499Sroot { 687421Sroot register struct proc *p; 697421Sroot register a, sig; 707421Sroot register struct a { 717421Sroot int pid; 727421Sroot int signo; 737421Sroot } *uap; 747421Sroot int f, priv; 757421Sroot 767421Sroot uap = (struct a *)u.u_ap; 777421Sroot f = 0; 787421Sroot a = uap->pid; 797421Sroot priv = 0; 807421Sroot sig = uap->signo; 817421Sroot if (sig < 0) 827421Sroot /* 837421Sroot * A negative signal means send to process group. 847421Sroot */ 857421Sroot uap->signo = -uap->signo; 867421Sroot if (uap->signo == 0 || uap->signo > NSIG) { 877421Sroot u.u_error = EINVAL; 887421Sroot return; 897421Sroot } 907421Sroot if (a > 0 && sig > 0) { 917421Sroot p = pfind(a); 927421Sroot if (p == 0 || u.u_uid && u.u_uid != p->p_uid) { 937421Sroot u.u_error = ESRCH; 947421Sroot return; 957421Sroot } 967421Sroot psignal(p, uap->signo); 977421Sroot return; 987421Sroot } 997421Sroot if (a==-1 && u.u_uid==0) { 1007421Sroot priv++; 1017421Sroot a = 0; 1027421Sroot sig = -1; /* like sending to pgrp */ 1037421Sroot } else if (a==0) { 1047421Sroot /* 1057421Sroot * Zero process id means send to my process group. 1067421Sroot */ 1077421Sroot sig = -1; 1087421Sroot a = u.u_procp->p_pgrp; 1097421Sroot if (a == 0) { 1107421Sroot u.u_error = EINVAL; 1117421Sroot return; 1127421Sroot } 1137421Sroot } 1147421Sroot for(p = proc; p < procNPROC; p++) { 1157421Sroot if (p->p_stat == NULL) 1167421Sroot continue; 1177421Sroot if (sig > 0) { 1187421Sroot if (p->p_pid != a) 1197421Sroot continue; 1207421Sroot } else if (p->p_pgrp!=a && priv==0 || p->p_ppid==0 || 1217421Sroot (p->p_flag&SSYS) || (priv && p==u.u_procp)) 1227421Sroot continue; 1237421Sroot if (u.u_uid != 0 && u.u_uid != p->p_uid && 1247421Sroot (uap->signo != SIGCONT || !inferior(p))) 1257421Sroot continue; 1267421Sroot f++; 1277421Sroot psignal(p, uap->signo); 1287421Sroot } 1297421Sroot if (f == 0) 1307421Sroot u.u_error = ESRCH; 1317421Sroot } 1327421Sroot 1337499Sroot ossig() 1347499Sroot { 1357499Sroot register int (*f)(); 1367499Sroot struct a { 1377499Sroot int signo; 1387499Sroot int (*fun)(); 1397499Sroot } *uap; 1407499Sroot register struct proc *p = u.u_procp; 1417499Sroot register a; 1427499Sroot long sigmask; 1437421Sroot 1447499Sroot uap = (struct a *)u.u_ap; 1457499Sroot a = uap->signo & SIGNUMMASK; 1467499Sroot f = uap->fun; 1477499Sroot if (a<=0 || a>=NSIG || a==SIGKILL || a==SIGSTOP || 1487499Sroot a==SIGCONT && (f == SIG_IGN || f == SIG_HOLD)) { 1497499Sroot u.u_error = EINVAL; 1507499Sroot return; 1517499Sroot } 1527499Sroot if ((uap->signo &~ SIGNUMMASK) || (f != SIG_DFL && f != SIG_IGN && 1537499Sroot SIGISDEFER(f))) 1547499Sroot u.u_procp->p_flag |= SNUSIG; 1557499Sroot /* 1567499Sroot * Don't clobber registers if we are to simulate 1577499Sroot * a ret+rti. 1587499Sroot */ 1597499Sroot if ((uap->signo&SIGDORTI) == 0) 1607499Sroot u.u_r.r_val1 = (int)u.u_signal[a]; 1617499Sroot /* 1627499Sroot * Change setting atomically. 1637499Sroot */ 1647499Sroot (void) spl6(); 1657499Sroot sigmask = 1L << (a-1); 166*9858Ssam if (f == SIG_IGN) 1677499Sroot p->p_sig &= ~sigmask; /* never to be seen again */ 1687499Sroot u.u_signal[a] = f; 1697499Sroot if (f != SIG_DFL && f != SIG_IGN && f != SIG_HOLD) 1707499Sroot f = SIG_CATCH; 1717499Sroot if ((int)f & 1) 1727499Sroot p->p_siga0 |= sigmask; 1737499Sroot else 1747499Sroot p->p_siga0 &= ~sigmask; 1757499Sroot if ((int)f & 2) 1767499Sroot p->p_siga1 |= sigmask; 1777499Sroot else 1787499Sroot p->p_siga1 &= ~sigmask; 1797499Sroot (void) spl0(); 1807499Sroot /* 1817499Sroot * Now handle options. 1827499Sroot */ 1837499Sroot if (uap->signo & SIGDOPAUSE) { 1847499Sroot /* 1857499Sroot * Simulate a PDP11 style wait instrution which 1867499Sroot * atomically lowers priority, enables interrupts 1877499Sroot * and hangs. 1887499Sroot */ 1897499Sroot opause(); 1907499Sroot /*NOTREACHED*/ 1917499Sroot } 1927499Sroot if (uap->signo & SIGDORTI) 1937499Sroot u.u_eosys = SIMULATERTI; 1947499Sroot } 1957421Sroot 1967421Sroot /* 1977421Sroot * Send the specified signal to 1987421Sroot * all processes with 'pgrp' as 1997421Sroot * process group. 2007421Sroot * Called by tty.c for quits and 2017421Sroot * interrupts. 2027421Sroot */ 2037421Sroot gsignal(pgrp, sig) 2047421Sroot register int pgrp; 2057421Sroot { 2067421Sroot register struct proc *p; 2077421Sroot 2087421Sroot if (pgrp == 0) 2097421Sroot return; 2107421Sroot for(p = proc; p < procNPROC; p++) 2117421Sroot if (p->p_pgrp == pgrp) 2127421Sroot psignal(p, sig); 2137421Sroot } 2147421Sroot 2157421Sroot /* 2167421Sroot * Send the specified signal to 2177421Sroot * the specified process. 2187421Sroot */ 2197421Sroot psignal(p, sig) 2207421Sroot register struct proc *p; 2217421Sroot register int sig; 2227421Sroot { 2237421Sroot register int s; 2247421Sroot register int (*action)(); 2257421Sroot long sigmask; 2267421Sroot 2277421Sroot if ((unsigned)sig >= NSIG) 2287421Sroot return; 2297421Sroot sigmask = (1L << (sig-1)); 2307421Sroot 2317421Sroot /* 2327421Sroot * If proc is traced, always give parent a chance. 2337421Sroot * Otherwise get the signal action from the bits in the proc table. 2347421Sroot */ 2357421Sroot if (p->p_flag & STRC) 2367421Sroot action = SIG_DFL; 2377421Sroot else { 2387421Sroot s = (p->p_siga1&sigmask) != 0; 2397421Sroot s <<= 1; 2407421Sroot s |= (p->p_siga0&sigmask) != 0; 2417421Sroot action = (int(*)())s; 2427421Sroot /* 2437421Sroot * If the signal is ignored, we forget about it immediately. 2447421Sroot */ 2457421Sroot if (action == SIG_IGN) 2467421Sroot return; 2477421Sroot } 2487421Sroot #define mask(sig) (1<<(sig-1)) 2497421Sroot #define stops (mask(SIGSTOP)|mask(SIGTSTP)|mask(SIGTTIN)|mask(SIGTTOU)) 2507421Sroot if (sig) { 2517421Sroot p->p_sig |= sigmask; 2527421Sroot switch (sig) { 2537421Sroot 2547421Sroot case SIGTERM: 2557421Sroot if ((p->p_flag&STRC) != 0 || action != SIG_DFL) 2567421Sroot break; 2577421Sroot /* fall into ... */ 2587421Sroot 2597421Sroot case SIGKILL: 2607421Sroot if (p->p_nice > NZERO) 2617421Sroot p->p_nice = NZERO; 2627421Sroot break; 2637421Sroot 2647421Sroot case SIGCONT: 2657421Sroot p->p_sig &= ~stops; 2667421Sroot break; 2677421Sroot 2687421Sroot case SIGSTOP: 2697421Sroot case SIGTSTP: 2707421Sroot case SIGTTIN: 2717421Sroot case SIGTTOU: 2727421Sroot p->p_sig &= ~mask(SIGCONT); 2737421Sroot break; 2747421Sroot } 2757421Sroot } 2767421Sroot #undef mask 2777421Sroot #undef stops 2787421Sroot /* 2797421Sroot * Defer further processing for signals which are held. 2807421Sroot */ 2817421Sroot if (action == SIG_HOLD) 2827421Sroot return; 2837421Sroot s = spl6(); 2847421Sroot switch (p->p_stat) { 2857421Sroot 2867421Sroot case SSLEEP: 2877421Sroot /* 2887421Sroot * If process is sleeping at negative priority 2897421Sroot * we can't interrupt the sleep... the signal will 2907421Sroot * be noticed when the process returns through 2917421Sroot * trap() or syscall(). 2927421Sroot */ 2937421Sroot if (p->p_pri <= PZERO) 2947421Sroot goto out; 2957421Sroot /* 2967421Sroot * Process is sleeping and traced... make it runnable 2977421Sroot * so it can discover the signal in issig() and stop 2987421Sroot * for the parent. 2997421Sroot */ 3007421Sroot if (p->p_flag&STRC) 3017421Sroot goto run; 3027421Sroot switch (sig) { 3037421Sroot 3047421Sroot case SIGSTOP: 3057421Sroot case SIGTSTP: 3067421Sroot case SIGTTIN: 3077421Sroot case SIGTTOU: 3087421Sroot /* 3097421Sroot * These are the signals which by default 3107421Sroot * stop a process. 3117421Sroot */ 3127421Sroot if (action != SIG_DFL) 3137421Sroot goto run; 3147421Sroot /* 3157421Sroot * Don't clog system with children of init 3167421Sroot * stopped from the keyboard. 3177421Sroot */ 3187421Sroot if (sig != SIGSTOP && p->p_pptr == &proc[1]) { 3197421Sroot psignal(p, SIGKILL); 3207421Sroot p->p_sig &= ~sigmask; 3217421Sroot splx(s); 3227421Sroot return; 3237421Sroot } 3247421Sroot /* 3257421Sroot * If a child in vfork(), stopping could 3267421Sroot * cause deadlock. 3277421Sroot */ 3287421Sroot if (p->p_flag&SVFORK) 3297421Sroot goto out; 3307421Sroot p->p_sig &= ~sigmask; 3317421Sroot p->p_cursig = sig; 3327421Sroot stop(p); 3337421Sroot goto out; 3347421Sroot 3357421Sroot case SIGIO: 3367421Sroot case SIGURG: 3377421Sroot case SIGCHLD: 3387421Sroot /* 3397421Sroot * These signals are special in that they 3407421Sroot * don't get propogated... if the process 3417421Sroot * isn't interested, forget it. 3427421Sroot */ 3437421Sroot if (action != SIG_DFL) 3447421Sroot goto run; 3457421Sroot p->p_sig &= ~sigmask; /* take it away */ 3467421Sroot goto out; 3477421Sroot 3487421Sroot default: 3497421Sroot /* 3507421Sroot * All other signals cause the process to run 3517421Sroot */ 3527421Sroot goto run; 3537421Sroot } 3547421Sroot /*NOTREACHED*/ 3557421Sroot 3567421Sroot case SSTOP: 3577421Sroot /* 3587421Sroot * If traced process is already stopped, 3597421Sroot * then no further action is necessary. 3607421Sroot */ 3617421Sroot if (p->p_flag&STRC) 3627421Sroot goto out; 3637421Sroot switch (sig) { 3647421Sroot 3657421Sroot case SIGKILL: 3667421Sroot /* 3677421Sroot * Kill signal always sets processes running. 3687421Sroot */ 3697421Sroot goto run; 3707421Sroot 3717421Sroot case SIGCONT: 3727421Sroot /* 3737421Sroot * If the process catches SIGCONT, let it handle 3747421Sroot * the signal itself. If it isn't waiting on 3757421Sroot * an event, then it goes back to run state. 3767421Sroot * Otherwise, process goes back to sleep state. 3777421Sroot */ 3787421Sroot if (action != SIG_DFL || p->p_wchan == 0) 3797421Sroot goto run; 3807421Sroot p->p_stat = SSLEEP; 3817421Sroot goto out; 3827421Sroot 3837421Sroot case SIGSTOP: 3847421Sroot case SIGTSTP: 3857421Sroot case SIGTTIN: 3867421Sroot case SIGTTOU: 3877421Sroot /* 3887421Sroot * Already stopped, don't need to stop again. 3897421Sroot * (If we did the shell could get confused.) 3907421Sroot */ 3917421Sroot p->p_sig &= ~sigmask; /* take it away */ 3927421Sroot goto out; 3937421Sroot 3947421Sroot default: 3957421Sroot /* 3967421Sroot * If process is sleeping interruptibly, then 3977421Sroot * unstick it so that when it is continued 3987421Sroot * it can look at the signal. 3997421Sroot * But don't setrun the process as its not to 4007421Sroot * be unstopped by the signal alone. 4017421Sroot */ 4027421Sroot if (p->p_wchan && p->p_pri > PZERO) 4037421Sroot unsleep(p); 4047421Sroot goto out; 4057421Sroot } 4067421Sroot /*NOTREACHED*/ 4077421Sroot 4087421Sroot default: 4097421Sroot /* 4107421Sroot * SRUN, SIDL, SZOMB do nothing with the signal, 4117421Sroot * other than kicking ourselves if we are running. 4127421Sroot * It will either never be noticed, or noticed very soon. 4137421Sroot */ 4147421Sroot if (p == u.u_procp && !noproc) 4158444Sroot #include "../vax/mtpr.h" 4167421Sroot aston(); 4177421Sroot goto out; 4187421Sroot } 4197421Sroot /*NOTREACHED*/ 4207421Sroot run: 4217421Sroot /* 4227421Sroot * Raise priority to at least PUSER. 4237421Sroot */ 4247421Sroot if (p->p_pri > PUSER) 4257421Sroot if ((p != u.u_procp || noproc) && p->p_stat == SRUN && 4267421Sroot (p->p_flag & SLOAD)) { 4277421Sroot remrq(p); 4287421Sroot p->p_pri = PUSER; 4297421Sroot setrq(p); 4307421Sroot } else 4317421Sroot p->p_pri = PUSER; 4327421Sroot setrun(p); 4337421Sroot out: 4347421Sroot splx(s); 4357421Sroot } 4367421Sroot 4377421Sroot /* 4387421Sroot * Returns true if the current 4397421Sroot * process has a signal to process. 4407421Sroot * The signal to process is put in p_cursig. 4417421Sroot * This is asked at least once each time a process enters the 4427421Sroot * system (though this can usually be done without actually 4437421Sroot * calling issig by checking the pending signal masks.) 4447421Sroot * A signal does not do anything 4457421Sroot * directly to a process; it sets 4467421Sroot * a flag that asks the process to 4477421Sroot * do something to itself. 4487421Sroot */ 4497421Sroot issig() 4507421Sroot { 4517421Sroot register struct proc *p; 4527421Sroot register int sig; 4537421Sroot long sigbits; 4547421Sroot long sigmask; 4557421Sroot 4567421Sroot p = u.u_procp; 4577421Sroot for (;;) { 4587421Sroot sigbits = p->p_sig; 4597421Sroot if ((p->p_flag&STRC) == 0) 4607421Sroot sigbits &= ~p->p_ignsig; 4617421Sroot if (p->p_flag&SVFORK) 4627421Sroot #define bit(a) (1<<(a-1)) 4637421Sroot sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); 4647421Sroot if (sigbits == 0) 4657421Sroot break; 4667421Sroot sig = ffs((int)sigbits); 4677421Sroot sigmask = 1L << (sig-1); 4687421Sroot p->p_sig &= ~sigmask; /* take the signal! */ 4697421Sroot p->p_cursig = sig; 4707421Sroot if (p->p_flag&STRC && (p->p_flag&SVFORK)==0) { 4717421Sroot /* 4727421Sroot * If traced, always stop, and stay 4737421Sroot * stopped until released by the parent. 4747421Sroot */ 4757421Sroot do { 4767421Sroot stop(p); 4777421Sroot swtch(); 4787421Sroot } while (!procxmt() && p->p_flag&STRC); 4797421Sroot 4807421Sroot /* 4817421Sroot * If the traced bit got turned off, 4827421Sroot * then put the signal taken above back into p_sig 4837421Sroot * and go back up to the top to rescan signals. 4847421Sroot * This ensures that siga0 and u_signal are consistent. 4857421Sroot */ 4867421Sroot if ((p->p_flag&STRC) == 0) { 4877421Sroot p->p_sig |= sigmask; 4887421Sroot continue; 4897421Sroot } 4907421Sroot 4917421Sroot /* 4927421Sroot * If parent wants us to take the signal, 4937421Sroot * then it will leave it in p->p_cursig; 4947421Sroot * otherwise we just look for signals again. 4957421Sroot */ 4967421Sroot sig = p->p_cursig; 4977421Sroot if (sig == 0) 4987421Sroot continue; 4997421Sroot } 5007421Sroot switch (u.u_signal[sig]) { 5017421Sroot 5027421Sroot case SIG_DFL: 5037421Sroot /* 5047421Sroot * Don't take default actions on system processes. 5057421Sroot */ 5067421Sroot if (p->p_ppid == 0) 5077421Sroot break; 5087421Sroot switch (sig) { 5097421Sroot 5107421Sroot case SIGTSTP: 5117421Sroot case SIGTTIN: 5127421Sroot case SIGTTOU: 5137421Sroot /* 5147421Sroot * Children of init aren't allowed to stop 5157421Sroot * on signals from the keyboard. 5167421Sroot */ 5177421Sroot if (p->p_pptr == &proc[1]) { 5187421Sroot psignal(p, SIGKILL); 5197421Sroot continue; 5207421Sroot } 5217421Sroot /* fall into ... */ 5227421Sroot 5237421Sroot case SIGSTOP: 5247421Sroot if (p->p_flag&STRC) 5257421Sroot continue; 5267421Sroot stop(p); 5277421Sroot swtch(); 5287421Sroot continue; 5297421Sroot 5307421Sroot case SIGCONT: 5317421Sroot case SIGCHLD: 5327421Sroot /* 5337421Sroot * These signals are normally not 5347421Sroot * sent if the action is the default. 5357421Sroot */ 5367421Sroot continue; /* == ignore */ 5377421Sroot 5387421Sroot default: 5397421Sroot goto send; 5407421Sroot } 5417421Sroot /*NOTREACHED*/ 5427421Sroot 5437421Sroot case SIG_HOLD: 5447421Sroot case SIG_IGN: 5457421Sroot /* 5467421Sroot * Masking above should prevent us 5477421Sroot * ever trying to take action on a held 5487421Sroot * or ignored signal, unless process is traced. 5497421Sroot */ 5507421Sroot if ((p->p_flag&STRC) == 0) 5517421Sroot printf("issig\n"); 5527421Sroot continue; 5537421Sroot 5547421Sroot default: 5557421Sroot /* 5567421Sroot * This signal has an action, let 5577421Sroot * psig process it. 5587421Sroot */ 5597421Sroot goto send; 5607421Sroot } 5617421Sroot /*NOTREACHED*/ 5627421Sroot } 5637421Sroot /* 5647421Sroot * Didn't find a signal to send. 5657421Sroot */ 5667421Sroot p->p_cursig = 0; 5677421Sroot return (0); 5687421Sroot 5697421Sroot send: 5707421Sroot /* 5717421Sroot * Let psig process the signal. 5727421Sroot */ 5737421Sroot return (sig); 5747421Sroot } 5757421Sroot 5767421Sroot /* 5777421Sroot * Put the argument process into the stopped 5787421Sroot * state and notify the parent via wakeup and/or signal. 5797421Sroot */ 5807421Sroot stop(p) 5817421Sroot register struct proc *p; 5827421Sroot { 5837421Sroot 5847421Sroot p->p_stat = SSTOP; 5857421Sroot p->p_flag &= ~SWTED; 5867421Sroot wakeup((caddr_t)p->p_pptr); 5877421Sroot /* 5887421Sroot * Avoid sending signal to parent if process is traced 5897421Sroot */ 5907421Sroot if (p->p_flag&STRC) 5917421Sroot return; 5927421Sroot psignal(p->p_pptr, SIGCHLD); 5937421Sroot } 5947421Sroot 5957421Sroot /* 5967421Sroot * Perform the action specified by 5977421Sroot * the current signal. 5987421Sroot * The usual sequence is: 5997421Sroot * if (issig()) 6007421Sroot * psig(); 6017421Sroot * The signal bit has already been cleared by issig, 6027421Sroot * and the current signal number stored in p->p_cursig. 6037421Sroot */ 6047421Sroot psig() 6057421Sroot { 6067421Sroot register struct proc *rp = u.u_procp; 6077421Sroot register int n = rp->p_cursig; 6087421Sroot long sigmask = 1L << (n-1); 6097421Sroot register int (*action)(); 6107421Sroot 6117421Sroot if (rp->p_cursig == 0) 6127421Sroot panic("psig"); 6137421Sroot action = u.u_signal[n]; 6147421Sroot if (action != SIG_DFL) { 6157421Sroot if (action == SIG_IGN || action == SIG_HOLD) 6167421Sroot panic("psig action"); 6177421Sroot u.u_error = 0; 6187421Sroot if (n != SIGILL && n != SIGTRAP) 6197421Sroot u.u_signal[n] = 0; 6207421Sroot /* 6217421Sroot * If this catch value indicates automatic holding of 6227421Sroot * subsequent signals, set the hold value. 6237421Sroot */ 6247421Sroot if (SIGISDEFER(action)) { 6257421Sroot (void) spl6(); 6267421Sroot if ((int)SIG_HOLD & 1) 6277421Sroot rp->p_siga0 |= sigmask; 6287421Sroot else 6297421Sroot rp->p_siga0 &= ~sigmask; 6307421Sroot if ((int)SIG_HOLD & 2) 6317421Sroot rp->p_siga1 |= sigmask; 6327421Sroot else 6337421Sroot rp->p_siga1 &= ~sigmask; 6347421Sroot u.u_signal[n] = SIG_HOLD; 6357421Sroot (void) spl0(); 6367421Sroot action = SIGUNDEFER(action); 6377421Sroot } 6388032Sroot u.u_ru.ru_nsignals++; 6397421Sroot sendsig(action, n); 6407421Sroot rp->p_cursig = 0; 6417421Sroot return; 6427421Sroot } 6437421Sroot u.u_acflag |= AXSIG; 6447421Sroot switch (n) { 6457421Sroot 6467421Sroot case SIGILL: 6477421Sroot case SIGIOT: 6487421Sroot case SIGBUS: 6497421Sroot case SIGQUIT: 6507421Sroot case SIGTRAP: 6517421Sroot case SIGEMT: 6527421Sroot case SIGFPE: 6537421Sroot case SIGSEGV: 6547421Sroot case SIGSYS: 6557421Sroot u.u_arg[0] = n; 6567421Sroot if (core()) 6577421Sroot n += 0200; 6587421Sroot } 6597421Sroot exit(n); 6607421Sroot } 6617421Sroot 6627421Sroot #ifdef unneeded 6637421Sroot int corestop = 0; 6647421Sroot #endif 6657421Sroot /* 6667421Sroot * Create a core image on the file "core" 6677421Sroot * If you are looking for protection glitches, 6687421Sroot * there are probably a wealth of them here 6697421Sroot * when this occurs to a suid command. 6707421Sroot * 6717421Sroot * It writes UPAGES block of the 6727421Sroot * user.h area followed by the entire 6737421Sroot * data+stack segments. 6747421Sroot */ 6757421Sroot core() 6767421Sroot { 6777421Sroot register struct inode *ip; 6787421Sroot extern schar(); 6797421Sroot 6807421Sroot #ifdef unneeded 6817421Sroot if (corestop) { 6827421Sroot int i; 6837421Sroot for (i = 0; i < 10; i++) 6847421Sroot if (u.u_comm[i]) 6857421Sroot putchar(u.u_comm[i], 0); 6867421Sroot printf(", uid %d\n", u.u_uid); 6877421Sroot if (corestop&2) 6887421Sroot asm("halt"); 6897421Sroot } 6907421Sroot #endif 6917421Sroot if (u.u_uid != u.u_ruid) 6927818Sroot return (0); 6938032Sroot if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= 6948032Sroot u.u_rlimit[RLIMIT_CORE].rlim_cur) 6957421Sroot return (0); 6967421Sroot u.u_error = 0; 6977421Sroot u.u_dirp = "core"; 6989160Ssam ip = namei(schar, CREATE, 1); 6997421Sroot if (ip == NULL) { 7007421Sroot if (u.u_error) 7017421Sroot return (0); 7027421Sroot ip = maknode(0666); 7037421Sroot if (ip==NULL) 7047421Sroot return (0); 7057421Sroot } 7067818Sroot if (access(ip, IWRITE) || 7077818Sroot (ip->i_mode&IFMT) != IFREG || 7087818Sroot ip->i_nlink != 1) { 7097421Sroot u.u_error = EFAULT; 7107818Sroot goto out; 7117818Sroot } 7129160Ssam itrunc(ip, (u_long)0); 7137818Sroot u.u_acflag |= ACORE; 7148967Sroot /* if (u.u_error == 0) */ 7158967Sroot u.u_error = rdwri(UIO_WRITE, ip, 7168967Sroot (caddr_t)&u, 7178967Sroot ctob(UPAGES), 7188967Sroot 0, 1, (int *)0); 7198101Sroot if (u.u_error == 0) 7208644Sroot u.u_error = rdwri(UIO_WRITE, ip, 7218967Sroot (caddr_t)ctob(dptov(u.u_procp, 0)), 7228967Sroot ctob(u.u_dsize), 7238644Sroot ctob(UPAGES), 0, (int *)0); 7248101Sroot if (u.u_error == 0) 7258644Sroot u.u_error = rdwri(UIO_WRITE, ip, 7268967Sroot (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), 7278967Sroot ctob(u.u_ssize), 7288644Sroot ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); 7297818Sroot out: 7307421Sroot iput(ip); 7317818Sroot return (u.u_error == 0); 7327421Sroot } 733