summaryrefslogtreecommitdiff
path: root/security/apparmor/policy_unpack.c
diff options
context:
space:
mode:
Diffstat (limited to 'security/apparmor/policy_unpack.c')
-rw-r--r--security/apparmor/policy_unpack.c85
1 files changed, 76 insertions, 9 deletions
diff --git a/security/apparmor/policy_unpack.c b/security/apparmor/policy_unpack.c
index 40c8dc617b13..98d019185e57 100644
--- a/security/apparmor/policy_unpack.c
+++ b/security/apparmor/policy_unpack.c
@@ -203,6 +203,15 @@ static bool inbounds(struct aa_ext *e, size_t size)
return (size <= e->end - e->pos);
}
+static void *kvmemdup(const void *src, size_t len)
+{
+ void *p = kvmalloc(len, GFP_KERNEL);
+
+ if (p)
+ memcpy(p, src, len);
+ return p;
+}
+
/**
* aa_u16_chunck - test and do bounds checking for a u16 size based chunk
* @e: serialized data read head (NOT NULL)
@@ -522,6 +531,68 @@ fail:
return 0;
}
+static bool unpack_xattrs(struct aa_ext *e, struct aa_profile *profile)
+{
+ void *pos = e->pos;
+
+ if (unpack_nameX(e, AA_STRUCT, "xattrs")) {
+ int i, size;
+
+ size = unpack_array(e, NULL);
+ profile->xattr_count = size;
+ profile->xattrs = kcalloc(size, sizeof(char *),
+ GFP_KERNEL);
+ if (!profile->xattrs)
+ goto fail;
+ for (i = 0; i < size; i++) {
+ if (!unpack_strdup(e, &profile->xattrs[i], NULL))
+ goto fail;
+ }
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+ }
+
+ if (unpack_nameX(e, AA_STRUCT, "xattr_values")) {
+ int i, size;
+
+ size = unpack_array(e, NULL);
+
+ /* Must be the same number of xattr values as xattrs */
+ if (size != profile->xattr_count)
+ goto fail;
+
+ profile->xattr_lens = kcalloc(size, sizeof(size_t),
+ GFP_KERNEL);
+ if (!profile->xattr_lens)
+ goto fail;
+
+ profile->xattr_values = kcalloc(size, sizeof(char *),
+ GFP_KERNEL);
+ if (!profile->xattr_values)
+ goto fail;
+
+ for (i = 0; i < size; i++) {
+ profile->xattr_lens[i] = unpack_blob(e,
+ &profile->xattr_values[i], NULL);
+ profile->xattr_values[i] =
+ kvmemdup(profile->xattr_values[i],
+ profile->xattr_lens[i]);
+ }
+
+ if (!unpack_nameX(e, AA_ARRAYEND, NULL))
+ goto fail;
+ if (!unpack_nameX(e, AA_STRUCTEND, NULL))
+ goto fail;
+ }
+ return 1;
+
+fail:
+ e->pos = pos;
+ return 0;
+}
+
static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
{
void *pos = e->pos;
@@ -556,15 +627,6 @@ fail:
return 0;
}
-static void *kvmemdup(const void *src, size_t len)
-{
- void *p = kvmalloc(len, GFP_KERNEL);
-
- if (p)
- memcpy(p, src, len);
- return p;
-}
-
static u32 strhash(const void *data, u32 len, u32 seed)
{
const char * const *key = data;
@@ -719,6 +781,11 @@ static struct aa_profile *unpack_profile(struct aa_ext *e, char **ns_name)
goto fail;
}
+ if (!unpack_xattrs(e, profile)) {
+ info = "failed to unpack profile xattrs";
+ goto fail;
+ }
+
if (!unpack_rlimits(e, profile)) {
info = "failed to unpack profile rlimits";
goto fail;