aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/md/dm-mpath.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-mpath.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-mpath.c')
-rw-r--r--drivers/md/dm-mpath.c6
1 files changed, 4 insertions, 2 deletions
diff --git a/drivers/md/dm-mpath.c b/drivers/md/dm-mpath.c
index e92a0005eeff..922a3385eead 100644
--- a/drivers/md/dm-mpath.c
+++ b/drivers/md/dm-mpath.c
@@ -1070,8 +1070,9 @@ static int switch_pg_num(struct multipath *m, const char *pgstr)
1070 struct priority_group *pg; 1070 struct priority_group *pg;
1071 unsigned pgnum; 1071 unsigned pgnum;
1072 unsigned long flags; 1072 unsigned long flags;
1073 char dummy;
1073 1074
1074 if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum || 1075 if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
1075 (pgnum > m->nr_priority_groups)) { 1076 (pgnum > m->nr_priority_groups)) {
1076 DMWARN("invalid PG number supplied to switch_pg_num"); 1077 DMWARN("invalid PG number supplied to switch_pg_num");
1077 return -EINVAL; 1078 return -EINVAL;
@@ -1101,8 +1102,9 @@ static int bypass_pg_num(struct multipath *m, const char *pgstr, int bypassed)
1101{ 1102{
1102 struct priority_group *pg; 1103 struct priority_group *pg;
1103 unsigned pgnum; 1104 unsigned pgnum;
1105 char dummy;
1104 1106
1105 if (!pgstr || (sscanf(pgstr, "%u", &pgnum) != 1) || !pgnum || 1107 if (!pgstr || (sscanf(pgstr, "%u%c", &pgnum, &dummy) != 1) || !pgnum ||
1106 (pgnum > m->nr_priority_groups)) { 1108 (pgnum > m->nr_priority_groups)) {
1107 DMWARN("invalid PG number supplied to bypass_pg"); 1109 DMWARN("invalid PG number supplied to bypass_pg");
1108 return -EINVAL; 1110 return -EINVAL;