Re: perf: use-after-free in perf_event_for_each

From: Peter Zijlstra
Date: Mon Jan 23 2017 - 12:05:00 EST


On Mon, Jan 23, 2017 at 02:30:12PM +0100, Dmitry Vyukov wrote:
> Hello,
>
> The following program triggers use-after-free in perf_event_for_each:
> https://gist.githubusercontent.com/dvyukov/f1c354a8356e42f4d0b3d912e1bec956/raw/31d7ecdf6dc2c7327b80ef8581a39c823bbe405d/gistfile1.txt
>
> BUG: KASAN: use-after-free in perf_event_for_each_child+0x15f/0x180
> kernel/events/core.c:4495 at addr ffff8800680ec248
> Read of size 8 by task a.out/19370
> CPU: 3 PID: 19370 Comm: a.out Not tainted 4.10.0-rc5+ #186
> Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011
> Call Trace:
> __asan_report_load8_noabort+0x3e/0x40 mm/kasan/report.c:328
> perf_event_for_each_child+0x15f/0x180 kernel/events/core.c:4495

That's the WARN_ON_ONCE() in there, and since the object that's being
UAF'ed is an event, this would be the first dereference in there, this
means that this is the event passed in from the next function.

> perf_event_for_each kernel/events/core.c:4514 [inline]

And this is the first caller (ie, !sibling), suggesting that the line
above:

event = event->group_leader;

is the curlprit, because the earlier event->ctx, dereference is fine
(and we're holding ctx->mutex).


> _perf_ioctl kernel/events/core.c:4671 [inline]
> perf_ioctl+0x9b5/0x1480 kernel/events/core.c:4685
> vfs_ioctl fs/ioctl.c:43 [inline]


This also matches with that the program does; which is something along
the lines of:

event = sys_perf_event_open();
sibling = sys_perf_event_open(.group_fd = event);
dup3(sibling, event, ..);
ioctl(sibling);

Where the dup3() will close event (which should then promote the sibling
to its own full event) and ioctl() on the sibling, which them comes
apart.


So it looks like something fishy on the close the leader and promote the
sibling code, but I cannot put my finger on it just yet. I've ran out of
time for today, but will continue staring at this tomorrow -- of course
hoping that this email will give someone else ideas while I'm off :-)