aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/spi/spi.c
diff options
context:
space:
mode:
authorYang Yingliang <yangyingliang@huawei.com>2022-07-12 21:55:04 +0800
committerMark Brown <broonie@kernel.org>2022-07-13 13:49:02 +0100
commit43cc5a0afe4184a7fafe1eba32b5a11bb69c9ce0 (patch)
tree2b8b11523c75916c3149759489b24352b2c33c30 /drivers/spi/spi.c
parentspi: remove duplicate parameters check in acpi_spi_add_resource() (diff)
downloadlinux-dev-43cc5a0afe4184a7fafe1eba32b5a11bb69c9ce0.tar.xz
linux-dev-43cc5a0afe4184a7fafe1eba32b5a11bb69c9ce0.zip
spi: Fix simplification of devm_spi_register_controller
This reverts commit 59ebbe40fb51 ("spi: simplify devm_spi_register_controller"). If devm_add_action() fails in devm_add_action_or_reset(), devm_spi_unregister() will be called, it decreases the refcount of 'ctlr->dev' to 0, then it will cause uaf in the drivers that calling spi_put_controller() in error path. Fixes: 59ebbe40fb51 ("spi: simplify devm_spi_register_controller") Signed-off-by: Yang Yingliang <yangyingliang@huawei.com> Reviewed-by: Conor Dooley <conor.dooley@microchip.com> Link: https://lore.kernel.org/r/20220712135504.1055688-1-yangyingliang@huawei.com Signed-off-by: Mark Brown <broonie@kernel.org>
Diffstat (limited to 'drivers/spi/spi.c')
-rw-r--r--drivers/spi/spi.c19
1 files changed, 14 insertions, 5 deletions
diff --git a/drivers/spi/spi.c b/drivers/spi/spi.c
index 562d6441c7fd..1c14d682ffed 100644
--- a/drivers/spi/spi.c
+++ b/drivers/spi/spi.c
@@ -3132,9 +3132,9 @@ free_bus_id:
}
EXPORT_SYMBOL_GPL(spi_register_controller);
-static void devm_spi_unregister(void *ctlr)
+static void devm_spi_unregister(struct device *dev, void *res)
{
- spi_unregister_controller(ctlr);
+ spi_unregister_controller(*(struct spi_controller **)res);
}
/**
@@ -3153,13 +3153,22 @@ static void devm_spi_unregister(void *ctlr)
int devm_spi_register_controller(struct device *dev,
struct spi_controller *ctlr)
{
+ struct spi_controller **ptr;
int ret;
+ ptr = devres_alloc(devm_spi_unregister, sizeof(*ptr), GFP_KERNEL);
+ if (!ptr)
+ return -ENOMEM;
+
ret = spi_register_controller(ctlr);
- if (ret)
- return ret;
+ if (!ret) {
+ *ptr = ctlr;
+ devres_add(dev, ptr);
+ } else {
+ devres_free(ptr);
+ }
- return devm_add_action_or_reset(dev, devm_spi_unregister, ctlr);
+ return ret;
}
EXPORT_SYMBOL_GPL(devm_spi_register_controller);