[syzbot] [sound?] BUG: sleeping function called from invalid context in snd_card_locked

15 views
Skip to first unread message

syzbot

unread,
Feb 28, 2025, 9:37:28 PM2/28/25
to linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, syzkall...@googlegroups.com, ti...@suse.com
Hello,

syzbot found the following issue on:

HEAD commit: d082ecbc71e9 Linux 6.14-rc4
git tree: upstream
console output: https://syzkaller.appspot.com/x/log.txt?x=14e3d7a4580000
kernel config: https://syzkaller.appspot.com/x/.config?x=8f2f8fb6ad08b539
dashboard link: https://syzkaller.appspot.com/bug?extid=4cb9fad083898f54c517
compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils for Debian) 2.40

Unfortunately, I don't have any reproducer for this issue yet.

Downloadable assets:
disk image (non-bootable): https://storage.googleapis.com/syzbot-assets/7feb34a89c2a/non_bootable_disk-d082ecbc.raw.xz
vmlinux: https://storage.googleapis.com/syzbot-assets/f7cfa9bd3468/vmlinux-d082ecbc.xz
kernel image: https://storage.googleapis.com/syzbot-assets/d47dd7c3fc5d/bzImage-d082ecbc.xz

IMPORTANT: if you fix the issue, please add the following tag to the commit:
Reported-by: syzbot+4cb9fa...@syzkaller.appspotmail.com

BUG: sleeping function called from invalid context at kernel/locking/mutex.c:562
in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 1167, name: kworker/0:1H
preempt_count: 0, expected: 0
RCU nest depth: 0, expected: 0
2 locks held by kworker/0:1H/1167:
#0: ffff88801b089148 ((wq_completion)events_highpri){+.+.}-{0:0}, at: process_one_work+0x1293/0x1ba0 kernel/workqueue.c:3211
#1: ffffc900061f7d18 ((work_completion)(&timer->task_work)){+.+.}-{0:0}, at: process_one_work+0x921/0x1ba0 kernel/workqueue.c:3212
irq event stamp: 1044
hardirqs last enabled at (1043): [<ffffffff8b59c523>] __raw_spin_unlock_irq include/linux/spinlock_api_smp.h:159 [inline]
hardirqs last enabled at (1043): [<ffffffff8b59c523>] _raw_spin_unlock_irq+0x23/0x50 kernel/locking/spinlock.c:202
hardirqs last disabled at (1044): [<ffffffff8b59c2c2>] __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:108 [inline]
hardirqs last disabled at (1044): [<ffffffff8b59c2c2>] _raw_spin_lock_irqsave+0x52/0x60 kernel/locking/spinlock.c:162
softirqs last enabled at (204): [<ffffffff817c131b>] softirq_handle_end kernel/softirq.c:407 [inline]
softirqs last enabled at (204): [<ffffffff817c131b>] handle_softirqs+0x5bb/0x8f0 kernel/softirq.c:589
softirqs last disabled at (183): [<ffffffff817c17e9>] __do_softirq kernel/softirq.c:595 [inline]
softirqs last disabled at (183): [<ffffffff817c17e9>] invoke_softirq kernel/softirq.c:435 [inline]
softirqs last disabled at (183): [<ffffffff817c17e9>] __irq_exit_rcu+0x109/0x170 kernel/softirq.c:662
CPU: 0 UID: 0 PID: 1167 Comm: kworker/0:1H Not tainted 6.14.0-rc4-syzkaller #0
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Workqueue: events_highpri snd_timer_work
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
__might_resched+0x3c0/0x5e0 kernel/sched/core.c:8767
__mutex_lock_common kernel/locking/mutex.c:562 [inline]
__mutex_lock+0x108/0xb10 kernel/locking/mutex.c:730
class_mutex_constructor include/linux/mutex.h:201 [inline]
snd_card_locked+0x1b/0x60 sound/core/init.c:399
snd_request_card+0x14/0x70 sound/core/sound.c:62
snd_seq_client_use_ptr+0x375/0x3c0 sound/core/seq/seq_clientmgr.c:152
get_event_dest_client sound/core/seq/seq_clientmgr.c:533 [inline]
snd_seq_deliver_single_event+0xdb/0x6e0 sound/core/seq/seq_clientmgr.c:663
snd_seq_deliver_event+0x291/0x4b0 sound/core/seq/seq_clientmgr.c:822
snd_seq_dispatch_event+0x117/0x580 sound/core/seq/seq_clientmgr.c:897
snd_seq_check_queue+0x248/0x510 sound/core/seq/seq_queue.c:256
snd_seq_timer_interrupt+0x2e3/0x390 sound/core/seq/seq_timer.c:153
snd_timer_process_callbacks+0x217/0x2e0 sound/core/timer.c:785
snd_timer_work+0xa9/0x100 sound/core/timer.c:815
process_one_work+0x9c5/0x1ba0 kernel/workqueue.c:3236
process_scheduled_works kernel/workqueue.c:3317 [inline]
worker_thread+0x6c8/0xf00 kernel/workqueue.c:3398
kthread+0x3af/0x750 kernel/kthread.c:464
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:148
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
</TASK>

