diff options
author | Kees Cook <kees@kernel.org> | 2025-05-02 15:41:20 -0700 |
---|---|---|
committer | Kees Cook <kees@kernel.org> | 2025-05-08 09:42:40 -0700 |
commit | f55aef7e0cc7583062cbda9becaa3b2ba3255fa3 (patch) | |
tree | e7355e3243396e6089fcb04c67ea52ff1232b6d7 | |
parent | b370f7eacdcfe1dd17bee00506296aa3fdc773cb (diff) |
lib/tests: randstruct: Add deep function pointer layout test
The recent fix in commit c2ea09b193d2 ("randstruct: gcc-plugin: Remove
bogus void member") has fixed another issue: it was not always detecting
composite structures made only of function pointers and structures of
function pointers. Add a test for this case, and break out the layout
tests since this issue is actually a problem for Clang as well[1].
Link: https://github.com/llvm/llvm-project/issues/138355 [1]
Link: https://lore.kernel.org/r/20250502224116.work.591-kees@kernel.org
Signed-off-by: Kees Cook <kees@kernel.org>
-rw-r--r-- | lib/tests/randstruct_kunit.c | 79 |
1 files changed, 65 insertions, 14 deletions
diff --git a/lib/tests/randstruct_kunit.c b/lib/tests/randstruct_kunit.c index c796c8fae263..f3a2d63c4cfb 100644 --- a/lib/tests/randstruct_kunit.c +++ b/lib/tests/randstruct_kunit.c @@ -56,7 +56,6 @@ struct randstruct_funcs_untouched { struct randstruct_funcs_shuffled { DO_MANY_MEMBERS(func_member) }; -#undef func_member #define func_body(x, ignored) \ static noinline size_t func_##x(int arg) \ @@ -103,9 +102,16 @@ struct contains_randstruct_shuffled { int after; }; -static void randstruct_layout(struct kunit *test) -{ - int mismatches; +struct contains_func_untouched { + struct randstruct_funcs_shuffled inner; + DO_MANY_MEMBERS(func_member) +} __no_randomize_layout; + +struct contains_func_shuffled { + struct randstruct_funcs_shuffled inner; + DO_MANY_MEMBERS(func_member) +}; +#undef func_member #define check_mismatch(x, untouched, shuffled) \ if (offsetof(untouched, x) != offsetof(shuffled, x)) \ @@ -114,24 +120,66 @@ static void randstruct_layout(struct kunit *test) offsetof(shuffled, x), \ offsetof(untouched, x)); \ -#define check_pair(outcome, untouched, shuffled) \ +#define check_pair(outcome, untouched, shuffled, checker...) \ mismatches = 0; \ - DO_MANY_MEMBERS(check_mismatch, untouched, shuffled) \ + DO_MANY_MEMBERS(checker, untouched, shuffled) \ kunit_info(test, "Differing " #untouched " vs " #shuffled " member positions: %d\n", \ mismatches); \ KUNIT_##outcome##_MSG(test, mismatches, 0, \ #untouched " vs " #shuffled " layouts: unlucky or broken?\n"); - check_pair(EXPECT_EQ, struct randstruct_untouched, struct randstruct_untouched) - check_pair(EXPECT_GT, struct randstruct_untouched, struct randstruct_shuffled) - check_pair(EXPECT_GT, struct randstruct_untouched, struct randstruct_funcs_shuffled) - check_pair(EXPECT_GT, struct randstruct_funcs_untouched, struct randstruct_funcs_shuffled) - check_pair(EXPECT_GT, struct randstruct_mixed_untouched, struct randstruct_mixed_shuffled) -#undef check_pair +static void randstruct_layout_same(struct kunit *test) +{ + int mismatches; -#undef check_mismatch + check_pair(EXPECT_EQ, struct randstruct_untouched, struct randstruct_untouched, + check_mismatch) + check_pair(EXPECT_GT, struct randstruct_untouched, struct randstruct_shuffled, + check_mismatch) +} + +static void randstruct_layout_mixed(struct kunit *test) +{ + int mismatches; + + check_pair(EXPECT_EQ, struct randstruct_mixed_untouched, struct randstruct_mixed_untouched, + check_mismatch) + check_pair(EXPECT_GT, struct randstruct_mixed_untouched, struct randstruct_mixed_shuffled, + check_mismatch) } +static void randstruct_layout_fptr(struct kunit *test) +{ + int mismatches; + + check_pair(EXPECT_EQ, struct randstruct_untouched, struct randstruct_untouched, + check_mismatch) + check_pair(EXPECT_GT, struct randstruct_untouched, struct randstruct_funcs_shuffled, + check_mismatch) + check_pair(EXPECT_GT, struct randstruct_funcs_untouched, struct randstruct_funcs_shuffled, + check_mismatch) +} + +#define check_mismatch_prefixed(x, prefix, untouched, shuffled) \ + check_mismatch(prefix.x, untouched, shuffled) + +static void randstruct_layout_fptr_deep(struct kunit *test) +{ + int mismatches; + + if (IS_ENABLED(CONFIG_CC_IS_CLANG)) + kunit_skip(test, "Clang randstruct misses inner functions: https://github.com/llvm/llvm-project/issues/138355"); + + check_pair(EXPECT_EQ, struct contains_func_untouched, struct contains_func_untouched, + check_mismatch_prefixed, inner) + + check_pair(EXPECT_GT, struct contains_func_untouched, struct contains_func_shuffled, + check_mismatch_prefixed, inner) +} + +#undef check_pair +#undef check_mismatch + #define check_mismatch(x, ignore) \ KUNIT_EXPECT_EQ_MSG(test, untouched->x, shuffled->x, \ "Mismatched member value in %s initializer\n", \ @@ -266,7 +314,10 @@ static int randstruct_test_init(struct kunit *test) } static struct kunit_case randstruct_test_cases[] = { - KUNIT_CASE(randstruct_layout), + KUNIT_CASE(randstruct_layout_same), + KUNIT_CASE(randstruct_layout_mixed), + KUNIT_CASE(randstruct_layout_fptr), + KUNIT_CASE(randstruct_layout_fptr_deep), KUNIT_CASE(randstruct_initializers), {} }; |