[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <tip-1b6858d5a2eb2485761f06bd48055ed5bed08464@git.kernel.org>
Date: Sat, 22 Jun 2019 03:04:47 -0700
From: "tip-bot for Chang S. Bae" <tipbot@...or.com>
To: linux-tip-commits@...r.kernel.org
Cc: ak@...ux.intel.com, tglx@...utronix.de,
linux-kernel@...r.kernel.org, luto@...nel.org, hpa@...or.com,
chang.seok.bae@...el.com, ravi.v.shankar@...el.com,
mingo@...nel.org
Subject: [tip:x86/cpu] selftests/x86/fsgsbase: Test ptracer-induced GSBASE
write
Commit-ID: 1b6858d5a2eb2485761f06bd48055ed5bed08464
Gitweb: https://git.kernel.org/tip/1b6858d5a2eb2485761f06bd48055ed5bed08464
Author: Chang S. Bae <chang.seok.bae@...el.com>
AuthorDate: Wed, 8 May 2019 03:02:17 -0700
Committer: Thomas Gleixner <tglx@...utronix.de>
CommitDate: Sat, 22 Jun 2019 11:38:51 +0200
selftests/x86/fsgsbase: Test ptracer-induced GSBASE write
The test validates that the selector is not changed when a ptracer writes
the ptracee's GSBASE.
Suggested-by: Andy Lutomirski <luto@...nel.org>
Signed-off-by: Chang S. Bae <chang.seok.bae@...el.com>
Signed-off-by: Thomas Gleixner <tglx@...utronix.de>
Cc: "H . Peter Anvin" <hpa@...or.com>
Cc: Andi Kleen <ak@...ux.intel.com>
Cc: Ravi Shankar <ravi.v.shankar@...el.com>
Cc: H. Peter Anvin <hpa@...or.com>
Link: https://lkml.kernel.org/r/1557309753-24073-3-git-send-email-chang.seok.bae@intel.com
---
tools/testing/selftests/x86/fsgsbase.c | 70 ++++++++++++++++++++++++++++++++++
1 file changed, 70 insertions(+)
diff --git a/tools/testing/selftests/x86/fsgsbase.c b/tools/testing/selftests/x86/fsgsbase.c
index af85bd4752a5..b02ddce49bbb 100644
--- a/tools/testing/selftests/x86/fsgsbase.c
+++ b/tools/testing/selftests/x86/fsgsbase.c
@@ -23,6 +23,9 @@
#include <pthread.h>
#include <asm/ldt.h>
#include <sys/mman.h>
+#include <stddef.h>
+#include <sys/ptrace.h>
+#include <sys/wait.h>
#ifndef __x86_64__
# error This test is 64-bit only
@@ -367,6 +370,71 @@ static void test_unexpected_base(void)
}
}
+#define USER_REGS_OFFSET(r) offsetof(struct user_regs_struct, r)
+
+static void test_ptrace_write_gsbase(void)
+{
+ int status;
+ pid_t child = fork();
+
+ if (child < 0)
+ err(1, "fork");
+
+ if (child == 0) {
+ printf("[RUN]\tPTRACE_POKE(), write GSBASE from ptracer\n");
+
+ /*
+ * Use the LDT setup and fetch the GSBASE from the LDT
+ * by switching to the (nonzero) selector (again)
+ */
+ do_unexpected_base();
+ asm volatile ("mov %0, %%gs" : : "rm" ((unsigned short)0x7));
+
+ if (ptrace(PTRACE_TRACEME, 0, NULL, NULL) != 0)
+ err(1, "PTRACE_TRACEME");
+
+ raise(SIGTRAP);
+ _exit(0);
+ }
+
+ wait(&status);
+
+ if (WSTOPSIG(status) == SIGTRAP) {
+ unsigned long gs;
+ unsigned long gs_offset = USER_REGS_OFFSET(gs);
+ unsigned long base_offset = USER_REGS_OFFSET(gs_base);
+
+ gs = ptrace(PTRACE_PEEKUSER, child, gs_offset, NULL);
+
+ if (gs != 0x7) {
+ nerrs++;
+ printf("[FAIL]\tGS is not prepared with nonzero\n");
+ goto END;
+ }
+
+ if (ptrace(PTRACE_POKEUSER, child, base_offset, 0xFF) != 0)
+ err(1, "PTRACE_POKEUSER");
+
+ gs = ptrace(PTRACE_PEEKUSER, child, gs_offset, NULL);
+
+ /*
+ * In a non-FSGSBASE system, the nonzero selector will load
+ * GSBASE (again). But what is tested here is whether the
+ * selector value is changed or not by the GSBASE write in
+ * a ptracer.
+ */
+ if (gs != 0x7) {
+ nerrs++;
+ printf("[FAIL]\tGS changed to %lx\n", gs);
+ } else {
+ printf("[OK]\tGS remained 0x7\n");
+ }
+ }
+
+END:
+ ptrace(PTRACE_CONT, child, NULL, NULL);
+}
+
int main()
{
pthread_t thread;
@@ -423,5 +491,7 @@ int main()
if (pthread_join(thread, NULL) != 0)
err(1, "pthread_join");
+ test_ptrace_write_gsbase();
+
return nerrs == 0 ? 0 : 1;
}
Powered by blists - more mailing lists