From: sashiko-bot@kernel.org
To: "James Hilliard" <james.hilliard1@gmail.com>,
"Miquel Raynal" <miquel.raynal@bootlin.com>,
"Richard Weinberger" <richard@nod.at>,
"Vignesh Raghavendra" <vigneshr@ti.com>
Cc: linux-mtd@lists.infradead.org,
"Greg Kroah-Hartman" <gregkh@linuxfoundation.org>,
"Srinivas Kandagatla" <srini@kernel.org>,
"Tze Yee Ng" <tze.yee.ng@altera.com>
Subject: Re: [PATCH v4 03/58] mtd: separate class devices from retained backing objects
Date: Fri, 13 Nov 2026 19:16:47 +0000 [thread overview]
Message-ID: <sashiko-outbox-213533@kernel.org> (raw)
In-Reply-To: <20261113-submit-rawnand-retained-handle-lifetime-v1-v4-3-556b1d7c6221@gmail.com>
Thank you for your contribution! Sashiko AI review found 3 potential
issues to consider:
- [High] mtd: out-of-bounds access in gluebi_get_device() via
add_mtd_partitions()
- [Medium] mtd: concurrent child removal in add_mtd_partitions() deletes
all partitions
- [Medium] mtd: mtd_device_parse_register() and unregister check
device_is_registered()
--
commit 6ac4170246a3c7e1422d462f2c77f494c0bb8489
Author: James Hilliard <james.hilliard1@gmail.com>
mtd: separate class devices from retained backing objects
This commit allocates MTD class devices separately from struct mtd_info,
moves the MTD class and device release handling into a built-in helper,
and adds reference counting for backing master and partition metadata.
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 620326279957f..dd404d36156ea 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
[ ... ]
> @@ -1150,7 +1200,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
> ret = 0;
> else if (nr_parts)
> ret = add_mtd_partitions(mtd, parts, nr_parts);
> - else if (!device_is_registered(&mtd->dev))
> + else if (!mtd->dev || !device_is_registered(mtd->dev))
> ret = add_mtd_device(mtd);
> else
> ret = 0;
> @@ -1184,7 +1234,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
> nvmem_unregister(mtd->otp_factory_nvmem);
> }
>
> - if (ret && device_is_registered(&mtd->dev)) {
> + if (ret && mtd->dev && device_is_registered(mtd->dev)) {
> err = del_mtd_device(mtd);
> if (err)
> pr_err("Error when deleting MTD device (%d)\n", err);
> @@ -1225,7 +1275,7 @@ int mtd_device_unregister(struct mtd_info *master)
> if (err)
> return err;
>
> - if (!device_is_registered(&master->dev))
> + if (!master->dev || !device_is_registered(master->dev))
> return 0;
>
> return del_mtd_device(master);
[Severity: Medium]
Can checking device_is_registered(master->dev) instead of
master->registered cause mtd_device_unregister() to call del_mtd_device()
a second time and fail with -ENODEV?
With CONFIG_MTD_PARTITIONED_MASTER=y, mtd_device_parse_register() calls
add_mtd_device(mtd) before parsing and registering partitions. If
userspace (such as udevd on KOBJ_ADD) or an in-kernel consumer acquires a
handle on the master during that window and partition registration then
fails (for example with -EPROBE_DEFER), del_mtd_device(mtd) clears
mtd->registered and drops the initial refcnt without running
mtd_device_release(). Because mtd->dev remains registered until the
handle is put, a driver error path that calls mtd_device_unregister()
(such as physmap_flash_probe() -> physmap_flash_remove()) sees
device_is_registered(master->dev) == true and calls del_mtd_device(master)
again, returning -ENODEV. Wait-free unmanaged callers also return from
mtd_device_parse_register() with mtd->dev drvdata and mtd->nvmem still
attached to the mtd_info they are about to free, and a deferred probe
retry hits WARN_ONCE(mtd->dev) in add_mtd_device().
[ ... ]
> diff --git a/drivers/mtd/mtdpart.c b/drivers/mtd/mtdpart.c
> index c316cfe92c7e4..58d1343476912 100644
> --- a/drivers/mtd/mtdpart.c
> +++ b/drivers/mtd/mtdpart.c
[ ... ]
> @@ -419,35 +420,47 @@ int add_mtd_partitions(struct mtd_info *parent,
> nbparts, parent->name);
>
> for (i = 0; i < nbparts; i++) {
> + mutex_lock(&master->master.partitions_lock);
> + if (master->master.unregistering ||
> + (mtd_is_partition(parent) && !parent->registered)) {
> + ret = -ENODEV;
> + goto err_unlock;
> + }
> +
> child = allocate_partition(parent, parts + i, i, cur_offset);
> if (IS_ERR(child)) {
> ret = PTR_ERR(child);
> - goto err_del_partitions;
> + goto err_unlock;
> }
>
> if (IS_REACHABLE(CONFIG_MTD_VIRT_CONCAT)) {
> - if (mtd_virt_concat_add(child))
> + if (mtd_virt_concat_add(child)) {
> + mutex_unlock(&master->master.partitions_lock);
> continue;
> + }
> }
>
> - mutex_lock(&master->master.partitions_lock);
> list_add_tail(&child->part.node, &parent->partitions);
> - mutex_unlock(&master->master.partitions_lock);
>
> ret = add_mtd_device(child);
> if (ret) {
> - mutex_lock(&master->master.partitions_lock);
> list_del(&child->part.node);
> - mutex_unlock(&master->master.partitions_lock);
> -
> free_partition(child);
> - goto err_del_partitions;
> + goto err_unlock;
> }
>
> mtd_add_partition_attrs(child);
> + cur_offset = child->part.offset + child->part.size;
> +
> + /* Parsing drops the partition lock and may race with deletion. */
> + ret = PTR_ERR_OR_ZERO(get_mtd_device(child, -1));
> + if (ret)
> + goto err_unlock;
> + mutex_unlock(&master->master.partitions_lock);
>
> /* Look for subpartitions (skip if no maching parser found) */
> ret = parse_mtd_partitions(child, parts[i].types, NULL);
> + put_mtd_device(child);
[Severity: High]
Does calling get_mtd_device(child, -1) on every new partition cause an
out-of-bounds access in gluebi_get_device() when a gluebi MTD device is
partitioned?
__get_mtd_device(child) passes child to master->_get_device(mtd), whereas
__put_mtd_device(child) passes master to master->_put_device(master).
gluebi_get_device() applies container_of() directly to mtd without calling
mtd_get_master(mtd):
drivers/mtd/ubi/gluebi.c:gluebi_get_device() {
...
gluebi = container_of(mtd, struct gluebi_device, mtd);
mutex_lock(&devices_mutex);
if (gluebi->refcnt > 0) {
gluebi->refcnt += 1;
...
}
Because child is allocated by allocate_partition() as a standalone struct
mtd_info rather than embedded in struct gluebi_device, gluebi_get_device()
reads and writes past the end of child, and the paired put_mtd_device(child)
then decrements the master gluebi->refcnt in gluebi_put_device(master).
> if (ret < 0 && ret == -ENOENT) {
> pr_debug("Skip parsing subpartitions: %d\n", ret);
> continue;
> @@ -455,12 +468,12 @@ int add_mtd_partitions(struct mtd_info *parent,
> pr_err("Failed to parse subpartitions: %d\n", ret);
> goto err_del_partitions;
> }
> -
> - cur_offset = child->part.offset + child->part.size;
> }
>
> return 0;
>
> +err_unlock:
> + mutex_unlock(&master->master.partitions_lock);
> err_del_partitions:
> del_mtd_partitions(master);
[Severity: Medium]
If child is removed via BLKPG_DEL_PARTITION while partitions_lock is
dropped for parse_mtd_partitions(child, ...), does jumping to err_unlock
destroy all partitions on the root master device?
When a subpartition parser calls add_mtd_partitions(child, ...) after
child->registered has been cleared by mtd_del_partition(), the
!parent->registered check sets ret = -ENODEV and jumps to err_unlock.
That falls through to del_mtd_partitions(master) on the top-level master
instead of just skipping subpartitions for the removed child, and returns
-ENODEV to the outer add_mtd_partitions() loop (which only ignores
-ENOENT), failing the entire master registration.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261113-submit-rawnand-retained-handle-lifetime-v1-v4-0-556b1d7c6221@gmail.com?part=3
______________________________________________________
Linux MTD discussion mailing list
http://lists.infradead.org/mailman/listinfo/linux-mtd/
next prev parent reply other threads:[~2026-11-13 19:16 UTC|newest]
Thread overview: 125+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-13 18:14 [PATCH v4 00/58] mtd: rawnand: retain chip and controller state across removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 01/58] nvmem: disconnect provider callbacks before unregister returns James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 02/58] mtd: acquire an MTD handle from a referenced class device James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 03/58] mtd: separate class devices from retained backing objects James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 19:16 ` sashiko-bot [this message]
2026-11-13 18:14 ` [PATCH v4 04/58] mtd: retain virtual concatenations across component removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 05/58] mtd: rawnand: separate hardware disconnection from cleanup James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 06/58] mtd: rawnand: share retained chip and controller ownership James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 07/58] mtd: rawnand: sunxi: retain chip state until the final MTD put James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 08/58] mtd: rawnand: plat_nand: retain open-handle state on removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 09/58] mtd: rawnand: gpio: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 10/58] mtd: rawnand: stm32_fmc2: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 11/58] mtd: rawnand: denali: retain chips across controller removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 12/58] mtd: rawnand: arasan: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 13/58] mtd: rawnand: mxic: retain open-handle state on removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 14/58] mtd: rawnand: intel: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 15/58] mtd: rawnand: tegra: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 16/58] mtd: rawnand: mtk: retain chips across controller removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 17/58] mtd: rawnand: rockchip: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 18/58] mtd: rawnand: atmel: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 19/58] mtd: rawnand: orion: retain open-handle state on removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 20/58] mtd: rawnand: socrates: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 21/58] mtd: rawnand: fsl_upm: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 22/58] mtd: rawnand: pasemi: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 23/58] mtd: rawnand: ams-delta: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 24/58] mtd: rawnand: xway: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 25/58] mtd: rawnand: hisi504: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 26/58] mtd: rawnand: vf610: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 27/58] mtd: rawnand: technologic: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:39 ` sashiko-bot
2026-11-13 18:14 ` [PATCH v4 28/58] mtd: rawnand: loongson: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 29/58] mtd: rawnand: ma35d1: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 30/58] mtd: rawnand: pl35x: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 31/58] mtd: rawnand: mxc: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 32/58] mtd: rawnand: fsmc: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 33/58] mtd: rawnand: gpmi: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 34/58] mtd: rawnand: omap2: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 35/58] mtd: rawnand: marvell: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 36/58] mtd: rawnand: renesas: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 20:01 ` Wolfram Sang
2026-11-13 20:01 ` Wolfram Sang
2026-11-13 18:14 ` [PATCH v4 37/58] mtd: rawnand: meson: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 38/58] mtd: rawnand: cadence: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 39/58] mtd: rawnand: qcom: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 40/58] mtd: rawnand: cafe: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 41/58] mtd: rawnand: brcmnand: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 42/58] mtd: rawnand: au1550nd: retain chip state across removal James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:14 ` [PATCH v4 43/58] mtd: rawnand: sharpsl: " James Hilliard
2026-11-13 18:14 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 44/58] mtd: rawnand: davinci: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 45/58] mtd: rawnand: sh_flctl: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 46/58] mtd: rawnand: lpc32xx_slc: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 47/58] mtd: rawnand: lpc32xx_mlc: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 48/58] mtd: rawnand: ndfc: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 49/58] mtd: rawnand: txx9ndfmc: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 50/58] mtd: rawnand: ingenic: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 51/58] mtd: rawnand: mpc5121: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 52/58] mtd: rawnand: bcm47xxnflash: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 53/58] mtd: rawnand: fsl_elbc: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 54/58] mtd: rawnand: fsl_ifc: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 55/58] mtd: rawnand: r852: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 56/58] mtd: rawnand: nandsim: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 57/58] mtd: rawnand: cs553x: " James Hilliard
2026-11-13 18:15 ` James Hilliard
2026-11-13 18:15 ` [PATCH v4 58/58] mtd: rawnand: diskonchip: " James Hilliard
2026-11-13 18:15 ` James Hilliard
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-213533@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=james.hilliard1@gmail.com \
--cc=linux-mtd@lists.infradead.org \
--cc=miquel.raynal@bootlin.com \
--cc=richard@nod.at \
--cc=sashiko-reviews@lists.linux.dev \
--cc=srini@kernel.org \
--cc=tze.yee.ng@altera.com \
--cc=vigneshr@ti.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.