summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--sys/kern/imgact_aout.c44
-rw-r--r--sys/kern/imgact_elf.c52
-rw-r--r--sys/kern/kern_sig.c72
-rw-r--r--sys/sys/imgact_aout.h2
-rw-r--r--sys/sys/imgact_elf.h2
-rw-r--r--sys/sys/signalvar.h1
-rw-r--r--sys/sys/sysent.h2
7 files changed, 87 insertions, 88 deletions
diff --git a/sys/kern/imgact_aout.c b/sys/kern/imgact_aout.c
index 0b3cbf5..90f22dd 100644
--- a/sys/kern/imgact_aout.c
+++ b/sys/kern/imgact_aout.c
@@ -75,7 +75,7 @@ struct sysentvec aout_sysvec = {
aout_coredump
};
-static int
+int
exec_aout_imgact(imgp)
struct image_params *imgp;
{
@@ -244,44 +244,19 @@ exec_aout_imgact(imgp)
* expand_name(), unless the process was setuid/setgid.
*/
int
-aout_coredump(p)
+aout_coredump(p, vp, limit)
register struct proc *p;
-{
register struct vnode *vp;
+ off_t limit;
+{
register struct ucred *cred = p->p_cred->pc_ucred;
register struct vmspace *vm = p->p_vmspace;
- struct nameidata nd;
- struct vattr vattr;
- int error, error1;
- char *name; /* name of corefile */
+ int error = 0;
- STOPEVENT(p, S_CORE, 0);
- if (sugid_coredump == 0 && p->p_flag & P_SUGID)
- return (EFAULT);
if (ctob(UPAGES + vm->vm_dsize + vm->vm_ssize) >=
- p->p_rlimit[RLIMIT_CORE].rlim_cur)
+ limit)
return (EFAULT);
- name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
- if (name == NULL)
- return (EFAULT); /* XXX -- not the best error */
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
- error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
- free(name, M_TEMP);
- if (error)
- return (error);
- vp = nd.ni_vp;
- /* Don't dump to non-regular files or files with links. */
- if (vp->v_type != VREG ||
- VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
- error = EFAULT;
- goto out;
- }
- VATTR_NULL(&vattr);
- vattr.va_size = 0;
- VOP_LEASE(vp, p, cred, LEASE_WRITE);
- VOP_SETATTR(vp, &vattr, cred, p);
- p->p_acflag |= ACORE;
bcopy(p, &p->p_addr->u_kproc.kp_proc, sizeof(struct proc));
fill_eproc(p, &p->p_addr->u_kproc.kp_eproc);
error = cpu_coredump(p, vp, cred);
@@ -295,12 +270,7 @@ aout_coredump(p)
round_page(ctob(vm->vm_ssize)),
(off_t)ctob(UPAGES) + ctob(vm->vm_dsize), UIO_USERSPACE,
IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
-out:
- VOP_UNLOCK(vp, 0, p);
- error1 = vn_close(vp, FWRITE, cred, p);
- if (error == 0)
- error = error1;
- return (error);
+ return error;
}
/*
diff --git a/sys/kern/imgact_elf.c b/sys/kern/imgact_elf.c
index d58d274..e31d90b 100644
--- a/sys/kern/imgact_elf.c
+++ b/sys/kern/imgact_elf.c
@@ -683,24 +683,17 @@ static void elf_putnote __P((void *, size_t *, const char *, int,
extern int osreldate;
int
-elf_coredump(p)
+elf_coredump(p, vp, limit)
register struct proc *p;
-{
register struct vnode *vp;
+ off_t limit;
+{
register struct ucred *cred = p->p_cred->pc_ucred;
- struct nameidata nd;
- struct vattr vattr;
- int error, error1;
- char *name; /* name of corefile */
+ int error = 0;
struct sseg_closure seginfo;
void *hdr;
size_t hdrsize;
- STOPEVENT(p, S_CORE, 0);
-
- if (sugid_coredump == 0 && p->p_flag & P_SUGID)
- return (EFAULT);
-
/* Size the program segments. */
seginfo.count = 0;
seginfo.size = 0;
@@ -716,31 +709,8 @@ elf_coredump(p)
(const prstatus_t *)NULL, (const prfpregset_t *)NULL,
(const prpsinfo_t *)NULL, seginfo.count);
- if (hdrsize + seginfo.size >= p->p_rlimit[RLIMIT_CORE].rlim_cur)
+ if (hdrsize + seginfo.size >= limit)
return (EFAULT);
- name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
- if (name == NULL)
- return (EFAULT); /* XXX -- not the best error */
-
- NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
- error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
- free(name, M_TEMP);
- if (error)
- return (error);
- vp = nd.ni_vp;
-
- /* Don't dump to non-regular files or files with links. */
- if (vp->v_type != VREG ||
- VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
- error = EFAULT;
- goto out;
- }
- VATTR_NULL(&vattr);
- vattr.va_size = 0;
- VOP_LEASE(vp, p, cred, LEASE_WRITE);
- VOP_SETATTR(vp, &vattr, cred, p);
- p->p_acflag |= ACORE;
-
/*
* Allocate memory for building the header, fill it up,
@@ -748,8 +718,7 @@ elf_coredump(p)
*/
hdr = malloc(hdrsize, M_TEMP, M_WAITOK);
if (hdr == NULL) {
- error = EINVAL;
- goto out;
+ return EINVAL;
}
error = elf_corehdr(p, vp, cred, seginfo.count, hdr, hdrsize);
@@ -772,13 +741,8 @@ elf_coredump(p)
}
}
free(hdr, M_TEMP);
-
-out:
- VOP_UNLOCK(vp, 0, p);
- error1 = vn_close(vp, FWRITE, cred, p);
- if (error == 0)
- error = error1;
- return (error);
+
+ return error;
}
/*
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index 49465fc..4921a39 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -71,6 +71,8 @@
static int killpg1 __P((struct proc *cp, int signum, int pgid, int all));
static void setsigvec __P((struct proc *p, int signum, struct sigaction *sa));
static void stop __P((struct proc *));
+static char *expand_name __P((const char *, uid_t, int));
+static int coredump __P((struct proc *));
static int kern_logsigexit = 1;
SYSCTL_INT(_kern, KERN_LOGSIGEXIT, logsigexit, CTLFLAG_RW,
@@ -1255,8 +1257,7 @@ sigexit(p, signum)
* these messages.)
* XXX : Todo, as well as euid, write out ruid too
*/
- if (p->p_sysent->sv_coredump != NULL &&
- (*p->p_sysent->sv_coredump)(p) == 0)
+ if (coredump(p) == 0)
signum |= WCOREFLAG;
if (kern_logsigexit)
log(LOG_INFO,
@@ -1286,7 +1287,7 @@ SYSCTL_STRING(_kern, OID_AUTO, corefile, CTLFLAG_RW, corefilename,
* This is controlled by the sysctl variable kern.corefile (see above).
*/
-char *
+static char *
expand_name(name, uid, pid)
const char *name; uid_t uid; pid_t pid; {
char *temp;
@@ -1353,6 +1354,71 @@ const char *name; uid_t uid; pid_t pid; {
}
/*
+ * Dump a process' core. The main routine does some
+ * policy checking, and creates the name of the coredump;
+ * then it passes on a vnode and a size limit to the process-specific
+ * coredump routine if there is one; if there _is not_ one, it returns
+ * ENOSYS; otherwise it returns the error from the process-specific routine.
+ */
+
+static int
+coredump(p)
+ register struct proc *p;
+{
+ register struct vnode *vp;
+ register struct ucred *cred = p->p_cred->pc_ucred;
+ struct nameidata nd;
+ struct vattr vattr;
+ int error, error1;
+ char *name; /* name of corefile */
+ off_t limit;
+
+ STOPEVENT(p, S_CORE, 0);
+
+ if ((sugid_coredump == 0) && p->p_flag & P_SUGID)
+ return (EFAULT);
+
+ /*
+ * Note that this layout means that limit checking is done
+ * AFTER the corefile name is created. This could happen
+ * other ways as well, so I'm not too worried about it, but
+ * it is potentially confusing.
+ */
+ name = expand_name(p->p_comm, p->p_ucred->cr_uid, p->p_pid);
+ NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
+ error = vn_open(&nd, O_CREAT | FWRITE | O_NOFOLLOW, S_IRUSR | S_IWUSR);
+ free(name, M_TEMP);
+ if (error)
+ return (error);
+ vp = nd.ni_vp;
+
+ /* Don't dump to non-regular files or files with links. */
+ if (vp->v_type != VREG ||
+ VOP_GETATTR(vp, &vattr, cred, p) || vattr.va_nlink != 1) {
+ error = EFAULT;
+ goto out;
+ }
+ VATTR_NULL(&vattr);
+ vattr.va_size = 0;
+ VOP_LEASE(vp, p, cred, LEASE_WRITE);
+ VOP_SETATTR(vp, &vattr, cred, p);
+ p->p_acflag |= ACORE;
+
+ limit = p->p_rlimit[RLIMIT_CORE].rlim_cur;
+
+ error = p->p_sysent->sv_coredump ?
+ p->p_sysent->sv_coredump(p, vp, limit) :
+ ENOSYS;
+
+out:
+ VOP_UNLOCK(vp, 0, p);
+ error1 = vn_close(vp, FWRITE, cred, p);
+ if (error == 0)
+ error = error1;
+ return (error);
+}
+
+/*
* Nonexistent system call-- signal process (may want to handle it).
* Flag error in case process won't see signal immediately (blocked or ignored).
*/
diff --git a/sys/sys/imgact_aout.h b/sys/sys/imgact_aout.h
index 5b4b68f..873f1b2 100644
--- a/sys/sys/imgact_aout.h
+++ b/sys/sys/imgact_aout.h
@@ -151,7 +151,7 @@ struct exec {
struct proc;
__BEGIN_DECLS
-int aout_coredump __P((struct proc *));
+int aout_coredump __P((struct proc *, struct vnode *, off_t));
__END_DECLS
#endif /* KERNEL */
diff --git a/sys/sys/imgact_elf.h b/sys/sys/imgact_elf.h
index 596ecdb..3c6e7ec 100644
--- a/sys/sys/imgact_elf.h
+++ b/sys/sys/imgact_elf.h
@@ -103,7 +103,7 @@ int elf_remove_brand_entry __P((Elf64_Brandinfo *entry));
struct proc;
-int elf_coredump __P((struct proc *));
+int elf_coredump __P((struct proc *, struct vnode *, off_t));
#endif /* KERNEL */
diff --git a/sys/sys/signalvar.h b/sys/sys/signalvar.h
index 058f0f1..b3da667 100644
--- a/sys/sys/signalvar.h
+++ b/sys/sys/signalvar.h
@@ -158,7 +158,6 @@ extern int sugid_coredump; /* Sysctl variable kern.sugid_coredump */
* Machine-independent functions:
*/
void execsigs __P((struct proc *p));
-char *expand_name __P((const char*, uid_t, pid_t));
void gsignal __P((int pgid, int sig));
int issignal __P((struct proc *p));
void killproc __P((struct proc *p, char *why));
diff --git a/sys/sys/sysent.h b/sys/sys/sysent.h
index ab258c2..e593f38 100644
--- a/sys/sys/sysent.h
+++ b/sys/sys/sysent.h
@@ -69,7 +69,7 @@ struct sysentvec {
void (*sv_prepsyscall) __P((struct trapframe *, int *,
u_int *, caddr_t *));
char *sv_name; /* name of binary type */
- int (*sv_coredump) __P((struct proc *p));
+ int (*sv_coredump) __P((struct proc *p, struct vnode *, off_t));
/* function to dump core, or NULL */
};
OpenPOWER on IntegriCloud