fsi_master_aspeed_probe() allocates aspeed and passes its embedded
master device to fsi_master_register().
After the master index is allocated, fsi_master_register() calls
device_register(), which initializes master.dev and takes its initial
reference. If device registration fails, the reference remains held
when fsi_master_register() returns an error.
The probe error path then calls kfree(aspeed) directly without dropping
the device reference. This leaves the initialized master.dev reference
stranded and bypasses aspeed_master_release().
Disable the clock and call put_device() when registration fails after
the master index has been allocated. Keep the direct kfree() path for
failures that occur before master.dev is initialized.
This issue was found by a static analysis tool I am developing.
Fixes: 606397d67f41 ("fsi: Add ast2600 master driver")
Signed-off-by: Guangshuo Li <lgs201920130244@gmail.com>
---
drivers/fsi/fsi-master-aspeed.c | 12 ++++++++++--
1 file changed, 10 insertions(+), 2 deletions(-)
diff --git a/drivers/fsi/fsi-master-aspeed.c b/drivers/fsi/fsi-master-aspeed.c
index aa1380cdff33..2a54b6fa3394 100644
--- a/drivers/fsi/fsi-master-aspeed.c
+++ b/drivers/fsi/fsi-master-aspeed.c
@@ -626,8 +626,12 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
aspeed_master_init(aspeed);
rc = fsi_master_register(&aspeed->master);
- if (rc)
- goto err_release;
+ if (rc) {
+ if (aspeed->master.idx < 0)
+ goto err_release;
+
+ goto err_put_master;
+ }
/* At this point, fsi_master_register performs the device_initialize(),
* and holds the sole reference on master.dev. This means the device
@@ -638,6 +642,10 @@ static int fsi_master_aspeed_probe(struct platform_device *pdev)
*/
get_device(&aspeed->master.dev);
return 0;
+err_put_master:
+ clk_disable_unprepare(aspeed->clk);
+ put_device(&aspeed->master.dev);
+ return rc;
err_release:
clk_disable_unprepare(aspeed->clk);
--
2.43.0