aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorEric Paris2006-07-10 04:43:55 -0700
committerLinus Torvalds2006-07-10 13:24:13 -0700
commit0808925ea5684a0ce25483b30e94d4f398804978 (patch)
tree62456726442d656d21bc4fa6b1339f0236f0a6e8
parentc312feb2931ded0582378712727b7ea017a951bd (diff)
[PATCH] SELinux: add rootcontext= option to label root inode when mounting
Introduce a new rootcontext= option to FS mounting. This option will allow you to explicitly label the root inode of an FS being mounted before that FS or inode because visible to userspace. This was found to be useful for things like stateless linux, see https://bugzilla.redhat.com/bugzilla/show_bug.cgi?id=190001 Signed-off-by: Eric Paris <eparis@parisplace.org> Acked-by: Stephen Smalley <sds@tycho.nsa.gov> Signed-off-by: James Morris <jmorris@namei.org> Signed-off-by: Andrew Morton <akpm@osdl.org> Signed-off-by: Linus Torvalds <torvalds@osdl.org>
-rw-r--r--security/selinux/hooks.c66
1 files changed, 57 insertions, 9 deletions
diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c
index 7e101dbea4cb..2e8b4dfcbc74 100644
--- a/security/selinux/hooks.c
+++ b/security/selinux/hooks.c
@@ -320,12 +320,14 @@ enum {
Opt_context = 1,
Opt_fscontext = 2,
Opt_defcontext = 4,
+ Opt_rootcontext = 8,
};
static match_table_t tokens = {
{Opt_context, "context=%s"},
{Opt_fscontext, "fscontext=%s"},
{Opt_defcontext, "defcontext=%s"},
+ {Opt_rootcontext, "rootcontext=%s"},
};
#define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n"
@@ -346,10 +348,25 @@ static int may_context_mount_sb_relabel(u32 sid,
return rc;
}
+static int may_context_mount_inode_relabel(u32 sid,
+ struct superblock_security_struct *sbsec,
+ struct task_security_struct *tsec)
+{
+ int rc;
+ rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ FILESYSTEM__RELABELFROM, NULL);
+ if (rc)
+ return rc;
+
+ rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
+ FILESYSTEM__ASSOCIATE, NULL);
+ return rc;
+}
+
static int try_context_mount(struct super_block *sb, void *data)
{
char *context = NULL, *defcontext = NULL;
- char *fscontext = NULL;
+ char *fscontext = NULL, *rootcontext = NULL;
const char *name;
u32 sid;
int alloc = 0, rc = 0, seen = 0;
@@ -423,6 +440,22 @@ static int try_context_mount(struct super_block *sb, void *data)
seen |= Opt_fscontext;
break;
+ case Opt_rootcontext:
+ if (seen & Opt_rootcontext) {
+ rc = -EINVAL;
+ printk(KERN_WARNING SEL_MOUNT_FAIL_MSG);
+ goto out_free;
+ }
+ rootcontext = match_strdup(&args[0]);
+ if (!rootcontext) {
+ rc = -ENOMEM;
+ goto out_free;
+ }
+ if (!alloc)
+ alloc = 1;
+ seen |= Opt_rootcontext;
+ break;
+
case Opt_defcontext:
if (sbsec->behavior != SECURITY_FS_USE_XATTR) {
rc = -EINVAL;
@@ -501,6 +534,25 @@ static int try_context_mount(struct super_block *sb, void *data)
sbsec->behavior = SECURITY_FS_USE_MNTPOINT;
}
+ if (rootcontext) {
+ struct inode *inode = sb->s_root->d_inode;
+ struct inode_security_struct *isec = inode->i_security;
+ rc = security_context_to_sid(rootcontext, strlen(rootcontext), &sid);
+ if (rc) {
+ printk(KERN_WARNING "SELinux: security_context_to_sid"
+ "(%s) failed for (dev %s, type %s) errno=%d\n",
+ rootcontext, sb->s_id, name, rc);
+ goto out_free;
+ }
+
+ rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
+ if (rc)
+ goto out_free;
+
+ isec->sid = sid;
+ isec->initialized = 1;
+ }
+
if (defcontext) {
rc = security_context_to_sid(defcontext, strlen(defcontext), &sid);
if (rc) {
@@ -513,13 +565,7 @@ static int try_context_mount(struct super_block *sb, void *data)
if (sid == sbsec->def_sid)
goto out_free;
- rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM,
- FILESYSTEM__RELABELFROM, NULL);
- if (rc)
- goto out_free;
-
- rc = avc_has_perm(sid, sbsec->sid, SECCLASS_FILESYSTEM,
- FILESYSTEM__ASSOCIATE, NULL);
+ rc = may_context_mount_inode_relabel(sid, sbsec, tsec);
if (rc)
goto out_free;
@@ -531,6 +577,7 @@ out_free:
kfree(context);
kfree(defcontext);
kfree(fscontext);
+ kfree(rootcontext);
}
out:
return rc;
@@ -1882,7 +1929,8 @@ static inline int selinux_option(char *option, int len)
{
return (match_prefix("context=", sizeof("context=")-1, option, len) ||
match_prefix("fscontext=", sizeof("fscontext=")-1, option, len) ||
- match_prefix("defcontext=", sizeof("defcontext=")-1, option, len));
+ match_prefix("defcontext=", sizeof("defcontext=")-1, option, len) ||
+ match_prefix("rootcontext=", sizeof("rootcontext=")-1, option, len));
}
static inline void take_option(char **to, char *from, int *first, int len)