diff options
author | Nikos Tsironis <ntsironis@arrikto.com> | 2020-03-27 17:01:10 +0300 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2020-03-27 21:42:25 +0300 |
commit | 9fc06ff56845cc5ccafec52f545fc2e08d22f849 (patch) | |
tree | a1d17e2eba1e558cbcccf03d83ed817356a45d82 /drivers/md | |
parent | cd481c12269b4d276f1a52eda0ebd419079bfe3a (diff) | |
download | linux-9fc06ff56845cc5ccafec52f545fc2e08d22f849.tar.xz |
dm clone: Add missing casts to prevent overflows and data corruption
Add missing casts when converting from regions to sectors.
In case BITS_PER_LONG == 32, the lack of the appropriate casts can lead
to overflows and miscalculation of the device sector.
As a result, we could end up discarding and/or copying the wrong parts
of the device, thus corrupting the device's data.
Fixes: 7431b7835f55 ("dm: add clone target")
Cc: stable@vger.kernel.org # v5.4+
Signed-off-by: Nikos Tsironis <ntsironis@arrikto.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
Diffstat (limited to 'drivers/md')
-rw-r--r-- | drivers/md/dm-clone-target.c | 9 |
1 files changed, 6 insertions, 3 deletions
diff --git a/drivers/md/dm-clone-target.c b/drivers/md/dm-clone-target.c index 6ee85fb3388a..ca5020c58f7c 100644 --- a/drivers/md/dm-clone-target.c +++ b/drivers/md/dm-clone-target.c @@ -282,7 +282,7 @@ static bool bio_triggers_commit(struct clone *clone, struct bio *bio) /* Get the address of the region in sectors */ static inline sector_t region_to_sector(struct clone *clone, unsigned long region_nr) { - return (region_nr << clone->region_shift); + return ((sector_t)region_nr << clone->region_shift); } /* Get the region number of the bio */ @@ -471,7 +471,7 @@ static void complete_discard_bio(struct clone *clone, struct bio *bio, bool succ if (test_bit(DM_CLONE_DISCARD_PASSDOWN, &clone->flags) && success) { remap_to_dest(clone, bio); bio_region_range(clone, bio, &rs, &nr_regions); - trim_bio(bio, rs << clone->region_shift, + trim_bio(bio, region_to_sector(clone, rs), nr_regions << clone->region_shift); generic_make_request(bio); } else @@ -804,11 +804,14 @@ static void hydration_copy(struct dm_clone_region_hydration *hd, unsigned int nr struct dm_io_region from, to; struct clone *clone = hd->clone; + if (WARN_ON(!nr_regions)) + return; + region_size = clone->region_size; region_start = hd->region_nr; region_end = region_start + nr_regions - 1; - total_size = (nr_regions - 1) << clone->region_shift; + total_size = region_to_sector(clone, nr_regions - 1); if (region_end == clone->nr_regions - 1) { /* |