linux-kselftest-5.6-rc1-kunit

This kunit update for Linux 5.6-rc1 consists of:
 
 -- Support for building kunit as a module from Alan Maguire
 -- AppArmor KUnit tests for policy unpack from Mike Salvatore
 -----BEGIN PGP SIGNATURE-----
 
 iQIzBAABCgAdFiEEPZKym/RZuOCGeA/kCwJExA0NQxwFAl4xz/wACgkQCwJExA0N
 Qxyg2A//X0bnhN82oCchkTRW3GyGi5wTR2wGhoNzMZD0XUtCvn+4BlCSP20ttYdT
 beiLCiewcuEdvXRyEV9Kikvet/67ovbjA/ce6ZrR7TlIHo8esKcy19/nu1OTvtI1
 8eji1q7NSEV9iswz1ZoBAw+MTDHZfOI9qYY2UPcwjy7xWN84z2X1w+8UQ3EamOKd
 6BfbohsYuuTTHhA2k1aUzvQcHqNz0YdH4yvNQpdunJXLUI04TeGZA6Ug66u6kWEd
 1f5SSAu6r1vnU7DADrb1QwEDuIwL4KBuaMg2Rj5GLxTNp3wxmW9M2Dit+iN7+vNH
 TS31kZW6KgxC5XuGVPENJaWlDX5Hm+5W8uiRZLNXsxDy927u53RzwrSZw/FbdbB1
 HuPZZCzE1soWHdPIQz44HCCAg9XddypYlC1o4IYL1JkJknqG12ky4xgM8GRNCZAB
 oUW3Ax3Lcr0EJALO/kFd/uEbl79PdmDk8uPMU1jtLyx5cs70yC3fsT2GB+DbP802
 i/FxTtrOMGjU2OWcYfQcXapvZdgImf9nPsSZe3FJXjHfytNRbVZOZ2rHAMh03Keu
 EBthDs6ejm6OUSGUXjngE9NaQKXsNSQ1Qor+6FrGnT4IxUMzWenudqHH7/dgF7Fr
 fHlZGBilKMc/EYKb/6hj4kvEChrSIXj6TFknmI28I/epPiOr2gU=
 =AFO4
 -----END PGP SIGNATURE-----

Merge tag 'linux-kselftest-5.6-rc1-kunit' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest

Pull Kselftest kunit updates from Shuah Khan:
 "This kunit update consists of:

   - Support for building kunit as a module from Alan Maguire

   - AppArmor KUnit tests for policy unpack from Mike Salvatore"

* tag 'linux-kselftest-5.6-rc1-kunit' of git://git.kernel.org/pub/scm/linux/kernel/git/shuah/linux-kselftest:
  kunit: building kunit as a module breaks allmodconfig
  kunit: update documentation to describe module-based build
  kunit: allow kunit to be loaded as a module
  kunit: remove timeout dependence on sysctl_hung_task_timeout_seconds
  kunit: allow kunit tests to be loaded as a module
  kunit: hide unexported try-catch interface in try-catch-impl.h
  kunit: move string-stream.h to lib/kunit
  apparmor: add AppArmor KUnit tests for policy unpack
This commit is contained in:
Linus Torvalds 2020-01-29 15:25:34 -08:00
commit 08a3ef8f6b
28 changed files with 788 additions and 74 deletions

View File

@ -29,7 +29,8 @@ Yes, well, mostly.
For the most part, the KUnit core framework (what you use to write the tests)
can compile to any architecture; it compiles like just another part of the
kernel and runs when the kernel boots. However, there is some infrastructure,
kernel and runs when the kernel boots, or when built as a module, when the
module is loaded. However, there is some infrastructure,
like the KUnit Wrapper (``tools/testing/kunit/kunit.py``) that does not support
other architectures.

View File

@ -49,6 +49,9 @@ to a standalone program that can be run like any other program directly inside
of a host operating system; to be clear, it does not require any virtualization
support; it is just a regular program.
Alternatively, kunit and kunit tests can be built as modules and tests will
run when the test module is loaded.
KUnit is fast. Excluding build time, from invocation to completion KUnit can run
several dozen tests in only 10 to 20 seconds; this might not sound like a big
deal to some people, but having such fast and easy to run tests fundamentally

