linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH v1 0/4] selftests/x86: Improve signal test code
@ 2023-04-03  4:43 Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 1/4] selftests/x86: Fix the altstack free Chang S. Bae
                   ` (3 more replies)
  0 siblings, 4 replies; 5+ messages in thread
From: Chang S. Bae @ 2023-04-03  4:43 UTC (permalink / raw)
  To: linux-kselftest, linux-kernel
  Cc: shuah, luto, dave.hansen, tglx, bp, jun.miao, chang.seok.bae

Hi all,

This is a cleanup series to consolidate a common signal setup code.
Right now quite a bit of duplicated code is there in an unorganized
way. Here is a rework of that signal-related code:

(1) Consolidate the signal handler helpers

  They have been exactly copied everywhere. Place them in the shared
  code. Then, remove those duplicates.

(2) Simplify altstack code

  Most cases require just a usable alternate stack. So, there is a
  chance to simplify them all. Abstract the entire setup code to one
  setup call. Then, it can reduce the amount of code there.

  For testing sigaltstack() specifically, another helper is provided
  that excludes the syscall part.

The series also includes some preparatory changes for them:

* Along with the rework, some existing problem was uncovered. A couple
  of tests look to free the altstack memory even before the signal
  delivery. Adjust the memory cleanup to resolve this issue.

* Also resolve a define conflict separately before including the
  refactored header.

Then, there is another selftest fix that I posted:
  https://lore.kernel.org/lkml/20230330233520.21937-1-chang.seok.bae@intel.com/
which has a conflict with this. As the fix should go first, this
cleanup series is based on it.

FWIW, at the moment, the new x86 selftest cases -- lam and
test_shadow_stack do not conflict with this.

Here is the repository where this series can be found:
  git://github.com/intel/amx-linux.git selftest-signal

Thanks,
Chang

Chang S. Bae (4):
  selftests/x86: Fix the altstack free
  selftests/x86/mov_ss_trap: Include processor-flags.h
  selftests/x86: Consolidate signal handler helpers
  selftests/x86: Refactor altstack setup code

 tools/testing/selftests/x86/Makefile          |  16 ++-
 tools/testing/selftests/x86/amx.c             |  67 +++--------
 .../selftests/x86/corrupt_xstate_header.c     |  15 +--
 tools/testing/selftests/x86/entry_from_vm86.c |  25 +---
 tools/testing/selftests/x86/fsgsbase.c        |  25 +---
 tools/testing/selftests/x86/helpers.c         | 110 ++++++++++++++++++
 tools/testing/selftests/x86/helpers.h         |  10 ++
 tools/testing/selftests/x86/ioperm.c          |  26 +----
 tools/testing/selftests/x86/iopl.c            |  26 +----
 tools/testing/selftests/x86/ldt_gdt.c         |  19 +--
 tools/testing/selftests/x86/mov_ss_trap.c     |  26 +----
 tools/testing/selftests/x86/ptrace_syscall.c  |  24 +---
 tools/testing/selftests/x86/sigaltstack.c     |  67 +++--------
 tools/testing/selftests/x86/sigreturn.c       |  35 +-----
 .../selftests/x86/single_step_syscall.c       |  36 +-----
 .../testing/selftests/x86/syscall_arg_fault.c |  24 +---
 tools/testing/selftests/x86/syscall_nt.c      |  13 ---
 tools/testing/selftests/x86/sysret_rip.c      |  24 +---
 tools/testing/selftests/x86/test_vsyscall.c   |  13 ---
 tools/testing/selftests/x86/unwind_vdso.c     |  13 ---
 20 files changed, 205 insertions(+), 409 deletions(-)
 create mode 100644 tools/testing/selftests/x86/helpers.c

-- 
2.17.1


^ permalink raw reply	[flat|nested] 5+ messages in thread

* [PATCH v1 1/4] selftests/x86: Fix the altstack free
  2023-04-03  4:43 [PATCH v1 0/4] selftests/x86: Improve signal test code Chang S. Bae
@ 2023-04-03  4:43 ` Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 2/4] selftests/x86/mov_ss_trap: Include processor-flags.h Chang S. Bae
                   ` (2 subsequent siblings)
  3 siblings, 0 replies; 5+ messages in thread
From: Chang S. Bae @ 2023-04-03  4:43 UTC (permalink / raw)
  To: linux-kselftest, linux-kernel
  Cc: shuah, luto, dave.hansen, tglx, bp, jun.miao, chang.seok.bae

Some altstacks are freed up too early even before the test signal
delivery. Move the memory cleanup after a signal return.

Fixes: a051b2e56f2a ("selftests/x86: Fix error: variably modified 'altstack_data' at file scope")
Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Jun Miao <jun.miao@windriver.com>
Cc: linux-kselftest@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
The issue was discovered by the altstack refactoring in this series
that replaces malloc()/free() with mmap()/munmap().
---
 tools/testing/selftests/x86/mov_ss_trap.c       | 17 ++++++++++-------
 .../testing/selftests/x86/single_step_syscall.c | 17 ++++++++++-------
 2 files changed, 20 insertions(+), 14 deletions(-)

diff --git a/tools/testing/selftests/x86/mov_ss_trap.c b/tools/testing/selftests/x86/mov_ss_trap.c
index cc3de6ff9fba..6b9bf8dc3b60 100644
--- a/tools/testing/selftests/x86/mov_ss_trap.c
+++ b/tools/testing/selftests/x86/mov_ss_trap.c
@@ -142,8 +142,17 @@ static void handle_and_longjmp(int sig, siginfo_t *si, void *ctx_void)
 
 int main()
 {
+	stack_t stack = { };
 	unsigned long nr;
 
+	stack.ss_size = SIGSTKSZ;
+	stack.ss_sp = malloc(sizeof(char) * SIGSTKSZ);
+	if (!stack.ss_sp)
+		err(1, "malloc()");
+
+	if (sigaltstack(&stack, NULL) != 0)
+		err(1, "sigaltstack()");
+
 	asm volatile ("mov %%ss, %[ss]" : [ss] "=m" (ss));
 	printf("\tSS = 0x%hx, &SS = 0x%p\n", ss, &ss);
 
@@ -248,15 +257,8 @@ int main()
 	 */
 	if (sigsetjmp(jmpbuf, 1) == 0) {
 		printf("[RUN]\tMOV SS; SYSENTER\n");
-		stack_t stack = {
-			.ss_sp = malloc(sizeof(char) * SIGSTKSZ),
-			.ss_size = SIGSTKSZ,
-		};
-		if (sigaltstack(&stack, NULL) != 0)
-			err(1, "sigaltstack");
 		sethandler(SIGSEGV, handle_and_longjmp, SA_RESETHAND | SA_ONSTACK);
 		nr = SYS_getpid;
-		free(stack.ss_sp);
 		/* Clear EBP first to make sure we segfault cleanly. */
 		asm volatile ("xorl %%ebp, %%ebp; mov %[ss], %%ss; SYSENTER" : "+a" (nr)
 			      : [ss] "m" (ss) : "flags", "rcx"
@@ -281,6 +283,7 @@ int main()
 			);
 	}
 
+	free(stack.ss_sp);
 	printf("[OK]\tI aten't dead\n");
 	return 0;
 }
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c
index 9a30f443e928..2d8e0edca23f 100644
--- a/tools/testing/selftests/x86/single_step_syscall.c
+++ b/tools/testing/selftests/x86/single_step_syscall.c
@@ -144,10 +144,19 @@ static void fast_syscall_no_tf(void)
 
 int main()
 {
+	stack_t stack = { };
 #ifdef CAN_BUILD_32
 	int tmp;
 #endif
 
+	stack.ss_size = SIGSTKSZ;
+	stack.ss_sp = malloc(sizeof(char) * SIGSTKSZ);
+	if (!stack.ss_sp)
+		err(1, "malloc()");
+
+	if (sigaltstack(&stack, NULL) != 0)
+		err(1, "sigaltstack()");
+
 	sethandler(SIGTRAP, sigtrap, 0);
 
 	printf("[RUN]\tSet TF and check nop\n");
@@ -208,17 +217,10 @@ int main()
 	if (sigsetjmp(jmpbuf, 1) == 0) {
 		unsigned long nr = SYS_getpid;
 		printf("[RUN]\tSet TF and check SYSENTER\n");
-		stack_t stack = {
-			.ss_sp = malloc(sizeof(char) * SIGSTKSZ),
-			.ss_size = SIGSTKSZ,
-		};
-		if (sigaltstack(&stack, NULL) != 0)
-			err(1, "sigaltstack");
 		sethandler(SIGSEGV, print_and_longjmp,
 			   SA_RESETHAND | SA_ONSTACK);
 		sethandler(SIGILL, print_and_longjmp, SA_RESETHAND);
 		set_eflags(get_eflags() | X86_EFLAGS_TF);
-		free(stack.ss_sp);
 		/* Clear EBP first to make sure we segfault cleanly. */
 		asm volatile ("xorl %%ebp, %%ebp; SYSENTER" : "+a" (nr) :: "flags", "rcx"
 #ifdef __x86_64__
@@ -238,5 +240,6 @@ int main()
 	/* Now make sure that another fast syscall doesn't set TF again. */
 	fast_syscall_no_tf();
 
+	free(stack.ss_sp);
 	return 0;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v1 2/4] selftests/x86/mov_ss_trap: Include processor-flags.h
  2023-04-03  4:43 [PATCH v1 0/4] selftests/x86: Improve signal test code Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 1/4] selftests/x86: Fix the altstack free Chang S. Bae
@ 2023-04-03  4:43 ` Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 3/4] selftests/x86: Consolidate signal handler helpers Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 4/4] selftests/x86: Refactor altstack setup code Chang S. Bae
  3 siblings, 0 replies; 5+ messages in thread
