From 540c39279322cb278ad45840f260fe4b92c3c8b7 Mon Sep 17 00:00:00 2001 From: Chunwei Chen Date: Fri, 27 May 2016 15:39:34 -0700 Subject: [PATCH] Fix out-of-bound access in zfs_fillpage The original code will do an out-of-bound access on pl[] during last iteration. ================================================================== BUG: KASAN: stack-out-of-bounds in zfs_getpage+0x14c/0x2d0 [zfs] Read of size 8 by task tmpfile/7850 page:ffffea00017c6dc0 count:0 mapcount:0 mapping: (null) index:0x0 flags: 0xffff8000000000() page dumped because: kasan: bad access detected CPU: 3 PID: 7850 Comm: tmpfile Tainted: G OE 4.6.0+ #3 ffff88005f1b7678 0000000006dbe035 ffff88005f1b7508 ffffffff81635618 ffff88005f1b7678 ffff88005f1b75a0 ffff88005f1b7590 ffffffff81313ee8 ffffea0001ae8dd0 ffff88005f1b7670 0000000000000246 0000000041b58ab3 Call Trace: [] dump_stack+0x63/0x8b [] kasan_report_error+0x528/0x560 [] ? filemap_map_pages+0x5f0/0x5f0 [] kasan_report+0x58/0x60 [] ? zfs_getpage+0x14c/0x2d0 [zfs] [] __asan_load8+0x5e/0x70 [] zfs_getpage+0x14c/0x2d0 [zfs] [] zpl_readpage+0xd1/0x180 [zfs] [] SyS_execve+0x3a/0x50 [] do_syscall_64+0xef/0x180 [] entry_SYSCALL64_slow_path+0x25/0x25 Memory state around the buggy address: ffff88005f1b7500: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ffff88005f1b7580: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 >ffff88005f1b7600: 00 00 00 00 00 00 00 00 00 00 f1 f1 f1 f1 00 f4 ^ ffff88005f1b7680: f4 f4 f3 f3 f3 f3 00 00 00 00 00 00 00 00 00 00 ffff88005f1b7700: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ================================================================== Signed-off-by: Chunwei Chen Signed-off-by: Tony Hutter Signed-off-by: Brian Behlendorf Closes #4705 Issue #4708 --- module/zfs/zfs_vnops.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/module/zfs/zfs_vnops.c b/module/zfs/zfs_vnops.c index e53992cbbd..48a72e3023 100644 --- a/module/zfs/zfs_vnops.c +++ b/module/zfs/zfs_vnops.c @@ -4271,10 +4271,10 @@ zfs_fillpage(struct inode *ip, struct page *pl[], int nr_pages) * Iterate over list of pages and read each page individually. */ page_idx = 0; - cur_pp = pl[0]; for (total = io_off + io_len; io_off < total; io_off += PAGESIZE) { caddr_t va; + cur_pp = pl[page_idx++]; va = kmap(cur_pp); err = dmu_read(os, zp->z_id, io_off, PAGESIZE, va, DMU_READ_PREFETCH); @@ -4285,7 +4285,6 @@ zfs_fillpage(struct inode *ip, struct page *pl[], int nr_pages) err = SET_ERROR(EIO); return (err); } - cur_pp = pl[++page_idx]; } return (0);