From 31595b74098190c382439de632dcd5d00d6c4477 Mon Sep 17 00:00:00 2001 From: Tomoki Shirasawa Date: Fri, 25 Mar 2016 12:57:31 +0900 Subject: [PATCH] fix REQ-43 --- arch/x86/kernel/cpu.c | 10 +++ arch/x86/kernel/include/prctl.h | 17 +++++ arch/x86/kernel/syscall.c | 119 ++++++++++++++++++++++++++++++++ kernel/include/syscall.h | 5 -- kernel/process.c | 3 +- kernel/syscall.c | 108 +---------------------------- lib/include/ihk/cpu.h | 3 + 7 files changed, 152 insertions(+), 113 deletions(-) create mode 100644 arch/x86/kernel/include/prctl.h diff --git a/arch/x86/kernel/cpu.c b/arch/x86/kernel/cpu.c index ab90c36d..3b74bec8 100644 --- a/arch/x86/kernel/cpu.c +++ b/arch/x86/kernel/cpu.c @@ -28,6 +28,7 @@ #include #include #include +#include #define LAPIC_ID 0x020 #define LAPIC_TIMER 0x320 @@ -1533,6 +1534,15 @@ ihk_mc_user_context_t *lookup_user_context(struct thread *thread) return uctx; } /* lookup_user_context() */ +extern long do_arch_prctl(unsigned long code, unsigned long address); +void +ihk_mc_init_user_tlsbase(ihk_mc_user_context_t *ctx, + unsigned long tls_base_addr) +{ + do_arch_prctl(ARCH_SET_FS, tls_base_addr); +} + + /*@ @ assigns \nothing; @*/ diff --git a/arch/x86/kernel/include/prctl.h b/arch/x86/kernel/include/prctl.h new file mode 100644 index 00000000..c3de4631 --- /dev/null +++ b/arch/x86/kernel/include/prctl.h @@ -0,0 +1,17 @@ +/** + * \file prctl.h + * License details are found in the file LICENSE. + */ +/* + * HISTORY + */ + +#ifndef __ARCH_PRCTL_H +#define __ARCH_PRCTL_H + +#define ARCH_SET_GS 0x1001 +#define ARCH_SET_FS 0x1002 +#define ARCH_GET_FS 0x1003 +#define ARCH_GET_GS 0x1004 + +#endif diff --git a/arch/x86/kernel/syscall.c b/arch/x86/kernel/syscall.c index 918617c7..b2b1cd44 100644 --- a/arch/x86/kernel/syscall.c +++ b/arch/x86/kernel/syscall.c @@ -26,6 +26,7 @@ #include #include #include +#include void terminate(int, int); extern long do_sigaction(int sig, struct k_sigaction *act, struct k_sigaction *oact); @@ -550,6 +551,75 @@ void ptrace_report_signal(struct thread *thread, int sig) schedule(); dkprintf("ptrace_report_signal,wake up\n"); } + +static long +ptrace_arch_prctl(int pid, long code, long addr) +{ + long rc = -EIO; + struct thread *child; + struct mcs_rwlock_node_irqsave lock; + + child = find_thread(pid, pid, &lock); + if (!child) + return -ESRCH; + if (child->proc->status == PS_TRACED) { + switch (code) { + case ARCH_GET_FS: { + unsigned long value; + unsigned long *p = (unsigned long *)addr; + rc = ptrace_read_user(child, + offsetof(struct user_regs_struct, fs_base), + &value); + if (rc == 0) { + rc = copy_to_user(p, (char *)&value, sizeof(value)); + } + break; + } + case ARCH_GET_GS: { + unsigned long value; + unsigned long *p = (unsigned long *)addr; + rc = ptrace_read_user(child, + offsetof(struct user_regs_struct, gs_base), + &value); + if (rc == 0) { + rc = copy_to_user(p, (char *)&value, sizeof(value)); + } + break; + } + case ARCH_SET_FS: + rc = ptrace_write_user(child, + offsetof(struct user_regs_struct, fs_base), + (unsigned long)addr); + break; + case ARCH_SET_GS: + rc = ptrace_write_user(child, + offsetof(struct user_regs_struct, gs_base), + (unsigned long)addr); + break; + default: + rc = -EINVAL; + break; + } + } + thread_unlock(child, &lock); + + return rc; +} + +long +arch_ptrace(long request, int pid, long addr, long data) +{ + switch(request) { + case PTRACE_ARCH_PRCTL: + return ptrace_arch_prctl(pid, data, addr); + break; + + default: + break; + } + return -EOPNOTSUPP; +} + static int isrestart(int num, unsigned long rc, int sig, int restart) { @@ -1387,3 +1457,52 @@ out: dkprintf("shmget(%#lx,%#lx,%#x): %d %d\n", key, size, shmflg0, error, shmid); return (error)?: shmid; } /* sys_shmget() */ + +long do_arch_prctl(unsigned long code, unsigned long address) +{ + int err = 0; + enum ihk_asr_type type; + + switch (code) { + case ARCH_SET_FS: + case ARCH_GET_FS: + type = IHK_ASR_X86_FS; + break; + case ARCH_GET_GS: + type = IHK_ASR_X86_GS; + break; + case ARCH_SET_GS: + return -ENOTSUPP; + default: + return -EINVAL; + } + + switch (code) { + case ARCH_SET_FS: + dkprintf("[%d] arch_prctl: ARCH_SET_FS: 0x%lX\n", + ihk_mc_get_processor_id(), address); + cpu_local_var(current)->tlsblock_base = address; + err = ihk_mc_arch_set_special_register(type, address); + break; + case ARCH_SET_GS: + err = ihk_mc_arch_set_special_register(type, address); + break; + case ARCH_GET_FS: + case ARCH_GET_GS: + err = ihk_mc_arch_get_special_register(type, + (unsigned long*)address); + break; + default: + break; + } + + return err; +} + + +SYSCALL_DECLARE(arch_prctl) +{ + return do_arch_prctl(ihk_mc_syscall_arg0(ctx), + ihk_mc_syscall_arg1(ctx)); +} + diff --git a/kernel/include/syscall.h b/kernel/include/syscall.h index a8665c9f..4cd8f182 100644 --- a/kernel/include/syscall.h +++ b/kernel/include/syscall.h @@ -69,11 +69,6 @@ #define SCD_MSG_PROCFS_TID_CREATE 0x44 #define SCD_MSG_PROCFS_TID_DELETE 0x45 -#define ARCH_SET_GS 0x1001 -#define ARCH_SET_FS 0x1002 -#define ARCH_GET_FS 0x1003 -#define ARCH_GET_GS 0x1004 - /* Cloning flags. */ # define CSIGNAL 0x000000ff /* Signal mask to be sent at exit. */ # define CLONE_VM 0x00000100 /* Set if VM shared between processes. */ diff --git a/kernel/process.c b/kernel/process.c index 5eb29e80..b18b2f38 100644 --- a/kernel/process.c +++ b/kernel/process.c @@ -42,7 +42,6 @@ #define ekprintf(...) kprintf(__VA_ARGS__) #endif -extern long do_arch_prctl(unsigned long code, unsigned long address); extern long alloc_debugreg(struct thread *proc); extern void save_debugreg(unsigned long *debugreg); extern void restore_debugreg(unsigned long *debugreg); @@ -2626,7 +2625,7 @@ redo: ihk_mc_get_processor_id(), next->tlsblock_base); /* Set up new TLS.. */ - do_arch_prctl(ARCH_SET_FS, next->tlsblock_base); + ihk_mc_init_user_tlsbase(next->uctx, next->tlsblock_base); if (prev) { last = ihk_mc_switch_context(&prev->ctx, &next->ctx, prev); diff --git a/kernel/syscall.c b/kernel/syscall.c index c910879a..0c96d914 100644 --- a/kernel/syscall.c +++ b/kernel/syscall.c @@ -114,6 +114,7 @@ extern void debug_log(unsigned long); extern void free_all_process_memory_range(struct process_vm *vm); extern int arch_clear_host_user_space(); extern int arch_range_check(unsigned long addr, unsigned long len); +extern long arch_ptrace(long request, int pid, long addr, long data); extern struct cpu_local_var *clv; int prepare_process_ranges_args_envs(struct thread *thread, @@ -1426,54 +1427,6 @@ SYSCALL_DECLARE(gettid) return cpu_local_var(current)->tid; } -long do_arch_prctl(unsigned long code, unsigned long address) -{ - int err = 0; - enum ihk_asr_type type; - - switch (code) { - case ARCH_SET_FS: - case ARCH_GET_FS: - type = IHK_ASR_X86_FS; - break; - case ARCH_GET_GS: - type = IHK_ASR_X86_GS; - break; - case ARCH_SET_GS: - return -ENOTSUPP; - default: - return -EINVAL; - } - - switch (code) { - case ARCH_SET_FS: - dkprintf("[%d] arch_prctl: ARCH_SET_FS: 0x%lX\n", - ihk_mc_get_processor_id(), address); - cpu_local_var(current)->tlsblock_base = address; - err = ihk_mc_arch_set_special_register(type, address); - break; - case ARCH_SET_GS: - err = ihk_mc_arch_set_special_register(type, address); - break; - case ARCH_GET_FS: - case ARCH_GET_GS: - err = ihk_mc_arch_get_special_register(type, - (unsigned long*)address); - break; - default: - break; - } - - return err; -} - - -SYSCALL_DECLARE(arch_prctl) -{ - return do_arch_prctl(ihk_mc_syscall_arg0(ctx), - ihk_mc_syscall_arg1(ctx)); -} - extern void ptrace_report_signal(struct thread *thread, int sig); static int ptrace_report_exec(struct thread *thread) { @@ -4606,59 +4559,6 @@ static long ptrace_setregs(int pid, long data) return rc; } -static long ptrace_arch_prctl(int pid, long code, long addr) -{ - long rc = -EIO; - struct thread *child; - struct mcs_rwlock_node_irqsave lock; - - child = find_thread(pid, pid, &lock); - if (!child) - return -ESRCH; - if (child->proc->status == PS_TRACED) { - switch (code) { - case ARCH_GET_FS: { - unsigned long value; - unsigned long *p = (unsigned long *)addr; - rc = ptrace_read_user(child, - offsetof(struct user_regs_struct, fs_base), - &value); - if (rc == 0) { - rc = copy_to_user(p, (char *)&value, sizeof(value)); - } - break; - } - case ARCH_GET_GS: { - unsigned long value; - unsigned long *p = (unsigned long *)addr; - rc = ptrace_read_user(child, - offsetof(struct user_regs_struct, gs_base), - &value); - if (rc == 0) { - rc = copy_to_user(p, (char *)&value, sizeof(value)); - } - break; - } - case ARCH_SET_FS: - rc = ptrace_write_user(child, - offsetof(struct user_regs_struct, fs_base), - (unsigned long)addr); - break; - case ARCH_SET_GS: - rc = ptrace_write_user(child, - offsetof(struct user_regs_struct, gs_base), - (unsigned long)addr); - break; - default: - rc = -EINVAL; - break; - } - } - thread_unlock(child, &lock); - - return rc; -} - extern long ptrace_read_fpregs(struct thread *thread, void *fpregs); extern long ptrace_write_fpregs(struct thread *thread, void *fpregs); @@ -5169,16 +5069,12 @@ SYSCALL_DECLARE(ptrace) dkprintf("ptrace: PTRACE_SETREGSET: addr=0x%x, data=%p\n", addr, data); error = ptrace_setregset(pid, addr, data); break; - case PTRACE_ARCH_PRCTL: - error = ptrace_arch_prctl(pid, data, addr); - dkprintf("PTRACE_ARCH_PRCTL: data=%p addr=%p return=%p\n", data, addr, error); - break; case PTRACE_GETEVENTMSG: dkprintf("ptrace: PTRACE_GETEVENTMSG: data=%p\n", data); error = ptrace_geteventmsg(pid, data); break; default: - kprintf("ptrace: unimplemented ptrace(%d) called.\n", request); + error = arch_ptrace(request, pid, addr, data); break; } diff --git a/lib/include/ihk/cpu.h b/lib/include/ihk/cpu.h index 78e41504..331f9fee 100644 --- a/lib/include/ihk/cpu.h +++ b/lib/include/ihk/cpu.h @@ -76,6 +76,9 @@ void ihk_mc_init_user_process(ihk_mc_kernel_context_t *ctx, void *stack_pointer, unsigned long user_pc, unsigned long user_sp); +void ihk_mc_init_user_tlsbase(ihk_mc_user_context_t *ctx, + unsigned long tls_base_addr); + enum ihk_mc_user_context_regtype { IHK_UCR_STACK_POINTER = 1, IHK_UCR_PROGRAM_COUNTER = 2,