linux/security/apparmor/policy_unpack_test.c
Linus Torvalds 8b45c6c90a + Features
- improve debug printing
   - carry mediation check on label (optimization)
   - improve ability for compiler to optimize __begin_current_label_crit_section
   - transition for a linked list of rulesets to a vector of rulesets
   - don't hardcode profile signal, allow it to be set by policy
   - ability to mediate caps via the state machine instead of lut
   - Add Ubuntu af_unix mediation, put it behind new v9 abi
 
 + Cleanups
   - fix typos and spelling errors
   - cleanup kernel doc and code inconsistencies
   - remove redundant checks/code
   - remove unused variables
   - Use str_yes_no() helper function
   - mark tables static where appropriate
   - make all generated string array headers const char *const
   - refactor to doc semantics of file_perm checks
   - replace macro calls to network/socket fns with explicit calls
   - refactor/cleanup socket mediation code preparing for finer grained
     mediation of different network families
   - several updates to kernel doc comments
 
 + Bug fixes
   - apparmor: Fix incorrect profile->signal range check
   - idmap mount fixes
   - policy unpack unaligned access fixes
   - kfree_sensitive() where appropriate
   - fix oops when freeing policy
   - fix conflicting attachment resolution
   - fix exec table look-ups when stacking isn't first
   - fix exec auditing
   - mitigate userspace generating overly large xtables
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEE7cSDD705q2rFEEf7BS82cBjVw9gFAmiQmakACgkQBS82cBjV
 w9jvKBAAn/HblSPo112ycW/yjeonkyiCY56LvyeU1YWQ8m370xPqM3yK2SHcj2i1
 we1mx5beDxbH5xn7c6w0EtyoHP7FNhyHp7neG8/WaJ1JG4uxv9HvrDmEJeQEJn/3
 5AP1q2dZF9NwnKBfB5zjwZXBJzncWtYBoLUjYMbehWlQjufT2yElyM8YZZN8ziLE
 M5ILVX6UMGpBH/zuX5kN2idLcubnv5MvLo2IEt+/nGLPbed44w+mZTM5WOTbzPNq
 w8axyNdhGt9kcSGwWuM+48T4oLfwagoxIZ3RXSQ4eExk6I8ZaFXua8nknC9wENN4
 9vkzDSWAupQ+o1bLKVNMVkqvBIIqmvEWvwket/hiyxs3Y5PDckRqOgQ/4Wbmgp9B
 KhLXxzIrF9PXkZ/rpMzloxnvDtMwoSScDShhW4TCRCmpDo/GwPwoPIpgbnc3kTq0
 poomca9KZ7YEnX/90Bh92Duo5OBDOHYlbWVE7EWX01htcxExQJt47JK48C25cY5p
 /cVDVepoz7EnKjB7mm9k6K1gYGvDeu3W1whRZNEK74AQJ7p+CrBoU+WjeMmZqP5V
 s47cLF17hbnw4ZvfsxQDkPgSOP1kuJIVlwFV2lPQk5hDcT6V0kZtqUzczKJSqeJb
 CGOkKvM7ao/7Cn8pmDNG1ZuPl/HuJ6wjlxt7SVt4/3rzLFzwglo=
 =Djjn
 -----END PGP SIGNATURE-----

Merge tag 'apparmor-pr-2025-08-04' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor

