BACKPORT: Smack: Prevent the * and @ labels from being used in SMACK64EXEC
authorCasey Schaufler <casey@schaufler-ca.com>
Tue, 17 Dec 2013 00:27:26 +0000 (16:27 -0800)
committerRafal Krypa <r.krypa@samsung.com>
Tue, 29 Dec 2015 12:26:47 +0000 (13:26 +0100)
Smack prohibits processes from using the star ("*") and web ("@") labels
because we don't want files with those labels getting created implicitly.
All setting of those labels should be done explicitly. The trouble is that
there is no check for these labels in the processing of SMACK64EXEC. That
is repaired.

Targeted for git://git.gitorious.org/smack-next/kernel.git

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
(cherry-picked from upstream 19760ad03cc639d6f6f8e9beff0f8e6df654b677)

security/smack/smack_lsm.c

index 934f142ce51f7e1e18aae15cd08c0ce3c60dbc6f..d4fd7ccb45a8add01fea186f0adc61abc3536084 100644 (file)
@@ -840,31 +840,43 @@ static int smack_inode_setxattr(struct dentry *dentry, const char *name,
                                const void *value, size_t size, int flags)
 {
        struct smk_audit_info ad;
+       struct smack_known *skp;
+       int check_priv = 0;
+       int check_import = 0;
+       int check_star = 0;
        int rc = 0;
 
+       /*
+        * Check label validity here so import won't fail in post_setxattr
+        */
        if (strcmp(name, XATTR_NAME_SMACK) == 0 ||
            strcmp(name, XATTR_NAME_SMACKIPIN) == 0 ||
-           strcmp(name, XATTR_NAME_SMACKIPOUT) == 0 ||
-           strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
-           strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
-               if (!smack_privileged(CAP_MAC_ADMIN))
-                       rc = -EPERM;
-               /*
-                * check label validity here so import wont fail on
-                * post_setxattr
-                */
-               if (size == 0 || size >= SMK_LONGLABEL ||
-                   smk_import(value, size) == NULL)
-                       rc = -EINVAL;
+           strcmp(name, XATTR_NAME_SMACKIPOUT) == 0) {
+               check_priv = 1;
+               check_import = 1;
+       } else if (strcmp(name, XATTR_NAME_SMACKEXEC) == 0 ||
+                  strcmp(name, XATTR_NAME_SMACKMMAP) == 0) {
+               check_priv = 1;
+               check_import = 1;
+               check_star = 1;
        } else if (strcmp(name, XATTR_NAME_SMACKTRANSMUTE) == 0) {
-               if (!smack_privileged(CAP_MAC_ADMIN))
-                       rc = -EPERM;
+               check_priv = 1;
                if (size != TRANS_TRUE_SIZE ||
                    strncmp(value, TRANS_TRUE, TRANS_TRUE_SIZE) != 0)
                        rc = -EINVAL;
        } else
                rc = cap_inode_setxattr(dentry, name, value, size, flags);
 
+       if (check_priv && !smack_privileged(CAP_MAC_ADMIN))
+               rc = -EPERM;
+
+       if (rc == 0 && check_import) {
+               skp = smk_import_entry(value, size);
+               if (skp == NULL || (check_star &&
+                   (skp == &smack_known_star || skp == &smack_known_web)))
+                       rc = -EINVAL;
+       }
+
        smk_ad_init(&ad, __func__, LSM_AUDIT_DATA_DENTRY);
        smk_ad_setfield_u_fs_path_dentry(&ad, dentry);
 
@@ -2850,8 +2862,17 @@ static void smack_d_instantiate(struct dentry *opt_dentry, struct inode *inode)
                        if (rc >= 0)
                                transflag = SMK_INODE_TRANSMUTE;
                }
-               isp->smk_task = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
-               isp->smk_mmap = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
+               /*
+                * Don't let the exec or mmap label be "*" or "@".
+                */
+               skp = smk_fetch(XATTR_NAME_SMACKEXEC, inode, dp);
+               if (skp == &smack_known_star || skp == &smack_known_web)
+                       skp = NULL;
+               isp->smk_task = skp;
+               skp = smk_fetch(XATTR_NAME_SMACKMMAP, inode, dp);
+               if (skp == &smack_known_star || skp == &smack_known_web)
+                       skp = NULL;
+               isp->smk_mmap = skp;
 
                dput(dp);
                break;