Skip to contentSkip to conversation

platform: fix reference leak on failed platform_device_register()

PATCH In review Vastargazing 6 participants 19 messages May 4 – May 14

Subsystems (7)
lore
Share & tools
lore
#1 lore raw

PATCH 1/5 misc: eeprom: digsy_mtc: fix reference leak on failed device registration

In reply to Vastargazing

When platform_device_register() fails in digsy_mtc_eeprom_devices_init(), the embedded struct device has already been initialized by device_initialize() inside platform_device_register(). The failure path cleans up the software node but returns the error without dropping the device reference:

digsy_mtc_eeprom_devices_init()

    -> platform_device_register(&digsy_mtc_eeprom)
       -> device_initialize(&digsy_mtc_eeprom.dev)   /* kref = 1 */
       -> platform_device_add(&digsy_mtc_eeprom)     /* fails */
    <- returns error, kref still 1, reference leaked

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() in the error branch before removing the software node.

Fixes 469dded18391 ("misc/eeprom: add eeprom access driver for digsy_mtc board")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)
---
 drivers/misc/eeprom/digsy_mtc_eeprom.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/misc/eeprom/digsy_mtc_eeprom.c +3 -1
index ee58f7ce5bfa..4ca3e567c49d 100644
@@ -89,8 +89,10 @@ static int __init digsy_mtc_eeprom_devices_init(void)
 		return ret;
 
 	ret = platform_device_register(&digsy_mtc_eeprom);
-	if (ret)
+	if (ret) {
+		platform_device_put(&digsy_mtc_eeprom);
 		device_remove_software_node(&digsy_mtc_eeprom.dev);
+	}
 
 	return ret;
 }
Signature · 1 line
2.51.0
#2 lore raw

PATCH 2/5 platform/chrome: cros_ec_lpc: fix reference leak on failed device registration

In reply to Vastargazing

When platform_device_register() fails in cros_ec_lpc_init(), the embedded struct device has already been initialized by device_initialize() inside platform_device_register(). The error path unregisters the driver but returns without dropping the device reference:

cros_ec_lpc_init()

    -> platform_device_register(&cros_ec_lpc_device)
       -> device_initialize(&cros_ec_lpc_device.dev)   /* kref = 1 */
       -> platform_device_add(&cros_ec_lpc_device)     /* fails */
    <- platform_driver_unregister() called, but kref still 1

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() before unregistering the driver.

Fixes 5f454bdf6353 ("platform/chrome: cros_ec_lpc: Register the driver if ACPI entry is missing.")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)
---
 drivers/platform/chrome/cros_ec_lpc.c | 1 +
 1 file changed, 1 insertion(+)
drivers/platform/chrome/cros_ec_lpc.c +1 -0
index 78cfff80cdea..cb3ff76d29e9 100644
@@ -892,6 +892,7 @@ static int __init cros_ec_lpc_init(void)
 		ret = platform_device_register(&cros_ec_lpc_device);
 		if (ret) {
 			pr_err(DRV_NAME ": can't register device: %d\n", ret);
+			platform_device_put(&cros_ec_lpc_device);
 			platform_driver_unregister(&cros_ec_lpc_driver);
 		}
 	}
Signature · 1 line
2.51.0
#4 lore raw

PATCH 3/5 mtd: maps: physmap: fix reference leak on failed device registration

In reply to Vastargazing

When platform_device_register() fails in physmap_init(), the embedded struct device has already been initialized by device_initialize() inside platform_device_register(). The error path unregisters the driver but returns without dropping the device reference:

physmap_init()

    -> platform_device_register(&physmap_flash)
       -> device_initialize(&physmap_flash.dev)   /* kref = 1 */
       -> platform_device_add(&physmap_flash)     /* fails */
    <- platform_driver_unregister() called, but kref still 1

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() before unregistering the driver.

Fixes 73566edf9b91 ("[MTD] Convert physmap to platform driver")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)
---
 drivers/mtd/maps/physmap-core.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/mtd/maps/physmap-core.c +3 -1