View File

@ -539,6 +539,22 @@ Interspersed in the kernel logs you might see the following:
Congratulations, you just ran a KUnit test on the x86 architecture!
In a similar manner, kunit and kunit tests can also be built as modules,
so if you wanted to run tests in this way you might add the following config
options to your ``.config``:
.. code-block:: none
CONFIG_KUNIT=m
CONFIG_KUNIT_EXAMPLE_TEST=m
Once the kernel is built and installed, a simple
.. code-block:: bash
modprobe example-test
...will run the tests.
Writing new tests for other architectures
-----------------------------------------

View File

@ -150,7 +150,7 @@ config DEBUG_TEST_DRIVER_REMOVE
config PM_QOS_KUNIT_TEST
bool "KUnit Test for PM QoS features"
depends on KUNIT
depends on KUNIT=y
config HMEM_REPORTING
bool

View File

@ -114,4 +114,4 @@ static struct kunit_suite pm_qos_test_module = {
.name = "qos-kunit-test",
.test_cases = pm_qos_test_cases,
};
kunit_test_suite(pm_qos_test_module);
kunit_test_suites(&pm_qos_test_module);

View File

@ -109,7 +109,7 @@ config EXT4_DEBUG
echo 1 > /sys/module/ext4/parameters/mballoc_debug
config EXT4_KUNIT_TESTS
bool "KUnit tests for ext4"
tristate "KUnit tests for ext4"
select EXT4_FS
depends on KUNIT
help

View File

@ -13,5 +13,6 @@ ext4-y := balloc.o bitmap.o block_validity.o dir.o ext4_jbd2.o extents.o \
ext4-$(CONFIG_EXT4_FS_POSIX_ACL) += acl.o
ext4-$(CONFIG_EXT4_FS_SECURITY) += xattr_security.o
ext4-$(CONFIG_EXT4_KUNIT_TESTS) += inode-test.o
ext4-inode-test-objs += inode-test.o
obj-$(CONFIG_EXT4_KUNIT_TESTS) += ext4-inode-test.o
ext4-$(CONFIG_FS_VERITY) += verity.o

View File

@ -269,4 +269,6 @@ static struct kunit_suite ext4_inode_test_suite = {
.test_cases = ext4_inode_test_cases,
};
kunit_test_suite(ext4_inode_test_suite);
kunit_test_suites(&ext4_inode_test_suite);
MODULE_LICENSE("GPL v2");

View File

