summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@amacapital.net>2014-12-08 11:13:00 -0800
committerAndy Lutomirski <luto@amacapital.net>2014-12-08 11:14:09 -0800
commitfdde65981140f47ed5980e9894754141f5340557 (patch)
tree77059422ec2ef3b4bb4f081b12089234e540a936
parent8bf0f3233d8433a1b376175dc7753e7e146abda1 (diff)
downloadmisc-tests-fdde65981140f47ed5980e9894754141f5340557.tar.gz
segregs: New test
-rw-r--r--.gitignore1
-rw-r--r--Makefile5
-rw-r--r--segregs.c70
3 files changed, 75 insertions, 1 deletions
diff --git a/.gitignore b/.gitignore
index a0587a1..3f62f08 100644
--- a/.gitignore
+++ b/.gitignore
@@ -6,6 +6,7 @@ kernel_pf
user_visible_state
highsys
null_seccomp
+segregs
*~
*_32
*_64
diff --git a/Makefile b/Makefile
index 934516a..2353f8c 100644
--- a/Makefile
+++ b/Makefile
@@ -7,7 +7,7 @@ SIMPLE_CC_TARGETS := evil-clock-test
SPLIT_C_TARGETS := dump-vdso dump-vvar syscall_exit_regs sigreturn dump_all_pmcs
SPLIT_CC_TARGETS := timing_test test_vsyscall test_vdso_parser
-ALL_TARGETS := $(SIMPLE_C_TARGETS) $(SIMPLE_CC_TARGETS) $(SPLIT_C_TARGETS:%=%_64) $(SPLIT_CC_TARGETS:%=%_64) $(SPLIT_C_TARGETS:%=%_32) $(SPLIT_CC_TARGETS:%=%_32) syscall32_from_64
+ALL_TARGETS := $(SIMPLE_C_TARGETS) $(SIMPLE_CC_TARGETS) $(SPLIT_C_TARGETS:%=%_64) $(SPLIT_CC_TARGETS:%=%_64) $(SPLIT_C_TARGETS:%=%_32) $(SPLIT_CC_TARGETS:%=%_32) syscall32_from_64 segregs
CFLAGS := -O2 -g -std=gnu99 -pthread -Wall
CCFLAGS := -O2 -g -std=gnu++11 -pthread -Wall
@@ -20,6 +20,9 @@ clean:
$(SIMPLE_C_TARGETS): %: %.c
gcc -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
+segregs: segregs.c
+ gcc -o $@ $(CFLAGS) $(EXTRA_CFLAGS) -m32 $^ -lrt -ldl
+
$(SIMPLE_CC_TARGETS): %: %.cc
g++ -o $@ $(CCFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl
diff --git a/segregs.c b/segregs.c
new file mode 100644
index 0000000..d6fdff1
--- /dev/null
+++ b/segregs.c
@@ -0,0 +1,70 @@
+#include <stdio.h>
+#include <stdbool.h>
+#include <sys/syscall.h>
+#include <unistd.h>
+#include <asm/ldt.h>
+#include <err.h>
+#include <sys/user.h>
+
+#ifdef __x86_64__
+# error This test is 32-bit only
+#endif
+
+static unsigned short GDT3(int idx)
+{
+ return (idx << 3) | 3;
+}
+
+static int create_tls(int idx, unsigned int base)
+{
+ struct user_desc desc = {
+ .entry_number = idx,
+ .base_addr = base,
+ .limit = 0xfffff,
+ .seg_32bit = 1,
+ .contents = 0, /* Data, grow-up */
+ .read_exec_only = 0,
+ .limit_in_pages = 1,
+ .seg_not_present = 0,
+ .useable = 0,
+ };
+
+ if (syscall(SYS_set_thread_area, &desc) != 0)
+ err(1, "set_thread_area");
+
+ return desc.entry_number;
+}
+
+int main()
+{
+ int idx = create_tls(-1, 0);
+ printf("Allocated GDT index %d\n", idx);
+
+ unsigned short orig_es;
+ asm volatile ("mov %%es,%0" : "=rm" (orig_es));
+
+ int errors = 0;
+ int total = 1000;
+ for (int i = 0; i < total; i++) {
+ asm volatile ("mov %0,%%es" : : "rm" (GDT3(idx)));
+ usleep(100);
+
+ unsigned short es;
+ asm volatile ("mov %%es,%0" : "=rm" (es));
+ asm volatile ("mov %0,%%es" : : "rm" (orig_es));
+ if (es != GDT3(idx)) {
+ if (errors == 0)
+ printf("[FAIL]\tES changed from 0x%hx to 0x%hx\n",
+ GDT3(idx), es);
+ errors++;
+ }
+ }
+
+ if (errors) {
+ printf("[FAIL]\tES was corrupted %d/%d times\n", errors, total);
+ return 1;
+ } else {
+ printf("[OK]\tES was preserved\n");
+ return 0;
+ }
+}