index dcda7685fc99..45d79ca622c1 100644
@@ -654,8 +654,10 @@ static int __init physmap_init(void)
 #ifdef CONFIG_MTD_PHYSMAP_COMPAT
 	if (err == 0) {
 		err = platform_device_register(&physmap_flash);
-		if (err)
+		if (err) {
+			platform_device_put(&physmap_flash);
 			platform_driver_unregister(&physmap_flash_driver);
+		}
 	}
 #endif
 
Signature · 1 line
2.51.0
#6 lore raw

PATCH 4/5 perf: arm: pmu: fix reference leak on failed device registration

In reply to Vastargazing

When platform_device_register() fails in arm_acpi_register_pmu_device(), the embedded struct device has already been initialized by device_initialize() inside platform_device_register(). The error path unregisters the GSI interrupt but returns without dropping the device reference:

arm_acpi_register_pmu_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- acpi_unregister_gsi() called, but kref still 1

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() in the error branch before unregistering the GSI.

Fixes d24a0c7099b3 ("arm_pmu: acpi: spe: Add initial MADT/SPE probing")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)
---
 drivers/perf/arm_pmu_acpi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/perf/arm_pmu_acpi.c +3 -1
index e80f76d95e68..c2defbc32ad9 100644
@@ -119,8 +119,10 @@ arm_acpi_register_pmu_device(struct platform_device *pdev, u8 len,
 
 	pdev->resource[0].start = irq;
 	ret = platform_device_register(pdev);
-	if (ret)
+	if (ret) {
+		platform_device_put(pdev);
 		acpi_unregister_gsi(gsi);
+	}
 
 	return ret;
 }
Signature · 1 line
2.51.0
#9 lore raw

PATCH 5/5 mfd: sm501: fix reference leak on failed device registration

In reply to Vastargazing

When platform_device_register() fails in sm501_register_device(), the platform device allocated by sm501_create_subdev() has its struct device initialized by device_initialize() inside platform_device_register(). The error path logs the error but returns without dropping the device reference, leaking the memory allocated by sm501_create_subdev():

sm501_register_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- dev_err() called, kref still 1, sm501_device_release never called

The device's release callback (sm501_device_release) calls kfree() on the containing sm501_device structure. Without platform_device_put(), this memory is never freed.

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() in the error branch, which triggers sm501_device_release() and frees the allocated memory.

Fixes b6d6454fdb66 ("[PATCH] mfd: SM501 core driver")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)
---
 drivers/mfd/sm501.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/mfd/sm501.c +3 -1
index 0ee6d8940e69..8276456b142f 100644
@@ -704,9 +704,11 @@ static int sm501_register_device(struct sm501_devdata *sm,
 	if (ret >= 0) {
 		dev_dbg(sm->dev, "registered %s\n", pdev->name);
 		list_add_tail(&smdev->list, &sm->devices);
-	} else
+	} else {
 		dev_err(sm->dev, "error registering %s (%d)\n",
 			pdev->name, ret);
+		platform_device_put(pdev);
+	}
 
 	return ret;
 }
Signature · 1 line
2.51.0
#0 lore raw

cover platform: fix reference leak on failed platform_device_register()

platform_device_register() calls device_initialize() before platform_device_add(). If platform_device_add() fails, device_initialize() has already set the struct device kref to 1, and the kref must be released via platform_device_put(). The kernel-doc for platform_device_register() states this explicitly:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

This series fixes five drivers that call platform_device_register() and return the error code without calling platform_device_put() on the failure path. The pattern was identified by Coccinelle static analysis, confirmed by manual inspection, and is analogous to the recently merged fix in commit 4ff036f95238 ("ALSA: pcmtest: fix reference leak on failed device registration").

Sites fixed:
drivers/misc/eeprom/digsy_mtc_eeprom.c
drivers/platform/chrome/cros_ec_lpc.c
drivers/mtd/maps/physmap-core.c
drivers/perf/arm_pmu_acpi.c
drivers/mfd/sm501.c

Build tested on x86 defconfig:
- digsy_mtc_eeprom.c: compiled cleanly

  - cros_ec_lpc.c:       compiled cleanly
  - sm501.c:             compiled cleanly
  - physmap-core.c:      pre-existing Werror in map.h header (unrelated)
  - arm_pmu_acpi.c:      ARM-only, no asm/cputype.h on x86

