Mercurial > illumos > fmac
changeset 7870:85ca241b1198
Mediate rename
Apply directory and file permission checks on rename operations. To
allow a distinction between rename and unlink checking on the source
vnode, the fmac_vnode_remove() hook in zfs_zaccess_delete() introduced
by the prior patch is moved to zfs_remove() and zfs_rmdir(), and a
separate fmac_vnode_rename() hook is added to zfs_rename(). As with the
remove/rmdir hooks, we have to hook zfs presently for rename since the
source and target vnodes are only available there.
Sample AVC output on a mv /etc/shadow- /etc/shadow:
avc: denied { remove_name } for
scontext=user_u:user_r:user_t:unclassified
tcontext=system_u:object_r:etc_t:unclassified tclass=dir pid=100813
comm=mv path=/etc
avc: denied { rename } for scontext=user_u:user_r:user_t:unclassified
tcontext=system_u:object_r:shadow_t:unclassified tclass=file pid=100813
comm=mv path=/etc/shadow-
avc: denied { add_name } for
scontext=user_u:user_r:user_t:unclassified
tcontext=system_u:object_r:etc_t:unclassified tclass=dir pid=100813
comm=mv path=/etc
avc: denied { unlink } for scontext=user_u:user_r:user_t:unclassified
tcontext=system_u:object_r:shadow_t:unclassified tclass=file pid=100813
comm=mv path=/etc/shadow
author | Stephen Smalley <sds@tycho.nsa.gov> |
---|---|
date | Thu, 18 Sep 2008 09:53:35 -0400 |
parents | 9efedf760333 |
children | bc3a0d3a4dc9 |
files | usr/src/uts/common/fmac/fmac.c usr/src/uts/common/fs/zfs/zfs_acl.c usr/src/uts/common/fs/zfs/zfs_vnops.c usr/src/uts/common/sys/fmac/fmac.h |
diffstat | 4 files changed, 78 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fmac/fmac.c Wed Sep 17 16:58:20 2008 -0400 +++ b/usr/src/uts/common/fmac/fmac.c Thu Sep 18 09:53:35 2008 -0400 @@ -382,7 +382,7 @@ } int -fmac_vnode_remove(vnode_t *dvp, vnode_t *vp, cred_t *cr) +fmac_vnode_remove(vnode_t *dvp, vnode_t *vp, char *name, cred_t *cr) { security_id_t cr_secid; security_class_t sclass; @@ -401,6 +401,7 @@ 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__REMOVE_NAME, &ad); if (error) @@ -415,6 +416,65 @@ } int +fmac_vnode_rename(vnode_t *sdvp, vnode_t *svp, vnode_t *tdvp, vnode_t *tvp, + cred_t *cr) +{ + security_id_t cr_secid; + security_class_t sclass, tclass; + access_vector_t av; + int error; + avc_audit_data_t ad; + + if (!fmac_enabled) + return (0); + + sclass = fmac_vtype_to_sclass(svp->v_type); + if (!sclass) + return (0); + + cr_secid = crgetsecid(cr); + + AVC_AUDIT_DATA_INIT(&ad, FS); + + ad.u.fs.vp = sdvp; + error = avc_has_perm_audit(cr_secid, sdvp->v_secid, SECCLASS_DIR, + DIR__REMOVE_NAME, &ad); + if (error) + return (error); + + ad.u.fs.vp = svp; + error = avc_has_perm_audit(cr_secid, svp->v_secid, sclass, + FILE__RENAME, &ad); + if (error) + return (error); + + ad.u.fs.vp = tdvp; + error = avc_has_perm_audit(cr_secid, tdvp->v_secid, SECCLASS_DIR, + DIR__ADD_NAME, &ad); + if (error) + return (error); + + if (tvp) { + tclass = fmac_vtype_to_sclass(tvp->v_type); + if (!tclass) + return (0); + + if (tclass == SECCLASS_DIR) + av = DIR__RMDIR; + else + av = FILE__UNLINK; + + ad.u.fs.vp = tvp; + error = avc_has_perm_audit(cr_secid, tvp->v_secid, tclass, av, + &ad); + if (error) + return (error); + } + + return (0); +} + +int fmac_exec(cred_t *cr, vnode_t *vp, boolean_t *setsecid, boolean_t *execsetid, security_id_t *prev_secidp, security_id_t *secidp) {
--- a/usr/src/uts/common/fs/zfs/zfs_acl.c Wed Sep 17 16:58:20 2008 -0400 +++ b/usr/src/uts/common/fs/zfs/zfs_acl.c Thu Sep 18 09:53:35 2008 -0400 @@ -50,7 +50,6 @@ #include <sys/dmu.h> #include <sys/dnode.h> #include <sys/zap.h> -#include <sys/fmac/fmac.h> #include "fs/fs_subr.h" #include <acl/acl_common.h> @@ -2515,10 +2514,6 @@ boolean_t dzpcheck_privs = B_TRUE; boolean_t zpcheck_privs = B_TRUE; - zp_error = fmac_vnode_remove(ZTOV(dzp), ZTOV(zp), cr); - if (zp_error) - return (zp_error); - /* * We want specific DELETE permissions to * take precedence over WRITE/EXECUTE. We don't
--- a/usr/src/uts/common/fs/zfs/zfs_vnops.c Wed Sep 17 16:58:20 2008 -0400 +++ b/usr/src/uts/common/fs/zfs/zfs_vnops.c Thu Sep 18 09:53:35 2008 -0400 @@ -74,6 +74,7 @@ #include <sys/kidmap.h> #include <sys/cred_impl.h> #include <sys/attr.h> +#include <sys/fmac/fmac.h> /* * Programming rules. @@ -1446,6 +1447,10 @@ goto out; } + error = fmac_vnode_remove(dvp, vp, name, cr); + if (error) + goto out; + vnevent_remove(vp, dvp, name, ct); if (realnmp) @@ -1802,6 +1807,10 @@ goto out; } + error = fmac_vnode_remove(dvp, vp, name, cr); + if (error) + goto out; + vnevent_rmdir(vp, dvp, name, ct); /* @@ -3084,6 +3093,11 @@ if (error = zfs_zaccess_rename(sdzp, szp, tdzp, tzp, cr)) goto out; + error = fmac_vnode_rename(sdvp, ZTOV(szp), tdvp, + tzp ? ZTOV(tzp) : NULL, cr); + if (error) + goto out; + if (ZTOV(szp)->v_type == VDIR) { /* * Check to make sure rename is valid.
--- a/usr/src/uts/common/sys/fmac/fmac.h Wed Sep 17 16:58:20 2008 -0400 +++ b/usr/src/uts/common/sys/fmac/fmac.h Thu Sep 18 09:53:35 2008 -0400 @@ -93,7 +93,9 @@ 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_vnode_remove(vnode_t *dvp, vnode_t *vp, cred_t *cr); +int fmac_vnode_remove(vnode_t *dvp, vnode_t *vp, char *name, cred_t *cr); +int fmac_vnode_rename(vnode_t *sdvp, vnode_t *svp, vnode_t *tdvp, vnode_t *tvp, + cred_t *cr); 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);