Patch "rcu/kvfree: Fix data-race in __mod_timer / kvfree_call_rcu" has been added to the 6.12-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    rcu/kvfree: Fix data-race in __mod_timer / kvfree_call_rcu

to the 6.12-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     rcu-kvfree-fix-data-race-in-__mod_timer-kvfree_call_.patch
and it can be found in the queue-6.12 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit 5ba6a9d783d411dbf411c88a7b93646d12a65f32
Author: Uladzislau Rezki (Sony) <urezki@xxxxxxxxx>
Date:   Tue Oct 22 12:53:07 2024 +0200

    rcu/kvfree: Fix data-race in __mod_timer / kvfree_call_rcu
    
    [ Upstream commit a23da88c6c80e41e0503e0b481a22c9eea63f263 ]
    
    KCSAN reports a data race when access the krcp->monitor_work.timer.expires
    variable in the schedule_delayed_monitor_work() function:
    
    <snip>
    BUG: KCSAN: data-race in __mod_timer / kvfree_call_rcu
    
    read to 0xffff888237d1cce8 of 8 bytes by task 10149 on cpu 1:
     schedule_delayed_monitor_work kernel/rcu/tree.c:3520 [inline]
     kvfree_call_rcu+0x3b8/0x510 kernel/rcu/tree.c:3839
     trie_update_elem+0x47c/0x620 kernel/bpf/lpm_trie.c:441
     bpf_map_update_value+0x324/0x350 kernel/bpf/syscall.c:203
     generic_map_update_batch+0x401/0x520 kernel/bpf/syscall.c:1849
     bpf_map_do_batch+0x28c/0x3f0 kernel/bpf/syscall.c:5143
     __sys_bpf+0x2e5/0x7a0
     __do_sys_bpf kernel/bpf/syscall.c:5741 [inline]
     __se_sys_bpf kernel/bpf/syscall.c:5739 [inline]
     __x64_sys_bpf+0x43/0x50 kernel/bpf/syscall.c:5739
     x64_sys_call+0x2625/0x2d60 arch/x86/include/generated/asm/syscalls_64.h:322
     do_syscall_x64 arch/x86/entry/common.c:52 [inline]
     do_syscall_64+0xc9/0x1c0 arch/x86/entry/common.c:83
     entry_SYSCALL_64_after_hwframe+0x77/0x7f
    
    write to 0xffff888237d1cce8 of 8 bytes by task 56 on cpu 0:
     __mod_timer+0x578/0x7f0 kernel/time/timer.c:1173
     add_timer_global+0x51/0x70 kernel/time/timer.c:1330
     __queue_delayed_work+0x127/0x1a0 kernel/workqueue.c:2523
     queue_delayed_work_on+0xdf/0x190 kernel/workqueue.c:2552
     queue_delayed_work include/linux/workqueue.h:677 [inline]
     schedule_delayed_monitor_work kernel/rcu/tree.c:3525 [inline]
     kfree_rcu_monitor+0x5e8/0x660 kernel/rcu/tree.c:3643
     process_one_work kernel/workqueue.c:3229 [inline]
     process_scheduled_works+0x483/0x9a0 kernel/workqueue.c:3310
     worker_thread+0x51d/0x6f0 kernel/workqueue.c:3391
     kthread+0x1d1/0x210 kernel/kthread.c:389
     ret_from_fork+0x4b/0x60 arch/x86/kernel/process.c:147
     ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
    
    Reported by Kernel Concurrency Sanitizer on:
    CPU: 0 UID: 0 PID: 56 Comm: kworker/u8:4 Not tainted 6.12.0-rc2-syzkaller-00050-g5b7c893ed5ed #0
    Hardware name: Google Google Compute Engine/Google Compute Engine, BIOS Google 09/13/2024
    Workqueue: events_unbound kfree_rcu_monitor
    <snip>
    
    kfree_rcu_monitor() rearms the work if a "krcp" has to be still
    offloaded and this is done without holding krcp->lock, whereas
    the kvfree_call_rcu() holds it.
    
    Fix it by acquiring the "krcp->lock" for kfree_rcu_monitor() so
    both functions do not race anymore.
    
    Reported-by: syzbot+061d370693bdd99f9d34@xxxxxxxxxxxxxxxxxxxxxxxxx
    Link: https://lore.kernel.org/lkml/ZxZ68KmHDQYU0yfD@pc636/T/
    Fixes: 8fc5494ad5fa ("rcu/kvfree: Move need_offload_krc() out of krcp->lock")
    Signed-off-by: Uladzislau Rezki (Sony) <urezki@xxxxxxxxx>
    Reviewed-by: Neeraj Upadhyay <Neeraj.Upadhyay@xxxxxxx>
    Signed-off-by: Frederic Weisbecker <frederic@xxxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/kernel/rcu/tree.c b/kernel/rcu/tree.c
index b1f883fcd9185..3e486ccaa4ca3 100644
--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3511,7 +3511,7 @@ static int krc_count(struct kfree_rcu_cpu *krcp)
 }
 
 static void
-schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
+__schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
 {
 	long delay, delay_left;
 
@@ -3525,6 +3525,16 @@ schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
 	queue_delayed_work(system_unbound_wq, &krcp->monitor_work, delay);
 }
 
+static void
+schedule_delayed_monitor_work(struct kfree_rcu_cpu *krcp)
+{
+	unsigned long flags;
+
+	raw_spin_lock_irqsave(&krcp->lock, flags);
+	__schedule_delayed_monitor_work(krcp);
+	raw_spin_unlock_irqrestore(&krcp->lock, flags);
+}
+
 static void
 kvfree_rcu_drain_ready(struct kfree_rcu_cpu *krcp)
 {
@@ -3836,7 +3846,7 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
 
 	// Set timer to drain after KFREE_DRAIN_JIFFIES.
 	if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING)
-		schedule_delayed_monitor_work(krcp);
+		__schedule_delayed_monitor_work(krcp);
 
 unlock_return:
 	krc_this_cpu_unlock(krcp, flags);




[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux