ptrace/powerpc: revert "hw_breakpoints: Fix racy access to ptrace breakpoints"
This reverts commit07fa7a0a8a
("hw_breakpoints: Fix racy access to ptrace breakpoints") and removes ptrace_get/put_breakpoints() added by other commits. The patch was fine but we can no longer race with SIGKILL after commit9899d11f65
("ptrace: ensure arch_ptrace/ptrace_request can never race with SIGKILL"), the __TASK_TRACED tracee can't be woken up and ->ptrace_bps[] can't go away. Signed-off-by: Oleg Nesterov <oleg@redhat.com> Acked-by: Michael Neuling <mikey@neuling.org> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Cc: Paul Mackerras <paulus@samba.org> Cc: Frederic Weisbecker <fweisbec@gmail.com> Cc: Ingo Molnar <mingo@kernel.org> Cc: Jan Kratochvil <jan.kratochvil@redhat.com> Cc: Paul Mundt <lethal@linux-sh.org> Cc: Will Deacon <will.deacon@arm.com> Cc: Prasad <prasad@linux.vnet.ibm.com> Cc: Russell King <linux@arm.linux.org.uk> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
Родитель
02be46fba4
Коммит
6961ed96f1
|
@ -975,16 +975,12 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
||||||
hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
|
hw_brk.type = (data & HW_BRK_TYPE_DABR) | HW_BRK_TYPE_PRIV_ALL;
|
||||||
hw_brk.len = 8;
|
hw_brk.len = 8;
|
||||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
if (ptrace_get_breakpoints(task) < 0)
|
|
||||||
return -ESRCH;
|
|
||||||
|
|
||||||
bp = thread->ptrace_bps[0];
|
bp = thread->ptrace_bps[0];
|
||||||
if ((!data) || !(hw_brk.type & HW_BRK_TYPE_RDWR)) {
|
if ((!data) || !(hw_brk.type & HW_BRK_TYPE_RDWR)) {
|
||||||
if (bp) {
|
if (bp) {
|
||||||
unregister_hw_breakpoint(bp);
|
unregister_hw_breakpoint(bp);
|
||||||
thread->ptrace_bps[0] = NULL;
|
thread->ptrace_bps[0] = NULL;
|
||||||
}
|
}
|
||||||
ptrace_put_breakpoints(task);
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
if (bp) {
|
if (bp) {
|
||||||
|
@ -997,11 +993,9 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
||||||
|
|
||||||
ret = modify_user_hw_breakpoint(bp, &attr);
|
ret = modify_user_hw_breakpoint(bp, &attr);
|
||||||
if (ret) {
|
if (ret) {
|
||||||
ptrace_put_breakpoints(task);
|
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
thread->ptrace_bps[0] = bp;
|
thread->ptrace_bps[0] = bp;
|
||||||
ptrace_put_breakpoints(task);
|
|
||||||
thread->hw_brk = hw_brk;
|
thread->hw_brk = hw_brk;
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@ -1016,12 +1010,9 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
|
||||||
ptrace_triggered, NULL, task);
|
ptrace_triggered, NULL, task);
|
||||||
if (IS_ERR(bp)) {
|
if (IS_ERR(bp)) {
|
||||||
thread->ptrace_bps[0] = NULL;
|
thread->ptrace_bps[0] = NULL;
|
||||||
ptrace_put_breakpoints(task);
|
|
||||||
return PTR_ERR(bp);
|
return PTR_ERR(bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrace_put_breakpoints(task);
|
|
||||||
|
|
||||||
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
|
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
|
||||||
task->thread.hw_brk = hw_brk;
|
task->thread.hw_brk = hw_brk;
|
||||||
#else /* CONFIG_PPC_ADV_DEBUG_REGS */
|
#else /* CONFIG_PPC_ADV_DEBUG_REGS */
|
||||||
|
@ -1440,26 +1431,19 @@ static long ppc_set_hwdebug(struct task_struct *child,
|
||||||
if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
|
if (bp_info->trigger_type & PPC_BREAKPOINT_TRIGGER_WRITE)
|
||||||
brk.type |= HW_BRK_TYPE_WRITE;
|
brk.type |= HW_BRK_TYPE_WRITE;
|
||||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
if (ptrace_get_breakpoints(child) < 0)
|
|
||||||
return -ESRCH;
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Check if the request is for 'range' breakpoints. We can
|
* Check if the request is for 'range' breakpoints. We can
|
||||||
* support it if range < 8 bytes.
|
* support it if range < 8 bytes.
|
||||||
*/
|
*/
|
||||||
if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE) {
|
if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_RANGE_INCLUSIVE)
|
||||||
len = bp_info->addr2 - bp_info->addr;
|
len = bp_info->addr2 - bp_info->addr;
|
||||||
} else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
|
else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
|
||||||
len = 1;
|
len = 1;
|
||||||
else {
|
else
|
||||||
ptrace_put_breakpoints(child);
|
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
|
||||||
bp = thread->ptrace_bps[0];
|
bp = thread->ptrace_bps[0];
|
||||||
if (bp) {
|
if (bp)
|
||||||
ptrace_put_breakpoints(child);
|
|
||||||
return -ENOSPC;
|
return -ENOSPC;
|
||||||
}
|
|
||||||
|
|
||||||
/* Create a new breakpoint request if one doesn't exist already */
|
/* Create a new breakpoint request if one doesn't exist already */
|
||||||
hw_breakpoint_init(&attr);
|
hw_breakpoint_init(&attr);
|
||||||
|
@ -1471,11 +1455,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
|
||||||
ptrace_triggered, NULL, child);
|
ptrace_triggered, NULL, child);
|
||||||
if (IS_ERR(bp)) {
|
if (IS_ERR(bp)) {
|
||||||
thread->ptrace_bps[0] = NULL;
|
thread->ptrace_bps[0] = NULL;
|
||||||
ptrace_put_breakpoints(child);
|
|
||||||
return PTR_ERR(bp);
|
return PTR_ERR(bp);
|
||||||
}
|
}
|
||||||
|
|
||||||
ptrace_put_breakpoints(child);
|
|
||||||
return 1;
|
return 1;
|
||||||
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
|
#endif /* CONFIG_HAVE_HW_BREAKPOINT */
|
||||||
|
|
||||||
|
@ -1519,16 +1501,12 @@ static long ppc_del_hwdebug(struct task_struct *child, long data)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
#ifdef CONFIG_HAVE_HW_BREAKPOINT
|
||||||
if (ptrace_get_breakpoints(child) < 0)
|
|
||||||
return -ESRCH;
|
|
||||||
|
|
||||||
bp = thread->ptrace_bps[0];
|
bp = thread->ptrace_bps[0];
|
||||||
if (bp) {
|
if (bp) {
|
||||||
unregister_hw_breakpoint(bp);
|
unregister_hw_breakpoint(bp);
|
||||||
thread->ptrace_bps[0] = NULL;
|
thread->ptrace_bps[0] = NULL;
|
||||||
} else
|
} else
|
||||||
ret = -ENOENT;
|
ret = -ENOENT;
|
||||||
ptrace_put_breakpoints(child);
|
|
||||||
return ret;
|
return ret;
|
||||||
#else /* CONFIG_HAVE_HW_BREAKPOINT */
|
#else /* CONFIG_HAVE_HW_BREAKPOINT */
|
||||||
if (child->thread.hw_brk.address == 0)
|
if (child->thread.hw_brk.address == 0)
|
||||||
|
|
Загрузка…
Ссылка в новой задаче