]> git.karo-electronics.de Git - karo-tx-linux.git/blobdiff - security/smack/smack_lsm.c
Merge remote-tracking branch 'security/next'
[karo-tx-linux.git] / security / smack / smack_lsm.c
index 1511965549b8232fdd4d3469166023c2d140f908..69fdc384af301f7724b26f6be7e6264da41bd6c2 100644 (file)
@@ -57,6 +57,13 @@ static struct kmem_cache *smack_inode_cache;
 int smack_enabled;
 
 #ifdef CONFIG_SECURITY_SMACK_BRINGUP
+static char *smk_bu_mess[] = {
+       "Bringup Error",        /* Unused */
+       "Bringup",              /* SMACK_BRINGUP_ALLOW */
+       "Unconfined Subject",   /* SMACK_UNCONFINED_SUBJECT */
+       "Unconfined Object",    /* SMACK_UNCONFINED_OBJECT */
+};
+
 static void smk_bu_mode(int mode, char *s)
 {
        int i = 0;
@@ -87,9 +94,11 @@ static int smk_bu_note(char *note, struct smack_known *sskp,
 
        if (rc <= 0)
                return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
 
        smk_bu_mode(mode, acc);
-       pr_info("Smack Bringup: (%s %s %s) %s\n",
+       pr_info("Smack %s: (%s %s %s) %s\n", smk_bu_mess[rc],
                sskp->smk_known, oskp->smk_known, acc, note);
        return 0;
 }
@@ -106,9 +115,11 @@ static int smk_bu_current(char *note, struct smack_known *oskp,
 
        if (rc <= 0)
                return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
 
        smk_bu_mode(mode, acc);
-       pr_info("Smack Bringup: (%s %s %s) %s %s\n",
+       pr_info("Smack %s: (%s %s %s) %s %s\n", smk_bu_mess[rc],
                tsp->smk_task->smk_known, oskp->smk_known,
                acc, current->comm, note);
        return 0;
@@ -126,9 +137,11 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
 
        if (rc <= 0)
                return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
 
        smk_bu_mode(mode, acc);
-       pr_info("Smack Bringup: (%s %s %s) %s to %s\n",
+       pr_info("Smack %s: (%s %s %s) %s to %s\n", smk_bu_mess[rc],
                tsp->smk_task->smk_known, smk_task->smk_known, acc,
                current->comm, otp->comm);
        return 0;
@@ -141,14 +154,25 @@ static int smk_bu_task(struct task_struct *otp, int mode, int rc)
 static int smk_bu_inode(struct inode *inode, int mode, int rc)
 {
        struct task_smack *tsp = current_security();
+       struct inode_smack *isp = inode->i_security;
        char acc[SMK_NUM_ACCESS_TYPE + 1];
 
+       if (isp->smk_flags & SMK_INODE_IMPURE)
+               pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+                       inode->i_sb->s_id, inode->i_ino, current->comm);
+
        if (rc <= 0)
                return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
+       if (rc == SMACK_UNCONFINED_SUBJECT &&
+           (mode & (MAY_WRITE | MAY_APPEND)))
+               isp->smk_flags |= SMK_INODE_IMPURE;
 
        smk_bu_mode(mode, acc);
-       pr_info("Smack Bringup: (%s %s %s) inode=(%s %ld) %s\n",
-               tsp->smk_task->smk_known, smk_of_inode(inode)->smk_known, acc,
+
+       pr_info("Smack %s: (%s %s %s) inode=(%s %ld) %s\n", smk_bu_mess[rc],
+               tsp->smk_task->smk_known, isp->smk_inode->smk_known, acc,
                inode->i_sb->s_id, inode->i_ino, current->comm);
        return 0;
 }
@@ -162,13 +186,20 @@ static int smk_bu_file(struct file *file, int mode, int rc)
        struct task_smack *tsp = current_security();
        struct smack_known *sskp = tsp->smk_task;
        struct inode *inode = file_inode(file);
+       struct inode_smack *isp = inode->i_security;
        char acc[SMK_NUM_ACCESS_TYPE + 1];
 
+       if (isp->smk_flags & SMK_INODE_IMPURE)
+               pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+                       inode->i_sb->s_id, inode->i_ino, current->comm);
+
        if (rc <= 0)
                return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
 
        smk_bu_mode(mode, acc);
-       pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
+       pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
                sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
                inode->i_sb->s_id, inode->i_ino, file,
                current->comm);
@@ -185,13 +216,20 @@ static int smk_bu_credfile(const struct cred *cred, struct file *file,
        struct task_smack *tsp = cred->security;
        struct smack_known *sskp = tsp->smk_task;
        struct inode *inode = file->f_inode;
+       struct inode_smack *isp = inode->i_security;
        char acc[SMK_NUM_ACCESS_TYPE + 1];
 
+       if (isp->smk_flags & SMK_INODE_IMPURE)
+               pr_info("Smack Unconfined Corruption: inode=(%s %ld) %s\n",
+                       inode->i_sb->s_id, inode->i_ino, current->comm);
+
        if (rc <= 0)
                return rc;
+       if (rc > SMACK_UNCONFINED_OBJECT)
+               rc = 0;
 
        smk_bu_mode(mode, acc);
-       pr_info("Smack Bringup: (%s %s %s) file=(%s %ld %pD) %s\n",
+       pr_info("Smack %s: (%s %s %s) file=(%s %ld %pD) %s\n", smk_bu_mess[rc],
                sskp->smk_known, smk_of_inode(inode)->smk_known, acc,
                inode->i_sb->s_id, inode->i_ino, file,
                current->comm);
@@ -2449,7 +2487,21 @@ static int smack_inode_setsecurity(struct inode *inode, const char *name,
 static int smack_socket_post_create(struct socket *sock, int family,
                                    int type, int protocol, int kern)
 {
-       if (family != PF_INET || sock->sk == NULL)
+       struct socket_smack *ssp;
+
+       if (sock->sk == NULL)
+               return 0;
+
+       /*
+        * Sockets created by kernel threads receive web label.
+        */
+       if (unlikely(current->flags & PF_KTHREAD)) {
+               ssp = sock->sk->sk_security;
+               ssp->smk_in = &smack_known_web;
+               ssp->smk_out = &smack_known_web;
+       }
+
+       if (family != PF_INET)
                return 0;
        /*
         * Set the outbound netlbl.
@@ -3983,6 +4035,36 @@ static int smack_key_permission(key_ref_t key_ref,
        rc = smk_bu_note("key access", tkp, keyp->security, request, rc);
        return rc;
 }
+
+/*
+ * smack_key_getsecurity - Smack label tagging the key
+ * @key points to the key to be queried
+ * @_buffer points to a pointer that should be set to point to the
+ * resulting string (if no label or an error occurs).
+ * Return the length of the string (including terminating NUL) or -ve if
+ * an error.
+ * May also return 0 (and a NULL buffer pointer) if there is no label.
+ */
+static int smack_key_getsecurity(struct key *key, char **_buffer)
+{
+       struct smack_known *skp = key->security;
+       size_t length;
+       char *copy;
+
+       if (key->security == NULL) {
+               *_buffer = NULL;
+               return 0;
+       }
+
+       copy = kstrdup(skp->smk_known, GFP_KERNEL);
+       if (copy == NULL)
+               return -ENOMEM;
+       length = strlen(copy) + 1;
+
+       *_buffer = copy;
+       return length;
+}
+
 #endif /* CONFIG_KEYS */
 
 /*
@@ -4307,6 +4389,7 @@ struct security_operations smack_ops = {
        .key_alloc =                    smack_key_alloc,
        .key_free =                     smack_key_free,
        .key_permission =               smack_key_permission,
+       .key_getsecurity =              smack_key_getsecurity,
 #endif /* CONFIG_KEYS */
 
  /* Audit hooks */