mirror of
https://git.FreeBSD.org/src.git
synced 2024-12-14 10:09:48 +00:00
General cleanup of core-dumping code.
Submitted by: Sean Fagan,
This commit is contained in:
parent
8f0ba3dbab
commit
fca666a142
Notes:
svn2git
2020-12-20 02:59:44 +00:00
svn path=/head/; revision=50717
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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).
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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 */
|
||||
};
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user