On 5/30/2025 4:07 PM, Xin Li (Intel) wrote:
> When FRED is enabled, if the Trap Flag (TF) is set without an external
> debugger attached, it can lead to an infinite loop in the SIGTRAP
> handler.  To avoid this, the software event flag in the augmented SS
> must be cleared, ensuring that no single-step trap remains pending when
> ERETU completes.
> 
> This test checks for that specific scenario—verifying whether the kernel
> correctly prevents an infinite SIGTRAP loop in this edge case.
> 

It isn't clear from the commit message whether the test is specific to
FRED or a generic one.

> Signed-off-by: Xin Li (Intel) <[email protected]>
> ---
>  tools/testing/selftests/x86/Makefile          |  2 +-
>  .../selftests/x86/test_sigtrap_handler.c      | 80 +++++++++++++++++++
>  2 files changed, 81 insertions(+), 1 deletion(-)
>  create mode 100644 tools/testing/selftests/x86/test_sigtrap_handler.c
> 
> diff --git a/tools/testing/selftests/x86/Makefile 
> b/tools/testing/selftests/x86/Makefile
> index f703fcfe9f7c..c486fd88ebb1 100644
> --- a/tools/testing/selftests/x86/Makefile
> +++ b/tools/testing/selftests/x86/Makefile
> @@ -12,7 +12,7 @@ CAN_BUILD_WITH_NOPIE := $(shell ./check_cc.sh "$(CC)" 
> trivial_program.c -no-pie)
>  
>  TARGETS_C_BOTHBITS := single_step_syscall sysret_ss_attrs syscall_nt 
> test_mremap_vdso \
>                       check_initial_reg_state sigreturn iopl ioperm \
> -                     test_vsyscall mov_ss_trap \
> +                     test_vsyscall mov_ss_trap test_sigtrap_handler \
>                       syscall_arg_fault fsgsbase_restore sigaltstack
>  TARGETS_C_BOTHBITS += nx_stack
>  TARGETS_C_32BIT_ONLY := entry_from_vm86 test_syscall_vdso unwind_vdso \
> diff --git a/tools/testing/selftests/x86/test_sigtrap_handler.c 
> b/tools/testing/selftests/x86/test_sigtrap_handler.c
> new file mode 100644
> index 000000000000..9c5c2cf0cf88
> --- /dev/null
> +++ b/tools/testing/selftests/x86/test_sigtrap_handler.c
> @@ -0,0 +1,80 @@
> +// SPDX-License-Identifier: GPL-2.0-or-later

Curious about your use of GPL-2.0-or-later?

All the files in this directory use GPL-2.0-only or GPL-2.0.

> +/*
> + *  Copyright (C) 2025 Intel Corporation
> + */
> +#define _GNU_SOURCE
> +
> +#include <err.h>
> +#include <signal.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <string.h>
> +#include <sys/ucontext.h>
> +
> +#ifdef __x86_64__
> +# define REG_IP REG_RIP
> +#else
> +# define REG_IP REG_EIP
> +#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");
> +
> +     return;
> +}
> +
> +static unsigned int loop_count_on_same_ip;
> +
> +static void sigtrap(int sig, siginfo_t *info, void *ctx_void)
> +{
> +     ucontext_t *ctx = (ucontext_t *)ctx_void;
> +     static unsigned long last_trap_ip;
> +
> +     if (last_trap_ip == ctx->uc_mcontext.gregs[REG_IP]) {
> +             printf("trapped on %016lx\n", last_trap_ip);
> +
> +             if (++loop_count_on_same_ip > 10) {
> +                     printf("trap loop detected, test failed\n");
> +                     exit(2);
> +             }

Most of the x86 selftests use the ksft_exit_fail_msg(), ksft_print_msg()
or [RUN, FAIL, OK] style for error messages and other informational prints.


> +
> +             return;
> +     }
> +
> +     loop_count_on_same_ip = 0;
> +     last_trap_ip = ctx->uc_mcontext.gregs[REG_IP];
> +     printf("trapped on %016lx\n", last_trap_ip);
> +}
> +
> +int main(int argc, char *argv[])
> +{
> +     sethandler(SIGTRAP, sigtrap, 0);
> +

I would suggest a comment here to explain what the following assembly
code is supposed to do. It isn't obvious from a cursory look.

> +     asm volatile(
> +#ifdef __x86_64__
> +             /* Avoid clobbering the redzone */
> +             "sub $128, %rsp\n\t"
> +#endif
> +             "push $0x302\n\t"
> +             "popf\n\t"
> +             "nop\n\t"
> +             "nop\n\t"
> +             "push $0x202\n\t"
> +             "popf\n\t"
> +#ifdef __x86_64__
> +             "add $128, %rsp\n\t"
> +#endif
> +     );
> +
> +     printf("test passed\n");
> +     return 0;
> +}
> 
> base-commit: 485d11d84a2452ac16466cc7ae041c93d38929bc


Reply via email to