Mercurial > illumos > fmac
changeset 7881:fbb450806b75
Labeled tmpfs support
Take 3 of the labeled tmpfs support. With the change to sysattr_list(),
it is no longer a problem to return EINVAL on any of the default system
attributes in tmp_setattr. We will still need to address the removal of
VFSFT_XVATTR from tmpfs when we rebase to snv_100+ by introducing a
VFSFT_XVATTR_SECCTX or implementing the default system attributes in
tmpfs.
The root directory of a tmpfs mount is initially labeled from the mount
point directory, as with the existing uid/gid/mode assignment. Thus,
for example, one can umount /tmp from single-user mode and setfilecon
the mount point directory to system_u:object_r:tmp_t in order to get the
tmpfs mount to pick up that context on subsequent mounts. John also
found that we can label the other tmpfs mount points by moving setfiles
to /sbin and invoking it from /lib/svc/method/fs-minimal
on /tmp, /var/run and any other tmpfs mount points.
Files and directories created in the tmpfs mount are then labeled via
the fmac_vnode_create and post_create hooks as in ZFS, except that we do
not need to set up an xvattr on the file creation code path since there
is no storage of the secctx and we only need to set up the incore secid
on the vnode.
Upon tmp_getattr, the fmac_vnode_get_secctx() hook is invoked to get the
secctx from the secid in order to pass back to userspace. Upon
tmp_setattr, the secpolicy hook will ultimately call
fmac_vnode_set_secctx() and update the vnode secid, so we only need to
set the return flag for XAT_SECCTX.
A call to fmac_vnode_access() is inserted into tmp_taccess() to apply a
FMAC permission check whenever the existing tmpfs permission checks
would grant access. This uses conventional modes and thus does not pass
V_ACE_MASK. A call to fmac_vnode_remove() is inserted into
tmp_sticky_remove_access() as an initial cut at mediating removal of
files in tmpfs, although this may need to be taken to the callers when
rename checking is introduced.
Webrev at: http://cr.opensolaris.org/~sds/tmpfs3/
author | Stephen Smalley <sds@tycho.nsa.gov> |
---|---|
date | Thu, 09 Oct 2008 15:17:07 -0400 |
parents | 83bea1900f31 |
children | 5619e6e27d7c |
files | usr/src/uts/common/fmac/fmac.c usr/src/uts/common/fs/tmpfs/tmp_subr.c usr/src/uts/common/fs/tmpfs/tmp_vfsops.c usr/src/uts/common/fs/tmpfs/tmp_vnops.c usr/src/uts/common/sys/fmac/fmac.h |
diffstat | 5 files changed, 103 insertions(+), 7 deletions(-) [+] |
line wrap: on
line diff
--- a/usr/src/uts/common/fmac/fmac.c Thu Oct 09 15:16:55 2008 -0400 +++ b/usr/src/uts/common/fmac/fmac.c Thu Oct 09 15:17:07 2008 -0400 @@ -254,6 +254,40 @@ } int +fmac_vnode_get_secctx(vnode_t *vp, vattr_t *vap) +{ + xvattr_t *xvap = (xvattr_t *)vap; + xoptattr_t *xoap; + security_context_t scontext; + uint32_t scontext_len; + int error; + + if (!fmac_enabled) + return (0); + + xoap = xva_getxoptattr(xvap); + if (!xoap) + return (0); + + if (!XVA_ISSET_REQ(xvap, XAT_SECCTX)) + return (0); + + error = security_sid_to_context(vp->v_secid, &scontext, &scontext_len); + if (error) + return (error); + + if (scontext_len > sizeof (xoap->xoa_secctx)) { + security_context_free(scontext); + return (EINVAL); + } + + (void) strncpy(xoap->xoa_secctx, scontext, sizeof (xoap->xoa_secctx)); + XVA_SET_RTN(xvap, XAT_SECCTX); + security_context_free(scontext); + return (0); +} + +int fmac_vnode_create(vnode_t *dvp, char *name, xvattr_t *xvap, vattr_t **vapp, cred_t *cr, security_id_t *secidp) { @@ -303,6 +337,15 @@ if (error) return (error); + if (!xvap) { + /* + * Caller only wants the secid, not an xvattr w/ secctx. + * tmpfs is one such example. + */ + *secidp = secid; + return (0); + } + if (!(vap->va_mask & AT_XVATTR)) { /* * If the vattr is not already an xvattr, then wrap the
--- a/usr/src/uts/common/fs/tmpfs/tmp_subr.c Thu Oct 09 15:16:55 2008 -0400 +++ b/usr/src/uts/common/fs/tmpfs/tmp_subr.c Thu Oct 09 15:17:07 2008 -0400 @@ -42,6 +42,7 @@ #include <sys/kmem.h> #include <sys/atomic.h> #include <sys/policy.h> +#include <sys/fmac/fmac.h> #include <sys/fs/tmp.h> #include <sys/fs/tmpnode.h> @@ -52,6 +53,8 @@ { struct tmpnode *tp = vtp; int shift = 0; + int error = 0; + /* * Check access based on owner, group and * public permissions in tmpnode. @@ -65,10 +68,14 @@ /* compute missing mode bits */ mode &= ~(tp->tn_mode << shift); - if (mode == 0) - return (0); + if (mode) + error = secpolicy_vnode_access(cred, TNTOV(tp), tp->tn_uid, + mode); - return (secpolicy_vnode_access(cred, TNTOV(tp), tp->tn_uid, mode)); + if (!error) + error = fmac_vnode_access(TNTOV(tp), mode, 0, cred, B_TRUE); + + return (error); } /* @@ -86,15 +93,19 @@ struct cred *cr) { uid_t uid = crgetuid(cr); + int error = 0; if ((dir->tn_mode & S_ISVTX) && uid != dir->tn_uid && uid != entry->tn_uid && (entry->tn_type != VREG || tmp_taccess(entry, VWRITE, cr) != 0)) - return (secpolicy_vnode_remove(cr)); + error = secpolicy_vnode_remove(cr); - return (0); + if (!error) + error = fmac_vnode_remove(TNTOV(dir), TNTOV(entry), NULL, cr); + + return (error); } /*
--- a/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c Thu Oct 09 15:16:55 2008 -0400 +++ b/usr/src/uts/common/fs/tmpfs/tmp_vfsops.c Thu Oct 09 15:17:07 2008 -0400 @@ -342,6 +342,7 @@ rw_enter(&tp->tn_rwlock, RW_WRITER); TNTOV(tp)->v_flag |= VROOT; + TNTOV(tp)->v_secid = mvp->v_secid; /* * If the getattr succeeded, use its results. Otherwise allow
--- a/usr/src/uts/common/fs/tmpfs/tmp_vnops.c Thu Oct 09 15:16:55 2008 -0400 +++ b/usr/src/uts/common/fs/tmpfs/tmp_vnops.c Thu Oct 09 15:17:07 2008 -0400 @@ -64,6 +64,7 @@ #include <sys/vm.h> #include <sys/vtrace.h> #include <sys/policy.h> +#include <sys/fmac/fmac.h> #include <fs/fs_subr.h> static int tmp_getapage(struct vnode *, u_offset_t, size_t, uint_t *, @@ -702,7 +703,8 @@ */ vap->va_nblocks = (fsblkcnt64_t)btodb(ptob(btopr(vap->va_size))); mutex_exit(&tp->tn_tlock); - return (0); + + return (fmac_vnode_get_secctx(vp, vap)); } /*ARGSUSED4*/ @@ -718,14 +720,34 @@ struct tmpnode *tp = (struct tmpnode *)VTOTN(vp); int error = 0; struct vattr *get; + xvattr_t *xvap = (xvattr_t *)vap; long mask; /* * Cannot set these attributes */ - if ((vap->va_mask & AT_NOSET) || (vap->va_mask & AT_XVATTR)) + if (vap->va_mask & AT_NOSET) return (EINVAL); + /* + * Only support XAT_SECCTX presently. + */ + if (vap->va_mask & AT_XVATTR) { + if (XVA_ISSET_REQ(xvap, XAT_CREATETIME) || + XVA_ISSET_REQ(xvap, XAT_ARCHIVE) || + XVA_ISSET_REQ(xvap, XAT_SYSTEM) || + XVA_ISSET_REQ(xvap, XAT_READONLY) || + XVA_ISSET_REQ(xvap, XAT_HIDDEN) || + XVA_ISSET_REQ(xvap, XAT_NOUNLINK) || + XVA_ISSET_REQ(xvap, XAT_IMMUTABLE) || + XVA_ISSET_REQ(xvap, XAT_APPENDONLY) || + XVA_ISSET_REQ(xvap, XAT_NODUMP) || + XVA_ISSET_REQ(xvap, XAT_OPAQUE) || + XVA_ISSET_REQ(xvap, XAT_AV_MODIFIED) || + XVA_ISSET_REQ(xvap, XAT_AV_SCANSTAMP)) + return (EINVAL); + } + mutex_enter(&tp->tn_tlock); get = &tp->tn_attr; @@ -741,6 +763,11 @@ mask = vap->va_mask; + if ((mask & AT_XVATTR) && XVA_ISSET_REQ(xvap, XAT_SECCTX)) { + /* vnode secid was updated during the secpolicy call. */ + XVA_SET_RTN(xvap, XAT_SECCTX); + } + if (mask & AT_MODE) { get->va_mode &= S_IFMT; get->va_mode |= vap->va_mode & ~S_IFMT; @@ -937,6 +964,7 @@ struct tmpnode *self; int error; struct tmpnode *oldtp; + security_id_t secid; again: parent = (struct tmpnode *)VTOTN(dvp); @@ -1021,6 +1049,10 @@ if (error != ENOENT) return (error); + error = fmac_vnode_create(dvp, nm, NULL, &vap, cred, &secid); + if (error) + return (error); + rw_enter(&parent->tn_rwlock, RW_WRITER); error = tdirenter(tm, parent, nm, DE_CREATE, (struct tmpnode *)NULL, (struct tmpnode *)NULL, @@ -1057,6 +1089,8 @@ return (ENOSYS); *vpp = newvp; } + + fmac_vnode_post_create(*vpp, secid); TRACE_3(TR_FAC_TMPFS, TR_TMPFS_CREATE, "tmpfs create:dvp %p nm %s vpp %p", dvp, nm, vpp); return (0); @@ -1300,6 +1334,11 @@ struct tmpnode *self = NULL; struct tmount *tm = (struct tmount *)VTOTM(dvp); int error; + security_id_t secid; + + error = fmac_vnode_create(dvp, nm, NULL, &va, cred, &secid); + if (error) + return (error); /* no new dirs allowed in xattr dirs */ if (parent->tn_flags & ISXATTR) @@ -1333,6 +1372,7 @@ } rw_exit(&parent->tn_rwlock); *vpp = TNTOV(self); + fmac_vnode_post_create(*vpp, secid); return (0); }
--- a/usr/src/uts/common/sys/fmac/fmac.h Thu Oct 09 15:16:55 2008 -0400 +++ b/usr/src/uts/common/sys/fmac/fmac.h Thu Oct 09 15:17:07 2008 -0400 @@ -88,6 +88,7 @@ int fmac_vnode_lookup(vnode_t *, cred_t *, caller_context_t *); int fmac_vfs_root(vfs_t *, vnode_t *); int fmac_vnode_set_secctx(char *, cred_t *, vtype_t, vnode_t *); +int fmac_vnode_get_secctx(vnode_t *vp, vattr_t *vap); 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);