Vastargazing (5):
misc: eeprom: digsy_mtc: fix reference leak on failed device
registration
platform/chrome: cros_ec_lpc: fix reference leak on failed device
registration
mtd: maps: physmap: fix reference leak on failed device registration
perf: arm: pmu: fix reference leak on failed device registration
mfd: sm501: fix reference leak on failed device registration

 drivers/mfd/sm501.c                    | 4 +++-
 drivers/misc/eeprom/digsy_mtc_eeprom.c | 4 +++-
 drivers/mtd/maps/physmap-core.c        | 4 +++-
 drivers/perf/arm_pmu_acpi.c            | 4 +++-
 drivers/platform/chrome/cros_ec_lpc.c  | 1 +
 5 files changed, 13 insertions(+), 4 deletions(-)
Signature · 1 line
2.51.0
#7 lore raw

Re: [PATCH 4/5] perf: arm: pmu: fix reference leak on failed device registration

In reply to Vastargazing
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] Calling `platform_device_put()` on statically allocated platform devices triggers a kernel…

Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] Calling platform_device_put() on statically allocated platform devices triggers a kernel WARNING. --

commit 3c982eab6d069fa3cf3109dda88a31b66ceb0afd
Author: Vastargazing <[email protected]>

perf: arm: pmu: fix reference leak on failed device registration

When platform_device_register() fails in arm_acpi_register_pmu_device(), this commit adds a call to platform_device_put() in the error branch to prevent a reference leak.

drivers/perf/arm_pmu_acpi.c arm_acpi_register_pmu_device(struct platform_device *pdev, u8 len, · line 123

Quoted 11 lines
drivers/perf/arm_pmu_acpi.c +2 -1
index e80f76d95e68..c2defbc32ad9 100644
@@ -119,8 +119,10 @@ arm_acpi_register_pmu_device(struct platform_device *pdev, u8 len,
 
 	pdev->resource[0].start = irq;
 	ret = platform_device_register(pdev);
-	if (ret)
+	if (ret) {
+		platform_device_put(pdev);

Because the devices passed to this function (spe_dev and trbe_dev) are statically allocated and do not provide a .dev.release callback, will calling platform_device_put() trigger a kernel warning?

When the reference count drops to 0, device_release() is invoked. Since no release function is defined for these static objects, it triggers the driver core warning about lacking a release() function, which could panic the system if panic_on_warn is configured.

The kernel documentation's advice to use platform_device_put() applies to dynamically allocated devices, not statically allocated global variables.

Quoted 5 lines
drivers/perf/arm_pmu_acpi.c +1 -0
 		acpi_unregister_gsi(gsi);
+	}
 
 	return ret;
 }
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
#10 lore raw

PATCH v2 1/1 mfd: sm501: fix reference leak on failed device registration

In reply to Vastargazing

When platform_device_register() fails in sm501_register_device(), the platform device allocated by sm501_create_subdev() has its struct device initialized by device_initialize() inside platform_device_register(). The error path logs the error but returns without dropping the device reference, leaking the memory allocated by sm501_create_subdev():

sm501_register_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- dev_err() called, kref still 1, sm501_device_release never called

The device's release callback (sm501_device_release) calls kfree() on the containing sm501_device structure. Without platform_device_put(), this memory is never freed.

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() in the error branch, which triggers sm501_device_release() and frees the allocated memory.

Fixes b6d6454fdb66 ("[PATCH] mfd: SM501 core driver")
---
 drivers/mfd/sm501.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/mfd/sm501.c +3 -1
index 0ee6d8940e69..8276456b142f 100644
@@ -704,9 +704,11 @@ static int sm501_register_device(struct sm501_devdata *sm,
 	if (ret >= 0) {
 		dev_dbg(sm->dev, "registered %s\n", pdev->name);
 		list_add_tail(&smdev->list, &sm->devices);
-	} else
+	} else {
 		dev_err(sm->dev, "error registering %s (%d)\n",
 			pdev->name, ret);
+		platform_device_put(pdev);
+	}
 
 	return ret;
 }
Signature · 1 line
2.51.0
maintainer Applied
#11 lore raw

Re: [PATCH v2] mfd: sm501: fix reference leak on failed device registration

Quoted 6 lines · Valery Borovsky

