From c312feb2931ded0582378712727b7ea017a951bd Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 10 Jul 2006 04:43:53 -0700 Subject: [PATCH] SELinux: decouple fscontext/context mount options Remove the conflict between fscontext and context mount options. If context= is specified without fscontext it will operate just as before, if both are specified we will use mount point labeling and all inodes will get the label specified by context=. The superblock will be labeled with the label of fscontext=, thus affecting operations which check the superblock security context, such as associate permissions. Signed-off-by: Eric Paris Acked-by: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 69 +++++++++++++++++++++++++++++++++++++----------- 1 file changed, 54 insertions(+), 15 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 24caaeec8894..7e101dbea4cb 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -246,6 +246,7 @@ static int superblock_alloc_security(struct super_block *sb) sbsec->sb = sb; sbsec->sid = SECINITSID_UNLABELED; sbsec->def_sid = SECINITSID_FILE; + sbsec->mntpoint_sid = SECINITSID_UNLABELED; sb->s_security = sbsec; return 0; @@ -329,9 +330,26 @@ static match_table_t tokens = { #define SEL_MOUNT_FAIL_MSG "SELinux: duplicate or incompatible mount options\n" +static int may_context_mount_sb_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(tsec->sid, sid, SECCLASS_FILESYSTEM, + FILESYSTEM__RELABELTO, NULL); + return rc; +} + static int try_context_mount(struct super_block *sb, void *data) { char *context = NULL, *defcontext = NULL; + char *fscontext = NULL; const char *name; u32 sid; int alloc = 0, rc = 0, seen = 0; @@ -374,7 +392,7 @@ static int try_context_mount(struct super_block *sb, void *data) switch (token) { case Opt_context: - if (seen) { + if (seen & (Opt_context|Opt_defcontext)) { rc = -EINVAL; printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); goto out_free; @@ -390,13 +408,13 @@ static int try_context_mount(struct super_block *sb, void *data) break; case Opt_fscontext: - if (seen & (Opt_context|Opt_fscontext)) { + if (seen & Opt_fscontext) { rc = -EINVAL; printk(KERN_WARNING SEL_MOUNT_FAIL_MSG); goto out_free; } - context = match_strdup(&args[0]); - if (!context) { + fscontext = match_strdup(&args[0]); + if (!fscontext) { rc = -ENOMEM; goto out_free; } @@ -441,29 +459,46 @@ static int try_context_mount(struct super_block *sb, void *data) if (!seen) goto out; - if (context) { - rc = security_context_to_sid(context, strlen(context), &sid); + /* sets the context of the superblock for the fs being mounted. */ + if (fscontext) { + rc = security_context_to_sid(fscontext, strlen(fscontext), &sid); if (rc) { printk(KERN_WARNING "SELinux: security_context_to_sid" "(%s) failed for (dev %s, type %s) errno=%d\n", - context, sb->s_id, name, rc); + fscontext, sb->s_id, name, rc); goto out_free; } - rc = avc_has_perm(tsec->sid, sbsec->sid, SECCLASS_FILESYSTEM, - FILESYSTEM__RELABELFROM, NULL); + rc = may_context_mount_sb_relabel(sid, sbsec, tsec); if (rc) goto out_free; - rc = avc_has_perm(tsec->sid, sid, SECCLASS_FILESYSTEM, - FILESYSTEM__RELABELTO, NULL); + sbsec->sid = sid; + } + + /* + * Switch to using mount point labeling behavior. + * sets the label used on all file below the mountpoint, and will set + * the superblock context if not already set. + */ + if (context) { + rc = security_context_to_sid(context, strlen(context), &sid); + if (rc) { + printk(KERN_WARNING "SELinux: security_context_to_sid" + "(%s) failed for (dev %s, type %s) errno=%d\n", + context, sb->s_id, name, rc); + goto out_free; + } + + rc = may_context_mount_sb_relabel(sid, sbsec, tsec); if (rc) goto out_free; - sbsec->sid = sid; + if (!fscontext) + sbsec->sid = sid; + sbsec->mntpoint_sid = sid; - if (seen & Opt_context) - sbsec->behavior = SECURITY_FS_USE_MNTPOINT; + sbsec->behavior = SECURITY_FS_USE_MNTPOINT; } if (defcontext) { @@ -495,6 +530,7 @@ out_free: if (alloc) { kfree(context); kfree(defcontext); + kfree(fscontext); } out: return rc; @@ -876,8 +912,11 @@ static int inode_doinit_with_dentry(struct inode *inode, struct dentry *opt_dent goto out; isec->sid = sid; break; + case SECURITY_FS_USE_MNTPOINT: + isec->sid = sbsec->mntpoint_sid; + break; default: - /* Default to the fs SID. */ + /* Default to the fs superblock SID. */ isec->sid = sbsec->sid; if (sbsec->proc) { -- cgit v1.2.2 From 0808925ea5684a0ce25483b30e94d4f398804978 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Mon, 10 Jul 2006 04:43:55 -0700 Subject: [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 Acked-by: Stephen Smalley Signed-off-by: James Morris Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 66 +++++++++++++++++++++++++++++++++++++++++------- 1 file changed, 57 insertions(+), 9 deletions(-) (limited to 'security/selinux/hooks.c') 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) -- cgit v1.2.2 From b04ea3cebf79d6808632808072f276dbc98aaf01 Mon Sep 17 00:00:00 2001 From: Eric Paris Date: Fri, 14 Jul 2006 00:24:33 -0700 Subject: [PATCH] Fix security check for joint context= and fscontext= mount options After some discussion on the actual meaning of the filesystem class security check in try context mount it was determined that the checks for the context= mount options were not correct if fscontext mount option had already been used. When labeling the superblock we should be checking relabel_from and relabel_to. But if the superblock has already been labeled (with fscontext) then context= is actually labeling the inodes, and so we should be checking relabel_from and associate. This patch fixes which checks are called depending on the mount options. Signed-off-by: Eric Paris Acked-by: Stephen Smalley Acked-by: James Morris Cc: Chris Wright Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- security/selinux/hooks.c | 14 +++++++++----- 1 file changed, 9 insertions(+), 5 deletions(-) (limited to 'security/selinux/hooks.c') diff --git a/security/selinux/hooks.c b/security/selinux/hooks.c index 2e8b4dfcbc74..a91c961ba38b 100644 --- a/security/selinux/hooks.c +++ b/security/selinux/hooks.c @@ -523,12 +523,16 @@ static int try_context_mount(struct super_block *sb, void *data) goto out_free; } - rc = may_context_mount_sb_relabel(sid, sbsec, tsec); - if (rc) - goto out_free; - - if (!fscontext) + if (!fscontext) { + rc = may_context_mount_sb_relabel(sid, sbsec, tsec); + if (rc) + goto out_free; sbsec->sid = sid; + } else { + rc = may_context_mount_inode_relabel(sid, sbsec, tsec); + if (rc) + goto out_free; + } sbsec->mntpoint_sid = sid; sbsec->behavior = SECURITY_FS_USE_MNTPOINT; -- cgit v1.2.2