mirror of
https://github.com/kdave/btrfs-progs
synced 2025-02-06 12:52:01 +00:00
btrfs-progs: check if adding device would overflow while scanning
It's theoretically possible to add multiple devices with sizes that add up to or exceed 16EiB. A file system will be created successfully but will have a superblock with incorrect values for total_bytes and other fields. Kernels up to v5.0 will crash when they encounter this scenario. We need to check for overflow and reject the device if it would overflow. Bugzilla: https://bugzilla.suse.com/show_bug.cgi?id=1099147 Reviewed-by: Qu Wenruo <wqu@suse.com> Signed-off-by: Jeff Mahoney <jeffm@suse.com> Signed-off-by: David Sterba <dsterba@suse.com>
This commit is contained in:
parent
391b891278
commit
d29f475108
@ -26,6 +26,7 @@
|
||||
#include <linux/limits.h>
|
||||
#include <blkid/blkid.h>
|
||||
#include <uuid/uuid.h>
|
||||
#include "kernel-lib/overflow.h"
|
||||
#include "common/path-utils.h"
|
||||
#include "common/device-scan.h"
|
||||
#include "common/messages.h"
|
||||
@ -118,7 +119,8 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
|
||||
struct btrfs_device *device;
|
||||
struct btrfs_dev_item *dev_item;
|
||||
char *buf = NULL;
|
||||
u64 fs_total_bytes;
|
||||
const u64 old_size = btrfs_super_total_bytes(super);
|
||||
u64 new_size;
|
||||
u64 num_devs;
|
||||
int ret;
|
||||
|
||||
@ -156,13 +158,20 @@ int btrfs_add_to_fsid(struct btrfs_trans_handle *trans,
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (check_add_overflow(old_size, device_total_bytes, &new_size)) {
|
||||
error(
|
||||
"adding device of %llu bytes would exceed max file system size",
|
||||
device->total_bytes);
|
||||
ret = -EOVERFLOW;
|
||||
goto out;
|
||||
}
|
||||
|
||||
INIT_LIST_HEAD(&device->dev_list);
|
||||
ret = btrfs_add_device(trans, fs_info, device);
|
||||
if (ret)
|
||||
goto out;
|
||||
|
||||
fs_total_bytes = btrfs_super_total_bytes(super) + device_total_bytes;
|
||||
btrfs_set_super_total_bytes(super, fs_total_bytes);
|
||||
btrfs_set_super_total_bytes(super, new_size);
|
||||
|
||||
num_devs = btrfs_super_num_devices(super) + 1;
|
||||
btrfs_set_super_num_devices(super, num_devs);
|
||||
|
Loading…
Reference in New Issue
Block a user