Smack: Make the syslog control configurable
authorCasey Schaufler <casey@schaufler-ca.com>
Mon, 23 Dec 2013 19:07:10 +0000 (11:07 -0800)
committerCasey Schaufler <casey@schaufler-ca.com>
Mon, 23 Dec 2013 23:50:55 +0000 (15:50 -0800)
The syslog control requires that the calling proccess
have the floor ("_") Smack label. Tizen does not run any
processes except for kernel helpers with the floor label.
This changes allows the admin to configure a specific
label for syslog. The default value is the star ("*")
label, effectively removing the restriction. The value
can be set using smackfs/syslog for anyone who wants
a more restrictive behavior.

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

Signed-off-by: Casey Schaufler <casey@schaufler-ca.com>
security/smack/smack.h
security/smack/smack_lsm.c
security/smack/smackfs.c

index 364cc64fce717be1e75d16fa91f4aeaadc55539f..d072fd32212d36cb359dbd31006614c3471f2981 100644 (file)
@@ -241,7 +241,8 @@ u32 smack_to_secid(const char *);
 extern int smack_cipso_direct;
 extern int smack_cipso_mapped;
 extern struct smack_known *smack_net_ambient;
-extern char *smack_onlycap;
+extern struct smack_known *smack_onlycap;
+extern struct smack_known *smack_syslog_label;
 extern const char *smack_cipso_option;
 
 extern struct smack_known smack_known_floor;
@@ -312,7 +313,7 @@ static inline int smack_privileged(int cap)
 
        if (!capable(cap))
                return 0;
-       if (smack_onlycap == NULL || smack_onlycap == skp->smk_known)
+       if (smack_onlycap == NULL || smack_onlycap == skp)
                return 1;
        return 0;
 }
index 62ebf4f8a6c76e491e192ead7568dd8c5cad5c87..67b7381d02448a9c6f058c522fad1515ac13b67d 100644 (file)
@@ -219,8 +219,6 @@ static int smack_ptrace_traceme(struct task_struct *ptp)
  * smack_syslog - Smack approval on syslog
  * @type: message type
  *
- * Require that the task has the floor label
- *
  * Returns 0 on success, error code otherwise.
  */
 static int smack_syslog(int typefrom_file)
@@ -231,7 +229,7 @@ static int smack_syslog(int typefrom_file)
        if (smack_privileged(CAP_MAC_OVERRIDE))
                return 0;
 
-        if (skp != &smack_known_floor)
+        if (smack_syslog_label != NULL && smack_syslog_label != skp)
                rc = -EACCES;
 
        return rc;
index 1c89ade186b651bd7898821bbc3b9199da871305..f5a6bb8e282848e8ec1247c7d46e881b92b5a814 100644 (file)
@@ -52,6 +52,7 @@ enum smk_inos {
        SMK_CIPSO2      = 17,   /* load long label -> CIPSO mapping */
        SMK_REVOKE_SUBJ = 18,   /* set rules with subject label to '-' */
        SMK_CHANGE_RULE = 19,   /* change or add rules (long labels) */
+       SMK_SYSLOG      = 20,   /* change syslog label) */
 };
 
 /*
@@ -59,6 +60,7 @@ enum smk_inos {
  */
 static DEFINE_MUTEX(smack_cipso_lock);
 static DEFINE_MUTEX(smack_ambient_lock);
+static DEFINE_MUTEX(smack_syslog_lock);
 static DEFINE_MUTEX(smk_netlbladdr_lock);
 
 /*
@@ -90,7 +92,13 @@ int smack_cipso_mapped = SMACK_CIPSO_MAPPED_DEFAULT;
  * everyone. It is expected that the hat (^) label
  * will be used if any label is used.
  */
