apparmor: make unpack_array return a trianary value
authorJohn Johansen <john.johansen@canonical.com>
Fri, 26 Aug 2022 16:26:57 +0000 (09:26 -0700)
committerJohn Johansen <john.johansen@canonical.com>
Mon, 3 Oct 2022 21:49:03 +0000 (14:49 -0700)
currently unpack_array() does not return an error nor whether the
array is not present. The ability to detect an error or the array
not being present is needed so rework the unpack_array() to return
the needed information.

Signed-off-by: John Johansen <john.johansen@canonical.com>
security/apparmor/policy_unpack.c
security/apparmor/policy_unpack_test.c

index a1fe0a5..7d3b3e6 100644 (file)
@@ -67,6 +67,11 @@ struct aa_ext {
        u32 version;
 };
 
+#define tri int
+#define TRI_TRUE 1
+#define TRI_NONE 0
+#define TRI_FALSE -1
+
 /* audit callback for unpack fields */
 static void audit_cb(struct audit_buffer *ab, void *va)
 {
@@ -344,22 +349,22 @@ fail:
        return false;
 }
 
-static size_t unpack_array(struct aa_ext *e, const char *name)
+static tri unpack_array(struct aa_ext *e, const char *name, u16 *size)
 {
        void *pos = e->pos;
 
        if (unpack_nameX(e, AA_ARRAY, name)) {
-               int size;
                if (!inbounds(e, sizeof(u16)))
                        goto fail;
-               size = (int)le16_to_cpu(get_unaligned((__le16 *) e->pos));
+               *size = le16_to_cpu(get_unaligned((__le16 *) e->pos));
                e->pos += sizeof(u16);
-               return size;
+               return TRI_TRUE;
        }
 
+       return TRI_NONE;
 fail:
        e->pos = pos;
-       return 0;
+       return TRI_FALSE;
 }
 
 static size_t unpack_blob(struct aa_ext *e, char **blob, const char *name)
@@ -477,11 +482,12 @@ static bool unpack_trans_table(struct aa_ext *e, struct aa_str_table *strs)
 
        /* exec table is optional */
        if (unpack_nameX(e, AA_STRUCT, "xtable")) {
-               int i, size;
+               u16 size;
+               int i;
 
-               size = unpack_array(e, NULL);
-               /* currently 2^24 bits entries 0-3 */
-               if (size > (1 << 24))
+               if (unpack_array(e, NULL, &size) != TRI_TRUE ||
+                   size > (1 << 24))
+                 /* currently 2^24 bits entries 0-3 */
                        goto fail;
                table = kcalloc(size, sizeof(char *), GFP_KERNEL);
                if (!table)
@@ -546,9 +552,11 @@ 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;
+               u16 size;
+               int i;
 
-               size = unpack_array(e, NULL);
+               if (unpack_array(e, NULL, &size) != TRI_TRUE)
+                       goto fail;
                profile->xattr_count = size;
                profile->xattrs = kcalloc(size, sizeof(char *), GFP_KERNEL);
                if (!profile->xattrs)
@@ -573,10 +581,12 @@ fail:
 static bool unpack_secmark(struct aa_ext *e, struct aa_profile *profile)
 {
        void *pos = e->pos;
-       int i, size;
+       u16 size;
+       int i;
 
        if (unpack_nameX(e, AA_STRUCT, "secmark")) {
-               size = unpack_array(e, NULL);
+               if (unpack_array(e, NULL, &size) != TRI_TRUE)
+                       goto fail;
 
                profile->secmark = kcalloc(size, sizeof(struct aa_secmark),
                                           GFP_KERNEL);
@@ -620,14 +630,15 @@ static bool unpack_rlimits(struct aa_ext *e, struct aa_profile *profile)
 
        /* rlimits are optional */
        if (unpack_nameX(e, AA_STRUCT, "rlimits")) {
-               int i, size;
+               u16 size;
+               int i;
                u32 tmp = 0;
                if (!unpack_u32(e, &tmp, NULL))
                        goto fail;
                profile->rlimits.mask = tmp;
 
-               size = unpack_array(e, NULL);
-               if (size > RLIM_NLIMITS)
+               if (unpack_array(e, NULL, &size) != TRI_TRUE ||
+                   size > RLIM_NLIMITS)
                        goto fail;
                for (i = 0; i < size; i++) {
                        u64 tmp2 = 0;
index 0a969b2..1a43d53 100644 (file)
@@ -144,8 +144,8 @@ static void policy_unpack_test_unpack_array_with_null_name(struct kunit *test)
 
        puf->e->pos += TEST_ARRAY_BUF_OFFSET;
 
-       array_size = unpack_array(puf->e, NULL);
-
+       KUNIT_EXPECT_EQ(test, unpack_array(puf->e, NULL, &array_size),
+                       TRI_TRUE);
        KUNIT_EXPECT_EQ(test, array_size, (u16)TEST_ARRAY_SIZE);
        KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
                puf->e->start + TEST_ARRAY_BUF_OFFSET + sizeof(u16) + 1);
@@ -159,8 +159,8 @@ static void policy_unpack_test_unpack_array_with_name(struct kunit *test)
 
        puf->e->pos += TEST_NAMED_ARRAY_BUF_OFFSET;
 
-       array_size = unpack_array(puf->e, name);
-
+       KUNIT_EXPECT_EQ(test, unpack_array(puf->e, name, &array_size),
+                       TRI_TRUE);
        KUNIT_EXPECT_EQ(test, array_size, (u16)TEST_ARRAY_SIZE);
        KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
                puf->e->start + TEST_ARRAY_BUF_OFFSET + sizeof(u16) + 1);
@@ -175,8 +175,8 @@ static void policy_unpack_test_unpack_array_out_of_bounds(struct kunit *test)
        puf->e->pos += TEST_NAMED_ARRAY_BUF_OFFSET;
        puf->e->end = puf->e->start + TEST_ARRAY_BUF_OFFSET + sizeof(u16);
 
-       array_size = unpack_array(puf->e, name);
-
+       KUNIT_EXPECT_EQ(test, unpack_array(puf->e, name, &array_size),
+                       TRI_TRUE);
        KUNIT_EXPECT_EQ(test, array_size, 0);
        KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
                puf->e->start + TEST_NAMED_ARRAY_BUF_OFFSET);