summaryrefslogtreecommitdiff
path: root/security/apparmor/policy_unpack.c
diff options
context:
space:
mode:
authorWilliam Hua <william.hua@canonical.com>2017-01-16 03:49:28 +0300
committerJohn Johansen <john.johansen@canonical.com>2017-01-16 12:18:51 +0300
commite025be0f26d5597b0a2bdfa65145a0171e77b614 (patch)
tree0f9300ae3893d6af776466d12fe22a739d01d75d /security/apparmor/policy_unpack.c
parent12eb87d50bfe234c3f964e9fb47bbd0135010c13 (diff)
downloadlinux-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.c66
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, &params))
+ 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;