From: Ran Xiaokai <ran.xiaokai@zte.com.cn>
In a preempt-RT kernel, although most of the irq handler have been
converted to the threaded mode except those which have the
IRQF_NO_THREAD flag set. The hrtimer IRQ is such an example.
So kcsan report could be triggered from a HARD-irq context, this will
trigger the "sleeping function called from invalid context" bug.
[ C1] BUG: sleeping function called from invalid context at kernel/locking/spinlock_rt.c:48
[ C1] in_atomic(): 1, irqs_disabled(): 1, non_block: 0, pid: 0, name: swapper/1
[ C1] preempt_count: 10002, expected: 0
[ C1] RCU nest depth: 0, expected: 0
[ C1] no locks held by swapper/1/0.
[ C1] irq event stamp: 156674
[ C1] hardirqs last enabled at (156673): [<ffffffff81130bd9>] do_idle+0x1f9/0x240
[ C1] hardirqs last disabled at (156674): [<ffffffff82254f84>] sysvec_apic_timer_interrupt+0x14/0xc0
[ C1] softirqs last enabled at (0): [<ffffffff81099f47>] copy_process+0xfc7/0x4b60
[ C1] softirqs last disabled at (0): [<0000000000000000>] 0x0
[ C1] Preemption disabled at:
[ C1] [<ffffffff814a3e2a>] paint_ptr+0x2a/0x90
[ C1] CPU: 1 UID: 0 PID: 0 Comm: swapper/1 Not tainted 6.11.0+ #3
[ C1] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS rel-1.12.0-0-ga698c8995f-prebuilt.qemu.org 04/01/2014
[ C1] Call Trace:
[ C1] <IRQ>
[ C1] dump_stack_lvl+0x7e/0xc0
[ C1] dump_stack+0x1d/0x30
[ C1] __might_resched+0x1a2/0x270
[ C1] rt_spin_lock+0x68/0x170
[ C1] ? kcsan_skip_report_debugfs+0x43/0xe0
[ C1] kcsan_skip_report_debugfs+0x43/0xe0
[ C1] ? hrtimer_next_event_without+0x110/0x110
[ C1] print_report+0xb5/0x590
[ C1] kcsan_report_known_origin+0x1b1/0x1d0
[ C1] kcsan_setup_watchpoint+0x348/0x650
[ C1] __tsan_unaligned_write1+0x16d/0x1d0
[ C1] hrtimer_interrupt+0x3d6/0x430
[ C1] __sysvec_apic_timer_interrupt+0xe8/0x3a0
[ C1] sysvec_apic_timer_interrupt+0x97/0xc0
[ C1] </IRQ>
To fix this, we can not simply convert the report_filterlist_lock
to a raw_spinlock_t. In the insert_report_filterlist() path:
raw_spin_lock_irqsave(&report_filterlist_lock, flags);
krealloc
__do_kmalloc_node
slab_alloc_node
__slab_alloc
local_lock_irqsave(&s->cpu_slab->lock, flags)
local_lock_t is now a spinlock_t which is sleepable in preempt-RT
kernel, so kmalloc() and similar functions can not be called with
a raw_spinlock_t lock held.
Instead, we can convert it to rcu lock to fix this.
Ran Xiaokai (4):
kcsan, debugfs: Remove redundant call of kallsyms_lookup_name()
kcsan, debugfs: refactor set_report_filterlist_whitelist() to return a
value
kcsan, debugfs: fix atomic sleep by converting spinlock_t to rcu lock
kcsan, debugfs: avoid updating white/blacklist with the same value
kernel/kcsan/debugfs.c | 192 ++++++++++++++++++++++++++++++++-----------------
1 file changed, 125 insertions(+), 67 deletions(-)
--
2.15.2