]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - security/smack/smackfs.c
Merge current mainline tree into linux-omap tree
[linux-2.6-omap-h63xx.git] / security / smack / smackfs.c
index 271a835fbbe3f72f4e5465cbf84b9b271fa7e77a..c21d8c8bf0c789f3af9693fac3cdbd226dd4b8cc 100644 (file)
@@ -39,6 +39,7 @@ enum smk_inos {
        SMK_DIRECT      = 6,    /* CIPSO level indicating direct label */
        SMK_AMBIENT     = 7,    /* internet ambient label */
        SMK_NLTYPE      = 8,    /* label scheme to use by default */
+       SMK_ONLYCAP     = 9,    /* the only "capable" label */
 };
 
 /*
@@ -68,6 +69,16 @@ int smack_net_nltype = NETLBL_NLTYPE_CIPSOV4;
  */
 int smack_cipso_direct = SMACK_CIPSO_DIRECT_DEFAULT;
 
+/*
+ * Unless a process is running with this label even
+ * having CAP_MAC_OVERRIDE isn't enough to grant
+ * privilege to violate MAC policy. If no label is
+ * designated (the NULL case) capabilities apply to
+ * everyone. It is expected that the hat (^) label
+ * will be used if any label is used.
+ */
+char *smack_onlycap;
+
 static int smk_cipso_doi_value = SMACK_CIPSO_DOI_DEFAULT;
 struct smk_list_entry *smack_list;
 
@@ -343,9 +354,11 @@ static void smk_cipso_doi(void)
                doip->tags[rc] = CIPSO_V4_TAG_INVALID;
 
        rc = netlbl_cfg_cipsov4_add_map(doip, NULL, &audit_info);
-       if (rc != 0)
+       if (rc != 0) {
                printk(KERN_WARNING "%s:%d add rc = %d\n",
                       __func__, __LINE__, rc);
+               kfree(doip);
+       }
 }
 
 /**
@@ -787,6 +800,85 @@ static const struct file_operations smk_ambient_ops = {
        .write          = smk_write_ambient,
 };
 
+/**
+ * smk_read_onlycap - read() for /smack/onlycap
+ * @filp: file pointer, not actually used
+ * @buf: where to put the result
+ * @cn: maximum to send along
+ * @ppos: where to start
+ *
+ * Returns number of bytes read or error code, as appropriate
+ */
+static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
+                               size_t cn, loff_t *ppos)
+{
+       char *smack = "";
+       ssize_t rc = -EINVAL;
+       int asize;
+
+       if (*ppos != 0)
+               return 0;
+
+       if (smack_onlycap != NULL)
+               smack = smack_onlycap;
+
+       asize = strlen(smack) + 1;
+
+       if (cn >= asize)
+               rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
+
+       return rc;
+}
+
+/**
+ * smk_write_onlycap - write() for /smack/onlycap
+ * @filp: file pointer, not actually used
+ * @buf: where to get the data from
+ * @count: bytes sent
+ * @ppos: where to start
+ *
+ * Returns number of bytes written or error code, as appropriate
+ */
+static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
+                                size_t count, loff_t *ppos)
+{
+       char in[SMK_LABELLEN];
+       char *sp = current->security;
+
+       if (!capable(CAP_MAC_ADMIN))
+               return -EPERM;
+
+       /*
+        * This can be done using smk_access() but is done
+        * explicitly for clarity. The smk_access() implementation
+        * would use smk_access(smack_onlycap, MAY_WRITE)
+        */
+       if (smack_onlycap != NULL && smack_onlycap != sp)
+               return -EPERM;
+
+       if (count >= SMK_LABELLEN)
+               return -EINVAL;
+
+       if (copy_from_user(in, buf, count) != 0)
+               return -EFAULT;
+
+       /*
+        * Should the null string be passed in unset the onlycap value.
+        * This seems like something to be careful with as usually
+        * smk_import only expects to return NULL for errors. It
+        * is usually the case that a nullstring or "\n" would be
+        * bad to pass to smk_import but in fact this is useful here.
+        */
+       smack_onlycap = smk_import(in, count);
+
+       return count;
+}
+
+static const struct file_operations smk_onlycap_ops = {
+       .read           = smk_read_onlycap,
+       .write          = smk_write_onlycap,
+};
+
 struct option_names {
        int     o_number;
        char    *o_name;
@@ -919,6 +1011,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
                        {"ambient", &smk_ambient_ops, S_IRUGO|S_IWUSR},
                [SMK_NLTYPE]    =
                        {"nltype", &smk_nltype_ops, S_IRUGO|S_IWUSR},
+               [SMK_ONLYCAP]   =
+                       {"onlycap", &smk_onlycap_ops, S_IRUGO|S_IWUSR},
                /* last one */ {""}
        };