UML guest SKAS4 support. diff --git a/arch/um/include/as-layout.h b/arch/um/include/as-layout.h index cac542d..929d053 100644 --- a/arch/um/include/as-layout.h +++ b/arch/um/include/as-layout.h @@ -23,16 +23,15 @@ */ #ifdef __ASSEMBLY__ -#define _AC(X, Y) (Y) +#define _C(Y) (Y) #else -#define __AC(X, Y) (X (Y)) -#define _AC(X, Y) __AC(X, Y) +#define _C(Y) ((unsigned long) (Y)) #endif -#define STUB_START _AC(, 0x100000) -#define STUB_CODE _AC((unsigned long), STUB_START) -#define STUB_DATA _AC((unsigned long), STUB_CODE + UM_KERN_PAGE_SIZE) -#define STUB_END _AC((unsigned long), STUB_DATA + UM_KERN_PAGE_SIZE) +#define STUB_START _C(0x100000) +#define STUB_CODE STUB_START +#define STUB_DATA (STUB_CODE + UM_KERN_PAGE_SIZE) +#define STUB_END (STUB_DATA + UM_KERN_PAGE_SIZE) #ifndef __ASSEMBLY__ diff --git a/arch/um/include/skas/mm_id.h b/arch/um/include/skas/mm_id.h index 48dd098..a2e7643 100644 --- a/arch/um/include/skas/mm_id.h +++ b/arch/um/include/skas/mm_id.h @@ -7,7 +7,7 @@ #define __MM_ID_H struct mm_id { - union { + struct { int mm_fd; int pid; } u; diff --git a/arch/um/include/skas/skas.h b/arch/um/include/skas/skas.h index 331f343..ea56428 100644 --- a/arch/um/include/skas/skas.h +++ b/arch/um/include/skas/skas.h @@ -6,9 +6,25 @@ #ifndef __SKAS_H #define __SKAS_H -#include "sysdep/ptrace.h" +#ifndef __KERNEL__ +#include <unistd.h> +#include <sys/syscall.h> +#endif +#include "uml-config.h" -extern int have_siginfo_segv; +#ifdef UML_CONFIG_X86_32 +#define __NR_new_mm 327 +#define __NR_switch_mm 328 +#else +#define __NR_new_mm 288 +#define __NR_switch_mm 289 +#endif + +#define PTRACE_SWITCH_MM 34 + +#ifndef __ASSEMBLY__ + +#include "sysdep/ptrace.h" #define STUB_ADDR(x) (STUB_CODE + (unsigned long) (x) - \ (unsigned long) &__syscall_stub_start) @@ -17,6 +33,11 @@ extern int userspace_pid[]; extern int proc_mm, ptrace_faultinfo, ptrace_ldt; extern int skas_needs_stub; +extern int have_switch_mm; +extern int have_ptrace_switch_mm; +extern int have_siginfo_segv; +extern int self_mm_fd; + extern int user_thread(unsigned long stack, int flags); extern void new_thread_handler(void); extern void handle_syscall(struct uml_pt_regs *regs); @@ -25,4 +46,45 @@ extern void get_skas_faultinfo(int pid, struct faultinfo * fi); extern long execute_syscall_skas(void *r); extern unsigned long current_stub_stack(void); +#ifndef __KERNEL__ +#include <errno.h> +#include <asm/user.h> + +struct user_regs { + unsigned long regs[MAX_REG_NR]; +#ifdef UML_CONFIG_X86_32 + struct user_fxsr_struct *fp_state; + struct user_fxsr_struct fpregs; +#else + struct user_i387_struct *fp_state; + struct user_i387_struct fpregs; +#endif +}; + +static inline long new_mm(void) +{ + int ret = syscall(__NR_new_mm, 0, 0, 0, 0, 0, 0); + + if (ret < 0) + return -errno; + + return ret; +} + +static inline long switch_mm(int mm_fd, struct user_regs *save_regs, + struct user_regs *new_regs, unsigned long ip, + unsigned long sp) +{ + int ret = syscall(__NR_switch_mm, mm_fd, save_regs, new_regs, ip, sp, + 0); + + if (ret < 0) + return -errno; + + return 0; +} +#endif + +#endif + #endif diff --git a/arch/um/kernel/reboot.c b/arch/um/kernel/reboot.c index 00197d3..a597b5d 100644 --- a/arch/um/kernel/reboot.c +++ b/arch/um/kernel/reboot.c @@ -12,7 +12,7 @@ void (*pm_power_off)(void); static void kill_off_processes(void) { - if (proc_mm) + if (proc_mm || have_switch_mm) /* * FIXME: need to loop over userspace_pids */ diff --git a/arch/um/kernel/skas/mmu.c b/arch/um/kernel/skas/mmu.c index 412fadc..5f4c32e 100644 --- a/arch/um/kernel/skas/mmu.c +++ b/arch/um/kernel/skas/mmu.c @@ -46,6 +46,9 @@ static int init_stub_pte(struct mm_struct *mm, unsigned long proc, return -ENOMEM; } +extern int copy_context_skas4(struct mm_id *id); +extern int get_new_mm(void); + int init_new_context(struct task_struct *task, struct mm_struct *mm) { struct mm_context *from_mm = NULL; @@ -71,6 +74,19 @@ int init_new_context(struct task_struct *task, struct mm_struct *mm) goto out_free; } to_mm->id.u.mm_fd = ret; + } else if (have_switch_mm) { + to_mm->id.u.mm_fd = get_new_mm(); + if (to_mm->id.u.mm_fd < 0) { + ret = to_mm->id.u.mm_fd; + goto out_free; + } + + ret = copy_context_skas4(&to_mm->id); + if (ret < 0) { + os_close_file(to_mm->id.u.mm_fd); + to_mm->id.u.mm_fd = -1; + goto out_free; + } } else { if (from_mm) @@ -167,7 +183,7 @@ void destroy_context(struct mm_struct *mm) { struct mm_context *mmu = &mm->context; - if (proc_mm) + if (proc_mm || have_switch_mm) os_close_file(mmu->id.u.mm_fd); else { /* diff --git a/arch/um/kernel/skas/process.c b/arch/um/kernel/skas/process.c index 4f63928..32e84d7 100644 --- a/arch/um/kernel/skas/process.c +++ b/arch/um/kernel/skas/process.c @@ -55,7 +55,7 @@ int __init start_uml(void) { stack_protections((unsigned long) &cpu0_irqstack); set_sigstack(cpu0_irqstack, THREAD_SIZE); - if (proc_mm) { + if (proc_mm || have_switch_mm) { userspace_pid[0] = start_userspace(0); if (userspace_pid[0] < 0) { printf("start_uml - start_userspace returned %d\n", diff --git a/arch/um/kernel/um_arch.c b/arch/um/kernel/um_arch.c index a6c1dd1..d00ebbd 100644 --- a/arch/um/kernel/um_arch.c +++ b/arch/um/kernel/um_arch.c @@ -284,7 +284,9 @@ int __init linux_main(int argc, char **argv) can_do_skas(); - if (proc_mm && ptrace_faultinfo) + if (have_switch_mm) + mode = "SKAS4"; + else if (proc_mm && ptrace_faultinfo) mode = "SKAS3"; else mode = "SKAS0"; diff --git a/arch/um/os-Linux/skas/mem.c b/arch/um/os-Linux/skas/mem.c index 384e43b..42a3026 100644 --- a/arch/um/os-Linux/skas/mem.c +++ b/arch/um/os-Linux/skas/mem.c @@ -6,6 +6,7 @@ #include <stddef.h> #include <unistd.h> #include <errno.h> +#include <signal.h> #include <string.h> #include <sys/mman.h> #include "init.h" @@ -22,7 +23,7 @@ #include "sysdep/stub.h" #include "uml-config.h" -extern unsigned long batch_syscall_stub, __syscall_stub_start; +extern unsigned long batch_syscall_stub, switch_mm_stub, __syscall_stub_start; extern void wait_stub_done(int pid); @@ -40,13 +41,9 @@ static unsigned long syscall_regs[MAX_REG_NR]; static int __init init_syscall_regs(void) { - unsigned long *stub_entry; - get_safe_registers(syscall_regs); - stub_entry = &batch_syscall_stub; - - syscall_regs[REGS_IP_INDEX] = STUB_ADDR(stub_entry); + syscall_regs[REGS_IP_INDEX] = STUB_ADDR(&batch_syscall_stub); return 0; } @@ -125,6 +122,32 @@ static long do_syscall_stub(struct mm_id *mm_idp, void **addr) return ret; } +long do_syscall_stub_skas4(struct mm_id *mm_idp, void **addr, unsigned long ip, + unsigned long sp) +{ + long ret; + struct user_regs return_regs; + unsigned long *ptr; + int err; + sigset_t sigs, old; + + ptr = (unsigned long *) (mm_idp->stack + UM_KERN_PAGE_SIZE - + sizeof(long)); + *ptr = (unsigned long) &return_regs; + *(ptr - 1) = self_mm_fd; + + sigfillset(&sigs); + sigprocmask(SIG_SETMASK, &sigs, &old); + err = switch_mm(mm_idp->u.mm_fd, &return_regs, NULL, ip, sp); + sigprocmask(SIG_SETMASK, &old, NULL); + + ret = syscall_stub_done(mm_idp->stack); + + *addr = check_init_stack(mm_idp, NULL); + + return ret; +} + static int flush_syscalls(struct mm_id *mm_idp, void **addr, int extra) { unsigned long *stack = check_init_stack(mm_idp, *addr); @@ -133,10 +156,17 @@ static int flush_syscalls(struct mm_id *mm_idp, void **addr, int extra) current = ((unsigned long) stack) & ~UM_KERN_PAGE_MASK; end = UM_KERN_PAGE_SIZE; + if (have_switch_mm) + end -= 2 * sizeof(long); + if (current + (10 + extra) * sizeof(long) < end) return 0; - return do_syscall_stub(mm_idp, addr); + if (have_switch_mm) + return do_syscall_stub_skas4(mm_idp, addr, + STUB_ADDR(&switch_mm_stub), 0); + else + return do_syscall_stub(mm_idp, addr); } long run_syscall_stub(struct mm_id *mm_idp, int syscall, @@ -165,11 +195,18 @@ long run_syscall_stub(struct mm_id *mm_idp, int syscall, *stack++ = expected; *stack = 0; - if (done) + if (!done) { + *addr = stack; + return 0; + } + + if (have_switch_mm) + return do_syscall_stub_skas4(mm_idp, addr, + STUB_ADDR(&switch_mm_stub), 0); + else return do_syscall_stub(mm_idp, addr); *addr = stack; - return 0; } diff --git a/arch/um/os-Linux/skas/process.c b/arch/um/os-Linux/skas/process.c index 08297ae..23a9b42 100644 --- a/arch/um/os-Linux/skas/process.c +++ b/arch/um/os-Linux/skas/process.c @@ -262,7 +262,7 @@ static int userspace_tramp(void *stack) } } } - if (!ptrace_faultinfo && (stack != NULL)) { + if (!ptrace_faultinfo) { struct sigaction sa; unsigned long v = STUB_ADDR(stub_segv_handler); @@ -306,7 +306,7 @@ int start_userspace(unsigned long stub_stack) sp = (unsigned long) stack + UM_KERN_PAGE_SIZE - sizeof(void *); flags = CLONE_FILES; - if (proc_mm) + if (proc_mm || have_switch_mm) flags |= CLONE_VM; else flags |= SIGCHLD; @@ -569,6 +569,56 @@ int copy_context_skas0(unsigned long new_stack, int pid) return err; } +extern unsigned long switch_mm_stub; +extern long task_size; + +static void unmap_new_as(void) +{ + void (*p)(void); + void *addr; + unsigned long stack = (unsigned long) &stack & ~(UM_KERN_PAGE_SIZE - 1); + unsigned long long data_offset, code_offset; + int fd = phys_mapping(to_phys((void *) stack), &data_offset); + + addr = mmap((void *) STUB_DATA, UM_KERN_PAGE_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, + data_offset); + if (addr == MAP_FAILED) + panic("Failed to remap stack"); + + fd = phys_mapping(to_phys(&__syscall_stub_start), &code_offset); + addr = mmap((void *) STUB_CODE, UM_KERN_PAGE_SIZE, + PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, + code_offset); + if (addr == MAP_FAILED) + panic("Failed to remap code"); + + p = (void (*)(void)) (STUB_ADDR(&switch_mm_stub)); + (*p)(); +} + +extern long do_syscall_stub_skas4(struct mm_id *mm_idp, void **addr, + unsigned long ip, unsigned long sp); + +int copy_context_skas4(struct mm_id *id) +{ + void *data = NULL; + int err; + + err = unmap(id, 0, STUB_START, 0, &data); + if (err) + return err; + + if (STUB_END < task_size) { + err = unmap(id, STUB_END, task_size - STUB_END, 0, &data); + if (err) + return err; + } + + return do_syscall_stub_skas4(id, &data, (unsigned long) unmap_new_as, + id->stack + UM_KERN_PAGE_SIZE / 2); +} + /* * This is used only, if stub pages are needed, while proc_mm is * available. Opening /proc/mm creates a new mm_context, which lacks @@ -738,6 +788,11 @@ void __switch_mm(struct mm_id *mm_idp) "failed, errno = %d\n", errno); fatal_sigsegv(); } - } - else userspace_pid[0] = mm_idp->u.pid; + } else if (have_ptrace_switch_mm) { + err = ptrace(PTRACE_SWITCH_MM, userspace_pid[0], 0, + mm_idp->u.mm_fd); + if (err) + panic("__switch_mm - PTRACE_SWITCH_MM " + "failed, errno = %d\n", errno); + } else userspace_pid[0] = mm_idp->u.pid; } diff --git a/arch/um/os-Linux/start_up.c b/arch/um/os-Linux/start_up.c index 81e1333..021d41c 100644 --- a/arch/um/os-Linux/start_up.c +++ b/arch/um/os-Linux/start_up.c @@ -162,6 +162,9 @@ static int disable_switch_mm; int have_siginfo_segv; static int disable_siginfo_segv; +int have_ptrace_switch_mm; +static int disable_ptrace_switch_mm; + int skas_needs_stub; static int __init skas0_cmd_param(char *str, int* add) @@ -169,8 +172,10 @@ static int __init skas0_cmd_param(char *str, int* add) disable_ptrace_faultinfo = 1; disable_ptrace_ldt = 1; disable_proc_mm = 1; + disable_switch_mm = 1; disable_siginfo_segv = 1; + disable_ptrace_switch_mm = 1; return 0; } @@ -415,7 +420,7 @@ __uml_setup("noptraceldt", noptraceldt_cmd_param, " To support PTRACE_LDT, the host needs to be patched using\n" " the current skas3 patch.\n\n"); -static inline void check_skas3_ptrace_faultinfo(void) +static inline void __init check_skas3_ptrace_faultinfo(void) { struct ptrace_faultinfo fi; int pid, n; @@ -439,7 +444,7 @@ static inline void check_skas3_ptrace_faultinfo(void) stop_ptraced_child(pid, 1, 1); } -static inline void check_skas3_ptrace_ldt(void) +static inline void __init check_skas3_ptrace_ldt(void) { #ifdef PTRACE_LDT int pid, n; @@ -470,7 +475,7 @@ static inline void check_skas3_ptrace_ldt(void) #endif } -static inline void check_skas3_proc_mm(void) +static inline void __init check_skas3_proc_mm(void) { non_fatal(" - /proc/mm..."); if (access("/proc/mm", W_OK) < 0) @@ -483,6 +488,19 @@ static inline void check_skas3_proc_mm(void) } } +static void __init can_do_skas3(void) +{ + non_fatal("Checking for the skas3 patch in the host:\n"); + + check_skas3_proc_mm(); + check_skas3_ptrace_faultinfo(); + check_skas3_ptrace_ldt(); + + if (!proc_mm || (!ptrace_faultinfo && !have_siginfo_segv) || + !ptrace_ldt) + skas_needs_stub = 1; +} + static void *fault_address; static int check_fault_info(struct faultinfo *fi) @@ -493,7 +511,7 @@ static int check_fault_info(struct faultinfo *fi) static jmp_buf siginfo_buf; -static void segv_handler(int sig, siginfo_t *si, void *foo) +static void __init segv_handler(int sig, siginfo_t *si, void *foo) { struct faultinfo fi; int n; @@ -503,7 +521,7 @@ static void segv_handler(int sig, siginfo_t *si, void *foo) longjmp(siginfo_buf, n); } -static int fault(void) +static int __init fault(void) { struct sigaction sa, old; int err, n; @@ -557,7 +575,7 @@ __uml_setup("nogetsiginfo", nogetsiginfo_cmd_param, #define PTRACE_GETSIGINFO 0x4202 #endif -static int check_siginfo(void) +static int __init check_siginfo(void) { siginfo_t si; struct faultinfo fi; @@ -607,25 +625,213 @@ static int check_siginfo(void) if (disable_siginfo_segv) non_fatal("Extended PTRACE_GETSIGINFO disabled on command " - "line"); + "line\n"); else have_siginfo_segv = 1; return ok; } -void can_do_skas(void) +static struct user_regs return_regs; +int self_mm_fd; + +static int switch_mm_works; + +static void after_switch(void) { - non_fatal("Checking for the skas3 patch in the host:\n"); + /* + * If we are really in a new address space, setting this to + * zero won't affect the value of 1 already set in the old + * address space. + */ + switch_mm_works = 0; - check_skas3_proc_mm(); - check_skas3_ptrace_faultinfo(); - check_skas3_ptrace_ldt(); - check_siginfo(); + switch_mm(self_mm_fd, NULL, &return_regs, 0, 0); +} - if (!proc_mm || (!ptrace_faultinfo && !have_siginfo_segv) || - !ptrace_ldt) +static int __init check_switch_mm(void) +{ + char *mm_stack; + int err, there = -1; + + non_fatal("\t/proc/self/mm ... "); + self_mm_fd = open("/proc/self/mm", O_RDONLY); + if (self_mm_fd < 0) + goto bad; + non_fatal("OK\n"); + + mm_stack = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_PRIVATE | MAP_ANONYMOUS, -1, 0); + if (mm_stack == MAP_FAILED) + goto bad; + + non_fatal("\tnew_mm ... "); + there = new_mm(); + if (there < 0) + goto bad_unmap; + non_fatal("OK\n"); + + switch_mm_works = 1; + + non_fatal("\tswitching over ... "); + err = switch_mm(there, &return_regs, NULL, (unsigned long) after_switch, + ((unsigned long) &mm_stack[UM_KERN_PAGE_SIZE]) - + sizeof(void *)); + if (err < 0) + goto bad_close; + non_fatal("switched back ... "); + if (!switch_mm_works) + goto bad_close; + else + non_fatal("OK\n"); + + munmap(mm_stack, UM_KERN_PAGE_SIZE); + close(there); + + if (disable_switch_mm) + non_fatal("switch_mm support disabled on command line\n"); + else + have_switch_mm = 1; + + return 1; + bad_close: + if (there > 0) + close(there); + bad_unmap: + munmap(mm_stack, UM_KERN_PAGE_SIZE); + bad: + non_fatal("Failed - \n"); + perror(""); + return 0; +} + +static int ptrace_switch_mm_works; + +static int __init after_ptrace_switch(void) +{ + ptrace_switch_mm_works = 1; + exit(0); +} + +static int __init check_ptrace_switch_mm(void) +{ + void *stack; + unsigned long regs[MAX_REG_NR]; + int pid, here, err, status; + + non_fatal("\tPTRACE_SWITCH_MM ... "); + pid = fork(); + if (pid == 0){ + ptrace(PTRACE_TRACEME, 0, 0, 0); + kill(getpid(), SIGSTOP); + + exit(0); + } + else if (pid < 0) + goto bad; + + stack = mmap(NULL, UM_KERN_PAGE_SIZE, PROT_READ | PROT_WRITE, + MAP_SHARED | MAP_ANONYMOUS, -1, 0); + if (stack == MAP_FAILED) + goto bad; + + here = open("/proc/self/mm", O_RDONLY); + if (here < 0) + goto bad_unmap; + + err = waitpid(pid, &status, WUNTRACED); + if (err < 0) + goto bad_close; + else if (err != pid) { + non_fatal("waitpid returned %d, expected %d\n", err, pid); + goto bad_close; + } else if (!WIFSTOPPED(status) || (WSTOPSIG(status) != SIGSTOP)) { + non_fatal("waitpid returned status 0x%d\n", status); + goto bad_close; + } + + err = ptrace(PTRACE_GETREGS, pid, 0, regs); + if (err < 0) + goto bad_close; + + regs[REGS_IP_INDEX] = (unsigned long) after_ptrace_switch; + regs[REGS_SP_INDEX] = (unsigned long) stack + UM_KERN_PAGE_SIZE - + sizeof(void *); + + if (ptrace(PTRACE_SETREGS, pid, 0, regs) < 0) + goto bad_close; + + if (ptrace(PTRACE_SWITCH_MM, pid, NULL, here) < 0) + goto bad_close; + + if (ptrace(PTRACE_CONT, pid, NULL, 0) < 0) + goto bad_close; + + err = waitpid(pid, &status, WUNTRACED); + if (err < 0) + goto bad_close; + else if(err != pid) { + non_fatal("waitpid returned %d, expected %d\n", err, pid); + goto bad_close; + } else if (!WIFEXITED(status) || (WEXITSTATUS(status) != 0)) { + non_fatal("waitpid returned status 0x%d\n", status); + goto bad_close; + } + + if (!ptrace_switch_mm_works) + goto bad_close; + else + non_fatal("OK\n"); + + if (disable_ptrace_switch_mm) + non_fatal("PTRACE_SWITCH_MM support disabled on command " + "line\n"); + else + have_ptrace_switch_mm = 1; + + close(here); + munmap(stack, UM_KERN_PAGE_SIZE); + + return 1; + + bad_close: + close(here); + bad_unmap: + munmap(stack, UM_KERN_PAGE_SIZE); + bad: + non_fatal("Failed - \n"); + perror(""); + return 0; +} + +static int __init can_do_skas4(void) +{ + int ret; + + non_fatal("Checking for SKAS4 support in the host:\n"); + + ret = check_switch_mm() && check_ptrace_switch_mm() && check_siginfo(); + if (ret) skas_needs_stub = 1; + + return ret; +} + +void __init can_do_skas(void) +{ + if (!can_do_skas4()) + can_do_skas3(); +} + +int get_new_mm(void) +{ + int err; + + err = new_mm(); + if (err < 0) + err = -errno; + + return err; } int __init parse_iomem(char *str, int *add) diff --git a/arch/um/sys-i386/stub.S b/arch/um/sys-i386/stub.S index a63397f..117462e 100644 --- a/arch/um/sys-i386/stub.S +++ b/arch/um/sys-i386/stub.S @@ -1,5 +1,6 @@ #include "uml-config.h" #include "as-layout.h" +#include "skas/skas.h" #define PROCESS_LIST \ /* load pointer to first operation */ \ @@ -43,3 +44,17 @@ batch_syscall_stub: PROCESS_LIST /* stop */ int3 + + .globl switch_mm_stub +switch_mm_stub: + PROCESS_LIST + + mov $__NR_switch_mm, %eax + mov STUB_DATA + UM_KERN_PAGE_SIZE - 8, %ebx + xor %ecx, %ecx + mov STUB_DATA + UM_KERN_PAGE_SIZE - 4, %edx + xor %esi, %esi + xor %edi, %edi + int $0x80 + + int3 diff --git a/arch/um/sys-x86_64/stub.S b/arch/um/sys-x86_64/stub.S index 69460e6..b4043b0 100644 --- a/arch/um/sys-x86_64/stub.S +++ b/arch/um/sys-x86_64/stub.S @@ -1,5 +1,6 @@ #include "uml-config.h" #include "as-layout.h" +#include "skas/skas.h" #define PROCESS_LIST \ mov $(STUB_DATA >> 32), %rbx; \ @@ -46,3 +47,22 @@ batch_syscall_stub: PROCESS_LIST /* stop */ int3 + + .globl switch_mm_stub +switch_mm_stub: + PROCESS_LIST + + mov $__NR_switch_mm, %rax + mov $(STUB_DATA >> 32), %rdi + sal $32, %rdi + mov $(STUB_DATA & 0xffffffff + 4096 - 8), %rsi + add %rdi, %rsi + mov (%rsi), %rdx + sub $8, %rsi + mov (%rsi), %rdi + xor %rsi, %rsi + xor %r10, %r10 + xor %r8, %r8 + syscall + + int3 diff --git a/arch/um/sys-x86_64/syscalls.c b/arch/um/sys-x86_64/syscalls.c index f1199fd..e861ad6 100644 --- a/arch/um/sys-x86_64/syscalls.c +++ b/arch/um/sys-x86_64/syscalls.c @@ -30,7 +30,7 @@ long arch_prctl(struct task_struct *task, int code, unsigned long __user *addr) { unsigned long *ptr = addr, tmp; long ret; - int pid = task->mm->context.id.u.pid; + int pid = userspace_pid[0]; /* * With ARCH_SET_FS (and ARCH_SET_GS is treated similarly to
------------------------------------------------------------------------- This SF.net email is sponsored by: Microsoft Defy all challenges. Microsoft(R) Visual Studio 2008. http://clk.atdmt.com/MRT/go/vse0120000070mrt/direct/01/ _______________________________________________ User-mode-linux-user mailing list User-mode-linux-user@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/user-mode-linux-user