-char *smack_onlycap;
+struct smack_known *smack_onlycap;
+
+/*
+ * If this value is set restrict syslog use to the label specified.
+ * It can be reset via smackfs/syslog
+ */
+struct smack_known *smack_syslog_label;
 
 /*
  * Certain IP addresses may be designated as single label hosts.
@@ -1603,7 +1611,7 @@ static const struct file_operations smk_ambient_ops = {
 };
 
 /**
- * smk_read_onlycap - read() for /smack/onlycap
+ * smk_read_onlycap - read() for smackfs/onlycap
  * @filp: file pointer, not actually used
  * @buf: where to put the result
  * @cn: maximum to send along
@@ -1622,7 +1630,7 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
                return 0;
 
        if (smack_onlycap != NULL)
-               smack = smack_onlycap;
+               smack = smack_onlycap->smk_known;
 
        asize = strlen(smack) + 1;
 
@@ -1633,7 +1641,7 @@ static ssize_t smk_read_onlycap(struct file *filp, char __user *buf,
 }
 
 /**
- * smk_write_onlycap - write() for /smack/onlycap
+ * smk_write_onlycap - write() for smackfs/onlycap
  * @file: file pointer, not actually used
  * @buf: where to get the data from
  * @count: bytes sent
@@ -1656,7 +1664,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
         * explicitly for clarity. The smk_access() implementation
         * would use smk_access(smack_onlycap, MAY_WRITE)
         */
-       if (smack_onlycap != NULL && smack_onlycap != skp->smk_known)
+       if (smack_onlycap != NULL && smack_onlycap != skp)
                return -EPERM;
 
        data = kzalloc(count, GFP_KERNEL);
@@ -1676,7 +1684,7 @@ static ssize_t smk_write_onlycap(struct file *file, const char __user *buf,
        if (copy_from_user(data, buf, count) != 0)
                rc = -EFAULT;
        else
-               smack_onlycap = smk_import(data, count);
+               smack_onlycap = smk_import_entry(data, count);
 
        kfree(data);
        return rc;
@@ -2159,12 +2167,89 @@ static const struct file_operations smk_change_rule_ops = {
 };
 
 /**
- * smk_fill_super - fill the /smackfs superblock
+ * smk_read_syslog - read() for smackfs/syslog
+ * @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_syslog(struct file *filp, char __user *buf,
+                               size_t cn, loff_t *ppos)
+{
+       struct smack_known *skp;
+       ssize_t rc = -EINVAL;
+       int asize;
+
+       if (*ppos != 0)
+               return 0;
+
+       if (smack_syslog_label == NULL)
+               skp = &smack_known_star;
+       else
+               skp = smack_syslog_label;
+
+       asize = strlen(skp->smk_known) + 1;
+
+       if (cn >= asize)
+               rc = simple_read_from_buffer(buf, cn, ppos, skp->smk_known,
+                                               asize);
+
+       return rc;
+}
+
+/**
+ * smk_write_syslog - write() for smackfs/syslog
+ * @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_syslog(struct file *file, const char __user *buf,
+                               size_t count, loff_t *ppos)
+{
+       char *data;
+       struct smack_known *skp;
+       int rc = count;
+
+       if (!smack_privileged(CAP_MAC_ADMIN))
+               return -EPERM;
+
+       data = kzalloc(count, GFP_KERNEL);
+       if (data == NULL)
+               return -ENOMEM;
+
+       if (copy_from_user(data, buf, count) != 0)
+               rc = -EFAULT;
+       else {
+               skp = smk_import_entry(data, count);
+               if (skp == NULL)
+                       rc = -EINVAL;
+               else
+                       smack_syslog_label = smk_import_entry(data, count);
+       }
+
+       kfree(data);
+       return rc;
+}
+
+static const struct file_operations smk_syslog_ops = {
+       .read           = smk_read_syslog,
+       .write          = smk_write_syslog,
+       .llseek         = default_llseek,
+};
+
+
+/**
+ * smk_fill_super - fill the smackfs superblock
  * @sb: the empty superblock
  * @data: unused
  * @silent: unused
  *
- * Fill in the well known entries for /smack
+ * Fill in the well known entries for the smack filesystem
  *
  * Returns 0 on success, an error code on failure
  */
@@ -2209,6 +2294,8 @@ static int smk_fill_super(struct super_block *sb, void *data, int silent)
                        S_IRUGO|S_IWUSR},
                [SMK_CHANGE_RULE] = {
                        "change-rule", &smk_change_rule_ops, S_IRUGO|S_IWUSR},
+               [SMK_SYSLOG] = {
+                       "syslog", &smk_syslog_ops, S_IRUGO|S_IWUSR},
                /* last one */
                        {""}
        };