mirror of
https://github.com/torvalds/linux.git
synced 2026-05-29 17:43:52 +02:00
mfd: core: Add locking around 'mfd_of_node_list'
Manipulating a list in the kernel isn't safe without some sort of
mutual exclusion. Add a mutex any time we access / modify
'mfd_of_node_list' to prevent possible crashes.
Cc: stable@vger.kernel.org
Fixes: 466a62d764 ("mfd: core: Make a best effort attempt to match devices with the correct of_nodes")
Signed-off-by: Douglas Anderson <dianders@chromium.org>
Link: https://patch.msgid.link/20251210113002.1.I6ceaca2cfb7eb25737012b166671f516696be4fd@changeid
Signed-off-by: Lee Jones <lee@kernel.org>
This commit is contained in:
parent
a71fee8421
commit
20117c92bc
|
|
@ -22,6 +22,7 @@
|
|||
#include <linux/regulator/consumer.h>
|
||||
|
||||
static LIST_HEAD(mfd_of_node_list);
|
||||
static DEFINE_MUTEX(mfd_of_node_mutex);
|
||||
|
||||
struct mfd_of_node_entry {
|
||||
struct list_head list;
|
||||
|
|
@ -104,9 +105,11 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
|
|||
u64 of_node_addr;
|
||||
|
||||
/* Skip if OF node has previously been allocated to a device */
|
||||
list_for_each_entry(of_entry, &mfd_of_node_list, list)
|
||||
if (of_entry->np == np)
|
||||
return -EAGAIN;
|
||||
scoped_guard(mutex, &mfd_of_node_mutex) {
|
||||
list_for_each_entry(of_entry, &mfd_of_node_list, list)
|
||||
if (of_entry->np == np)
|
||||
return -EAGAIN;
|
||||
}
|
||||
|
||||
if (!cell->use_of_reg)
|
||||
/* No of_reg defined - allocate first free compatible match */
|
||||
|
|
@ -128,7 +131,8 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
|
|||
|
||||
of_entry->dev = &pdev->dev;
|
||||
of_entry->np = np;
|
||||
list_add_tail(&of_entry->list, &mfd_of_node_list);
|
||||
scoped_guard(mutex, &mfd_of_node_mutex)
|
||||
list_add_tail(&of_entry->list, &mfd_of_node_list);
|
||||
|
||||
of_node_get(np);
|
||||
device_set_node(&pdev->dev, of_fwnode_handle(np));
|
||||
|
|
@ -284,11 +288,13 @@ static int mfd_add_device(struct device *parent, int id,
|
|||
if (cell->swnode)
|
||||
device_remove_software_node(&pdev->dev);
|
||||
fail_of_entry:
|
||||
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
|
||||
if (of_entry->dev == &pdev->dev) {
|
||||
list_del(&of_entry->list);
|
||||
kfree(of_entry);
|
||||
}
|
||||
scoped_guard(mutex, &mfd_of_node_mutex) {
|
||||
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
|
||||
if (of_entry->dev == &pdev->dev) {
|
||||
list_del(&of_entry->list);
|
||||
kfree(of_entry);
|
||||
}
|
||||
}
|
||||
fail_alias:
|
||||
regulator_bulk_unregister_supply_alias(&pdev->dev,
|
||||
cell->parent_supplies,
|
||||
|
|
@ -358,11 +364,13 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
|
|||
if (cell->swnode)
|
||||
device_remove_software_node(&pdev->dev);
|
||||
|
||||
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
|
||||
if (of_entry->dev == &pdev->dev) {
|
||||
list_del(&of_entry->list);
|
||||
kfree(of_entry);
|
||||
}
|
||||
scoped_guard(mutex, &mfd_of_node_mutex) {
|
||||
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
|
||||
if (of_entry->dev == &pdev->dev) {
|
||||
list_del(&of_entry->list);
|
||||
kfree(of_entry);
|
||||
}
|
||||
}
|
||||
|
||||
regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
|
||||
cell->num_parent_supplies);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user