hulk inclusion category: bugfix bugzilla: https://gitee.com/openeuler/kernel/issues/IBC1RM CVE: NA
--------------------------------
printk calls zap_locks() to bypass logbuf_lock during panic. If the current system uses qspinlock, it may cause a deadloop in queued_spin_lock_slowpath(). Consider the following locking sequence:
cpu1: (0, 0, 1) cpu2: (0, 1, 1) cpu3: (3, 1, 1)
If zap_locks() is called at this time, cpu2 may acquire the lock first, and then cpu3 acquires the lock. When cpu3 releases the lock, it checks if the tail is itself. Originally, it should be, but after zap_locks(), the tail is modified to 0. At this point, cpu3 thinks there are other contenders, it will first set the locked bit and then wait for the contender to set its next pointer. However, in reality, there are no other contenders, so cpu3 will hold the lock (locked bit is 1) and loop here, causing other CPUs that want to acquire the lock to be stuck.
To fix this problem, the lock initialization in zap_locks() can be degraded to clear locked_pending and retain the tail, avoiding misjudgment.
Fixes: be926ed0f034 ("printk/panic: Avoid deadlock in printk()") Signed-off-by: Li Huafei lihuafei1@huawei.com --- kernel/printk/printk.c | 10 ++++++++++ 1 file changed, 10 insertions(+)
diff --git a/kernel/printk/printk.c b/kernel/printk/printk.c index 11ebe66c473a..532d1f9a194f 100644 --- a/kernel/printk/printk.c +++ b/kernel/printk/printk.c @@ -1634,11 +1634,21 @@ void zap_locks(void) { if (raw_spin_is_locked(&logbuf_lock)) { debug_locks_off(); +#ifdef CONFIG_QUEUED_SPINLOCKS + /* Do not clear the tail to avoid infinite loop in qspinlock. */ + WRITE_ONCE(logbuf_lock.raw_lock.locked_pending, 0); +#else raw_spin_lock_init(&logbuf_lock); +#endif }
if (raw_spin_is_locked(&console_owner_lock)) { +#ifdef CONFIG_QUEUED_SPINLOCKS + /* Do not clear the tail to avoid infinite loop in qspinlock. */ + WRITE_ONCE(console_owner_lock.raw_lock.locked_pending, 0); +#else raw_spin_lock_init(&console_owner_lock); +#endif console_owner = NULL; console_waiter = false; }
反馈: 您发送到kernel@openeuler.org的补丁/补丁集,已成功转换为PR! PR链接地址: https://gitee.com/openeuler/kernel/pulls/14306 邮件列表地址:https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/F...
FeedBack: The patch(es) which you have sent to kernel@openeuler.org mailing list has been converted to a pull request successfully! Pull request link: https://gitee.com/openeuler/kernel/pulls/14306 Mailing list address: https://mailweb.openeuler.org/hyperkitty/list/kernel@openeuler.org/message/F...