diff options
author | julian <julian@FreeBSD.org> | 1999-09-01 00:29:56 +0000 |
---|---|---|
committer | julian <julian@FreeBSD.org> | 1999-09-01 00:29:56 +0000 |
commit | 777a32c86509533074c7be935c4c055b2067f28b (patch) | |
tree | 11e2d7c456bbdbd477715a2e2bc4aec73bfec435 | |
parent | 938ff8b8dc85de738517655e95e7e31f276c899f (diff) | |
download | FreeBSD-src-777a32c86509533074c7be935c4c055b2067f28b.zip FreeBSD-src-777a32c86509533074c7be935c4c055b2067f28b.tar.gz |
General cleanup of core-dumping code.
Submitted by: Sean Fagan,
-rw-r--r-- | sys/kern/imgact_aout.c | 44 | ||||
-rw-r--r-- | sys/kern/imgact_elf.c | 52 | ||||
-rw-r--r-- | sys/kern/kern_sig.c | 72 | ||||
-rw-r--r-- | sys/sys/imgact_aout.h | 2 | ||||
-rw-r--r-- | sys/sys/imgact_elf.h | 2 | ||||
-rw-r--r-- | sys/sys/signalvar.h | 1 | ||||
-rw-r--r-- | sys/sys/sysent.h | 2 |
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 */ }; |