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

software node: Handle software node injection to an existing device properly

The function software_node_notify() - the function that creates
and removes the symlinks between the node and the device - was
called unconditionally in device_add_software_node() and
device_remove_software_node(), but it needs to be called in
those functions only in the special case where the node is
added to a device that has already been registered.

This fixes NULL pointer dereference that happens if
device_remove_software_node() is used with device that was
never registered.

Fixes: b622b24519f5 ("software node: Allow node addition to already existing device")
Reported-and-tested-by: Dominik Brodowski <linux@dominikbrodowski.net>
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Heikki Krogerus <heikki.krogerus@linux.intel.com>
Signed-off-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>

authored by

Heikki Krogerus and committed by
Rafael J. Wysocki
5dca69e2 13311e74

+12 -4
+12 -4
drivers/base/swnode.c
··· 1045 1045 } 1046 1046 1047 1047 set_secondary_fwnode(dev, &swnode->fwnode); 1048 - software_node_notify(dev, KOBJ_ADD); 1048 + 1049 + /* 1050 + * If the device has been fully registered by the time this function is 1051 + * called, software_node_notify() must be called separately so that the 1052 + * symlinks get created and the reference count of the node is kept in 1053 + * balance. 1054 + */ 1055 + if (device_is_registered(dev)) 1056 + software_node_notify(dev, KOBJ_ADD); 1049 1057 1050 1058 return 0; 1051 1059 } ··· 1073 1065 if (!swnode) 1074 1066 return; 1075 1067 1076 - software_node_notify(dev, KOBJ_REMOVE); 1068 + if (device_is_registered(dev)) 1069 + software_node_notify(dev, KOBJ_REMOVE); 1077 1070 set_secondary_fwnode(dev, NULL); 1078 1071 kobject_put(&swnode->kobj); 1079 1072 } ··· 1128 1119 1129 1120 switch (action) { 1130 1121 case KOBJ_ADD: 1131 - ret = sysfs_create_link_nowarn(&dev->kobj, &swnode->kobj, 1132 - "software_node"); 1122 + ret = sysfs_create_link(&dev->kobj, &swnode->kobj, "software_node"); 1133 1123 if (ret) 1134 1124 break; 1135 1125