* [RFC PATCH] dm: Check for device sector overflow if CONFIG_LBDAF is not set
@ 2018-11-04 13:42 Milan Broz
2018-11-05 18:35 ` Mikulas Patocka
0 siblings, 1 reply; 6+ messages in thread
From: Milan Broz @ 2018-11-04 13:42 UTC (permalink / raw)
To: dm-devel; +Cc: mpatocka, Milan Broz, snitzer
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 performad on wrong offset and 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
In this patch I tried to add check for this problem to dm-linear and dm-crypt,
but I am sure there are more places and I am not sure this is the proper way.
Should we use uint64_t in DM internally for device offset instead?
There are probably some internal calculations in dm-table.c that
can overflow as well.
NOTE: it is a RFC patch that is incomplete (more targets need fixes).
Signed-off-by: Milan Broz <gmazyland@gmail.com>
---
drivers/md/dm-crypt.c | 4 ++++
drivers/md/dm-linear.c | 4 ++++
2 files changed, 8 insertions(+)
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 49be7a6a2e81..008fc40ef84b 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -2786,6 +2786,10 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
cc->start = tmpll;
+ if (sizeof(cc->start) < sizeof(tmpll) && cc->start != tmpll) {
+ ti->error = "Device sector overflow";
+ goto bad;
+ }
if (crypt_integrity_aead(cc) || cc->integrity_iv_size) {
ret = crypt_integrity_ctr(cc, ti);
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 8d7ddee6ac4d..b5a0065d1436 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -50,6 +50,10 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
goto bad;
}
lc->start = tmp;
+ if (sizeof(lc->start) < sizeof(tmp) && lc->start != tmp) {
+ ti->error = "Device sector overflow";
+ goto bad;
+ }
ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev);
if (ret) {
--
2.19.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] dm: Check for device sector overflow if CONFIG_LBDAF is not set
2018-11-04 13:42 [RFC PATCH] dm: Check for device sector overflow if CONFIG_LBDAF is not set Milan Broz
@ 2018-11-05 18:35 ` Mikulas Patocka
2018-11-05 18:59 ` Milan Broz
0 siblings, 1 reply; 6+ messages in thread
From: Mikulas Patocka @ 2018-11-05 18:35 UTC (permalink / raw)
To: Milan Broz; +Cc: dm-devel, snitzer
On Sun, 4 Nov 2018, Milan Broz wrote:
> 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 performad on wrong offset and 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
>
> In this patch I tried to add check for this problem to dm-linear and dm-crypt,
> but I am sure there are more places and I am not sure this is the proper way.
>
> Should we use uint64_t in DM internally for device offset instead?
>
> There are probably some internal calculations in dm-table.c that
> can overflow as well.
>
> NOTE: it is a RFC patch that is incomplete (more targets need fixes).
OK.
But the condition "sizeof(cc->start) < sizeof(tmpll)" could be dropped,
the compiler will optimize out "cc->start != tmpll" if the types have the
same width.
Mikulas
> Signed-off-by: Milan Broz <gmazyland@gmail.com>
> ---
> drivers/md/dm-crypt.c | 4 ++++
> drivers/md/dm-linear.c | 4 ++++
> 2 files changed, 8 insertions(+)
>
> diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> index 49be7a6a2e81..008fc40ef84b 100644
> --- a/drivers/md/dm-crypt.c
> +++ b/drivers/md/dm-crypt.c
> @@ -2786,6 +2786,10 @@ static int crypt_ctr(struct dm_target *ti, unsigned int argc, char **argv)
> goto bad;
> }
> cc->start = tmpll;
> + if (sizeof(cc->start) < sizeof(tmpll) && cc->start != tmpll) {
> + ti->error = "Device sector overflow";
> + goto bad;
> + }
>
> if (crypt_integrity_aead(cc) || cc->integrity_iv_size) {
> ret = crypt_integrity_ctr(cc, ti);
> diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
> index 8d7ddee6ac4d..b5a0065d1436 100644
> --- a/drivers/md/dm-linear.c
> +++ b/drivers/md/dm-linear.c
> @@ -50,6 +50,10 @@ static int linear_ctr(struct dm_target *ti, unsigned int argc, char **argv)
> goto bad;
> }
> lc->start = tmp;
> + if (sizeof(lc->start) < sizeof(tmp) && lc->start != tmp) {
> + ti->error = "Device sector overflow";
> + goto bad;
> + }
>
> ret = dm_get_device(ti, argv[0], dm_table_get_mode(ti->table), &lc->dev);
> if (ret) {
> --
> 2.19.1
>
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] dm: Check for device sector overflow if CONFIG_LBDAF is not set
2018-11-05 18:35 ` Mikulas Patocka
@ 2018-11-05 18:59 ` Milan Broz
2018-11-06 21:44 ` Mikulas Patocka
0 siblings, 1 reply; 6+ messages in thread
From: Milan Broz @ 2018-11-05 18:59 UTC (permalink / raw)
To: Mikulas Patocka, Milan Broz; +Cc: dm-devel, snitzer
On 05/11/2018 19:35, Mikulas Patocka wrote:
> But the condition "sizeof(cc->start) < sizeof(tmpll)" could be dropped,
> the compiler will optimize out "cc->start != tmpll" if the types have the
> same width.
Yes, the intention here is that in 64bit env. the whole if condition
is not compiled in. If it happens without "sizeof(cc->start) < sizeof(tmpll)",
then we can drop it.
So, does it make sense to add this to all dm targets? Or any better idea?
Milan
^ permalink raw reply [flat|nested] 6+ messages in thread
* Re: [RFC PATCH] dm: Check for device sector overflow if CONFIG_LBDAF is not set
2018-11-05 18:59 ` Milan Broz
@ 2018-11-06 21:44 ` Mikulas Patocka
2018-11-07 21:24 ` [PATCH v2] " Milan Broz
0 siblings, 1 reply; 6+ messages in thread
From: Mikulas Patocka @ 2018-11-06 21:44 UTC (permalink / raw)
To: Milan Broz; +Cc: dm-devel, snitzer
On Mon, 5 Nov 2018, Milan Broz wrote:
> On 05/11/2018 19:35, Mikulas Patocka wrote:
> > But the condition "sizeof(cc->start) < sizeof(tmpll)" could be dropped,
> > the compiler will optimize out "cc->start != tmpll" if the types have the
> > same width.
>
> Yes, the intention here is that in 64bit env. the whole if condition
> is not compiled in. If it happens without "sizeof(cc->start) < sizeof(tmpll)",
> then we can drop it.
>
> So, does it make sense to add this to all dm targets? Or any better idea?
>
> Milan
In the targets that I have written, I tried to protect against this:
if (sscanf(argv[1], "%llu%c", &start, &dummy) != 1 || start != (sector_t)start)
ic->provided_data_sectors = le64_to_cpu(ic->sb->provided_data_sectors)
if (ic->provided_data_sectors != le64_to_cpu(ic->sb->provided_data_sectors)) {
wc->start_sector = start_sector;
if (wc->start_sector != start_sector
If you find some more unprotected cases, it's OK to convert them.
Mikulas
^ permalink raw reply [flat|nested] 6+ messages in thread
* [PATCH v2] dm: Check for device sector overflow if CONFIG_LBDAF is not set
2018-11-06 21:44 ` Mikulas Patocka
@ 2018-11-07 21:24 ` Milan Broz
2018-11-15 13:20 ` Mikulas Patocka
0 siblings, 1 reply; 6+ messages in thread
From: Milan Broz @ 2018-11-07 21:24 UTC (permalink / raw)
To: dm-devel; +Cc: mpatocka, Milan Broz, snitzer
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>
---
drivers/md/dm-crypt.c | 2 +-
drivers/md/dm-delay.c | 2 +-
drivers/md/dm-flakey.c | 2 +-
drivers/md/dm-linear.c | 2 +-
drivers/md/dm-raid1.c | 3 ++-
drivers/md/dm-unstripe.c | 2 +-
6 files changed, 7 insertions(+), 6 deletions(-)
diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
index 49be7a6a2e81..a41fe7975dc6 100644
--- a/drivers/md/dm-crypt.c
+++ b/drivers/md/dm-crypt.c
@@ -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;
}
diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
index 2fb7bb4304ad..fddffe251bf6 100644
--- a/drivers/md/dm-delay.c
+++ b/drivers/md/dm-delay.c
@@ -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;
}
diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
index 3cb97fa4c11d..8261aa8c7fe1 100644
--- a/drivers/md/dm-flakey.c
+++ b/drivers/md/dm-flakey.c
@@ -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;
}
diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
index 8d7ddee6ac4d..ad980a38fb1e 100644
--- a/drivers/md/dm-linear.c
+++ b/drivers/md/dm-linear.c
@@ -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;
}
diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
index 79eab1071ec2..5a51151f680d 100644
--- a/drivers/md/dm-raid1.c
+++ b/drivers/md/dm-raid1.c
@@ -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;
}
diff --git a/drivers/md/dm-unstripe.c b/drivers/md/dm-unstripe.c
index 954b7ab4e684..e673dacf6418 100644
--- a/drivers/md/dm-unstripe.c
+++ b/drivers/md/dm-unstripe.c
@@ -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;
}
--
2.19.1
^ permalink raw reply related [flat|nested] 6+ messages in thread
* Re: [PATCH v2] dm: Check for device sector overflow if CONFIG_LBDAF is not set
2018-11-07 21:24 ` [PATCH v2] " Milan Broz
@ 2018-11-15 13:20 ` Mikulas Patocka
0 siblings, 0 replies; 6+ messages in thread
From: Mikulas Patocka @ 2018-11-15 13:20 UTC (permalink / raw)
To: Milan Broz; +Cc: dm-devel, snitzer
On Wed, 7 Nov 2018, Milan Broz wrote:
> 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>
> ---
> drivers/md/dm-crypt.c | 2 +-
> drivers/md/dm-delay.c | 2 +-
> drivers/md/dm-flakey.c | 2 +-
> drivers/md/dm-linear.c | 2 +-
> drivers/md/dm-raid1.c | 3 ++-
> drivers/md/dm-unstripe.c | 2 +-
> 6 files changed, 7 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/md/dm-crypt.c b/drivers/md/dm-crypt.c
> index 49be7a6a2e81..a41fe7975dc6 100644
> --- a/drivers/md/dm-crypt.c
> +++ b/drivers/md/dm-crypt.c
> @@ -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;
> }
> diff --git a/drivers/md/dm-delay.c b/drivers/md/dm-delay.c
> index 2fb7bb4304ad..fddffe251bf6 100644
> --- a/drivers/md/dm-delay.c
> +++ b/drivers/md/dm-delay.c
> @@ -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;
> }
> diff --git a/drivers/md/dm-flakey.c b/drivers/md/dm-flakey.c
> index 3cb97fa4c11d..8261aa8c7fe1 100644
> --- a/drivers/md/dm-flakey.c
> +++ b/drivers/md/dm-flakey.c
> @@ -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;
> }
> diff --git a/drivers/md/dm-linear.c b/drivers/md/dm-linear.c
> index 8d7ddee6ac4d..ad980a38fb1e 100644
> --- a/drivers/md/dm-linear.c
> +++ b/drivers/md/dm-linear.c
> @@ -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;
> }
> diff --git a/drivers/md/dm-raid1.c b/drivers/md/dm-raid1.c
> index 79eab1071ec2..5a51151f680d 100644
> --- a/drivers/md/dm-raid1.c
> +++ b/drivers/md/dm-raid1.c
> @@ -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;
> }
> diff --git a/drivers/md/dm-unstripe.c b/drivers/md/dm-unstripe.c
> index 954b7ab4e684..e673dacf6418 100644
> --- a/drivers/md/dm-unstripe.c
> +++ b/drivers/md/dm-unstripe.c
> @@ -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;
> }
> --
> 2.19.1
>
^ permalink raw reply [flat|nested] 6+ messages in thread
end of thread, other threads:[~2018-11-15 13:20 UTC | newest]
Thread overview: 6+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2018-11-04 13:42 [RFC PATCH] dm: Check for device sector overflow if CONFIG_LBDAF is not set Milan Broz
2018-11-05 18:35 ` Mikulas Patocka
2018-11-05 18:59 ` Milan Broz
2018-11-06 21:44 ` Mikulas Patocka
2018-11-07 21:24 ` [PATCH v2] " Milan Broz
2018-11-15 13:20 ` Mikulas Patocka
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.