|
@@ -933,12 +933,16 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
|
|
if (data && !(data & DABR_TRANSLATION))
|
|
|
return -EIO;
|
|
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
|
|
+ if (ptrace_get_breakpoints(task) < 0)
|
|
|
+ return -ESRCH;
|
|
|
+
|
|
|
bp = thread->ptrace_bps[0];
|
|
|
if ((!data) || !(data & (DABR_DATA_WRITE | DABR_DATA_READ))) {
|
|
|
if (bp) {
|
|
|
unregister_hw_breakpoint(bp);
|
|
|
thread->ptrace_bps[0] = NULL;
|
|
|
}
|
|
|
+ ptrace_put_breakpoints(task);
|
|
|
return 0;
|
|
|
}
|
|
|
if (bp) {
|
|
@@ -948,9 +952,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
|
|
(DABR_DATA_WRITE | DABR_DATA_READ),
|
|
|
&attr.bp_type);
|
|
|
ret = modify_user_hw_breakpoint(bp, &attr);
|
|
|
- if (ret)
|
|
|
+ if (ret) {
|
|
|
+ ptrace_put_breakpoints(task);
|
|
|
return ret;
|
|
|
+ }
|
|
|
thread->ptrace_bps[0] = bp;
|
|
|
+ ptrace_put_breakpoints(task);
|
|
|
thread->dabr = data;
|
|
|
return 0;
|
|
|
}
|
|
@@ -965,9 +972,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
|
|
ptrace_triggered, task);
|
|
|
if (IS_ERR(bp)) {
|
|
|
thread->ptrace_bps[0] = NULL;
|
|
|
+ ptrace_put_breakpoints(task);
|
|
|
return PTR_ERR(bp);
|
|
|
}
|
|
|
|
|
|
+ ptrace_put_breakpoints(task);
|
|
|
+
|
|
|
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
|
|
|
|
|
|
/* Move contents to the DABR register */
|
|
@@ -1591,10 +1601,7 @@ 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
|