Message ID | 20201007182531.2201548-1-dxu@dxuuu.xyz (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
Series | btrfs: Fix divide by zero | expand |
On 2020/10/8 上午2:25, Daniel Xu wrote: > If there's no parity and num_stripes < ncopies, an btrfs image can > trigger a divide by zero in calc_stripe_length(). > > Here's a zstd compressed image to reproduce the error: > https://www.dropbox.com/s/p11kayzhuia80xr/ubsan-divide-by-0.zst?dl=0 It would be better to submit the image to bugs.kernel.org and add it as Link: tag. > > The image was generated through fuzzing. > > Signed-off-by: Daniel Xu <dxu@dxuuu.xyz> Despite that, the patch looks good enough. After fixing the link and tag, feel free to add my reviewed by tag: Reviewed-by: Qu Wenruo <wqu@suse.com> Thanks, Qu > --- > fs/btrfs/tree-checker.c | 18 ++++++++++++++++++ > 1 file changed, 18 insertions(+) > > diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c > index 7b1fee630f97..e03c3807921f 100644 > --- a/fs/btrfs/tree-checker.c > +++ b/fs/btrfs/tree-checker.c > @@ -760,18 +760,36 @@ int btrfs_check_chunk_valid(struct extent_buffer *leaf, > u64 type; > u64 features; > bool mixed = false; > + int raid_index; > + int nparity; > + int ncopies; > > length = btrfs_chunk_length(leaf, chunk); > stripe_len = btrfs_chunk_stripe_len(leaf, chunk); > num_stripes = btrfs_chunk_num_stripes(leaf, chunk); > sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); > type = btrfs_chunk_type(leaf, chunk); > + raid_index = btrfs_bg_flags_to_raid_index(type); > + ncopies = btrfs_raid_array[raid_index].ncopies; > + nparity = btrfs_raid_array[raid_index].nparity; > > if (!num_stripes) { > chunk_err(leaf, chunk, logical, > "invalid chunk num_stripes, have %u", num_stripes); > return -EUCLEAN; > } > + if (num_stripes < ncopies) { > + chunk_err(leaf, chunk, logical, > + "invalid chunk num_stripes < ncopies, have %u < %d", > + num_stripes, ncopies); > + return -EUCLEAN; > + } > + if (nparity && num_stripes == nparity) { > + chunk_err(leaf, chunk, logical, > + "invalid chunk num_stripes == nparity, have %u == %d", > + num_stripes, nparity); > + return -EUCLEAN; > + } > if (!IS_ALIGNED(logical, fs_info->sectorsize)) { > chunk_err(leaf, chunk, logical, > "invalid chunk logical, have %llu should aligned to %u", >
diff --git a/fs/btrfs/tree-checker.c b/fs/btrfs/tree-checker.c index 7b1fee630f97..e03c3807921f 100644 --- a/fs/btrfs/tree-checker.c +++ b/fs/btrfs/tree-checker.c @@ -760,18 +760,36 @@ int btrfs_check_chunk_valid(struct extent_buffer *leaf, u64 type; u64 features; bool mixed = false; + int raid_index; + int nparity; + int ncopies; length = btrfs_chunk_length(leaf, chunk); stripe_len = btrfs_chunk_stripe_len(leaf, chunk); num_stripes = btrfs_chunk_num_stripes(leaf, chunk); sub_stripes = btrfs_chunk_sub_stripes(leaf, chunk); type = btrfs_chunk_type(leaf, chunk); + raid_index = btrfs_bg_flags_to_raid_index(type); + ncopies = btrfs_raid_array[raid_index].ncopies; + nparity = btrfs_raid_array[raid_index].nparity; if (!num_stripes) { chunk_err(leaf, chunk, logical, "invalid chunk num_stripes, have %u", num_stripes); return -EUCLEAN; } + if (num_stripes < ncopies) { + chunk_err(leaf, chunk, logical, + "invalid chunk num_stripes < ncopies, have %u < %d", + num_stripes, ncopies); + return -EUCLEAN; + } + if (nparity && num_stripes == nparity) { + chunk_err(leaf, chunk, logical, + "invalid chunk num_stripes == nparity, have %u == %d", + num_stripes, nparity); + return -EUCLEAN; + } if (!IS_ALIGNED(logical, fs_info->sectorsize)) { chunk_err(leaf, chunk, logical, "invalid chunk logical, have %llu should aligned to %u",
If there's no parity and num_stripes < ncopies, an btrfs image can trigger a divide by zero in calc_stripe_length(). Here's a zstd compressed image to reproduce the error: https://www.dropbox.com/s/p11kayzhuia80xr/ubsan-divide-by-0.zst?dl=0 The image was generated through fuzzing. Signed-off-by: Daniel Xu <dxu@dxuuu.xyz> --- fs/btrfs/tree-checker.c | 18 ++++++++++++++++++ 1 file changed, 18 insertions(+)