* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
* SUCH DAMAGE.
*
- * @(#)kern_sig.c 7.35 (Berkeley) 6/28/91
+ * from: @(#)kern_sig.c 7.35 (Berkeley) 6/28/91
+ * $Id: kern_sig.c,v 1.11 1994/05/05 18:44:13 csgr Exp $
*/
#define SIGPROP /* include signal properties table */
#include "resourcevar.h"
#include "namei.h"
#include "vnode.h"
+#include "mount.h"
+#include "filedesc.h"
#include "proc.h"
+#include "ucred.h"
#include "systm.h"
#include "timeb.h"
#include "times.h"
#include "kernel.h"
#include "wait.h"
#include "ktrace.h"
+#include "syslog.h"
#include "machine/cpu.h"
#include "kinfo_proc.h"
#include "user.h" /* for coredump */
+static void setsigvec(struct proc *, int, struct sigaction *);
+static void stop(struct proc *);
+static void sigexit(struct proc *, int);
+static int killpg1(struct proc *, int, int, int);
+
/*
* Can process p, with pcred pc, send the signal signo to process q?
*/
(pc)->pc_ucred->cr_uid == (q)->p_ucred->cr_uid || \
((signo) == SIGCONT && (q)->p_session == (p)->p_session))
+struct sigaction_args {
+ int signo;
+ struct sigaction *nsa;
+ struct sigaction *osa;
+};
+
/* ARGSUSED */
+int
sigaction(p, uap, retval)
struct proc *p;
- register struct args {
- int signo;
- struct sigaction *nsa;
- struct sigaction *osa;
- } *uap;
+ register struct sigaction_args *uap;
int *retval;
{
struct sigaction vec;
return (0);
}
+void
setsigvec(p, sig, sa)
register struct proc *p;
int sig;
* and return old mask as return value;
* the library stub does the rest.
*/
+
+struct sigprocmask_args {
+ int how;
+ sigset_t mask;
+};
+
+int
sigprocmask(p, uap, retval)
register struct proc *p;
- struct args {
- int how;
- sigset_t mask;
- } *uap;
+ struct sigprocmask_args *uap;
int *retval;
{
int error = 0;
}
/* ARGSUSED */
+int
sigpending(p, uap, retval)
struct proc *p;
void *uap;
/*
* Generalized interface signal handler, 4.3-compatible.
*/
+
+struct osigvec_args {
+ int signo;
+ struct sigvec *nsv;
+ struct sigvec *osv;
+};
+
/* ARGSUSED */
+int
osigvec(p, uap, retval)
struct proc *p;
- register struct args {
- int signo;
- struct sigvec *nsv;
- struct sigvec *osv;
- } *uap;
+ register struct osigvec_args *uap;
int *retval;
{
struct sigvec vec;
return (0);
}
+struct osigblock_args {
+ int mask;
+};
+
+int
osigblock(p, uap, retval)
register struct proc *p;
- struct args {
- int mask;
- } *uap;
+ struct osigblock_args *uap;
int *retval;
{
return (0);
}
+struct osigsetmask_args {
+ int mask;
+};
+
+int
osigsetmask(p, uap, retval)
struct proc *p;
- struct args {
- int mask;
- } *uap;
+ struct osigsetmask_args *uap;
int *retval;
{
* in the meantime. Note nonstandard calling convention:
* libc stub passes mask, not pointer, to save a copyin.
*/
+
+struct sigsuspend_args {
+ sigset_t mask;
+};
+
/* ARGSUSED */
+int
sigsuspend(p, uap, retval)
register struct proc *p;
- struct args {
- sigset_t mask;
- } *uap;
+ struct sigsuspend_args *uap;
int *retval;
{
register struct sigacts *ps = p->p_sigacts;
return (EINTR);
}
+struct sigstack_args {
+ struct sigstack *nss;
+ struct sigstack *oss;
+};
+
/* ARGSUSED */
+int
sigstack(p, uap, retval)
struct proc *p;
- register struct args {
- struct sigstack *nss;
- struct sigstack *oss;
- } *uap;
+ register struct sigstack_args *uap;
int *retval;
{
struct sigstack ss;
return (error);
}
+struct kill_args {
+ int pid;
+ int signo;
+};
+
/* ARGSUSED */
+int
kill(cp, uap, retval)
register struct proc *cp;
- register struct args {
- int pid;
- int signo;
- } *uap;
+ register struct kill_args *uap;
int *retval;
{
register struct proc *p;
}
#ifdef COMPAT_43
+
+struct okillpg_args {
+ int pgid;
+ int signo;
+};
+
/* ARGSUSED */
+int
okillpg(p, uap, retval)
struct proc *p;
- register struct args {
- int pgid;
- int signo;
- } *uap;
+ register struct okillpg_args *uap;
int *retval;
{
* Common code for kill process group/broadcast kill.
* cp is calling process.
*/
+static int
killpg1(cp, signo, pgid, all)
register struct proc *cp;
int signo, pgid, all;
register sig_t action;
int mask;
+ /* Ignore signals to system (internal) daemons */
+ if (p->p_flag & SSYS)
+ return;
+
if ((unsigned)sig >= NSIG || sig == 0)
panic("psignal sig");
mask = sigmask(sig);
* while (sig = CURSIG(curproc))
* psig(sig);
*/
+int
issig(p)
register struct proc *p;
{
* Signals are handled elsewhere.
* The process must not be on the run queue.
*/
+static void
stop(p)
register struct proc *p;
{
* If dumping core, save the signal number for the debugger.
* Calls exit and does not return.
*/
+static void
sigexit(p, sig)
register struct proc *p;
int sig;
p->p_acflag |= AXSIG;
if (sigprop[sig] & SA_CORE) {
p->p_sigacts->ps_sig = sig;
+ /*
+ * Log signals which would cause core dumps
+ * (Log as LOG_INFO to appease those who don't want
+ * these messages.)
+ * XXX : Todo, as well as euid, write out ruid too
+ */
+ log(LOG_INFO, "pid %d: %s: uid %d: exited on signal %d\n",
+ p->p_pid, p->p_comm, p->p_ucred->cr_uid, sig);
if (coredump(p) == 0)
sig |= WCOREFLAG;
}
- exit(p, W_EXITCODE(0, sig));
+ kexit(p, W_EXITCODE(0, sig));
/* NOTREACHED */
}
/*
* Create a core dump.
- * The file name is "core.progname".
- * Core dumps are not created if the process is setuid.
+ * The file name is "progname.core".
+ * Core dumps are not created if:
+ * the process is setuid,
+ * we are on a filesystem mounted with MNT_NOCORE,
+ * a file already exists and is not a core file,
+ * or was not produced from the same program,
+ * the link count to the corefile is > 1.
*/
+int
coredump(p)
register struct proc *p;
{
register struct ucred *cred = pcred->pc_ucred;
register struct vmspace *vm = p->p_vmspace;
struct vattr vattr;
- int error, error1;
+ int error, error1, exists;
struct nameidata nd;
- char name[MAXCOMLEN+6]; /* core.progname */
+ char name[MAXCOMLEN+6]; /* progname.core */
if (pcred->p_svuid != pcred->p_ruid ||
pcred->p_svgid != pcred->p_rgid)
if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >=
p->p_rlimit[RLIMIT_CORE].rlim_cur)
return (EFAULT);
- sprintf(name, "core.%s", p->p_comm);
+ if (p->p_fd->fd_cdir->v_mount->mnt_flag & MNT_NOCORE)
+ return (EFAULT);
+
+ sprintf(name, "%s.core", p->p_comm);
nd.ni_dirp = name;
nd.ni_segflg = UIO_SYSSPACE;
- if (error = vn_open(&nd, p, O_CREAT|FWRITE, 0644))
+ if ((error = vn_open(&nd, p, FWRITE, 0600)) == 0)
+ exists = 1;
+ else
+ exists = 0;
+ if (error == ENOENT)
+ error = vn_open(&nd, p, O_CREAT | FWRITE, 0600);
+ if (error)
return (error);
vp = nd.ni_vp;
if (vp->v_type != VREG || VOP_GETATTR(vp, &vattr, cred, p) ||
error = EFAULT;
goto out;
}
+ if (exists) { /* if file already exists, look if it's a coredump */
+ struct user userbuf; /* XXX */
+ error = vn_rdwr(UIO_READ, vp, (caddr_t)&userbuf, sizeof(userbuf),
+ (off_t)0, UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred,
+ (int *)NULL, p);
+ if (error || (vattr.va_size != ctob(UPAGES +
+ userbuf.u_kproc.kp_eproc.e_vm.vm_dsize +
+ userbuf.u_kproc.kp_eproc.e_vm.vm_ssize)) ||
+ strcmp(p->p_comm, userbuf.u_kproc.kp_proc.p_comm)) {
+ error = EFAULT;
+ goto out;
+ }
+ }
VATTR_NULL(&vattr);
vattr.va_size = 0;
VOP_SETATTR(vp, &vattr, cred, p);
* Flag error in case process won't see signal immediately (blocked or ignored).
*/
/* ARGSUSED */
+int
nosys(p, args, retval)
struct proc *p;
void *args;