Skip to content
/ linux Public

Commit dcfa679

Browse files
diandersSasha Levin
authored andcommitted
mfd: core: Add locking around 'mfd_of_node_list'
[ Upstream commit 20117c9 ] 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: 466a62d ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent ead67d0 commit dcfa679

File tree

1 file changed

+22
-14
lines changed

1 file changed

+22
-14
lines changed

drivers/mfd/mfd-core.c

Lines changed: 22 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
#include <linux/regulator/consumer.h>
2323

2424
static LIST_HEAD(mfd_of_node_list);
25+
static DEFINE_MUTEX(mfd_of_node_mutex);
2526

2627
struct mfd_of_node_entry {
2728
struct list_head list;
@@ -132,9 +133,11 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
132133
u64 of_node_addr;
133134

134135
/* Skip if OF node has previously been allocated to a device */
135-
list_for_each_entry(of_entry, &mfd_of_node_list, list)
136-
if (of_entry->np == np)
137-
return -EAGAIN;
136+
scoped_guard(mutex, &mfd_of_node_mutex) {
137+
list_for_each_entry(of_entry, &mfd_of_node_list, list)
138+
if (of_entry->np == np)
139+
return -EAGAIN;
140+
}
138141

139142
if (!cell->use_of_reg)
140143
/* No of_reg defined - allocate first free compatible match */
@@ -159,7 +162,8 @@ static int mfd_match_of_node_to_dev(struct platform_device *pdev,
159162

160163
of_entry->dev = &pdev->dev;
161164
of_entry->np = np;
162-
list_add_tail(&of_entry->list, &mfd_of_node_list);
165+
scoped_guard(mutex, &mfd_of_node_mutex)
166+
list_add_tail(&of_entry->list, &mfd_of_node_list);
163167

164168
pdev->dev.of_node = np;
165169
pdev->dev.fwnode = &np->fwnode;
@@ -316,11 +320,13 @@ static int mfd_add_device(struct device *parent, int id,
316320
if (cell->swnode)
317321
device_remove_software_node(&pdev->dev);
318322
fail_of_entry:
319-
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
320-
if (of_entry->dev == &pdev->dev) {
321-
list_del(&of_entry->list);
322-
kfree(of_entry);
323-
}
323+
scoped_guard(mutex, &mfd_of_node_mutex) {
324+
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
325+
if (of_entry->dev == &pdev->dev) {
326+
list_del(&of_entry->list);
327+
kfree(of_entry);
328+
}
329+
}
324330
fail_alias:
325331
regulator_bulk_unregister_supply_alias(&pdev->dev,
326332
cell->parent_supplies,
@@ -390,11 +396,13 @@ static int mfd_remove_devices_fn(struct device *dev, void *data)
390396
if (cell->swnode)
391397
device_remove_software_node(&pdev->dev);
392398

393-
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
394-
if (of_entry->dev == &pdev->dev) {
395-
list_del(&of_entry->list);
396-
kfree(of_entry);
397-
}
399+
scoped_guard(mutex, &mfd_of_node_mutex) {
400+
list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list)
401+
if (of_entry->dev == &pdev->dev) {
402+
list_del(&of_entry->list);
403+
kfree(of_entry);
404+
}
405+
}
398406

399407
regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies,
400408
cell->num_parent_supplies);

0 commit comments

Comments
 (0)