diff options
author | Demi Marie Obenour <demi@invisiblethingslab.com> | 2023-06-03 16:52:40 +0200 |
---|---|---|
committer | Mike Snitzer <snitzer@kernel.org> | 2023-06-23 16:31:51 +0200 |
commit | 13f4a697f8b4feb705569f9336127e9e2f9ac596 (patch) | |
tree | b06d5d26f3bafba66b50edbc6cd5cf99aa145dd7 | |
parent | dm ioctl: Check dm_target_spec is sufficiently aligned (diff) | |
download | linux-13f4a697f8b4feb705569f9336127e9e2f9ac596.tar.xz linux-13f4a697f8b4feb705569f9336127e9e2f9ac596.zip |
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>
-rw-r--r-- | drivers/md/dm-ioctl.c | 16 |
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)); |