summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMikulas Patocka <mpatocka@redhat.com>2026-04-09 18:49:58 +0300
committerMikulas Patocka <mpatocka@redhat.com>2026-04-09 21:49:04 +0300
commit2fa49cc884f6496a915c35621ba4da35649bf159 (patch)
tree664caa07aac9d9e0d03a609023a15d20f7d19862
parent43fd83c0b1dc127cf13b4c05303665924e63ef94 (diff)
downloadlinux-2fa49cc884f6496a915c35621ba4da35649bf159.tar.xz
dm: fix a buffer overflow in ioctl processing
Tony Asleson (using Claude) found a buffer overflow in dm-ioctl in the function retrieve_status: 1. The code in retrieve_status checks that the output string fits into the output buffer and writes the output string there 2. Then, the code aligns the "outptr" variable to the next 8-byte boundary: outptr = align_ptr(outptr); 3. The alignment doesn't check overflow, so outptr could point past the buffer end 4. The "for" loop is iterated again, it executes: remaining = len - (outptr - outbuf); 5. If "outptr" points past "outbuf + len", the arithmetics wraps around and the variable "remaining" contains unusually high number 6. With "remaining" being high, the code writes more data past the end of the buffer Luckily, this bug has no security implications because: 1. Only root can issue device mapper ioctls 2. The commonly used libraries that communicate with device mapper (libdevmapper and devicemapper-rs) use buffer size that is aligned to 8 bytes - thus, "outptr = align_ptr(outptr)" can't overshoot the input buffer and the bug can't happen accidentally Reported-by: Tony Asleson <tasleson@redhat.com> Signed-off-by: Mikulas Patocka <mpatocka@redhat.com> Reviewed-by: Bryn M. Reeves <bmr@redhat.com> Cc: stable@vger.kernel.org
-rw-r--r--drivers/md/dm-ioctl.c4
1 files changed, 4 insertions, 0 deletions
diff --git a/drivers/md/dm-ioctl.c b/drivers/md/dm-ioctl.c
index 405acc14d718..a529174c94cf 100644
--- a/drivers/md/dm-ioctl.c
+++ b/drivers/md/dm-ioctl.c
@@ -1356,6 +1356,10 @@ static void retrieve_status(struct dm_table *table,
used = param->data_start + (outptr - outbuf);
outptr = align_ptr(outptr);
+ if (!outptr || outptr > outbuf + len) {
+ param->flags |= DM_BUFFER_FULL_FLAG;
+ break;
+ }
spec->next = outptr - outbuf;
}