Developers manage to overwrite states blindly without thought. That's fatal
and hard to debug. Add sanity checks to make it fail.

Signed-off-by: Thomas Gleixner <t...@linutronix.de>
---
 kernel/cpu.c |   33 +++++++++++++++++++++------------
 1 file changed, 21 insertions(+), 12 deletions(-)

--- a/kernel/cpu.c
+++ b/kernel/cpu.c
@@ -1432,23 +1432,29 @@ static int cpuhp_cb_check(enum cpuhp_sta
        return 0;
 }
 
-static void cpuhp_store_callbacks(enum cpuhp_state state,
-                                 const char *name,
-                                 int (*startup)(unsigned int cpu),
-                                 int (*teardown)(unsigned int cpu),
-                                 bool multi_instance)
+static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
+                                int (*startup)(unsigned int cpu),
+                                int (*teardown)(unsigned int cpu),
+                                bool multi_instance)
 {
        /* (Un)Install the callbacks for further cpu hotplug operations */
        struct cpuhp_step *sp;
+       int ret = 0;
 
        mutex_lock(&cpuhp_state_mutex);
        sp = cpuhp_get_step(state);
+       if (name && sp->name) {
+               ret = -EBUSY;
+               goto out;
+       }
        sp->startup.single = startup;
        sp->teardown.single = teardown;
        sp->name = name;
        sp->multi_instance = multi_instance;
        INIT_HLIST_HEAD(&sp->list);
+out:
        mutex_unlock(&cpuhp_state_mutex);
+       return ret;
 }
 
 static void *cpuhp_get_teardown_cb(enum cpuhp_state state)
@@ -1580,11 +1586,13 @@ EXPORT_SYMBOL_GPL(__cpuhp_state_add_inst
 
 /**
  * __cpuhp_setup_state - Setup the callbacks for an hotplug machine state
- * @state:     The state to setup
- * @invoke:    If true, the startup function is invoked for cpus where
- *             cpu state >= @state
- * @startup:   startup callback function
- * @teardown:  teardown callback function
+ * @state:             The state to setup
+ * @invoke:            If true, the startup function is invoked for cpus where
+ *                     cpu state >= @state
+ * @startup:           startup callback function
+ * @teardown:          teardown callback function
+ * @multi_instance:    State is set up for multiple instances which get
+ *                     added afterwards.
  *
  * Returns:
  *   On success:
@@ -1615,9 +1623,10 @@ int __cpuhp_setup_state(enum cpuhp_state
                state = ret;
        }
 
-       cpuhp_store_callbacks(state, name, startup, teardown, multi_instance);
+       ret = cpuhp_store_callbacks(state, name, startup, teardown,
+                                   multi_instance);
 
-       if (!invoke || !startup)
+       if (ret || !invoke || !startup)
                goto out;
 
        /*


Reply via email to