summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2015-04-17 14:05:54 -0700
committerAndy Lutomirski <luto@kernel.org>2015-04-17 14:16:00 -0700
commitf67708ab5f6432af863b3fa3f405bd120c492fb7 (patch)
treee3acb94766601ad1afe057c5894f8410dc075639
parent6522dfcac5dfbf2ad31920d529a2a42d57359b6f (diff)
downloadmisc-tests-f67708ab5f6432af863b3fa3f405bd120c492fb7.tar.gz
gsbase: new test
Signed-off-by: Andy Lutomirski <luto@kernel.org>
-rw-r--r--.gitignore1
-rw-r--r--Makefile2
-rw-r--r--gsbase.c79
3 files changed, 81 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index 3f62f08..a1fe161 100644
--- a/.gitignore
+++ b/.gitignore
@@ -7,6 +7,7 @@ user_visible_state
highsys
null_seccomp
segregs
+gsbase
*~
*_32
*_64
diff --git a/Makefile b/Makefile
index f602715..5896c92 100644
--- a/Makefile
+++ b/Makefile
@@ -1,6 +1,6 @@
.PHONY: all clean
-SIMPLE_C_TARGETS := dump-vsyscall context_switch_latency kernel_pf user_visible_state null_seccomp highsys
+SIMPLE_C_TARGETS := dump-vsyscall context_switch_latency kernel_pf user_visible_state null_seccomp highsys gsbase
SIMPLE_CC_TARGETS := evil-clock-test
diff --git a/gsbase.c b/gsbase.c
new file mode 100644
index 0000000..87e4407
--- /dev/null
+++ b/gsbase.c
@@ -0,0 +1,79 @@
+/*
+ * gsbase.c, a gsbase test
+ * Copyright (c) 2014 Andy Lutomirski
+ * GPL v2
+ */
+
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <err.h>
+#include <sys/user.h>
+#include <asm/prctl.h>
+#include <sys/prctl.h>
+#include <sys/mman.h>
+
+#ifndef __x86_64__
+# error This test is 64-bit only
+#endif
+
+static unsigned char *testptr, *testptr2;
+
+static unsigned char read_gs_testvals(void)
+{
+ unsigned char ret;
+ asm volatile ("movb %%gs:%1, %0" : "=r" (ret) : "m" (*testptr));
+ return ret;
+}
+
+int main()
+{
+ int errors = 0;
+
+ testptr = mmap((void *)0x200000000UL, 1, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
+ if (testptr == MAP_FAILED)
+ err(1, "mmap");
+
+ testptr2 = mmap((void *)0x300000000UL, 1, PROT_READ | PROT_WRITE,
+ MAP_PRIVATE | MAP_FIXED | MAP_ANONYMOUS, -1, 0);
+ if (testptr2 == MAP_FAILED)
+ err(1, "mmap");
+
+ *testptr = 0;
+ *testptr2 = 1;
+
+ if (syscall(SYS_arch_prctl, ARCH_SET_GS,
+ (unsigned long)testptr2 - (unsigned long)testptr) != 0)
+ err(1, "ARCH_SET_GS");
+
+ usleep(100);
+
+ if (read_gs_testvals() == 1) {
+ printf("[OK]\tARCH_SET_GS worked\n");
+ } else {
+ printf("[FAIL]\tARCH_SET_GS failed\n");
+ errors++;
+ }
+
+ asm volatile ("mov %0,%%gs" : : "r" (0));
+
+ if (read_gs_testvals() == 0) {
+ printf("[OK]\tWriting 0 to gs worked\n");
+ } else {
+ printf("[FAIL]\tWriting 0 to gs failed\n");
+ errors++;
+ }
+
+ usleep(100);
+
+ if (read_gs_testvals() == 0) {
+ printf("[OK]\tgsbase is still zero\n");
+ } else {
+ printf("[FAIL]\tgsbase reset itself to 1\n");
+ errors++;
+ }
+
+ return errors == 0 ? 0 : 1;
+}