================================
WARNING: inconsistent lock state
6.14.0-rc4-syzkaller #0 Tainted: G W
--------------------------------
inconsistent {IN-HARDIRQ-W} -> {HARDIRQ-ON-W} usage.
kworker/0:1H/1167 [HC0[0]:SC0[0]:HE1:SE1] takes:
ffff8880236dc148 (&timer->lock){?.-.}-{3:3}, at: spin_lock include/linux/spinlock.h:351 [inline]
ffff8880236dc148 (&timer->lock){?.-.}-{3:3}, at: snd_timer_process_callbacks+0x227/0x2e0 sound/core/timer.c:786
{IN-HARDIRQ-W} state was registered at:
lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5851
__raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154
spin_lock include/linux/spinlock.h:351 [inline]
class_spinlock_constructor include/linux/spinlock.h:559 [inline]
snd_hrtimer_callback+0x53/0x400 sound/core/hrtimer.c:38
__run_hrtimer kernel/time/hrtimer.c:1801 [inline]
__hrtimer_run_queues+0x20a/0xae0 kernel/time/hrtimer.c:1865
hrtimer_interrupt+0x392/0x8e0 kernel/time/hrtimer.c:1927
local_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1038 [inline]
__sysvec_apic_timer_interrupt+0x10f/0x400 arch/x86/kernel/apic/apic.c:1055
instr_sysvec_apic_timer_interrupt arch/x86/kernel/apic/apic.c:1049 [inline]
sysvec_apic_timer_interrupt+0x9f/0xc0 arch/x86/kernel/apic/apic.c:1049
asm_sysvec_apic_timer_interrupt+0x1a/0x20 arch/x86/include/asm/idtentry.h:702
__raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:151 [inline]
_raw_spin_unlock_irqrestore+0x31/0x80 kernel/locking/spinlock.c:194
class_raw_spinlock_irqsave_destructor include/linux/spinlock.h:551 [inline]
try_to_wake_up+0x949/0x1490 kernel/sched/core.c:4214
wake_up_process kernel/sched/core.c:4463 [inline]
wake_up_q+0x9c/0x160 kernel/sched/core.c:1075
raw_spin_unlock_irqrestore_wake include/linux/sched/wake_q.h:96 [inline]
__mutex_unlock_slowpath+0x231/0x6a0 kernel/locking/mutex.c:933
device_unlock include/linux/device.h:1045 [inline]
hub_event+0xc5f/0x4e10 drivers/usb/core/hub.c:5954
process_one_work+0x9c5/0x1ba0 kernel/workqueue.c:3236
process_scheduled_works kernel/workqueue.c:3317 [inline]
worker_thread+0x6c8/0xf00 kernel/workqueue.c:3398
kthread+0x3af/0x750 kernel/kthread.c:464
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:148
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
irq event stamp: 1197
hardirqs last enabled at (1197): [<ffffffff8b59c5b2>] __raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:151 [inline]
hardirqs last enabled at (1197): [<ffffffff8b59c5b2>] _raw_spin_unlock_irqrestore+0x52/0x80 kernel/locking/spinlock.c:194
hardirqs last disabled at (1196): [<ffffffff8b59c2c2>] __raw_spin_lock_irqsave include/linux/spinlock_api_smp.h:108 [inline]
hardirqs last disabled at (1196): [<ffffffff8b59c2c2>] _raw_spin_lock_irqsave+0x52/0x60 kernel/locking/spinlock.c:162
softirqs last enabled at (1156): [<ffffffff817c131b>] softirq_handle_end kernel/softirq.c:407 [inline]
softirqs last enabled at (1156): [<ffffffff817c131b>] handle_softirqs+0x5bb/0x8f0 kernel/softirq.c:589
softirqs last disabled at (1047): [<ffffffff817c17e9>] __do_softirq kernel/softirq.c:595 [inline]
softirqs last disabled at (1047): [<ffffffff817c17e9>] invoke_softirq kernel/softirq.c:435 [inline]
softirqs last disabled at (1047): [<ffffffff817c17e9>] __irq_exit_rcu+0x109/0x170 kernel/softirq.c:662

