[<prev] [next>] [day] [month] [year] [list]
Message-Id: <20250502224116.work.591-kees@kernel.org>
Date: Fri, 2 May 2025 15:41:20 -0700
From: Kees Cook <kees@...nel.org>
To: Bill Wendling <morbo@...gle.com>
Cc: Kees Cook <kees@...nel.org>,
"Gustavo A. R. Silva" <gustavoars@...nel.org>,
Nathan Chancellor <nathan@...nel.org>,
Nick Desaulniers <nick.desaulniers+lkml@...il.com>,
Justin Stitt <justinstitt@...gle.com>,
linux-hardening@...r.kernel.org,
llvm@...ts.linux.dev,
linux-kernel@...r.kernel.org
Subject: [PATCH] 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]
Signed-off-by: Kees Cook <kees@...nel.org>
---
Cc: Bill Wendling <morbo@...gle.com>
Cc: "Gustavo A. R. Silva" <gustavoars@...nel.org>
Cc: Nathan Chancellor <nathan@...nel.org>
Cc: Nick Desaulniers <nick.desaulniers+lkml@...il.com>
Cc: Justin Stitt <justinstitt@...gle.com>
Cc: <linux-hardening@...r.kernel.org>
Cc: <llvm@...ts.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
Powered by blists - more mailing lists