From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from fieldses.org ([173.255.197.46]:45288 "EHLO fieldses.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752904AbeFHUyd (ORCPT ); Fri, 8 Jun 2018 16:54:33 -0400 Date: Fri, 8 Jun 2018 16:54:33 -0400 From: "J. Bruce Fields" To: Scott Mayhew Cc: jlayton@kernel.org, linux-nfs@vger.kernel.org Subject: Re: [PATCH] nfsd: fix potential use-after-free in nfsd4_decode_getdeviceinfo Message-ID: <20180608205433.GA14821@fieldses.org> References: <20180608203146.19810-1-smayhew@redhat.com> MIME-Version: 1.0 Content-Type: text/plain; charset=us-ascii In-Reply-To: <20180608203146.19810-1-smayhew@redhat.com> Sender: linux-nfs-owner@vger.kernel.org List-ID: On Fri, Jun 08, 2018 at 04:31:46PM -0400, Scott Mayhew wrote: > When running a fuzz tester against a KASAN-enabled kernel, the following > splat periodically occurs. Applied, thanks! Also checked the three other pnfs decoders there and didn't see anything similar. --b. > > The problem occurs when the test sends a GETDEVICEINFO request with a > malformed xdr array (size but no data) for gdia_notify_types and the > array size is > 0x3fffffff, which results in an overflow in the value of > nbytes which is passed to read_buf(). > > If the array size is 0x40000000, 0x80000000, or 0xc0000000, then after > the overflow occurs, the value of nbytes 0, and when that happens the > pointer returned by read_buf() points to the end of the xdr data (i.e. > argp->end) when really it should be returning NULL. > > Fix this by returning NFS4ERR_BAD_XDR if the array size is > 1000 (this > value is arbitrary, but it's the same threshold used by > nfsd4_decode_bitmap()... in could really be any value >= 1 since it's > expected to get at most a single bitmap in gdia_notify_types). > > [ 119.256854] ================================================================== > [ 119.257611] BUG: KASAN: use-after-free in nfsd4_decode_getdeviceinfo+0x5a4/0x5b0 [nfsd] > [ 119.258422] Read of size 4 at addr ffff880113ada000 by task nfsd/538 > > [ 119.259146] CPU: 0 PID: 538 Comm: nfsd Not tainted 4.17.0+ #1 > [ 119.259662] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.9.3-1.fc25 04/01/2014 > [ 119.261202] Call Trace: > [ 119.262265] dump_stack+0x71/0xab > [ 119.263371] print_address_description+0x6a/0x270 > [ 119.264609] kasan_report+0x258/0x380 > [ 119.265854] ? nfsd4_decode_getdeviceinfo+0x5a4/0x5b0 [nfsd] > [ 119.267291] nfsd4_decode_getdeviceinfo+0x5a4/0x5b0 [nfsd] > [ 119.268549] ? nfs4svc_decode_compoundargs+0xa5b/0x13c0 [nfsd] > [ 119.269873] ? nfsd4_decode_sequence+0x490/0x490 [nfsd] > [ 119.271095] nfs4svc_decode_compoundargs+0xa5b/0x13c0 [nfsd] > [ 119.272393] ? nfsd4_release_compoundargs+0x1b0/0x1b0 [nfsd] > [ 119.273658] nfsd_dispatch+0x183/0x850 [nfsd] > [ 119.274918] svc_process+0x161c/0x31a0 [sunrpc] > [ 119.276172] ? svc_printk+0x190/0x190 [sunrpc] > [ 119.277386] ? svc_xprt_release+0x451/0x680 [sunrpc] > [ 119.278622] nfsd+0x2b9/0x430 [nfsd] > [ 119.279771] ? nfsd_destroy+0x1c0/0x1c0 [nfsd] > [ 119.281157] kthread+0x2db/0x390 > [ 119.282347] ? kthread_create_worker_on_cpu+0xc0/0xc0 > [ 119.283756] ret_from_fork+0x35/0x40 > > [ 119.286041] Allocated by task 436: > [ 119.287525] kasan_kmalloc+0xa0/0xd0 > [ 119.288685] kmem_cache_alloc+0xe9/0x1f0 > [ 119.289900] get_empty_filp+0x7b/0x410 > [ 119.291037] path_openat+0xca/0x4220 > [ 119.292242] do_filp_open+0x182/0x280 > [ 119.293411] do_sys_open+0x216/0x360 > [ 119.294555] do_syscall_64+0xa0/0x2f0 > [ 119.295721] entry_SYSCALL_64_after_hwframe+0x44/0xa9 > > [ 119.298068] Freed by task 436: > [ 119.299271] __kasan_slab_free+0x130/0x180 > [ 119.300557] kmem_cache_free+0x78/0x210 > [ 119.301823] rcu_process_callbacks+0x35b/0xbd0 > [ 119.303162] __do_softirq+0x192/0x5ea > > [ 119.305443] The buggy address belongs to the object at ffff880113ada000 > which belongs to the cache filp of size 256 > [ 119.308556] The buggy address is located 0 bytes inside of > 256-byte region [ffff880113ada000, ffff880113ada100) > [ 119.311376] The buggy address belongs to the page: > [ 119.312728] page:ffffea00044eb680 count:1 mapcount:0 mapping:0000000000000000 index:0xffff880113ada780 > [ 119.314428] flags: 0x17ffe000000100(slab) > [ 119.315740] raw: 0017ffe000000100 0000000000000000 ffff880113ada780 00000001000c0001 > [ 119.317379] raw: ffffea0004553c60 ffffea00045c11e0 ffff88011b167e00 0000000000000000 > [ 119.319050] page dumped because: kasan: bad access detected > > [ 119.321652] Memory state around the buggy address: > [ 119.322993] ffff880113ad9f00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > [ 119.324515] ffff880113ad9f80: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 > [ 119.326087] >ffff880113ada000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > [ 119.327547] ^ > [ 119.328730] ffff880113ada080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb > [ 119.330218] ffff880113ada100: fc fc fc fc fc fc fc fc fb fb fb fb fb fb fb fb > [ 119.331740] ================================================================== > > Signed-off-by: Scott Mayhew > --- > fs/nfsd/nfs4xdr.c | 2 ++ > 1 file changed, 2 insertions(+) > > diff --git a/fs/nfsd/nfs4xdr.c b/fs/nfsd/nfs4xdr.c > index 1d048dd..48e412e 100644 > --- a/fs/nfsd/nfs4xdr.c > +++ b/fs/nfsd/nfs4xdr.c > @@ -1585,6 +1585,8 @@ nfsd4_decode_getdeviceinfo(struct nfsd4_compoundargs *argp, > gdev->gd_maxcount = be32_to_cpup(p++); > num = be32_to_cpup(p++); > if (num) { > + if (num > 1000) > + goto xdr_error; > READ_BUF(4 * num); > gdev->gd_notify_types = be32_to_cpup(p++); > for (i = 1; i < num; i++) { > -- > 2.9.5