Skip to content

Commit

Permalink
dm clone: Add missing casts to prevent overflows and data corruption
Browse files Browse the repository at this point in the history
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: 7431b78 ("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>
  • Loading branch information
ntsiron authored and snitm committed Mar 27, 2020
1 parent cd481c1 commit 9fc06ff
Showing 1 changed file with 6 additions and 3 deletions.
9 changes: 6 additions & 3 deletions drivers/md/dm-clone-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -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 */
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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) {
/*
Expand Down

0 comments on commit 9fc06ff

Please sign in to comment.