[PATCH] fix: mtd: mtd_device_parse_register: fix refcount imbalance on add_mtd_device failure and multi-call scenarios

WenTao Liang vulab at iscas.ac.cn
Sat Jun 27 20:58:22 PDT 2026



> 2026年6月26日 23:13,WenTao Liang <vulab at iscas.ac.cn> 写道:
> 
> add_mtd_device initializes mtd->refcnt via kref_init unconditionally. The
>  cleanup in the out label only calls del_mtd_device when
>  device_is_registered is true. When add_mtd_device fails before
>  device_register, the refcnt is left at 1 (leak). Conversely, when
>  CONFIG_MTD_PARTITIONED_MASTER is disabled and the device was already
>  registered by a prior call, the error path incorrectly calls
>  del_mtd_device without a matching add_mtd_device in this invocation,
>  causing a refcount underflow.
> 
> Track whether add_mtd_device succeeded in this invocation with a
>  registered flag, and only call del_mtd_device on error when registered is
>  true.
> 
> Cc: stable at vger.kernel.org
> Fixes: 1c4c215cbdcb ("mtd: add new API for handling MTD registration")
> Signed-off-by: WenTao Liang <vulab at iscas.ac.cn>
> ---
> drivers/mtd/mtdcore.c | 10 +++++++---
> 1 file changed, 7 insertions(+), 3 deletions(-)
> 
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 576537774628..59d8a6c61f55 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -1108,6 +1108,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
> 			      int nr_parts)
> {
> 	int ret, err;
> +	bool registered = false;
> 
> 	mtd_set_dev_defaults(mtd);
> 
> @@ -1119,6 +1120,7 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
> 		ret = add_mtd_device(mtd);
> 		if (ret)
> 			goto out;
> +		registered = true;
> 	}
> 
> 	if (IS_REACHABLE(CONFIG_MTD_VIRT_CONCAT)) {
> @@ -1136,9 +1138,11 @@ 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 (!device_is_registered(&mtd->dev)) {
> 		ret = add_mtd_device(mtd);
> -	else
> +		if (!ret)
> +			registered = true;
> +	} else
> 		ret = 0;
> 
> 	if (ret)
> @@ -1170,7 +1174,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 && registered) {
> 		err = del_mtd_device(mtd);
> 		if (err)
> 			pr_err("Error when deleting MTD device (%d)\n", err);
> -- 
> 2.39.5 (Apple Git-154)

Please ignore this patch. I will resend a proper version after
learning the kernel submission process.

Apologies for the noise.

Best regards,
WenTao Liang




More information about the linux-mtd mailing list