changeset 7865:831da5fa2b03

Set linker security flag on security context transitions When the calling domain is less trusted than the new domain, we want to set the linker security flag so that ld.so will not trust the caller. This is subject to policy via a process:execsetid permission check; if allowed, then the linker security flag is not set. We set the EXECSETID_UGIDS flag because that is what is checked by elfexec(). There appear to be no side effects from setting this flag. If desired, we could introduce our own flag value here, as with setting of PRIV_SETUGID flag by the base context transition support. If someone could explain the rationale for why PRIV_SETID is not the same as EXECSETID_SETID and why PRIV_SETUGID is not the same as EXECSETID_UGIDS in meaning, I would be appreciative. I find it vaguely maddening that setting PRIV_SETUGID in privflags causes EXECSETID_SETID to be set in setidfl and an actual identity change resulting from PRIV_SETID results in setting of EXECSETID_UGIDS, reversing the sense of the flag names. Perhaps this is just historical and deserves a code cleanup? Example of running "LD_PRELOAD=evil.o passwd" as root from a user_t shell: dmesg output: avc: denied { execsetid } for scontext=system_u:system_r:user_t:unclassified tcontext=system_u:system_r:passwd_t:unclassified tclass=process pid=100768 comm=sh Command output: ld.so.1: passwd: warning: ./evil.o: open failed: illegal insecure pathname Of course, if we allow this permission in policy, kernel mediation of the PROT_EXEC mapping will still prevent execution of unauthorized shared objects: dmesg output: avc: denied { execute } for scontext=system_u:system_r:passwd_t:unclassified tcontext=system_u:object_r:file_t:unclassified tclass=file pid=100768 comm=passwd path=/export/home/sds/evil.o Command output: ld.so.1: passwd: fatal: ./evil.o: Permission denied Killed
author Stephen Smalley <sds@tycho.nsa.gov>
date Tue, 16 Sep 2008 14:54:50 -0400
parents f40998e41fac
children ff1aaba25d57
files usr/src/uts/common/fmac/fmac.c usr/src/uts/common/os/exec.c usr/src/uts/common/sys/fmac/fmac.h
diffstat 3 files changed, 19 insertions(+), 4 deletions(-) [+]
line wrap: on
line diff
--- a/usr/src/uts/common/fmac/fmac.c	Mon Sep 15 08:30:57 2008 -0400
+++ b/usr/src/uts/common/fmac/fmac.c	Tue Sep 16 14:54:50 2008 -0400
@@ -333,7 +333,7 @@
 
 int
 fmac_exec(cred_t *cr, vnode_t *vp, boolean_t *setsecid,
-    security_id_t *prev_secidp, security_id_t *secidp)
+    boolean_t *execsetid, security_id_t *prev_secidp, security_id_t *secidp)
 {
 	security_id_t prev_secid, secid;
 	int error;
@@ -355,6 +355,7 @@
 		    FILE__EXECUTE_NO_TRANS);
 		if (error)
 			return (error);
+		*execsetid = B_FALSE;
 		*setsecid = B_FALSE;
 		return (0);
 	}
@@ -368,6 +369,14 @@
 	    FILE__ENTRYPOINT);
 	if (error)
 		return (error);
+
+	error = avc_has_perm(prev_secid, secid, SECCLASS_PROCESS,
+	    PROCESS__EXECSETID);
+	if (error)
+		*execsetid = B_TRUE;
+	else
+		*execsetid = B_FALSE;
+
 	*setsecid = B_TRUE;
 	*prev_secidp = prev_secid;
 	*secidp = secid;
@@ -420,6 +429,8 @@
 int
 fmac_priv_proc_cred_perm(const cred_t *scr, cred_t *tcr, int mode)
 {
+	_NOTE(ARGUNUSED(mode));	/* todo:  distinguish read vs. write? */
+
 	if (!fmac_enabled)
 		return (0);
 	return (avc_has_perm(crgetsecid((cred_t *)scr), crgetsecid(tcr),
--- a/usr/src/uts/common/os/exec.c	Mon Sep 15 08:30:57 2008 -0400
+++ b/usr/src/uts/common/os/exec.c	Tue Sep 16 14:54:50 2008 -0400
@@ -524,7 +524,7 @@
 	ssize_t resid;
 	uid_t uid, gid;
 	security_id_t prev_secid, secid;
-	boolean_t setsecid = B_FALSE;
+	boolean_t setsecid = B_FALSE, fmac_execsetid = B_FALSE;
 	struct vattr vattr;
 	char magbuf[MAGIC_BYTES];
 	int setid;
@@ -568,7 +568,8 @@
 	if (level == 0) {
 		privflags = execsetid(vp, &vattr, &uid, &gid);
 
-		error = fmac_exec(CRED(), vp, &setsecid, &prev_secid, &secid);
+		error = fmac_exec(CRED(), vp, &setsecid, &fmac_execsetid,
+		    &prev_secid, &secid);
 		if (error)
 			goto bad;
 
@@ -673,6 +674,9 @@
 	if (setid & PRIV_INCREASE)
 		setidfl |= EXECSETID_PRIVS;
 
+	if (fmac_execsetid)
+		setidfl |= EXECSETID_UGIDS;
+
 	error = (*eswp->exec_func)(vp, uap, args, idatap, level, execsz,
 	    setidfl, exec_file, cred, brand_action);
 	rw_exit(eswp->exec_lock);
--- a/usr/src/uts/common/sys/fmac/fmac.h	Mon Sep 15 08:30:57 2008 -0400
+++ b/usr/src/uts/common/sys/fmac/fmac.h	Tue Sep 16 14:54:50 2008 -0400
@@ -92,7 +92,7 @@
     security_id_t *);
 void fmac_vnode_post_create(vnode_t *, security_id_t);
 int fmac_exec(cred_t *cr, vnode_t *vp, boolean_t *setsecid,
-    security_id_t *prev_secidp, security_id_t *secidp);
+    boolean_t *execsetid, security_id_t *prev_secidp, security_id_t *secidp);
 int fmac_vnode_access(vnode_t *, int, int, cred_t *, boolean_t);
 int fmac_priv_proc_cred_perm(const cred_t *scr, cred_t *tcr, int mode);
 #endif /* _KERNEL */