mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: Andrei Vagin <avagin@google.com>
To: Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>
Cc: linux-kernel@vger.kernel.org, criu@lists.linux.dev,
	 Borislav Petkov <bp@alien8.de>,
	Dave Hansen <dave.hansen@linux.intel.com>,
	x86@kernel.org,  Andrei Vagin <avagin@google.com>,
	"H. Peter Anvin" <hpa@zytor.com>,
	 "Chang S. Bae" <chang.seok.bae@intel.com>
Subject: [PATCH 5/5] selftests/x86: Add a consistency test for signal frames
Date: Tue, 26 May 2026 20:50:47 +0000	[thread overview]
Message-ID: <20260526205047.3339490-6-avagin@google.com> (raw)
In-Reply-To: <20260526205047.3339490-1-avagin@google.com>

Extend sigframe_portability test to include a consistency check.  Verify
that the kernel correctly rejects signal frames where the xstate_size is
too small for the enabled features in the xfeatures mask.

Refactor the test to use separate helpers for portability and
consistency test cases, each with its own signal handler.

Signed-off-by: Andrei Vagin <avagin@google.com>
---
 .../selftests/x86/sigframe_portability.c      | 106 +++++++++++++-----
 tools/testing/selftests/x86/xstate.h          |   5 +
 2 files changed, 81 insertions(+), 30 deletions(-)

diff --git a/tools/testing/selftests/x86/sigframe_portability.c b/tools/testing/selftests/x86/sigframe_portability.c
index 8888079a153a..a60aa4d20dd1 100644
--- a/tools/testing/selftests/x86/sigframe_portability.c
+++ b/tools/testing/selftests/x86/sigframe_portability.c
@@ -17,13 +17,14 @@
 #include "xstate.h"
 
 /*
- * This test verifies the portability of the signal frame.
- * It simulates a scenario where a signal frame is created on a system with
- * fewer xstate features and restored on a system with more features.
+ * This test verifies the portability and consistency of the signal frame.
+ * Portability: A frame created on a system with fewer features can be
+ *              restored on a system with more features.
+ * Consistency: The kernel rejects frames where xstate_size is insufficient
+ *              for the features enabled in xfeatures.
  */
 
 #define SIGFRAME_XSTATE_HDR_OFFSET	512
-
 #define XSTATE_SSE_ONLY_SIZE	(SIGFRAME_XSTATE_HDR_OFFSET + XSAVE_HDR_SIZE)
 #define XFEATURE_MASK_FPSSE	((1 << XFEATURE_FP) | (1 << XFEATURE_SSE))
 
@@ -55,7 +56,17 @@ static void check_avx_support(void)
 
 #define TEST_YMMH_VAL (0x5656565656565656UL)
 
-static void handle_signal(int sig, siginfo_t *si, void *ucp)
+static void read_ymm0(uint64_t *v)
+{
+	asm volatile ("vmovdqu %%ymm0, %0" : "=m"  (*(char (*)[32])v));
+}
+
+static void write_ymm0(uint64_t *v)
+{
+	asm volatile ("vmovdqu %0, %%ymm0" : : "m"  (*(char (*)[32])v));
+}
+
+static void handle_portability(int sig, siginfo_t *si, void *ucp)
 {
 	ucontext_t *uc = ucp;
 	void *fp = uc->uc_mcontext.fpregs;
@@ -72,18 +83,14 @@ static void handle_signal(int sig, siginfo_t *si, void *ucp)
 
 	xbuf = (struct xsave_buffer *)fp;
 
-	if (sw->xstate_size < xstate_size_ymm) {
-		snprintf(sig_err_buf, SIGNAL_BUF_LEN,
-			 "xstate size is too small: %d (expected %d or greater)",
-			 sw->xstate_size, xstate_size_ymm);
-		return;
-	}
-
+	/* Shrink the frame to just YMM size */
 	sw->xstate_size = xstate_size_ymm;
 
 	xfeatures = get_xstatebv(xbuf);
 	xfeatures &= XFEATURE_MASK_FPSSE | (1 << XFEATURE_YMM);
 	set_xstatebv(xbuf, xfeatures);
+	/* Also update sw->xfeatures as the kernel relies on it */
+	set_fpx_sw_bytes_features(fp, xfeatures);
 
 	*(uint32_t *)(fp + sw->xstate_size) = FP_XSTATE_MAGIC2;
 
@@ -96,26 +103,12 @@ static void handle_signal(int sig, siginfo_t *si, void *ucp)
 		memset(fp + sw->xstate_size + 4, 0, sw->extended_size - sw->xstate_size - 4);
 }
 
