diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-12-08 11:13:00 -0800 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-12-08 11:14:09 -0800 |
commit | fdde65981140f47ed5980e9894754141f5340557 (patch) | |
tree | 77059422ec2ef3b4bb4f081b12089234e540a936 | |
parent | 8bf0f3233d8433a1b376175dc7753e7e146abda1 (diff) | |
download | misc-tests-fdde65981140f47ed5980e9894754141f5340557.tar.gz |
segregs: New test
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | segregs.c | 70 |
3 files changed, 75 insertions, 1 deletions
@@ -6,6 +6,7 @@ kernel_pf user_visible_state highsys null_seccomp +segregs *~ *_32 *_64 @@ -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; + } +} |