linux/fs/f2fs
Chao Yu dbf20cb259 f2fs: avoid use invalid mapping of node_inode when evict meta inode
Andrey Tsyvarev reported:
"Using memory error detector reveals the following use-after-free error
in 3.15.0:

AddressSanitizer: heap-use-after-free in f2fs_evict_inode
Read of size 8 by thread T22279:
  [<ffffffffa02d8702>] f2fs_evict_inode+0x102/0x2e0 [f2fs]
  [<ffffffff812359af>] evict+0x15f/0x290
  [<     inlined    >] iput+0x196/0x280 iput_final
  [<ffffffff812369a6>] iput+0x196/0x280
  [<ffffffffa02dc416>] f2fs_put_super+0xd6/0x170 [f2fs]
  [<ffffffff81210095>] generic_shutdown_super+0xc5/0x1b0
  [<ffffffff812105fd>] kill_block_super+0x4d/0xb0
  [<ffffffff81210a86>] deactivate_locked_super+0x66/0x80
  [<ffffffff81211c98>] deactivate_super+0x68/0x80
  [<ffffffff8123cc88>] mntput_no_expire+0x198/0x250
  [<     inlined    >] SyS_umount+0xe9/0x1a0 SYSC_umount
  [<ffffffff8123f1c9>] SyS_umount+0xe9/0x1a0
  [<ffffffff81cc8df9>] system_call_fastpath+0x16/0x1b

Freed by thread T3:
  [<ffffffffa02dc337>] f2fs_i_callback+0x27/0x30 [f2fs]
  [<     inlined    >] rcu_process_callbacks+0x2d6/0x930 __rcu_reclaim
  [<     inlined    >] rcu_process_callbacks+0x2d6/0x930 rcu_do_batch
  [<     inlined    >] rcu_process_callbacks+0x2d6/0x930 invoke_rcu_callbacks
  [<     inlined    >] rcu_process_callbacks+0x2d6/0x930 __rcu_process_callbacks
  [<ffffffff810fd266>] rcu_process_callbacks+0x2d6/0x930
  [<ffffffff8107cce2>] __do_softirq+0x142/0x380
  [<ffffffff8107cf50>] run_ksoftirqd+0x30/0x50
  [<ffffffff810b2a87>] smpboot_thread_fn+0x197/0x280
  [<ffffffff810a8238>] kthread+0x148/0x160
  [<ffffffff81cc8d4c>] ret_from_fork+0x7c/0xb0

Allocated by thread T22276:
  [<ffffffffa02dc7dd>] f2fs_alloc_inode+0x2d/0x170 [f2fs]
  [<ffffffff81235e2a>] iget_locked+0x10a/0x230
  [<ffffffffa02d7495>] f2fs_iget+0x35/0xa80 [f2fs]
  [<ffffffffa02e2393>] f2fs_fill_super+0xb53/0xff0 [f2fs]
  [<ffffffff81211bce>] mount_bdev+0x1de/0x240
  [<ffffffffa02dbce0>] f2fs_mount+0x10/0x20 [f2fs]
  [<ffffffff81212a85>] mount_fs+0x55/0x220
  [<ffffffff8123c026>] vfs_kern_mount+0x66/0x200
  [<     inlined    >] do_mount+0x2b4/0x1120 do_new_mount
  [<ffffffff812400d4>] do_mount+0x2b4/0x1120
  [<     inlined    >] SyS_mount+0xb2/0x110 SYSC_mount
  [<ffffffff812414a2>] SyS_mount+0xb2/0x110
  [<ffffffff81cc8df9>] system_call_fastpath+0x16/0x1b

The buggy address ffff8800587866c8 is located 48 bytes inside
  of 680-byte region [ffff880058786698, ffff880058786940)

Memory state around the buggy address:
  ffff880058786100: ffffffff ffffffff ffffffff ffffffff
  ffff880058786200: ffffffff ffffffff ffffffrr rrrrrrrr
  ffff880058786300: rrrrrrrr rrffffff ffffffff ffffffff
  ffff880058786400: ffffffff ffffffff ffffffff ffffffff
  ffff880058786500: ffffffff ffffffff ffffffff fffffffr
 >ffff880058786600: rrrrrrrr rrrrrrrr rrrfffff ffffffff
                                                ^
  ffff880058786700: ffffffff ffffffff ffffffff ffffffff
  ffff880058786800: ffffffff ffffffff ffffffff ffffffff
  ffff880058786900: ffffffff rrrrrrrr rrrrrrrr rrrr....
  ffff880058786a00: ........ ........ ........ ........
  ffff880058786b00: ........ ........ ........ ........