From: Chang S. Bae @ 2023-04-03  4:43 UTC (permalink / raw)
  To: linux-kselftest, linux-kernel
  Cc: shuah, luto, dave.hansen, tglx, bp, jun.miao, chang.seok.bae

Instead of defining X86_EFLAGS_RF, include the header file.

Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
Resolve here before including helper.h in the next patch which,
otherwise, has to remove the define there along with other changes.
---
 tools/testing/selftests/x86/mov_ss_trap.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)

diff --git a/tools/testing/selftests/x86/mov_ss_trap.c b/tools/testing/selftests/x86/mov_ss_trap.c
index 6b9bf8dc3b60..f8633aafc90c 100644
--- a/tools/testing/selftests/x86/mov_ss_trap.c
+++ b/tools/testing/selftests/x86/mov_ss_trap.c
@@ -35,8 +35,7 @@
 #include <string.h>
 #include <setjmp.h>
 #include <sys/prctl.h>
-
-#define X86_EFLAGS_RF (1UL << 16)
+#include <asm/processor-flags.h>
 
 #if __x86_64__
 # define REG_IP REG_RIP
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v1 3/4] selftests/x86: Consolidate signal handler helpers
  2023-04-03  4:43 [PATCH v1 0/4] selftests/x86: Improve signal test code Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 1/4] selftests/x86: Fix the altstack free Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 2/4] selftests/x86/mov_ss_trap: Include processor-flags.h Chang S. Bae
@ 2023-04-03  4:43 ` Chang S. Bae
  2023-04-03  4:43 ` [PATCH v1 4/4] selftests/x86: Refactor altstack setup code Chang S. Bae
  3 siblings, 0 replies; 5+ messages in thread
From: Chang S. Bae @ 2023-04-03  4:43 UTC (permalink / raw)
  To: linux-kselftest, linux-kernel
  Cc: shuah, luto, dave.hansen, tglx, bp, jun.miao, chang.seok.bae,
	Borislav Petkov

Many test cases have the same signal handler (un)register helpers
which have been copied exactly over there.

Clean up this by moving this helper into a common place. Also, update
the Makefile to support this shared code.

Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: linux-kernel@vger.kernel.org
Cc: linux-kselftest@vger.kernel.org
---
 tools/testing/selftests/x86/Makefile          | 16 ++++++++--
 tools/testing/selftests/x86/amx.c             | 25 +---------------
 .../selftests/x86/corrupt_xstate_header.c     | 15 +---------
 tools/testing/selftests/x86/entry_from_vm86.c | 25 ++--------------
 tools/testing/selftests/x86/fsgsbase.c        | 25 ++--------------
 tools/testing/selftests/x86/helpers.c         | 30 +++++++++++++++++++
 tools/testing/selftests/x86/helpers.h         |  6 ++++
 tools/testing/selftests/x86/ioperm.c          | 26 ++--------------
 tools/testing/selftests/x86/iopl.c            | 26 ++--------------
 tools/testing/selftests/x86/ldt_gdt.c         | 19 +++---------
 tools/testing/selftests/x86/mov_ss_trap.c     | 15 ++--------
 tools/testing/selftests/x86/ptrace_syscall.c  | 24 ++-------------
 tools/testing/selftests/x86/sigaltstack.c     | 27 ++---------------
 tools/testing/selftests/x86/sigreturn.c       | 25 ++--------------
 .../selftests/x86/single_step_syscall.c       | 23 --------------
 .../testing/selftests/x86/syscall_arg_fault.c | 13 --------
 tools/testing/selftests/x86/syscall_nt.c      | 13 --------
 tools/testing/selftests/x86/sysret_rip.c      | 24 +--------------
 tools/testing/selftests/x86/test_vsyscall.c   | 13 --------
 tools/testing/selftests/x86/unwind_vdso.c     | 13 --------
 20 files changed, 72 insertions(+), 331 deletions(-)
 create mode 100644 tools/testing/selftests/x86/helpers.c

