summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorThorsten Lockert <tholo@cvs.openbsd.org>1996-10-18 06:08:41 +0000
committerThorsten Lockert <tholo@cvs.openbsd.org>1996-10-18 06:08:41 +0000
commit7d763c491c052bb2d95521e127cce1c9c750129c (patch)
tree4de412910ce417a3232bc3f3418ab09eb1bcf042
parente6b9df8f42cba4c337ffef0bcfb8dbdde1933c2b (diff)
From Keith Bostic, with some minor changes:
The problem reported on BUGTRACK was that ftpd could be convinced to drop core after it had discarded its special permissions, but while it still had a copy of the encrypted passwords in its buffers. Change coredump() to: + Don't drop core for any process that was ever setuid/setgid if it's not running as root. + Change errno returns from EFAULT to appropriate values -- this will be useful for when coredump() becomes a system call and gcore goes away. + Create core dump files mode 600, and don't dump to files that are owned by anyone else or readable or writable by anyone other than the owner.
-rw-r--r--sys/kern/kern_sig.c53
1 files changed, 34 insertions, 19 deletions
diff --git a/sys/kern/kern_sig.c b/sys/kern/kern_sig.c
index b59eb3b075a..349ef5f883a 100644
--- a/sys/kern/kern_sig.c
+++ b/sys/kern/kern_sig.c
@@ -1,4 +1,4 @@
-/* $OpenBSD: kern_sig.c,v 1.6 1996/09/03 11:01:43 deraadt Exp $ */
+/* $OpenBSD: kern_sig.c,v 1.7 1996/10/18 06:08:40 tholo Exp $ */
/* $NetBSD: kern_sig.c,v 1.54 1996/04/22 01:38:32 christos Exp $ */
/*
@@ -1046,8 +1046,7 @@ coredump(p)
register struct proc *p;
{
register struct vnode *vp;
- register struct pcred *pcred = p->p_cred;
- register struct ucred *cred = pcred->pc_ucred;
+ register struct ucred *cred = p->p_cred->pc_ucred;
register struct vmspace *vm = p->p_vmspace;
struct nameidata nd;
struct vattr vattr;
@@ -1055,26 +1054,41 @@ coredump(p)
char name[MAXCOMLEN+6]; /* progname.core */
struct core core;
- if (!(pcred->p_svuid == pcred->p_ruid && pcred->p_ruid == 0) &&
- (pcred->p_svuid != pcred->p_ruid ||
- cred->cr_uid != pcred->p_ruid ||
- pcred->p_svgid != pcred->p_rgid ||
- cred->cr_gid != pcred->p_rgid))
- return (EFAULT);
+ /*
+ * Don't dump if not root and the process has used set user or
+ * group privileges.
+ */
+ if ((p->p_flag & P_SUGID) &&
+ (error = suser(p->p_ucred, &p->p_acflag)) != 0)
+ return (error);
+
+ /* Don't dump if will exceed file size limit. */
if (USPACE + ctob(vm->vm_dsize + vm->vm_ssize) >=
p->p_rlimit[RLIMIT_CORE].rlim_cur)
return (EFAULT);
+
sprintf(name, "%s.core", p->p_comm);
- NDINIT(&nd, LOOKUP, FOLLOW, UIO_SYSSPACE, name, p);
- error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR);
- if (error)
+ NDINIT(&nd, LOOKUP, NOFOLLOW, UIO_SYSSPACE, name, p);
+ if ((error = vn_open(&nd, O_CREAT | FWRITE, S_IRUSR | S_IWUSR)) != 0)
return (error);
- vp = nd.ni_vp;
+ /*
+ * Change euid to uid for coredump output
+ */
+ cred = crdup(cred);
+ cred->cr_uid = p->p_cred->p_ruid;
+
+ /*
+ * Don't dump to non-regular files, files with links, or files
+ * owned by someone else.
+ */
+ vp = nd.ni_vp;
+ if ((error = VOP_GETATTR(vp, &vattr, cred, p)) != 0)
+ goto out;
/* 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;
+ if (vp->v_type != VREG || vattr.va_nlink != 1 ||
+ vattr.va_mode & ((VREAD | VWRITE) >> 3 | (VREAD | VWRITE) >> 6)) {
+ error = EACCES;
goto out;
}
VATTR_NULL(&vattr);
@@ -1109,14 +1123,14 @@ coredump(p)
error = vn_rdwr(UIO_WRITE, vp, vm->vm_daddr,
(int)core.c_dsize,
(off_t)core.c_cpusize, UIO_USERSPACE,
- IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
+ IO_NODELOCKED|IO_UNIT, cred, NULL, p);
if (error)
goto out;
error = vn_rdwr(UIO_WRITE, vp,
(caddr_t) trunc_page(USRSTACK - ctob(vm->vm_ssize)),
core.c_ssize,
(off_t)(core.c_cpusize + core.c_dsize), UIO_USERSPACE,
- IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
+ IO_NODELOCKED|IO_UNIT, cred, NULL, p);
} else {
/*
* vm_coredump() spits out all appropriate segments.
@@ -1127,11 +1141,12 @@ coredump(p)
goto out;
error = vn_rdwr(UIO_WRITE, vp, (caddr_t)&core,
(int)core.c_hdrsize, (off_t)0,
- UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, (int *) NULL, p);
+ UIO_SYSSPACE, IO_NODELOCKED|IO_UNIT, cred, NULL, p);
}
out:
VOP_UNLOCK(vp);
error1 = vn_close(vp, FWRITE, cred, p);
+ crfree(cred);
if (error == 0)
error = error1;
return (error);