#define _GNU_SOURCE #include #include #include #include #include #include #include int var = 9; int status = 0; void print_base(char *who) { unsigned long base; int val; syscall(SYS_arch_prctl, ARCH_GET_GS, &base); asm("movl %%gs:0,%0":"=r"(val)); printf("%s:\tbase %16lx val %d var %p\n", who, base, val, &var); if (val != var) status = 1; } int main(int argc, char *argv[]) { unsigned short entry = 1; unsigned short selector = (entry*8) | 0x4; struct user_desc desc = { .entry_number = entry, .base_addr = (unsigned) (uintptr_t) &var, .limit = 0xfffffffful, .contents = MODIFY_LDT_CONTENTS_DATA, .read_exec_only = 0, .limit_in_pages = 1, .seg_not_present = 0, .useable = 1, }; pid_t pid; int i; if (syscall(SYS_modify_ldt, 0x11, &desc, sizeof(desc))) perror("modify_ldt"); #if 1 syscall(SYS_arch_prctl, ARCH_SET_GS, &argc); #else syscall(SYS_arch_prctl, ARCH_SET_GS, &status); #endif asm volatile("movw %w0,%%gs"::"q"(selector)); print_base("parent"); #if 0 { struct timespec ts = {0, 1000000}; nanosleep(&ts, NULL); } #endif pid = syscall(SYS_fork); print_base(pid ? "parent" : "child"); asm volatile("movw %w0,%%gs"::"q"(selector)); print_base(pid ? "parent" : "child"); if (pid) waitpid(pid, &status, 0); return status != 0; }