Skip to contentSkip to conversation

FAILED: patch "[PATCH] smp/hotplug: Handle removal correctly in" failed to apply to 4.9-stable tree

PATCH [email protected] 1 participant 1 message Sep 20, 2017

Subsystems (2)
lore
Share & tools
lore

[email protected]

author maintainer
#0 lore raw

The patch below does not apply to the 4.9-stable tree.
If someone wants it applied there, or to any other stable or longterm tree, then please email the backport, including the original git commit id to <[email protected]>.

thanks,

greg k-h

------------------ original commit in Linus's tree ------------------

Quoted 1 line

From 0c96b27305faf06c068b45e07d28336c80dac286 Mon Sep 17 00:00:00 2001

From: Ethan Barnes <[email protected]>
Date: Wed, 19 Jul 2017 22:36:00 +0000
Subject: [PATCH] smp/hotplug: Handle removal correctly in
cpuhp_store_callbacks()

If cpuhp_store_callbacks() is called for CPUHP_AP_ONLINE_DYN or CPUHP_BP_PREPARE_DYN, which are the indicators for dynamically allocated states, then cpuhp_store_callbacks() allocates a new dynamic state. The first allocation in each range returns CPUHP_AP_ONLINE_DYN or CPUHP_BP_PREPARE_DYN.

If cpuhp_remove_state() is invoked for one of these states, then there is no protection against the allocation mechanism. So the removal, which should clear the callbacks and the name, gets a new state assigned and clears that one.

As a consequence the state which should be cleared stays initialized. A consecutive CPU hotplug operation dereferences the state callbacks and accesses either freed or reused memory, resulting in crashes.

Add a protection against this by checking the name argument for NULL. If it's NULL it's a removal. If not, it's an allocation.

[ tglx: Added a comment and massaged changelog ]

Fixes 5b7aa87e0482 ("cpu/hotplug: Implement setup/removal interface")
Cc Ingo Molnar <[email protected]>
Cc "Srivatsa S. Bhat" <[email protected]>
Cc Sebastian Siewior <[email protected]>
Cc Paul McKenney <[email protected]>
kernel/cpu.c +11 -1
index eee033134262..a88c29ab09be 100644
@@ -1252,7 +1252,17 @@ static int cpuhp_store_callbacks(enum cpuhp_state state, const char *name,
 	struct cpuhp_step *sp;
 	int ret = 0;
 
-	if (state == CPUHP_AP_ONLINE_DYN || state == CPUHP_BP_PREPARE_DYN) {
+	/*
+	 * If name is NULL, then the state gets removed.
+	 *
+	 * CPUHP_AP_ONLINE_DYN and CPUHP_BP_PREPARE_DYN are handed out on
+	 * the first allocation from these dynamic ranges, so the removal
+	 * would trigger a new allocation and clear the wrong (already
+	 * empty) state, leaving the callbacks of the to be cleared state
+	 * dangling, which causes wreckage on the next hotplug operation.
+	 */
+	if (name && (state == CPUHP_AP_ONLINE_DYN ||
+		     state == CPUHP_BP_PREPARE_DYN)) {
 		ret = cpuhp_reserve_state(state);
 		if (ret < 0)
 			return ret;