Smack: allow to access /smack/access as normal user
[cascardo/linux.git] / security / smack / smackfs.c
index 54f6e18..6aceef5 100644 (file)
@@ -191,19 +191,37 @@ static int smk_set_access(struct smack_rule *srp, struct list_head *rule_list,
 }
 
 /**
- * smk_parse_rule - parse subject, object and access type
+ * smk_parse_rule - parse Smack rule from load string
  * @data: string to be parsed whose size is SMK_LOADLEN
- * @rule: parsed entities are stored in here
+ * @rule: Smack rule
+ * @import: if non-zero, import labels
  */
-static int smk_parse_rule(const char *data, struct smack_rule *rule)
+static int smk_parse_rule(const char *data, struct smack_rule *rule, int import)
 {
-       rule->smk_subject = smk_import(data, 0);
-       if (rule->smk_subject == NULL)
-               return -1;
+       char smack[SMK_LABELLEN];
+       struct smack_known *skp;
 
-       rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
-       if (rule->smk_object == NULL)
-               return -1;
+       if (import) {
+               rule->smk_subject = smk_import(data, 0);
+               if (rule->smk_subject == NULL)
+                       return -1;
+
+               rule->smk_object = smk_import(data + SMK_LABELLEN, 0);
+               if (rule->smk_object == NULL)
+                       return -1;
+       } else {
+               smk_parse_smack(data, 0, smack);
+               skp = smk_find_entry(smack);
+               if (skp == NULL)
+                       return -1;
+               rule->smk_subject = skp->smk_known;
+
+               smk_parse_smack(data + SMK_LABELLEN, 0, smack);
+               skp = smk_find_entry(smack);
+               if (skp == NULL)
+                       return -1;
+               rule->smk_object = skp->smk_known;
+       }
 
        rule->smk_access = 0;
 
@@ -327,7 +345,7 @@ static ssize_t smk_write_load_list(struct file *file, const char __user *buf,
                goto out;
        }
 
-       if (smk_parse_rule(data, rule))
+       if (smk_parse_rule(data, rule, 1))
                goto out_free_rule;
 
        if (rule_list == NULL) {
@@ -1497,21 +1515,21 @@ static ssize_t smk_write_access(struct file *file, const char __user *buf,
 {
        struct smack_rule rule;
        char *data;
-
-       if (!capable(CAP_MAC_ADMIN))
-               return -EPERM;
+       int res;
 
        data = simple_transaction_get(file, buf, count);
        if (IS_ERR(data))
                return PTR_ERR(data);
 
-       if (count < SMK_LOADLEN || smk_parse_rule(data, &rule))
+       if (count < SMK_LOADLEN || smk_parse_rule(data, &rule, 0))
                return -EINVAL;
 
-       data[0] = smk_access(rule.smk_subject, rule.smk_object,
-                            rule.smk_access, NULL) == 0;
+       res = smk_access(rule.smk_subject, rule.smk_object, rule.smk_access,
+                         NULL);
+       data[0] = res == 0 ? '1' : '0';
+       data[1] = '\0';
 
-       simple_transaction_set(file, 1);
+       simple_transaction_set(file, 2);
        return SMK_LOADLEN;
 }
 
@@ -1557,7 +1575,7 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
                [SMK_LOAD_SELF] = {
                        "load-self", &smk_load_self_ops, S_IRUGO|S_IWUGO},
                [SMK_ACCESSES] = {
-                       "access", &smk_access_ops, S_IRUGO|S_IWUSR},
+                       "access", &smk_access_ops, S_IRUGO|S_IWUGO},
                /* last one */
                        {""}
        };