Skip to content

Commit 77db4e1

Browse files
danieljordan10gregkh
authored andcommitted
padata: add separate cpuhp node for CPUHP_PADATA_DEAD
[ Upstream commit 3c2214b6027ff37945799de717c417212e1a8c54 ] 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+ projectceladon#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: 894c9ef9780c ("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> Signed-off-by: Sasha Levin <sashal@kernel.org>
1 parent f23be4d commit 77db4e1

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
@@ -145,7 +145,8 @@ struct padata_shell {
145145
/**
146146
* struct padata_instance - The overall control structure.
147147
*
148-
* @cpu_notifier: cpu hotplug notifier.
148+
* @cpu_online_node: Linkage for CPU online callback.
149+
* @cpu_dead_node: Linkage for CPU offline callback.
149150
* @parallel_wq: The workqueue used for parallel work.
150151
* @serial_wq: The workqueue used for serial work.
151152
* @pslist: List of padata_shell objects attached to this instance.
@@ -160,7 +161,8 @@ struct padata_shell {
160161
* @flags: padata flags.
161162
*/
162163
struct padata_instance {
163-
struct hlist_node node;
164+
struct hlist_node cpu_online_node;
165+
struct hlist_node cpu_dead_node;
164166
struct workqueue_struct *parallel_wq;
165167
struct workqueue_struct *serial_wq;
166168
struct list_head pslist;

kernel/padata.c

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

785-
pinst = hlist_entry_safe(node, struct padata_instance, node);
785+
pinst = hlist_entry_safe(node, struct padata_instance, cpu_online_node);
786786
if (!pinst_has_cpu(pinst, cpu))
787787
return 0;
788788

@@ -797,7 +797,7 @@ static int padata_cpu_dead(unsigned int cpu, struct hlist_node *node)
797797
struct padata_instance *pinst;
798798
int ret;
799799

800-
pinst = hlist_entry_safe(node, struct padata_instance, node);
800+
pinst = hlist_entry_safe(node, struct padata_instance, cpu_dead_node);
801801
if (!pinst_has_cpu(pinst, cpu))
802802
return 0;
803803

@@ -813,8 +813,9 @@ static enum cpuhp_state hp_online;
813813
static void __padata_free(struct padata_instance *pinst)
814814
{
815815
#ifdef CONFIG_HOTPLUG_CPU
816-
cpuhp_state_remove_instance_nocalls(CPUHP_PADATA_DEAD, &pinst->node);
817-
cpuhp_state_remove_instance_nocalls(hp_online, &pinst->node);
816+
cpuhp_state_remove_instance_nocalls(CPUHP_PADATA_DEAD,
817+
&pinst->cpu_dead_node);
818+
cpuhp_state_remove_instance_nocalls(hp_online, &pinst->cpu_online_node);
818819
#endif
819820

820821
WARN_ON(!list_empty(&pinst->pslist));
@@ -1020,9 +1021,10 @@ static struct padata_instance *padata_alloc(const char *name,
10201021
mutex_init(&pinst->lock);
10211022

10221023
#ifdef CONFIG_HOTPLUG_CPU
1023-
cpuhp_state_add_instance_nocalls_cpuslocked(hp_online, &pinst->node);
1024+
cpuhp_state_add_instance_nocalls_cpuslocked(hp_online,
1025+
&pinst->cpu_online_node);
10241026
cpuhp_state_add_instance_nocalls_cpuslocked(CPUHP_PADATA_DEAD,
1025-
&pinst->node);
1027+
&pinst->cpu_dead_node);
10261028
#endif
10271029

10281030
put_online_cpus();

0 commit comments

Comments
 (0)