diff mbox series

rtc: fix data race in rtc_dev_poll()

Message ID 20250510150945.18387-1-aha310510@gmail.com
State New
Headers show
Series rtc: fix data race in rtc_dev_poll() | expand

Commit Message

Jeongjun Park May 10, 2025, 3:09 p.m. UTC
I found data-race in my fuzzer:

==================================================================
BUG: KCSAN: data-race in rtc_dev_poll / rtc_handle_legacy_irq

write to 0xffff88800b307380 of 8 bytes by interrupt on cpu 1:
 rtc_handle_legacy_irq+0x58/0xb0 drivers/rtc/interface.c:624
 rtc_pie_update_irq+0x75/0x90 drivers/rtc/interface.c:672
 __run_hrtimer kernel/time/hrtimer.c:1761 [inline]
 __hrtimer_run_queues+0x2c4/0x5d0 kernel/time/hrtimer.c:1825
 hrtimer_interrupt+0x214/0x4a0 kernel/time/hrtimer.c:1887
 local_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1038 [inline]
....

read to 0xffff88800b307380 of 8 bytes by task 11566 on cpu 0:
 rtc_dev_poll+0x6c/0xa0 drivers/rtc/dev.c:198
 vfs_poll include/linux/poll.h:82 [inline]
 select_poll_one fs/select.c:480 [inline]
 do_select+0x95f/0x1030 fs/select.c:536
 core_sys_select+0x284/0x6d0 fs/select.c:677
 do_pselect.constprop.0+0x118/0x150 fs/select.c:759
....

value changed: 0x00000000000801c0 -> 0x00000000000802c0
==================================================================

rtc_dev_poll() is reading rtc->irq_data without a spinlock for some
unknown reason. This causes a data-race, so we need to add a spinlock
to fix it.

Cc: <stable@vger.kernel.org>
Fixes: e824290e5dcf ("[PATCH] RTC subsystem: dev interface")
Signed-off-by: Jeongjun Park <aha310510@gmail.com>
---
 drivers/rtc/dev.c | 2 ++
 1 file changed, 2 insertions(+)

--
diff mbox series

Patch

diff --git a/drivers/rtc/dev.c b/drivers/rtc/dev.c
index 0eeae5bcc3aa..a6570a5a938a 100644
--- a/drivers/rtc/dev.c
+++ b/drivers/rtc/dev.c
@@ -195,7 +195,9 @@  static __poll_t rtc_dev_poll(struct file *file, poll_table *wait)
 
 	poll_wait(file, &rtc->irq_queue, wait);
 
+	spin_lock_irq(&rtc->irq_lock);
 	data = rtc->irq_data;
+	spin_unlock_irq(&rtc->irq_lock);
 
 	return (data != 0) ? (EPOLLIN | EPOLLRDNORM) : 0;
 }