Messages in this thread | | | Date | Thu, 22 Feb 2018 18:49:56 +0100 | From | Oleg Nesterov <> | Subject | Re: uprobes/perf: KASAN: use-after-free in uprobe_perf_close |
| |
On 02/22, Peter Zijlstra wrote: > > On Thu, Feb 22, 2018 at 05:37:15PM +0100, Oleg Nesterov wrote: > > On 02/22, Prashant Bhole wrote: > > > > After debugging, found that uprobe_perf_close() is called after task has > > > been terminated and uprobe_perf_close() tries to access task_struct of the > > > terminated process. > > > > Oh. You can't imagine how much I forgot this code ;) I will recheck, but at > > first glance you are right. We can't rely on _free_event()->put_ctx() which > > does put_task_struct() after event->destroy(), the exiting task does > > put_task_struct(current) itself and sets child_ctx->task = TASK_TOMBSTONE in > > perf_event_exit_task_context(). > > > > In short, nothing protects event->hw.target. But uprobe_perf_open() should be > > safe, perf_init_event() is called when the caller has the additional reference. > > > > I am wondering if this was wrong from the very beginning or it was broken later, > > but I won't even try to check. > > b2fe8ba674e8 ("uprobes/perf: Avoid uprobe_apply() whenever possible") > > Seems to have added that PF_EXITING test that dereferences the target > pointer.
Hehe ;) no, I think we should blame another commit 63b6da39bb38e8f1a1ef3180d32a39d6 ("perf: Fix perf_event_exit_task() race").
I can be easily wrong, but after perf_event_exit_task_context()->put_task_struct() added by this commit nothing protects event->hw.target.
And just in case, we can simply remove that PF_EXITING test in uprobe_perf_close(), this is a minor optimization. But __uprobe_perf_filter() needs a stable ->target too.
Oleg.
| |