other info that might help us debug this:
Possible unsafe locking scenario:

CPU0
----
lock(&timer->lock);
<Interrupt>
lock(&timer->lock);

*** DEADLOCK ***

2 locks held by kworker/0:1H/1167:
#0: ffff88801b089148 ((wq_completion)events_highpri){+.+.}-{0:0}, at: process_one_work+0x1293/0x1ba0 kernel/workqueue.c:3211
#1: ffffc900061f7d18 ((work_completion)(&timer->task_work)){+.+.}-{0:0}, at: process_one_work+0x921/0x1ba0 kernel/workqueue.c:3212

stack backtrace:
CPU: 0 UID: 0 PID: 1167 Comm: kworker/0:1H Tainted: G W 6.14.0-rc4-syzkaller #0
Tainted: [W]=WARN
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Workqueue: events_highpri snd_timer_work
Call Trace:
<TASK>
__dump_stack lib/dump_stack.c:94 [inline]
dump_stack_lvl+0x116/0x1f0 lib/dump_stack.c:120
print_usage_bug.part.0+0x3fb/0x680 kernel/locking/lockdep.c:4040
print_usage_bug kernel/locking/lockdep.c:4008 [inline]
valid_state kernel/locking/lockdep.c:4054 [inline]
mark_lock_irq kernel/locking/lockdep.c:4265 [inline]
mark_lock+0x92d/0xc60 kernel/locking/lockdep.c:4751
mark_usage kernel/locking/lockdep.c:4660 [inline]
__lock_acquire+0x98e/0x3c40 kernel/locking/lockdep.c:5182
lock_acquire.part.0+0x11b/0x380 kernel/locking/lockdep.c:5851
__raw_spin_lock include/linux/spinlock_api_smp.h:133 [inline]
_raw_spin_lock+0x2e/0x40 kernel/locking/spinlock.c:154
spin_lock include/linux/spinlock.h:351 [inline]
snd_timer_process_callbacks+0x227/0x2e0 sound/core/timer.c:786
snd_timer_work+0xa9/0x100 sound/core/timer.c:815
process_one_work+0x9c5/0x1ba0 kernel/workqueue.c:3236
process_scheduled_works kernel/workqueue.c:3317 [inline]
worker_thread+0x6c8/0xf00 kernel/workqueue.c:3398
kthread+0x3af/0x750 kernel/kthread.c:464
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:148
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
</TASK>
------------[ cut here ]------------
raw_local_irq_restore() called with IRQs enabled
WARNING: CPU: 0 PID: 1167 at kernel/locking/irqflag-debug.c:10 warn_bogus_irq_restore+0x29/0x30 kernel/locking/irqflag-debug.c:10
Modules linked in:
CPU: 0 UID: 0 PID: 1167 Comm: kworker/0:1H Tainted: G W 6.14.0-rc4-syzkaller #0
Tainted: [W]=WARN
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.16.3-debian-1.16.3-2~bpo12+1 04/01/2014
Workqueue: events_highpri snd_timer_work
RIP: 0010:warn_bogus_irq_restore+0x29/0x30 kernel/locking/irqflag-debug.c:10
Code: 90 f3 0f 1e fa 90 80 3d f9 a7 f3 04 00 74 06 90 c3 cc cc cc cc c6 05 ea a7 f3 04 01 90 48 c7 c7 c0 e6 6c 8b e8 58 df 22 f6 90 <0f> 0b 90 90 eb df 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90
RSP: 0018:ffffc900061f7c18 EFLAGS: 00010282
RAX: 0000000000000000 RBX: ffff8880236dc130 RCX: ffffffff817a1229
RDX: ffff888028238000 RSI: ffffffff817a1236 RDI: 0000000000000001
RBP: 0000000000000286 R08: 0000000000000001 R09: 0000000000000000
R10: 0000000000000000 R11: 61636f6c5f776172 R12: ffff8880236dc000
R13: ffff8880236dc1b0 R14: 0000000000000000 R15: ffff88801b09d800
FS: 0000000000000000(0000) GS:ffff88806a600000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007fecdd000218 CR3: 0000000031f9c000 CR4: 0000000000352ef0
DR0: 0000000000000002 DR1: fffffffffffffffb DR2: 0000000000010001
DR3: 0000000000000004 DR6: 00000000fffe0ff0 DR7: 0000000000000400
Call Trace:
<TASK>
__raw_spin_unlock_irqrestore include/linux/spinlock_api_smp.h:151 [inline]
_raw_spin_unlock_irqrestore+0x74/0x80 kernel/locking/spinlock.c:194
spin_unlock_irqrestore include/linux/spinlock.h:406 [inline]
class_spinlock_irqsave_destructor include/linux/spinlock.h:572 [inline]
snd_timer_work+0xbe/0x100 sound/core/timer.c:814
process_one_work+0x9c5/0x1ba0 kernel/workqueue.c:3236
process_scheduled_works kernel/workqueue.c:3317 [inline]
worker_thread+0x6c8/0xf00 kernel/workqueue.c:3398
kthread+0x3af/0x750 kernel/kthread.c:464
ret_from_fork+0x45/0x80 arch/x86/kernel/process.c:148
ret_from_fork_asm+0x1a/0x30 arch/x86/entry/entry_64.S:244
</TASK>


