]> git.proxmox.com Git - mirror_ubuntu-artful-kernel.git/blobdiff - security/apparmor/lib.c
Merge branches 'for-4.11/upstream-fixes', 'for-4.12/accutouch', 'for-4.12/cp2112...
[mirror_ubuntu-artful-kernel.git] / security / apparmor / lib.c
index c1827e068454cf992c510fd7f6bc9cbbda67a500..66475bda6f72212c330e7c6f8febfc930beb4e74 100644 (file)
@@ -12,6 +12,7 @@
  * License.
  */
 
+#include <linux/ctype.h>
 #include <linux/mm.h>
 #include <linux/slab.h>
 #include <linux/string.h>
@@ -19,7 +20,8 @@
 
 #include "include/audit.h"
 #include "include/apparmor.h"
-
+#include "include/lib.h"
+#include "include/policy.h"
 
 /**
  * aa_split_fqname - split a fqname into a profile and namespace name
@@ -59,6 +61,58 @@ char *aa_split_fqname(char *fqname, char **ns_name)
        return name;
 }
 
+/**
+ * skipn_spaces - Removes leading whitespace from @str.
+ * @str: The string to be stripped.
+ *
+ * Returns a pointer to the first non-whitespace character in @str.
+ * if all whitespace will return NULL
+ */
+
+static const char *skipn_spaces(const char *str, size_t n)
+{
+       for (; n && isspace(*str); --n)
+               ++str;
+       if (n)
+               return (char *)str;
+       return NULL;
+}
+
+const char *aa_splitn_fqname(const char *fqname, size_t n, const char **ns_name,
+                            size_t *ns_len)
+{
+       const char *end = fqname + n;
+       const char *name = skipn_spaces(fqname, n);
+
+       if (!name)
+               return NULL;
+       *ns_name = NULL;
+       *ns_len = 0;
+       if (name[0] == ':') {
+               char *split = strnchr(&name[1], end - &name[1], ':');
+               *ns_name = skipn_spaces(&name[1], end - &name[1]);
+               if (!*ns_name)
+                       return NULL;
+               if (split) {
+                       *ns_len = split - *ns_name;
+                       if (*ns_len == 0)
+                               *ns_name = NULL;
+                       split++;
+                       if (end - split > 1 && strncmp(split, "//", 2) == 0)
+                               split += 2;
+                       name = skipn_spaces(split, end - split);
+               } else {
+                       /* a ns name without a following profile is allowed */
+                       name = NULL;
+                       *ns_len = end - *ns_name;
+               }
+       }
+       if (name && *name == 0)
+               name = NULL;
+
+       return name;
+}
+
 /**
  * aa_info_message - log a none profile related status message
  * @str: message to log
@@ -66,11 +120,9 @@ char *aa_split_fqname(char *fqname, char **ns_name)
 void aa_info_message(const char *str)
 {
        if (audit_enabled) {
-               struct common_audit_data sa;
-               struct apparmor_audit_data aad = {0,};
-               sa.type = LSM_AUDIT_DATA_NONE;
-               sa.aad = &aad;
-               aad.info = str;
+               DEFINE_AUDIT_DATA(sa, LSM_AUDIT_DATA_NONE, NULL);
+
+               aad(&sa)->info = str;
                aa_audit_msg(AUDIT_APPARMOR_STATUS, &sa, NULL);
        }
        printk(KERN_INFO "AppArmor: %s\n", str);
@@ -95,7 +147,8 @@ void *__aa_kvmalloc(size_t size, gfp_t flags)
 
        /* do not attempt kmalloc if we need more than 16 pages at once */
        if (size <= (16*PAGE_SIZE))
-               buffer = kmalloc(size, flags | GFP_NOIO | __GFP_NOWARN);
+               buffer = kmalloc(size, flags | GFP_KERNEL | __GFP_NORETRY |
+                                __GFP_NOWARN);
        if (!buffer) {
                if (flags & __GFP_ZERO)
                        buffer = vzalloc(size);
@@ -104,3 +157,47 @@ void *__aa_kvmalloc(size_t size, gfp_t flags)
        }
        return buffer;
 }
+
+/**
+ * aa_policy_init - initialize a policy structure
+ * @policy: policy to initialize  (NOT NULL)
+ * @prefix: prefix name if any is required.  (MAYBE NULL)
+ * @name: name of the policy, init will make a copy of it  (NOT NULL)
+ *
+ * Note: this fn creates a copy of strings passed in
+ *
+ * Returns: true if policy init successful
+ */
+bool aa_policy_init(struct aa_policy *policy, const char *prefix,
+                   const char *name, gfp_t gfp)
+{
+       /* freed by policy_free */
+       if (prefix) {
+               policy->hname = kmalloc(strlen(prefix) + strlen(name) + 3,
+                                       gfp);
+               if (policy->hname)
+                       sprintf((char *)policy->hname, "%s//%s", prefix, name);
+       } else
+               policy->hname = kstrdup(name, gfp);
+       if (!policy->hname)
+               return 0;
+       /* base.name is a substring of fqname */
+       policy->name = basename(policy->hname);
+       INIT_LIST_HEAD(&policy->list);
+       INIT_LIST_HEAD(&policy->profiles);
+
+       return 1;
+}
+
+/**
+ * aa_policy_destroy - free the elements referenced by @policy
+ * @policy: policy that is to have its elements freed  (NOT NULL)
+ */
+void aa_policy_destroy(struct aa_policy *policy)
+{
+       AA_BUG(on_list_rcu(&policy->profiles));
+       AA_BUG(on_list_rcu(&policy->list));
+
+       /* don't free name as its a subset of hname */
+       kzfree(policy->hname);
+}