OSDN Git Service

Merge branch 'next' of git://git.kernel.org/pub/scm/linux/kernel/git/jmorris/linux...
[uclinux-h8/linux.git] / security / smack / smack_lsm.c
index 0cc54a0..87a9741 100644 (file)
@@ -549,7 +549,7 @@ static int smack_sb_alloc_security(struct super_block *sb)
        sbsp->smk_floor = &smack_known_floor;
        sbsp->smk_hat = &smack_known_hat;
        /*
-        * smk_initialized will be zero from kzalloc.
+        * SMK_SB_INITIALIZED will be zero from kzalloc.
         */
        sb->s_security = sbsp;
 
@@ -766,10 +766,10 @@ static int smack_set_mnt_opts(struct super_block *sb,
        int num_opts = opts->num_mnt_opts;
        int transmute = 0;
 
-       if (sp->smk_initialized)
+       if (sp->smk_flags & SMK_SB_INITIALIZED)
                return 0;
 
-       sp->smk_initialized = 1;
+       sp->smk_flags |= SMK_SB_INITIALIZED;
 
        for (i = 0; i < num_opts; i++) {
                switch (opts->mnt_opts_flags[i]) {
@@ -821,6 +821,17 @@ static int smack_set_mnt_opts(struct super_block *sb,
                skp = smk_of_current();
                sp->smk_root = skp;
                sp->smk_default = skp;
+               /*
+                * For a handful of fs types with no user-controlled
+                * backing store it's okay to trust security labels
+                * in the filesystem. The rest are untrusted.
+                */
+               if (sb->s_user_ns != &init_user_ns &&
+                   sb->s_magic != SYSFS_MAGIC && sb->s_magic != TMPFS_MAGIC &&
+                   sb->s_magic != RAMFS_MAGIC) {
+                       transmute = 1;
+                       sp->smk_flags |= SMK_SB_UNTRUSTED;
+               }
        }
 
        /*
@@ -908,6 +919,7 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
        struct inode *inode = file_inode(bprm->file);
        struct task_smack *bsp = bprm->cred->security;
        struct inode_smack *isp;
+       struct superblock_smack *sbsp;
        int rc;
 
        if (bprm->cred_prepared)
@@ -917,6 +929,11 @@ static int smack_bprm_set_creds(struct linux_binprm *bprm)
        if (isp->smk_task == NULL || isp->smk_task == bsp->smk_task)
                return 0;
 
+       sbsp = inode->i_sb->s_security;
+       if ((sbsp->smk_flags & SMK_SB_UNTRUSTED) &&
+           isp->smk_task != sbsp->smk_root)
+               return 0;
+
        if (bprm->unsafe & (LSM_UNSAFE_PTRACE | LSM_UNSAFE_PTRACE_CAP)) {
                struct task_struct *tracer;
                rc = 0;
@@ -1203,6 +1220,7 @@ static int smack_inode_rename(struct inode *old_inode,
  */
 static int smack_inode_permission(struct inode *inode, int mask)
 {
+       struct superblock_smack *sbsp = inode->i_sb->s_security;
        struct smk_audit_info ad;
        int no_block = mask & MAY_NOT_BLOCK;
        int rc;
@@ -1214,6 +1232,11 @@ static int smack_inode_permission(struct inode *inode, int mask)
        if (mask == 0)
                return 0;
 
+       if (sbsp->smk_flags & SMK_SB_UNTRUSTED) {
+               if (smk_of_inode(inode) != sbsp->smk_root)
+                       return -EACCES;
+       }
+
        /* May be droppable after audit */
        if (no_block)
                return -ECHILD;
@@ -1708,6 +1731,7 @@ static int smack_mmap_file(struct file *file,
        struct task_smack *tsp;
        struct smack_known *okp;
        struct inode_smack *isp;
+       struct superblock_smack *sbsp;
        int may;
        int mmay;
        int tmay;
@@ -1719,6 +1743,10 @@ static int smack_mmap_file(struct file *file,
        isp = file_inode(file)->i_security;
        if (isp->smk_mmap == NULL)
                return 0;
+       sbsp = file_inode(file)->i_sb->s_security;
+       if (sbsp->smk_flags & SMK_SB_UNTRUSTED &&
+           isp->smk_mmap != sbsp->smk_root)
+               return -EACCES;
        mkp = isp->smk_mmap;
 
        tsp = current_security();