From 3f38eabc5b585c1afdb74f848fc46147c12b08d6 Mon Sep 17 00:00:00 2001 From: Huibin Hong Date: Wed, 30 Apr 2025 14:41:57 +0800 Subject: [PATCH] arm64: armv8_deprecated: protect prev_mode or it would cause undef_lock deadlock When do 'echo 1 > /proc/sys/abi/swp' on two cpus at the same time, we can see: call_undef_hook() at traps.c:442 do_undefinstr() at traps.c:504 el0_undef() at entry-common.c:605 el0t_64_sync_handler() at entry-common.c:689 el0t_64_sync() at entry.S:585 That is because write swp 1 at the same time, add the swp_hooks to the undef_hook list twice, swp_hooks list node's next becomes itself. When list_for_each_entry of the undef_hook, cpu loops forever here. Change-Id: Ice60dbc633020220e7218a554e9d0e4c7dacceb4 Signed-off-by: Huibin Hong --- arch/arm64/kernel/armv8_deprecated.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/arch/arm64/kernel/armv8_deprecated.c b/arch/arm64/kernel/armv8_deprecated.c index fb0e7c7b2e20..9ca9892a6e39 100644 --- a/arch/arm64/kernel/armv8_deprecated.c +++ b/arch/arm64/kernel/armv8_deprecated.c @@ -209,9 +209,10 @@ static int emulation_proc_handler(struct ctl_table *table, int write, { int ret = 0; struct insn_emulation *insn = container_of(table->data, struct insn_emulation, current_mode); - enum insn_emulation_mode prev_mode = insn->current_mode; + enum insn_emulation_mode prev_mode; mutex_lock(&insn_emulation_mutex); + prev_mode = insn->current_mode; ret = proc_dointvec_minmax(table, write, buffer, lenp, ppos); if (ret || !write || prev_mode == insn->current_mode)