@ -9,10 +9,11 @@
#ifndef _KUNIT_ASSERT_H
#define _KUNIT_ASSERT_H
#include <kunit/string-stream.h>
#include <linux/err.h>
#include <linux/kernel.h>
struct kunit;
struct string_stream;
/**
* enum kunit_assert_type - Type of expectation/assertion.

View File

@ -12,6 +12,7 @@
#include <kunit/assert.h>
#include <kunit/try-catch.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/types.h>
@ -197,31 +198,47 @@ void kunit_init_test(struct kunit *test, const char *name);
int kunit_run_tests(struct kunit_suite *suite);
/**
* kunit_test_suite() - used to register a &struct kunit_suite with KUnit.
* kunit_test_suites() - used to register one or more &struct kunit_suite
* with KUnit.
*
* @suite: a statically allocated &struct kunit_suite.
* @suites: a statically allocated list of &struct kunit_suite.
*
* Registers @suite with the test framework. See &struct kunit_suite for
* Registers @suites with the test framework. See &struct kunit_suite for
* more information.
*
* NOTE: Currently KUnit tests are all run as late_initcalls; this means
* When builtin, KUnit tests are all run as late_initcalls; this means
* that they cannot test anything where tests must run at a different init
* phase. One significant restriction resulting from this is that KUnit
* cannot reliably test anything that is initialize in the late_init phase;
* another is that KUnit is useless to test things that need to be run in
* an earlier init phase.
*
* An alternative is to build the tests as a module. Because modules
* do not support multiple late_initcall()s, we need to initialize an
* array of suites for a module.
*
* TODO(brendanhiggins@google.com): Don't run all KUnit tests as
* late_initcalls. I have some future work planned to dispatch all KUnit
* tests from the same place, and at the very least to do so after
* everything else is definitely initialized.
*/
#define kunit_test_suite(suite) \
static int kunit_suite_init##suite(void) \
{ \
return kunit_run_tests(&suite); \
} \
late_initcall(kunit_suite_init##suite)
#define kunit_test_suites(...) \
static struct kunit_suite *suites[] = { __VA_ARGS__, NULL}; \
static int kunit_test_suites_init(void) \
{ \
unsigned int i; \
for (i = 0; suites[i] != NULL; i++) \
kunit_run_tests(suites[i]); \
return 0; \
} \
late_initcall(kunit_test_suites_init); \
static void __exit kunit_test_suites_exit(void) \
{ \
return; \
} \
module_exit(kunit_test_suites_exit)
#define kunit_test_suite(suite) kunit_test_suites(&suite)
/*
* Like kunit_alloc_resource() below, but returns the struct kunit_resource

View File

@ -53,11 +53,6 @@ struct kunit_try_catch {
void *context;
};
void kunit_try_catch_init(struct kunit_try_catch *try_catch,
struct kunit *test,
kunit_try_catch_func_t try,
kunit_try_catch_func_t catch);
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context);
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch);
@ -67,9 +62,4 @@ static inline int kunit_try_catch_get_result(struct kunit_try_catch *try_catch)
return try_catch->try_result;
}
/*
* Exposed for testing only.
*/
void kunit_generic_try_catch_init(struct kunit_try_catch *try_catch);
#endif /* _KUNIT_TRY_CATCH_H */

View File

@ -389,4 +389,6 @@ static struct kunit_suite sysctl_test_suite = {
.test_cases = sysctl_test_cases,
};
kunit_test_suite(sysctl_test_suite);
kunit_test_suites(&sysctl_test_suite);
MODULE_LICENSE("GPL v2");

View File

@ -2025,7 +2025,7 @@ config TEST_SYSCTL
If unsure, say N.
config SYSCTL_KUNIT_TEST
bool "KUnit test for sysctl"
tristate "KUnit test for sysctl"
depends on KUNIT
help
This builds the proc sysctl unit test, which runs on boot.
@ -2036,7 +2036,7 @@ config SYSCTL_KUNIT_TEST
If unsure, say N.
config LIST_KUNIT_TEST
bool "KUnit Test for Kernel Linked-list structures"
tristate "KUnit Test for Kernel Linked-list structures"
depends on KUNIT
help
This builds the linked list KUnit test suite.

View File

@ -3,7 +3,7 @@
#
menuconfig KUNIT
bool "KUnit - Enable support for unit tests"
tristate "KUnit - Enable support for unit tests"
help
Enables support for kernel unit tests (KUnit), a lightweight unit
testing and mocking framework for the Linux kernel. These tests are
@ -15,7 +15,7 @@ menuconfig KUNIT
if KUNIT
config KUNIT_TEST
bool "KUnit test for KUnit"
tristate "KUnit test for KUnit"
help
Enables the unit tests for the KUnit test framework. These tests test
the KUnit test framework itself; the tests are both written using
@ -24,7 +24,7 @@ config KUNIT_TEST
expected.
config KUNIT_EXAMPLE_TEST
bool "Example test for KUnit"
tristate "Example test for KUnit"
help
Enables an example unit test that illustrates some of the basic
features of KUnit. This test only exists to help new users understand

View File

@ -1,9 +1,15 @@
obj-$(CONFIG_KUNIT) += test.o \
obj-$(CONFIG_KUNIT) += kunit.o
kunit-objs += test.o \
string-stream.o \
assert.o \
try-catch.o
obj-$(CONFIG_KUNIT_TEST) += test-test.o \
string-stream-test.o
obj-$(CONFIG_KUNIT_TEST) += kunit-test.o
obj-$(CONFIG_KUNIT_EXAMPLE_TEST) += example-test.o
# string-stream-test compiles built-in only.
ifeq ($(CONFIG_KUNIT_TEST),y)
obj-$(CONFIG_KUNIT_TEST) += string-stream-test.o
endif
obj-$(CONFIG_KUNIT_EXAMPLE_TEST) += kunit-example-test.o

View File

@ -7,6 +7,8 @@
*/
#include <kunit/assert.h>
#include "string-stream.h"
void kunit_base_assert_format(const struct kunit_assert *assert,
struct string_stream *stream)
{
@ -24,6 +26,7 @@ void kunit_base_assert_format(const struct kunit_assert *assert,
string_stream_add(stream, "%s FAILED at %s:%d\n",
expect_or_assert, assert->file, assert->line);
}
EXPORT_SYMBOL_GPL(kunit_base_assert_format);
void kunit_assert_print_msg(const struct kunit_assert *assert,
struct string_stream *stream)
@ -31,6 +34,7 @@ void kunit_assert_print_msg(const struct kunit_assert *assert,
if (assert->message.fmt)
string_stream_add(stream, "\n%pV", &assert->message);
}
EXPORT_SYMBOL_GPL(kunit_assert_print_msg);
void kunit_fail_assert_format(const struct kunit_assert *assert,
struct string_stream *stream)
@ -38,6 +42,7 @@ void kunit_fail_assert_format(const struct kunit_assert *assert,
kunit_base_assert_format(assert, stream);
string_stream_add(stream, "%pV", &assert->message);
}
EXPORT_SYMBOL_GPL(kunit_fail_assert_format);
void kunit_unary_assert_format(const struct kunit_assert *assert,
struct string_stream *stream)
@ -56,6 +61,7 @@ void kunit_unary_assert_format(const struct kunit_assert *assert,
unary_assert->condition);
kunit_assert_print_msg(assert, stream);
}
EXPORT_SYMBOL_GPL(kunit_unary_assert_format);
void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
struct string_stream *stream)
@ -76,6 +82,7 @@ void kunit_ptr_not_err_assert_format(const struct kunit_assert *assert,
}
kunit_assert_print_msg(assert, stream);
}
EXPORT_SYMBOL_GPL(kunit_ptr_not_err_assert_format);
void kunit_binary_assert_format(const struct kunit_assert *assert,
struct string_stream *stream)
@ -97,6 +104,7 @@ void kunit_binary_assert_format(const struct kunit_assert *assert,
binary_assert->right_value);
kunit_assert_print_msg(assert, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_assert_format);
void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
struct string_stream *stream)
@ -118,6 +126,7 @@ void kunit_binary_ptr_assert_format(const struct kunit_assert *assert,
binary_assert->right_value);
kunit_assert_print_msg(assert, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_ptr_assert_format);
void kunit_binary_str_assert_format(const struct kunit_assert *assert,
struct string_stream *stream)
@ -139,3 +148,4 @@ void kunit_binary_str_assert_format(const struct kunit_assert *assert,
binary_assert->right_value);
kunit_assert_print_msg(assert, stream);
}
EXPORT_SYMBOL_GPL(kunit_binary_str_assert_format);

