summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAndy Lutomirski <luto@kernel.org>2015-04-23 15:10:38 -0700
committerAndy Lutomirski <luto@kernel.org>2015-04-23 15:10:38 -0700
commit1c236b677e1a83e2751c8882dd3cd0ffef29dd1c (patch)
treeddaa5ad442c5c2368f3e7ebd9ccac9d0cae51c60
parent1c496dbfe2643b3fbdcc32ec1023bf9c312cfd53 (diff)
downloadmisc-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.c41
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);
}