From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752572AbdCELpy (ORCPT ); Sun, 5 Mar 2017 06:45:54 -0500 Received: from mail-ua0-f173.google.com ([209.85.217.173]:36710 "EHLO mail-ua0-f173.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752362AbdCELpw (ORCPT ); Sun, 5 Mar 2017 06:45:52 -0500 MIME-Version: 1.0 In-Reply-To: References: <20170304193910.GG29622@ZenIV.linux.org.uk> From: Dmitry Vyukov Date: Sun, 5 Mar 2017 12:37:13 +0100 Message-ID: Subject: Re: fs: use-after-free in path_lookupat To: Al Viro Cc: "linux-fsdevel@vger.kernel.org" , LKML , syzkaller Content-Type: text/plain; charset=UTF-8 Sender: linux-kernel-owner@vger.kernel.org List-ID: X-Mailing-List: linux-kernel@vger.kernel.org On Sun, Mar 5, 2017 at 12:24 PM, Dmitry Vyukov wrote: >>>> On Sat, Mar 04, 2017 at 03:59:36PM +0100, Dmitry Vyukov wrote: >>>> >>>>> I am getting the following use-after-free reports while running >>>>> syzkaller fuzzer on 86292b33d4b79ee03e2f43ea0381ef85f077c760 (but also >>>>> happened on 6dc39c50e4aeb769c8ae06edf2b1a732f3490913 and >>>>> c82be9d2244aacea9851c86f4fb74694c99cd874). >>>> >>>> IOW, it's not fs/namei.c patches from this window... >>>> >>>>> unlazy_walk+0xf2/0x4b0 fs/namei.c:692 >>>> >>>> Could you post disassembly (e.g. from objdump -d) of your unlazy_walk()? >>>> For the kernel the trace is from... >>>> >>>>> r4 = memfd_create(&(0x7f0000013000)="2f6465762f6877726e6700", 0x0) >>>>> name_to_handle_at(r4, &(0x7f0000003000-0x6)="2e2f62757300", >>>>> &(0x7f0000003000-0xd)={0xc, 0x0, "cd21"}, &(0x7f0000002000)=0x0, >>>>> 0x1000) >>>>> >>>>> What's strange is that dirfd passed to name_to_handle_at is memfd >>>>> handle (sic). And path lookup somehow does not fail early on this. >>>>> Does it make any sense? >>>> >>>> It doesn't, but is that the triggering call of name_to_handle_at(), or do you >>>> have it called elsewhere? I am pretty sure it is that one. I don't think I ever used name_to_handle_at syscall in my life and I definitely didn't make it lookup a memfd :) >>>> FWIW, no LOOKUP_ROOT in filename_lookup() flags + NULL root + dfd not >>>> equal to AT_FDCWD + non-empty name should've ended up in >>>> if (!d_can_lookup(dentry)) { >>>> fdput(f); >>>> return ERR_PTR(-ENOTDIR); >>>> } >>>> in path_init() and it shouldn't have progressed any further. And in case >>>> of name_to_handle_at() we have user_path_at(dfd, name, lookup_flags, &path), >>>> i.e. user_path_at_empty(dfd, name, lookup_flags, &path, NULL), i.e. >>>> filename_lookup(dfd, getname_flags(name, lookup_flags, NULL), lookup_flags, >>>> &path, NULL). IOW, filename_lookup() is called with root equal to NULL, >>>> dfd and name coming straight from userland and lookup_flags containing >>>> nothing beyond LOOKUP_EMPTY and LOOKUP_FOLLOW... > Yes, but still it somehow happens... I've added this diff: --- a/fs/namei.c +++ b/fs/namei.c @@ -2213,6 +2213,7 @@ static const char *path_init(struct nameidata *nd, unsigned flags) dentry = f.file->f_path.dentry; +pr_err("%d: path_init: s=%s flags=%d\n", current->pid, s, dentry->d_flags); if (*s) { if (!d_can_lookup(dentry)) { fdput(f); Most of the time flags are 4194304, but occasionally they are 5243016: [ 172.559822] 21279: path_init: s= flags=4194304 [ 172.572357] 21275: path_init: s= flags=4194304 [ 172.605964] 21297: path_init: s= flags=4194304 [ 172.609712] 21301: path_init: s= flags=4194304 [ 172.620832] 21287: path_init: s= flags=4194304 [ 172.651228] 21288: path_init: s= flags=4194304 [ 172.660516] 21306: path_init: s= flags=4194304 [ 172.689294] 21308: path_init: s= flags=4194304 [ 172.689743] 21281: path_init: s= flags=4194304 [ 172.705908] 21313: path_init: s= flags=4194304 [ 172.755287] 21297: path_init: s= flags=5243016 [ 172.762358] 21306: path_init: s= flags=4194304 [ 172.763248] 21306: path_init: s= flags=4194304 [ 172.766700] 21317: path_init: s= flags=4194304 [ 172.775612] 21313: path_init: s= flags=4194304 [ 172.797624] 21308: path_init: s= flags=4194304 [ 172.798709] 21328: path_init: s= flags=4194304 [ 172.800170] 21322: path_init: s= flags=4194304 ... [ 179.202077] 22190: path_init: s= flags=4194304 [ 179.209753] 22189: path_init: s= flags=4194304 [ 179.211614] 22187: path_init: s= flags=4194304 [ 179.223048] 22165: path_init: s= flags=4194304 [ 179.271114] 22195: path_init: s= flags=4194304 [ 179.290350] 22182: path_init: s= flags=4194304 [ 179.301246] 22189: path_init: s= flags=4194304 [ 179.325996] 22202: path_init: s= flags=4194304 [ 179.327900] 22203: path_init: s= flags=4194304 [ 179.349044] 22195: path_init: s= flags=4194304 [ 179.363826] 22211: path_init: s= flags=4194304 [ 179.364938] 22207: path_init: s= flags=4194304 [ 179.364985] 22206: path_init: s= flags=4194304 [ 179.415240] 22214: path_init: s= flags=4194304 [ 179.464470] 22219: path_init: s= flags=4194304 [ 179.484437] 22225: path_init: s= flags=4194304 [ 179.489139] 22207: path_init: s= flags=4194304 [ 179.495212] 22206: path_init: s= flags=4194304 [ 179.521143] 22216: path_init: s= flags=4194304 [ 179.526780] 22228: path_init: s= flags=4194304 [ 179.540650] 22227: path_init: s= flags=4194304 [ 179.545824] 22225: path_init: s= flags=4194304 [ 179.574581] 22214: path_init: s= flags=4194304 [ 179.577168] 22236: path_init: s= flags=4194304 [ 179.618489] 22240: path_init: s= flags=4194304 [ 179.644057] 22243: path_init: s= flags=4194304 [ 179.647793] 22228: path_init: s= flags=4194304 [ 179.680428] 22248: path_init: s= flags=4194304 [ 179.716533] 22240: path_init: s= flags=4194304 [ 179.720363] 22227: path_init: s= flags=4194304 [ 179.721421] 22236: path_init: s= flags=4194304 [ 179.722195] 22249: path_init: s= flags=4194304 [ 179.729854] 22252: path_init: s= flags=4194304 [ 179.772353] 22248: path_init: s= flags=5243016 [ 179.778042] 22243: path_init: s= flags=4194304 [ 179.779056] ================================================================== [ 179.779707] BUG: KASAN: use-after-free in perf_trace_lock_acquire+0x9cf/0xa00 at addr ffff88005c34c930 [ 179.780010] Read of size 8 by task syz-executor/22243 [ 179.780010] CPU: 2 PID: 22243 Comm: syz-executor Not tainted 4.10.0+ #294 [ 179.781396] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS Bochs 01/01/2011 [ 179.782914] Call Trace: [ 179.782914] dump_stack+0x2fb/0x3fd [ 179.782914] ? arch_local_irq_restore+0x53/0x53 [ 179.782914] ? vprintk_emit+0x566/0x770 [ 179.782914] ? console_unlock+0xf50/0xf50 [ 179.782914] ? console_unlock+0xf50/0xf50 [ 179.782914] ? lock_set_class+0xc00/0xc00 [ 179.782914] ? __lock_is_held+0xb6/0x140 [ 179.782914] ? check_noncircular+0x20/0x20 [ 179.782914] ? lock_set_class+0xc00/0xc00 [ 179.782914] ? __handle_mm_fault+0x1c84/0x2cd0 [ 179.782914] ? vprintk_default+0x28/0x30 [ 179.789989] ? vprintk_func+0x47/0x90 [ 179.789989] ? printk+0xc8/0xf9 [ 179.789989] ? load_image_and_restore+0x134/0x134 [ 179.789989] kasan_object_err+0x1c/0x90 [ 179.789989] kasan_report.part.2+0x1b0/0x460 [ 179.789989] ? kasan_check_write+0x14/0x20 [ 179.789989] ? do_raw_spin_lock+0xbd/0x1f0 [ 179.789989] ? perf_trace_lock_acquire+0x9cf/0xa00 [ 179.789989] __asan_report_load8_noabort+0x29/0x30 [ 179.789989] perf_trace_lock_acquire+0x9cf/0xa00 [ 179.789989] ? RECLAIM_FS_verbose+0x10/0x10 [ 179.789989] ? mark_held_locks+0x100/0x100 [ 179.789989] ? mark_held_locks+0x100/0x100 [ 179.789989] ? __do_page_fault+0x51b/0xb60 [ 179.789989] ? lock_acquire+0x630/0x630 [ 179.789989] ? memset+0x31/0x40 [ 179.789989] lock_acquire+0x473/0x630 [ 179.789989] ? lockref_get_not_dead+0x19/0x80 [ 179.789989] ? lock_set_class+0xc00/0xc00 [ 179.789989] ? trace_hardirqs_on_caller+0x545/0x6f0 [ 179.789989] ? mark_held_locks+0x100/0x100 [ 179.789989] ? trace_hardirqs_on_caller+0x545/0x6f0 [ 179.789989] ? mark_held_locks+0x100/0x100 [ 179.789989] ? mark_held_locks+0x100/0x100 [ 179.789989] ? retint_kernel+0x10/0x10 [ 179.789989] ? trace_hardirqs_on_caller+0x545/0x6f0 [ 179.789989] ? mark_held_locks+0x100/0x100 [ 179.789989] ? trace_hardirqs_on_caller+0x545/0x6f0 [ 179.789989] ? mark_held_locks+0x100/0x100 [ 179.789989] ? trace_hardirqs_on_thunk+0x1a/0x1c [ 179.789989] ? retint_kernel+0x10/0x10 [ 179.789989] _raw_spin_lock+0x33/0x50 [ 179.789989] ? lockref_get_not_dead+0x19/0x80 [ 179.789989] lockref_get_not_dead+0x19/0x80 [ 179.789989] legitimize_path.isra.36+0x7d/0x1a0 [ 179.789989] unlazy_walk+0xf2/0x4b0 [ 179.789989] complete_walk+0xb2/0x1f0 [ 179.789989] path_lookupat+0x1c1/0x400 [ 179.789989] filename_lookup+0x282/0x540 [ 179.789989] ? filename_parentat+0x5b0/0x5b0 [ 179.806362] ? kmem_cache_alloc+0x3f5/0x6e0 [ 179.806648] ? getname_flags+0x256/0x580 [ 179.806648] user_path_at_empty+0x40/0x50 [ 179.806648] SyS_name_to_handle_at+0xff/0x720 [ 179.806648] ? vfs_dentry_acceptable+0x10/0x10 [ 179.806648] ? retint_kernel+0x10/0x10 [ 179.806648] entry_SYSCALL_64_fastpath+0x1f/0xc2 [ 179.806648] RIP: 0033:0x4458d9 [ 179.806648] RSP: 002b:00007faa1547cb58 EFLAGS: 00000286 ORIG_RAX: 000000000000012f [ 179.806648] RAX: ffffffffffffffda RBX: 0000000000000050 RCX: 00000000004458d9 [ 179.806648] RDX: 0000000020002ff3 RSI: 0000000020002ffa RDI: 0000000000000050 [ 179.806648] RBP: 00000000006e11b0 R08: 0000000000001000 R09: 0000000000000000 [ 179.806648] R10: 0000000020002000 R11: 0000000000000286 R12: 0000000000708000 [ 179.806648] R13: 0000000000000000 R14: 00007faa1547d9c0 R15: 00007faa1547d700 [ 179.806648] Object at ffff88005c34c880, in cache dentry size: 288 [ 179.814491] 22252: path_init: s= flags=4194304 [ 179.806648] Allocated: [ 179.806648] PID = 22260 [ 179.806648] save_stack_trace+0x16/0x20 [ 179.806648] save_stack+0x43/0xd0 [ 179.816189] kasan_kmalloc+0xaa/0xd0 [ 179.816189] kasan_slab_alloc+0x12/0x20 [ 179.816189] kmem_cache_alloc+0x102/0x6e0 [ 179.816189] __d_alloc+0xb3/0xbb0 [ 179.816189] d_alloc_pseudo+0x1d/0x30 [ 179.816189] __shmem_file_setup+0x20c/0x5a0 [ 179.816189] SyS_memfd_create+0x172/0x2c0 [ 179.816189] entry_SYSCALL_64_fastpath+0x1f/0xc2 [ 179.816189] Freed: [ 179.816189] PID = 22265 [ 179.816189] save_stack_trace+0x16/0x20 [ 179.816189] save_stack+0x43/0xd0 [ 179.816189] kasan_slab_free+0x6f/0xb0 [ 179.816189] kmem_cache_free+0x71/0x240 [ 179.816189] dentry_free+0xd5/0x160 [ 179.816189] __dentry_kill+0x471/0x6d0 [ 179.816189] dput.part.25+0x5ce/0x7c0 [ 179.816189] dput+0x1f/0x30 [ 179.816189] __fput+0x538/0x800 [ 179.816189] ____fput+0x15/0x20 [ 179.816189] task_work_run+0x197/0x260 [ 179.816189] exit_to_usermode_loop+0x23b/0x2a0 [ 179.816189] syscall_return_slowpath+0x4d3/0x570 [ 179.816189] entry_SYSCALL_64_fastpath+0xc0/0xc2 [ 179.816189] Disposed: [ 179.816189] PID = 21945 [ 179.816189] save_stack_trace+0x16/0x20 [ 179.816189] save_stack+0x43/0xd0 [ 179.816189] kasan_set_rcu_track+0xcf/0xf0 [ 179.816189] __call_rcu.constprop.77+0x1d6/0x15a0 [ 179.816189] call_rcu_sched+0x12/0x20 [ 179.816189] dentry_free+0xb7/0x160 [ 179.816189] __dentry_kill+0x471/0x6d0 [ 179.816189] dput.part.25+0x4fe/0x7c0 [ 179.816189] dput+0x1f/0x30 [ 179.816189] __debugfs_remove.part.10+0xb8/0xf0 [ 179.816189] debugfs_remove+0xea/0x1f0 [ 179.816189] bdi_unregister+0x2f9/0x550 [ 179.816189] bdi_destroy+0x15/0x20 [ 179.816189] v9fs_session_init+0x905/0x1a30 [ 179.816189] v9fs_mount+0x81/0x830 [ 179.816189] mount_fs+0x97/0x2e0 [ 179.816189] vfs_kern_mount.part.23+0xc6/0x490 [ 179.816189] do_mount+0x418/0x2da0 [ 179.816189] SyS_mount+0xab/0x120 [ 179.816189] entry_SYSCALL_64_fastpath+0x1f/0xc2 [ 179.816189] Memory state around the buggy address: [ 179.816189] ffff88005c34c800: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc [ 179.816189] ffff88005c34c880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 179.816189] >ffff88005c34c900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb [ 179.816189] ^ [ 179.816189] ffff88005c34c980: fb fb fb fb fc fc fc fc fc fc fc fc 00 00 00 00 [ 179.816189] ffff88005c34ca00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 [ 179.816189] ==================================================================