diff options
author | Andy Lutomirski <luto@kernel.org> | 2015-04-23 15:10:38 -0700 |
---|---|---|
committer | Andy Lutomirski <luto@kernel.org> | 2015-04-23 15:10:38 -0700 |
commit | 1c236b677e1a83e2751c8882dd3cd0ffef29dd1c (patch) | |
tree | ddaa5ad442c5c2368f3e7ebd9ccac9d0cae51c60 | |
parent | 1c496dbfe2643b3fbdcc32ec1023bf9c312cfd53 (diff) | |
download | misc-tests-1c236b677e1a83e2751c8882dd3cd0ffef29dd1c.tar.gz |
sysret_ss_attrs: Commit 64-bit set_thread_area for posterity
Signed-off-by: Andy Lutomirski <luto@kernel.org>
-rw-r--r-- | sysret_ss_attrs.c | 41 |
1 files changed, 40 insertions, 1 deletions
diff --git a/sysret_ss_attrs.c b/sysret_ss_attrs.c index fa81ce2..9d80edd 100644 --- a/sysret_ss_attrs.c +++ b/sysret_ss_attrs.c @@ -18,6 +18,7 @@ #include <stdbool.h> #include <sys/ptrace.h> #include <sys/user.h> +#include <errno.h> #include <pthread.h> static unsigned short GDT3(int idx) @@ -25,6 +26,32 @@ static unsigned short GDT3(int idx) return (idx << 3) | 3; } +static int force_set_thread_area(struct user_desc *u_info) +{ +#ifdef __x86_64__ + int ret; + struct user_desc *low = mmap(NULL, sizeof(struct user_desc), + PROT_READ | PROT_WRITE, + MAP_ANONYMOUS | MAP_PRIVATE | MAP_32BIT, + -1, 0); + memcpy(low, u_info, sizeof(struct user_desc)); + /* Call the 32-bit set_thread_area (nr 243) using int80 */ + asm volatile ("int $0x80" + : "=a" (ret) : "a" (243), "b" (low) + : "memory"); + if (ret < 0) { + munmap(low, sizeof(struct user_desc)); + errno = -ret; + return -1; + } + memcpy(u_info, low, sizeof(struct user_desc)); + munmap(low, sizeof(struct user_desc)); + return ret; +#else + return syscall(SYS_set_thread_area, u_info); +#endif +} + static void *threadproc(void *ctx) { struct user_desc desc = { @@ -39,26 +66,38 @@ static void *threadproc(void *ctx) .useable = 0, }; - if (syscall(SYS_set_thread_area, &desc) != 0) + if (force_set_thread_area(&desc) != 0) err(1, "set_thread_area"); asm volatile ( "mov %%ax, %%ss\n\t" "1:\n\t" + /* "movl $0xbfffffff, %%eax\n\t" "int $0x80\n\t" + */ "jmp 1b" : : "a" (GDT3(desc.entry_number)) ); + return NULL; } + + int main() { + cpu_set_t cpuset; + CPU_ZERO(&cpuset); + CPU_SET(0, &cpuset); + sched_setaffinity(0, sizeof(cpuset), &cpuset); + pthread_t thread; if (pthread_create(&thread, 0, threadproc, 0) != 0) err(1, "pthread_create"); + pause(); + while (1) { usleep(1); } |