diff options
author | Andy Lutomirski <luto@amacapital.net> | 2014-07-03 18:19:55 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@amacapital.net> | 2014-07-03 18:19:55 -0700 |
commit | 54cda8df3f6970ce80fe068b0aa7b244841d0faa (patch) | |
tree | a8e164733aea3daa8310f5bdc7414a95d4ef4919 | |
parent | 2cb30ed696bae0d4bdd882b5be3e05d07beb166e (diff) | |
download | misc-tests-54cda8df3f6970ce80fe068b0aa7b244841d0faa.tar.gz |
Add syscall32_from_64
-rw-r--r-- | Makefile | 5 | ||||
-rw-r--r-- | syscall32_from_64.c | 22 | ||||
-rw-r--r-- | thunks.S | 60 |
3 files changed, 86 insertions, 1 deletions
@@ -7,7 +7,7 @@ SIMPLE_CC_TARGETS := evil-clock-test SPLIT_C_TARGETS := dump-vdso dump-vvar syscall_exit_regs SPLIT_CC_TARGETS := timing_test test_vsyscall -ALL_TARGETS := $(SIMPLE_C_TARGETS) $(SIMPLE_CC_TARGETS) $(SPLIT_C_TARGETS:%=%_64) $(SPLIT_CC_TARGETS:%=%_64) $(SPLIT_C_TARGETS:%=%_32) $(SPLIT_CC_TARGETS:%=%_32) +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 CFLAGS := -O2 -g -std=gnu99 -pthread -Wall CCFLAGS := -O2 -g -std=gnu++11 -pthread -Wall @@ -34,3 +34,6 @@ $(SPLIT_CC_TARGETS:%=%_32): %_32: %.cc $(SPLIT_CC_TARGETS:%=%_64): %_64: %.cc g++ -m64 -o $@ $(CCFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl + +syscall32_from_64: syscall32_from_64.c thunks.S + gcc -m64 -o $@ $(CFLAGS) $(EXTRA_CFLAGS) $^ -lrt -ldl diff --git a/syscall32_from_64.c b/syscall32_from_64.c new file mode 100644 index 0000000..775cef2 --- /dev/null +++ b/syscall32_from_64.c @@ -0,0 +1,22 @@ +#include <stdio.h> + +extern unsigned long call32_from_64(void *stack, void (*function)(void)); + +asm (".pushsection .text\n\t" + ".code32\n\t" + "syscall32:\n\t" + "mov $20,%eax\n\t" // NR_getpid (32-bit) + "syscall\n\t" + "syscall32_ret:\n\t" + "ret\n\t" + ".code64"); +extern void syscall32(void); + +static char low_stack[4096]; + +int main() +{ + unsigned long ret = call32_from_64(low_stack, syscall32); + printf("syscall return = %ld\n", (long)ret); + return 0; +} diff --git a/thunks.S b/thunks.S new file mode 100644 index 0000000..ab3a0a0 --- /dev/null +++ b/thunks.S @@ -0,0 +1,60 @@ + .text + + .global init_thunks + .type init_thunks, @function +init_thunks: + mov $0x2b, %rax /* USER32_DS */ + mov %rax,%ss + mov %rax,%ds + mov %rax,%es + ret +.size init_thunks, .-init_thunks + + .global call32_from_64 + .type call32_from_64, @function +call32_from_64: + // rdi: stack to use + // esi: function to call + + // Save registers + pushq %rbx + pushq %rbp + pushq %r12 + pushq %r13 + pushq %r14 + pushq %r15 + pushfq + + // Switch stacks + mov %rsp,(%rdi) + mov %rdi,%rsp + + // Switch to compatibility mode + pushq $0x23 /* USER32_CS */ + pushq $1f + lretq + +1: + .code32 + // Call the function + call *%esi + // Switch back to long mode + jmp $0x33,$1f + .code64 + +1: + // Restore the stack + mov (%rsp),%rsp + + // Restore registers + popfq + popq %r15 + popq %r14 + popq %r13 + popq %r12 + popq %rbp + popq %rbx + + ret + +.size call32_from_64, .-call32_from_64 |