linux/fs/xfs
Eryu Guan 161f55efba xfs: fix use-after-free in xfs_finish_page_writeback
Commit 28b783e47a ("xfs: bufferhead chains are invalid after
end_page_writeback") fixed one use-after-free issue by
pre-calculating the loop conditionals before calling bh->b_end_io()
in the end_io processing loop, but it assigned 'next' pointer before
checking end offset boundary & breaking the loop, at which point the
bh might be freed already, and caused use-after-free.

This is caught by KASAN when running fstests generic/127 on sub-page
block size XFS.

[ 2517.244502] run fstests generic/127 at 2017-04-27 07:30:50
[ 2747.868840] ==================================================================
[ 2747.876949] BUG: KASAN: use-after-free in xfs_destroy_ioend+0x3d3/0x4e0 [xfs] at addr ffff8801395ae698
...
[ 2747.918245] Call Trace:
[ 2747.920975]  dump_stack+0x63/0x84
[ 2747.924673]  kasan_object_err+0x21/0x70
[ 2747.928950]  kasan_report+0x271/0x530
[ 2747.933064]  ? xfs_destroy_ioend+0x3d3/0x4e0 [xfs]
[ 2747.938409]  ? end_page_writeback+0xce/0x110
[ 2747.943171]  __asan_report_load8_noabort+0x19/0x20
[ 2747.948545]  xfs_destroy_ioend+0x3d3/0x4e0 [xfs]
[ 2747.953724]  xfs_end_io+0x1af/0x2b0 [xfs]
[ 2747.958197]  process_one_work+0x5ff/0x1000
[ 2747.962766]  worker_thread+0xe4/0x10e0
[ 2747.966946]  kthread+0x2d3/0x3d0
[ 2747.970546]  ? process_one_work+0x1000/0x1000
[ 2747.975405]  ? kthread_create_on_node+0xc0/0xc0
[ 2747.980457]  ? syscall_return_slowpath+0xe6/0x140
[ 2747.985706]  ? do_page_fault+0x30/0x80
[ 2747.989887]  ret_from_fork+0x2c/0x40
[ 2747.993874] Object at ffff8801395ae690, in cache buffer_head size: 104
[ 2748.001155] Allocated:
[ 2748.003782] PID = 8327
[ 2748.006411]  save_stack_trace+0x1b/0x20
[ 2748.010688]  save_stack+0x46/0xd0
[ 2748.014383]  kasan_kmalloc+0xad/0xe0
[ 2748.018370]  kasan_slab_alloc+0x12/0x20
[ 2748.022648]  kmem_cache_alloc+0xb8/0x1b0
[ 2748.027024]  alloc_buffer_head+0x22/0xc0
[ 2748.031399]  alloc_page_buffers+0xd1/0x250
[ 2748.035968]  create_empty_buffers+0x30/0x410
[ 2748.040730]  create_page_buffers+0x120/0x1b0
[ 2748.045493]  __block_write_begin_int+0x17a/0x1800
[ 2748.050740]  iomap_write_begin+0x100/0x2f0
[ 2748.055308]  iomap_zero_range_actor+0x253/0x5c0
[ 2748.060362]  iomap_apply+0x157/0x270
[ 2748.064347]  iomap_zero_range+0x5a/0x80
[ 2748.068624]  iomap_truncate_page+0x6b/0xa0
[ 2748.073227]  xfs_setattr_size+0x1f7/0xa10 [xfs]
[ 2748.078312]  xfs_vn_setattr_size+0x68/0x140 [xfs]
[ 2748.083589]  xfs_file_fallocate+0x4ac/0x820 [xfs]
[ 2748.088838]  vfs_fallocate+0x2cf/0x780
[ 2748.093021]  SyS_fallocate+0x48/0x80
[ 2748.097006]  do_syscall_64+0x18a/0x430
[ 2748.101186]  return_from_SYSCALL_64+0x0/0x6a
[ 2748.105948] Freed:
[ 2748.108189] PID = 8327
[ 2748.110816]  save_stack_trace+0x1b/0x20
[ 2748.115093]  save_stack+0x46/0xd0
[ 2748.118788]  kasan_slab_free+0x73/0xc0
[ 2748.122969]  kmem_cache_free+0x7a/0x200
[ 2748.127247]  free_buffer_head+0x41/0x80
[ 2748.131524]  try_to_free_buffers+0x178/0x250
[ 2748.136316]  xfs_vm_releasepage+0x2e9/0x3d0 [xfs]
[ 2748.141563]  try_to_release_page+0x100/0x180
[ 2748.146325]  invalidate_inode_pages2_range+0x7da/0xcf0
[ 2748.152087]  xfs_shift_file_space+0x37d/0x6e0 [xfs]
[ 2748.157557]  xfs_collapse_file_space+0x49/0x120 [xfs]
[ 2748.163223]  xfs_file_fallocate+0x2a7/0x820 [xfs]
[ 2748.168462]  vfs_fallocate+0x2cf/0x780
[ 2748.172642]  SyS_fallocate+0x48/0x80
[ 2748.176629]  do_syscall_64+0x18a/0x430
[ 2748.180810]  return_from_SYSCALL_64+0x0/0x6a

Fixed it by checking on offset against end & breaking out first,
dereference bh only if there're still bufferheads to process.

Signed-off-by: Eryu Guan <eguan@redhat.com>
Reviewed-by: Christoph Hellwig <hch@lst.de>
Reviewed-by: Darrick J. Wong <darrick.wong@oracle.com>
Signed-off-by: Darrick J. Wong <darrick.wong@oracle.com>
2017-05-05 12:16:48 -07:00
..
libxfs xfs: reserve enough blocks to handle btree splits when remapping 2017-05-03 13:21:40 -07:00
Kconfig xfs: implement iomap based buffered write path 2016-06-21 09:53:44 +10:00
kmem.c xfs: remove kmem_zalloc_greedy 2017-03-07 20:10:50 -08:00
kmem.h xfs: remove kmem_zalloc_greedy 2017-03-07 20:10:50 -08:00
Makefile xfs: implement the GETFSMAP ioctl 2017-04-03 15:18:17 -07:00
mrlock.h
uuid.c
uuid.h
xfs_acl.c Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/viro/vfs 2016-10-10 20:16:43 -07:00
xfs_acl.h
xfs_aops.c xfs: fix use-after-free in xfs_finish_page_writeback 2017-05-05 12:16:48 -07:00
xfs_aops.h xfs: use iomap_dio_rw 2016-11-30 14:37:15 +11:00
xfs_attr_inactive.c xfs: make several functions static 2016-06-01 17:38:15 +10:00
xfs_attr_list.c xfs: several xattr functions can be void 2016-12-05 12:32:14 +11:00
xfs_attr.h xfs: several xattr functions can be void 2016-12-05 12:32:14 +11:00
xfs_bmap_item.c xfs: reserve enough blocks to handle btree splits when remapping 2017-05-03 13:21:40 -07:00
xfs_bmap_item.h xfs: log bmap intent items 2016-10-04 11:05:44 -07:00
xfs_bmap_util.c xfs: more do_div cleanups 2017-04-25 09:40:41 -07:00
xfs_bmap_util.h xfs: remove unused full argument from bmap 2017-01-30 16:32:25 -08:00
xfs_buf_item.c xfs: reset b_first_retry_time when clear the retry status of xfs_buf_t 2017-02-03 14:39:07 -08:00
xfs_buf_item.h
xfs_buf.c xfs: fix up quotacheck buffer list error handling 2017-04-25 09:40:42 -07:00
xfs_buf.h xfs: fix up quotacheck buffer list error handling 2017-04-25 09:40:42 -07:00
xfs_dir2_readdir.c xfs: prevent multi-fsb dir readahead from reading random blocks 2017-04-25 09:40:40 -07:00
xfs_discard.c xfs: Allow user to kill fstrim process 2017-04-27 10:45:34 -07:00
xfs_discard.h xfs: don't block the log commit handler for discards 2017-02-09 11:36:40 -08:00
xfs_dquot_item.c xfs: allocate log vector buffers outside CIL context lock 2016-07-22 09:52:35 +10:00
xfs_dquot_item.h
xfs_dquot.c xfs: don't wrap ID in xfs_dq_get_next_id 2017-01-17 11:43:38 -08:00
xfs_dquot.h
xfs_error.c Merge branch 'xfs-4.8-misc-fixes-3' into for-next 2016-07-20 11:51:08 +10:00
xfs_error.h xfs: simulate per-AG reservations being critically low 2016-10-05 16:26:31 -07:00
xfs_export.c xfs: abstract block export operations from nfsd layouts 2016-07-15 15:31:29 -04:00
xfs_export.h
xfs_extent_busy.c xfs: fix len comparison in xfs_extent_busy_trim 2017-02-16 17:20:12 -08:00
xfs_extent_busy.h xfs: improve handling of busy extents in the low-level allocator 2017-02-09 10:50:25 -08:00
xfs_extfree_item.c xfs: better log intent item refcount checking 2017-04-25 09:40:42 -07:00
xfs_extfree_item.h xfs: refactor redo intent item processing 2016-08-03 11:23:49 +10:00
xfs_file.c fs: add i_blocksize() 2017-02-27 18:43:46 -08:00
xfs_filestream.c Merge branch 'xfs-4.9-log-recovery-fixes' into for-next 2016-10-03 09:56:28 +11:00
xfs_filestream.h
xfs_fsmap.c xfs: use NULL instead of 0 to initialize a pointer in xfs_getfsmap 2017-04-25 09:40:41 -07:00
xfs_fsmap.h xfs: implement the GETFSMAP ioctl 2017-04-03 15:18:17 -07:00
xfs_fsops.c xfs: remove boilerplate around xfs_btree_init_block 2017-01-30 16:32:24 -08:00
xfs_fsops.h xfs: preallocate blocks for worst-case btree expansion 2016-10-05 16:26:27 -07:00
xfs_globals.c xfs: garbage collect old cowextsz reservations 2016-10-05 16:26:28 -07:00
xfs_icache.c xfs: update ag iterator to support wait on new inodes 2017-04-28 08:11:08 -07:00
xfs_icache.h xfs: update ag iterator to support wait on new inodes 2017-04-28 08:11:08 -07:00
xfs_icreate_item.c fs: xfs: xfs_icreate_item: constify xfs_item_ops structure 2016-11-28 14:57:42 +11:00
xfs_icreate_item.h
xfs_inode_item.c xfs: remove xfs_trans_ail_delete_bulk 2017-04-25 09:40:42 -07:00
xfs_inode_item.h
xfs_inode.c xfs: drop iolock from reclaim context to appease lockdep 2017-04-12 08:43:23 -07:00
xfs_inode.h xfs: support ability to wait on new inodes 2017-04-28 08:11:08 -07:00
xfs_ioctl32.c xfs: implement the GETFSMAP ioctl 2017-04-03 15:18:17 -07:00
xfs_ioctl32.h
xfs_ioctl.c xfs: fix getfsmap userspace memory corruption while setting OF_LAST 2017-04-25 09:40:42 -07:00
xfs_ioctl.h xfs: don't pass ioflags around in the ioctl path 2016-07-20 11:29:35 +10:00
xfs_iomap.c xfs: actually report xattr extents via iomap 2017-04-06 16:00:39 -07:00
xfs_iomap.h xfs: introduce xfs_aligned_fsb_count 2017-02-06 17:47:46 -08:00
xfs_iops.c statx: Add a system call to make enhanced file info available 2017-03-02 20:51:15 -05:00
xfs_iops.h xfs: Propagate dentry down to inode_change_ok() 2016-09-22 10:56:19 +02:00
xfs_itable.c xfs: fix kernel memory exposure problems 2017-04-03 15:18:15 -07:00
xfs_itable.h
xfs_linux.h xfs: remove custom do_div implementations 2017-04-12 08:42:51 -07:00
xfs_log_cil.c xfs: don't block the log commit handler for discards 2017-02-09 11:36:40 -08:00
xfs_log_priv.h xfs: don't block the log commit handler for discards 2017-02-09 11:36:40 -08:00
xfs_log_recover.c Merge branch 'xfs-4.10-misc-fixes-3' into for-next 2016-12-07 17:42:30 +11:00
xfs_log.c xfs: corruption needs to respect endianess too! 2017-04-25 09:40:42 -07:00
xfs_log.h xfs: remove unused struct declarations 2017-01-30 16:32:25 -08:00
xfs_message.c
xfs_message.h
xfs_mount.c xfs: publish UUID in struct super_block 2017-04-28 08:10:53 -07:00
xfs_mount.h xfs: more do_div cleanups 2017-04-25 09:40:41 -07:00
xfs_mru_cache.c
xfs_mru_cache.h
xfs_ondisk.h xfs: define the on-disk refcount btree format 2016-10-03 09:11:18 -07:00
xfs_pnfs.c xfs: remove i_iolock and use i_rwsem in the VFS inode instead 2016-11-30 14:33:25 +11:00
xfs_pnfs.h xfs: remove i_iolock and use i_rwsem in the VFS inode instead 2016-11-30 14:33:25 +11:00
xfs_qm_bhv.c
xfs_qm_syscalls.c xfs: wait on new inodes during quotaoff dquot release 2017-04-28 08:11:08 -07:00
xfs_qm.c xfs: fix up quotacheck buffer list error handling 2017-04-25 09:40:42 -07:00
xfs_qm.h
xfs_quota.h
xfs_quotaops.c
xfs_refcount_item.c xfs: better log intent item refcount checking 2017-04-25 09:40:42 -07:00
xfs_refcount_item.h xfs: log refcount intent items 2016-10-03 09:11:21 -07:00
xfs_reflink.c xfs: reserve enough blocks to handle btree splits when remapping 2017-05-03 13:21:40 -07:00
xfs_reflink.h xfs: only reclaim unwritten COW extents periodically 2017-03-07 16:45:58 -08:00
xfs_rmap_item.c xfs: better log intent item refcount checking 2017-04-25 09:40:42 -07:00
xfs_rmap_item.h xfs: convert RUI log formats to use variable length arrays 2016-09-19 10:24:27 +10:00
xfs_rtalloc.c xfs: simplify xfs_rtallocate_extent 2017-02-17 16:52:52 -08:00
xfs_rtalloc.h xfs: add a couple of queries to iterate free extents in the rtbitmap 2017-04-03 15:18:17 -07:00
xfs_stats.c xfs: make xfs btree stats less huge 2016-12-05 14:38:58 +11:00
xfs_stats.h xfs: make xfs btree stats less huge 2016-12-05 14:38:58 +11:00
xfs_super.c xfs: use dedicated log worker wq to avoid deadlock with cil wq 2017-04-03 15:18:15 -07:00
xfs_super.h xfs: don't block the log commit handler for discards 2017-02-09 11:36:40 -08:00
xfs_symlink.c xfs: remove i_iolock and use i_rwsem in the VFS inode instead 2016-11-30 14:33:25 +11:00
xfs_symlink.h
xfs_sysctl.c xfs: garbage collect old cowextsz reservations 2016-10-05 16:26:28 -07:00
xfs_sysctl.h xfs: garbage collect old cowextsz reservations 2016-10-05 16:26:28 -07:00
xfs_sysfs.c xfs: resurrect debug mode drop buffered writes mechanism 2017-02-16 17:19:15 -08:00
xfs_sysfs.h xfs: configurable error behavior via sysfs 2016-05-18 10:58:51 +10:00
xfs_trace.c xfs: implement the GETFSMAP ioctl 2017-04-03 15:18:17 -07:00
xfs_trace.h xfs: don't use bool values in trace buffers 2017-04-25 09:40:42 -07:00
xfs_trans_ail.c xfs: remove xfs_trans_ail_delete_bulk 2017-04-25 09:40:42 -07:00
xfs_trans_bmap.c xfs: implement deferred bmbt map/unmap operations 2016-10-04 11:05:44 -07:00
xfs_trans_buf.c xfs: remove XBF_STALE flag wrapper macros 2016-02-10 15:01:11 +11:00
xfs_trans_dquot.c
xfs_trans_extfree.c xfs: set up per-AG free space reservations 2016-09-19 10:30:52 +10:00
xfs_trans_inode.c fs: Replace current_fs_time() with current_time() 2016-09-27 21:06:22 -04:00
xfs_trans_priv.h xfs: remove xfs_trans_ail_delete_bulk 2017-04-25 09:40:42 -07:00
xfs_trans_refcount.c xfs: connect refcount adjust functions to upper layers 2016-10-03 09:11:22 -07:00
xfs_trans_rmap.c xfs: add shared rmap map/unmap/convert log item types 2016-10-05 16:26:29 -07:00
xfs_trans.c xfs: fold __xfs_trans_roll into xfs_trans_roll 2017-04-06 16:00:11 -07:00
xfs_trans.h xfs: fold __xfs_trans_roll into xfs_trans_roll 2017-04-06 16:00:11 -07:00
xfs_xattr.c xfs: several xattr functions can be void 2016-12-05 12:32:14 +11:00
xfs.h