[PATCH 04/58] mtd: rawnand: separate hardware disconnection from cleanup
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Sat Nov 7 12:42:00 PST 2026
Thank you for your contribution! Sashiko AI review found 2 potential
issues to consider:
- [High] mtd: rawnand: unlocked hardware access after nand_disconnect()
in write_bbt()
- [Medium] mtd: rawnand: nand_suspend() returning -ENODEV aborts system
suspend
--
commit 0d69828030d21f2e8c3f391544ee5a56406e7996
Author: James Hilliard <james.hilliard1 at gmail.com>
mtd: rawnand: separate hardware disconnection from cleanup
This commit adds nand_disconnect() to mark a NAND chip as disconnected
under the chip and controller locks and makes nand_get_device(),
nand_suspend(), nand_resume(), and panic_nand_write() reject hardware
access once disconnected.
> diff --git a/drivers/mtd/nand/raw/nand_base.c b/drivers/mtd/nand/raw/nand_base.c
> index a5b278ab9384f..8f7d2571e8d9a 100644
> --- a/drivers/mtd/nand/raw/nand_base.c
> +++ b/drivers/mtd/nand/raw/nand_base.c
[ ... ]
> @@ -581,7 +607,9 @@ static int nand_block_markbad_lowlevel(struct nand_chip *chip, loff_t ofs)
> nand_erase_nand(chip, &einfo, 0);
>
> /* Write bad block marker to OOB */
> - nand_get_device(chip);
> + ret = nand_get_device(chip);
> + if (ret)
> + return ret;
>
> ret = nand_markbad_bbm(chip, ofs);
> nand_release_device(chip);
[Severity: High]
Can a concurrent nand_disconnect() cause write_bbt() to issue unlocked
hardware operations on the disconnected controller when updating an
on-flash BBT?
nand_block_markbad_lowlevel() releases the chip and controller locks
before calling nand_markbad_bbt() -> nand_update_bbt() -> write_bbt().
If nand_disconnect() runs before write_bbt() calls nand_erase_nand() or
scan_write_bbt(), nand_get_device() returns -ENODEV, which write_bbt()
treats as a bad BBT eraseblock:
drivers/mtd/nand/raw/nand_bbt.c:write_bbt() {
...
res = nand_erase_nand(this, &einfo, 1);
if (res < 0) {
pr_warn("nand_bbt: error while erasing BBT block %d\n",
res);
mark_bbt_block_bad(this, td, chip, block);
continue;
}
...
}
mark_bbt_block_bad() then marks each reserved BBT block worn in memory
and calls nand_markbad_bbm() -> nand_default_block_markbad() ->
nand_do_write_oob() without calling nand_get_device(), accessing
controller resources that have already been freed after
nand_disconnect() returned.
[ ... ]
> @@ -4688,10 +4728,14 @@ static int nand_suspend(struct mtd_info *mtd)
> int ret = 0;
>
> mutex_lock(&chip->lock);
> + if (chip->disconnected) {
> + mutex_unlock(&chip->lock);
> + return -ENODEV;
> + }
> if (chip->ops.suspend)
> ret = chip->ops.suspend(chip);
> if (!ret)
> - chip->suspended = 1;
> + WRITE_ONCE(chip->suspended, true);
> mutex_unlock(&chip->lock);
>
> return ret;
[Severity: Medium]
Does returning -ENODEV from nand_suspend() abort system suspend when an
open MTD handle outlives controller unbind?
While an MTD handle remains open after del_mtd_device() and
nand_disconnect(), mtd->dev stays registered on dpm_list until the last
reference is put in mtd_device_release(). During system suspend,
mtd_cls_suspend() calls mtd_suspend() -> nand_suspend(), and returning
-ENODEV fails dpm_suspend() instead of treating the disconnected chip as
a no-op like nand_resume() and nand_sync() do.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261107-submit-rawnand-retained-handle-lifetime-v1-v1-0-0181ef0cc4c8@gmail.com?part=4
More information about the linux-mtd
mailing list