mirror of
https://github.com/torvalds/linux.git
synced 2025-08-15 14:11:42 +02:00
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>
This commit is contained in:
parent
b370f7eacd
commit
f55aef7e0c
1 changed files with 65 additions and 14 deletions
|
@ -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),
|
||||
{}
|
||||
};
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue