Skip to content

Commit db42549

Browse files
author
Kent Overstreet
committed
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>
1 parent 18b4abc commit db42549

4 files changed

Lines changed: 17 additions & 3 deletions

File tree

fs/bcachefs/bcachefs_format.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -591,6 +591,12 @@ struct bch_member {
591591
__le64 btree_allocated_bitmap;
592592
};
593593

594+
/*
595+
* This limit comes from the bucket_gens array - it's a single allocation, and
596+
* kernel allocation are limited to INT_MAX
597+
*/
598+
#define BCH_MEMBER_NBUCKETS_MAX (INT_MAX - 64)
599+
594600
#define BCH_MEMBER_V1_BYTES 56
595601

596602
LE64_BITMASK(BCH_MEMBER_STATE, struct bch_member, flags, 0, 4)

fs/bcachefs/errcode.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -175,6 +175,7 @@
175175
x(EINVAL, block_size_too_small) \
176176
x(EINVAL, bucket_size_too_small) \
177177
x(EINVAL, device_size_too_small) \
178+
x(EINVAL, device_size_too_big) \
178179
x(EINVAL, device_not_a_member_of_filesystem) \
179180
x(EINVAL, device_has_been_removed) \
180181
x(EINVAL, device_splitbrain) \

fs/bcachefs/sb-members.c

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -124,9 +124,9 @@ static int validate_member(struct printbuf *err,
124124
struct bch_sb *sb,
125125
int i)
126126
{
127-
if (le64_to_cpu(m.nbuckets) > LONG_MAX) {
128-
prt_printf(err, "device %u: too many buckets (got %llu, max %lu)",
129-
i, le64_to_cpu(m.nbuckets), LONG_MAX);
127+
if (le64_to_cpu(m.nbuckets) > BCH_MEMBER_NBUCKETS_MAX) {
128+
prt_printf(err, "device %u: too many buckets (got %llu, max %u)",
129+
i, le64_to_cpu(m.nbuckets), BCH_MEMBER_NBUCKETS_MAX);
130130
return -BCH_ERR_invalid_sb_members;
131131
}
132132

fs/bcachefs/super.c

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1959,6 +1959,13 @@ int bch2_dev_resize(struct bch_fs *c, struct bch_dev *ca, u64 nbuckets)
19591959
goto err;
19601960
}
19611961

1962+
if (nbuckets > BCH_MEMBER_NBUCKETS_MAX) {
1963+
bch_err(ca, "New device size too big (%llu greater than max %u)",
1964+
nbuckets, BCH_MEMBER_NBUCKETS_MAX);
1965+
ret = -BCH_ERR_device_size_too_big;
1966+
goto err;
1967+
}
1968+
19621969
if (bch2_dev_is_online(ca) &&
19631970
get_capacity(ca->disk_sb.bdev->bd_disk) <
19641971
ca->mi.bucket_size * nbuckets) {

0 commit comments

Comments
 (0)