Loading arch/arm/kernel/ptrace.c +8 −0 Original line number Diff line number Diff line Loading @@ -767,12 +767,20 @@ long arch_ptrace(struct task_struct *child, long request, #ifdef CONFIG_HAVE_HW_BREAKPOINT case PTRACE_GETHBPREGS: if (ptrace_get_breakpoints(child) < 0) return -ESRCH; ret = ptrace_gethbpregs(child, addr, (unsigned long __user *)data); ptrace_put_breakpoints(child); break; case PTRACE_SETHBPREGS: if (ptrace_get_breakpoints(child) < 0) return -ESRCH; ret = ptrace_sethbpregs(child, addr, (unsigned long __user *)data); ptrace_put_breakpoints(child); break; #endif Loading arch/powerpc/kernel/ptrace.c +3 −0 Original line number Diff line number Diff line Loading @@ -1591,7 +1591,10 @@ long arch_ptrace(struct task_struct *child, long request, } case PTRACE_SET_DEBUGREG: if (ptrace_get_breakpoints(child) < 0) return -ESRCH; ret = ptrace_set_debugreg(child, addr, data); ptrace_put_breakpoints(child); break; #ifdef CONFIG_PPC64 Loading arch/sh/kernel/ptrace_32.c +4 −0 Original line number Diff line number Diff line Loading @@ -117,7 +117,11 @@ void user_enable_single_step(struct task_struct *child) set_tsk_thread_flag(child, TIF_SINGLESTEP); if (ptrace_get_breakpoints(child) < 0) return; set_single_step(child, pc); ptrace_put_breakpoints(child); } void user_disable_single_step(struct task_struct *child) Loading arch/x86/kernel/ptrace.c +26 −10 Original line number Diff line number Diff line Loading @@ -608,6 +608,9 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data) unsigned len, type; struct perf_event *bp; if (ptrace_get_breakpoints(tsk) < 0) return -ESRCH; data &= ~DR_CONTROL_RESERVED; old_dr7 = ptrace_get_dr7(thread->ptrace_bps); restore: Loading Loading @@ -655,6 +658,9 @@ restore: } goto restore; } ptrace_put_breakpoints(tsk); return ((orig_ret < 0) ? orig_ret : rc); } Loading @@ -668,10 +674,17 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n) if (n < HBP_NUM) { struct perf_event *bp; if (ptrace_get_breakpoints(tsk) < 0) return -ESRCH; bp = thread->ptrace_bps[n]; if (!bp) return 0; val = 0; else val = bp->hw.info.address; ptrace_put_breakpoints(tsk); } else if (n == 6) { val = thread->debugreg6; } else if (n == 7) { Loading @@ -686,6 +699,10 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, struct perf_event *bp; struct thread_struct *t = &tsk->thread; struct perf_event_attr attr; int err = 0; if (ptrace_get_breakpoints(tsk) < 0) return -ESRCH; if (!t->ptrace_bps[nr]) { ptrace_breakpoint_init(&attr); Loading @@ -709,24 +726,23 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, * writing for the user. And anyway this is the previous * behaviour. */ if (IS_ERR(bp)) return PTR_ERR(bp); if (IS_ERR(bp)) { err = PTR_ERR(bp); goto put; } t->ptrace_bps[nr] = bp; } else { int err; bp = t->ptrace_bps[nr]; attr = bp->attr; attr.bp_addr = addr; err = modify_user_hw_breakpoint(bp, &attr); if (err) return err; } return 0; put: ptrace_put_breakpoints(tsk); return err; } /* Loading include/linux/ptrace.h +12 −1 Original line number Diff line number Diff line Loading @@ -189,6 +189,10 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) child->ptrace = current->ptrace; __ptrace_link(child, current->parent); } #ifdef CONFIG_HAVE_HW_BREAKPOINT atomic_set(&child->ptrace_bp_refcnt, 1); #endif } /** Loading Loading @@ -350,6 +354,13 @@ extern int task_current_syscall(struct task_struct *target, long *callno, unsigned long args[6], unsigned int maxargs, unsigned long *sp, unsigned long *pc); #endif #ifdef CONFIG_HAVE_HW_BREAKPOINT extern int ptrace_get_breakpoints(struct task_struct *tsk); extern void ptrace_put_breakpoints(struct task_struct *tsk); #else static inline void ptrace_put_breakpoints(struct task_struct *tsk) { } #endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* __KERNEL */ #endif Loading
arch/arm/kernel/ptrace.c +8 −0 Original line number Diff line number Diff line Loading @@ -767,12 +767,20 @@ long arch_ptrace(struct task_struct *child, long request, #ifdef CONFIG_HAVE_HW_BREAKPOINT case PTRACE_GETHBPREGS: if (ptrace_get_breakpoints(child) < 0) return -ESRCH; ret = ptrace_gethbpregs(child, addr, (unsigned long __user *)data); ptrace_put_breakpoints(child); break; case PTRACE_SETHBPREGS: if (ptrace_get_breakpoints(child) < 0) return -ESRCH; ret = ptrace_sethbpregs(child, addr, (unsigned long __user *)data); ptrace_put_breakpoints(child); break; #endif Loading
arch/powerpc/kernel/ptrace.c +3 −0 Original line number Diff line number Diff line Loading @@ -1591,7 +1591,10 @@ long arch_ptrace(struct task_struct *child, long request, } case PTRACE_SET_DEBUGREG: if (ptrace_get_breakpoints(child) < 0) return -ESRCH; ret = ptrace_set_debugreg(child, addr, data); ptrace_put_breakpoints(child); break; #ifdef CONFIG_PPC64 Loading
arch/sh/kernel/ptrace_32.c +4 −0 Original line number Diff line number Diff line Loading @@ -117,7 +117,11 @@ void user_enable_single_step(struct task_struct *child) set_tsk_thread_flag(child, TIF_SINGLESTEP); if (ptrace_get_breakpoints(child) < 0) return; set_single_step(child, pc); ptrace_put_breakpoints(child); } void user_disable_single_step(struct task_struct *child) Loading
arch/x86/kernel/ptrace.c +26 −10 Original line number Diff line number Diff line Loading @@ -608,6 +608,9 @@ static int ptrace_write_dr7(struct task_struct *tsk, unsigned long data) unsigned len, type; struct perf_event *bp; if (ptrace_get_breakpoints(tsk) < 0) return -ESRCH; data &= ~DR_CONTROL_RESERVED; old_dr7 = ptrace_get_dr7(thread->ptrace_bps); restore: Loading Loading @@ -655,6 +658,9 @@ restore: } goto restore; } ptrace_put_breakpoints(tsk); return ((orig_ret < 0) ? orig_ret : rc); } Loading @@ -668,10 +674,17 @@ static unsigned long ptrace_get_debugreg(struct task_struct *tsk, int n) if (n < HBP_NUM) { struct perf_event *bp; if (ptrace_get_breakpoints(tsk) < 0) return -ESRCH; bp = thread->ptrace_bps[n]; if (!bp) return 0; val = 0; else val = bp->hw.info.address; ptrace_put_breakpoints(tsk); } else if (n == 6) { val = thread->debugreg6; } else if (n == 7) { Loading @@ -686,6 +699,10 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, struct perf_event *bp; struct thread_struct *t = &tsk->thread; struct perf_event_attr attr; int err = 0; if (ptrace_get_breakpoints(tsk) < 0) return -ESRCH; if (!t->ptrace_bps[nr]) { ptrace_breakpoint_init(&attr); Loading @@ -709,24 +726,23 @@ static int ptrace_set_breakpoint_addr(struct task_struct *tsk, int nr, * writing for the user. And anyway this is the previous * behaviour. */ if (IS_ERR(bp)) return PTR_ERR(bp); if (IS_ERR(bp)) { err = PTR_ERR(bp); goto put; } t->ptrace_bps[nr] = bp; } else { int err; bp = t->ptrace_bps[nr]; attr = bp->attr; attr.bp_addr = addr; err = modify_user_hw_breakpoint(bp, &attr); if (err) return err; } return 0; put: ptrace_put_breakpoints(tsk); return err; } /* Loading
include/linux/ptrace.h +12 −1 Original line number Diff line number Diff line Loading @@ -189,6 +189,10 @@ static inline void ptrace_init_task(struct task_struct *child, bool ptrace) child->ptrace = current->ptrace; __ptrace_link(child, current->parent); } #ifdef CONFIG_HAVE_HW_BREAKPOINT atomic_set(&child->ptrace_bp_refcnt, 1); #endif } /** Loading Loading @@ -350,6 +354,13 @@ extern int task_current_syscall(struct task_struct *target, long *callno, unsigned long args[6], unsigned int maxargs, unsigned long *sp, unsigned long *pc); #endif #ifdef CONFIG_HAVE_HW_BREAKPOINT extern int ptrace_get_breakpoints(struct task_struct *tsk); extern void ptrace_put_breakpoints(struct task_struct *tsk); #else static inline void ptrace_put_breakpoints(struct task_struct *tsk) { } #endif /* CONFIG_HAVE_HW_BREAKPOINT */ #endif /* __KERNEL */ #endif