[PATCH v1 1/4] selftests/x86: Fix the altstack free

From: Chang S. Bae
Date: Mon Apr 03 2023 - 00:55:46 EST


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@xxxxxxxxx>
Cc: Shuah Khan <shuah@xxxxxxxxxx>
Cc: Jun Miao <jun.miao@xxxxxxxxxxxxx>
Cc: linux-kselftest@xxxxxxxxxxxxxxx
Cc: linux-kernel@xxxxxxxxxxxxxxx
---
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