Pull apparmor updates from John Johansen:
 "This has one major feature, it pulls in a cleaned up version of
  af_unix mediation that Ubuntu has been carrying for years. It is
  placed behind a new abi to ensure that it does cause policy
  regressions. With pulling in the af_unix mediation there have been
  cleanups and some refactoring of network socket mediation. This
  accounts for the majority of the changes in the diff.

  In addition there are a few improvements providing minor code
  optimizations. several code cleanups, and bug fixes.

  Features:
   - improve debug printing
   - carry mediation check on label (optimization)
   - improve ability for compiler to optimize
     __begin_current_label_crit_section
   - transition for a linked list of rulesets to a vector of rulesets
   - don't hardcode profile signal, allow it to be set by policy
   - ability to mediate caps via the state machine instead of lut
   - Add Ubuntu af_unix mediation, put it behind new v9 abi

  Cleanups:
   - fix typos and spelling errors
   - cleanup kernel doc and code inconsistencies
   - remove redundant checks/code
   - remove unused variables
   - Use str_yes_no() helper function
   - mark tables static where appropriate
   - make all generated string array headers const char *const
   - refactor to doc semantics of file_perm checks
   - replace macro calls to network/socket fns with explicit calls
   - refactor/cleanup socket mediation code preparing for finer grained
     mediation of different network families
   - several updates to kernel doc comments

  Bug fixes:
   - fix incorrect profile->signal range check
   - idmap mount fixes
   - policy unpack unaligned access fixes
   - kfree_sensitive() where appropriate
   - fix oops when freeing policy
   - fix conflicting attachment resolution
   - fix exec table look-ups when stacking isn't first
   - fix exec auditing
   - mitigate userspace generating overly large xtables"

* tag 'apparmor-pr-2025-08-04' of git://git.kernel.org/pub/scm/linux/kernel/git/jj/linux-apparmor: (60 commits)
  apparmor: fix: oops when trying to free null ruleset
  apparmor: fix Regression on linux-next (next-20250721)
  apparmor: fix test error: WARNING in apparmor_unix_stream_connect
  apparmor: Remove the unused variable rules
  apparmor: fix: accept2 being specifie even when permission table is presnt
  apparmor: transition from a list of rules to a vector of rules
  apparmor: fix documentation mismatches in val_mask_to_str and socket functions
  apparmor: remove redundant perms.allow MAY_EXEC bitflag set
  apparmor: fix kernel doc warnings for kernel test robot
  apparmor: Fix unaligned memory accesses in KUnit test
  apparmor: Fix 8-byte alignment for initial dfa blob streams
  apparmor: shift uid when mediating af_unix in userns
  apparmor: shift ouid when mediating hard links in userns
  apparmor: make sure unix socket labeling is correctly updated.
  apparmor: fix regression in fs based unix sockets when using old abi
  apparmor: fix AA_DEBUG_LABEL()
  apparmor: fix af_unix auditing to include all address information
  apparmor: Remove use of the double lock
  apparmor: update kernel doc comments for xxx_label_crit_section
  apparmor: make __begin_current_label_crit_section() indicate whether put is needed
  ...
2025-08-04 08:17:28 -07:00

616 lines
18 KiB
C