-static void read_ymm0(uint64_t *v)
-{
-	asm volatile ("vmovdqu %%ymm0, %0" : "=m"  (*(char (*)[32])v));
-}
-
-static void write_ymm0(uint64_t *v)
-{
-	asm volatile ("vmovdqu %0, %%ymm0" : : "m"  (*(char (*)[32])v));
-}
-
-int main(void)
+static void test_portability(void)
 {
 	uint64_t v[4] = {0, 0, 0, 0};
 
-	ksft_print_header();
-	ksft_set_plan(1);
-
-	check_avx_support();
-
-	sethandler(SIGUSR1, handle_signal, 0);
+	sig_err_buf[0] = 0;
+	sethandler(SIGUSR1, handle_portability, 0);
 
 	v[0] = 0x1111111111111111ULL;
 	v[1] = 0x2222222222222222ULL;
@@ -130,13 +123,66 @@ int main(void)
 	if (sig_err_buf[0])
 		ksft_test_result_fail("%s\n", sig_err_buf);
 	else if (v[2] == TEST_YMMH_VAL && v[3] == (TEST_YMMH_VAL + 1))
-		ksft_test_result_pass("YMM state restored correctly\n");
+		ksft_test_result_pass("YMM state restored correctly from shrunk frame\n");
 	else
 		ksft_test_result_fail(
 				"Got upper bits: 0x%lx 0x%lx (expected %lx %lx)\n",
 			       v[2], v[3], TEST_YMMH_VAL, TEST_YMMH_VAL + 1);
 
 	clearhandler(SIGUSR1);
+}
+
+static void handle_consistency(int sig, siginfo_t *si, void *ucp)
+{
+	ucontext_t *uc = ucp;
+	void *fp = uc->uc_mcontext.fpregs;
+	struct _fpx_sw_bytes *sw = get_fpx_sw_bytes(fp);
+
+	/* The origin frame contains an AVX state. */
+	sw->xstate_size = XSTATE_SSE_ONLY_SIZE;
+
+	*(uint32_t *)(fp + sw->xstate_size) = FP_XSTATE_MAGIC2;
+}
+
+static void test_consistency(void)
+{
+	uint64_t v[4] = {0, 0, 0, 0};
+
+	sig_err_buf[0] = 0;
+	sethandler(SIGUSR2, handle_consistency, 0);
+
+	v[0] = 0x1111111111111111ULL;
+	v[1] = 0x2222222222222222ULL;
+	v[2] = 0x3333333333333333ULL;
+	v[3] = 0x4444444444444444ULL;
+	write_ymm0(v);
+
+	raise(SIGUSR2);
+	v[0] = v[1] = v[2] = v[3] = 0;
+	read_ymm0(v);
+
+	/*
+	 * When inconsistent, the kernel should have fallen back to
+	 * FX-only mode, so YMM upper bits should be zero (init state).
+	 */
+	if (v[2] == 0 && v[3] == 0)
+		ksft_test_result_pass("Inconsistent size correctly rejected\n");
+	else
+		ksft_test_result_fail("Inconsistent size was NOT rejected: 0x%lx 0x%lx\n",
+				      v[2], v[3]);
+
+	clearhandler(SIGUSR2);
+}
+
+int main(void)
+{
+	ksft_print_header();
+	ksft_set_plan(2);
+
+	check_avx_support();
+
+	test_portability();
+	test_consistency();
 
 	ksft_finished();
 	return 0;
diff --git a/tools/testing/selftests/x86/xstate.h b/tools/testing/selftests/x86/xstate.h
index b24501b621f3..c531667b66ad 100644
--- a/tools/testing/selftests/x86/xstate.h
+++ b/tools/testing/selftests/x86/xstate.h
@@ -182,6 +182,11 @@ static inline uint64_t get_fpx_sw_bytes_features(void *buffer)
 	return *(uint64_t *)(buffer + SW_BYTES_BV_OFFSET);
 }
 
+static inline void set_fpx_sw_bytes_features(void *buffer, uint64_t features)
+{
+	*(uint64_t *)(buffer + SW_BYTES_BV_OFFSET) = features;
+}
+
 static inline void set_rand_data(struct xstate_info *xstate, struct xsave_buffer *xbuf)
 {
 	int *ptr = (int *)&xbuf->bytes[xstate->xbuf_offset];
-- 
2.54.0.746.g67dd491aae-goog


      parent reply	other threads:[~2026-05-26 20:50 UTC|newest]

Thread overview: 9+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-05-26 20:50 [PATCH 0/5] x86/fpu: Restore and reinforce signal frame portability Andrei Vagin
2026-05-26 20:50 ` [PATCH 1/5] Revert "x86/fpu: Refine and simplify the magic number check during signal return" Andrei Vagin
2026-05-27 19:48   ` Sasha Levin
2026-05-28 17:08     ` Andrei Vagin
2026-06-03 15:13   ` Sasha Levin
2026-05-26 20:50 ` [PATCH 2/5] x86/fpu: Document signal frame portability Andrei Vagin
2026-05-26 20:50 ` [PATCH 3/5] selftests/x86: Add a test for " Andrei Vagin
2026-05-26 20:50 ` [PATCH 4/5] x86/fpu: Add consistency check between xstate_size and xfeatures Andrei Vagin
2026-05-26 20:50 ` Andrei Vagin [this message]

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=20260526205047.3339490-6-avagin@google.com \
    --to=avagin@google.com \
    --cc=bp@alien8.de \
    --cc=chang.seok.bae@intel.com \
    --cc=criu@lists.linux.dev \
    --cc=dave.hansen@linux.intel.com \
    --cc=hpa@zytor.com \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=tglx@kernel.org \
    --cc=x86@kernel.org \
    /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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®