When platform_device_register() fails in sm501_register_device(), the platform device allocated by sm501_create_subdev() has its struct device initialized by device_initialize() inside platform_device_register(). The error path logs the error but returns without dropping the device reference, leaking the memory allocated by sm501_create_subdev():

Quoted 7 lines

sm501_register_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- dev_err() called, kref still 1, sm501_device_release never called

[...]

Applied to mtd/next, thanks!

[1/1] mfd: sm501: fix reference leak on failed device registration

      commit: faa9bba3fe2f37e7dcb26d4501d890fbfd7df160

Patche(s) should be available on mtd/linux.git and will be part of the next PR (provided that no robot complains by then).

Kind regards,
Miquèl

maintainer
#5 lore raw

Re: [PATCH 3/5] mtd: maps: physmap: fix reference leak on failed device registration

In reply to Vastargazing
Quoted 17 lines · Vastargazing

When platform_device_register() fails in physmap_init(), the embedded struct device has already been initialized by device_initialize() inside platform_device_register(). The error path unregisters the driver but returns without dropping the device reference:

physmap_init()

    -> platform_device_register(&physmap_flash)
       -> device_initialize(&physmap_flash.dev)   /* kref = 1 */
       -> platform_device_add(&physmap_flash)     /* fails */
    <- platform_driver_unregister() called, but kref still 1

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Quoted 6 lines

Fix this by calling platform_device_put() before unregistering the driver.

Fixes 73566edf9b91 ("[MTD] Convert physmap to platform driver")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)

Somehow b4 applied another patch from that series, I'm not sure why. I just dropped it. Please resend this patch alone.

Also, your SoB line seems to be incorrect, we need a proper name, please have a loot at the DCO.

Thanks,
Miquèl

maintainer
#3 lore raw

Re: [PATCH 2/5] platform/chrome: cros_ec_lpc: fix reference leak on failed device registration

In reply to Vastargazing
Quoted 32 lines · Vastargazing

When platform_device_register() fails in cros_ec_lpc_init(), the embedded struct device has already been initialized by device_initialize() inside platform_device_register(). The error path unregisters the driver but returns without dropping the device reference:

cros_ec_lpc_init()

    -> platform_device_register(&cros_ec_lpc_device)
       -> device_initialize(&cros_ec_lpc_device.dev)   /* kref = 1 */
       -> platform_device_add(&cros_ec_lpc_device)     /* fails */
    <- platform_driver_unregister() called, but kref still 1

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() before unregistering the driver.

Fixes 5f454bdf6353 ("platform/chrome: cros_ec_lpc: Register the driver if ACPI entry is missing.")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)
---
 drivers/platform/chrome/cros_ec_lpc.c | 1 +
 1 file changed, 1 insertion(+)
drivers/platform/chrome/cros_ec_lpc.c +0 -0
index 78cfff80cdea..cb3ff76d29e9 100644

drivers/platform/chrome/cros_ec_lpc.c static int __init cros_ec_lpc_init(void) · line 898

Quoted 7 lines
drivers/platform/chrome/cros_ec_lpc.c +1 -0
@@ -892,6 +892,7 @@ static int __init cros_ec_lpc_init(void)
 		ret = platform_device_register(&cros_ec_lpc_device);
 		if (ret) {
 			pr_err(DRV_NAME ": can't register device: %d\n", ret);
+			platform_device_put(&cros_ec_lpc_device);
 			platform_driver_unregister(&cros_ec_lpc_driver);
 		}
 	}

The patch is identical to [1]. See also [2].

[1] https://lore.kernel.org/chrome-platform/[email protected]/
[2] https://lore.kernel.org/chrome-platform/CANUHTR9_c=msO7mAax=Aj4U--GB=2ozserOvrTU8WueqdSMN8Q@mail.gmail.com/

#8 lore raw

Re: [PATCH 4/5] perf: arm: pmu: fix reference leak on failed device registration

In reply to Vastargazing
Quoted 34 lines · Vastargazing

When platform_device_register() fails in arm_acpi_register_pmu_device(), the embedded struct device has already been initialized by device_initialize() inside platform_device_register(). The error path unregisters the GSI interrupt but returns without dropping the device reference:

arm_acpi_register_pmu_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- acpi_unregister_gsi() called, but kref still 1

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() in the error branch before unregistering the GSI.

