diff options
author | Mikulas Patocka <mpatocka@redhat.com> | 2012-03-28 13:41:26 -0400 |
---|---|---|
committer | Alasdair G Kergon <agk@redhat.com> | 2012-03-28 13:41:26 -0400 |
commit | 31998ef19385c944600d9a981b96252f98204bee (patch) | |
tree | ab757b8d6e3d349cf42827354e594687dcf6c5c8 /drivers/md/dm-log.c | |
parent | 0447568fc51e0268e201f7086d2450cf986e0411 (diff) |
dm: reject trailing characters in sccanf input
Device mapper uses sscanf to convert arguments to numbers. The problem is that
the way we use it ignores additional unmatched characters in the scanned string.
For example, this `if (sscanf(string, "%d", &number) == 1)' will match a number,
but also it will match number with some garbage appended, like "123abc".
As a result, device mapper accepts garbage after some numbers. For example
the command `dmsetup create vg1-new --table "0 16384 linear 254:1bla 34816bla"'
will pass without an error.
This patch fixes all sscanf uses in device mapper. It appends "%c" with
a pointer to a dummy character variable to every sscanf statement.
The construct `if (sscanf(string, "%d%c", &number, &dummy) == 1)' succeeds
only if string is a null-terminated number (optionally preceded by some
whitespace characters). If there is some character appended after the number,
sscanf matches "%c", writes the character to the dummy variable and returns 2.
We check the return value for 1 and consequently reject numbers with some
garbage appended.
Signed-off-by: Mikulas Patocka <mpatocka@redhat.com>
Acked-by: Mike Snitzer <snitzer@redhat.com>
Signed-off-by: Alasdair G Kergon <agk@redhat.com>
Diffstat (limited to 'drivers/md/dm-log.c')
-rw-r--r-- | drivers/md/dm-log.c | 3 |
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/md/dm-log.c b/drivers/md/dm-log.c index 3b52bb72bd1f..65ebaebf502b 100644 --- a/drivers/md/dm-log.c +++ b/drivers/md/dm-log.c | |||
@@ -369,6 +369,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
369 | unsigned int region_count; | 369 | unsigned int region_count; |
370 | size_t bitset_size, buf_size; | 370 | size_t bitset_size, buf_size; |
371 | int r; | 371 | int r; |
372 | char dummy; | ||
372 | 373 | ||
373 | if (argc < 1 || argc > 2) { | 374 | if (argc < 1 || argc > 2) { |
374 | DMWARN("wrong number of arguments to dirty region log"); | 375 | DMWARN("wrong number of arguments to dirty region log"); |
@@ -387,7 +388,7 @@ static int create_log_context(struct dm_dirty_log *log, struct dm_target *ti, | |||
387 | } | 388 | } |
388 | } | 389 | } |
389 | 390 | ||
390 | if (sscanf(argv[0], "%u", ®ion_size) != 1 || | 391 | if (sscanf(argv[0], "%u%c", ®ion_size, &dummy) != 1 || |
391 | !_check_region_size(ti, region_size)) { | 392 | !_check_region_size(ti, region_size)) { |
392 | DMWARN("invalid region size %s", argv[0]); | 393 | DMWARN("invalid region size %s", argv[0]); |
393 | return -EINVAL; | 394 | return -EINVAL; |