diff --git a/tools/testing/selftests/x86/Makefile b/tools/testing/selftests/x86/Makefile
index ca9374b56ead..382585a314c0 100644
--- a/tools/testing/selftests/x86/Makefile
+++ b/tools/testing/selftests/x86/Makefile
@@ -36,6 +36,10 @@ BINARIES_64 := $(patsubst %,$(OUTPUT)/%,$(BINARIES_64))
 
 CFLAGS := -O2 -g -std=gnu99 -pthread -Wall $(KHDR_INCLUDES)
 
+LIB := helpers
+LIB_OBJ_32 := $(patsubst %,$(OUTPUT)/%.o,$(LIB:%=%_32))
+LIB_OBJ_64 := $(patsubst %,$(OUTPUT)/%.o,$(LIB:%=%_64))
+
 # call32_from_64 in thunks.S uses absolute addresses.
 ifeq ($(CAN_BUILD_WITH_NOPIE),1)
 CFLAGS += -no-pie
@@ -69,12 +73,18 @@ all_32: $(BINARIES_32)
 
 all_64: $(BINARIES_64)
 
-EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64)
+EXTRA_CLEAN := $(BINARIES_32) $(BINARIES_64) $(LIB_OBJ_32) $(LIB_OBJ_64)
+
+$(LIB_OBJ_32): $(OUTPUT)/%_32.o: %.c
+	$(CC) -O -m32 -o $@ -c $^ $(CFLAGS) $(EXTRA_CFLAGS)
+
+$(LIB_OBJ_64): $(OUTPUT)/%_64.o: %.c
+	$(CC) -O -m64 -o $@ -c $^ $(CFLAGS) $(EXTRA_CFLAGS)
 
-$(BINARIES_32): $(OUTPUT)/%_32: %.c helpers.h
+$(BINARIES_32): $(OUTPUT)/%_32: %.c helpers.h $(LIB_OBJ_32)
 	$(CC) -m32 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl -lm
 
-$(BINARIES_64): $(OUTPUT)/%_64: %.c helpers.h
+$(BINARIES_64): $(OUTPUT)/%_64: %.c helpers.h $(LIB_OBJ_64)
 	$(CC) -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
 
 # x86_64 users should be encouraged to install 32-bit libraries
diff --git a/tools/testing/selftests/x86/amx.c b/tools/testing/selftests/x86/amx.c
index 854f7d61be89..1e8e60b1f7b9 100644
--- a/tools/testing/selftests/x86/amx.c
+++ b/tools/testing/selftests/x86/amx.c
@@ -20,6 +20,7 @@
 #include <sys/uio.h>
 
 #include "../kselftest.h" /* For __cpuid_count() */
+#include "helpers.h"
 
 #ifndef __x86_64__
 # error This test is 64-bit only
@@ -61,30 +62,6 @@ static inline void xrstor(struct xsave_buffer *xbuf, uint64_t rfbm)
 /* err() exits and will not return */
 #define fatal_error(msg, ...)	err(1, "[FAIL]\t" msg, ##__VA_ARGS__)
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		fatal_error("sigaction");
-}
-
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		fatal_error("sigaction");
-}
-
 #define XFEATURE_XTILECFG	17
 #define XFEATURE_XTILEDATA	18
 #define XFEATURE_MASK_XTILECFG	(1 << XFEATURE_XTILECFG)
diff --git a/tools/testing/selftests/x86/corrupt_xstate_header.c b/tools/testing/selftests/x86/corrupt_xstate_header.c
index cf9ce8fbb656..111ec58cd1d0 100644
--- a/tools/testing/selftests/x86/corrupt_xstate_header.c
+++ b/tools/testing/selftests/x86/corrupt_xstate_header.c
@@ -11,13 +11,13 @@
 #include <stdio.h>
 #include <string.h>
 #include <sched.h>
-#include <signal.h>
 #include <err.h>
 #include <unistd.h>
 #include <stdint.h>
 #include <sys/wait.h>
 
 #include "../kselftest.h" /* For __cpuid_count() */
