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

Configure Feed

Select the types of activity you want to include in your feed.

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: 466a62d7642f ("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>

authored by

Douglas Anderson and committed by
Lee Jones
20117c92 a71fee84

+22 -14
+22 -14
drivers/mfd/mfd-core.c
··· 22 22 #include <linux/regulator/consumer.h> 23 23 24 24 static LIST_HEAD(mfd_of_node_list); 25 + static DEFINE_MUTEX(mfd_of_node_mutex); 25 26 26 27 struct mfd_of_node_entry { 27 28 struct list_head list; ··· 105 104 u64 of_node_addr; 106 105 107 106 /* Skip if OF node has previously been allocated to a device */ 108 - list_for_each_entry(of_entry, &mfd_of_node_list, list) 109 - if (of_entry->np == np) 110 - return -EAGAIN; 107 + scoped_guard(mutex, &mfd_of_node_mutex) { 108 + list_for_each_entry(of_entry, &mfd_of_node_list, list) 109 + if (of_entry->np == np) 110 + return -EAGAIN; 111 + } 111 112 112 113 if (!cell->use_of_reg) 113 114 /* No of_reg defined - allocate first free compatible match */ ··· 131 128 132 129 of_entry->dev = &pdev->dev; 133 130 of_entry->np = np; 134 - list_add_tail(&of_entry->list, &mfd_of_node_list); 131 + scoped_guard(mutex, &mfd_of_node_mutex) 132 + list_add_tail(&of_entry->list, &mfd_of_node_list); 135 133 136 134 of_node_get(np); 137 135 device_set_node(&pdev->dev, of_fwnode_handle(np)); ··· 288 284 if (cell->swnode) 289 285 device_remove_software_node(&pdev->dev); 290 286 fail_of_entry: 291 - list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) 292 - if (of_entry->dev == &pdev->dev) { 293 - list_del(&of_entry->list); 294 - kfree(of_entry); 295 - } 287 + scoped_guard(mutex, &mfd_of_node_mutex) { 288 + list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) 289 + if (of_entry->dev == &pdev->dev) { 290 + list_del(&of_entry->list); 291 + kfree(of_entry); 292 + } 293 + } 296 294 fail_alias: 297 295 regulator_bulk_unregister_supply_alias(&pdev->dev, 298 296 cell->parent_supplies, ··· 364 358 if (cell->swnode) 365 359 device_remove_software_node(&pdev->dev); 366 360 367 - list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) 368 - if (of_entry->dev == &pdev->dev) { 369 - list_del(&of_entry->list); 370 - kfree(of_entry); 371 - } 361 + scoped_guard(mutex, &mfd_of_node_mutex) { 362 + list_for_each_entry_safe(of_entry, tmp, &mfd_of_node_list, list) 363 + if (of_entry->dev == &pdev->dev) { 364 + list_del(&of_entry->list); 365 + kfree(of_entry); 366 + } 367 + } 372 368 373 369 regulator_bulk_unregister_supply_alias(dev, cell->parent_supplies, 374 370 cell->num_parent_supplies);