[PATCH] mtd: core: reject OOB transfers starting at the device end
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Wed Nov 4 12:12:18 PST 2026
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Medium] mtd: core: maxooblen underflow in mtd_check_oob_ops() on unaligned size
--
commit f1617f89facd985e5ed9b314a9af3e4693ab3800
Author: James Hilliard <james.hilliard1 at gmail.com>
mtd: core: reject OOB transfers starting at the device end
This commit updates mtd_check_oob_ops() to reject nonempty OOB transfers
starting at or beyond mtd->size so that maxooblen does not underflow when
ops->ooboffs is nonzero.
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 491a27d0315fa..b82fd7ccd111d 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -1676,6 +1676,9 @@ static int mtd_check_oob_ops(struct mtd_info *mtd, loff_t offs,
> if (ops->ooblen) {
> size_t maxooblen;
>
> + if (offs >= mtd->size)
> + return -EINVAL;
[Severity: Medium]
Can maxooblen still underflow in mtd_check_oob_ops() when mtd->size is not
aligned to mtd->writesize?
In drivers/mtd/mtdpart.c, allocate_partition() allows registering read-only
partitions whose size is not a multiple of writesize:
drivers/mtd/mtdpart.c:allocate_partition() {
...
tmp = mtd_get_master_ofs(child, 0) + child->part.size;
remainder = do_div(tmp, wr_alignment);
if ((child->flags & MTD_WRITEABLE) && remainder) {
child->flags &= ~MTD_WRITEABLE;
printk(KERN_WARNING"mtd: partition \"%s\" doesn't end on an erase/write block -- force read-only\n",
part->name);
}
child->size = child->part.size;
...
}
And mtd_check_oob_ops() computes maxooblen using floor division via
mtd_div_by_ws():
drivers/mtd/mtdcore.c:mtd_check_oob_ops() {
...
if (offs >= mtd->size)
return -EINVAL;
if (ops->ooboffs >= mtd_oobavail(mtd, ops))
return -EINVAL;
maxooblen = ((size_t)(mtd_div_by_ws(mtd->size, mtd) -
mtd_div_by_ws(offs, mtd)) *
mtd_oobavail(mtd, ops)) - ops->ooboffs;
...
}
When a request arrives via mtdchar_readoob() -> mtd_read_oob() ->
mtd_check_oob_ops() with an offset in the trailing partial page
[mtd_div_by_ws(mtd->size, mtd) * mtd->writesize, mtd->size) and a nonzero
ops->ooboffs, offs < mtd->size holds, but mtd_div_by_ws(offs, mtd) equals
mtd_div_by_ws(mtd->size, mtd). Subtracting ops->ooboffs from zero then
underflows maxooblen and allows reading OOB data from the page extending
past the partition end.
Would checking mtd_div_by_ws(offs, mtd) >= mtd_div_by_ws(mtd->size, mtd)
instead of offs >= mtd->size avoid this underflow for unaligned partition
sizes as well?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261104-submit-mtd-oob-end-v1-v1-1-5cb8ad921cb0@gmail.com?part=1
More information about the linux-mtd
mailing list