Skip to content

Commit

Permalink
dm clone: Add overflow check for number of regions
Browse files Browse the repository at this point in the history
Add overflow check for clone->nr_regions variable, which holds the
number of regions of the target.

The overflow can occur with sufficiently large devices, if BITS_PER_LONG
== 32. E.g., if the region size is 8 sectors (4K), the overflow would
occur for device sizes > 34359738360 sectors (~16TB).

This could result in multiple device sectors wrongly mapping to the same
region number, due to the truncation from 64 bits to 32 bits, which
would lead to data corruption.

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
Nikos Tsironis authored and Mike Snitzer committed Mar 27, 2020
1 parent 4b51429 commit cd481c1
Showing 1 changed file with 11 additions and 1 deletion.
12 changes: 11 additions & 1 deletion drivers/md/dm-clone-target.c
Original file line number Diff line number Diff line change
Expand Up @@ -1790,6 +1790,7 @@ static int copy_ctr_args(struct clone *clone, int argc, const char **argv, char
static int clone_ctr(struct dm_target *ti, unsigned int argc, char **argv)
{
int r;
sector_t nr_regions;
struct clone *clone;
struct dm_arg_set as;

Expand Down Expand Up @@ -1831,7 +1832,16 @@ static int clone_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto out_with_source_dev;

clone->region_shift = __ffs(clone->region_size);
clone->nr_regions = dm_sector_div_up(ti->len, clone->region_size);
nr_regions = dm_sector_div_up(ti->len, clone->region_size);

/* Check for overflow */
if (nr_regions != (unsigned long)nr_regions) {
ti->error = "Too many regions. Consider increasing the region size";
r = -EOVERFLOW;
goto out_with_source_dev;
}

clone->nr_regions = nr_regions;

r = validate_nr_regions(clone->nr_regions, &ti->error);
if (r)
Expand Down

0 comments on commit cd481c1

Please sign in to comment.