// SPDX-License-Identifier: GPL-2.0-only
/*
* KUnit tests for AppArmor's policy unpack.
*/
#include <kunit/test.h>
#include <kunit/visibility.h>
#include "include/policy.h"
#include "include/policy_unpack.h"
#include <linux/unaligned.h>
#define TEST_STRING_NAME "TEST_STRING"
#define TEST_STRING_DATA "testing"
#define TEST_STRING_BUF_OFFSET \
(3 + strlen(TEST_STRING_NAME) + 1)
#define TEST_U32_NAME "U32_TEST"
#define TEST_U32_DATA ((u32)0x01020304)
#define TEST_NAMED_U32_BUF_OFFSET \
(TEST_STRING_BUF_OFFSET + 3 + strlen(TEST_STRING_DATA) + 1)
#define TEST_U32_BUF_OFFSET \
(TEST_NAMED_U32_BUF_OFFSET + 3 + strlen(TEST_U32_NAME) + 1)
#define TEST_U16_OFFSET (TEST_U32_BUF_OFFSET + 3)
#define TEST_U16_DATA ((u16)(TEST_U32_DATA >> 16))
#define TEST_U64_NAME "U64_TEST"
#define TEST_U64_DATA ((u64)0x0102030405060708)
#define TEST_NAMED_U64_BUF_OFFSET (TEST_U32_BUF_OFFSET + sizeof(u32) + 1)
#define TEST_U64_BUF_OFFSET \
(TEST_NAMED_U64_BUF_OFFSET + 3 + strlen(TEST_U64_NAME) + 1)
#define TEST_BLOB_NAME "BLOB_TEST"
#define TEST_BLOB_DATA "\xde\xad\x00\xbe\xef"
#define TEST_BLOB_DATA_SIZE (ARRAY_SIZE(TEST_BLOB_DATA))
#define TEST_NAMED_BLOB_BUF_OFFSET (TEST_U64_BUF_OFFSET + sizeof(u64) + 1)
#define TEST_BLOB_BUF_OFFSET \
(TEST_NAMED_BLOB_BUF_OFFSET + 3 + strlen(TEST_BLOB_NAME) + 1)
#define TEST_ARRAY_NAME "ARRAY_TEST"
#define TEST_ARRAY_SIZE 16
#define TEST_NAMED_ARRAY_BUF_OFFSET \
(TEST_BLOB_BUF_OFFSET + 5 + TEST_BLOB_DATA_SIZE)
#define TEST_ARRAY_BUF_OFFSET \
(TEST_NAMED_ARRAY_BUF_OFFSET + 3 + strlen(TEST_ARRAY_NAME) + 1)
MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
struct policy_unpack_fixture {
struct aa_ext *e;
size_t e_size;
};
static struct aa_ext *build_aa_ext_struct(struct policy_unpack_fixture *puf,
struct kunit *test, size_t buf_size)
{
char *buf;
struct aa_ext *e;
buf = kunit_kzalloc(test, buf_size, GFP_USER);
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, buf);
e = kunit_kmalloc(test, sizeof(*e), GFP_USER);
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, e);
e->start = buf;
e->end = e->start + buf_size;
e->pos = e->start;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_STRING_NAME) + 1;
strscpy(buf + 3, TEST_STRING_NAME, e->end - (void *)(buf + 3));
buf = e->start + TEST_STRING_BUF_OFFSET;
*buf = AA_STRING;
*(buf + 1) = strlen(TEST_STRING_DATA) + 1;
strscpy(buf + 3, TEST_STRING_DATA, e->end - (void *)(buf + 3));
buf = e->start + TEST_NAMED_U32_BUF_OFFSET;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_U32_NAME) + 1;
strscpy(buf + 3, TEST_U32_NAME, e->end - (void *)(buf + 3));
*(buf + 3 + strlen(TEST_U32_NAME) + 1) = AA_U32;
put_unaligned_le32(TEST_U32_DATA, buf + 3 + strlen(TEST_U32_NAME) + 2);
buf = e->start + TEST_NAMED_U64_BUF_OFFSET;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_U64_NAME) + 1;
strscpy(buf + 3, TEST_U64_NAME, e->end - (void *)(buf + 3));
*(buf + 3 + strlen(TEST_U64_NAME) + 1) = AA_U64;
*((__le64 *)(buf + 3 + strlen(TEST_U64_NAME) + 2)) = cpu_to_le64(TEST_U64_DATA);
buf = e->start + TEST_NAMED_BLOB_BUF_OFFSET;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_BLOB_NAME) + 1;
strscpy(buf + 3, TEST_BLOB_NAME, e->end - (void *)(buf + 3));
*(buf + 3 + strlen(TEST_BLOB_NAME) + 1) = AA_BLOB;
*(buf + 3 + strlen(TEST_BLOB_NAME) + 2) = TEST_BLOB_DATA_SIZE;
memcpy(buf + 3 + strlen(TEST_BLOB_NAME) + 6,
TEST_BLOB_DATA, TEST_BLOB_DATA_SIZE);
buf = e->start + TEST_NAMED_ARRAY_BUF_OFFSET;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_ARRAY_NAME) + 1;
strscpy(buf + 3, TEST_ARRAY_NAME, e->end - (void *)(buf + 3));
*(buf + 3 + strlen(TEST_ARRAY_NAME) + 1) = AA_ARRAY;
put_unaligned_le16(TEST_ARRAY_SIZE, buf + 3 + strlen(TEST_ARRAY_NAME) + 2);
return e;
}
static int policy_unpack_test_init(struct kunit *test)
{
size_t e_size = TEST_ARRAY_BUF_OFFSET + sizeof(u16) + 1;
struct policy_unpack_fixture *puf;
puf = kunit_kmalloc(test, sizeof(*puf), GFP_USER);
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, puf);
puf->e_size = e_size;
puf->e = build_aa_ext_struct(puf, test, e_size);
test->priv = puf;
return 0;
}
static void policy_unpack_test_inbounds_when_inbounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
KUNIT_EXPECT_TRUE(test, aa_inbounds(puf->e, 0));
KUNIT_EXPECT_TRUE(test, aa_inbounds(puf->e, puf->e_size / 2));
KUNIT_EXPECT_TRUE(test, aa_inbounds(puf->e, puf->e_size));
}
static void policy_unpack_test_inbounds_when_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
KUNIT_EXPECT_FALSE(test, aa_inbounds(puf->e, puf->e_size + 1));
}
static void policy_unpack_test_unpack_array_with_null_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
u16 array_size = 0;
puf->e->pos += TEST_ARRAY_BUF_OFFSET;
KUNIT_EXPECT_TRUE(test, aa_unpack_array(puf->e, NULL, &array_size));
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);
}
static void policy_unpack_test_unpack_array_with_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char name[] = TEST_ARRAY_NAME;
u16 array_size = 0;
puf->e->pos += TEST_NAMED_ARRAY_BUF_OFFSET;
KUNIT_EXPECT_TRUE(test, aa_unpack_array(puf->e, name, &array_size));
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);
}
static void policy_unpack_test_unpack_array_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char name[] = TEST_ARRAY_NAME;
u16 array_size;
puf->e->pos += TEST_NAMED_ARRAY_BUF_OFFSET;
puf->e->end = puf->e->start + TEST_ARRAY_BUF_OFFSET + sizeof(u16);
KUNIT_EXPECT_FALSE(test, aa_unpack_array(puf->e, name, &array_size));
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_NAMED_ARRAY_BUF_OFFSET);
}
static void policy_unpack_test_unpack_blob_with_null_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *blob = NULL;
size_t size;
puf->e->pos += TEST_BLOB_BUF_OFFSET;
size = aa_unpack_blob(puf->e, &blob, NULL);
KUNIT_ASSERT_EQ(test, size, TEST_BLOB_DATA_SIZE);
KUNIT_EXPECT_TRUE(test,
memcmp(blob, TEST_BLOB_DATA, TEST_BLOB_DATA_SIZE) == 0);
}
static void policy_unpack_test_unpack_blob_with_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *blob = NULL;
size_t size;
puf->e->pos += TEST_NAMED_BLOB_BUF_OFFSET;
size = aa_unpack_blob(puf->e, &blob, TEST_BLOB_NAME);
KUNIT_ASSERT_EQ(test, size, TEST_BLOB_DATA_SIZE);
KUNIT_EXPECT_TRUE(test,
memcmp(blob, TEST_BLOB_DATA, TEST_BLOB_DATA_SIZE) == 0);
}
static void policy_unpack_test_unpack_blob_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *blob = NULL;
void *start;
int size;
puf->e->pos += TEST_NAMED_BLOB_BUF_OFFSET;
start = puf->e->pos;
puf->e->end = puf->e->start + TEST_BLOB_BUF_OFFSET
+ TEST_BLOB_DATA_SIZE - 1;
size = aa_unpack_blob(puf->e, &blob, TEST_BLOB_NAME);
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start);
}
static void policy_unpack_test_unpack_str_with_null_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char *string = NULL;
size_t size;
puf->e->pos += TEST_STRING_BUF_OFFSET;
size = aa_unpack_str(puf->e, &string, NULL);
KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1);
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
}
static void policy_unpack_test_unpack_str_with_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char *string = NULL;
size_t size;
size = aa_unpack_str(puf->e, &string, TEST_STRING_NAME);
KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1);
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
}
static void policy_unpack_test_unpack_str_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char *string = NULL;
void *start = puf->e->pos;
int size;
puf->e->end = puf->e->pos + TEST_STRING_BUF_OFFSET
+ strlen(TEST_STRING_DATA) - 1;
size = aa_unpack_str(puf->e, &string, TEST_STRING_NAME);
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start);
}
static void policy_unpack_test_unpack_strdup_with_null_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *string = NULL;
size_t size;
puf->e->pos += TEST_STRING_BUF_OFFSET;
size = aa_unpack_strdup(puf->e, &string, NULL);
KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1);
KUNIT_EXPECT_FALSE(test,
((uintptr_t)puf->e->start <= (uintptr_t)string)
&& ((uintptr_t)string <= (uintptr_t)puf->e->end));
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
kfree(string);
}
static void policy_unpack_test_unpack_strdup_with_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *string = NULL;
size_t size;
size = aa_unpack_strdup(puf->e, &string, TEST_STRING_NAME);
KUNIT_EXPECT_EQ(test, size, strlen(TEST_STRING_DATA) + 1);
KUNIT_EXPECT_FALSE(test,
((uintptr_t)puf->e->start <= (uintptr_t)string)
&& ((uintptr_t)string <= (uintptr_t)puf->e->end));
KUNIT_EXPECT_STREQ(test, string, TEST_STRING_DATA);
kfree(string);
}
static void policy_unpack_test_unpack_strdup_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
void *start = puf->e->pos;
char *string = NULL;
int size;
puf->e->end = puf->e->pos + TEST_STRING_BUF_OFFSET
+ strlen(TEST_STRING_DATA) - 1;
size = aa_unpack_strdup(puf->e, &string, TEST_STRING_NAME);
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_NULL(test, string);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start);
kfree(string);
}
static void policy_unpack_test_unpack_nameX_with_null_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
bool success;
puf->e->pos += TEST_U32_BUF_OFFSET;
success = aa_unpack_nameX(puf->e, AA_U32, NULL);
KUNIT_EXPECT_TRUE(test, success);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_U32_BUF_OFFSET + 1);
}
static void policy_unpack_test_unpack_nameX_with_wrong_code(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
bool success;
puf->e->pos += TEST_U32_BUF_OFFSET;
success = aa_unpack_nameX(puf->e, AA_BLOB, NULL);
KUNIT_EXPECT_FALSE(test, success);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_U32_BUF_OFFSET);
}
static void policy_unpack_test_unpack_nameX_with_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char name[] = TEST_U32_NAME;
bool success;
puf->e->pos += TEST_NAMED_U32_BUF_OFFSET;
success = aa_unpack_nameX(puf->e, AA_U32, name);
KUNIT_EXPECT_TRUE(test, success);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_U32_BUF_OFFSET + 1);
}
static void policy_unpack_test_unpack_nameX_with_wrong_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
static const char name[] = "12345678";
bool success;
puf->e->pos += TEST_NAMED_U32_BUF_OFFSET;
success = aa_unpack_nameX(puf->e, AA_U32, name);
KUNIT_EXPECT_FALSE(test, success);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_NAMED_U32_BUF_OFFSET);
}
static void policy_unpack_test_unpack_u16_chunk_basic(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *chunk = NULL;
size_t size;
puf->e->pos += TEST_U16_OFFSET;
/*
* WARNING: For unit testing purposes, we're pushing puf->e->end past
* the end of the allocated memory. Doing anything other than comparing
* memory addresses is dangerous.
*/
puf->e->end += TEST_U16_DATA;
size = aa_unpack_u16_chunk(puf->e, &chunk);
KUNIT_EXPECT_PTR_EQ(test, chunk,
puf->e->start + TEST_U16_OFFSET + 2);
KUNIT_EXPECT_EQ(test, size, TEST_U16_DATA);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, (chunk + TEST_U16_DATA));
}
static void policy_unpack_test_unpack_u16_chunk_out_of_bounds_1(
struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *chunk = NULL;
size_t size;
puf->e->pos = puf->e->end - 1;
size = aa_unpack_u16_chunk(puf->e, &chunk);
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_NULL(test, chunk);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, puf->e->end - 1);
}
static void policy_unpack_test_unpack_u16_chunk_out_of_bounds_2(
struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
char *chunk = NULL;
size_t size;
puf->e->pos += TEST_U16_OFFSET;
/*
* WARNING: For unit testing purposes, we're pushing puf->e->end past
* the end of the allocated memory. Doing anything other than comparing
* memory addresses is dangerous.
*/
puf->e->end = puf->e->pos + TEST_U16_DATA - 1;
size = aa_unpack_u16_chunk(puf->e, &chunk);
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_NULL(test, chunk);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, puf->e->start + TEST_U16_OFFSET);
}
static void policy_unpack_test_unpack_u32_with_null_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
bool success;
u32 data = 0;
puf->e->pos += TEST_U32_BUF_OFFSET;
success = aa_unpack_u32(puf->e, &data, NULL);
KUNIT_EXPECT_TRUE(test, success);
KUNIT_EXPECT_EQ(test, data, TEST_U32_DATA);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_U32_BUF_OFFSET + sizeof(u32) + 1);
}
static void policy_unpack_test_unpack_u32_with_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char name[] = TEST_U32_NAME;
bool success;
u32 data = 0;
puf->e->pos += TEST_NAMED_U32_BUF_OFFSET;
success = aa_unpack_u32(puf->e, &data, name);
KUNIT_EXPECT_TRUE(test, success);
KUNIT_EXPECT_EQ(test, data, TEST_U32_DATA);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_U32_BUF_OFFSET + sizeof(u32) + 1);
}
static void policy_unpack_test_unpack_u32_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char name[] = TEST_U32_NAME;
bool success;
u32 data = 0;
puf->e->pos += TEST_NAMED_U32_BUF_OFFSET;
puf->e->end = puf->e->start + TEST_U32_BUF_OFFSET + sizeof(u32);
success = aa_unpack_u32(puf->e, &data, name);
KUNIT_EXPECT_FALSE(test, success);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_NAMED_U32_BUF_OFFSET);
}
static void policy_unpack_test_unpack_u64_with_null_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
bool success;
u64 data = 0;
puf->e->pos += TEST_U64_BUF_OFFSET;
success = aa_unpack_u64(puf->e, &data, NULL);
KUNIT_EXPECT_TRUE(test, success);
KUNIT_EXPECT_EQ(test, data, TEST_U64_DATA);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_U64_BUF_OFFSET + sizeof(u64) + 1);
}
static void policy_unpack_test_unpack_u64_with_name(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char name[] = TEST_U64_NAME;
bool success;
u64 data = 0;
puf->e->pos += TEST_NAMED_U64_BUF_OFFSET;
success = aa_unpack_u64(puf->e, &data, name);
KUNIT_EXPECT_TRUE(test, success);
KUNIT_EXPECT_EQ(test, data, TEST_U64_DATA);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_U64_BUF_OFFSET + sizeof(u64) + 1);
}
static void policy_unpack_test_unpack_u64_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
const char name[] = TEST_U64_NAME;
bool success;
u64 data = 0;
puf->e->pos += TEST_NAMED_U64_BUF_OFFSET;
puf->e->end = puf->e->start + TEST_U64_BUF_OFFSET + sizeof(u64);
success = aa_unpack_u64(puf->e, &data, name);
KUNIT_EXPECT_FALSE(test, success);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos,
puf->e->start + TEST_NAMED_U64_BUF_OFFSET);
}
static void policy_unpack_test_unpack_X_code_match(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
bool success = aa_unpack_X(puf->e, AA_NAME);
KUNIT_EXPECT_TRUE(test, success);
KUNIT_EXPECT_TRUE(test, puf->e->pos == puf->e->start + 1);
}
static void policy_unpack_test_unpack_X_code_mismatch(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
bool success = aa_unpack_X(puf->e, AA_STRING);
KUNIT_EXPECT_FALSE(test, success);
KUNIT_EXPECT_TRUE(test, puf->e->pos == puf->e->start);
}
static void policy_unpack_test_unpack_X_out_of_bounds(struct kunit *test)
{
struct policy_unpack_fixture *puf = test->priv;
bool success;
puf->e->pos = puf->e->end;
success = aa_unpack_X(puf->e, AA_NAME);
KUNIT_EXPECT_FALSE(test, success);
}
static struct kunit_case apparmor_policy_unpack_test_cases[] = {
KUNIT_CASE(policy_unpack_test_inbounds_when_inbounds),
KUNIT_CASE(policy_unpack_test_inbounds_when_out_of_bounds),
KUNIT_CASE(policy_unpack_test_unpack_array_with_null_name),
KUNIT_CASE(policy_unpack_test_unpack_array_with_name),
KUNIT_CASE(policy_unpack_test_unpack_array_out_of_bounds),
KUNIT_CASE(policy_unpack_test_unpack_blob_with_null_name),
KUNIT_CASE(policy_unpack_test_unpack_blob_with_name),
KUNIT_CASE(policy_unpack_test_unpack_blob_out_of_bounds),
KUNIT_CASE(policy_unpack_test_unpack_nameX_with_null_name),
KUNIT_CASE(policy_unpack_test_unpack_nameX_with_wrong_code),
KUNIT_CASE(policy_unpack_test_unpack_nameX_with_name),
KUNIT_CASE(policy_unpack_test_unpack_nameX_with_wrong_name),
KUNIT_CASE(policy_unpack_test_unpack_str_with_null_name),
KUNIT_CASE(policy_unpack_test_unpack_str_with_name),
KUNIT_CASE(policy_unpack_test_unpack_str_out_of_bounds),
KUNIT_CASE(policy_unpack_test_unpack_strdup_with_null_name),
KUNIT_CASE(policy_unpack_test_unpack_strdup_with_name),
KUNIT_CASE(policy_unpack_test_unpack_strdup_out_of_bounds),
KUNIT_CASE(policy_unpack_test_unpack_u16_chunk_basic),
KUNIT_CASE(policy_unpack_test_unpack_u16_chunk_out_of_bounds_1),
KUNIT_CASE(policy_unpack_test_unpack_u16_chunk_out_of_bounds_2),
KUNIT_CASE(policy_unpack_test_unpack_u32_with_null_name),
KUNIT_CASE(policy_unpack_test_unpack_u32_with_name),
KUNIT_CASE(policy_unpack_test_unpack_u32_out_of_bounds),
KUNIT_CASE(policy_unpack_test_unpack_u64_with_null_name),
KUNIT_CASE(policy_unpack_test_unpack_u64_with_name),
KUNIT_CASE(policy_unpack_test_unpack_u64_out_of_bounds),
KUNIT_CASE(policy_unpack_test_unpack_X_code_match),
KUNIT_CASE(policy_unpack_test_unpack_X_code_mismatch),
KUNIT_CASE(policy_unpack_test_unpack_X_out_of_bounds),
{},
};
static struct kunit_suite apparmor_policy_unpack_test_module = {
.name = "apparmor_policy_unpack",
.init = policy_unpack_test_init,
.test_cases = apparmor_policy_unpack_test_cases,
};
kunit_test_suite(apparmor_policy_unpack_test_module);
MODULE_DESCRIPTION("KUnit tests for AppArmor's policy unpack");
MODULE_LICENSE("GPL");