Mercurial > illumos > fmac
changeset 7867:19259f972546
Mediate create and link
Apply directory and file permission checks on create and link
operations. This extends the existing fmac_vnode_create() hook to apply
dir:add_name and file:create permission checks and adds a new
fmac_vnode_link() hook to apply dir:add_name and file:link permission
checks. Other changes include:
- pass the link name to audit for inclusion in avc messages,
- fix memory leak of security context in fmac_vnode_create(),
- pass the vnode to audit on the fmac_exec() checks so that path= info
is included in avc messages.
The issue of unifying this logic with the corresponding filesystem
access checking is deferred to a future patch.
Sample avc output with this patch applied:
avc: denied { add_name } for
scontext=user_u:user_r:user_t:unclassified
tcontext=system_u:object_r:etc_t:unclassified tclass=dir pid=100779
comm=ln path=/etc name=foo
avc: denied { link } for scontext=user_u:user_r:user_t:unclassified
tcontext=system_u:object_r:shadow_t:unclassified tclass=file pid=100779
comm=ln path=/etc/shadow name=foo
author | Stephen Smalley <sds@tycho.nsa.gov> |
---|---|
date | Wed, 17 Sep 2008 13:46:26 -0400 |
parents | ff1aaba25d57 |
children | 9efedf760333 |
files | usr/src/uts/common/fmac/avc.c usr/src/uts/common/fmac/fmac.c usr/src/uts/common/fs/vnode.c usr/src/uts/common/sys/fmac/avc.h usr/src/uts/common/sys/fmac/fmac.h |
diffstat | 5 files changed, 79 insertions(+), 15 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fmac/avc.c Tue Sep 16 16:12:50 2008 -0400 +++ b/usr/src/uts/common/fmac/avc.c Wed Sep 17 13:46:26 2008 -0400 @@ -567,6 +567,8 @@ vp = a->u.fs.vp; if (vp && vp->v_path) avc_audit_append(" path=%s", vp->v_path); + if (a->u.fs.name) + avc_audit_append(" name=%s", a->u.fs.name); break; } }
--- a/usr/src/uts/common/fmac/fmac.c Tue Sep 16 16:12:50 2008 -0400 +++ b/usr/src/uts/common/fmac/fmac.c Wed Sep 17 13:46:26 2008 -0400 @@ -262,8 +262,7 @@ uint32_t scontext_len; xoptattr_t *xoap; int error; - - _NOTE(ARGUNUSED(name)); /* future use in audit message */ + avc_audit_data_t ad; if (!fmac_enabled) return (0); @@ -284,6 +283,24 @@ cr_secid = crgetsecid(cr); + error = security_transition_sid(cr_secid, dvp->v_secid, sclass, + &secid); + if (error) + return (error); + + AVC_AUDIT_DATA_INIT(&ad, FS); + ad.u.fs.vp = dvp; + ad.u.fs.name = name; + + error = avc_has_perm_audit(cr_secid, dvp->v_secid, SECCLASS_DIR, + DIR__ADD_NAME, &ad); + if (error) + return (error); + + error = avc_has_perm_audit(cr_secid, secid, sclass, FILE__CREATE, &ad); + if (error) + return (error); + /* * Wrap the vattr with an xvattr so we can pass the * secctx to the fs code. @@ -293,32 +310,30 @@ xvap->xva_vattr.va_mask |= AT_XVATTR; /* reset after memcpy */ XVA_SET_REQ(xvap, XAT_SECCTX); - error = security_transition_sid(cr_secid, dvp->v_secid, sclass, - &secid); - if (error) - return (error); - error = security_sid_to_context(secid, &scontext, &scontext_len); if (error) return (error); if (scontext_len > sizeof (xoap->xoa_secctx)) - return (EINVAL); + goto inval; xoap = xva_getxoptattr(xvap); if (!xoap) - return (EINVAL); + goto inval; (void) strncpy(xoap->xoa_secctx, scontext, sizeof (xoap->xoa_secctx)); - *secidp = secid; - /* * Switch the vap pointer to the newly populated xvattr. * fop_create/fop_mkdir will then pass the xvattr along to * the underlying fs code. The original vattr is not mutated. */ *vapp = &xvap->xva_vattr; + *secidp = secid; + security_context_free(scontext); return (0); +inval: + security_context_free(scontext); + return (EINVAL); } void @@ -332,11 +347,47 @@ } int +fmac_vnode_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr, + caller_context_t *ct) +{ + security_id_t cr_secid; + security_class_t sclass; + int error; + vnode_t *realvp; + avc_audit_data_t ad; + + if (!fmac_enabled) + return (0); + + sclass = fmac_vtype_to_sclass(svp->v_type); + if (!sclass) + return (0); + + if (VOP_REALVP(svp, &realvp, ct) == 0) + svp = realvp; + + cr_secid = crgetsecid(cr); + + AVC_AUDIT_DATA_INIT(&ad, FS); + ad.u.fs.vp = tdvp; + ad.u.fs.name = name; + error = avc_has_perm_audit(cr_secid, tdvp->v_secid, SECCLASS_DIR, + DIR__ADD_NAME, &ad); + if (error) + return (error); + + ad.u.fs.vp = svp; + return (avc_has_perm_audit(cr_secid, svp->v_secid, sclass, + FILE__LINK, &ad)); +} + +int fmac_exec(cred_t *cr, vnode_t *vp, boolean_t *setsecid, boolean_t *execsetid, security_id_t *prev_secidp, security_id_t *secidp) { security_id_t prev_secid, secid; int error; + avc_audit_data_t ad; if (!fmac_enabled) return (0); @@ -351,8 +402,10 @@ } if (prev_secid == secid) { - error = avc_has_perm(prev_secid, vp->v_secid, SECCLASS_FILE, - FILE__EXECUTE_NO_TRANS); + AVC_AUDIT_DATA_INIT(&ad, FS); + ad.u.fs.vp = vp; + error = avc_has_perm_audit(prev_secid, vp->v_secid, + SECCLASS_FILE, FILE__EXECUTE_NO_TRANS, &ad); if (error) return (error); *execsetid = B_FALSE; @@ -365,8 +418,10 @@ if (error) return (error); - error = avc_has_perm(secid, vp->v_secid, SECCLASS_FILE, - FILE__ENTRYPOINT); + AVC_AUDIT_DATA_INIT(&ad, FS); + ad.u.fs.vp = vp; + error = avc_has_perm_audit(secid, vp->v_secid, SECCLASS_FILE, + FILE__ENTRYPOINT, &ad); if (error) return (error);
--- a/usr/src/uts/common/fs/vnode.c Tue Sep 16 16:12:50 2008 -0400 +++ b/usr/src/uts/common/fs/vnode.c Wed Sep 17 13:46:26 2008 -0400 @@ -3445,6 +3445,10 @@ VOPXID_MAP_CR(tdvp, cr); + err = fmac_vnode_link(tdvp, svp, tnm, cr, ct); + if (err) + return (err); + err = (*(tdvp)->v_op->vop_link)(tdvp, svp, tnm, cr, ct, flags); VOPSTATS_UPDATE(tdvp, link); return (err);
--- a/usr/src/uts/common/sys/fmac/avc.h Tue Sep 16 16:12:50 2008 -0400 +++ b/usr/src/uts/common/sys/fmac/avc.h Wed Sep 17 13:46:26 2008 -0400 @@ -83,6 +83,7 @@ union { struct { struct vnode *vp; + char *name; } fs; } u;
--- a/usr/src/uts/common/sys/fmac/fmac.h Tue Sep 16 16:12:50 2008 -0400 +++ b/usr/src/uts/common/sys/fmac/fmac.h Wed Sep 17 13:46:26 2008 -0400 @@ -91,6 +91,8 @@ int fmac_vnode_create(vnode_t *, char *, xvattr_t *, vattr_t **, cred_t *, security_id_t *); void fmac_vnode_post_create(vnode_t *, security_id_t); +int fmac_vnode_link(vnode_t *tdvp, vnode_t *svp, char *name, cred_t *cr, + caller_context_t *ct); int fmac_exec(cred_t *cr, vnode_t *vp, boolean_t *setsecid, boolean_t *execsetid, security_id_t *prev_secidp, security_id_t *secidp); int fmac_vnode_access(vnode_t *, int, int, cred_t *, boolean_t);