summaryrefslogtreecommitdiff
path: root/fs/readdir.c
diff options
context:
space:
mode:
authorAnand Jain <anand.jain@oracle.com>2018-08-06 18:12:37 +0800
committerDavid Sterba <dsterba@suse.com>2018-08-23 17:37:27 +0200
commit801660b040d132f67fac6a95910ad307c5929b49 (patch)
treea179695d4720b1f61d2f8f6bb87c7bacaabf81b3 /fs/readdir.c
parenta5b7f4295eeae8b05ca91f6d145cd8773b08de9e (diff)
downloadlinux-801660b040d132f67fac6a95910ad307c5929b49.tar.gz
btrfs: btrfs_shrink_device should call commit transaction at the end
Test case btrfs/164 reports use-after-free: [ 6712.084324] general protection fault: 0000 [#1] PREEMPT SMP .. [ 6712.195423] btrfs_update_commit_device_size+0x75/0xf0 [btrfs] [ 6712.201424] btrfs_commit_transaction+0x57d/0xa90 [btrfs] [ 6712.206999] btrfs_rm_device+0x627/0x850 [btrfs] [ 6712.211800] btrfs_ioctl+0x2b03/0x3120 [btrfs] Reason for this is that btrfs_shrink_device adds the resized device to the fs_devices::resized_devices after it has called the last commit transaction. So the list fs_devices::resized_devices is not empty when btrfs_shrink_device returns. Now the parent function btrfs_rm_device calls: btrfs_close_bdev(device); call_rcu(&device->rcu, free_device_rcu); and then does the transactio ncommit. It goes through the fs_devices::resized_devices in btrfs_update_commit_device_size and leads to use-after-free. Fix this by making sure btrfs_shrink_device calls the last needed btrfs_commit_transaction before the return. This is consistent with what the grow counterpart does and this makes sure the on-disk state is persistent when the function returns. Reported-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com> Tested-by: Lu Fengqi <lufq.fnst@cn.fujitsu.com> Signed-off-by: Anand Jain <anand.jain@oracle.com> Reviewed-by: David Sterba <dsterba@suse.com> [ update changelog ] Signed-off-by: David Sterba <dsterba@suse.com>
Diffstat (limited to 'fs/readdir.c')
0 files changed, 0 insertions, 0 deletions