dm: Check for device sector overflow if CONFIG_LBDAF is not set
authorMilan Broz <gmazyland@gmail.com>
Wed, 7 Nov 2018 21:24:55 +0000 (22:24 +0100)
committerMike Snitzer <snitzer@redhat.com>
Tue, 18 Dec 2018 14:02:26 +0000 (09:02 -0500)
Reference to a device in device-mapper table contains offset in sectors.

If the sector_t is 32bit integer (CONFIG_LBDAF is not set), then
several device-mapper targets can overflow this offset and validity
check is then performed on a wrong offset and a wrong table is activated.

See for example (on 32bit without CONFIG_LBDAF) this overflow:

  # dmsetup create test --table "0 2048 linear /dev/sdg 4294967297"
  # dmsetup table test
  0 2048 linear 8:96 1

This patch adds explicit check for overflow if the offset is sector_t type.

Signed-off-by: Milan Broz <gmazyland@gmail.com>
Reviewed-by: Mikulas Patocka <mpatocka@redhat.com>
Signed-off-by: Mike Snitzer <snitzer@redhat.com>
drivers/md/dm-crypt.c
drivers/md/dm-delay.c
drivers/md/dm-flakey.c
drivers/md/dm-linear.c
drivers/md/dm-raid1.c
drivers/md/dm-unstripe.c

index 9a4dec0a0f711517068e1fed7279e4cef29c6210..fc7d8b8a654fc4a97cba998071072e4d2964224a 100644 (file)
@@ -2781,7 +2781,7 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        ret = -EINVAL;
-       if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1) {
+       if (sscanf(argv[4], "%llu%c", &tmpll, &dummy) != 1 || tmpll != (sector_t)tmpll) {
                ti->error = "Invalid device sector";
                goto bad;
        }
index 2fb7bb4304ad7f0ade6eb10ccd02d07f36271acf..fddffe251bf6bf5c2ded195c31e392bc228568d8 100644 (file)
@@ -141,7 +141,7 @@ static int delay_class_ctr(struct dm_target *ti, struct delay_class *c, char **a
        unsigned long long tmpll;
        char dummy;
 
-       if (sscanf(argv[1], "%llu%c", &tmpll, &dummy) != 1) {
+       if (sscanf(argv[1], "%llu%c", &tmpll, &dummy) != 1 || tmpll != (sector_t)tmpll) {
                ti->error = "Invalid device sector";
                return -EINVAL;
        }
index 3cb97fa4c11da49ebbff1b609d87490e66504947..8261aa8c7fe1135f1ed7054b962a87e788dad144 100644 (file)
@@ -213,7 +213,7 @@ static int flakey_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        devname = dm_shift_arg(&as);
 
        r = -EINVAL;
-       if (sscanf(dm_shift_arg(&as), "%llu%c", &tmpll, &dummy) != 1) {
+       if (sscanf(dm_shift_arg(&as), "%llu%c", &tmpll, &dummy) != 1 || tmpll != (sector_t)tmpll) {
                ti->error = "Invalid device sector";
                goto bad;
        }
index 8d7ddee6ac4d3aa271ddceb620ae5bbd4f3a09ca..ad980a38fb1e84be717a3032586153c08b9b251a 100644 (file)
@@ -45,7 +45,7 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
        }
 
        ret = -EINVAL;
-       if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1) {
+       if (sscanf(argv[1], "%llu%c", &tmp, &dummy) != 1 || tmp != (sector_t)tmp) {
                ti->error = "Invalid device sector";
                goto bad;
        }
index 79eab1071ec22ba73458cc99c5841de30f2105b0..5a51151f680d6b0d552a80f549dfce0ede0d6b24 100644 (file)
@@ -943,7 +943,8 @@ static int get_mirror(struct mirror_set *ms, struct dm_target *ti,
        char dummy;
        int ret;
 
-       if (sscanf(argv[1], "%llu%c", &offset, &dummy) != 1) {
+       if (sscanf(argv[1], "%llu%c", &offset, &dummy) != 1 ||
+           offset != (sector_t)offset) {
                ti->error = "Invalid offset";
                return -EINVAL;
        }
index 954b7ab4e684d3fdec832abc557373a8ca19e756..e673dacf6418191854689e4a4337f40927b89e5a 100644 (file)
@@ -78,7 +78,7 @@ static int unstripe_ctr(struct dm_target *ti, unsigned int argc, char **argv)
                goto err;
        }
 
-       if (sscanf(argv[4], "%llu%c", &start, &dummy) != 1) {
+       if (sscanf(argv[4], "%llu%c", &start, &dummy) != 1 || start != (sector_t)start) {
                ti->error = "Invalid striped device offset";
                goto err;
        }