From: Takashi Iwai <tiwai@suse.de>
To: 徐晗翔 <xuhx@hust.edu.cn>
Cc: perex@perex.cz, tiwai@suse.com, linux-sound@vger.kernel.org,
linux-kernel@vger.kernel.org
Subject: Re: ALSA: ctxfi: free atimer only after the timer IRQ is quiesced
Date: Fri, 13 Nov 2026 17:30:54 +0100 [thread overview]
Message-ID: <87ik20publ.wl-tiwai@suse.de> (raw)
In-Reply-To: <57529fbf.262c8.1a1d4c65987.Coremail.xuhx@hust.edu.cn>
On Fri, 13 Nov 2026 12:58:51 +0100,
徐晗翔 wrote:
>
> `ct_timer_free()` frees `struct ct_timer` while the ctxfi timer IRQ handler can
> still be executing, or can start after `snd_card_disconnect()` has already done
> its single `synchronize_irq()`. A handler that has passed the non-atomic
> `hw->irq_callback` check then calls `ct_timer_interrupt()` with the freed
> `atimer`; `free_irq()` only runs later, inside `ct_atc_destroy()` ->
> `destroy_hw_obj()`. This is a use-after-free on the timer object and can crash
> or wedge the device during PCI removal/unbind.
>
> The detailed description:
>
> * Test environment / affected version
>
> Linux 7.3.0 source tree under review. This report is source-level only: no
> ctxfi hardware was available and QEMU has no ctxfi device model, so no
> driver-specific reproducer was run. The source paths/line numbers below are
> from 7.3.
>
> * Mechanism
>
> `ct_timer_new()` (`sound/pci/ctxfi/cttimer.c:388-411`) installs the native
> timer callback by default when `!use_system_timer && hw->set_timer_irq`:
>
> hw->irq_callback_data = atimer;
> hw->irq_callback = ct_timer_interrupt;
>
> The PCI IRQ handlers `ct_20k1_interrupt()` (`cthw20k1.c:1878-1891`) and
> `ct_20k2_interrupt()` (`cthw20k2.c:2045-2059`) do:
>
> if (hw->irq_callback)
> hw->irq_callback(hw->irq_callback_data, status);
>
> `ct_timer_interrupt()` (`cttimer.c:379-386`) then reads
> `timer->ops->interrupt` and calls it with `timer`. Neither the check nor
> the two loads is atomic.
>
> `ct_timer_free()` (`cttimer.c:414-421`) does:
>
> struct hw *hw = atimer->atc->hw;
> hw->irq_callback = NULL;
> if (atimer->ops->free_global)
> atimer->ops->free_global(atimer);
> kfree(atimer);
>
> `ct_xfitimer_free_global()` only calls `ct_xfitimer_irq_stop()`; that helper
> stops the hardware only if `atimer->running` is set (`cttimer.c:137-145`).
> It does not wait for an in-flight IRQ handler.
>
> `ct_atc_destroy()` (`ctatc.c:1250-1286`) then calls `ct_timer_free()` at
> 1257-1260, calls `destroy_hw_obj(atc->hw)` at 1274-1275, and only after that
> `kfree(atc)` at 1283. `destroy_hw_obj()` -> `hw_card_shutdown()` ->
> `free_irq()` at `cthw20k1.c:1969` / `cthw20k2.c:2140`. So `atc` itself is
> not the freed object in this window; `atimer` is freed before `free_irq()`.
>
> * Why the existing synchronization does not close the window
>
> ctxfi does set `card->sync_irq` at `cthw20k1.c:1937` / `cthw20k2.c:2104`,
> and `snd_card_disconnect()` (`sound/core/init.c:495-562`) calls
> `synchronize_irq(card->sync_irq)` once at 540-541. But that call happens
> before `ct_timer_free()`, only waits handlers that are running at that
> instant, and does not disable the IRQ line. A new handler can enter after
> the one-time sync and before `free_irq()`.
>
> The `hw->irq_callback = NULL` store does not close the race either: a
> handler that loaded the callback pointer before the store can still call it.
>
> * Trigger model
>
> Open a ctxfi device (native timer path, the default), then remove/unbind the
> PCI device while an interrupt is pending or arrives during teardown. The
> window is between `ct_timer_free()` and `free_irq()`. Consequence: UAF read
> of `atimer->ops` and timer fields in IRQ context; crash, stall, or potential
> control-flow corruption.
>
> * Suggested direction
>
> After clearing `hw->irq_callback` and calling `free_global()`, but before
> `kfree(atimer)`, do:
>
> if (hw->irq >= 0)
> synchronize_irq(hw->irq);
>
> Alternatively, move `free_irq()` earlier so it precedes the timer free.
> Keep the existing `hw->irq == -1` initialization contract.
>
>
> Please keep me in Cc; I am not subscribed to the lists.
Could you rather submit a fix patch (with a proper patch description)
for each your reported issue? You can put Link: tag to pointing to
the earlier reports.
thanks,
Takashi
next prev parent reply other threads:[~2026-11-13 16:30 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <4c7f9772.192e1.1a17d5c2ed5.Coremail.xuhx@hust.edu.cn>
[not found] ` <2026102727-data-sequel-ce41@gregkh>
2026-11-13 11:58 ` ALSA: ctxfi: free atimer only after the timer IRQ is quiesced 徐晗翔
2026-11-13 16:30 ` Takashi Iwai [this message]
2026-11-13 12:03 ` ALSA: ctxfi: do not free a running system timer when timer_delete_sync_try() returns -1 (UAF) 徐晗翔
2026-11-13 12:04 ` ALSA: asihpi: free IRQ before snd_card_free()/HPI delete on HPI6205 removal (UAF) 徐晗翔
2026-11-13 12:06 ` ALSA: asihpi: quiesce PCM timer and IRQ before freeing dpcm on close (UAF) 徐晗翔
2026-11-13 12:15 ` ALSA: pcm: link-group walk in timer callback can use a closed substream's freed runtime (UAF) 徐晗翔
2026-11-13 12:28 ` ALSA: usb-audio: us144mkii: PCM close frees runtime while playback/feedback URB completion and capture work still use it (UAF) 徐晗翔
2026-11-13 12:29 ` ALSA: usb-audio: us144mkii: queued stop_pcm_work calls snd_pcm_stop() after PCM close and dereferences NULL runtime 徐晗翔
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=87ik20publ.wl-tiwai@suse.de \
--to=tiwai@suse.de \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-sound@vger.kernel.org \
--cc=perex@perex.cz \
--cc=tiwai@suse.com \
--cc=xuhx@hust.edu.cn \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox