]> git.ipfire.org Git - thirdparty/kernel/stable.git/commitdiff
mtdchar: fix integer overflow in read/write ioctls
authorDan Carpenter <dan.carpenter@linaro.org>
Tue, 30 Sep 2025 12:32:34 +0000 (15:32 +0300)
committerGreg Kroah-Hartman <gregkh@linuxfoundation.org>
Mon, 1 Dec 2025 10:43:20 +0000 (11:43 +0100)
commit e4185bed738da755b191aa3f2e16e8b48450e1b8 upstream.

The "req.start" and "req.len" variables are u64 values that come from the
user at the start of the function.  We mask away the high 32 bits of
"req.len" so that's capped at U32_MAX but the "req.start" variable can go
up to U64_MAX which means that the addition can still integer overflow.

Use check_add_overflow() to fix this bug.

Fixes: 095bb6e44eb1 ("mtdchar: add MEMREAD ioctl")
Fixes: 6420ac0af95d ("mtdchar: prevent unbounded allocation in MEMWRITE ioctl")
Cc: stable@vger.kernel.org
Signed-off-by: Dan Carpenter <dan.carpenter@linaro.org>
Signed-off-by: Miquel Raynal <miquel.raynal@bootlin.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
drivers/mtd/mtdchar.c

index 8dc4f5c493fcbac3abe17818cd5f7b2adcc70dd9..335c702633ffe023372477d536ce5320703b0676 100644 (file)
@@ -599,6 +599,7 @@ mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp)
        uint8_t *datbuf = NULL, *oobbuf = NULL;
        size_t datbuf_len, oobbuf_len;
        int ret = 0;
+       u64 end;
 
        if (copy_from_user(&req, argp, sizeof(req)))
                return -EFAULT;
@@ -618,7 +619,7 @@ mtdchar_write_ioctl(struct mtd_info *mtd, struct mtd_write_req __user *argp)
        req.len &= 0xffffffff;
        req.ooblen &= 0xffffffff;
 
-       if (req.start + req.len > mtd->size)
+       if (check_add_overflow(req.start, req.len, &end) || end > mtd->size)
                return -EINVAL;
 
        datbuf_len = min_t(size_t, req.len, mtd->erasesize);
@@ -698,6 +699,7 @@ mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp)
        size_t datbuf_len, oobbuf_len;
        size_t orig_len, orig_ooblen;
        int ret = 0;
+       u64 end;
 
        if (copy_from_user(&req, argp, sizeof(req)))
                return -EFAULT;
@@ -724,7 +726,7 @@ mtdchar_read_ioctl(struct mtd_info *mtd, struct mtd_read_req __user *argp)
        req.len &= 0xffffffff;
        req.ooblen &= 0xffffffff;
 
-       if (req.start + req.len > mtd->size) {
+       if (check_add_overflow(req.start, req.len, &end) || end > mtd->size) {
                ret = -EINVAL;
                goto out;
        }