View File

@ -85,4 +85,6 @@ static struct kunit_suite example_test_suite = {
* This registers the above test suite telling KUnit that this is a suite of
* tests that need to be run.
*/
kunit_test_suite(example_test_suite);
kunit_test_suites(&example_test_suite);
MODULE_LICENSE("GPL v2");

View File

@ -7,6 +7,8 @@
*/
#include <kunit/test.h>
#include "try-catch-impl.h"
struct kunit_try_catch_test_context {
struct kunit_try_catch *try_catch;
bool function_called;
@ -100,7 +102,6 @@ static struct kunit_suite kunit_try_catch_test_suite = {
.init = kunit_try_catch_test_init,
.test_cases = kunit_try_catch_test_cases,
};
kunit_test_suite(kunit_try_catch_test_suite);
/*
* Context for testing test managed resources
@ -328,4 +329,6 @@ static struct kunit_suite kunit_resource_test_suite = {
.exit = kunit_resource_test_exit,
.test_cases = kunit_resource_test_cases,
};
kunit_test_suite(kunit_resource_test_suite);
kunit_test_suites(&kunit_try_catch_test_suite, &kunit_resource_test_suite);
MODULE_LICENSE("GPL v2");

View File

@ -6,10 +6,11 @@
* Author: Brendan Higgins <brendanhiggins@google.com>
*/
#include <kunit/string-stream.h>
#include <kunit/test.h>
#include <linux/slab.h>
#include "string-stream.h"
static void string_stream_test_empty_on_creation(struct kunit *test)
{
struct string_stream *stream = alloc_string_stream(test, GFP_KERNEL);
@ -49,4 +50,4 @@ static struct kunit_suite string_stream_test_suite = {
.name = "string-stream-test",
.test_cases = string_stream_test_cases
};
kunit_test_suite(string_stream_test_suite);
kunit_test_suites(&string_stream_test_suite);

View File

@ -6,11 +6,12 @@
* Author: Brendan Higgins <brendanhiggins@google.com>
*/
#include <kunit/string-stream.h>
#include <kunit/test.h>
#include <linux/list.h>
#include <linux/slab.h>
#include "string-stream.h"
struct string_stream_fragment_alloc_context {
struct kunit *test;
int len;

View File

@ -7,10 +7,12 @@
*/
#include <kunit/test.h>
#include <kunit/try-catch.h>
#include <linux/kernel.h>
#include <linux/sched/debug.h>
#include "string-stream.h"
#include "try-catch-impl.h"
static void kunit_set_failure(struct kunit *test)
{
WRITE_ONCE(test->success, false);
@ -171,6 +173,7 @@ void kunit_do_assertion(struct kunit *test,
if (assert->type == KUNIT_ASSERTION)
kunit_abort(test);
}
EXPORT_SYMBOL_GPL(kunit_do_assertion);
void kunit_init_test(struct kunit *test, const char *name)
{
@ -179,6 +182,7 @@ void kunit_init_test(struct kunit *test, const char *name)
test->name = name;
test->success = true;
}
EXPORT_SYMBOL_GPL(kunit_init_test);
/*
* Initializes and runs test case. Does not clean up or do post validations.
@ -317,6 +321,7 @@ int kunit_run_tests(struct kunit_suite *suite)
return 0;
}
EXPORT_SYMBOL_GPL(kunit_run_tests);
struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
kunit_resource_init_t init,
@ -342,6 +347,7 @@ struct kunit_resource *kunit_alloc_and_get_resource(struct kunit *test,
return res;
}
EXPORT_SYMBOL_GPL(kunit_alloc_and_get_resource);
static void kunit_resource_free(struct kunit *test, struct kunit_resource *res)
{
@ -400,6 +406,7 @@ int kunit_resource_destroy(struct kunit *test,
kunit_resource_free(test, resource);
return 0;
}
EXPORT_SYMBOL_GPL(kunit_resource_destroy);
struct kunit_kmalloc_params {
size_t size;
@ -435,6 +442,7 @@ void *kunit_kmalloc(struct kunit *test, size_t size, gfp_t gfp)
gfp,
&params);
}
EXPORT_SYMBOL_GPL(kunit_kmalloc);
void kunit_kfree(struct kunit *test, const void *ptr)
{
@ -447,6 +455,7 @@ void kunit_kfree(struct kunit *test, const void *ptr)
WARN_ON(rc);
}
EXPORT_SYMBOL_GPL(kunit_kfree);
void kunit_cleanup(struct kunit *test)
{
@ -476,3 +485,17 @@ void kunit_cleanup(struct kunit *test)
kunit_resource_free(test, resource);
}
}
EXPORT_SYMBOL_GPL(kunit_cleanup);
static int __init kunit_init(void)
{
return 0;
}
late_initcall(kunit_init);
static void __exit kunit_exit(void)
{
}
module_exit(kunit_exit);
MODULE_LICENSE("GPL v2");

View File

@ -0,0 +1,27 @@
/* SPDX-License-Identifier: GPL-2.0 */
/*
* Internal kunit try catch implementation to be shared with tests.
*
* Copyright (C) 2019, Google LLC.
* Author: Brendan Higgins <brendanhiggins@google.com>
*/
#ifndef _KUNIT_TRY_CATCH_IMPL_H
#define _KUNIT_TRY_CATCH_IMPL_H
#include <kunit/try-catch.h>
#include <linux/types.h>
struct kunit;
static inline void kunit_try_catch_init(struct kunit_try_catch *try_catch,
struct kunit *test,
kunit_try_catch_func_t try,
kunit_try_catch_func_t catch)
{
try_catch->test = test;
try_catch->try = try;
try_catch->catch = catch;
}
#endif /* _KUNIT_TRY_CATCH_IMPL_H */

View File

@ -8,17 +8,18 @@
*/
#include <kunit/test.h>
#include <kunit/try-catch.h>
#include <linux/completion.h>
#include <linux/kernel.h>
#include <linux/kthread.h>
#include <linux/sched/sysctl.h>
#include "try-catch-impl.h"
void __noreturn kunit_try_catch_throw(struct kunit_try_catch *try_catch)
{
try_catch->try_result = -EFAULT;
complete_and_exit(try_catch->try_completion, -EFAULT);
}
EXPORT_SYMBOL_GPL(kunit_try_catch_throw);
static int kunit_generic_run_threadfn_adapter(void *data)
{
@ -31,8 +32,6 @@ static int kunit_generic_run_threadfn_adapter(void *data)
static unsigned long kunit_test_timeout(void)
{
unsigned long timeout_msecs;
/*
* TODO(brendanhiggins@google.com): We should probably have some type of
* variable timeout here. The only question is what that timeout value
@ -49,22 +48,11 @@ static unsigned long kunit_test_timeout(void)
*
* For more background on this topic, see:
* https://mike-bland.com/2011/11/01/small-medium-large.html
*
* If tests timeout due to exceeding sysctl_hung_task_timeout_secs,
* the task will be killed and an oops generated.
*/
if (sysctl_hung_task_timeout_secs) {
/*
* If sysctl_hung_task is active, just set the timeout to some
* value less than that.
*
* In regards to the above TODO, if we decide on variable
* timeouts, this logic will likely need to change.
*/
timeout_msecs = (sysctl_hung_task_timeout_secs - 1) *
MSEC_PER_SEC;
} else {
timeout_msecs = 300 * MSEC_PER_SEC; /* 5 min */
}
return timeout_msecs;
return 300 * MSEC_PER_SEC; /* 5 min */
}
void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
@ -106,13 +94,4 @@ void kunit_try_catch_run(struct kunit_try_catch *try_catch, void *context)
try_catch->catch(try_catch->context);
}
void kunit_try_catch_init(struct kunit_try_catch *try_catch,
struct kunit *test,
kunit_try_catch_func_t try,
kunit_try_catch_func_t catch)
{
try_catch->test = test;
try_catch->try = try;
try_catch->catch = catch;
}
EXPORT_SYMBOL_GPL(kunit_try_catch_run);

View File

@ -743,4 +743,6 @@ static struct kunit_suite list_test_module = {
.test_cases = list_test_cases,
};
kunit_test_suite(list_test_module);
kunit_test_suites(&list_test_module);
MODULE_LICENSE("GPL v2");

View File

@ -68,3 +68,19 @@ config SECURITY_APPARMOR_DEBUG_MESSAGES
Set the default value of the apparmor.debug kernel parameter.
When enabled, various debug messages will be logged to
the kernel message buffer.
config SECURITY_APPARMOR_KUNIT_TEST
bool "Build KUnit tests for policy_unpack.c"
depends on KUNIT=y && SECURITY_APPARMOR
help
This builds the AppArmor KUnit tests.
KUnit tests run during boot and output the results to the debug log
in TAP format (http://testanything.org/). Only useful for kernel devs
running KUnit test harness and are not for inclusion into a
production build.
For more information on KUnit and unit tests in general please refer
to the KUnit documentation in Documentation/dev-tools/kunit/.
If unsure, say N.

View File

@ -1228,3 +1228,7 @@ int aa_unpack(struct aa_loaddata *udata, struct list_head *lh,
return error;
}
#ifdef CONFIG_SECURITY_APPARMOR_KUNIT_TEST
#include "policy_unpack_test.c"
#endif /* CONFIG_SECURITY_APPARMOR_KUNIT_TEST */

View File

@ -0,0 +1,607 @@
// SPDX-License-Identifier: GPL-2.0-only
/*
* KUnit tests for AppArmor's policy unpack.
*/
#include <kunit/test.h>
#include "include/policy.h"
#include "include/policy_unpack.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)
struct policy_unpack_fixture {
struct aa_ext *e;
size_t e_size;
};
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;
strcpy(buf + 3, TEST_STRING_NAME);
buf = e->start + TEST_STRING_BUF_OFFSET;
*buf = AA_STRING;
*(buf + 1) = strlen(TEST_STRING_DATA) + 1;
strcpy(buf + 3, TEST_STRING_DATA);
buf = e->start + TEST_NAMED_U32_BUF_OFFSET;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_U32_NAME) + 1;
strcpy(buf + 3, TEST_U32_NAME);
*(buf + 3 + strlen(TEST_U32_NAME) + 1) = AA_U32;
*((u32 *)(buf + 3 + strlen(TEST_U32_NAME) + 2)) = TEST_U32_DATA;
buf = e->start + TEST_NAMED_U64_BUF_OFFSET;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_U64_NAME) + 1;
strcpy(buf + 3, TEST_U64_NAME);
*(buf + 3 + strlen(TEST_U64_NAME) + 1) = AA_U64;
*((u64 *)(buf + 3 + strlen(TEST_U64_NAME) + 2)) = TEST_U64_DATA;
buf = e->start + TEST_NAMED_BLOB_BUF_OFFSET;
*buf = AA_NAME;
*(buf + 1) = strlen(TEST_BLOB_NAME) + 1;
strcpy(buf + 3, TEST_BLOB_NAME);
*(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;
strcpy(buf + 3, TEST_ARRAY_NAME);
*(buf + 3 + strlen(TEST_ARRAY_NAME) + 1) = AA_ARRAY;
*((u16 *)(buf + 3 + strlen(TEST_ARRAY_NAME) + 2)) = TEST_ARRAY_SIZE;
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, inbounds(puf->e, 0));
KUNIT_EXPECT_TRUE(test, inbounds(puf->e, puf->e_size / 2));
KUNIT_EXPECT_TRUE(test, 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, 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;
puf->e->pos += TEST_ARRAY_BUF_OFFSET;
array_size = unpack_array(puf->e, NULL);
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;
puf->e->pos += TEST_NAMED_ARRAY_BUF_OFFSET;
array_size = unpack_array(puf->e, name);
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);
array_size = unpack_array(puf->e, name);
KUNIT_EXPECT_EQ(test, array_size, (u16)0);
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 = 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 = 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 = 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 = 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 = 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 = 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 = 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);
}
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 = 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);
}
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 = unpack_strdup(puf->e, &string, TEST_STRING_NAME);
KUNIT_EXPECT_EQ(test, size, 0);
KUNIT_EXPECT_PTR_EQ(test, string, (char *)NULL);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, start);
}
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 = 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 = 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 = 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 = 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 = unpack_u16_chunk(puf->e, &chunk);
KUNIT_EXPECT_PTR_EQ(test, (void *)chunk,
puf->e->start + TEST_U16_OFFSET + 2);
KUNIT_EXPECT_EQ(test, size, (size_t)TEST_U16_DATA);
KUNIT_EXPECT_PTR_EQ(test, puf->e->pos, (void *)(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 = unpack_u16_chunk(puf->e, &chunk);
KUNIT_EXPECT_EQ(test, size, (size_t)0);
KUNIT_EXPECT_PTR_EQ(test, chunk, (char *)NULL);
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 = unpack_u16_chunk(puf->e, &chunk);
KUNIT_EXPECT_EQ(test, size, (size_t)0);
KUNIT_EXPECT_PTR_EQ(test, chunk, (char *)NULL);
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;
puf->e->pos += TEST_U32_BUF_OFFSET;
success = 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;
puf->e->pos += TEST_NAMED_U32_BUF_OFFSET;
success = 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;
puf->e->pos += TEST_NAMED_U32_BUF_OFFSET;
puf->e->end = puf->e->start + TEST_U32_BUF_OFFSET + sizeof(u32);
success = 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;
puf->e->pos += TEST_U64_BUF_OFFSET;
success = 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;
puf->e->pos += TEST_NAMED_U64_BUF_OFFSET;
success = 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;
puf->e->pos += TEST_NAMED_U64_BUF_OFFSET;
puf->e->end = puf->e->start + TEST_U64_BUF_OFFSET + sizeof(u64);
success = 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 = 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 = 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 = 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);