+#include "helpers.h"
 
 static inline int xsave_enabled(void)
 {
@@ -29,19 +29,6 @@ static inline int xsave_enabled(void)
 	return ecx & (1U << 27);
 }
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static void sigusr1(int sig, siginfo_t *info, void *uc_void)
 {
 	ucontext_t *uc = uc_void;
diff --git a/tools/testing/selftests/x86/entry_from_vm86.c b/tools/testing/selftests/x86/entry_from_vm86.c
index d1e919b0c1dc..535596f9ce24 100644
--- a/tools/testing/selftests/x86/entry_from_vm86.c
+++ b/tools/testing/selftests/x86/entry_from_vm86.c
@@ -11,7 +11,6 @@
 #include <assert.h>
 #include <stdlib.h>
 #include <sys/syscall.h>
-#include <sys/signal.h>
 #include <sys/ucontext.h>
 #include <unistd.h>
 #include <stdio.h>
@@ -24,31 +23,11 @@
 #include <errno.h>
 #include <sys/vm86.h>
 
+#include "helpers.h"
+
 static unsigned long load_addr = 0x10000;
 static int nerrs = 0;
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static sig_atomic_t got_signal;
 
 static void sighandler(int sig, siginfo_t *info, void *ctx_void)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
index 8c780cce941d..94642c57e483 100644
--- a/tools/testing/selftests/x86/fsgsbase.c
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -15,7 +15,6 @@
 #include <sys/user.h>
 #include <asm/prctl.h>
 #include <sys/prctl.h>
-#include <signal.h>
 #include <limits.h>
 #include <sys/ucontext.h>
 #include <sched.h>
@@ -28,6 +27,8 @@
 #include <sys/wait.h>
 #include <setjmp.h>
 
+#include "helpers.h"
+
 #ifndef __x86_64__
 # error This test is 64-bit only
 #endif
@@ -39,28 +40,6 @@ static unsigned short *shared_scratch;
 
 static int nerrs;
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static void sigsegv(int sig, siginfo_t *si, void *ctx_void)
 {
 	ucontext_t *ctx = (ucontext_t*)ctx_void;
diff --git a/tools/testing/selftests/x86/helpers.c b/tools/testing/selftests/x86/helpers.c
new file mode 100644
index 000000000000..a6ecc42d359f
--- /dev/null
+++ b/tools/testing/selftests/x86/helpers.c
@@ -0,0 +1,30 @@
+// SPDX-License-Identifier: GPL-2.0-only
+#define _GNU_SOURCE
+#include <string.h>
+#include <err.h>
+
+#include "helpers.h"
+
+void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
+		int flags)
+{
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_sigaction = handler;
+	sa.sa_flags = SA_SIGINFO | flags;
+	sigemptyset(&sa.sa_mask);
+	if (sigaction(sig, &sa, 0))
+		err(1, "sigaction");
+}
+
+void clearhandler(int sig)
+{
+	struct sigaction sa;
+
+	memset(&sa, 0, sizeof(sa));
+	sa.sa_handler = SIG_DFL;
+	sigemptyset(&sa.sa_mask);
+	if (sigaction(sig, &sa, 0))
+		err(1, "sigaction");
+}
diff --git a/tools/testing/selftests/x86/helpers.h b/tools/testing/selftests/x86/helpers.h
index 4ef42c4559a9..35ff4df35397 100644
--- a/tools/testing/selftests/x86/helpers.h
+++ b/tools/testing/selftests/x86/helpers.h
@@ -2,8 +2,14 @@
 #ifndef __SELFTESTS_X86_HELPERS_H
 #define __SELFTESTS_X86_HELPERS_H
 
+#include <signal.h>
 #include <asm/processor-flags.h>
 
+void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
+		int flags);
+
+void clearhandler(int sig);
+
 static inline unsigned long get_eflags(void)
 {
 #ifdef __x86_64__
diff --git a/tools/testing/selftests/x86/ioperm.c b/tools/testing/selftests/x86/ioperm.c
index 57ec5e99edb9..103573c3d855 100644
--- a/tools/testing/selftests/x86/ioperm.c
+++ b/tools/testing/selftests/x86/ioperm.c
@@ -8,7 +8,6 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdint.h>
-#include <signal.h>
 #include <setjmp.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,30 +19,9 @@
 #include <sched.h>
 #include <sys/io.h>
 
-static int nerrs = 0;
-
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-
-}
+#include "helpers.h"
 
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
+static int nerrs = 0;
 
 static jmp_buf jmpbuf;
 
diff --git a/tools/testing/selftests/x86/iopl.c b/tools/testing/selftests/x86/iopl.c
index 7e3e09c1abac..09544e598def 100644
--- a/tools/testing/selftests/x86/iopl.c
+++ b/tools/testing/selftests/x86/iopl.c
@@ -8,7 +8,6 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdint.h>
-#include <signal.h>
 #include <setjmp.h>
 #include <stdlib.h>
 #include <string.h>
@@ -20,30 +19,9 @@
 #include <sched.h>
 #include <sys/io.h>
 
-static int nerrs = 0;
-
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-
-}
+#include "helpers.h"
 
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
+static int nerrs = 0;
 
 static jmp_buf jmpbuf;
 
diff --git a/tools/testing/selftests/x86/ldt_gdt.c b/tools/testing/selftests/x86/ldt_gdt.c
index 3a29346e1452..80acade5d7df 100644
--- a/tools/testing/selftests/x86/ldt_gdt.c
+++ b/tools/testing/selftests/x86/ldt_gdt.c
@@ -8,7 +8,6 @@
 #include <err.h>
 #include <stdio.h>
 #include <stdint.h>
-#include <signal.h>
 #include <setjmp.h>
 #include <stdlib.h>
 #include <string.h>
@@ -26,6 +25,8 @@
 #include <asm/prctl.h>
 #include <sys/prctl.h>
 
+#include "helpers.h"
+
 #define AR_ACCESSED		(1<<8)
 
 #define AR_TYPE_RODATA		(0 * (1<<9))
@@ -506,20 +507,6 @@ static void fix_sa_restorer(int sig)
 }
 #endif
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-
-	fix_sa_restorer(sig);
-}
-
 static jmp_buf jmpbuf;
 
 static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
@@ -549,9 +536,11 @@ static void do_multicpu_tests(void)
 	}
 
 	sethandler(SIGSEGV, sigsegv, 0);
+	fix_sa_restorer(SIGSEGV);
 #ifdef __i386__
 	/* True 32-bit kernels send SIGILL instead of SIGSEGV on IRET faults. */
 	sethandler(SIGILL, sigsegv, 0);
+	fix_sa_restorer(SIGILL);
 #endif
 
 	printf("[RUN]\tCross-CPU LDT invalidation\n");
diff --git a/tools/testing/selftests/x86/mov_ss_trap.c b/tools/testing/selftests/x86/mov_ss_trap.c
index f8633aafc90c..cfec7a3e30b7 100644
--- a/tools/testing/selftests/x86/mov_ss_trap.c
+++ b/tools/testing/selftests/x86/mov_ss_trap.c
@@ -35,7 +35,8 @@
 #include <string.h>
 #include <setjmp.h>
 #include <sys/prctl.h>
-#include <asm/processor-flags.h>
+
+#include "helpers.h"
 
 #if __x86_64__
 # define REG_IP REG_RIP
@@ -93,18 +94,6 @@ static void enable_watchpoint(void)
 	}
 }
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static char const * const signames[] = {
 	[SIGSEGV] = "SIGSEGV",
 	[SIGBUS] = "SIBGUS",
diff --git a/tools/testing/selftests/x86/ptrace_syscall.c b/tools/testing/selftests/x86/ptrace_syscall.c
index 12aaa063196e..360ec88d5432 100644
--- a/tools/testing/selftests/x86/ptrace_syscall.c
+++ b/tools/testing/selftests/x86/ptrace_syscall.c
@@ -15,6 +15,8 @@
 #include <asm/ptrace-abi.h>
 #include <sys/auxv.h>
 
+#include "helpers.h"
+
 /* Bitness-agnostic defines for user_regs_struct fields. */
 #ifdef __x86_64__
 # define user_syscall_nr	orig_rax
@@ -93,18 +95,6 @@ static siginfo_t wait_trap(pid_t chld)
 	return si;
 }
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static void setsigign(int sig, int flags)
 {
 	struct sigaction sa;
@@ -116,16 +106,6 @@ static void setsigign(int sig, int flags)
 		err(1, "sigaction");
 }
 
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 #ifdef __x86_64__
 # define REG_BP REG_RBP
 #else
