All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH] ALSA: seq: oss: Ignore sync echoes without a write queue
@ 2026-10-16  2:17 Cen Zhang
  2026-10-16  8:22 ` Takashi Iwai
  0 siblings, 1 reply; 2+ messages in thread
From: Cen Zhang @ 2026-10-16  2:17 UTC (permalink / raw)
  To: perex, tiwai; +Cc: linux-sound, linux-kernel, baijiaju1990, jjzuming, zzzccc427

The sync-echo callback needs a write queue before it can wake up a
synchronizing writer. However, snd_seq_oss_open() publishes the session's
port with snd_seq_oss_event_input() as its callback before allocating
and assigning dp->writeq.

A kernel caller using snd_seq_kernel_client_dispatch() with the OSS
client ID can deliver an ECHO containing SEQ_SYNCTIMER to this port
before the write queue is assigned. The helper stamps the supplied
client ID into the event, so the callback's source-client check accepts
it. Regular userspace events carry their own client ID and are rejected.

The failing ordering is:

    OSS open                          Kernel direct dispatch
    --------                          ----------------------
    Zero-allocate dp
    Set dp->cseq
    Publish callback port
                                      Dispatch ECHO as the OSS client
                                      Look up and pin that port
                                      Enter snd_seq_oss_event_input()
                                      Pass NULL to writeq_wakeup()
    Allocate and assign dp->writeq

Dispatch reaches the callback after port publication and before the
queue assignment. OSS register_mutex serializes open and release, but
direct dispatch does not take it. The port use reference keeps dp alive
through the callback; it does not wait for constructor initialization.
The wakeup helper therefore attempts to acquire sync_lock through a
NULL queue pointer, causing a fault.

Sample dp->writeq once in the SEQ_SYNCTIMER branch and ignore the echo
when the queue is absent, matching the adjacent read-queue check. Pass
the checked pointer to the wakeup helper so a NULL sample cannot reach
the lock access. The existing port reference protects the queue's
lifetime through this call, since port deletion drains callbacks before
free_devinfo() frees the queue.

KASAN report as below:

    Oops: general protection fault, probably for non-canonical address 0xdffffc000000000d: 0000 [#1] SMP KASAN NOPTI
    KASAN: null-ptr-deref in range [0x0000000000000068-0x000000000000006f]
    CPU: 2 UID: 0 PID: 69 Comm: kworker/2:1 Tainted: G        W           7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
    Tainted: [W]=WARN
    Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    Workqueue: events pmbd_dispatch_early_sync_echo
    RIP: 0010:do_raw_spin_lock+0x71/0x270
    Code: d0 60 81 49 8d 14 04 c7 02 f1 f1 f1 f1 c7 42 04 04 f3 f3 f3 65 48 8b 15 05 df 88 09 48 89 54 24 60 31 d2 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 b9
    RSP: 0018:ffff88810450f878 EFLAGS: 00010013
    RAX: dffffc0000000000 RBX: 0000000000000068 RCX: 0000000000000000
    RDX: 000000000000000d RSI: 0000000000000000 RDI: 000000000000006c
    RBP: 0000000000000293 R08: 0000000000000001 R09: 0000000000000000
    R10: ffffffff8940fe57 R11: 0000000000000000 R12: 1ffff110208a1f10
    R13: 0000000000000068 R14: 0000000000000001 R15: ffff88810450fbee
    FS:  0000000000000000(0000) GS:ffff8881fd885000(0000) knlGS:0000000000000000
    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00000000006d2890 CR3: 0000000106cbf002 CR4: 0000000000770ef0
    PKRU: 55555554
    Call Trace:
     <TASK>
     ? pmbd_probe_hit_cookie+0xee/0x1c0
     ? __pfx_do_raw_spin_lock+0x10/0x10
     ? lock_acquire+0x2b8/0x2f0
     ? __pfx_pmbd_probe_hit_cookie+0x10/0x10
     _raw_spin_lock_irqsave+0x44/0x60
     ? snd_seq_oss_writeq_wakeup+0x30/0xf0
     snd_seq_oss_writeq_wakeup+0x30/0xf0
     snd_seq_oss_event_input+0x1e4/0x2a0
     ? do_raw_read_unlock+0x49/0xe0
     ? __pfx_snd_seq_oss_event_input+0x10/0x10
     __snd_seq_deliver_single_event+0x105/0x1a0
     ? snd_seq_port_use_ptr+0x111/0x170
     snd_seq_deliver_single_event+0x2fc/0x770
     ? __pfx_snd_seq_deliver_single_event+0x10/0x10
     ? __pfx_pmbd_hold_maybe+0x10/0x10
     snd_seq_deliver_event+0x45a/0x760
     ? __pfx_do_raw_spin_lock+0x10/0x10
     ? lock_acquire+0x2b8/0x2f0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_snd_seq_deliver_event+0x10/0x10
     ? _raw_spin_unlock_irqrestore+0x44/0x60
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? trace_hardirqs_on+0x18/0x160
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? _raw_spin_unlock_irqrestore+0x44/0x60
     ? srso_alias_return_thunk+0x5/0xfbef5
     snd_seq_kernel_client_dispatch+0x19c/0x1e0
     pmbd_dispatch_early_sync_echo+0x121/0x1c0
     ? __pfx_pmbd_dispatch_early_sync_echo+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? finish_task_switch.isra.0+0x1dc/0x980
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __kthread_parkme+0x175/0x220
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>
    Modules linked in:
    ---[ end trace 0000000000000000 ]---
    RIP: 0010:do_raw_spin_lock+0x71/0x270
    Code: d0 60 81 49 8d 14 04 c7 02 f1 f1 f1 f1 c7 42 04 04 f3 f3 f3 65 48 8b 15 05 df 88 09 48 89 54 24 60 31 d2 48 89 fa 48 c1 ea 03 <0f> b6 14 02 48 89 f8 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 b9
    RSP: 0018:ffff88810450f878 EFLAGS: 00010013
    RAX: dffffc0000000000 RBX: 0000000000000068 RCX: 0000000000000000
    RDX: 000000000000000d RSI: 0000000000000000 RDI: 000000000000006c
    RBP: 0000000000000293 R08: 0000000000000001 R09: 0000000000000000
    R10: ffffffff8940fe57 R11: 0000000000000000 R12: 1ffff110208a1f10
    R13: 0000000000000068 R14: 0000000000000001 R15: ffff88810450fbee
    FS:  0000000000000000(0000) GS:ffff8881fd885000(0000) knlGS:0000000000000000
    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: 00000000006d2890 CR3: 0000000106cbf002 CR4: 0000000000770ef0
    PKRU: 55555554
    Kernel panic - not syncing: Fatal exception
    Kernel Offset: disabled
    Rebooting in 1 seconds..

Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
---

diff --git a/sound/core/seq/oss/seq_oss_event.c b/sound/core/seq/oss/seq_oss_event.c
index 122735862044dcc9942ed0f79d4d88f2e0d6f4ba..3c2cfaea94d1de14f70e24ada73172fe6afb75b0 100644
--- a/sound/core/seq/oss/seq_oss_event.c
+++ b/sound/core/seq/oss/seq_oss_event.c
@@ -433,8 +433,12 @@ snd_seq_oss_event_input(struct snd_seq_event *ev, int direct, void *private_data
 
 	rec = (union evrec*)&ev->data;
 	if (rec->s.code == SEQ_SYNCTIMER) {
+		struct seq_oss_writeq *writeq = READ_ONCE(dp->writeq);
+
+		if (!writeq)
+			return 0;
 		/* sync echo back */
-		snd_seq_oss_writeq_wakeup(dp->writeq, rec->t.time);
+		snd_seq_oss_writeq_wakeup(writeq, rec->t.time);
 		
 	} else {
 		/* echo back event */

^ permalink raw reply related	[flat|nested] 2+ messages in thread

end of thread, other threads:[~2026-10-16  8:22 UTC | newest]

Thread overview: 2+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16  2:17 [PATCH] ALSA: seq: oss: Ignore sync echoes without a write queue Cen Zhang
2026-10-16  8:22 ` Takashi Iwai

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.