Skip to content

Commit 3c2214b

Browse files
danieljordan10herbertx
authored andcommitted
padata: add separate cpuhp node for CPUHP_PADATA_DEAD
Removing the pcrypt module triggers this: general protection fault, probably for non-canonical address 0xdead000000000122 CPU: 5 PID: 264 Comm: modprobe Not tainted 5.6.0+ STMicroelectronics#2 Hardware name: QEMU Standard PC RIP: 0010:__cpuhp_state_remove_instance+0xcc/0x120 Call Trace: padata_sysfs_release+0x74/0xce kobject_put+0x81/0xd0 padata_free+0x12/0x20 pcrypt_exit+0x43/0x8ee [pcrypt] padata instances wrongly use the same hlist node for the online and dead states, so __padata_free()'s second cpuhp remove call chokes on the node that the first poisoned. cpuhp multi-instance callbacks only walk forward in cpuhp_step->list and the same node is linked in both the online and dead lists, so the list corruption that results from padata_alloc() adding the node to a second list without removing it from the first doesn't cause problems as long as no instances are freed. Avoid the issue by giving each state its own node. Fixes: 894c9ef ("padata: validate cpumask without removed CPU during offline") Signed-off-by: Daniel Jordan <daniel.m.jordan@oracle.com> Cc: Herbert Xu <herbert@gondor.apana.org.au> Cc: Steffen Klassert <steffen.klassert@secunet.com> Cc: linux-crypto@vger.kernel.org Cc: linux-kernel@vger.kernel.org Cc: stable@vger.kernel.org # v5.4+ Signed-off-by: Herbert Xu <herbert@gondor.apana.org.au>
1 parent b2d7e8b commit 3c2214b

2 files changed

Lines changed: 12 additions & 8 deletions

File tree

include/linux/padata.h

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -139,7 +139,8 @@ struct padata_shell {
139139
/**
140140
* struct padata_instance - The overall control structure.
141141
*
142-
* @node: Used by CPU hotplug.
142+
* @cpu_online_node: Linkage for CPU online callback.
143+
* @cpu_dead_node: Linkage for CPU offline callback.
143144
* @parallel_wq: The workqueue used for parallel work.
144145
* @serial_wq: The workqueue used for serial work.
145146
* @pslist: List of padata_shell objects attached to this instance.
@@ -150,7 +151,8 @@ struct padata_shell {
150151
* @flags: padata flags.
151152
*/
152153
struct padata_instance {
153-
struct hlist_node node;
154+
struct hlist_node cpu_online_node;
155+
struct hlist_node cpu_dead_node;
154156
struct workqueue_struct *parallel_wq;
155157
struct workqueue_struct *serial_wq;
156158
struct list_head pslist;

kernel/padata.c

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -703,7 +703,7 @@ static int padata_cpu_online(unsigned int cpu, struct hlist_node *node)
703703
struct padata_instance *pinst;
704704
int ret;
705705

706-
pinst = hlist_entry_safe(node, struct padata_instance, node);
706+
pinst = hlist_entry_safe(node, struct padata_instance, cpu_online_node);
707707
if (!pinst_has_cpu(pinst, cpu))
708708
return 0;
709709

@@ -718,7 +718,7 @@ static int padata_cpu_dead(unsigned int cpu, struct hlist_node *node)
718718
struct padata_instance *pinst;
719719
int ret;
720720

721-
pinst = hlist_entry_safe(node, struct padata_instance, node);
721+
pinst = hlist_entry_safe(node, struct padata_instance, cpu_dead_node);
722722
if (!pinst_has_cpu(pinst, cpu))
723723
return 0;
724724

@@ -734,8 +734,9 @@ static enum cpuhp_state hp_online;
734734
static void __padata_free(struct padata_instance *pinst)
735735
{
736736
#ifdef CONFIG_HOTPLUG_CPU
737-
cpuhp_state_remove_instance_nocalls(CPUHP_PADATA_DEAD, &pinst->node);
738-
cpuhp_state_remove_instance_nocalls(hp_online, &pinst->node);
737+
cpuhp_state_remove_instance_nocalls(CPUHP_PADATA_DEAD,
738+
&pinst->cpu_dead_node);
739+
cpuhp_state_remove_instance_nocalls(hp_online, &pinst->cpu_online_node);
739740
#endif
740741

741742
WARN_ON(!list_empty(&pinst->pslist));
@@ -939,9 +940,10 @@ static struct padata_instance *padata_alloc(const char *name,
939940
mutex_init(&pinst->lock);
940941

941942
#ifdef CONFIG_HOTPLUG_CPU
942-
cpuhp_state_add_instance_nocalls_cpuslocked(hp_online, &pinst->node);
943+
cpuhp_state_add_instance_nocalls_cpuslocked(hp_online,
944+
&pinst->cpu_online_node);
943945
cpuhp_state_add_instance_nocalls_cpuslocked(CPUHP_PADATA_DEAD,
944-
&pinst->node);
946+
&pinst->cpu_dead_node);
945947
#endif
946948

947949
put_online_cpus();

0 commit comments

Comments
 (0)