Skip to content

Commit

Permalink
Btrfs: make sure we update latest_bdev
Browse files Browse the repository at this point in the history
When we are setting up the mount, we close all the
devices that were not actually part of the metadata we found.

But, we don't make sure that one of those devices wasn't
fs_devices->latest_bdev, which means we can do a use after free
on the one we closed.

This updates latest_bdev as it goes.

Signed-off-by: Chris Mason <[email protected]>
  • Loading branch information
chrismason-xx committed Feb 23, 2012
1 parent fe66a05 commit a6b0d5c
Show file tree
Hide file tree
Showing 2 changed files with 22 additions and 1 deletion.
6 changes: 6 additions & 0 deletions fs/btrfs/disk-io.c
Original file line number Diff line number Diff line change
Expand Up @@ -2305,6 +2305,12 @@ struct btrfs_root *open_ctree(struct super_block *sb,

btrfs_close_extra_devices(fs_devices);

if (!fs_devices->latest_bdev) {
printk(KERN_CRIT "btrfs: failed to read devices on %s\n",
sb->s_id);
goto fail_tree_roots;
}

retry_root_backup:
blocksize = btrfs_level_size(tree_root,
btrfs_super_root_level(disk_super));
Expand Down
17 changes: 16 additions & 1 deletion fs/btrfs/volumes.c
Original file line number Diff line number Diff line change
Expand Up @@ -459,12 +459,23 @@ int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
{
struct btrfs_device *device, *next;

struct block_device *latest_bdev = NULL;
u64 latest_devid = 0;
u64 latest_transid = 0;

mutex_lock(&uuid_mutex);
again:
/* This is the initialized path, it is safe to release the devices. */
list_for_each_entry_safe(device, next, &fs_devices->devices, dev_list) {
if (device->in_fs_metadata)
if (device->in_fs_metadata) {
if (!latest_transid ||
device->generation > latest_transid) {
latest_devid = device->devid;
latest_transid = device->generation;
latest_bdev = device->bdev;
}
continue;
}

if (device->bdev) {
blkdev_put(device->bdev, device->mode);
Expand All @@ -487,6 +498,10 @@ int btrfs_close_extra_devices(struct btrfs_fs_devices *fs_devices)
goto again;
}

fs_devices->latest_bdev = latest_bdev;
fs_devices->latest_devid = latest_devid;
fs_devices->latest_trans = latest_transid;

mutex_unlock(&uuid_mutex);
return 0;
}
Expand Down

0 comments on commit a6b0d5c

Please sign in to comment.