summaryrefslogtreecommitdiff
path: root/security/smack/smackfs.c
diff options
context:
space:
mode:
authorCasey Schaufler <casey@schaufler-ca.com>2015-03-22 04:26:40 +0300
committerCasey Schaufler <casey@schaufler-ca.com>2015-03-23 23:21:34 +0300
commitbf4b2fee99799780ea3dbb6d79d1909b3e32be13 (patch)
tree70224834f619caa3bf5abd39a7334f5b77bf5656 /security/smack/smackfs.c
parent7fc5f36e980a8f4830efdae3858f6e64eee538b7 (diff)
downloadlinux-bf4b2fee99799780ea3dbb6d79d1909b3e32be13.tar.xz
Smack: Allow an unconfined label in bringup mode
I have vehemently opposed adding a "permissive" mode to Smack for the simple reasons that it would be subject to massive abuse and that developers refuse to turn it off come product release. I still believe that this is true, and still refuse to add a general "permissive mode". So don't ask again. Bumjin Im suggested an approach that addresses most of the concerns, and I have implemented it here. I still believe that we'd be better off without this sort of thing, but it looks like this minimizes the abuse potential. Firstly, you have to configure Smack Bringup Mode. That allows for "release" software to be ammune from abuse. Second, only one label gets to be "permissive" at a time. You can use it for debugging, but that's about it. A label written to smackfs/unconfined is treated specially. If either the subject or object label of an access check matches the "unconfined" label, and the access would not have been allowed otherwise an audit record and a console message are generated. The audit record "request" string is marked with either "(US)" or "(UO)", to indicate that the request was granted because of an unconfined label. The fact that an inode was accessed by an unconfined label is remembered, and subsequent accesses to that "impure" object are noted in the log. The impurity is not stored in the filesystem, so a file mislabled as a side effect of using an unconfined label may still cause concern after a reboot. So, it's there, it's dangerous, but so many application developers seem incapable of living without it I have given in. I've tried to make it as safe as I can, but in the end it's still a chain saw. Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
Diffstat (limited to 'security/smack/smackfs.c')
-rw-r--r--security/smack/smackfs.c96
1 files changed, 96 insertions, 0 deletions
diff --git a/security/smack/smackfs.c b/security/smack/smackfs.c
index bce4e8f1b267..deb3d3bfbbf3 100644
--- a/security/smack/smackfs.c
+++ b/security/smack/smackfs.c
@@ -54,6 +54,9 @@ enum smk_inos {
SMK_CHANGE_RULE = 19, /* change or add rules (long labels) */
SMK_SYSLOG = 20, /* change syslog label) */
SMK_PTRACE = 21, /* set ptrace rule */
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+ SMK_UNCONFINED = 22, /* define an unconfined label */
+#endif
};
/*
@@ -95,6 +98,16 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
*/
struct smack_known *smack_onlycap;
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+/*
+ * Allow one label to be unconfined. This is for
+ * debugging and application bring-up purposes only.
+ * It is bad and wrong, but everyone seems to expect
+ * to have it.
+ */
+struct smack_known *smack_unconfined;
+#endif
+
/*
* If this value is set restrict syslog use to the label specified.
* It can be reset via smackfs/syslog
@@ -1717,6 +1730,85 @@ static const struct file_operations smk_onlycap_ops = {
.llseek = default_llseek,
};
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+/**
+ * smk_read_unconfined - read() for smackfs/unconfined
+ * @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_unconfined(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_unconfined != NULL)
+ smack = smack_unconfined->smk_known;
+
+ asize = strlen(smack) + 1;
+
+ if (cn >= asize)
+ rc = simple_read_from_buffer(buf, cn, ppos, smack, asize);
+
+ return rc;
+}
+
+/**
+ * smk_write_unconfined - write() for smackfs/unconfined
+ * @file: 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_unconfined(struct file *file, const char __user *buf,
+ size_t count, loff_t *ppos)
+{
+ char *data;
+ int rc = count;
+
+ if (!smack_privileged(CAP_MAC_ADMIN))
+ return -EPERM;
+
+ data = kzalloc(count + 1, GFP_KERNEL);
+ if (data == NULL)
+ return -ENOMEM;
+
+ /*
+ * Should the null string be passed in unset the unconfined 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.
+ *
+ * smk_import will also reject a label beginning with '-',
+ * so "-confine" will also work.
+ */
+ if (copy_from_user(data, buf, count) != 0)
+ rc = -EFAULT;
+ else
+ smack_unconfined = smk_import_entry(data, count);
+
+ kfree(data);
+ return rc;
+}
+
+static const struct file_operations smk_unconfined_ops = {
+ .read = smk_read_unconfined,
+ .write = smk_write_unconfined,
+ .llseek = default_llseek,
+};
+#endif /* CONFIG_SECURITY_SMACK_BRINGUP */
+
/**
* smk_read_logging - read() for /smack/logging
* @filp: file pointer, not actually used
@@ -2384,6 +2476,10 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
"syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
[SMK_PTRACE] = {
"ptrace", &smk_ptrace_ops, S_IRUGO|S_IWUSR},
+#ifdef CONFIG_SECURITY_SMACK_BRINGUP
+ [SMK_UNCONFINED] = {
+ "unconfined", &smk_unconfined_ops, S_IRUGO|S_IWUSR},
+#endif
/* last one */
{""}
};