Re: [syzbot] [bpf?] possible deadlock in kvfree_call_rcu

From: Uladzislau Rezki
Date: Sun Mar 31 2024 - 02:28:35 EST


On Tue, Mar 26, 2024 at 12:00:22PM -0700, syzbot wrote:
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: fe46a7dd189e Merge tag 'sound-6.9-rc1' of git://git.kernel..
> git tree: upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=11547a65180000
> kernel config: https://syzkaller.appspot.com/x/.config?x=4d90a36f0cab495a
> dashboard link: https://syzkaller.appspot.com/bug?extid=1fa663a2100308ab6eab
> compiler: Debian clang version 15.0.6, GNU ld (GNU Binutils for Debian) 2.40
>

#syz test https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git 7033999ecd7b

--- a/kernel/rcu/tree.c
+++ b/kernel/rcu/tree.c
@@ -3467,19 +3467,19 @@ void kvfree_call_rcu(struct rcu_head *head, void *ptr)
*/
kmemleak_ignore(ptr);

- // Set timer to drain after KFREE_DRAIN_JIFFIES.
- if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING)
- schedule_delayed_monitor_work(krcp);
-
unlock_return:
krc_this_cpu_unlock(krcp, flags);

- /*
- * Inline kvfree() after synchronize_rcu(). We can do
- * it from might_sleep() context only, so the current
- * CPU can pass the QS state.
- */
- if (!success) {
+ if (success) {
+ // Set timer to drain after KFREE_DRAIN_JIFFIES.
+ if (rcu_scheduler_active == RCU_SCHEDULER_RUNNING)
+ schedule_delayed_monitor_work(krcp);
+ } else {
+ /*
+ * Inline kvfree() after synchronize_rcu(). We can do
+ * it from might_sleep() context only, so the current
+ * CPU can pass the QS state.
+ */
debug_rcu_head_unqueue((struct rcu_head *) ptr);
synchronize_rcu();
kvfree(ptr);