---
This report is generated by a bot. It may contain errors.
See https://goo.gl/tpsmEJ for more information about syzbot.
syzbot engineers can be reached at syzk...@googlegroups.com.

syzbot will keep track of this issue. See:
https://goo.gl/tpsmEJ#status for how to communicate with syzbot.

If the report is already addressed, let syzbot know by replying with:
#syz fix: exact-commit-title

If you want to overwrite report's subsystems, reply with:
#syz set subsystems: new-subsystem
(See the list of subsystem names on the web dashboard)

If the report is a duplicate of another one, reply with:
#syz dup: exact-subject-of-another-report

If you want to undo deduplication, reply with:
#syz undup

Hillf Danton

unread,
Mar 1, 2025, 2:53:27 AM3/1/25
to syzbot, linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, syzkall...@googlegroups.com, ti...@suse.com
On Fri, 28 Feb 2025 18:37:25 -0800
Given irq context, this deadlock is false positive because of irq disabled.

syzbot

unread,
Mar 1, 2025, 4:26:35 AM3/1/25
to quic_z...@quicinc.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, quic_z...@quicinc.com, syzkall...@googlegroups.com, ti...@suse.com
> > Hello,
> >
> > syzbot found the following issue on:
> >
> > HEAD commit: d082ecbc71e9 Linux 6.14-rc4
> > git tree: upstream
> > console output: https://syzkaller.appspot.com/x/log.txt?x=14e3d7a4580000
> > kernel config:
> https://syzkaller.appspot.com/x/.config?x=8f2f8fb6ad08b539
> > dashboard link:
> https://syzkaller.appspot.com/bug?extid=4cb9fad083898f54c517
> > compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils
> for Debian) 2.40
>
>
> BUG: sleeping function called from invalid context and
> raw_local_irq_restore() called with IRQs enabled seems can be
> fixed by below change. if it is valid, will arise the PATCH.
>
> #syz test:

