General cleanup of core-dumping code.

Submitted by: Sean Fagan,
This commit is contained in:
Julian Elischer 1999-09-01 00:29:56 +00:00
parent 8f0ba3dbab
commit fca666a142
7 changed files with 87 additions and 88 deletions

View File

@ -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;
}
/*

View File

@ -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;
}
/*

View File

@ -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;
@ -1352,6 +1353,71 @@ const char *name; uid_t uid; pid_t pid; {
return temp;
}
/*
* 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).

View File

@ -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 */

View File

@ -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 */

View File

@ -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));

View File

@ -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 */
};