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
reply other threads:[~2026-09-23 20:14 UTC|newest]
Thread overview: [no followups] expand[flat|nested] mbox.gz Atom feed
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 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®