ptrace/powerpc: revert "hw_breakpoints: Fix racy access to ptrace breakpoints"
authorOleg Nesterov <oleg@redhat.com>
Mon, 8 Jul 2013 23:00:49 +0000 (16:00 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 9 Jul 2013 17:33:25 +0000 (10:33 -0700)
This reverts commit 07fa7a0a8a58 ("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
9899d11f6544 ("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>
arch/powerpc/kernel/ptrace.c

index 64f7bd5b1b0f59bcf23fa47c22eb012a5a440b16..9a0d24c390a3535e16c934f80ec19695da04d095 100644 (file)
@@ -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.len = 8;
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-       if (ptrace_get_breakpoints(task) < 0)
-               return -ESRCH;
-
        bp = thread->ptrace_bps[0];
        if ((!data) || !(hw_brk.type & HW_BRK_TYPE_RDWR)) {
                if (bp) {
                        unregister_hw_breakpoint(bp);
                        thread->ptrace_bps[0] = NULL;
                }
-               ptrace_put_breakpoints(task);
                return 0;
        }
        if (bp) {
@@ -997,11 +993,9 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
 
                ret =  modify_user_hw_breakpoint(bp, &attr);
                if (ret) {
-                       ptrace_put_breakpoints(task);
                        return ret;
                }
                thread->ptrace_bps[0] = bp;
-               ptrace_put_breakpoints(task);
                thread->hw_brk = hw_brk;
                return 0;
        }
@@ -1016,12 +1010,9 @@ int ptrace_set_debugreg(struct task_struct *task, unsigned long addr,
                                               ptrace_triggered, NULL, 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 */
        task->thread.hw_brk = hw_brk;
 #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)
                brk.type |= HW_BRK_TYPE_WRITE;
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-       if (ptrace_get_breakpoints(child) < 0)
-               return -ESRCH;
-
        /*
         * Check if the request is for 'range' breakpoints. We can
         * 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;
-       else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
+       else if (bp_info->addr_mode == PPC_BREAKPOINT_MODE_EXACT)
                len = 1;
-       else {
-               ptrace_put_breakpoints(child);
+       else
                return -EINVAL;
-       }
        bp = thread->ptrace_bps[0];
-       if (bp) {
-               ptrace_put_breakpoints(child);
+       if (bp)
                return -ENOSPC;
-       }
 
        /* Create a new breakpoint request if one doesn't exist already */
        hw_breakpoint_init(&attr);
@@ -1471,11 +1455,9 @@ static long ppc_set_hwdebug(struct task_struct *child,
                                               ptrace_triggered, NULL, child);
        if (IS_ERR(bp)) {
                thread->ptrace_bps[0] = NULL;
-               ptrace_put_breakpoints(child);
                return PTR_ERR(bp);
        }
 
-       ptrace_put_breakpoints(child);
        return 1;
 #endif /* CONFIG_HAVE_HW_BREAKPOINT */
 
@@ -1519,16 +1501,12 @@ static long ppc_del_hwdebug(struct task_struct *child, long data)
                return -EINVAL;
 
 #ifdef CONFIG_HAVE_HW_BREAKPOINT
-       if (ptrace_get_breakpoints(child) < 0)
-               return -ESRCH;
-
        bp = thread->ptrace_bps[0];
        if (bp) {
                unregister_hw_breakpoint(bp);
                thread->ptrace_bps[0] = NULL;
        } else
                ret = -ENOENT;
-       ptrace_put_breakpoints(child);
        return ret;
 #else /* CONFIG_HAVE_HW_BREAKPOINT */
        if (child->thread.hw_brk.address == 0)