* [PATCH] lib/tests: randstruct: Add deep function pointer layout test
@ 2025-05-02 22:41 Kees Cook
0 siblings, 0 replies; only message in thread
From: Kees Cook @ 2025-05-02 22:41 UTC (permalink / raw)
To: Bill Wendling
Cc: Kees Cook, Gustavo A. R. Silva, Nathan Chancellor,
Nick Desaulniers, Justin Stitt, linux-hardening, llvm,
linux-kernel
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]
Signed-off-by: Kees Cook <kees@kernel.org>
---
Cc: Bill Wendling <morbo@google.com>
Cc: "Gustavo A. R. Silva" <gustavoars@kernel.org>
Cc: Nathan Chancellor <nathan@kernel.org>
Cc: Nick Desaulniers <nick.desaulniers+lkml@gmail.com>
Cc: Justin Stitt <justinstitt@google.com>
Cc: <linux-hardening@vger.kernel.org>
Cc: <llvm@lists.linux.dev>
---
lib/tests/randstruct_kunit.c | 79 +++++++++++++++++++++++++++++-------
1 file 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),
{}
};
--
2.34.1
^ permalink raw reply related [flat|nested] only message in thread
only message in thread, other threads:[~2025-05-02 22:41 UTC | newest]
Thread overview: (only message) (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2025-05-02 22:41 [PATCH] lib/tests: randstruct: Add deep function pointer layout test Kees Cook
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.