want either no args or 2 args (repo, branch), got 4

>
> diff --git a/sound/core/timer.c b/sound/core/timer.c
> index fbada79380f9..5290c1b9f2b8 100644
> --- a/sound/core/timer.c
> +++ b/sound/core/timer.c
> @@ -767,6 +767,7 @@ static void snd_timer_process_callbacks(struct
> snd_timer *timer,
> {
> struct snd_timer_instance *ti;
> unsigned long resolution, ticks;
> + unsigned long flags;
>
> while (!list_empty(head)) {
> ti = list_first_entry(head, struct snd_timer_instance,
> @@ -780,10 +781,10 @@ static void snd_timer_process_callbacks(struct
> snd_timer *timer,
> ti->pticks = 0;
> resolution = ti->resolution;
> ti->flags |= SNDRV_TIMER_IFLG_CALLBACK;
> - spin_unlock(&timer->lock);
> + spin_unlock_irqrestore(&timer->lock, flags);
> if (ti->callback)
> ti->callback(ti, resolution, ticks);
> - spin_lock(&timer->lock);
> + spin_lock_irqsave(&timer->lock, flags);
> ti->flags &= ~SNDRV_TIMER_IFLG_CALLBACK;
> }
> }
> @@ -805,14 +806,16 @@ static void snd_timer_clear_callbacks(struct
> snd_timer *timer,
> static void snd_timer_work(struct work_struct *work)
> {
> struct snd_timer *timer = container_of(work, struct snd_timer,
> task_work);
> + unsigned long flags;
>
> if (timer->card && timer->card->shutdown) {
> snd_timer_clear_callbacks(timer, &timer->sack_list_head);
> return;
> }
>
> - guard(spinlock_irqsave)(&timer->lock);
> + spin_lock_irqsave(&timer->lock, flags);
> snd_timer_process_callbacks(timer, &timer->sack_list_head);
> + spin_unlock_irqrestore(&timer->lock, flags);
> }
>
> /*
>
>
>
>
>
> Thanks
> Zhongqiu Han

Takashi Iwai

unread,
Mar 1, 2025, 4:34:56 AM3/1/25
to Zhongqiu Han, syzbot+4cb9fa...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, syzkall...@googlegroups.com, ti...@suse.com
On Sat, 01 Mar 2025 10:25:55 +0100,
Zhongqiu Han wrote:
>
> > Hello,
> >
> > syzbot found the following issue on:
> >
> > HEAD commit: d082ecbc71e9 Linux 6.14-rc4
> > git tree: upstream
> > console output: https://syzkaller.appspot.com/x/log.txt?x=14e3d7a4580000
> > kernel config:
> https://syzkaller.appspot.com/x/.config?x=8f2f8fb6ad08b539
> > dashboard link:
> https://syzkaller.appspot.com/bug?extid=4cb9fad083898f54c517
> > compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils
> for Debian) 2.40
>
>
> BUG: sleeping function called from invalid context and
> raw_local_irq_restore() called with IRQs enabled seems can be
> fixed by below change. if it is valid, will arise the PATCH.

snd_timer_process_callbacks() gets called from two places, one from
snd_timer_work() and another from snd_timer_interrupt() where both
caller cover already with guard(spinlock_irqsave). That is, it's a
nested lock, hence without _irqsave().

IMO, the question is rather why the check of "!in_interrupt()" in
snd_seq_client_use_ptr() passed in this call path.


thanks,

Takashi

>
> #syz test:

Takashi Iwai

unread,
Mar 1, 2025, 5:22:56 AM3/1/25
to Zhongqiu Han, Takashi Iwai, syzbot+4cb9fa...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, syzkall...@googlegroups.com, ti...@suse.com
On Sat, 01 Mar 2025 10:50:43 +0100,
Zhongqiu Han wrote:
> Thanks Takashi for the discussion.
>
> I have an initial check:
> func snd_seq_check_queue is called from func snd_seq_timer_interrupt,
> and the scoped_guard can not cover it. maybe this the reason of
> !in_interrupt() check pass.
>
> just like my patch shared, snd_timer_process_callbacks called
> spin_unlock but not spin_unlock_irqrestore, which caused
> irqs_disabled(): 1 , and then caused the BUG.
>
>
> BUG: sleeping function called from invalid context at
> kernel/locking/mutex.c:562
> in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 1167, name:
> kworker/0:1H
>
>
> please feel free and kindly correct me if any misunderstanding.

Ah, no, the code in timer.c worked as expected; the lock in the caller
side is temporarily released intentionally for avoiding deadlock.

It's rather the problem in seq_clientmgr.c side, as I mentioned. The
check with !in_interrupt() is fragile in this case, and it's an
overkill to handle the module loading whenever it's referenced.

I'm going to submit the fix patch later.


thanks,

Takashi

Takashi Iwai

unread,
Mar 1, 2025, 5:43:06 AM3/1/25
to Zhongqiu Han, syzbot+4cb9fa...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, syzkall...@googlegroups.com, ti...@suse.com
On Sat, 01 Mar 2025 11:22:52 +0100,
Below is the copy:


Takashi

-- 8< --
From: Takashi Iwai <ti...@suse.de>
Subject: [PATCH] ALSA: seq: Avoid module auto-load handling at event delivery

snd_seq_client_use_ptr() is supposed to return the snd_seq_client
object for the given client ID, and it tries to handle the module
auto-loading when no matching object is found. Although the module
handling is performed only conditionally with "!in_interrupt()", this
condition may be fragile, e.g. when the code is called from the ALSA
timer callback where the spinlock is temporarily disabled while the
irq is disabled. Then his doesn't fit well and spews the error about
sleep from invalid context, as complained recently by syzbot.

Also, in general, handling the module-loading at each time if no
matching object is found is really an overkill. It can be still
useful when performed at the top-level ioctl or proc reads, but it
shouldn't be done at event delivery at all.

For addressing the issues above, this patch disables the module
handling in snd_seq_client_use_ptr() in normal cases like event
deliveries, but allow only in limited and safe situations.
A new function client_load_and_use_ptr() is used for the cases where
the module loading can be done safely, instead.

Reported-by: syzbot+4cb9fa...@syzkaller.appspotmail.com
Closes: https://lore.kernel.org/67c272e5.050a022...@google.com
Cc: <sta...@vger.kernel.org>
Signed-off-by: Takashi Iwai <ti...@suse.de>
---
sound/core/seq/seq_clientmgr.c | 46 ++++++++++++++++++++++------------
1 file changed, 30 insertions(+), 16 deletions(-)

diff --git a/sound/core/seq/seq_clientmgr.c b/sound/core/seq/seq_clientmgr.c
index cb66ec42a3f8..706f53e39b53 100644
--- a/sound/core/seq/seq_clientmgr.c
+++ b/sound/core/seq/seq_clientmgr.c
@@ -106,7 +106,7 @@ static struct snd_seq_client *clientptr(int clientid)
return clienttab[clientid];
}

-struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
+static struct snd_seq_client *client_use_ptr(int clientid, bool load_module)
{
unsigned long flags;
struct snd_seq_client *client;
@@ -126,7 +126,7 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
}
spin_unlock_irqrestore(&clients_lock, flags);
#ifdef CONFIG_MODULES
- if (!in_interrupt()) {
+ if (load_module) {
static DECLARE_BITMAP(client_requested, SNDRV_SEQ_GLOBAL_CLIENTS);
static DECLARE_BITMAP(card_requested, SNDRV_CARDS);

@@ -168,6 +168,20 @@ struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
return client;
}

+/* get snd_seq_client object for the given id quickly */
+struct snd_seq_client *snd_seq_client_use_ptr(int clientid)
+{
+ return client_use_ptr(clientid, false);
+}
+
+/* get snd_seq_client object for the given id;
+ * if not found, retry after loading the modules
+ */
+static struct snd_seq_client *client_load_and_use_ptr(int clientid)
+{
+ return client_use_ptr(clientid, IS_ENABLED(CONFIG_MODULES));
+}
+
/* Take refcount and perform ioctl_mutex lock on the given client;
* used only for OSS sequencer
* Unlock via snd_seq_client_ioctl_unlock() below
@@ -176,7 +190,7 @@ bool snd_seq_client_ioctl_lock(int clientid)
{
struct snd_seq_client *client;

- client = snd_seq_client_use_ptr(clientid);
+ client = client_load_and_use_ptr(clientid);
if (!client)
return false;
mutex_lock(&client->ioctl_mutex);
@@ -1195,7 +1209,7 @@ static int snd_seq_ioctl_running_mode(struct snd_seq_client *client, void *arg)
int err = 0;

/* requested client number */
- cptr = snd_seq_client_use_ptr(info->client);
+ cptr = client_load_and_use_ptr(info->client);
if (cptr == NULL)
return -ENOENT; /* don't change !!! */

@@ -1257,7 +1271,7 @@ static int snd_seq_ioctl_get_client_info(struct snd_seq_client *client,
struct snd_seq_client *cptr;

/* requested client number */
- cptr = snd_seq_client_use_ptr(client_info->client);
+ cptr = client_load_and_use_ptr(client_info->client);
if (cptr == NULL)
return -ENOENT; /* don't change !!! */

@@ -1396,7 +1410,7 @@ static int snd_seq_ioctl_get_port_info(struct snd_seq_client *client, void *arg)
struct snd_seq_client *cptr;
struct snd_seq_client_port *port;

- cptr = snd_seq_client_use_ptr(info->addr.client);
+ cptr = client_load_and_use_ptr(info->addr.client);
if (cptr == NULL)
return -ENXIO;

@@ -1503,10 +1517,10 @@ static int snd_seq_ioctl_subscribe_port(struct snd_seq_client *client,
struct snd_seq_client *receiver = NULL, *sender = NULL;
struct snd_seq_client_port *sport = NULL, *dport = NULL;

- receiver = snd_seq_client_use_ptr(subs->dest.client);
+ receiver = client_load_and_use_ptr(subs->dest.client);
if (!receiver)
goto __end;
- sender = snd_seq_client_use_ptr(subs->sender.client);
+ sender = client_load_and_use_ptr(subs->sender.client);
if (!sender)
goto __end;
sport = snd_seq_port_use_ptr(sender, subs->sender.port);
@@ -1871,7 +1885,7 @@ static int snd_seq_ioctl_get_client_pool(struct snd_seq_client *client,
struct snd_seq_client_pool *info = arg;
struct snd_seq_client *cptr;

- cptr = snd_seq_client_use_ptr(info->client);
+ cptr = client_load_and_use_ptr(info->client);
if (cptr == NULL)
return -ENOENT;
memset(info, 0, sizeof(*info));
@@ -1975,7 +1989,7 @@ static int snd_seq_ioctl_get_subscription(struct snd_seq_client *client,
struct snd_seq_client_port *sport = NULL;

result = -EINVAL;
- sender = snd_seq_client_use_ptr(subs->sender.client);
+ sender = client_load_and_use_ptr(subs->sender.client);
if (!sender)
goto __end;
sport = snd_seq_port_use_ptr(sender, subs->sender.port);
@@ -2006,7 +2020,7 @@ static int snd_seq_ioctl_query_subs(struct snd_seq_client *client, void *arg)
struct list_head *p;
int i;

- cptr = snd_seq_client_use_ptr(subs->root.client);
+ cptr = client_load_and_use_ptr(subs->root.client);
if (!cptr)
goto __end;
port = snd_seq_port_use_ptr(cptr, subs->root.port);
@@ -2073,7 +2087,7 @@ static int snd_seq_ioctl_query_next_client(struct snd_seq_client *client,
if (info->client < 0)
info->client = 0;
for (; info->client < SNDRV_SEQ_MAX_CLIENTS; info->client++) {
- cptr = snd_seq_client_use_ptr(info->client);
+ cptr = client_load_and_use_ptr(info->client);
if (cptr)
break; /* found */
}
@@ -2096,7 +2110,7 @@ static int snd_seq_ioctl_query_next_port(struct snd_seq_client *client,
struct snd_seq_client *cptr;
struct snd_seq_client_port *port = NULL;

- cptr = snd_seq_client_use_ptr(info->addr.client);
+ cptr = client_load_and_use_ptr(info->addr.client);
if (cptr == NULL)
return -ENXIO;

@@ -2193,7 +2207,7 @@ static int snd_seq_ioctl_client_ump_info(struct snd_seq_client *caller,
size = sizeof(struct snd_ump_endpoint_info);
else
size = sizeof(struct snd_ump_block_info);
- cptr = snd_seq_client_use_ptr(client);
+ cptr = client_load_and_use_ptr(client);
if (!cptr)
return -ENOENT;

@@ -2475,7 +2489,7 @@ int snd_seq_kernel_client_enqueue(int client, struct snd_seq_event *ev,
if (check_event_type_and_length(ev))
return -EINVAL;

- cptr = snd_seq_client_use_ptr(client);
+ cptr = client_load_and_use_ptr(client);
if (cptr == NULL)
return -EINVAL;

@@ -2707,7 +2721,7 @@ void snd_seq_info_clients_read(struct snd_info_entry *entry,

/* list the client table */
for (c = 0; c < SNDRV_SEQ_MAX_CLIENTS; c++) {
- client = snd_seq_client_use_ptr(c);
+ client = client_load_and_use_ptr(c);
if (client == NULL)
continue;
if (client->type == NO_CLIENT) {

Zhongqiu Han

unread,
Mar 1, 2025, 12:42:44 PM3/1/25
to syzbot+4cb9fa...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, syzbot+4cb9fa...@syzkaller.appspotmail.com, syzkall...@googlegroups.com, ti...@suse.com
> Hello,
>
> syzbot found the following issue on:
>
> HEAD commit: d082ecbc71e9 Linux 6.14-rc4
> git tree: upstream
> console output: https://syzkaller.appspot.com/x/log.txt?x=14e3d7a4580000
> kernel config:
https://syzkaller.appspot.com/x/.config?x=8f2f8fb6ad08b539
> dashboard link:
https://syzkaller.appspot.com/bug?extid=4cb9fad083898f54c517
> compiler: gcc (Debian 12.2.0-14) 12.2.0, GNU ld (GNU Binutils
for Debian) 2.40


BUG: sleeping function called from invalid context and
raw_local_irq_restore() called with IRQs enabled seems can be
fixed by below change. if it is valid, will arise the PATCH.

Zhongqiu Han

unread,
Mar 1, 2025, 12:42:50 PM3/1/25
to Takashi Iwai, syzbot+4cb9fa...@syzkaller.appspotmail.com, linux-...@vger.kernel.org, linux...@vger.kernel.org, pe...@perex.cz, syzkall...@googlegroups.com, ti...@suse.com
On 3/1/2025 5:34 PM, Takashi Iwai wrote:
Thanks Takashi for the discussion.

I have an initial check:
func snd_seq_check_queue is called from func snd_seq_timer_interrupt,
and the scoped_guard can not cover it. maybe this the reason of
!in_interrupt() check pass.

just like my patch shared, snd_timer_process_callbacks called
spin_unlock but not spin_unlock_irqrestore, which caused
irqs_disabled(): 1 , and then caused the BUG.


BUG: sleeping function called from invalid context at
kernel/locking/mutex.c:562
in_atomic(): 0, irqs_disabled(): 1, non_block: 0, pid: 1167, name:
kworker/0:1H


please feel free and kindly correct me if any misunderstanding.

>>
--
Thx and BRs,
Zhongqiu Han
Reply all
Reply to author
Forward
0 new messages