From a1a290060609c38a4ffd40846b12e555ddb50a40 Mon Sep 17 00:00:00 2001 From: Ken Sato Date: Wed, 27 Sep 2017 17:02:30 +0900 Subject: [PATCH] ptrace: Fix the timing of save_fp_regs, and Add copy fp_regs to child in clone_thread refs #702 --- arch/x86/kernel/cpu.c | 35 +++++++++++++++++++++++++++-------- arch/x86/kernel/syscall.c | 3 --- kernel/process.c | 5 +++++ 3 files changed, 32 insertions(+), 11 deletions(-) diff --git a/arch/x86/kernel/cpu.c b/arch/x86/kernel/cpu.c index 347d7321..b881f34a 100644 --- a/arch/x86/kernel/cpu.c +++ b/arch/x86/kernel/cpu.c @@ -1648,13 +1648,11 @@ release_fp_regs(struct thread *thread) thread->fp_regs = NULL; } -/*@ - @ requires \valid(thread); - @*/ -void -save_fp_regs(struct thread *thread) +static int +check_and_allocate_fp_regs(struct thread *thread) { - int pages; + int pages; + int result = 0; if (!thread->fp_regs) { pages = (xsave_size + (PAGE_SIZE - 1)) >> PAGE_SHIFT; @@ -1663,12 +1661,26 @@ save_fp_regs(struct thread *thread) if (!thread->fp_regs) { kprintf("error: allocating fp_regs pages\n"); - return; + result = 1; + goto out; } - memset(thread->fp_regs, 0, sizeof(fp_regs_struct)); memset(thread->fp_regs, 0, pages * PAGE_SIZE); } +out: + return result; +} + +/*@ + @ requires \valid(thread); + @*/ +void +save_fp_regs(struct thread *thread) +{ + if (check_and_allocate_fp_regs(thread) != 0) { + // alloc error + return; + } if (xsave_available) { unsigned int low, high; @@ -1684,6 +1696,13 @@ save_fp_regs(struct thread *thread) } } +void copy_fp_regs(struct thread *from, struct thread *to) +{ + if ((from->fp_regs != NULL) && (check_and_allocate_fp_regs(to) == 0)) { + memcpy(to->fp_regs, from->fp_regs, sizeof(fp_regs_struct)); + } +} + #ifdef POSTK_DEBUG_TEMP_FIX_19 void clear_fp_regs(struct thread *thread) diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 4f054b3d..aa4d8e52 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -33,7 +33,6 @@ void terminate(int, int); extern long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact); long syscall(int num, ihk_mc_user_context_t *ctx); -extern void save_fp_regs(struct thread *proc); void set_signal(int sig, void *regs0, siginfo_t *info); void check_signal(unsigned long rc, void *regs0, int num); extern unsigned long do_fork(int, unsigned long, unsigned long, unsigned long, @@ -460,7 +459,6 @@ void set_single_step(struct thread *thread) long ptrace_read_fpregs(struct thread *thread, void *fpregs) { - save_fp_regs(thread); if (thread->fp_regs == NULL) { return -ENOMEM; } @@ -470,7 +468,6 @@ long ptrace_read_fpregs(struct thread *thread, void *fpregs) long ptrace_write_fpregs(struct thread *thread, void *fpregs) { - save_fp_regs(thread); if (thread->fp_regs == NULL) { return -ENOMEM; } diff --git a/kernel/process.c b/kernel/process.c index f0eb8bd8..fdfabcd3 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -62,6 +62,7 @@ static void insert_vm_range_list(struct process_vm *vm, static int copy_user_ranges(struct process_vm *vm, struct process_vm *orgvm); extern void release_fp_regs(struct thread *proc); extern void save_fp_regs(struct thread *proc); +extern void copy_fp_regs(struct thread *from, struct thread *to); extern void restore_fp_regs(struct thread *proc); extern void __runq_add_proc(struct thread *proc, int cpu_id); extern void terminate_host(int pid); @@ -389,6 +390,10 @@ clone_thread(struct thread *org, unsigned long pc, unsigned long sp, /* NOTE: sp is the user mode stack! */ ihk_mc_init_user_process(&thread->ctx, &thread->uctx, ((char *)thread) + KERNEL_STACK_NR_PAGES * PAGE_SIZE, pc, sp); + + /* copy fp_regs from parent */ + save_fp_regs(org); + copy_fp_regs(org, thread); #ifdef POSTK_DEBUG_ARCH_DEP_23 /* add arch dep. clone_process() function */ arch_clone_thread(org, pc, sp, thread); #endif /* POSTK_DEBUG_ARCH_DEP_23 */