diff options
author | William Hua <william.hua@canonical.com> | 2017-01-16 03:49:28 +0300 |
---|---|---|
committer | John Johansen <john.johansen@canonical.com> | 2017-01-16 12:18:51 +0300 |
commit | e025be0f26d5597b0a2bdfa65145a0171e77b614 (patch) | |
tree | 0f9300ae3893d6af776466d12fe22a739d01d75d /security/apparmor/policy_unpack.c | |
parent | 12eb87d50bfe234c3f964e9fb47bbd0135010c13 (diff) | |
download | linux-e025be0f26d5597b0a2bdfa65145a0171e77b614.tar.xz |
apparmor: support querying extended trusted helper extra data
Allow a profile to carry extra data that can be queried via userspace.
This provides a means to store extra data in a profile that a trusted
helper can extract and use from live policy.
Signed-off-by: William Hua <william.hua@canonical.com>
Signed-off-by: John Johansen <john.johansen@canonical.com>
Diffstat (limited to 'security/apparmor/policy_unpack.c')
-rw-r--r-- | security/apparmor/policy_unpack.c | 66 |
1 files changed, 66 insertions, 0 deletions
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c index 59c891ad1270..4f61d40e29b0 100644 --- a/security/apparmor/policy_unpack.c +++ b/security/apparmor/policy_unpack.c @@ -485,6 +485,30 @@ fail: return 0; } +static void *kvmemdup(const void *src, size_t len) +{ + void *p = kvmalloc(len); + + if (p) + memcpy(p, src, len); + return p; +} + +static u32 strhash(const void *data, u32 len, u32 seed) +{ + const char * const *key = data; + + return jhash(*key, strlen(*key), seed); +} + +static int datacmp(struct rhashtable_compare_arg *arg, const void *obj) +{ + const struct aa_data *data = obj; + const char * const *key = arg->key; + + return strcmp(data->key, *key); +} + /** * unpack_profile - unpack a serialized profile * @e: serialized data extent information (NOT NULL) @@ -496,6 +520,9 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) struct aa_profile *profile = NULL; const char *tmpname, *tmpns = NULL, *name = NULL; size_t ns_len; + struct rhashtable_params params = { 0 }; + char *key = NULL; + struct aa_data *data; int i, error = -EPROTO; kernel_cap_t tmpcap; u32 tmp; @@ -654,6 +681,45 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name) if (!unpack_trans_table(e, profile)) goto fail; + if (unpack_nameX(e, AA_STRUCT, "data")) { + profile->data = kzalloc(sizeof(*profile->data), GFP_KERNEL); + if (!profile->data) + goto fail; + + params.nelem_hint = 3; + params.key_len = sizeof(void *); + params.key_offset = offsetof(struct aa_data, key); + params.head_offset = offsetof(struct aa_data, head); + params.hashfn = strhash; + params.obj_cmpfn = datacmp; + + if (rhashtable_init(profile->data, ¶ms)) + goto fail; + + while (unpack_strdup(e, &key, NULL)) { + data = kzalloc(sizeof(*data), GFP_KERNEL); + if (!data) { + kzfree(key); + goto fail; + } + + data->key = key; + data->size = unpack_blob(e, &data->data, NULL); + data->data = kvmemdup(data->data, data->size); + if (data->size && !data->data) { + kzfree(data->key); + kzfree(data); + goto fail; + } + + rhashtable_insert_fast(profile->data, &data->head, + profile->data->p); + } + + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) + goto fail; + } + if (!unpack_nameX(e, AA_STRUCTEND, NULL)) goto fail; |