From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751453AbdAWRE4 (ORCPT ); Mon, 23 Jan 2017 12:04:56 -0500 Received: from bombadil.infradead.org ([65.50.211.133]:37588 "EHLO bombadil.infradead.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1750723AbdAWRE4 (ORCPT ); Mon, 23 Jan 2017 12:04:56 -0500 Date: Mon, 23 Jan 2017 18:04:42 +0100 From: Peter Zijlstra To: Dmitry Vyukov Cc: Ingo Molnar , Arnaldo Carvalho de Melo , Alexander Shishkin , LKML , syzkaller Subject: Re: perf: use-after-free in perf_event_for_each Message-ID: <20170123170442.GL6515@twins.programming.kicks-ass.net> References: MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Disposition: inline In-Reply-To: User-Agent: Mutt/1.5.23.1 (2014-03-12) Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 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 :-)