diff options
author | Heinz Mauelshagen <heinzm@redhat.com> | 2018-03-28 11:07:14 -0400 |
---|---|---|
committer | Mike Snitzer <snitzer@redhat.com> | 2018-04-04 12:12:37 -0400 |
commit | 13bc62d4a6c79b95ec299591df1bae0a505f2d07 (patch) | |
tree | 0c4bd4c5f41d979435d04268de3e779c31967d75 | |
parent | d4b1aaf53c02e6440c49aeae06ba3a3a8ce9882a (diff) |
dm raid: fix parse_raid_params() variable range issue
parse_raid_params() compares variable "int value" with INT_MAX.
E.g. related Coverity report excerpt:
CID 1364818 (#2 of 3): Operands don't affect result (CONSTANT_EXPRESSION_RESULT) [select issue]
1433 if (value > INT_MAX) {
Fix by changing checks to avoid INT_MAX.
Whilst on it, avoid unnecessary checks against constants
and add check for sane recovery speed min/max.
Signed-off-by: Heinz Mauelshagen <heinzm@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
-rw-r--r-- | drivers/md/dm-raid.c | 27 |
1 files changed, 19 insertions, 8 deletions
diff --git a/drivers/md/dm-raid.c b/drivers/md/dm-raid.c index 598c9e3e41a5..6f823f44b4aa 100644 --- a/drivers/md/dm-raid.c +++ b/drivers/md/dm-raid.c | |||
@@ -1370,19 +1370,18 @@ static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as, | |||
1370 | * In device-mapper, we specify things in sectors, but | 1370 | * In device-mapper, we specify things in sectors, but |
1371 | * MD records this value in kB | 1371 | * MD records this value in kB |
1372 | */ | 1372 | */ |
1373 | value /= 2; | 1373 | if (value < 0 || value / 2 > COUNTER_MAX) { |
1374 | if (value > COUNTER_MAX) { | ||
1375 | rs->ti->error = "Max write-behind limit out of range"; | 1374 | rs->ti->error = "Max write-behind limit out of range"; |
1376 | return -EINVAL; | 1375 | return -EINVAL; |
1377 | } | 1376 | } |
1378 | 1377 | ||
1379 | rs->md.bitmap_info.max_write_behind = value; | 1378 | rs->md.bitmap_info.max_write_behind = value / 2; |
1380 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_DAEMON_SLEEP))) { | 1379 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_DAEMON_SLEEP))) { |
1381 | if (test_and_set_bit(__CTR_FLAG_DAEMON_SLEEP, &rs->ctr_flags)) { | 1380 | if (test_and_set_bit(__CTR_FLAG_DAEMON_SLEEP, &rs->ctr_flags)) { |
1382 | rs->ti->error = "Only one daemon_sleep argument pair allowed"; | 1381 | rs->ti->error = "Only one daemon_sleep argument pair allowed"; |
1383 | return -EINVAL; | 1382 | return -EINVAL; |
1384 | } | 1383 | } |
1385 | if (!value || (value > MAX_SCHEDULE_TIMEOUT)) { | 1384 | if (value < 0) { |
1386 | rs->ti->error = "daemon sleep period out of range"; | 1385 | rs->ti->error = "daemon sleep period out of range"; |
1387 | return -EINVAL; | 1386 | return -EINVAL; |
1388 | } | 1387 | } |
@@ -1424,27 +1423,33 @@ static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as, | |||
1424 | return -EINVAL; | 1423 | return -EINVAL; |
1425 | } | 1424 | } |
1426 | 1425 | ||
1426 | if (value < 0) { | ||
1427 | rs->ti->error = "Bogus stripe cache entries value"; | ||
1428 | return -EINVAL; | ||
1429 | } | ||
1427 | rs->stripe_cache_entries = value; | 1430 | rs->stripe_cache_entries = value; |
1428 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_MIN_RECOVERY_RATE))) { | 1431 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_MIN_RECOVERY_RATE))) { |
1429 | if (test_and_set_bit(__CTR_FLAG_MIN_RECOVERY_RATE, &rs->ctr_flags)) { | 1432 | if (test_and_set_bit(__CTR_FLAG_MIN_RECOVERY_RATE, &rs->ctr_flags)) { |
1430 | rs->ti->error = "Only one min_recovery_rate argument pair allowed"; | 1433 | rs->ti->error = "Only one min_recovery_rate argument pair allowed"; |
1431 | return -EINVAL; | 1434 | return -EINVAL; |
1432 | } | 1435 | } |
1433 | if (value > INT_MAX) { | 1436 | |
1437 | if (value < 0) { | ||
1434 | rs->ti->error = "min_recovery_rate out of range"; | 1438 | rs->ti->error = "min_recovery_rate out of range"; |
1435 | return -EINVAL; | 1439 | return -EINVAL; |
1436 | } | 1440 | } |
1437 | rs->md.sync_speed_min = (int)value; | 1441 | rs->md.sync_speed_min = value; |
1438 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_MAX_RECOVERY_RATE))) { | 1442 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_MAX_RECOVERY_RATE))) { |
1439 | if (test_and_set_bit(__CTR_FLAG_MAX_RECOVERY_RATE, &rs->ctr_flags)) { | 1443 | if (test_and_set_bit(__CTR_FLAG_MAX_RECOVERY_RATE, &rs->ctr_flags)) { |
1440 | rs->ti->error = "Only one max_recovery_rate argument pair allowed"; | 1444 | rs->ti->error = "Only one max_recovery_rate argument pair allowed"; |
1441 | return -EINVAL; | 1445 | return -EINVAL; |
1442 | } | 1446 | } |
1443 | if (value > INT_MAX) { | 1447 | |
1448 | if (value < 0) { | ||
1444 | rs->ti->error = "max_recovery_rate out of range"; | 1449 | rs->ti->error = "max_recovery_rate out of range"; |
1445 | return -EINVAL; | 1450 | return -EINVAL; |
1446 | } | 1451 | } |
1447 | rs->md.sync_speed_max = (int)value; | 1452 | rs->md.sync_speed_max = value; |
1448 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_REGION_SIZE))) { | 1453 | } else if (!strcasecmp(key, dm_raid_arg_name_by_flag(CTR_FLAG_REGION_SIZE))) { |
1449 | if (test_and_set_bit(__CTR_FLAG_REGION_SIZE, &rs->ctr_flags)) { | 1454 | if (test_and_set_bit(__CTR_FLAG_REGION_SIZE, &rs->ctr_flags)) { |
1450 | rs->ti->error = "Only one region_size argument pair allowed"; | 1455 | rs->ti->error = "Only one region_size argument pair allowed"; |
@@ -1490,6 +1495,12 @@ static int parse_raid_params(struct raid_set *rs, struct dm_arg_set *as, | |||
1490 | return -EINVAL; | 1495 | return -EINVAL; |
1491 | } | 1496 | } |
1492 | 1497 | ||
1498 | if (rs->md.sync_speed_max && | ||
1499 | rs->md.sync_speed_min > rs->md.sync_speed_max) { | ||
1500 | rs->ti->error = "Bogus recovery rates"; | ||
1501 | return -EINVAL; | ||
1502 | } | ||
1503 | |||
1493 | if (validate_region_size(rs, region_size)) | 1504 | if (validate_region_size(rs, region_size)) |
1494 | return -EINVAL; | 1505 | return -EINVAL; |
1495 | 1506 | ||