Subject: Re: sysctl knob to let sugid processes dump core (pr 15994)
To: None <tls@rek.tjls.com>
From: Elad Efrat <elad@NetBSD.org>
List: tech-security
Date: 01/27/2006 05:30:18
This is a multi-part message in MIME format.
--------------020006070602020805060702
Content-Type: text/plain; charset=ISO-8859-1
Content-Transfer-Encoding: 7bit

Thor Lancelot Simon wrote:

> Default disable, can only be modified at securelevel < 1.  That gives us
> the same basic situation we have now, with the convenience of not having
> to modify the kernel sources to get cores from setuid programs.

updated patch attached.

-e.

-- 
Elad Efrat

--------------020006070602020805060702
Content-Type: text/plain;
 name="setid_core.diff"
Content-Transfer-Encoding: 7bit
Content-Disposition: inline;
 filename="setid_core.diff"

Index: kern/init_sysctl.c
===================================================================
RCS file: /cvsroot/src/sys/kern/init_sysctl.c,v
retrieving revision 1.60
diff -u -p -r1.60 init_sysctl.c
--- kern/init_sysctl.c	27 Jan 2006 03:14:56 -0000	1.60
+++ kern/init_sysctl.c	27 Jan 2006 03:27:56 -0000
@@ -74,6 +74,7 @@ __KERNEL_RCSID(0, "$NetBSD: init_sysctl.
 #define	VERIEXEC_NEED_NODE
 #include <sys/verified_exec.h>
 #endif /* VERIFIED_EXEC */
+#include <sys/stat.h>
 
 #if defined(SYSVMSG) || defined(SYSVSEM) || defined(SYSVSHM)
 #include <sys/ipc.h>
@@ -92,6 +93,11 @@ __KERNEL_RCSID(0, "$NetBSD: init_sysctl.
 
 /* XXX this should not be here */
 int security_curtain = 0;
+int security_setidcore_dump;
+char security_setidcore_path[MAXPATHLEN] = "/var/crash/%n.core";
+uid_t security_setidcore_owner = 0;
+gid_t security_setidcore_group = 0;
+mode_t security_setidcore_mode = (S_IRUSR|S_IWUSR);
 
 /*
  * try over estimating by 5 procs/lwps
@@ -147,6 +153,7 @@ static int sysctl_kern_file2(SYSCTLFN_PR
 #ifdef VERIFIED_EXEC
 static int sysctl_kern_veriexec(SYSCTLFN_PROTO);
 #endif
+static int sysctl_security_setidcore(SYSCTLFN_PROTO);
 static int sysctl_kern_cpid(SYSCTLFN_PROTO);
 static int sysctl_doeproc(SYSCTLFN_PROTO);
 static int sysctl_kern_proc_args(SYSCTLFN_PROTO);
@@ -1036,6 +1043,44 @@ SYSCTL_SETUP(sysctl_security_setup, "sys
 				    " to users not owning them."),
 		       NULL, 0, &security_curtain, 0,
 		       CTL_CREATE, CTL_EOL);
+
+	sysctl_createv(clog, 0, &rnode, &rnode,
+		       CTLFLAG_PERMANENT,
+		       CTLTYPE_NODE, "setid_core",
+		       SYSCTL_DESCR("Set-id processes' coredump settings."),
+		       NULL, 0, NULL, 0,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "dump",
+		       SYSCTL_DESCR("Allow set-id processes to dump core."),
+		       sysctl_security_setidcore, 0, &security_setidcore_dump,
+		       sizeof(security_setidcore_dump),
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_STRING, "path",
+		       SYSCTL_DESCR("Path pattern for set-id coredumps."),
+		       NULL, 0, &security_setidcore_path, MAXPATHLEN,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "owner",
+		       SYSCTL_DESCR("Owner id for set-id processes' cores."),
+		       NULL, 0, &security_setidcore_owner, 0,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "group",
+		       SYSCTL_DESCR("Group id for set-id processes' cores."),
+		       NULL, 0, &security_setidcore_group, 0,
+		       CTL_CREATE, CTL_EOL);
+	sysctl_createv(clog, 0, &rnode, NULL,
+		       CTLFLAG_PERMANENT|CTLFLAG_READWRITE,
+		       CTLTYPE_INT, "mode",
+		       SYSCTL_DESCR("Mode for set-id processes' cores."),
+		       NULL, 0, &security_setidcore_mode, 0,
+		       CTL_CREATE, CTL_EOL);
 }
 
 /*
@@ -2522,6 +2567,27 @@ sysctl_kern_veriexec(SYSCTLFN_ARGS)
 }
 #endif /* VERIFIED_EXEC */
 
+static int
+sysctl_security_setidcore(SYSCTLFN_ARGS)
+{
+	int newsize, error;
+	struct sysctlnode node;
+
+	node = *rnode;
+	node.sysctl_data = &newsize;
+	newsize = *(int *)rnode->sysctl_data;
+	error = sysctl_lookup(SYSCTLFN_CALL(&node));
+	if (error || newp == NULL)
+		return error;
+
+	if (securelevel > 0)
+		return (EPERM);
+
+	*(int *)rnode->sysctl_data = newsize;
+
+	return 0;
+}
+
 /*
  * sysctl helper routine for kern.cp_id node.  maps cpus to their
  * cpuids.
Index: kern/kern_sig.c
===================================================================
RCS file: /cvsroot/src/sys/kern/kern_sig.c,v
retrieving revision 1.213
diff -u -p -r1.213 kern_sig.c
--- kern/kern_sig.c	24 Dec 2005 19:12:23 -0000	1.213
+++ kern/kern_sig.c	27 Jan 2006 03:27:59 -0000
@@ -70,6 +70,7 @@ __KERNEL_RCSID(0, "$NetBSD: kern_sig.c,v
 #include <sys/sa.h>
 #include <sys/savar.h>
 #include <sys/exec.h>
+#include <sys/sysctl.h>
 
 #include <sys/mount.h>
 #include <sys/syscallargs.h>
@@ -2101,9 +2102,10 @@ coredump(struct lwp *l, const char *patt
 	cred = p->p_cred->pc_ucred;
 
 	/*
-	 * Make sure the process has not set-id, to prevent data leaks.
+	 * Make sure the process has not set-id, to prevent data leaks,
+	 * unless it was specifically requested to allow set-id coredumps.
 	 */
-	if (p->p_flag & P_SUGID)
+	if ((p->p_flag & P_SUGID) && !security_setidcore_dump)
 		return (EPERM);
 
 	/*
@@ -2126,6 +2128,9 @@ restart:
 	    (vp->v_mount->mnt_flag & MNT_NOCOREDUMP) != 0)
 		return (EPERM);
 
+	if (p->p_flag & P_SUGID && security_setidcore_dump)
+		pattern = security_setidcore_path;
+
 	if (pattern == NULL)
 		pattern = p->p_limit->pl_corename;
 	if ((error = build_corename(p, name, pattern, sizeof(name))) != 0)
@@ -2155,6 +2160,13 @@ restart:
 	}
 	VATTR_NULL(&vattr);
 	vattr.va_size = 0;
+
+	if (p->p_flag & P_SUGID && security_setidcore_dump) {
+		vattr.va_uid = security_setidcore_owner;
+		vattr.va_gid = security_setidcore_group;
+		vattr.va_mode = security_setidcore_mode;
+	}
+
 	VOP_LEASE(vp, l, cred, LEASE_WRITE);
 	VOP_SETATTR(vp, &vattr, cred, l);
 	p->p_acflag |= ACORE;
Index: sys/sysctl.h
===================================================================
RCS file: /cvsroot/src/sys/sys/sysctl.h,v
retrieving revision 1.147
diff -u -p -r1.147 sysctl.h
--- sys/sysctl.h	27 Jan 2006 03:14:56 -0000	1.147
+++ sys/sysctl.h	27 Jan 2006 03:28:01 -0000
@@ -909,6 +909,11 @@ extern struct sysctlnode sysctl_root;
 
 /* XXX this should not be here */
 extern int security_curtain;
+extern int security_setidcore_dump;
+extern char security_setidcore_path[];
+extern uid_t security_setidcore_owner;
+extern gid_t security_setidcore_group;
+extern mode_t security_setidcore_mode;
 
 /*
  * A log of nodes created by a setup function or set of setup

--------------020006070602020805060702--