mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
synced 2026-07-16 11:05:53 -04:00
spi: fix use-after-free on managed registration failure
The SPI API is asymmetric and the controller is freed as part of deregistration (unless it has been allocated using devm_spi_alloc_host/target()). A recent change converting the managed registration function to use devm_add_action_or_reset() inadvertently introduced a (mostly theoretical) regression where a non-devres managed controller could be freed as part of failed registration. This in turn would lead to use-after-free in controller driver error paths. Fix this by taking another reference before calling devm_add_action_or_reset() and not releasing it on errors for non-devres allocated controllers. An alternative would be a partial revert of the offending commit, but it is better to handle this explicitly until the API has been fixed (e.g. see5e844cc37a("spi: Introduce device-managed SPI controller allocation")). Fixes:b6376dbed8("spi: Simplify devm_spi_*_controller()") Reported-by: Felix Gu <ustc.gu@gmail.com> Link: https://lore.kernel.org/all/20260324145548.139952-1-ustc.gu@gmail.com/ Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Signed-off-by: Johan Hovold <johan@kernel.org> Acked-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com> Link: https://patch.msgid.link/20260325145319.1132072-1-johan@kernel.org Signed-off-by: Mark Brown <broonie@kernel.org>
This commit is contained in:
@@ -3534,8 +3534,19 @@ int devm_spi_register_controller(struct device *dev,
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
return devm_add_action_or_reset(dev, devm_spi_unregister_controller, ctlr);
|
||||
/*
|
||||
* Prevent controller from being freed by spi_unregister_controller()
|
||||
* if devm_add_action_or_reset() fails for a non-devres allocated
|
||||
* controller.
|
||||
*/
|
||||
spi_controller_get(ctlr);
|
||||
|
||||
ret = devm_add_action_or_reset(dev, devm_spi_unregister_controller, ctlr);
|
||||
|
||||
if (ret == 0 || ctlr->devm_allocated)
|
||||
spi_controller_put(ctlr);
|
||||
|
||||
return ret;
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(devm_spi_register_controller);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user