Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

fsi: Aspeed: Fix a potential double free

A struct device can never be devm_alloc()'ed.
Here, it is embedded in "struct fsi_master", and "struct fsi_master" is
embedded in "struct fsi_master_aspeed".

Since "struct device" is embedded, the data structure embedding it must be
released with the release function, as is already done here.

So use kzalloc() instead of devm_kzalloc() when allocating "aspeed" and
update all error handling branches accordingly.

This prevent a potential double free().

This also fix another issue if opb_readl() fails. Instead of a direct
return, it now jumps in the error handling path.

Fixes: 606397d67f41 ("fsi: Add ast2600 master driver")
Suggested-by: Greg KH <gregkh@linuxfoundation.org>
Suggested-by: Guenter Roeck <linux@roeck-us.net>
Reviewed-by: Guenter Roeck <linux@roeck-us.net>
Signed-off-by: Christophe JAILLET <christophe.jaillet@wanadoo.fr>
Link: https://lore.kernel.org/r/2c123f8b0a40dc1a061fae982169fe030b4f47e6.1641765339.git.christophe.jaillet@wanadoo.fr
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Christophe JAILLET and committed by
Greg Kroah-Hartman
83ba7e89 aafce7bc

+11 -6
+11 -6
drivers/fsi/fsi-master-aspeed.c
··· 542 542 return rc; 543 543 } 544 544 545 - aspeed = devm_kzalloc(&pdev->dev, sizeof(*aspeed), GFP_KERNEL); 545 + aspeed = kzalloc(sizeof(*aspeed), GFP_KERNEL); 546 546 if (!aspeed) 547 547 return -ENOMEM; 548 548 549 549 aspeed->dev = &pdev->dev; 550 550 551 551 aspeed->base = devm_platform_ioremap_resource(pdev, 0); 552 - if (IS_ERR(aspeed->base)) 553 - return PTR_ERR(aspeed->base); 552 + if (IS_ERR(aspeed->base)) { 553 + rc = PTR_ERR(aspeed->base); 554 + goto err_free_aspeed; 555 + } 554 556 555 557 aspeed->clk = devm_clk_get(aspeed->dev, NULL); 556 558 if (IS_ERR(aspeed->clk)) { 557 559 dev_err(aspeed->dev, "couldn't get clock\n"); 558 - return PTR_ERR(aspeed->clk); 560 + rc = PTR_ERR(aspeed->clk); 561 + goto err_free_aspeed; 559 562 } 560 563 rc = clk_prepare_enable(aspeed->clk); 561 564 if (rc) { 562 565 dev_err(aspeed->dev, "couldn't enable clock\n"); 563 - return rc; 566 + goto err_free_aspeed; 564 567 } 565 568 566 569 rc = setup_cfam_reset(aspeed); ··· 598 595 rc = opb_readl(aspeed, ctrl_base + FSI_MVER, &raw); 599 596 if (rc) { 600 597 dev_err(&pdev->dev, "failed to read hub version\n"); 601 - return rc; 598 + goto err_release; 602 599 } 603 600 604 601 reg = be32_to_cpu(raw); ··· 637 634 638 635 err_release: 639 636 clk_disable_unprepare(aspeed->clk); 637 + err_free_aspeed: 638 + kfree(aspeed); 640 639 return rc; 641 640 } 642 641