diff options
Diffstat (limited to 'security/apparmor/lib.c')
-rw-r--r-- | security/apparmor/lib.c | 111 |
1 files changed, 104 insertions, 7 deletions
diff --git a/security/apparmor/lib.c b/security/apparmor/lib.c index c1827e068454..66475bda6f72 100644 --- a/security/apparmor/lib.c +++ b/security/apparmor/lib.c @@ -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 @@ -60,17 +62,67 @@ char *aa_split_fqname(char *fqname, char **ns_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 */ 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); +} |