mirror of
https://github.com/torvalds/linux
synced 2024-10-15 15:59:15 +00:00
bcachefs: Add a better limit for maximum number of buckets
The bucket_gens array is a single array allocation (one byte per bucket), and kernel allocations are still limited to INT_MAX. Check this limit to avoid failing the bucket_gens array allocation. Reported-by: syzbot+b29f436493184ea42e2b@syzkaller.appspotmail.com Signed-off-by: Kent Overstreet <kent.overstreet@linux.dev>
This commit is contained in:
parent
18b4abcead
commit
db42549d40
|
@ -591,6 +591,12 @@ struct bch_member {
|
||||||
__le64 btree_allocated_bitmap;
|
__le64 btree_allocated_bitmap;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
/*
|
||||||
|
* This limit comes from the bucket_gens array - it's a single allocation, and
|
||||||
|
* kernel allocation are limited to INT_MAX
|
||||||
|
*/
|
||||||
|
#define BCH_MEMBER_NBUCKETS_MAX (INT_MAX - 64)
|
||||||
|
|
||||||
#define BCH_MEMBER_V1_BYTES 56
|
#define BCH_MEMBER_V1_BYTES 56
|
||||||
|
|
||||||
LE64_BITMASK(BCH_MEMBER_STATE, struct bch_member, flags, 0, 4)
|
LE64_BITMASK(BCH_MEMBER_STATE, struct bch_member, flags, 0, 4)
|
||||||
|
|
|
@ -175,6 +175,7 @@
|
||||||
x(EINVAL, block_size_too_small) \
|
x(EINVAL, block_size_too_small) \
|
||||||
x(EINVAL, bucket_size_too_small) \
|
x(EINVAL, bucket_size_too_small) \
|
||||||
x(EINVAL, device_size_too_small) \
|
x(EINVAL, device_size_too_small) \
|
||||||
|
x(EINVAL, device_size_too_big) \
|
||||||
x(EINVAL, device_not_a_member_of_filesystem) \
|
x(EINVAL, device_not_a_member_of_filesystem) \
|
||||||
x(EINVAL, device_has_been_removed) \
|
x(EINVAL, device_has_been_removed) \
|
||||||
x(EINVAL, device_splitbrain) \
|
x(EINVAL, device_splitbrain) \
|
||||||
|
|
|
@ -124,9 +124,9 @@ static int validate_member(struct printbuf *err,
|
||||||
struct bch_sb *sb,
|
struct bch_sb *sb,
|
||||||
int i)
|
int i)
|
||||||
{
|
{
|
||||||
if (le64_to_cpu(m.nbuckets) > LONG_MAX) {
|
if (le64_to_cpu(m.nbuckets) > BCH_MEMBER_NBUCKETS_MAX) {
|
||||||
prt_printf(err, "device %u: too many buckets (got %llu, max %lu)",
|
prt_printf(err, "device %u: too many buckets (got %llu, max %u)",
|
||||||
i, le64_to_cpu(m.nbuckets), LONG_MAX);
|
i, le64_to_cpu(m.nbuckets), BCH_MEMBER_NBUCKETS_MAX);
|
||||||
return -BCH_ERR_invalid_sb_members;
|
return -BCH_ERR_invalid_sb_members;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -1959,6 +1959,13 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
|
||||||
goto err;
|
goto err;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (nbuckets > BCH_MEMBER_NBUCKETS_MAX) {
|
||||||
|
bch_err(ca, "New device size too big (%llu greater than max %u)",
|
||||||
|
nbuckets, BCH_MEMBER_NBUCKETS_MAX);
|
||||||
|
ret = -BCH_ERR_device_size_too_big;
|
||||||
|
goto err;
|
||||||
|
}
|
||||||
|
|
||||||
if (bch2_dev_is_online(ca) &&
|
if (bch2_dev_is_online(ca) &&
|
||||||
get_capacity(ca->disk_sb.bdev->bd_disk) <
|
get_capacity(ca->disk_sb.bdev->bd_disk) <
|
||||||
ca->mi.bucket_size * nbuckets) {
|
ca->mi.bucket_size * nbuckets) {
|
||||||
|
|
Loading…
Reference in a new issue