From: Bjoern Doebel <doebel@amazon.de>
To: Thomas Gleixner <tglx@kernel.org>, Ingo Molnar <mingo@redhat.com>,
Borislav Petkov <bp@alien8.de>,
Dave Hansen <dave.hansen@linux.intel.com>, <x86@kernel.org>
Cc: Peter Zijlstra <peterz@infradead.org>,
"H . Peter Anvin" <hpa@zytor.com>, Shuah Khan <shuah@kernel.org>,
Andy Lutomirski <luto@kernel.org>, <linux-kernel@vger.kernel.org>,
<linux-kselftest@vger.kernel.org>, <doebel@amazon.de>,
<stable@vger.kernel.org>
Subject: [PATCH] selftests/x86: Skip fsgsbase segment setup when int $0x80 is unavailable
Date: Wed, 23 Sep 2026 20:14:09 +0000 [thread overview]
Message-ID: <20260923201409.2187200-1-doebel@amazon.de> (raw)
The fsgsbase test's load_gs() helper needs a nonzero-based FS/GS
segment, i.e. a selector whose hidden base differs from the kernel's
saved thread base, to exercise the selector/base state tracking.
64-bit userspace can only create such a segment via modify_ldt() or,
failing that, via the 32-bit set_thread_area syscall over int $0x80.
On kernels built with CONFIG_MODIFY_LDT_SYSCALL=n, modify_ldt() fails
and the test falls back to int $0x80. If the kernel is also built
with CONFIG_IA32_EMULATION=n, no IDT gate is installed for vector
0x80, so executing int $0x80 raises a #GP fault and the test dies
with SIGSEGV instead of reporting results:
traps: fsgsbase_64[5460] general protection fault ip:4012a1
sp:7f38eb124de0 error:402 in fsgsbase_64[12a1,400000+2000]
With both options disabled, pure 64-bit userspace cannot install a
nonzero-based FS/GS segment at all, so this scenario is untestable.
Probe for a working int $0x80 at startup and skip the affected
subtests when neither mechanism is available instead of crashing.
While at it, replace the magic syscall numbers in the int $0x80
inline asm with named __NR_ia32_getpid / __NR_ia32_set_thread_area
constants. These deliberately use the ia32 syscall table numbering,
which differs from the x86-64 numbering exported by <sys/syscall.h>
on 64-bit builds.
Fixes: 0051202f6ad5f ("selftests/x86: Test the FSBASE/GSBASE API and context switching")
Signed-off-by: Bjoern Doebel <doebel@amazon.de>
Assisted-by: opencode:kimi-k3
Cc: stable@vger.kernel.org
---
tools/testing/selftests/x86/fsgsbase.c | 51 +++++++++++++++++++++++++-
1 file changed, 49 insertions(+), 2 deletions(-)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
index 0a75252d31b6a..8538ceb6c5785 100644
--- a/tools/testing/selftests/x86/fsgsbase.c
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -218,6 +218,40 @@ static void do_remote_base()
static __thread int set_thread_area_entry_number = -1;
+/*
+ * int $0x80 dispatches through the ia32 syscall table, whose numbers
+ * differ from the x86-64 table exposed by <sys/syscall.h> on an
+ * x86_64 build. Define the ia32 numbers we need explicitly.
+ */
+#define __NR_ia32_getpid 20
+#define __NR_ia32_set_thread_area 243
+
+static bool have_int80;
+
+static void sigsegv_int80(int sig, siginfo_t *si, void *ctx_void)
+{
+ siglongjmp(jmpbuf, 1);
+}
+
+static bool probe_int80(void)
+{
+ /*
+ * Check whether int $0x80 is available. Kernels built without
+ * CONFIG_IA32_EMULATION do not install an IDT entry for vector
+ * 0x80, so executing int $0x80 causes a #GP fault.
+ */
+ sethandler(SIGSEGV, sigsegv_int80, 0);
+ if (sigsetjmp(jmpbuf, 1) == 0) {
+ long ret;
+ /* getpid -- harmless if it works */
+ asm volatile ("int $0x80" : "=a" (ret) : "a" (__NR_ia32_getpid));
+ clearhandler(SIGSEGV);
+ return true;
+ }
+ clearhandler(SIGSEGV);
+ return false;
+}
+
static unsigned short load_gs(void)
{
/*
@@ -245,7 +279,7 @@ static unsigned short load_gs(void)
printf("\tusing LDT slot 0\n");
asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0x7));
return 0x7;
- } else {
+ } else if (have_int80) {
/* No modify_ldt for us (configured out, perhaps) */
struct user_desc *low_desc = mmap(
@@ -260,7 +294,7 @@ static unsigned short load_gs(void)
long ret;
asm volatile ("int $0x80"
: "=a" (ret), "+m" (*low_desc)
- : "a" (243), "b" (low_desc)
+ : "a" (__NR_ia32_set_thread_area), "b" (low_desc)
: "r8", "r9", "r10", "r11");
memcpy(&desc, low_desc, sizeof(desc));
munmap(low_desc, sizeof(desc));
@@ -275,6 +309,9 @@ static unsigned short load_gs(void)
unsigned short gs = (unsigned short)((desc.entry_number << 3) | 0x3);
asm volatile ("mov %0, %%gs" : : "rm" (gs));
return gs;
+ } else {
+ printf("[NOTE]\tno way to create a nonzero-based segment\n");
+ return 0;
}
}
@@ -516,6 +553,11 @@ static void test_ptrace_write_gsbase(void)
gs = ptrace(PTRACE_PEEKUSER, child, gs_offset, NULL);
+ if (*shared_scratch == 0) {
+ printf("[SKIP]\tCould not create a nonzero GS selector\n");
+ goto END;
+ }
+
if (gs != *shared_scratch) {
nerrs++;
printf("[FAIL]\tGS is not prepared with nonzero\n");
@@ -587,6 +629,11 @@ int main()
}
clearhandler(SIGILL);
+ /* Probe int $0x80 (32-bit syscall entry) */
+ have_int80 = probe_int80();
+ if (!have_int80)
+ printf("\tint $0x80 is unavailable (CONFIG_IA32_EMULATION=n?)\n");
+
sethandler(SIGSEGV, sigsegv, 0);
check_gs_value(0);
--
2.50.1
next reply other threads:[~2026-09-23 20:14 UTC|newest]
Thread overview: 2+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-23 20:14 Bjoern Doebel [this message]
2026-10-01 16:52 ` [PATCH v2] selftests/x86: Skip fsgsbase segment setup when int $0x80 is unavailable Bjoern Doebel
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=20260923201409.2187200-1-doebel@amazon.de \
--to=doebel@amazon.de \
--cc=bp@alien8.de \
--cc=dave.hansen@linux.intel.com \
--cc=hpa@zytor.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-kselftest@vger.kernel.org \
--cc=luto@kernel.org \
--cc=mingo@redhat.com \
--cc=peterz@infradead.org \
--cc=shuah@kernel.org \
--cc=stable@vger.kernel.org \
--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 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.