forked from luck/tmp_suning_uos_patched
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: 63b6da39bb
("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>
This commit is contained in:
parent
923adb1646
commit
fb822e6076
@ -109,8 +109,9 @@ void arch_unregister_hw_breakpoint(struct perf_event *bp)
|
|||||||
* If the breakpoint is unregistered between a hw_breakpoint_handler()
|
* If the breakpoint is unregistered between a hw_breakpoint_handler()
|
||||||
* and the single_step_dabr_instruction(), then cleanup the breakpoint
|
* and the single_step_dabr_instruction(), then cleanup the breakpoint
|
||||||
* restoration variables to prevent dangling pointers.
|
* restoration variables to prevent dangling pointers.
|
||||||
|
* FIXME, this should not be using bp->ctx at all! Sayeth peterz.
|
||||||
*/
|
*/
|
||||||
if (bp->ctx && bp->ctx->task)
|
if (bp->ctx && bp->ctx->task && bp->ctx->task != ((void *)-1L))
|
||||||
bp->ctx->task->thread.last_hit_ubp = NULL;
|
bp->ctx->task->thread.last_hit_ubp = NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user