diff options
Diffstat (limited to 'arch/blackfin/kernel/ptrace.c')
| -rw-r--r-- | arch/blackfin/kernel/ptrace.c | 70 |
1 files changed, 34 insertions, 36 deletions
diff --git a/arch/blackfin/kernel/ptrace.c b/arch/blackfin/kernel/ptrace.c index 43eb969405d..8b8fe671b1a 100644 --- a/arch/blackfin/kernel/ptrace.c +++ b/arch/blackfin/kernel/ptrace.c @@ -20,13 +20,13 @@ #include <asm/page.h> #include <asm/pgtable.h> -#include <asm/system.h> #include <asm/processor.h> #include <asm/asm-offsets.h> #include <asm/dma.h> #include <asm/fixed_code.h> #include <asm/cacheflush.h> #include <asm/mem_map.h> +#include <asm/mmu_context.h> /* * does not yet catch signals sent when the child dies. @@ -37,12 +37,13 @@ * Get contents of register REGNO in task TASK. */ static inline long -get_reg(struct task_struct *task, long regno, unsigned long __user *datap) +get_reg(struct task_struct *task, unsigned long regno, + unsigned long __user *datap) { long tmp; struct pt_regs *regs = task_pt_regs(task); - if (regno & 3 || regno > PT_LAST_PSEUDO || regno < 0) + if (regno & 3 || regno > PT_LAST_PSEUDO) return -EIO; switch (regno) { @@ -73,11 +74,11 @@ get_reg(struct task_struct *task, long regno, unsigned long __user *datap) * Write contents of register REGNO in task TASK. */ static inline int -put_reg(struct task_struct *task, long regno, unsigned long data) +put_reg(struct task_struct *task, unsigned long regno, unsigned long data) { struct pt_regs *regs = task_pt_regs(task); - if (regno & 3 || regno > PT_LAST_PSEUDO || regno < 0) + if (regno & 3 || regno > PT_LAST_PSEUDO) return -EIO; switch (regno) { @@ -113,9 +114,10 @@ put_reg(struct task_struct *task, long regno, unsigned long data) /* * check that an address falls within the bounds of the target process's memory mappings */ -static inline int is_user_addr_valid(struct task_struct *child, - unsigned long start, unsigned long len) +int +is_user_addr_valid(struct task_struct *child, unsigned long start, unsigned long len) { + bool valid; struct vm_area_struct *vma; struct sram_list_struct *sraml; @@ -123,9 +125,12 @@ static inline int is_user_addr_valid(struct task_struct *child, if (start + len < start) return -EIO; + down_read(&child->mm->mmap_sem); vma = find_vma(child->mm, start); - if (vma && start >= vma->vm_start && start + len <= vma->vm_end) - return 0; + valid = vma && start >= vma->vm_start && start + len <= vma->vm_end; + up_read(&child->mm->mmap_sem); + if (valid) + return 0; for (sraml = child->mm->context.sram_list; sraml; sraml = sraml->next) if (start >= (unsigned long)sraml->addr @@ -135,6 +140,13 @@ static inline int is_user_addr_valid(struct task_struct *child, if (start >= FIXED_CODE_START && start + len < FIXED_CODE_END) return 0; +#ifdef CONFIG_APP_STACK_L1 + if (child->mm->context.l1_stack_save) + if (start >= (unsigned long)l1_stack_base && + start + len < (unsigned long)l1_stack_base + l1_stack_len) + return 0; +#endif + return -EIO; } @@ -232,7 +244,8 @@ void user_disable_single_step(struct task_struct *child) clear_tsk_thread_flag(child, TIF_SINGLESTEP); } -long arch_ptrace(struct task_struct *child, long request, long addr, long data) +long arch_ptrace(struct task_struct *child, long request, + unsigned long addr, unsigned long data) { int ret; unsigned long __user *datap = (unsigned long __user *)data; @@ -292,28 +305,6 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) break; } -#ifdef CONFIG_BINFMT_ELF_FDPIC - case PTRACE_GETFDPIC: { - unsigned long tmp = 0; - - switch (addr) { - case_PTRACE_GETFDPIC_EXEC: - case PTRACE_GETFDPIC_EXEC: - tmp = child->mm->context.exec_fdpic_loadmap; - break; - case_PTRACE_GETFDPIC_INTERP: - case PTRACE_GETFDPIC_INTERP: - tmp = child->mm->context.interp_fdpic_loadmap; - break; - default: - break; - } - - ret = put_user(tmp, datap); - break; - } -#endif - /* when I and D space are separate, this will have to be fixed. */ case PTRACE_POKEDATA: pr_debug("ptrace: PTRACE_PEEKDATA\n"); @@ -357,8 +348,14 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) case PTRACE_PEEKUSR: switch (addr) { #ifdef CONFIG_BINFMT_ELF_FDPIC /* backwards compat */ - case PT_FDPIC_EXEC: goto case_PTRACE_GETFDPIC_EXEC; - case PT_FDPIC_INTERP: goto case_PTRACE_GETFDPIC_INTERP; + case PT_FDPIC_EXEC: + request = PTRACE_GETFDPIC; + addr = PTRACE_GETFDPIC_EXEC; + goto case_default; + case PT_FDPIC_INTERP: + request = PTRACE_GETFDPIC; + addr = PTRACE_GETFDPIC_INTERP; + goto case_default; #endif default: ret = get_reg(child, addr, datap); @@ -376,15 +373,16 @@ long arch_ptrace(struct task_struct *child, long request, long addr, long data) return copy_regset_to_user(child, &user_bfin_native_view, REGSET_GENERAL, 0, sizeof(struct pt_regs), - (void __user *)data); + datap); case PTRACE_SETREGS: pr_debug("ptrace: PTRACE_SETREGS\n"); return copy_regset_from_user(child, &user_bfin_native_view, REGSET_GENERAL, 0, sizeof(struct pt_regs), - (const void __user *)data); + datap); + case_default: default: ret = ptrace_request(child, request, addr, data); break; |
