powerpc/hw_breakpoint: Fix oops when destroying hw_breakpoint event
authorRavi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Wed, 2 Mar 2016 09:55:17 +0000 (15:25 +0530)
committerMichael Ellerman <mpe@ellerman.id.au>
Thu, 3 Mar 2016 11:06:08 +0000 (22:06 +1100)
commitfb822e6076d972691c5dd33431c10f82dda94ae9
tree95aefc3d511923fdb5438166bbb4d7e70cddfa85
parent923adb1646d5ba739d2a1e63ee20d60574d9da8e
powerpc/hw_breakpoint: Fix oops when destroying hw_breakpoint event

When destroying a hw_breakpoint event, the kernel oopses as follows:

  Unable to handle kernel paging request for data at address 0x00000c07
  NIP [c0000000000291d0] arch_unregister_hw_breakpoint+0x40/0x60
  LR [c00000000020b6b4] release_bp_slot+0x44/0x80

Call chain:

  hw_breakpoint_event_init()
    bp->destroy = bp_perf_event_destroy;

  do_exit()
    perf_event_exit_task()
      perf_event_exit_task_context()
        WRITE_ONCE(child_ctx->task, TASK_TOMBSTONE);
        perf_event_exit_event()
          free_event()
            _free_event()
              bp_perf_event_destroy() // event->destroy(event);
                release_bp_slot()
                  arch_unregister_hw_breakpoint()

perf_event_exit_task_context() sets child_ctx->task as TASK_TOMBSTONE
which is (void *)-1. arch_unregister_hw_breakpoint() tries to fetch
'thread' attribute of 'task' resulting in oops.

Peterz points out that the code shouldn't be using bp->ctx anyway, but
fixing that will require a decent amount of rework. So for now to fix
the oops, check if bp->ctx->task has been set to (void *)-1, before
dereferencing it. We don't use TASK_TOMBSTONE, because that would
require exporting it and it's supposed to be an internal detail.

Fixes: 63b6da39bb38 ("perf: Fix perf_event_exit_task() race")
Signed-off-by: Ravi Bangoria <ravi.bangoria@linux.vnet.ibm.com>
Acked-by: Peter Zijlstra (Intel) <peterz@infradead.org>
Signed-off-by: Michael Ellerman <mpe@ellerman.id.au>
arch/powerpc/kernel/hw_breakpoint.c