[PATCH 1/3] mtd: rawnand: qcom: parse boot partitions before registering MTD
sashiko-bot at kernel.org
sashiko-bot at kernel.org
Sun Nov 8 13:24:03 PST 2026
Thank you for your contribution! Sashiko AI review found no new issues
in this patch, but noticed 1 related pre-existing issue it does not
introduce:
- [Medium] mtd: rawnand: qcom: unlocked bam_txn reallocation in
qcom_nand_attach_chip() [1]
--
commit aecfb39160da37f68bc9b557fcfe8446b871939e
Author: James Hilliard <james.hilliard1 at gmail.com>
mtd: rawnand: qcom: parse boot partitions before registering MTD
This commit parses boot partitions in qcom_nand_host_init_and_register()
before calling mtd_device_parse_register() so that parsing errors do not
call nand_cleanup() on an already registered MTD device.
> diff --git a/drivers/mtd/nand/raw/qcom_nandc.c b/drivers/mtd/nand/raw/qcom_nandc.c
> index 2d98f79b492d6..f240d1effa043 100644
> --- a/drivers/mtd/nand/raw/qcom_nandc.c
> +++ b/drivers/mtd/nand/raw/qcom_nandc.c
> @@ -2052,16 +2052,16 @@ static int qcom_nand_host_init_and_register(struct qcom_nand_controller *nandc,
> if (ret)
> return ret;
>
> - ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0);
> - if (ret)
> - goto err;
> -
> if (nandc->props->use_codeword_fixup) {
> ret = qcom_nand_host_parse_boot_partitions(nandc, host, dn);
> if (ret)
> goto err;
> }
>
> + ret = mtd_device_parse_register(mtd, probes, NULL, NULL, 0);
> + if (ret)
> + goto err;
[Severity: Medium]
This problem wasn't introduced by this patch, but can qcom_nand_attach_chip()
free and reallocate nandc->bam_txn [1] while an earlier chip is already
registered and servicing I/O?
qcom_probe_nand_devices() calls qcom_nand_host_init_and_register() for each
child node in turn. Once the first chip is registered, MTD operations on it
take nandc->controller.lock and use the controller-wide nandc->bam_txn, while
probing a second chip runs qcom_nand_attach_chip() without holding
nandc->controller.lock:
drivers/mtd/nand/raw/qcom_nandc.c:qcom_nand_attach_chip() {
...
if (nandc->props->supports_bam)
qcom_free_bam_transaction(nandc);
nandc->max_cwperpage = max_t(unsigned int, nandc->max_cwperpage,
cwperpage);
/* Now allocate the BAM transaction based on updated max_cwperpage */
if (nandc->props->supports_bam) {
nandc->bam_txn = qcom_alloc_bam_transaction(nandc);
if (!nandc->bam_txn) {
dev_err(nandc->dev,
"failed to allocate bam transaction\n");
return -ENOMEM;
}
}
...
}
This allows the second chip's scan to free nandc->bam_txn underneath an
in-flight operation on the first chip:
CPU0 CPU1
qcom_probe_nand_devices()
qcom_nand_host_init_and_register()
mtd_device_parse_register() [chip 0]
nand_read_oob() [chip 0]
nand_get_device()
qcom_nandc_read_page()
...
qcom_nand_host_init_and_register() [chip 1]
nand_scan()
...
qcom_nand_attach_chip()
qcom_free_bam_transaction()
qcom_clear_bam_transaction()
<-- use-after-free
qcom_alloc_bam_transaction()
Also, if qcom_alloc_bam_transaction() fails for the second chip,
nandc->bam_txn is left NULL while the first chip remains registered, causing
subsequent operations on the first chip to hit a NULL pointer dereference.
[1] https://sashiko.dev/#/bug/linux-f5ec08db-a039-4be6-ba66-945cfc6d14f5
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261108-submit-qcom-nand-child-probe-errors-v1-v1-0-509f30a9e14d@gmail.com?part=1
More information about the linux-mtd
mailing list