diff --git a/tools/testing/selftests/x86/sigaltstack.c b/tools/testing/selftests/x86/sigaltstack.c
index 22a88b764a8e..7c2bd27908d5 100644
--- a/tools/testing/selftests/x86/sigaltstack.c
+++ b/tools/testing/selftests/x86/sigaltstack.c
@@ -1,7 +1,6 @@
 // SPDX-License-Identifier: GPL-2.0-only
 
 #define _GNU_SOURCE
-#include <signal.h>
 #include <stdio.h>
 #include <stdbool.h>
 #include <string.h>
@@ -14,6 +13,8 @@
 #include <sys/resource.h>
 #include <setjmp.h>
 
+#include "helpers.h"
+
 /* sigaltstack()-enforced minimum stack */
 #define ENFORCED_MINSIGSTKSZ	2048
 
@@ -27,30 +28,6 @@ static bool sigalrm_expected;
 
 static unsigned long at_minstack_size;
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static int setup_altstack(void *start, unsigned long size)
 {
 	stack_t ss;
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
index 5d7961a5f7f6..b2282ca57e23 100644
--- a/tools/testing/selftests/x86/sigreturn.c
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -36,7 +36,6 @@
 #include <string.h>
 #include <inttypes.h>
 #include <sys/mman.h>
-#include <sys/signal.h>
 #include <sys/ucontext.h>
 #include <asm/ldt.h>
 #include <err.h>
@@ -46,6 +45,8 @@
 #include <sys/ptrace.h>
 #include <sys/user.h>
 
+#include "helpers.h"
+
 /* Pull in AR_xyz defines. */
 typedef unsigned int u32;
 typedef unsigned short u16;
@@ -138,28 +139,6 @@ static unsigned short LDT3(int idx)
 	return (idx << 3) | 7;
 }
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static void add_ldt(const struct user_desc *desc, unsigned short *var,
 		    const char *name)
 {
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c
index 2d8e0edca23f..4c9b8fd7a41a 100644
--- a/tools/testing/selftests/x86/single_step_syscall.c
+++ b/tools/testing/selftests/x86/single_step_syscall.c
@@ -21,7 +21,6 @@
 #include <string.h>
 #include <inttypes.h>
 #include <sys/mman.h>
-#include <sys/signal.h>
 #include <sys/ucontext.h>
 #include <asm/ldt.h>
 #include <err.h>
@@ -33,28 +32,6 @@
 
 #include "helpers.h"
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static volatile sig_atomic_t sig_traps, sig_eflags;
 sigjmp_buf jmpbuf;
 
diff --git a/tools/testing/selftests/x86/syscall_arg_fault.c b/tools/testing/selftests/x86/syscall_arg_fault.c
index 461fa41a4d02..1149ac24921a 100644
--- a/tools/testing/selftests/x86/syscall_arg_fault.c
+++ b/tools/testing/selftests/x86/syscall_arg_fault.c
@@ -9,7 +9,6 @@
 #include <stdlib.h>
 #include <stdio.h>
 #include <string.h>
-#include <sys/signal.h>
 #include <sys/ucontext.h>
 #include <err.h>
 #include <setjmp.h>
@@ -17,18 +16,6 @@
 
 #include "helpers.h"
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static volatile sig_atomic_t sig_traps;
 static sigjmp_buf jmpbuf;
 
diff --git a/tools/testing/selftests/x86/syscall_nt.c b/tools/testing/selftests/x86/syscall_nt.c
index a108b80dd082..1a019bc43b9d 100644
--- a/tools/testing/selftests/x86/syscall_nt.c
+++ b/tools/testing/selftests/x86/syscall_nt.c
@@ -10,7 +10,6 @@
 #include <stdio.h>
 #include <unistd.h>
 #include <string.h>
-#include <signal.h>
 #include <err.h>
 #include <sys/syscall.h>
 
@@ -18,18 +17,6 @@
 
 static unsigned int nerrs;
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static void sigtrap(int sig, siginfo_t *si, void *ctx_void)
 {
 }
diff --git a/tools/testing/selftests/x86/sysret_rip.c b/tools/testing/selftests/x86/sysret_rip.c
index 84d74be1d902..da5164fde79a 100644
--- a/tools/testing/selftests/x86/sysret_rip.c
+++ b/tools/testing/selftests/x86/sysret_rip.c
@@ -11,7 +11,6 @@
 #include <stdio.h>
 #include <string.h>
 #include <inttypes.h>
-#include <sys/signal.h>
 #include <sys/ucontext.h>
 #include <sys/syscall.h>
 #include <err.h>
@@ -22,6 +21,7 @@
 #include <sys/mman.h>
 #include <assert.h>
 
+#include "helpers.h"
 
 asm (
 	".pushsection \".text\", \"ax\"\n\t"
@@ -39,28 +39,6 @@ asm (
 extern const char test_page[];
 static void const *current_test_page_addr = test_page;
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
-static void clearhandler(int sig)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_handler = SIG_DFL;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 /* State used by our signal handlers. */
 static gregset_t initial_regs;
 
diff --git a/tools/testing/selftests/x86/test_vsyscall.c b/tools/testing/selftests/x86/test_vsyscall.c
index 47cab972807c..d54f5e767abe 100644
--- a/tools/testing/selftests/x86/test_vsyscall.c
+++ b/tools/testing/selftests/x86/test_vsyscall.c
@@ -11,7 +11,6 @@
 #include <dlfcn.h>
 #include <string.h>
 #include <inttypes.h>
-#include <signal.h>
 #include <sys/ucontext.h>
 #include <errno.h>
 #include <err.h>
@@ -39,18 +38,6 @@
 /* max length of lines in /proc/self/maps - anything longer is skipped here */
 #define MAPS_LINE_LEN 128
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 /* vsyscalls and vDSO */
 bool vsyscall_map_r = false, vsyscall_map_x = false;
 
diff --git a/tools/testing/selftests/x86/unwind_vdso.c b/tools/testing/selftests/x86/unwind_vdso.c
index 4c311e1af4c7..51ba53904130 100644
--- a/tools/testing/selftests/x86/unwind_vdso.c
+++ b/tools/testing/selftests/x86/unwind_vdso.c
@@ -31,7 +31,6 @@ int main()
 #include <string.h>
 #include <inttypes.h>
 #include <sys/mman.h>
-#include <signal.h>
 #include <sys/ucontext.h>
 #include <err.h>
 #include <stddef.h>
@@ -43,18 +42,6 @@ int main()
 #include <dlfcn.h>
 #include <unwind.h>
 
-static void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
-		       int flags)
-{
-	struct sigaction sa;
-	memset(&sa, 0, sizeof(sa));
-	sa.sa_sigaction = handler;
-	sa.sa_flags = SA_SIGINFO | flags;
-	sigemptyset(&sa.sa_mask);
-	if (sigaction(sig, &sa, 0))
-		err(1, "sigaction");
-}
-
 static volatile sig_atomic_t nerrs;
 static unsigned long sysinfo;
 static bool got_sysinfo = false;
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

* [PATCH v1 4/4] selftests/x86: Refactor altstack setup code
  2023-04-03  4:43 [PATCH v1 0/4] selftests/x86: Improve signal test code Chang S. Bae
                   ` (2 preceding siblings ...)
  2023-04-03  4:43 ` [PATCH v1 3/4] selftests/x86: Consolidate signal handler helpers Chang S. Bae
@ 2023-04-03  4:43 ` Chang S. Bae
  3 siblings, 0 replies; 5+ messages in thread
From: Chang S. Bae @ 2023-04-03  4:43 UTC (permalink / raw)
  To: linux-kselftest, linux-kernel
  Cc: shuah, luto, dave.hansen, tglx, bp, jun.miao, chang.seok.bae,
	Borislav Petkov

The sigaltstack setup code is almost the same across x86 tests. Most
of the test probably just needs a ready-to-use altstack instead of all
the setup code.

Refactor them to these helpers to simplify the test code:

- setup_sigaltstack()

  Allocate an altstack memory with a size more than the
  kernel-provided minimum. Then register the altstack via
  sigaltstack(2).

- cleanup_sigaltstack()

  Unregister the altstack and free up the memory.

Then, these two function calls are supposed to be enough for most
sigaltstack-needed test cases. But, when explicit sigaltstack() is
needed, another helper is available:

- init_sigaltstack()

  Do the same as setup_sigaltstack(), except for not invoking the
  sigaltstack syscall.

Finally, while here, ensure an altstack cleanup everywhere an altstack
is used.

Signed-off-by: Chang S. Bae <chang.seok.bae@intel.com>
Cc: Shuah Khan <shuah@kernel.org>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: linux-kselftest@vger.kernel.org
Cc: linux-kernel@vger.kernel.org
---
The patch is based on another series that fixes the sigaltstack test:
  https://lore.kernel.org/all/20230330233520.21937-2-chang.seok.bae@intel.com/

Considerably that fix should go first before this cleanup rework.
---
 tools/testing/selftests/x86/amx.c             | 42 ++++------
 tools/testing/selftests/x86/helpers.c         | 80 +++++++++++++++++++
 tools/testing/selftests/x86/helpers.h         |  4 +
 tools/testing/selftests/x86/mov_ss_trap.c     | 11 +--
 tools/testing/selftests/x86/sigaltstack.c     | 40 ++++------
 tools/testing/selftests/x86/sigreturn.c       | 10 +--
 .../selftests/x86/single_step_syscall.c       | 12 +--
 .../testing/selftests/x86/syscall_arg_fault.c | 11 +--
 8 files changed, 130 insertions(+), 80 deletions(-)

diff --git a/tools/testing/selftests/x86/amx.c b/tools/testing/selftests/x86/amx.c
index 1e8e60b1f7b9..70e1d64e9c57 100644
--- a/tools/testing/selftests/x86/amx.c
+++ b/tools/testing/selftests/x86/amx.c
@@ -362,29 +362,11 @@ static void validate_xcomp_perm(enum expected_result exp)
 #  define AT_MINSIGSTKSZ	51
 #endif
 
-static void *alloc_altstack(unsigned int size)
+static void setup_altstack(stack_t *stack, enum expected_result exp)
 {
-	void *altstack;
-
-	altstack = mmap(NULL, size, PROT_READ | PROT_WRITE,
-			MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
-
-	if (altstack == MAP_FAILED)
-		fatal_error("mmap() for altstack");
-
-	return altstack;
-}
-
-static void setup_altstack(void *addr, unsigned long size, enum expected_result exp)
-{
-	stack_t ss;
 	int rc;
 
-	memset(&ss, 0, sizeof(ss));
-	ss.ss_size = size;
-	ss.ss_sp = addr;
-
-	rc = sigaltstack(&ss, NULL);
+	rc = sigaltstack(stack, NULL);
 
 	if (exp == FAIL_EXPECTED) {
 		if (rc) {
@@ -401,7 +383,7 @@ static void test_dynamic_sigaltstack(void)
 {
 	unsigned int small_size, enough_size;
 	unsigned long minsigstksz;
-	void *altstack;
+	stack_t stack = { };
 
 	minsigstksz = getauxval(AT_MINSIGSTKSZ);
 	printf("\tAT_MINSIGSTKSZ = %lu\n", minsigstksz);
@@ -416,9 +398,9 @@ static void test_dynamic_sigaltstack(void)
 		return;
 	}
 
-	enough_size = minsigstksz * 2;
-
-	altstack = alloc_altstack(enough_size);
+	if (init_sigaltstack(&stack) != 0)
+		fatal_error("sigaltstack allocation failed.");
+	enough_size = stack.ss_size;
 	printf("\tAllocate memory for altstack (%u bytes).\n", enough_size);
 
 	/*
@@ -427,7 +409,8 @@ static void test_dynamic_sigaltstack(void)
 	 */
 	small_size = minsigstksz - xtiledata.size;
 	printf("\tAfter sigaltstack() with small size (%u bytes).\n", small_size);
-	setup_altstack(altstack, small_size, SUCCESS_EXPECTED);
+	stack.ss_size = small_size;
+	setup_altstack(&stack, SUCCESS_EXPECTED);
 	validate_req_xcomp_perm(FAIL_EXPECTED);
 
 	/*
@@ -436,7 +419,8 @@ static void test_dynamic_sigaltstack(void)
 	 * and thus ARCH_REQ_XCOMP_PERM should succeed.
 	 */
 	printf("\tAfter sigaltstack() with enough size (%u bytes).\n", enough_size);
-	setup_altstack(altstack, enough_size, SUCCESS_EXPECTED);
+	stack.ss_size = enough_size;
+	setup_altstack(&stack, SUCCESS_EXPECTED);
 	validate_req_xcomp_perm(SUCCESS_EXPECTED);
 
 	/*
@@ -446,7 +430,11 @@ static void test_dynamic_sigaltstack(void)
 	 * once XTILEDATA permission is established.
 	 */
 	printf("\tThen, sigaltstack() with small size (%u bytes).\n", small_size);
-	setup_altstack(altstack, small_size, FAIL_EXPECTED);
+	stack.ss_size = small_size;
+	setup_altstack(&stack, FAIL_EXPECTED);
+
+	stack.ss_size = enough_size;
+	cleanup_sigaltstack(&stack);
 }
 
 static void test_dynamic_state(void)
diff --git a/tools/testing/selftests/x86/helpers.c b/tools/testing/selftests/x86/helpers.c
index a6ecc42d359f..1f5b1e5a3d66 100644
--- a/tools/testing/selftests/x86/helpers.c
+++ b/tools/testing/selftests/x86/helpers.c
@@ -3,6 +3,15 @@
 #include <string.h>
 #include <err.h>
 
+#include <sys/auxv.h>
+#include <sys/mman.h>
+
+#include "helpers.h"
+
+#ifndef AT_MINSIGSTKSZ
+#  define AT_MINSIGSTKSZ	51
+#endif
+
 #include "helpers.h"
 
 void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
@@ -28,3 +37,74 @@ void clearhandler(int sig)
 	if (sigaction(sig, &sa, 0))
 		err(1, "sigaction");
 }
+
+#define ALTSTKSZ	8096
+
+static unsigned long get_sigaltstacksz(void)
+{
+	return getauxval(AT_MINSIGSTKSZ) + ALTSTKSZ;
+}
+
+/**
+ * init_sigalstack -- allocate an altstack without registration
+ * @stack:	stack_t pointer
+ * Returns:	0 if successful; otherwise, nonzero
+ *
+ * Unless testing with different sizes, setup_sigaltstack() should be
+ * enough to provide a ready-to-use stack
+ */
+int init_sigaltstack(stack_t *stack)
+{
+	if (!stack)
+		return -1;
+
+	if (stack->ss_size > 0 && stack->ss_sp > 0)
+		return 0;
+
+	stack->ss_size = get_sigaltstacksz();
+
+	stack->ss_sp = mmap(NULL, stack->ss_size, PROT_READ | PROT_WRITE,
+			    MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
+	if (stack->ss_sp == MAP_FAILED)
+		return -1;
+
+	return 0;
+}
+
+/**
+ * setup_sigaltstack -- allocate and register an altstack
+ * @stack:	stack_t pointer
+ * Returns:	0 if successful; otherwise, nonzero
+ */
+int setup_sigaltstack(stack_t *stack)
+{
+	int rc;
+
+	rc = init_sigaltstack(stack);
+	if (rc)
+		return -1;
+
+	return sigaltstack(stack, NULL);
+}
+
+/**
+ * cleanup_sigaltstack -- unregister and free an altstack
+ * @stack:	stack_t pointer
+ * Returns:	None
+ */
+void cleanup_sigaltstack(stack_t *stack)
+{
+	size_t size;
+	void *sp;
+
+	if (!stack)
+		return;
+
+	size = stack->ss_size;
+	sp = stack->ss_sp;
+
+	stack->ss_flags = SS_DISABLE;
+	sigaltstack(stack, NULL);
+
+	munmap(sp, size);
+}
diff --git a/tools/testing/selftests/x86/helpers.h b/tools/testing/selftests/x86/helpers.h
index 35ff4df35397..a47ba1a2d929 100644
--- a/tools/testing/selftests/x86/helpers.h
+++ b/tools/testing/selftests/x86/helpers.h
@@ -5,6 +5,10 @@
 #include <signal.h>
 #include <asm/processor-flags.h>
 
+int init_sigaltstack(stack_t *stack);
+int setup_sigaltstack(stack_t *stack);
+void cleanup_sigaltstack(stack_t *stack);
+
 void sethandler(int sig, void (*handler)(int, siginfo_t *, void *),
 		int flags);
 
diff --git a/tools/testing/selftests/x86/mov_ss_trap.c b/tools/testing/selftests/x86/mov_ss_trap.c
index cfec7a3e30b7..c9ffc8b3a214 100644
--- a/tools/testing/selftests/x86/mov_ss_trap.c
+++ b/tools/testing/selftests/x86/mov_ss_trap.c
@@ -133,13 +133,8 @@ int main()
 	stack_t stack = { };
 	unsigned long nr;
 
-	stack.ss_size = SIGSTKSZ;
-	stack.ss_sp = malloc(sizeof(char) * SIGSTKSZ);
-	if (!stack.ss_sp)
-		err(1, "malloc()");
-
-	if (sigaltstack(&stack, NULL) != 0)
-		err(1, "sigaltstack()");
+	if (setup_sigaltstack(&stack) != 0)
+		err(1, "sigaltstack");
 
 	asm volatile ("mov %%ss, %[ss]" : [ss] "=m" (ss));
 	printf("\tSS = 0x%hx, &SS = 0x%p\n", ss, &ss);
@@ -271,7 +266,7 @@ int main()
 			);
 	}
 
-	free(stack.ss_sp);
+	cleanup_sigaltstack(&stack);
 	printf("[OK]\tI aten't dead\n");
 	return 0;
 }
diff --git a/tools/testing/selftests/x86/sigaltstack.c b/tools/testing/selftests/x86/sigaltstack.c
index 7c2bd27908d5..6f753406ca91 100644
--- a/tools/testing/selftests/x86/sigaltstack.c
+++ b/tools/testing/selftests/x86/sigaltstack.c
@@ -28,17 +28,6 @@ static bool sigalrm_expected;
 
 static unsigned long at_minstack_size;
 
-static int setup_altstack(void *start, unsigned long size)
-{
-	stack_t ss;
-
-	memset(&ss, 0, sizeof(ss));
-	ss.ss_size = size;
-	ss.ss_sp = start;
-
-	return sigaltstack(&ss, NULL);
-}
-
 static jmp_buf jmpbuf;
 
 static void sigsegv(int sig, siginfo_t *info, void *ctx_void)
@@ -63,14 +52,14 @@ static void sigalrm(int sig, siginfo_t *info, void *ctx_void)
 	}
 }
 
-static void test_sigaltstack(void *altstack, unsigned long size)
+static void test_sigaltstack(stack_t *stack)
 {
-	if (setup_altstack(altstack, size)) {
+	if (sigaltstack(stack, NULL)) {
 		/*
 		 * The kernel may return ENOMEM when the altstack size
 		 * is insufficient. Skip the test in this case.
 		 */
-		if (errno == ENOMEM && size < at_minstack_size) {
+		if (errno == ENOMEM && stack->ss_size < at_minstack_size) {
 			printf("[SKIP]\tThe running kernel disallows an insufficient size.\n");
 			return;
 		}
@@ -78,7 +67,7 @@ static void test_sigaltstack(void *altstack, unsigned long size)
 		err(1, "sigaltstack()");
 	}
 
-	sigalrm_expected = (size > at_minstack_size) ? true : false;
+	sigalrm_expected = (stack->ss_size > at_minstack_size) ? true : false;
 
 	sethandler(SIGSEGV, sigsegv, 0);
 	sethandler(SIGALRM, sigalrm, SA_ONSTACK);
@@ -97,19 +86,24 @@ static void test_sigaltstack(void *altstack, unsigned long size)
 
 int main(void)
 {
-	void *altstack;
+	unsigned long enough_size;
+	stack_t stack = { };
 
 	at_minstack_size = getauxval(AT_MINSIGSTKSZ);
 
-	altstack = mmap(NULL, at_minstack_size + SIGSTKSZ, PROT_READ | PROT_WRITE,
-			MAP_PRIVATE | MAP_ANONYMOUS | MAP_STACK, -1, 0);
-	if (altstack == MAP_FAILED)
-		err(1, "mmap()");
+	if (init_sigaltstack(&stack) != 0)
+		err(1, "sigaltstack allocation failed.");
+	enough_size = stack.ss_size;
+
+	if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size) {
+		stack.ss_size = ENFORCED_MINSIGSTKSZ + 1;
+		test_sigaltstack(&stack);
+	}
 
-	if ((ENFORCED_MINSIGSTKSZ + 1) < at_minstack_size)
-		test_sigaltstack(altstack, ENFORCED_MINSIGSTKSZ + 1);
+	stack.ss_size = enough_size;
+	test_sigaltstack(&stack);
 
-	test_sigaltstack(altstack, at_minstack_size + SIGSTKSZ);
+	cleanup_sigaltstack(&stack);
 
 	return nerrs == 0 ? 0 : 1;
 }
diff --git a/tools/testing/selftests/x86/sigreturn.c b/tools/testing/selftests/x86/sigreturn.c
index b2282ca57e23..f9e06a13ad82 100644
--- a/tools/testing/selftests/x86/sigreturn.c
+++ b/tools/testing/selftests/x86/sigreturn.c
@@ -741,17 +741,13 @@ int main()
 {
 	int total_nerrs = 0;
 	unsigned short my_cs, my_ss;
+	stack_t stack = { };
 
 	asm volatile ("mov %%cs,%0" : "=r" (my_cs));
 	asm volatile ("mov %%ss,%0" : "=r" (my_ss));
 	setup_ldt();
 
-	stack_t stack = {
-		/* Our sigaltstack scratch space. */
-		.ss_sp = malloc(sizeof(char) * SIGSTKSZ),
-		.ss_size = SIGSTKSZ,
-	};
-	if (sigaltstack(&stack, NULL) != 0)
+	if (setup_sigaltstack(&stack) != 0)
 		err(1, "sigaltstack");
 
 	sethandler(SIGUSR1, sigusr1, 0);
@@ -849,6 +845,6 @@ int main()
 	total_nerrs += test_nonstrict_ss();
 #endif
 
-	free(stack.ss_sp);
+	cleanup_sigaltstack(&stack);
 	return total_nerrs ? 1 : 0;
 }
diff --git a/tools/testing/selftests/x86/single_step_syscall.c b/tools/testing/selftests/x86/single_step_syscall.c
index 4c9b8fd7a41a..4e3224e52e30 100644
--- a/tools/testing/selftests/x86/single_step_syscall.c
+++ b/tools/testing/selftests/x86/single_step_syscall.c
@@ -126,13 +126,8 @@ int main()
 	int tmp;
 #endif
 
-	stack.ss_size = SIGSTKSZ;
-	stack.ss_sp = malloc(sizeof(char) * SIGSTKSZ);
-	if (!stack.ss_sp)
-		err(1, "malloc()");
-
-	if (sigaltstack(&stack, NULL) != 0)
-		err(1, "sigaltstack()");
+	if (setup_sigaltstack(&stack) != 0)
+		err(1, "sigaltstack");
 
 	sethandler(SIGTRAP, sigtrap, 0);
 
@@ -193,6 +188,7 @@ int main()
 	 */
 	if (sigsetjmp(jmpbuf, 1) == 0) {
 		unsigned long nr = SYS_getpid;
+
 		printf("[RUN]\tSet TF and check SYSENTER\n");
 		sethandler(SIGSEGV, print_and_longjmp,
 			   SA_RESETHAND | SA_ONSTACK);
@@ -217,6 +213,6 @@ int main()
 	/* Now make sure that another fast syscall doesn't set TF again. */
 	fast_syscall_no_tf();
 
-	free(stack.ss_sp);
+	cleanup_sigaltstack(&stack);
 	return 0;
 }
diff --git a/tools/testing/selftests/x86/syscall_arg_fault.c b/tools/testing/selftests/x86/syscall_arg_fault.c
index 1149ac24921a..1b22ef548582 100644
--- a/tools/testing/selftests/x86/syscall_arg_fault.c
+++ b/tools/testing/selftests/x86/syscall_arg_fault.c
@@ -87,12 +87,9 @@ static void sigill(int sig, siginfo_t *info, void *ctx_void)
 
 int main()
 {
-	stack_t stack = {
-		/* Our sigaltstack scratch space. */
-		.ss_sp = malloc(sizeof(char) * SIGSTKSZ),
-		.ss_size = SIGSTKSZ,
-	};
-	if (sigaltstack(&stack, NULL) != 0)
+	stack_t stack = { };
+
+	if (setup_sigaltstack(&stack) != 0)
 		err(1, "sigaltstack");
 
 	sethandler(SIGSEGV, sigsegv_or_sigbus, SA_ONSTACK);
@@ -218,6 +215,6 @@ int main()
 	set_eflags(get_eflags() & ~X86_EFLAGS_TF);
 #endif
 
-	free(stack.ss_sp);
+	cleanup_sigaltstack(&stack);
 	return 0;
 }
-- 
2.17.1


^ permalink raw reply related	[flat|nested] 5+ messages in thread

end of thread, other threads:[~2023-04-03  4:55 UTC | newest]

Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2023-04-03  4:43 [PATCH v1 0/4] selftests/x86: Improve signal test code Chang S. Bae
2023-04-03  4:43 ` [PATCH v1 1/4] selftests/x86: Fix the altstack free Chang S. Bae
2023-04-03  4:43 ` [PATCH v1 2/4] selftests/x86/mov_ss_trap: Include processor-flags.h Chang S. Bae
2023-04-03  4:43 ` [PATCH v1 3/4] selftests/x86: Consolidate signal handler helpers Chang S. Bae
2023-04-03  4:43 ` [PATCH v1 4/4] selftests/x86: Refactor altstack setup code Chang S. Bae

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).