ptrace/powerpc: revert "hw_breakpoints: Fix racy access to ptrace breakpoints"

This reverts commit 07fa7a0a8a ("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 commit
9899d11f65 ("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:
Oleg Nesterov 2013-07-08 16:00:49 -07:00 коммит произвёл Linus Torvalds
Родитель 02be46fba4
Коммит 6961ed96f1
1 изменённых файлов: 4 добавлений и 26 удалений

Просмотреть файл

@ -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)