X-Git-Url: https://git.subgeniuskitty.com/unix-history/.git/blobdiff_plain/1d34884955a18d4fba9967252d204fa337dabbf3..d30e3c486394d769de3bee83fa1d2ad0fb55e084:/usr/src/sys/kern/kern_sig.c diff --git a/usr/src/sys/kern/kern_sig.c b/usr/src/sys/kern/kern_sig.c index 912823dcfc..82d2aba183 100644 --- a/usr/src/sys/kern/kern_sig.c +++ b/usr/src/sys/kern/kern_sig.c @@ -1,31 +1,40 @@ -/* kern_sig.c 6.3 84/05/22 */ +/* + * Copyright (c) 1982, 1986 Regents of the University of California. + * All rights reserved. The Berkeley software License Agreement + * specifies the terms and conditions for redistribution. + * + * @(#)kern_sig.c 7.3 (Berkeley) %G% + */ #include "../machine/reg.h" #include "../machine/pte.h" #include "../machine/psl.h" +#include "../machine/mtpr.h" + +#include "param.h" +#include "systm.h" +#include "dir.h" +#include "user.h" +#include "inode.h" +#include "proc.h" +#include "timeb.h" +#include "times.h" +#include "buf.h" +#include "mount.h" +#include "text.h" +#include "seg.h" +#include "vm.h" +#include "acct.h" +#include "uio.h" +#include "kernel.h" + +#define cantmask (sigmask(SIGKILL)|sigmask(SIGCONT)|sigmask(SIGSTOP)) +#define stopsigmask (sigmask(SIGSTOP)|sigmask(SIGTSTP)| \ + sigmask(SIGTTIN)|sigmask(SIGTTOU)) -#include "../h/param.h" -#include "../h/systm.h" -#include "../h/dir.h" -#include "../h/user.h" -#include "../h/inode.h" -#include "../h/proc.h" -#include "../h/timeb.h" -#include "../h/times.h" -#include "../h/conf.h" -#include "../h/buf.h" -#include "../h/mount.h" -#include "../h/text.h" -#include "../h/seg.h" -#include "../h/vm.h" -#include "../h/acct.h" -#include "../h/uio.h" -#include "../h/kernel.h" -#include "../h/nami.h" - -#define mask(s) (1 << ((s)-1)) -#define cantmask (mask(SIGKILL)|mask(SIGCONT)|mask(SIGSTOP)) - +/* + * Generalized interface signal handler. + */ sigvec() { register struct a { @@ -36,6 +45,7 @@ sigvec() struct sigvec vec; register struct sigvec *sv; register int sig; + int bit; sig = uap->signo; if (sig <= 0 || sig >= NSIG || sig == SIGKILL || sig == SIGSTOP) { @@ -46,7 +56,12 @@ sigvec() if (uap->osv) { sv->sv_handler = u.u_signal[sig]; sv->sv_mask = u.u_sigmask[sig]; - sv->sv_onstack = (u.u_sigonstack & mask(sig)) != 0; + bit = sigmask(sig); + sv->sv_flags = 0; + if ((u.u_sigonstack & bit) != 0) + sv->sv_flags |= SV_ONSTACK; + if ((u.u_sigintr & bit) != 0) + sv->sv_flags |= SV_INTERRUPT; u.u_error = copyout((caddr_t)sv, (caddr_t)uap->osv, sizeof (vec)); if (u.u_error) @@ -72,15 +87,19 @@ setsigvec(sig, sv) register struct proc *p; register int bit; - bit = mask(sig); + bit = sigmask(sig); p = u.u_procp; /* * Change setting atomically. */ - (void) spl6(); + (void) splhigh(); u.u_signal[sig] = sv->sv_handler; u.u_sigmask[sig] = sv->sv_mask &~ cantmask; - if (sv->sv_onstack) + if (sv->sv_flags & SV_INTERRUPT) + u.u_sigintr |= bit; + else + u.u_sigintr &= ~bit; + if (sv->sv_flags & SV_ONSTACK) u.u_sigonstack |= bit; else u.u_sigonstack &= ~bit; @@ -101,33 +120,33 @@ setsigvec(sig, sv) sigblock() { struct a { - int sigmask; + int mask; } *uap = (struct a *)u.u_ap; register struct proc *p = u.u_procp; - (void) spl6(); + (void) splhigh(); u.u_r.r_val1 = p->p_sigmask; - p->p_sigmask |= uap->sigmask &~ cantmask; + p->p_sigmask |= uap->mask &~ cantmask; (void) spl0(); } sigsetmask() { struct a { - int sigmask; + int mask; } *uap = (struct a *)u.u_ap; register struct proc *p = u.u_procp; - (void) spl6(); + (void) splhigh(); u.u_r.r_val1 = p->p_sigmask; - p->p_sigmask = uap->sigmask &~ cantmask; + p->p_sigmask = uap->mask &~ cantmask; (void) spl0(); } sigpause() { struct a { - int sigmask; + int mask; } *uap = (struct a *)u.u_ap; register struct proc *p = u.u_procp; @@ -140,13 +159,12 @@ sigpause() */ u.u_oldmask = p->p_sigmask; p->p_flag |= SOMASK; - p->p_sigmask = uap->sigmask &~ cantmask; + p->p_sigmask = uap->mask &~ cantmask; for (;;) sleep((caddr_t)&u, PSLEP); /*NOTREACHED*/ } #undef cantmask -#undef mask sigstack() { @@ -170,17 +188,43 @@ sigstack() } } -/* KILL SHOULD BE UPDATED */ - kill() { register struct a { int pid; int signo; } *uap = (struct a *)u.u_ap; + register struct proc *p; - u.u_error = kill1(uap->signo < 0, - uap->signo < 0 ? -uap->signo : uap->signo, uap->pid); + if (uap->signo < 0 || uap->signo > NSIG) { + u.u_error = EINVAL; + return; + } + if (uap->pid > 0) { + /* kill single process */ + p = pfind(uap->pid); + if (p == 0) { + u.u_error = ESRCH; + return; + } + if (u.u_uid && u.u_uid != p->p_uid) + u.u_error = EPERM; + else if (uap->signo) + psignal(p, uap->signo); + return; + } + switch (uap->pid) { + case -1: /* broadcast signal */ + u.u_error = killpg1(uap->signo, 0, 1); + break; + case 0: /* signal own process group */ + u.u_error = killpg1(uap->signo, 0, 0); + break; + default: /* negative explicit process group */ + u.u_error = killpg1(uap->signo, -uap->pid, 0); + break; + } + return; } killpg() @@ -190,55 +234,44 @@ killpg() int signo; } *uap = (struct a *)u.u_ap; - u.u_error = kill1(1, uap->signo, uap->pgrp); + if (uap->signo < 0 || uap->signo > NSIG) { + u.u_error = EINVAL; + return; + } + u.u_error = killpg1(uap->signo, uap->pgrp, 0); } /* KILL CODE SHOULDNT KNOW ABOUT PROCESS INTERNALS !?! */ -kill1(ispgrp, signo, who) - int ispgrp, signo, who; +killpg1(signo, pgrp, all) + int signo, pgrp, all; { register struct proc *p; - int f, priv = 0; + int f, error = 0; - if (signo < 0 || signo > NSIG) - return (EINVAL); - if (who > 0 && !ispgrp) { - p = pfind(who); - if (p == 0) - return (ESRCH); - if (u.u_uid && u.u_uid != p->p_uid) - return (EPERM); - if (signo) - psignal(p, signo); - return (0); - } - if (who == -1 && u.u_uid == 0) - priv++, who = 0, ispgrp = 1; /* like sending to pgrp */ - else if (who == 0) { + if (!all && pgrp == 0) { /* * Zero process id means send to my process group. */ - ispgrp = 1; - who = u.u_procp->p_pgrp; - if (who == 0) - return (EINVAL); + pgrp = u.u_procp->p_pgrp; + if (pgrp == 0) + return (ESRCH); } for (f = 0, p = allproc; p != NULL; p = p->p_nxt) { - if (!ispgrp) { - if (p->p_pid != who) - continue; - } else if (p->p_pgrp != who && priv == 0 || p->p_ppid == 0 || - (p->p_flag&SSYS) || (priv && p == u.u_procp)) + if ((p->p_pgrp != pgrp && !all) || p->p_ppid == 0 || + (p->p_flag&SSYS) || (all && p == u.u_procp)) continue; if (u.u_uid != 0 && u.u_uid != p->p_uid && - (signo != SIGCONT || !inferior(p))) + (signo != SIGCONT || !inferior(p))) { + if (!all) + error = EPERM; continue; + } f++; if (signo) psignal(p, signo); } - return (f == 0 ? ESRCH : 0); + return (error ? error : (f == 0 ? ESRCH : 0)); } /* @@ -268,11 +301,11 @@ psignal(p, sig) { register int s; register int (*action)(); - int sigmask; + int mask; if ((unsigned)sig >= NSIG) return; - sigmask = 1 << (sig-1); + mask = sigmask(sig); /* * If proc is traced, always give parent a chance. @@ -284,19 +317,17 @@ psignal(p, sig) * If the signal is being ignored, * then we forget about it immediately. */ - if (p->p_sigignore & sigmask) + if (p->p_sigignore & mask) return; - if (p->p_sigmask & sigmask) + if (p->p_sigmask & mask) action = SIG_HOLD; - else if (p->p_sigcatch & sigmask) + else if (p->p_sigcatch & mask) action = SIG_CATCH; else action = SIG_DFL; } -#define mask(sig) (1<<(sig-1)) -#define stops (mask(SIGSTOP)|mask(SIGTSTP)|mask(SIGTTIN)|mask(SIGTTOU)) if (sig) { - p->p_sig |= sigmask; + p->p_sig |= mask; switch (sig) { case SIGTERM: @@ -310,25 +341,23 @@ psignal(p, sig) break; case SIGCONT: - p->p_sig &= ~stops; + p->p_sig &= ~stopsigmask; break; case SIGSTOP: case SIGTSTP: case SIGTTIN: case SIGTTOU: - p->p_sig &= ~mask(SIGCONT); + p->p_sig &= ~sigmask(SIGCONT); break; } } -#undef mask -#undef stops /* * Defer further processing for signals which are held. */ if (action == SIG_HOLD) return; - s = spl6(); + s = splhigh(); switch (p->p_stat) { case SSLEEP: @@ -365,7 +394,7 @@ psignal(p, sig) */ if (sig != SIGSTOP && p->p_pptr == &proc[1]) { psignal(p, SIGKILL); - p->p_sig &= ~sigmask; + p->p_sig &= ~mask; splx(s); return; } @@ -375,14 +404,16 @@ psignal(p, sig) */ if (p->p_flag&SVFORK) goto out; - p->p_sig &= ~sigmask; + p->p_sig &= ~mask; p->p_cursig = sig; + psignal(p->p_pptr, SIGCHLD); stop(p); goto out; case SIGIO: case SIGURG: case SIGCHLD: + case SIGWINCH: /* * These signals are special in that they * don't get propogated... if the process @@ -390,7 +421,7 @@ psignal(p, sig) */ if (action != SIG_DFL) goto run; - p->p_sig &= ~sigmask; /* take it away */ + p->p_sig &= ~mask; /* take it away */ goto out; default: @@ -436,7 +467,7 @@ psignal(p, sig) * Already stopped, don't need to stop again. * (If we did the shell could get confused.) */ - p->p_sig &= ~sigmask; /* take it away */ + p->p_sig &= ~mask; /* take it away */ goto out; default: @@ -460,7 +491,6 @@ psignal(p, sig) * It will either never be noticed, or noticed very soon. */ if (p == u.u_procp && !noproc) -#include "../vax/mtpr.h" aston(); goto out; } @@ -470,13 +500,7 @@ run: * Raise priority to at least PUSER. */ if (p->p_pri > PUSER) - if ((p != u.u_procp || noproc) && p->p_stat == SRUN && - (p->p_flag & SLOAD)) { - remrq(p); - p->p_pri = PUSER; - setrq(p); - } else - p->p_pri = PUSER; + p->p_pri = PUSER; setrun(p); out: splx(s); @@ -498,7 +522,7 @@ issig() { register struct proc *p; register int sig; - int sigbits, sigmask; + int sigbits, mask; p = u.u_procp; for (;;) { @@ -506,19 +530,19 @@ issig() if ((p->p_flag&STRC) == 0) sigbits &= ~p->p_sigignore; if (p->p_flag&SVFORK) -#define bit(a) (1<<(a-1)) - sigbits &= ~(bit(SIGSTOP)|bit(SIGTSTP)|bit(SIGTTIN)|bit(SIGTTOU)); + sigbits &= ~stopsigmask; if (sigbits == 0) break; - sig = ffs(sigbits); - sigmask = 1 << (sig-1); - p->p_sig &= ~sigmask; /* take the signal! */ + sig = ffs((long)sigbits); + mask = sigmask(sig); + p->p_sig &= ~mask; /* take the signal! */ p->p_cursig = sig; if (p->p_flag&STRC && (p->p_flag&SVFORK) == 0) { /* * If traced, always stop, and stay * stopped until released by the parent. */ + psignal(p->p_pptr, SIGCHLD); do { stop(p); swtch(); @@ -531,7 +555,7 @@ issig() * This ensures that p_sig* and u_signal are consistent. */ if ((p->p_flag&STRC) == 0) { - p->p_sig |= sigmask; + p->p_sig |= mask; continue; } @@ -548,13 +572,13 @@ issig() * If signal is being masked put it back * into p_sig and look for other signals. */ - sigmask = 1 << (sig-1); - if (p->p_sigmask & sigmask) { - p->p_sig |= sigmask; + mask = sigmask(sig); + if (p->p_sigmask & mask) { + p->p_sig |= mask; continue; } } - switch (u.u_signal[sig]) { + switch ((int)u.u_signal[sig]) { case SIG_DFL: /* @@ -580,6 +604,7 @@ issig() case SIGSTOP: if (p->p_flag&STRC) continue; + psignal(p->p_pptr, SIGCHLD); stop(p); swtch(); continue; @@ -588,6 +613,7 @@ issig() case SIGCHLD: case SIGURG: case SIGIO: + case SIGWINCH: /* * These signals are normally not * sent if the action is the default. @@ -634,7 +660,8 @@ send: /* * Put the argument process into the stopped - * state and notify the parent via wakeup and/or signal. + * state and notify the parent via wakeup. + * Signals are handled elsewhere. */ stop(p) register struct proc *p; @@ -643,12 +670,6 @@ stop(p) p->p_stat = SSTOP; p->p_flag &= ~SWTED; wakeup((caddr_t)p->p_pptr); - /* - * Avoid sending signal to parent if process is traced - */ - if (p->p_flag&STRC) - return; - psignal(p->p_pptr, SIGCHLD); } /* @@ -664,14 +685,14 @@ psig() { register struct proc *p = u.u_procp; register int sig = p->p_cursig; - int sigmask = 1 << (sig - 1), returnmask; + int mask = sigmask(sig), returnmask; register int (*action)(); if (sig == 0) panic("psig"); action = u.u_signal[sig]; if (action != SIG_DFL) { - if (action == SIG_IGN || (p->p_sigmask & sigmask)) + if (action == SIG_IGN || (p->p_sigmask & mask)) panic("psig action"); u.u_error = 0; /* @@ -684,20 +705,20 @@ psig() * mask from before the sigpause is what we want restored * after the signal processing is completed. */ - (void) spl6(); + (void) splhigh(); if (p->p_flag & SOUSIG) { if (sig != SIGILL && sig != SIGTRAP) { u.u_signal[sig] = SIG_DFL; - p->p_sigcatch &= ~sigmask; + p->p_sigcatch &= ~mask; } - sigmask = 0; + mask = 0; } if (p->p_flag & SOMASK) { returnmask = u.u_oldmask; p->p_flag &= ~SOMASK; } else returnmask = p->p_sigmask; - p->p_sigmask |= u.u_sigmask[sig] | sigmask; + p->p_sigmask |= u.u_sigmask[sig] | mask; (void) spl0(); u.u_ru.ru_nsignals++; sendsig(action, sig, returnmask); @@ -736,20 +757,24 @@ psig() core() { register struct inode *ip; - extern schar(); + register struct nameidata *ndp = &u.u_nd; if (u.u_uid != u.u_ruid || u.u_gid != u.u_rgid) return (0); if (ctob(UPAGES+u.u_dsize+u.u_ssize) >= u.u_rlimit[RLIMIT_CORE].rlim_cur) return (0); + if (u.u_procp->p_textp && access(u.u_procp->p_textp->x_iptr, IREAD)) + return (0); u.u_error = 0; - u.u_dirp = "core"; - ip = namei(schar, CREATE, 1); + ndp->ni_nameiop = CREATE | FOLLOW; + ndp->ni_segflg = UIO_SYSSPACE; + ndp->ni_dirp = "core"; + ip = namei(ndp); if (ip == NULL) { if (u.u_error) return (0); - ip = maknode(0644); + ip = maknode(0644, ndp); if (ip==NULL) return (0); } @@ -759,22 +784,30 @@ core() u.u_error = EFAULT; goto out; } +#ifdef MMAP + { register int fd; + /* unmasp funky devices in the user's address space */ + for (fd = 0; fd < u.u_lastfile; fd++) + if (u.u_ofile[fd] && (u.u_pofile[fd] & UF_MAPPED)) + munmapfd(fd); + } +#endif itrunc(ip, (u_long)0); u.u_acflag |= ACORE; u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)&u, ctob(UPAGES), - 0, 1, (int *)0); + (off_t)0, 1, (int *)0); if (u.u_error == 0) u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)ctob(dptov(u.u_procp, 0)), - ctob(u.u_dsize), - ctob(UPAGES), 0, (int *)0); + (int)ctob(u.u_dsize), + (off_t)ctob(UPAGES), 0, (int *)0); if (u.u_error == 0) u.u_error = rdwri(UIO_WRITE, ip, (caddr_t)ctob(sptov(u.u_procp, u.u_ssize - 1)), - ctob(u.u_ssize), - ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); + (int)ctob(u.u_ssize), + (off_t)ctob(UPAGES)+ctob(u.u_dsize), 0, (int *)0); out: iput(ip); return (u.u_error == 0);