Legend:
  f - 8 freed bytes
  r - 8 redzone bytes
  . - 8 allocated bytes
  x=1..7 - x allocated bytes + (8-x) redzone bytes

Investigation shows, that f2fs_evict_inode, when called for
'meta_inode', uses invalidate_mapping_pages() for 'node_inode'.
But 'node_inode' is deleted before 'meta_inode' in f2fs_put_super via
iput().

It seems that in common usage scenario this use-after-free is benign,
because 'node_inode' remains partially valid data even after
kmem_cache_free().
But things may change if, while 'meta_inode' is evicted in one f2fs
filesystem, another (mounted) f2fs filesystem requests inode from cache,
and formely
'node_inode' of the first filesystem is returned."

Nids for both meta_inode and node_inode are reservation, so it's not necessary
for us to invalidate pages which will never be allocated.
To fix this issue, let's skipping needlessly invalidating pages for
{meta,node}_inode in f2fs_evict_inode.

Reported-by: Andrey Tsyvarev <tsyvarev@ispras.ru>
Tested-by: Andrey Tsyvarev <tsyvarev@ispras.ru>
Signed-off-by: Gu Zheng <guz.fnst@cn.fujitsu.com>
Signed-off-by: Chao Yu <chao2.yu@samsung.com>
Signed-off-by: Jaegeuk Kim <jaegeuk@kernel.org>
2014-07-25 08:19:55 -07:00
..
acl.c f2fs: remove the redundant validation check of acl 2014-07-09 14:04:25 -07:00
acl.h f2fs: use generic posix ACL infrastructure 2014-01-25 23:58:19 -05:00
checkpoint.c f2fs updates for v3.16 2014-06-09 19:11:44 -07:00
data.c f2fs: add f2fs_balance_fs for direct IO 2014-07-25 08:13:58 -07:00
debug.c f2fs: cleanup the needless return of f2fs_create_root_stats 2014-07-11 15:01:47 -07:00
dir.c f2fs: check name_len of dir entry to prevent from deadloop 2014-07-10 17:00:02 -07:00
f2fs.h f2fs: remove the unused stat_lock 2014-07-11 15:01:48 -07:00
file.c f2fs: use inner macro and function to clean up codes 2014-07-09 14:04:26 -07:00
gc.c f2fs: remove the unused ctor argument of f2fs_kmem_cache_create() 2014-03-10 18:45:14 +09:00
gc.h f2fs: add a sysfs entry to control max_victim_search 2014-01-08 13:45:08 +09:00
hash.c f2fs: arguments cleanup of finding file flow functions 2014-07-09 14:04:26 -07:00
inline.c f2fs: avoid grab_cache_page_write_begin for data pages 2014-05-07 10:21:58 +09:00
inode.c f2fs: avoid use invalid mapping of node_inode when evict meta inode 2014-07-25 08:19:55 -07:00
Kconfig f2fs: introduce CONFIG_F2FS_CHECK_FS for BUG_ON control 2013-10-29 15:43:01 +09:00
Makefile f2fs: key functions to handle inline data 2013-12-26 20:40:09 +09:00
namei.c f2fs: support ->rename2() 2014-07-25 08:14:08 -07:00
node.c f2fs: refactor flush_nat_entries codes for reducing NAT writes 2014-07-09 14:04:25 -07:00
node.h f2fs: refactor flush_nat_entries codes for reducing NAT writes 2014-07-09 14:04:25 -07:00
recovery.c f2fs: avoid not to call remove_dirty_inode 2014-06-07 03:18:36 +09:00
segment.c f2fs: use inner macro and function to clean up codes 2014-07-09 14:04:26 -07:00
segment.h f2fs: reduce searching region of segmap when free section 2014-07-15 13:56:49 -07:00
super.c f2fs: use inner macro and function to clean up codes 2014-07-09 14:04:26 -07:00
xattr.c f2fs: fix recursive lock by f2fs_setxattr 2014-06-02 22:13:16 +09:00
xattr.h f2fs: pass flags field to setxattr functions 2014-05-07 10:21:56 +09:00