summaryrefslogtreecommitdiff
path: root/drivers/md
diff options
context:
space:
mode:
authorDemi Marie Obenour <demi@invisiblethingslab.com>2023-06-03 17:52:40 +0300
committerMike Snitzer <snitzer@kernel.org>2023-06-23 17:31:51 +0300
commit13f4a697f8b4feb705569f9336127e9e2f9ac596 (patch)
treeb06d5d26f3bafba66b50edbc6cd5cf99aa145dd7 /drivers/md
parentb60528d9e68113e2c297c3a45102332cb1d3e608 (diff)
downloadlinux-13f4a697f8b4feb705569f9336127e9e2f9ac596.tar.xz
dm ioctl: Avoid pointer arithmetic overflow
Especially on 32-bit systems, it is possible for the pointer arithmetic to overflow and cause a userspace pointer to be dereferenced in the kernel. Signed-off-by: Demi Marie Obenour <demi@invisiblethingslab.com> Reviewed-by: Mikulas Patocka <mpatocka@redhat.com> Signed-off-by: Mike Snitzer <snitzer@kernel.org>
Diffstat (limited to 'drivers/md')
-rw-r--r--drivers/md/dm-ioctl.c16
1 files changed, 16 insertions, 0 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 3a6989b7817d..e322fd490634 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1397,6 +1397,22 @@ static int next_target(struct dm_target_spec *last, uint32_t next, void *end,
static_assert(__alignof__(struct dm_target_spec) <= 8,
"struct dm_target_spec must not require more than 8-byte alignment");
+ /*
+ * Number of bytes remaining, starting with last. This is always
+ * sizeof(struct dm_target_spec) or more, as otherwise *last was
+ * out of bounds already.
+ */
+ size_t remaining = (char *)end - (char *)last;
+
+ /*
+ * There must be room for both the next target spec and the
+ * NUL-terminator of the target itself.
+ */
+ if (remaining - sizeof(struct dm_target_spec) <= next) {
+ DMERR("Target spec extends beyond end of parameters");
+ return -EINVAL;
+ }
+
if (next % __alignof__(struct dm_target_spec)) {
DMERR("Next dm_target_spec (offset %u) is not %zu-byte aligned",
next, __alignof__(struct dm_target_spec));