aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-table.c
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2012-03-28 13:41:26 -0400
committerAlasdair G Kergon <agk@redhat.com>2012-03-28 13:41:26 -0400
commit31998ef19385c944600d9a981b96252f98204bee (patch)
treeab757b8d6e3d349cf42827354e594687dcf6c5c8 /drivers/md/dm-table.c
parent0447568fc51e0268e201f7086d2450cf986e0411 (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-table.c')
-rw-r--r--drivers/md/dm-table.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/md/dm-table.c b/drivers/md/dm-table.c
index a3d1e18317f4..2e227fbf1622 100644
--- a/drivers/md/dm-table.c
+++ b/drivers/md/dm-table.c
@@ -463,10 +463,11 @@ int dm_get_device(struct dm_target *ti, const char *path, fmode_t mode,
463 struct dm_dev_internal *dd; 463 struct dm_dev_internal *dd;
464 unsigned int major, minor; 464 unsigned int major, minor;
465 struct dm_table *t = ti->table; 465 struct dm_table *t = ti->table;
466 char dummy;
466 467
467 BUG_ON(!t); 468 BUG_ON(!t);
468 469
469 if (sscanf(path, "%u:%u", &major, &minor) == 2) { 470 if (sscanf(path, "%u:%u%c", &major, &minor, &dummy) == 2) {
470 /* Extract the major/minor numbers */ 471 /* Extract the major/minor numbers */
471 dev = MKDEV(major, minor); 472 dev = MKDEV(major, minor);
472 if (MAJOR(dev) != major || MINOR(dev) != minor) 473 if (MAJOR(dev) != major || MINOR(dev) != minor)
@@ -841,9 +842,10 @@ static int validate_next_arg(struct dm_arg *arg, struct dm_arg_set *arg_set,
841 unsigned *value, char **error, unsigned grouped) 842 unsigned *value, char **error, unsigned grouped)
842{ 843{
843 const char *arg_str = dm_shift_arg(arg_set); 844 const char *arg_str = dm_shift_arg(arg_set);
845 char dummy;
844 846
845 if (!arg_str || 847 if (!arg_str ||
846 (sscanf(arg_str, "%u", value) != 1) || 848 (sscanf(arg_str, "%u%c", value, &dummy) != 1) ||
847 (*value < arg->min) || 849 (*value < arg->min) ||
848 (*value > arg->max) || 850 (*value > arg->max) ||
849 (grouped && arg_set->argc < *value)) { 851 (grouped && arg_set->argc < *value)) {