Skip to contentSkip to conversation

powercap: fix race condition in register_control_type

PATCH Applied Sumeet Pawnikar 2 participants 2 messages Dec 5, 2025 – Dec 15, 2025 Power management core

lore
Share & tools
lore
#0 lore raw

PATCH 1/1 powercap: fix race condition in register_control_type

The device becomes visible to userspace via device_register() even before it fully initialized by idr_init(). If userspace or another thread tries to register a zone immediately after device_register(), the control_type_valid() will fail because the control_type is not yet in the list. The IDR is not yet initialized, so this race condition causes zone registration failure.

Move idr_init() and list addition before device_register() fix the race condition.

---
 drivers/powercap/powercap_sys.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)
drivers/powercap/powercap_sys.c +10 -5
index 4112a0097338..bdc65e040d17 100644
@@ -625,17 +625,22 @@ struct powercap_control_type *powercap_register_control_type(
 	INIT_LIST_HEAD(&control_type->node);
 	control_type->dev.class = &powercap_class;
 	dev_set_name(&control_type->dev, "%s", name);
-	result = device_register(&control_type->dev);
-	if (result) {
-		put_device(&control_type->dev);
-		return ERR_PTR(result);
-	}
 	idr_init(&control_type->idr);
 
 	mutex_lock(&powercap_cntrl_list_lock);
 	list_add_tail(&control_type->node, &powercap_cntrl_list);
 	mutex_unlock(&powercap_cntrl_list_lock);
 
+	result = device_register(&control_type->dev);
+	if (result) {
+		mutex_lock(&powercap_cntrl_list_lock);
+		list_del(&control_type->node);
+		mutex_unlock(&powercap_cntrl_list_lock);
+		idr_destroy(&control_type->idr);
+		put_device(&control_type->dev);
+		return ERR_PTR(result);
+	}
+
 	return control_type;
 }
 EXPORT_SYMBOL_GPL(powercap_register_control_type);
Signature · 1 line
2.43.0
maintainer Applied
#1 lore raw
Quoted 40 lines · Sumeet Pawnikar

The device becomes visible to userspace via device_register() even before it fully initialized by idr_init(). If userspace or another thread tries to register a zone immediately after device_register(), the control_type_valid() will fail because the control_type is not yet in the list. The IDR is not yet initialized, so this race condition causes zone registration failure.

Move idr_init() and list addition before device_register() fix the race condition.

---
 drivers/powercap/powercap_sys.c | 15 ++++++++++-----
 1 file changed, 10 insertions(+), 5 deletions(-)
drivers/powercap/powercap_sys.c +4 -5
index 4112a0097338..bdc65e040d17 100644
@@ -625,17 +625,22 @@ struct powercap_control_type *powercap_register_control_type(
        INIT_LIST_HEAD(&control_type->node);
        control_type->dev.class = &powercap_class;
        dev_set_name(&control_type->dev, "%s", name);
-       result = device_register(&control_type->dev);
-       if (result) {
-               put_device(&control_type->dev);
-               return ERR_PTR(result);
-       }
        idr_init(&control_type->idr);
 
        mutex_lock(&powercap_cntrl_list_lock);
        list_add_tail(&control_type->node, &powercap_cntrl_list);
        mutex_unlock(&powercap_cntrl_list_lock);
 
+       result = device_register(&control_type->dev);
+       if (result) {
+               mutex_lock(&powercap_cntrl_list_lock);
+               list_del(&control_type->node);

drivers/powercap/powercap_sys.c struct powercap_control_type *powercap_register_control_type(

Quoted 10 lines
drivers/powercap/powercap_sys.c +6 -1
+               mutex_unlock(&powercap_cntrl_list_lock);
+               idr_destroy(&control_type->idr);
+               put_device(&control_type->dev);
+               return ERR_PTR(result);
+       }
+
        return control_type;
 }
 EXPORT_SYMBOL_GPL(powercap_register_control_type);
--

Applied as 6.19-rc material, thanks!