summaryrefslogtreecommitdiffstats
path: root/sys/kern/kern_sig.c
diff options
context:
space:
mode:
authorkettenis <kettenis@openbsd.org>2009-03-05 19:52:23 +0000
committerkettenis <kettenis@openbsd.org>2009-03-05 19:52:23 +0000
commit217c6e6ea39000891b190f66e75afb72f11bd3c8 (patch)
tree6f4a4464d1640b5190dc1c3ac3dc98564b48b19d /sys/kern/kern_sig.c
parentFix a panic in ether_output() when attempting to send multicast traffic on (diff)
downloadwireguard-openbsd-217c6e6ea39000891b190f66e75afb72f11bd3c8.tar.xz
wireguard-openbsd-217c6e6ea39000891b190f66e75afb72f11bd3c8.zip
Make ELF platforms generate ELF core dumps. Somewhat based on code from
NetBSD. ok kurt@, drahn@, miod@
Diffstat (limited to 'sys/kern/kern_sig.c')
-rw-r--r--sys/kern/kern_sig.c67
1 files changed, 57 insertions, 10 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index ed52c212eca..15053a45b20 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.102 2009/01/29 22:18:06 guenther Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.103 2009/03/05 19:52:24 kettenis Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -1380,6 +1380,13 @@ sigexit(struct proc *p, int signum)
int nosuidcoredump = 1;
+struct coredump_iostate {
+ struct proc *io_proc;
+ struct vnode *io_vp;
+ struct ucred *io_cred;
+ off_t io_offset;
+};
+
/*
* Dump core, into a file named "progname.core", unless the process was
* setuid/setgid.
@@ -1392,10 +1399,10 @@ coredump(struct proc *p)
struct vmspace *vm = p->p_vmspace;
struct nameidata nd;
struct vattr vattr;
+ struct coredump_iostate io;
int error, error1, len;
char name[sizeof("/var/crash/") + MAXCOMLEN + sizeof(".core")];
char *dir = "";
- struct core core;
/*
* Don't dump if not root and the process has used set user or
@@ -1455,6 +1462,31 @@ coredump(struct proc *p)
bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc));
fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
+ io.io_proc = p;
+ io.io_vp = vp;
+ io.io_cred = cred;
+ io.io_offset = 0;
+
+ error = (*p->p_emul->e_coredump)(p, &io);
+out:
+ VOP_UNLOCK(vp, 0, p);
+ error1 = vn_close(vp, FWRITE, cred, p);
+ crfree(cred);
+ if (error == 0)
+ error = error1;
+ return (error);
+}
+
+int
+coredump_trad(struct proc *p, void *cookie)
+{
+ struct coredump_iostate *io = cookie;
+ struct vmspace *vm = io->io_proc->p_vmspace;
+ struct vnode *vp = io->io_vp;
+ struct ucred *cred = io->io_cred;
+ struct core core;
+ int error;
+
core.c_midmag = 0;
strlcpy(core.c_name, p->p_comm, sizeof(core.c_name));
core.c_nseg = 0;
@@ -1466,26 +1498,41 @@ coredump(struct proc *p)
core.c_ssize = (u_long)round_page(ptoa(vm->vm_ssize));
error = cpu_coredump(p, vp, cred, &core);
if (error)
- goto out;
+ return (error);
/*
* uvm_coredump() spits out all appropriate segments.
* All that's left to do is to write the core header.
*/
error = uvm_coredump(p, vp, cred, &core);
if (error)
- goto out;
+ return (error);
error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&core,
(int)core.c_hdrsize, (off_t)0,
UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p);
-out:
- VOP_UNLOCK(vp, 0, p);
- error1 = vn_close(vp, FWRITE, cred, p);
- crfree(cred);
- if (error == 0)
- error = error1;
return (error);
}
+int
+coredump_write(void *cookie, enum uio_seg segflg, const void *data, size_t len)
+{
+ struct coredump_iostate *io = cookie;
+ int error;
+
+ error = vn_rdwr(UIO_WRITE, io->io_vp, (void *)data, len,
+ io->io_offset, segflg,
+ IO_NODELOCKED|IO_UNIT, io->io_cred, NULL, io->io_proc);
+ if (error) {
+ printf("pid %d (%s): %s write of %zu@%p at %lld failed: %d\n",
+ io->io_proc->p_pid, io->io_proc->p_comm,
+ segflg == UIO_USERSPACE ? "user" : "system",
+ len, data, (long long) io->io_offset, error);
+ return (error);
+ }
+
+ io->io_offset += len;
+ return (0);
+}
+
/*
* Nonexistent system call-- signal process (may want to handle it).
* Flag error in case process won't see signal immediately (blocked or ignored).