Message ID | 20230603145244.1538-3-demi@invisiblethingslab.com (mailing list archive) |
---|---|
State | Accepted, archived |
Delegated to: | Mike Snitzer |
Headers | show |
Series | Several device-mapper fixes | expand |
On Sat, 3 Jun 2023, Demi Marie Obenour wrote: > 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> > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") > Cc: stable@vger.kernel.org Reviewed-by: Mikulas Patocka <mpatocka@redhat.com> > --- > drivers/md/dm-ioctl.c | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) > > diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c > index 34fa74c6a70db8aa67aaba3f6a2fc4f38ef736bc..64e8f16d344c47057de5e2d29e3d63202197dca0 100644 > --- a/drivers/md/dm-ioctl.c > +++ b/drivers/md/dm-ioctl.c > @@ -1396,6 +1396,25 @@ 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 has excessive alignment requirements"); > + static_assert(offsetof(struct dm_ioctl, data) >= sizeof(struct dm_target_spec), > + "struct dm_target_spec too big"); > + > + /* > + * 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 % 8) { > DMERR("Next target spec (offset %u) is not 8-byte aligned", next); > return -EINVAL; > -- > Sincerely, > Demi Marie Obenour (she/her/hers) > Invisible Things Lab > > -- > dm-devel mailing list > dm-devel@redhat.com > https://listman.redhat.com/mailman/listinfo/dm-devel > -- dm-devel mailing list dm-devel@redhat.com https://listman.redhat.com/mailman/listinfo/dm-devel
On Sat, Jun 03 2023 at 10:52P -0400, Demi Marie Obenour <demi@invisiblethingslab.com> wrote: > 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> > Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") > Cc: stable@vger.kernel.org > --- > drivers/md/dm-ioctl.c | 19 +++++++++++++++++++ > 1 file changed, 19 insertions(+) > > diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c > index 34fa74c6a70db8aa67aaba3f6a2fc4f38ef736bc..64e8f16d344c47057de5e2d29e3d63202197dca0 100644 > --- a/drivers/md/dm-ioctl.c > +++ b/drivers/md/dm-ioctl.c > @@ -1396,6 +1396,25 @@ 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 has excessive alignment requirements"); > + static_assert(offsetof(struct dm_ioctl, data) >= sizeof(struct dm_target_spec), > + "struct dm_target_spec too big"); I'm struggling to see the point for this compile-time check? Especially when you consider (on x86_64): sizeof(struct dm_target_spec) = 40 offsetof(struct dm_ioctl, data) = 305 Just feels like there is no utility offered by adding this check. SO I've dropped it. But if you feel there is some inherent value please let me know. Thanks, Mike -- dm-devel mailing list dm-devel@redhat.com https://listman.redhat.com/mailman/listinfo/dm-devel
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c index 34fa74c6a70db8aa67aaba3f6a2fc4f38ef736bc..64e8f16d344c47057de5e2d29e3d63202197dca0 100644 --- a/drivers/md/dm-ioctl.c +++ b/drivers/md/dm-ioctl.c @@ -1396,6 +1396,25 @@ 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 has excessive alignment requirements"); + static_assert(offsetof(struct dm_ioctl, data) >= sizeof(struct dm_target_spec), + "struct dm_target_spec too big"); + + /* + * 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 % 8) { DMERR("Next target spec (offset %u) is not 8-byte aligned", next); return -EINVAL;
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> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2") Cc: stable@vger.kernel.org --- drivers/md/dm-ioctl.c | 19 +++++++++++++++++++ 1 file changed, 19 insertions(+)