Fixes d24a0c7099b3 ("arm_pmu: acpi: spe: Add initial MADT/SPE probing")
Assisted-by GitHub Copilot (Claude Sonnet 4.5)
---
 drivers/perf/arm_pmu_acpi.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/perf/arm_pmu_acpi.c +0 -0
index e80f76d95e68..c2defbc32ad9 100644

drivers/perf/arm_pmu_acpi.c arm_acpi_register_pmu_device(struct platform_device *pdev, u8 len, · line 123

Quoted 6 lines
drivers/perf/arm_pmu_acpi.c +2 -1
@@ -119,8 +119,10 @@ arm_acpi_register_pmu_device(struct platform_device *pdev, u8 len,
 
 	pdev->resource[0].start = irq;
 	ret = platform_device_register(pdev);
-	if (ret)
+	if (ret) {
+		platform_device_put(pdev);

Both spe_dev and trbe_dev using this are statically allocated, what am I missing here ? What will platform_device_put() do ?

Signature · 2 lines
Regards,
Sudeep
#17 lore raw

Re: [PATCH 1/5] perf/arm_pmu_acpi: fix reference leak in arm_pmu_acpi_probe error path

In reply to Vastargazing

Yeah, you're right, my bad. The arm_pmu_acpi.c patch is definitely broken.

Since spe_dev and trbe_dev are statically allocated, they don't have a .dev.release callback. If we hit platform_device_put() here, the refcount drops to zero and triggers device_release(), which is going to scream about the missing release function. At best, we get a messy WARN; at worst, it'll panic the kernel if someone's running with panic_on_warn.

The kernel-doc note about platform_device_put() is really meant for dynamic allocations where the release path actually frees memory. For static setups like this, the original code is actually the right way to go.

Please drop patches 1/5 through 4/5 from the v1 series—they all suffer from the same logic error. Patch 5/5 (mfd: sm501) is the only clean one, so I've re-sent that as a standalone v2.

Sorry for the noise.

Valery Borovsky

maintainer
#12 lore raw

Re: [PATCH v2] mfd: sm501: fix reference leak on failed device registration

In reply to Miquel Raynal
Quoted 13 lines · Miquel Raynal
Quoted 12 lines · Valery Borovsky

When platform_device_register() fails in sm501_register_device(), the platform device allocated by sm501_create_subdev() has its struct device initialized by device_initialize() inside platform_device_register(). The error path logs the error but returns without dropping the device reference, leaking the memory allocated by sm501_create_subdev():

sm501_register_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- dev_err() called, kref still 1, sm501_device_release never called
Quoted 3 lines
Quoted 1 line

[...]

Applied to mtd/next, thanks!

I think you misread the subject line.

Quoted 5 lines

[1/1] mfd: sm501: fix reference leak on failed device registration

      commit: faa9bba3fe2f37e7dcb26d4501d890fbfd7df160

Patche(s) should be available on mtd/linux.git and will be part of the next PR (provided that no robot complains by then).

Please remove this from your tree. It should be handled via M[F]D.

Thanks.

Signature · 1 line
Lee Jones
maintainer
#13 lore raw

Re: [PATCH v2] mfd: sm501: fix reference leak on failed device registration

Hi Lee,

Quoted 21 lines · Lee Jones
Quoted 13 lines · Miquel Raynal
Quoted 12 lines · Valery Borovsky

When platform_device_register() fails in sm501_register_device(), the platform device allocated by sm501_create_subdev() has its struct device initialized by device_initialize() inside platform_device_register(). The error path logs the error but returns without dropping the device reference, leaking the memory allocated by sm501_create_subdev():

sm501_register_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- dev_err() called, kref still 1, sm501_device_release never called
Quoted 3 lines
Quoted 1 line

[...]

Applied to mtd/next, thanks!

I think you misread the subject line.

Quoted 7 lines
Quoted 5 lines

[1/1] mfd: sm501: fix reference leak on failed device registration

      commit: faa9bba3fe2f37e7dcb26d4501d890fbfd7df160

Patche(s) should be available on mtd/linux.git and will be part of the next PR (provided that no robot complains by then).

Please remove this from your tree. It should be handled via M[F]D.

Yes, it took a bit of time for me to receive my own answer so I replied to the original patch immediately stating that I dropped it. For some reason b4 applied this patch, whereas I was applying another m*t*d patch from apparently the same series (?). Both the contribution and b4 behaviour was strange.

Sorry for the noise.

Thanks,
Miquèl

#14 lore raw

PATCH v3 1/1 mfd: sm501: fix reference leak on failed device registration

In reply to Valery Borovsky

When platform_device_register() fails in sm501_register_device(), the platform device allocated by sm501_create_subdev() has its struct device initialized by device_initialize() inside platform_device_register(). The error path logs the error but returns without dropping the device reference, leaking the memory allocated by sm501_create_subdev():

sm501_register_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- dev_err() called, kref still 1, sm501_device_release never called

The device's release callback (sm501_device_release) calls kfree() on the containing sm501_device structure. Without platform_device_put(), this memory is never freed.

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() in the error branch, which triggers sm501_device_release() and frees the allocated memory.

Fixes b6d6454fdb66 ("[PATCH] mfd: SM501 core driver")
---
 drivers/mfd/sm501.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)
drivers/mfd/sm501.c +3 -1
index 0ee6d8940e69..8276456b142f 100644
@@ -704,9 +704,11 @@ static int sm501_register_device(struct sm501_devdata *sm,
 	if (ret >= 0) {
 		dev_dbg(sm->dev, "registered %s\n", pdev->name);
 		list_add_tail(&smdev->list, &sm->devices);
-	} else
+	} else {
 		dev_err(sm->dev, "error registering %s (%d)\n",
 			pdev->name, ret);
+		platform_device_put(pdev);
+	}
 
 	return ret;
 }
Signature · 1 line
2.51.0
#18 lore raw

Re: [PATCH 3/5] mtd: maps: physmap-core: fix reference leak on failed device registration

In reply to Vastargazing

Hi Miquel,

Thanks for the review. I need to withdraw this patch as well, for the same reason as the rest of the series.

physmap_flash is a static platform_device without a .dev.release callback. Using platform_device_put() triggers a WARN in device_release() when the kref hits zero, which is a dealbreaker for systems with panic_on_warn=1.

The kernel-doc NOTE refers to dynamically allocated devices; for static ones, the original code is actually correct.

I've already sent a withdrawal notice for the whole series (1/5-4/5) to the cover letter thread. Sorry for the noise.

Best,
Valery Borovsky

maintainer
#15 lore raw

Re: [PATCH v3] mfd: sm501: fix reference leak on failed device registration

In reply to Valery Borovsky
Quoted 25 lines · Valery Borovsky

When platform_device_register() fails in sm501_register_device(), the platform device allocated by sm501_create_subdev() has its struct device initialized by device_initialize() inside platform_device_register(). The error path logs the error but returns without dropping the device reference, leaking the memory allocated by sm501_create_subdev():

sm501_register_device()

    -> platform_device_register(pdev)
       -> device_initialize(&pdev->dev)   /* kref = 1 */
       -> platform_device_add(pdev)       /* fails */
    <- dev_err() called, kref still 1, sm501_device_release never called

The device's release callback (sm501_device_release) calls kfree() on the containing sm501_device structure. Without platform_device_put(), this memory is never freed.

Per platform_device_register() kernel-doc:

NOTE: _Never_ directly free @pdev after calling this function, even if it returned an error! Always use platform_device_put() to give up the reference initialised in this function instead.

Fix this by calling platform_device_put() in the error branch, which triggers sm501_device_release() and frees the allocated memory.

Quoted 6 lines
Fixes b6d6454fdb66 ("[PATCH] mfd: SM501 core driver")
---
 drivers/mfd/sm501.c | 4 +++-
 1 file changed, 3 insertions(+), 1 deletion(-)

I don't see a message from me acknowledging this, but it is applied to my tree.

Signature · 1 line
Lee Jones
#16 lore raw

Re: [PATCH v3] mfd: sm501: fix reference leak on failed device registration

In reply to Valery Borovsky

Hi Lee,

Great, thanks for picking it up — confirmed on my end.

For context: an earlier version of this patch ended up briefly in mtd/next by accident (Miquel applied it to the wrong tree, then dropped it), so I appreciate you taking it directly into MFD.

Best,
Valery