All of lore.kernel.org
 help / color / mirror / Atom feed
From: Kees Cook <kees@kernel.org>
To: Bill Wendling <morbo@google.com>
Cc: Kees Cook <kees@kernel.org>,
	"Gustavo A. R. Silva" <gustavoars@kernel.org>,
	Nathan Chancellor <nathan@kernel.org>,
	Nick Desaulniers <nick.desaulniers+lkml@gmail.com>,
	Justin Stitt <justinstitt@google.com>,
	linux-hardening@vger.kernel.org, llvm@lists.linux.dev,
	linux-kernel@vger.kernel.org
Subject: [PATCH] lib/tests: randstruct: Add deep function pointer layout test
Date: Fri,  2 May 2025 15:41:20 -0700	[thread overview]
Message-ID: <20250502224116.work.591-kees@kernel.org> (raw)

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


                 reply	other threads:[~2025-05-02 22:41 UTC|newest]

Thread overview: [no followups] expand[flat|nested]  mbox.gz  Atom feed

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20250502224116.work.591-kees@kernel.org \
    --to=kees@kernel.org \
    --cc=gustavoars@kernel.org \
    --cc=justinstitt@google.com \
    --cc=linux-hardening@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=llvm@lists.linux.dev \
    --cc=morbo@google.com \
    --cc=nathan@kernel.org \
    --cc=nick.desaulniers+lkml@gmail.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.