Mercurial > illumos > fmac
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 */