| Age | Commit message (Collapse) | Author |
|
https://git.kernel.org/pub/scm/linux/kernel/git/mm/linux.git
# Conflicts:
# arch/alpha/Kconfig
# arch/arm64/mm/pageattr.c
# arch/um/Kconfig
# fs/coredump.c
# fs/xfs/libxfs/xfs_btree.c
|
|
There's no need to keep a fault handler around for this, instead map on
mmap.
While we're here, rename area to vma to be consistent.
This correctly makes the mapping a mixed map mapping.
This works towards establishing the invariant that only PFN mapped or mixed
map mappings may clear the VM_MAYWRITE flag. The status page mapping clears
VM_MAYWRITE, so it must not be mm-managed; the control page mapping remains
writable and is left fault-based.
The assumption is made that the struct pcm_mmap_status structure is at most
a page in size, which is asserted as a build bug.
This is safe to assume, as the size of the structure is 56 bytes at most.
Link: https://lore.kernel.org/20261013-b4-mmap-prepare-vma-flag-sanify-v6-13-1aa3c9b139f9@kernel.org
Signed-off-by: Lorenzo Stoakes (ARM) <ljs@kernel.org>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Acked-by: Takashi Iwai <tiwai@suse.de>
Reviewed-by: Suren Baghdasaryan <surenb@google.com>
Cc: Liam R. Howlett <liam@infradead.org>
Cc: Vlastimil Babka <vbabka@kernel.org>
Cc: Jann Horn <jannh@google.com>
Cc: Pedro Falcato <pfalcato@suse.de>
Cc: David Hildenbrand <david@kernel.org>
Cc: Mike Rapoport <rppt@kernel.org>
Cc: Michal Hocko <mhocko@suse.com>
Cc: Jonathan Corbet <corbet@lwn.net>
Cc: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Cc: Dennis Dalessandro <dennis.dalessandro@cornelisnetworks.com>
Cc: Jason Gunthorpe <jgg@ziepe.ca>
Cc: Leon Romanovsky <leon@kernel.org>
Cc: Paul Moore <paul@paul-moore.com>
Cc: Stephen Smalley <stephen.smalley.work@gmail.com>
Cc: Jaroslav Kysela <perex@perex.cz>
Cc: Takashi Iwai <tiwai@suse.com>
Cc: Alexei Starovoitov <ast@kernel.org>
Cc: Daniel Borkmann <daniel@iogearbox.net>
Cc: Andrii Nakryiko <andrii@kernel.org>
Cc: Eduard Zingerman <eddyz87@gmail.com>
Cc: Kumar Kartikeya Dwivedi <memxor@gmail.com>
Cc: Zi Yan <ziy@nvidia.com>
Cc: Baolin Wang <baolin.wang@linux.alibaba.com>
Cc: Nico Pache <nico.pache@linux.dev>
Cc: Ryan Roberts <ryan.roberts@arm.com>
Cc: Dev Jain <dev.jain@arm.com>
Cc: Barry Song <baohua@kernel.org>
Cc: Lance Yang <lance.yang@linux.dev>
Cc: Usama Arif <usama.arif@linux.dev>
Cc: Kiryl Shutsemau <kas@kernel.org>
Cc: Doug Gilbert <dgilbert@interlog.com>
Cc: James Bottomley <james.bottomley@hansenpartnership.com>
Cc: Martin K. Petersen <mkp@kernel.org>
Cc: Simona Vetter <simona@ffwll.ch>
Cc: Helge Deller <deller@gmx.de>
Cc: Sebastian Reichel <sre@kernel.org>
Cc: John Hubbard <jhubbard@nvidia.com>
Cc: Peter Xu <peterx@redhat.com>
Cc: Masami Hiramatsu <mhiramat@kernel.org>
Cc: Oleg Nesterov <oleg@redhat.com>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Ingo Molnar <mingo@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Dave Hansen <dave.hansen@linux.intel.com>
Cc: Arnaldo Carvalho de Melo <acme@kernel.org>
Cc: Namhyung Kim <namhyung@kernel.org>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: Rik van Riel <riel@surriel.com>
Cc: Harry Yoo <harry@kernel.org>
Cc: Juri Lelli <juri.lelli@redhat.com>
Cc: Vincent Guittot <vincent.guittot@linaro.org>
Cc: Maarten Lankhorst <maarten.lankhorst@linux.intel.com>
Cc: Maxime Ripard <mripard@kernel.org>
Cc: Thomas Zimmermann <tzimmermann@suse.de>
Cc: David Airlie <airlied@gmail.com>
Cc: Will Deacon <will@kernel.org>
Cc: Aneesh Kumar K.V <aneesh.kumar@kernel.org>
Cc: Nicholas Piggin <npiggin@gmail.com>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Muchun Song <muchun.song@linux.dev>
Cc: Oscar Salvador <osalvador@suse.de>
Cc: Matthew Wilcox (Oracle) <willy@infradead.org>
Cc: Jan Kara <jack@suse.cz>
Cc: Marc Zyngier <maz@kernel.org>
Cc: Oliver Upton <oupton@kernel.org>
Cc: Catalin Marinas <catalin.marinas@arm.com>
Cc: Madhavan Srinivasan <maddy@linux.ibm.com>
Cc: Anup Patel <anup@brainfault.org>
Cc: Paul Walmsley <pjw@kernel.org>
Cc: Palmer Dabbelt <palmer@dabbelt.com>
Cc: Albert Ou <aou@eecs.berkeley.edu>
Cc: Christian Borntraeger <borntraeger@linux.ibm.com>
Cc: Janosch Frank <frankja@linux.ibm.com>
Cc: Claudio Imbrenda <imbrenda@linux.ibm.com>
Cc: Alexander Gordeev <agordeev@linux.ibm.com>
Cc: Gerald Schaefer <gerald.schaefer@linux.ibm.com>
Cc: Heiko Carstens <hca@linux.ibm.com>
Cc: Vasily Gorbik <gor@linux.ibm.com>
Cc: David S. Miller <davem@davemloft.net>
Cc: Andreas Larsson <andreas@gaisler.com>
Cc: Al Viro <viro@zeniv.linux.org.uk>
Cc: Christian Brauner <brauner@kernel.org>
Cc: Matthew Brost <matthew.brost@intel.com>
Cc: Joshua Hahn <joshua.hahnjy@gmail.com>
Cc: Rakie Kim <rakie.kim@sk.com>
Cc: Byungchul Park <byungchul@sk.com>
Cc: Gregory Price <gourry@gourry.net>
Cc: Ying Huang <ying.huang@linux.alibaba.com>
Cc: Alistair Popple <apopple@nvidia.com>
Cc: Chris Li <chrisl@kernel.org>
Cc: Kairui Song <kasong@tencent.com>
Cc: Kemeng Shi <shikemeng@huaweicloud.com>
Cc: Nhat Pham <nphamcs@gmail.com>
Cc: Baoquan He <baoquan.he@linux.dev>
Cc: Youngjun Park <youngjun.park@lge.com>
Cc: Johannes Weiner <hannes@cmpxchg.org>
Cc: Qi Zheng <qi.zheng@linux.dev>
Cc: Shakeel Butt <shakeel.butt@linux.dev>
Cc: Axel Rasmussen <axelrasmussen@google.com>
Cc: Yuanchu Xie <yuanchu@google.com>
Cc: Wei Xu <weixugc@google.com>
Cc: Chengming Zhou <chengming.zhou@linux.dev>
Cc: Michal Hocko <mhocko@kernel.org>
Cc: Miklos Szeredi <miklos@szeredi.hu>
Cc: Xu Xin <xu.xin@linux.dev>
Cc: Ihor Solodrai <ihor.solodrai@linux.dev>
Cc: Bert Karwatzki <spasswolf@web.de>
|
|
snd_compr_task_start_prepare() only rejects tasks with
state >= SND_COMPRESS_TASK_STATE_FINISHED. Since the enum is
IDLE(0) < ACTIVE(1) < FINISHED(2), this accepts ACTIVE tasks and
rejects FINISHED ones, the opposite of what the origin_seqno
mechanism needs: origin_seqno is meant to let a caller reuse a
FINISHED task's buffers for a new job, not to restart a task that is
still queued with the driver.
The seqno lookup path in snd_compr_task_start() has its own explicit
"task->state != IDLE" guard, but the origin_seqno lookup path relies
solely on this function, so it can restart an ACTIVE task, causing
ops->task_start() to be called twice for the same task and
runtime->active_tasks to be incremented twice without a matching
finish/stop.
Accept IDLE and FINISHED, reject ACTIVE, on both entry paths.
Fixes: 04177158cf98 ("ALSA: compress_offload: introduce accel operation mode")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Acked-by: Vinod Koul <vkoul@kernel.org>
Link: https://patch.msgid.link/20261019144533.30665-5-peter.ujfalusi@linux.intel.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
snd_compr_set_metadata() calls stream->ops->set_metadata() straight
after copy_from_user(), without ever checking runtime->state, even
though the function's own comment says a parameter change should only
be allowed once the stream has left the OPEN state. Every other
metadata/param entry point in this file (SET_PARAMS, WRITE, ...)
enforces that gate.
A codec driver's set_metadata callback can assume SET_PARAMS has
already run and initialised its private state; calling it while the
stream is still OPEN can operate on that uninitialised state.
Add the OPEN-state check the existing comment already documents.
Fixes: 9727b490e543 ("ALSA: compress: add support for gapless playback")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Acked-by: Vinod Koul <vkoul@kernel.org>
Link: https://patch.msgid.link/20261019144533.30665-4-peter.ujfalusi@linux.intel.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
snd_compr_set_params() is invoked from the gapless next_track
re-entry path, which calls snd_compr_allocate_buffer() again and lets
buffer_size change while total_bytes_available and
total_bytes_transferred still hold values computed for the previous
buffer. snd_compr_calc_avail() then derives an avail/count value from
those stale counters against the new buffer_size, and
snd_compr_write_data() copy_from_user()s that many bytes into the
new, potentially smaller buffer, overflowing it with user-controlled
length and content.
The buffer is set up once, with the initial SET_PARAMS, and neither the
core nor the DSP expects it to change for a gapless track transition.
Do not call snd_compr_allocate_buffer() on the next_track path and
reject a request that changes the buffer geometry, so that the codec
parameters that the driver receives match the buffer in use.
Fixes: 9727b490e543 ("ALSA: compress: add support for gapless playback")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://patch.msgid.link/20261019144533.30665-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
When the driver has neither ops->copy nor a preallocated dma_buffer_p,
snd_compr_allocate_buffer() kmallocs runtime->buffer. If
ops->set_params() then rejects the parameters, SET_PARAMS fails, the
stream stays in the OPEN state and keeps the buffer. The next
SET_PARAMS allocates a new buffer and overwrites the pointer, so
repeated SET_PARAMS calls with parameters that the driver rejects leak
one buffer per call.
Release the framework-owned buffer when ops->set_params() fails on an
OPEN stream, so that a failed SET_PARAMS leaves no buffer behind and
the buffer is allocated only once per successful setup. Use the same
ownership check as snd_compr_free().
Fixes: b21c60a4edd2 ("ALSA: core: add support for compress_offload")
Cc: stable@vger.kernel.org
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://patch.msgid.link/20261019144533.30665-2-peter.ujfalusi@linux.intel.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
https://git.kernel.org/pub/scm/linux/kernel/git/broonie/sound into for-linus
ASoC: Updates for v7.4
There's an awful lot of cleanup work in this pull request, lots from Bui
Duc Phuc, Pengpeng Hou, HyeongJun An and Chancel Liu cleaning up detail
issues in drivers in addition to Mormoto-san's ongoing framework work.
This time Morimoto-san's work included enabling auto_selectable_formats
so there's less manual configuration required for DAI links.
There's also been a huge amount of upstreaming activity from Qualcomm,
some pain there but hopefully enough has now landed for things to be
smoother in future.
- Use auto_selectable_formats in most drivers to reduce the amount of
manual configuration required for DAI links.
- Support for compressed audio on SOF IPC4 systems.
- Support for AMD ACP 7.B and 7.F, AmLogic A9 and T7, Airoha AN7581,
ESS Technology ES9039Q2M, Intel Cherry Trail with RT5688, Nuvoton
NAU83G60, nVidia systems with WM8994, Qualcomm QAIF, Senary I2S, WCD9378
and various platforms, Realtek RT766 and RT767, Senary SN624x
I also mistakenly merged some SPI changes in here then applied more
patches on top before I noticed (it looks like this was b4's base
selection logic picking a bad base for some ASoC work), highlights there
are:
- Improvements for spidev_test to cover additional use cases, plus be a
bit easier to use.
- Push more Tegra210 QSPI handling into interrupt context for
performance improvements.
- Support for Qualcomm QPIC SNAND v2 and RealTek RTD1625 NOR.
- Documentation clarifications.
- Fixes for some runtime PM and error handling issues.
- Support for R-Car Gen5.
(this should also be going in via my SPI pull request)
|
|
Channel-map controls remain accessible between PCM opens. In-tree HDA
code publishes the generic controls through add_std_chmaps(), so a
SNDRV_CTL_IOCTL_ELEM_READ can overlap the final close of the same PCM
substream.
pcm_chmap_ctl_get() checks substream->runtime and later reads its channel
count. Final close clears and frees that runtime under pcm->open_mutex,
while the control callback holds only controls_rwsem:
Control GET Final PCM close
----------- ---------------
snd_ctl_elem_read()
down_read(controls_rwsem)
pcm_chmap_ctl_get()
check substream->runtime
lock(pcm->open_mutex)
snd_pcm_release_substream()
snd_pcm_detach_substream()
substream->runtime = NULL
kfree(runtime)
unlock(pcm->open_mutex)
substream->runtime->channels
NULL or freed-pointer access
up_read(controls_rwsem)
Reloading the cleared field can fault through NULL, while retaining the
old pointer can access freed storage. controls_rwsem keeps the control
alive, but does not serialize the matching PCM close.
Copy the channel count under open_mutex and use that scalar for the map
lookup. Use trylock with -EBUSY because snd_pcm_dev_disconnect() takes
open_mutex before removing controls under controls_rwsem; blocking in
the reverse order from GET could deadlock.
Fixes: 2d3391ec0ecc ("ALSA: PCM: channel mapping API implementation")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-0b5d6bc7124d0b921f2c-v4-b9738bdeab8823999181@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
With CONFIG_SND=m and CONFIG_SND_JACK_INJECTION_DEBUG enabled, an in-tree
HDA jack creates these debugfs files through snd_jack_new() and
snd_jack_add_debugfs(). Their file_operations live in snd, but none sets
.owner. full_proxy_open_regular() therefore takes no snd module reference
when it calls fops_get(real_fops).
A debugfs descriptor can outlive removal of its HDA card. Once the card
and dependent modules, including the OSS emulation modules, have been
removed, snd can be unloaded while that descriptor is still open:
Descriptor holder Card/module teardown
----------------- --------------------
open jack debugfs file
full_proxy_open_regular()
fops_get(real_fops)
owner == NULL: no snd pin
keep descriptor open
remove HDA card
snd_card_disconnect()
snd_jack_dev_disconnect()
remove debugfs nodes
snd_jack_dev_free()
unload dependent modules
rmmod snd
alsa_sound_exit()
free_module(): unmap snd
close descriptor
full_proxy_release()
read real_fops->release
fops_put(real_fops)
read real_fops->owner
debugfs_remove() drains active operations, but does not wait for idle
open descriptors. Release deliberately bypasses removal protection and
reads the real table even when no release callback is installed. The
last close can therefore access unloaded snd storage.
Set .owner to THIS_MODULE in all six tables. The existing proxy
fops_get()/fops_put() pair then keeps snd loaded through the final table
access on close.
Fixes: 2d670ea2bd53 ("ALSA: jack: implement software jack injection via debugfs")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-431ddb947e1a13b95d3a-v3-02d37dd7b4eb4774e100@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
A late HDA codec bind on an already registered card builds new PCMs
before registering them. add_std_chmaps() publishes generic channel-map
controls during this BUILD stage. If an earlier chmap succeeds and a
later allocation fails, probe cleanup frees the BUILD PCM while the
card's control device remains accessible.
These generic controls are added directly by snd_pcm_add_chmap_ctls();
snd_hda_ctls_clear() only removes codec-tracked mixer controls. BUILD
devices also skip dev_disconnect. snd_pcm_free_stream() then frees the
substreams before free_chmap() withdraws their generic control:
Late HDA codec bind / rollback Control GET on the live card
------------------------------ ----------------------------
hda_codec_driver_probe()
snd_hda_codec_build_pcms()
PCM is BUILD
snd_hda_codec_build_controls()
add_std_chmaps()
publish an earlier chmap
later allocation: -ENOMEM
snd_hda_codec_cleanup_for_unbind()
snd_hda_ctls_clear()
generic chmap remains
codec_release_pcms()
snd_device_free()
BUILD: skip dev_disconnect
snd_pcm_free_stream()
kfree(substream)
snd_ctl_elem_read()
down_read(controls_rwsem)
pcm_chmap_ctl_get()
walk freed substream
free_chmap()
snd_ctl_remove()
wait for GET
up_read(controls_rwsem)
The control read lock cannot protect a substream already freed before
control removal starts. The failure above occurs before
snd_card_register(), so the PCM has not transitioned out of BUILD.
Move free_chmap() before the substream free loop. Its snd_ctl_remove()
withdraws the control and drains readers under controls_rwsem before any
substream is released. Normal registered-device disconnect already
removes the control, so the later call remains harmless on that path.
Fixes: 2d3391ec0ecc ("ALSA: PCM: channel mapping API implementation")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-4a207d9ef3a3597a74a4-v4-80b0113669b1a62fbbe9@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
OSS proc entries and notifier callbacks can remain in use without an
open OSS device file. Normal snd-pcm-oss removal can therefore delete
an existing PCM's OSS proc entry while late HDA codec binding repeats
snd_card_register() on the same live card:
OSS PCM module unload Card registration
--------------------- -----------------
snd_info_free_entry(entry)
proc_remove(entry->p)
clear entry->p
snd_info_card_register()
republish linked entry
unlink and free entry
The new proc node retains a pointer to freed storage. Mixer OSS removal
can likewise release an adapter while a card notification still uses it.
Hold a snd-pcm-oss module reference for each PCM registered with its
notifier and a snd-mixer-oss reference for each card adapter. Release
them at final unregister or FREE, after proc and adapter cleanup. Normal
module unload can no longer initiate removal while these objects exist.
Track PCM OSS registration with a separate bool registered. Unlike
oss.reg, this state also covers unmapped PCMs and remains set across
DISCONNECT until final unregister. BUILD-state and creation-error cleanup
must not drop a reference when registration never acquired one. The PCM
notifier's register_mutex serialization keeps the final put ahead of
notifier removal and module teardown until dispatch has finished.
For mixer OSS, serialize callback publication, dispatch and withdrawal
in the core so module exit waits for callbacks, including one dropping
the last reference, to return. Keep card enumeration in the OSS module,
with card references released after dispatch drops the mutex. Ignore
duplicate REGISTER notifications so a delayed registration cannot
replace an adapter retained across DISCONNECT and leak its module pin.
Partial HDA codec teardown can still remove an individual PCM while the
card remains registered; its object-lifetime handling is separate.
Fixes: 2471b6c80a70 ("ALSA: info: Register proc entries recursively, too")
Suggested-by: Takashi Iwai <tiwai@suse.de>
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/pm-pmb-26d66390a25fec9fad6c-v6-5be251a3ac8832955a31-2@gmail.com
|
|
snd_pcm_free() traverses snd_pcm_notify_list and calls n_unregister
without register_mutex, although snd_pcm_notify() takes that mutex to
add and remove notifiers. PCM disconnect releases the mutex before the
free callback runs, so it does not protect this later traversal.
With no open OSS file, normal snd-pcm-oss removal can overlap PCM card
teardown, for example when unbinding snd-dummy:
PCM card teardown snd-pcm-oss unload
----------------- ------------------
snd_pcm_dev_disconnect()
remove PCM under register_mutex
unlock register_mutex
snd_pcm_free()
fetch notifier
snd_pcm_notify(..., 1)
unlink notifier under mutex
free module storage
read notifier->n_unregister
invoke callback
The free path can then read the notifier from released module storage
or call its unloaded code.
Hold register_mutex across the unregister traversal and its callbacks.
Notifier removal must wait until both have finished. This also protects
the traversal if a callback releases the last module reference: module
exit cannot unlink its notifier until the free path releases the mutex.
Drop the mutex before private_free and the remaining stream cleanup.
Fixes: c461482c8072 ("[ALSA] Unregister device files at disconnection")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/pm-pmb-26d66390a25fec9fad6c-v6-5be251a3ac8832955a31-1@gmail.com
|
|
A control found during a jack-name index scan must remain alive until
snd_ctl_find_id() finishes comparing its ID and count. However,
get_available_index() calls it without holding card->controls_rwsem.
With CONFIG_SND_CTL_FAST_LOOKUP enabled, the lookup loads a raw control
pointer from ctl_hash and dereferences it in elem_id_matches() without
any lock that excludes removal.
This can happen when a jack is created while a different jack owner on
the same card removes an existing control with the same name and index.
For example, probe and unbind of different HDA codecs can reach these
paths on a shared card if their generated jack names match.
The codec device locks do not serialize operations on different
codecs. The unbind path can free the control during the index scan:
Codec A: probe Codec B: unbind
-------------- ---------------
get_available_index()
snd_ctl_find_id()
kctl = xa_load(...)
hda_codec_driver_remove()
snd_hda_codec_cleanup_for_unbind()
snd_hda_jack_tbl_clear()
snd_device_free()
__snd_device_free()
snd_jack_dev_free()
snd_ctl_remove()
snd_ctl_remove_locked()
__snd_ctl_remove()
snd_ctl_free_one()
kfree(kctl)
elem_id_matches(kctl, ...)
read freed id/count -> UAF
Hold controls_rwsem for read across the index scan so removal cannot
free a control until the lookup has finished using it. Release the lock
when get_available_index() returns, before the caller adds the new
control under the write lock.
Fixes: 38ea4c3dc306 ("ALSA: control: Optimize locking for look-up")
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Assisted-by: LLM
Link: https://patch.msgid.link/pm-pmb-f08c844bb1163c8d4fa1-v2-2f3c99e40f90134846ee@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
When an OSS sequencer device is opened, it creates a sequencer port,
then further initializes the internal states like a timer instance,
etc. Since the sequencer port is published, an event can be already
delivered, and this may hit unexpected event handling, which can
eventually cause a NULL dereference (like the timer start/stop event
triggered before the timer initialization).
For avoiding such a race, introduce a simple guard and skips the event
processing until the port is fully initialized.
At releasing the device, in turn, clear this guard, so that any input
events will be discarded during the teardown.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Cc: <stable@vger.kernel.org>
Link: https://patch.msgid.link/20261016161930.482309-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Currently we add debugfs interfaces for jack injection (with
CONFIG_SND_JACK_INJECTION_DEBUG) at creating jack kctls in
snd_jack_kctl_add(). This means that those debugfs interfaces are
already exposed to user-space at the early probe phase -- that is, it
allows user-space already fiddling with it, while other components are
still being initialized and hidden until snd_card_register().
Depending on the driver implementation, such behavior can be an
unpleasant surprise.
For aligning the device exposure behavior, move the debugfs
registration at the device register phase, too. snd_jack_kctl_add()
may still add the corresponding debugfs interfaces (for the
dynamically added jacks, if any), but it's done only conditionally
after the card has been registered.
Reviewed-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261016140653.4406-1-tiwai@suse.de
|
|
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>
Link: https://patch.msgid.link/pm-pmb-3634251be738461947da-v2-64371e8c8d6cbf6956a3@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
A control selected by snd_ctl_add_followers() must remain alive until
_snd_ctl_add_follower() has copied it and installed its wrapper. The
lookup returns a raw pointer without retaining the control, and neither
the short-lived list lookup lock nor the fast lookup protects later use.
If a kernel client adds followers to a live virtual master while another
client removes or replaces a published follower, the following order is
possible, with the card and master kept alive:
Follower setup Control removal
snd_ctl_add_followers()
snd_ctl_find_id_mixer()
return follower
snd_ctl_remove()
down_write(controls_rwsem)
__snd_ctl_remove()
unlink follower
snd_ctl_free_one(follower)
up_write(controls_rwsem)
_snd_ctl_add_follower()
read follower->count
Removal completes after lookup returns and before setup reads the
control. Since setup holds neither controls_rwsem nor a reference, the
count read and subsequent control copies can access freed memory.
Hold controls_rwsem for writing across the lookup and follower setup.
This prevents removal or replacement from freeing the selected control
until wrapper installation is complete. Write ownership also excludes
control callbacks while setup changes the callback and private fields.
KASAN report as below:
BUG: KASAN: slab-use-after-free in _snd_ctl_add_follower+0x452/0x520
Read of size 4 at addr ffff888107957d50 by task loadmodule/491
CPU: 3 UID: 0 PID: 491 Comm: loadmodule Tainted: G O 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
Tainted: [O]=OOT_MODULE
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
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? _snd_ctl_add_follower+0x452/0x520
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? _snd_ctl_add_follower+0x452/0x520
kasan_report+0xe0/0x110
? _snd_ctl_add_follower+0x452/0x520
_snd_ctl_add_follower+0x452/0x520
snd_ctl_add_followers+0x153/0x2b0
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_snd_ctl_add_followers+0x10/0x10
? __might_fault+0x135/0x190
? srso_alias_return_thunk+0x5/0xfbef5
? __might_fault+0x14e/0x190
? __pfx_fixture_write+0x10/0x10 [pmbd_vmaster_fixture]
fixture_write+0x174/0x1f0 [pmbd_vmaster_fixture]
? __pfx_fixture_write+0x10/0x10 [pmbd_vmaster_fixture]
? __pfx___might_resched+0x10/0x10
proc_reg_write+0x1fb/0x2d0
vfs_write+0x25a/0x1010
? __pfx_proc_reg_write+0x10/0x10
? kmem_cache_free+0x242/0x580
? __pfx_vfs_write+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? putname+0x93/0xe0
? srso_alias_return_thunk+0x5/0xfbef5
? do_sys_openat2+0x12a/0x1b0
? __pfx_do_sys_openat2+0x10/0x10
ksys_write+0x111/0x200
? __pfx_ksys_write+0x10/0x10
? irqentry_exit+0xbe/0x820
? srso_alias_return_thunk+0x5/0xfbef5
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f0b835a9687
Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
RSP: 002b:00007ffc82ea0360 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f0b83517780 RCX: 00007f0b835a9687
RDX: 0000000000000005 RSI: 0000564f8a21d074 RDI: 0000000000000003
RBP: 0000000000000003 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000000
R13: 00007ffc82ea04f0 R14: 00007f0b83755000 R15: 0000564f8a21ed78
</TASK>
Allocated by task 485:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_noprof+0x2d7/0x770
snd_ctl_new+0x51/0x190
snd_ctl_new1+0x13c/0x650
0xffffffffc04011b5
do_one_initcall+0xf3/0x4e0
do_init_module+0x281/0x8e0
load_module+0x658c/0x7cc0
init_module_from_file+0x15b/0x180
idempotent_init_module+0x22d/0x770
__x64_sys_finit_module+0xd2/0x160
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 492:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
__snd_ctl_remove+0x2ac/0x3d0
snd_ctl_remove+0x46/0x70
fixture_write+0x1ae/0x1f0 [pmbd_vmaster_fixture]
proc_reg_write+0x1fb/0x2d0
vfs_write+0x25a/0x1010
ksys_write+0x111/0x200
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the object at ffff888107957d00
which belongs to the cache kmalloc-192 of size 192
The buggy address is located 80 bytes inside of
freed 192-byte region [ffff888107957d00, ffff888107957dc0)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x107957
flags: 0x200000000000000(node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000000 ffff8881000423c0 dead000000000100 dead000000000122
raw: 0000000000000000 0000000000100010 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888107957c00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888107957c80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff888107957d00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff888107957d80: fb fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ffff888107957e00: 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00
==================================================================
Fixes: ae07eb9bf23e ("ALSA: vmaster: Add snd_ctl_add_followers() helper")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-6c0b7e841529ddd0b21a-v2-b53dbcd593a7a4bd9582@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Capture hardware can produce samples after the last PCM pointer update.
Drain must refresh those pointers before stopping capture, or its final
availability check can miss the remaining frames. With linked hardware,
the first STOP may freeze other members, so refresh all running members
before entering the drain action.
Factor the traversal into snd_pcm_update_linked_hw_ptr(). Hold
snd_pcm_link_rwsem for reading to keep membership stable during that
traversal, and take each member's stream lock for its ordinary
snd_pcm_update_hw_ptr() call. Include running playback streams and invoke
the helper after pause resume so paused capture also receives its final
update. Keep pause and drain-init outside the helper's rwsem scope.
Updating a pointer inside the group drain action can enter the XRUN stop
path and recursively acquire the group lock. The helper runs before that
action, so an update error follows the existing group XRUN path and is
returned to the caller before drain-init.
Suggested-by: Takashi Iwai <tiwai@suse.de>
Link: https://lore.kernel.org/all/87jynkcn60.wl-tiwai@suse.de/
Assisted-by: LLM
Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>
Link: https://patch.msgid.link/v5-core-capture-drain-2.e9b40d3bc08c4162@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Capture drain can leave buffered samples in DRAINING, but the transfer
state check rejects reads in that state. Allow capture reads to consume
the remaining frames while preserving the playback state check.
When drain wakes a blocked capture reader, return the actual available
frame count from wait_for_avail(). A zero count would make the transfer
loop discard a nonempty tail. Finish capture EOF with snd_pcm_drain_done()
so the state transition applies to that substream and leaves a linked
playback stream draining its queued data.
Allow capture hwsync to use the cached final pointer in DRAINING. Capture
has already stopped, so DELAY and SYNC_PTR(HWSYNC) can report its remaining
frames without another driver pointer callback. Playback retains its
existing pointer update.
Synthetic atomic and nonatomic tests reproduce dropped tail frames,
linked playback stopping at capture EOF, and rejected position queries.
With this change, a blocked read gets all 64 tail frames, playback stays
DRAINING at capture EOF, and the queries succeed with no extra callback.
Assisted-by: LLM
Signed-off-by: Joonho Lee <mynameisjune111@gmail.com>
Link: https://patch.msgid.link/v5-core-capture-drain-1.e9b40d3bc08c4162@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
OSS mixer slot callbacks require an initialized private_data payload.
However, snd_mixer_oss_notify_handler() publishes card->mixer_oss before
snd_mixer_oss_build() constructs the default bindings, and
snd_mixer_oss_build_input() stores get_volume before private_data.
With OSS mixer emulation enabled and a native control matching a default
mapping, a volume read can arrive during initial binding construction.
For example, the dummy card provides the Master Volume control before
registration. The following ordering lets the read use the callback
before its payload is attached:
Card registration OSS volume read
----------------- ---------------
register the OSS mixer device
publish card->mixer_oss
store slot->get_volume
open the mixer device
lock reg_mutex
invoke slot->get_volume
load NULL private_data
read slot->present
store slot->private_data
The read holds reg_mutex, but the initial builder does not acquire it.
The controls_rwsem read lock protects native controls and does not
serialize the builder with another reader. As a result,
snd_mixer_oss_get_volume1() can dereference a NULL payload and Oops.
Hold the existing reg_mutex throughout snd_mixer_oss_build(), as proc
remapping already does for snd_mixer_oss_build_input(). A request can no
longer invoke a callback between its installation and the payload store.
This keeps the existing reg_mutex-before-controls_rwsem lock order.
KASAN report as below:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000000: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000000-0x0000000000000007]
CPU: 1 UID: 0 PID: 431 Comm: alsa-oss-trigge Tainted: G O 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
Tainted: [O]=OOT_MODULE
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
RIP: 0010:snd_mixer_oss_get_volume1+0xd1/0x610 [snd_mixer_oss]
Code: 00 c7 03 64 00 00 00 e9 b8 01 00 00 e8 e8 82 44 c1 49 8d 75 04 48 b8 00 00 00 00 00 fc ff df 48 89 f2 48 89 34 24 48 c1 ea 03 <0f> b6 14 02 48 89 f0 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 3f
RSP: 0018:ffff888104c67cc8 EFLAGS: 00010257
RAX: dffffc0000000000 RBX: ffff888104c67d80 RCX: ffffffffc0406cb8
RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffffffff862d93a4
RBP: ffff888104c67d90 R08: 0000000000000001 R09: 0000000000000001
R10: ffffffff89406e57 R11: ffff888104c9d700 R12: ffff888113c48038
R13: 0000000000000000 R14: ffff888113c48000 R15: ffff888104646820
FS: 00007f7904d29780(0000) GS:ffff8881fd81d000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f7904e388e0 CR3: 000000010662c002 CR4: 0000000000770ef0
PKRU: 55555554
Call Trace:
<TASK>
snd_mixer_oss_ioctl1+0x25d/0x16f0 [snd_mixer_oss]
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_snd_mixer_oss_get_volume1+0x10/0x10 [snd_mixer_oss]
? __pfx_snd_mixer_oss_ioctl1+0x10/0x10 [snd_mixer_oss]
? lock_release+0xc8/0x280
? pmbd_site_is_armed+0xa1/0xd0
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? trace_hardirqs_on+0x18/0x160
? srso_alias_return_thunk+0x5/0xfbef5
? _raw_spin_unlock_irqrestore+0x44/0x60
? srso_alias_return_thunk+0x5/0xfbef5
? pmbd_gate_site_armed+0x31/0x1c0
? srso_alias_return_thunk+0x5/0xfbef5
? pmbd_probe_hit_cookie+0xee/0x1c0
? __pfx_pmbd_probe_hit_cookie+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? selinux_file_ioctl+0xaa/0x280
snd_mixer_oss_ioctl+0x4a/0x80 [snd_mixer_oss]
? __pfx_snd_mixer_oss_ioctl+0x10/0x10 [snd_mixer_oss]
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f7904e3891b
Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00
RSP: 002b:00007ffc72071e20 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000000 RCX: 00007f7904e3891b
RDX: 00007ffc72071e84 RSI: 0000000080044d00 RDI: 0000000000000003
RBP: 0000000000000003 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 00007ffc72072e12
R13: 00007ffc72072060 R14: 00007f7904f67000 R15: 000055cd1e601d50
</TASK>
Modules linked in: snd_dummy(O) snd_mixer_oss(O)
---[ end trace 0000000000000000 ]---
RIP: 0010:snd_mixer_oss_get_volume1+0xd1/0x610 [snd_mixer_oss]
Code: 00 c7 03 64 00 00 00 e9 b8 01 00 00 e8 e8 82 44 c1 49 8d 75 04 48 b8 00 00 00 00 00 fc ff df 48 89 f2 48 89 34 24 48 c1 ea 03 <0f> b6 14 02 48 89 f0 83 e0 07 83 c0 03 38 d0 7c 08 84 d2 0f 85 3f
RSP: 0018:ffff888104c67cc8 EFLAGS: 00010257
RAX: dffffc0000000000 RBX: ffff888104c67d80 RCX: ffffffffc0406cb8
RDX: 0000000000000000 RSI: 0000000000000004 RDI: ffffffff862d93a4
RBP: ffff888104c67d90 R08: 0000000000000001 R09: 0000000000000001
R10: ffffffff89406e57 R11: ffff888104c9d700 R12: ffff888113c48038
R13: 0000000000000000 R14: ffff888113c48000 R15: ffff888104646820
FS: 00007f7904d29780(0000) GS:ffff8881fd81d000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 00007f7904e388e0 CR3: 000000010662c002 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>
Link: https://patch.msgid.link/pm-pmb-99c1214968ae9fa4d744-v2-df0befb9a699eb50dcec@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
In the recent addition of snd_pcm_sync_stop() call at snd_pcm_drop(),
I overlooked the guard() line in snd_pcm_drop() (and the review
overlooked, too) -- it must be called outside, of course!
Let's fix it. Now guard() became scoped_guard(), and its range is
shown more clearly.
Fixes: fdf9a21cda78 ("ALSA: pcm: Apply sync-stop at SNDRV_PCM_IOCTL_DROP ioctl")
Reported-by: Marek Szyprowski <m.szyprowski@samsung.com>
Closes: https://lore.kernel.org/c2bc1478-5999-455f-bd67-8b536c452215@samsung.com
Link: https://patch.msgid.link/20261015190147.230736-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
When a thread tries to sync-and-destroy the resource with
snd_refcount_sync(), it might lead to a UAF in a very slight time
window. Namely, snd_refount_put() calls wake_up() after
atomic_dec_and_test(), but wait_event() in snd_refcount_sync() checks
the condition via atomic_test() without serialization, hence the
thread that called snd_refcount_sync() can continue immediately to
release the resource before another thread calls wake_up().
For avoiding the race above, introduce the spinlock and take it at
snd_refcount_put() and snd_refcount_sync() in order to serialize the
operations.
Fixes: dcca9b6064c3 ("ALSA: Add simple refcount helper functions")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20261015071838.31082-1-tiwai%40suse.de
Reviewed-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/20261015112256.3902-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
We added a workaround for the case where a linked substream gets
unlinked during the drain operation by another substream of the same
linked group in the commit 9b1dbd69ba6f ("ALSA: pcm: fix
use-after-free on linked stream runtime in snd_pcm_drain()").
There, we just cached the parameters of the draining substream for
avoiding UAF.
Then, we check the draining substream (to_check) again in the loop and
remove it from the queue only when it's still present. It means,
however, that the wait queue entry won't be removed if the substream
went out of the link beforehand, hence a stale wq entry remains.
Later on, this can be woken up, and this may hit a UAF, too.
The problem surfaced more due to the recent change to call
snd_pcm_unlink() earlier.
For properly handling both cases above, in this patch, we introduce a
refcount to the snd_pcm_runtime that indicates the substream is being
accessed / used, then at snd_pcm_release_substream(), it's synced
before the actual resource release via snd_refcount_sync(). This
guarantees that the accessors are finished, and safe to release
memories. Along with the introduction of a refcount, the comments and
the code changes by the former fix were partially reverted as they
don't fit with the updated code flow any longer.
Last but not least, the setup of wait queue entry and
prepare_to_wait() call are moved before the group unref. With this
change, we can avoid the race between the enqueue and the wakeup, too.
Fixes: 9b1dbd69ba6f ("ALSA: pcm: fix use-after-free on linked stream runtime in snd_pcm_drain()")
Link: https://patch.msgid.link/20261015071838.31082-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
The RPN/NRPN conversion in fill_rpn() is supposed to return the number
of bytes of the resultant UMP packet, but it returns boolean values.
This would result in the incorrect ump_bytes in the converter, which
will confuse stream processing. Correct to the right value 8 as a MIDI
2.0 UMP packet.
Fixes: e6ce8a28c768 ("ALSA: ump: Transmit RPN/NRPN message at each MSB/LSB data reception")
Cc: <stable@vger.kernel.org>
Link: https://patch.msgid.link/20261015075439.50088-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
When a PCM stream is stopped via SNDRV_PCM_IOCTL_DROP ioctl, it calls
snd_pcm_stop() but sync-stop operation is missing. Although this is
usually no big issue, let's add snd_pcm_sync_stop() call, just to be
sure.
Link: https://patch.msgid.link/20261014142454.320703-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Hardware refinement must reject disconnected streams before entering
their runtime constraint rules. The native ioctl checks the state at
the outer dispatch, before copying the parameters, while the compat
HW_REFINE32 path only checks that the runtime exists. Both call the
unlocked refinement helper without the buffer access lock used by
HW_PARAMS.
The BUFFER_BYTES rule keeps a substream pointer as its private payload.
A compat request can still enter that rule after component disconnect.
If component free overlaps its execution, the following order permits
a use-after-free read of buffer_bytes_max:
Component cleanup Compat HW_REFINE
----------------- ----------------
snd_pcm_dev_disconnect()
Runtime -> DISCONNECTED
Enter compat ioctl
snd_pcm_hw_refine()
Enter BUFFER_BYTES rule
snd_device_free()
snd_pcm_free_stream()
Free substream
Read buffer_bytes_max
Add a wrapper that acquires the existing buffer access lock and checks
the same allowed states and mmap conditions as HW_PARAMS before running
the refinement rules. Share the state checker with snd_pcm_hw_params()
and use the wrapper for native, compat and legacy PCM HW_REFINE ioctls.
This rejects the described entry after disconnect and serializes these
refinement calls with other buffer-locked parameter operations.
Keep the original snd_pcm_hw_refine() helper for existing internal
callers, including snd_pcm_hw_params() which already holds the buffer
lock, to avoid locking that mutex recursively.
KASAN report as below:
BUG: KASAN: slab-use-after-free in snd_pcm_hw_rule_buffer_bytes_max+0x276/0x2a0
Read of size 8 at addr ffff888111b36870 by task pmbd_alsa_reade/486
CPU: 2 UID: 0 PID: 486 Comm: pmbd_alsa_reade Tainted: G O 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
Tainted: [O]=OOT_MODULE
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
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? snd_pcm_hw_rule_buffer_bytes_max+0x276/0x2a0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? snd_pcm_hw_rule_buffer_bytes_max+0x276/0x2a0
kasan_report+0xe0/0x110
? snd_pcm_hw_rule_buffer_bytes_max+0x276/0x2a0
snd_pcm_hw_rule_buffer_bytes_max+0x276/0x2a0
? snd_pcm_hw_rule_div+0x16b/0x200
? __pfx_snd_pcm_hw_rule_buffer_bytes_max+0x10/0x10
? constrain_params_by_rules+0x17a/0xfe0
constrain_params_by_rules+0x506/0xfe0
? __pfx_constrain_params_by_rules+0x10/0x10
? __ia32_compat_sys_ioctl+0x289/0x2f0
? do_int80_emulation+0x14a/0x5e0
? srso_alias_return_thunk+0x5/0xfbef5
? lock_release+0xc8/0x280
? srso_alias_return_thunk+0x5/0xfbef5
? snd_interval_refine+0x284/0x470
snd_pcm_hw_refine+0x768/0xcc0
? __pfx_snd_pcm_hw_refine+0x10/0x10
? _copy_from_user+0x51/0xa0
snd_pcm_ioctl_hw_params_compat+0x138/0x280
snd_pcm_ioctl_compat+0x4c5/0x7c0
? __pfx_snd_pcm_ioctl_compat+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? selinux_file_ioctl+0xaa/0x280
? ksys_write+0x16b/0x200
? __pfx_snd_pcm_ioctl_compat+0x10/0x10
__ia32_compat_sys_ioctl+0x289/0x2f0
? srso_alias_return_thunk+0x5/0xfbef5
do_int80_emulation+0x14a/0x5e0
asm_int80_emulation+0x1a/0x20
RIP: 0023:0x8049084
Code: 80 b8 04 00 00 00 bb 01 00 00 00 b9 43 a0 04 08 ba 2b 00 00 00 cd 80 b8 36 00 00 00 89 f3 b9 10 41 5c c2 ba b8 b0 04 08 cd 80 <85> c0 78 6c b8 04 00 00 00 bb 01 00 00 00 b9 27 a0 04 08 ba 1c 00
RSP: 002b:00000000ffd35e40 EFLAGS: 00000246 ORIG_RAX: 0000000000000036
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00000000c25c4110
RDX: 000000000804b0b8 RSI: 0000000000000003 RDI: 0000000000000004
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000000 R12: 0000000000000000
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
</TASK>
Allocated by task 486:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
snd_pcm_new_stream+0x98f/0x1350
_snd_pcm_new+0x1d1/0x310
snd_pcm_new+0x43/0x60
0xffffffffc0401115
do_one_initcall+0xf3/0x4e0
do_init_module+0x281/0x8e0
load_module+0x658c/0x7cc0
init_module_from_file+0x15b/0x180
idempotent_init_module+0x22d/0x770
__x64_sys_finit_module+0xd2/0x160
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 494:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
snd_pcm_free_stream+0xcf/0x290
snd_pcm_free+0xb1/0xf0
__snd_device_free+0x1a1/0x490
snd_device_free+0xcf/0x190
case_owner_ioctl+0xb8/0x160 [pmbd_alsa_fixture]
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the object at ffff888111b36800
which belongs to the cache kmalloc-1k of size 1024
The buggy address is located 112 bytes inside of
freed 1024-byte region [ffff888111b36800, ffff888111b36c00)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0xffff888111b35800 pfn:0x111b30
head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
flags: 0x200000000000240(workingset|head|node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000240 ffff888100042dc0 ffffea0004218610 ffffea00042c6810
raw: ffff888111b35800 000000000010000f 00000000f5000000 0000000000000000
head: 0200000000000240 ffff888100042dc0 ffffea0004218610 ffffea00042c6810
head: ffff888111b35800 000000000010000f 00000000f5000000 0000000000000000
head: 0200000000000003 fffffffffffffe01 00000000ffffffff 00000000ffffffff
head: 0000000000000000 0000000000000000 00000000ffffffff 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888111b36700: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff888111b36780: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff888111b36800: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
^
ffff888111b36880: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
ffff888111b36900: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
==================================================================
Suggested-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Assisted-by: LLM
Link: https://patch.msgid.link/pm-pmb-b3f7b3445bb11aaa9a7b-v3-371faafc2599ec7fa136@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
A closing PCM substream can remain in its linked group after the
driver close callback has freed its private data. With two configured
dummy capture substreams on the same PCM device, linked with LINK,
PREPARE on the surviving substream can still visit the closing member:
Final close of A PREPARE on linked B
---------------- -------------------
snd_pcm_drop(): group -> SETUP
do_hw_free(A)
dummy_pcm_close(A): free dpcm
Take snd_pcm_link_rwsem for reading
Walk the group, including A
dummy_pcm_prepare(A)
Read freed timer_ops
pcm_release_private(A)
snd_pcm_unlink(A)
Unlink at the start of final substream release, before dropping the
stream or releasing driver resources. The link write lock waits for
an existing group PREPARE, and unlink removes the closing member from
later group actions. Keep the existing stop synchronization in
do_hw_free() before the driver resources are freed.
Make unlink independent of the pcm_release callback so OSS substreams
are covered too. Remove the native-only unlink callback and its
registration, while retaining the callback hook for OSS cleanup.
The existing KASAN report below records the freed timer_ops read in
dummy_pcm_prepare().
KASAN report as below:
BUG: KASAN: slab-use-after-free in dummy_pcm_prepare+0xb7/0xc0
Read of size 8 at addr ffff888106b35f00 by task alsa_pcm_fixtur/491
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? dummy_pcm_prepare+0xb7/0xc0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? dummy_pcm_prepare+0xb7/0xc0
kasan_report+0xe0/0x110
? dummy_pcm_prepare+0xb7/0xc0
dummy_pcm_prepare+0xb7/0xc0
snd_pcm_do_prepare+0x71/0xb0
snd_pcm_action_group+0x505/0xb30
snd_pcm_action_nonatomic+0xab/0x150
snd_pcm_common_ioctl+0x1bf5/0x3a50
? srso_alias_return_thunk+0x5/0xfbef5
? do_vfs_ioctl+0x1f5/0x1280
? __pfx_do_vfs_ioctl+0x10/0x10
? ioctl_has_perm.constprop.0.isra.0+0x34f/0x500
? __pfx_snd_pcm_common_ioctl+0x10/0x10
? __fput+0x5ba/0xa60
? srso_alias_return_thunk+0x5/0xfbef5
snd_pcm_ioctl+0x76/0xb0
? __pfx_snd_pcm_ioctl+0x10/0x10
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x41ee8d
Code: 04 25 28 00 00 00 48 89 45 c8 31 c0 48 8d 45 10 c7 45 b0 10 00 00 00 48 89 45 b8 48 8d 45 d0 48 89 45 c0 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1a 48 8b 45 c8 64 48 2b 04 25 28 00 00 00
RSP: 002b:00007ffcfa72fb60 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 000000000041ee8d
RDX: 0000000000000000 RSI: 0000000000004140 RDI: 0000000000000004
RBP: 00007ffcfa72fbb0 R08: 00007ffcfa72fb98 R09: 0000000000000110
R10: 0000000000000001 R11: 0000000000000246 R12: 00007ffcfa72fcd8
R13: 00007ffcfa72fcf0 R14: 00000000004a8f28 R15: 0000000000000001
</TASK>
Allocated by task 488:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
dummy_hrtimer_create+0x4a/0x170
dummy_pcm_open+0xe7/0x730
snd_pcm_open_substream+0x926/0x1580
snd_pcm_open+0x28d/0x6d0
snd_pcm_capture_open+0x82/0xe0
snd_open+0x1ec/0x3e0
chrdev_open+0x21f/0x660
do_dentry_open+0x5c8/0x1300
vfs_open+0x87/0x390
path_openat+0x2460/0x3cd0
do_file_open+0x21e/0x470
do_sys_openat2+0xf4/0x1b0
__x64_sys_openat+0x136/0x1e0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 490:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
dummy_hrtimer_free+0x72/0xe0
dummy_pcm_close+0x9f/0xd0
snd_pcm_release_substream.part.0+0x104/0x310
snd_pcm_release+0x106/0x240
__fput+0x39f/0xa60
fput_close_sync+0xff/0x200
__x64_sys_close+0x8c/0xf0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
==================================================================
Fixes: 1576274d3028 ("[ALSA] Fix Oops of PCM OSS emulation")
Suggested-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-9c80f858ccc13b3de84d-v7-fcd8c7aa0e837bf0b036@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Each OSS MIDI alias and its coder must have one final-release owner.
find_slot() pins the alias under register_lock, but
snd_seq_oss_midi_check_exit_port() clears its slot in a separate critical
section without checking whether another callback already removed it.
The use counter protects active users, but draining it does not elect a
single remover.
This requires overlapping raw kernel-client port controls for the same
client. snd_seq_kernel_client_ctl() does not take ioctl_mutex, and
snd_seq_delete_port() releases ports_mutex before returning to the
DELETE_PORT handler's PORT_EXIT broadcast. If the old deletion is delayed
before that broadcast, a new port can reuse the vacant address. Its
PORT_START finds and keeps the old alias. Deleting the replacement then
produces a second PORT_EXIT for the same address. Non-atomic subscriber
delivery holds a read rwsem, so the two receive_announce() callbacks can
run concurrently:
Old-port deletion Replacement-port controls
----------------- -------------------------
Unlink and drain old port
Delay before PORT_EXIT Create port at the same address
PORT_START keeps existing alias
Delete port; PORT_EXIT pins mdev
PORT_EXIT pins the same mdev
Clear slot; drop pin Clear slot; drop pin
Wait for users to drain Wait for users to drain
Free coder; pause before kfree(mdev)
Free coder again: read
freed coder->buf
Both callbacks can select the same alias before either clears its slot.
After both drop their pins, both waits can return. The second call to
snd_midi_event_free() can then read the freed coder's buffer pointer,
as in the report below, and attempt to release the same objects twice.
Check that the pinned alias still occupies its slot under register_lock
before clearing it. A callback that finds it already removed drops its
pin and returns. Only the callback that removes the alias drains users
and frees the coder and record. The pin keeps the record alive through
this check, and the wait remains outside the spinlock.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in snd_midi_event_free+0x53/0x60
Read of size 8 at addr ffff888107074518 by task alsa-seq-fixtur/492
CPU: 3 UID: 0 PID: 492 Comm: alsa-seq-fixtur Not tainted 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
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
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? snd_midi_event_free+0x53/0x60
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? snd_midi_event_free+0x53/0x60
kasan_report+0xe0/0x110
? snd_midi_event_free+0x53/0x60
snd_midi_event_free+0x53/0x60
snd_seq_oss_midi_check_exit_port+0x1d8/0x370
receive_announce+0x1b8/0x370
? __pfx_receive_announce+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __lock_acquire+0x466/0x2260
? snd_seq_port_use_ptr+0x40/0x170
? srso_alias_return_thunk+0x5/0xfbef5
? find_held_lock+0x2b/0x80
? snd_seq_port_use_ptr+0x10c/0x170
? srso_alias_return_thunk+0x5/0xfbef5
? lock_release+0xc8/0x280
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_receive_announce+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
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_down_read_nested+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? do_raw_read_unlock+0x49/0xe0
? srso_alias_return_thunk+0x5/0xfbef5
? _raw_read_unlock+0x23/0x40
snd_seq_deliver_event+0x351/0x760
? __pfx_snd_seq_deliver_event+0x10/0x10
? _raw_spin_unlock_irqrestore+0x44/0x60
? 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+0x13f/0x170
snd_seq_system_broadcast+0x100/0x150
? __pfx_snd_seq_system_broadcast+0x10/0x10
? mark_held_locks+0x40/0x70
? _raw_spin_unlock_irqrestore+0x44/0x60
? srso_alias_return_thunk+0x5/0xfbef5
? lockdep_hardirqs_on_prepare+0xea/0x1a0
? srso_alias_return_thunk+0x5/0xfbef5
snd_seq_ioctl_delete_port+0x179/0x4b0
call_seq_client_ctl+0x90/0x110
snd_seq_kernel_client_ctl+0x8a/0x100
pmbd_case_delete_port+0xa6/0xf0
? __pfx_pmbd_case_delete_port+0x10/0x10
? __might_fault+0xdd/0x190
? srso_alias_return_thunk+0x5/0xfbef5
? __might_fault+0x14e/0x190
? srso_alias_return_thunk+0x5/0xfbef5
? strim+0x19c/0x200
pmbd_case_control_write+0x2c5/0x470
? __pfx_pmbd_case_control_write+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __debugfs_file_get+0x1bd/0x7f0
? srso_alias_return_thunk+0x5/0xfbef5
? lock_acquire+0x17b/0x2f0
? ksys_write+0x111/0x200
full_proxy_write+0x11f/0x180
vfs_write+0x25a/0x1010
? __pfx_full_proxy_write+0x10/0x10
? __pfx___mutex_lock+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? lock_acquire+0x17b/0x2f0
? __pfx_vfs_write+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? __fget_files+0x1e1/0x370
ksys_write+0x111/0x200
? __pfx_ksys_write+0x10/0x10
? rseq_register.isra.0+0x1f3/0x2e0
? srso_alias_return_thunk+0x5/0xfbef5
? exit_to_user_mode_loop+0x3a5/0x570
? srso_alias_return_thunk+0x5/0xfbef5
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f3532e4e9ee
Code: 08 0f 85 f5 4b ff ff 49 89 fb 48 89 f0 48 89 d7 48 89 ce 4c 89 c2 4d 89 ca 4c 8b 44 24 08 4c 8b 4c 24 10 4c 89 5c 24 08 0f 05 <c3> 66 2e 0f 1f 84 00 00 00 00 00 0f 1f 80 00 00 00 00 48 83 ec 08
RSP: 002b:00007f3532dafe08 EFLAGS: 00000246 ORIG_RAX: 0000000000000001
RAX: ffffffffffffffda RBX: 00007f3532db06c0 RCX: 00007f3532e4e9ee
RDX: 000000000000000a RSI: 000055efbd747156 RDI: 0000000000000003
RBP: 000055efbd747156 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 000000000000000a
R13: 0000000000000000 R14: 00007ffe7894e7f0 R15: 00007f35325b0000
</TASK>
Allocated by task 490:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
snd_midi_event_new+0x74/0x210
snd_seq_oss_midi_check_new_port+0x329/0x610
receive_announce+0x277/0x370
__snd_seq_deliver_single_event+0x105/0x1a0
snd_seq_deliver_single_event+0x2fc/0x770
snd_seq_deliver_event+0x351/0x760
snd_seq_kernel_client_dispatch+0x13f/0x170
snd_seq_system_broadcast+0x100/0x150
snd_seq_ioctl_create_port+0x39a/0x9d0
call_seq_client_ctl+0x90/0x110
snd_seq_kernel_client_ctl+0x8a/0x100
pmbd_case_create_port+0xcc/0x160
pmbd_case_control_write+0x21d/0x470
full_proxy_write+0x11f/0x180
vfs_write+0x25a/0x1010
ksys_write+0x111/0x200
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 493:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
snd_midi_event_free+0x48/0x60
snd_seq_oss_midi_check_exit_port+0x1d8/0x370
receive_announce+0x1b8/0x370
__snd_seq_deliver_single_event+0x105/0x1a0
snd_seq_deliver_single_event+0x2fc/0x770
snd_seq_deliver_event+0x351/0x760
snd_seq_kernel_client_dispatch+0x13f/0x170
snd_seq_system_broadcast+0x100/0x150
snd_seq_ioctl_delete_port+0x179/0x4b0
call_seq_client_ctl+0x90/0x110
snd_seq_kernel_client_ctl+0x8a/0x100
pmbd_case_delete_port+0xa6/0xf0
pmbd_case_control_write+0x398/0x470
full_proxy_write+0x11f/0x180
vfs_write+0x25a/0x1010
ksys_write+0x111/0x200
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the object at ffff888107074500
which belongs to the cache kmalloc-96 of size 96
The buggy address is located 24 bytes inside of
freed 96-byte region [ffff888107074500, ffff888107074560)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x107074
flags: 0x200000000000000(node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000000 ffff888100042280 dead000000000122 0000000000000000
raw: 0000000000000000 0000000000200020 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888107074400: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
ffff888107074480: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
>ffff888107074500: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
^
ffff888107074580: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
ffff888107074600: fa fb fb fb fb fb fb fb fb fb fb fb fc fc fc fc
==================================================================
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-7c5128efe2110a87b872-v2-c718183fd693e73d8e95@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
An HDA virtual-master hook must have its private argument initialized
before a control callback can invoke it. snd_hda_add_vmaster_hook()
installs the trampoline through snd_ctl_add_vmaster_hook(), which stores
master->hook before master->hook_private_data without serialization.
When a codec with a vmaster mute hook binds to an already registered
card, snd_hda_gen_build_controls() publishes and initializes the Master
Playback Switch before installing the hook. A native write that changes
the switch can then run in the following order:
1. The codec bind path publishes and initializes the master control in
__snd_hda_add_vmaster(), then calls snd_hda_add_vmaster_hook().
2. The hook setter stores master->hook, but has not yet stored its
private argument.
3. SNDRV_CTL_IOCTL_ELEM_WRITE takes controls_rwsem and calls
master_put() while the setter remains between those stores.
4. master_put() sees the callback and invokes vmaster_hook() with a
NULL argument. The trampoline dereferences it before the setter
can complete publication.
The write lock held by snd_ctl_elem_write() does not exclude the hook
setter, so this can cause a NULL pointer dereference. Take the same
controls_rwsem for writing inside snd_ctl_add_vmaster_hook() so the
callback and its argument are installed together with respect to
native control callbacks. Pass the card into the helper and update
the HDA caller, keeping the lock in the ALSA core. Release it when
registration returns, before the caller synchronizes the hook.
KASAN report as below:
Oops: general protection fault, probably for non-canonical address 0xdffffc0000000001: 0000 [#1] SMP KASAN NOPTI
KASAN: null-ptr-deref in range [0x0000000000000008-0x000000000000000f]
CPU: 1 UID: 0 PID: 499 Comm: alsa-vmaster-tr Not tainted 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
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
RIP: 0010:vmaster_hook+0x35/0xb0
Code: f5 53 48 89 fb 48 83 ec 08 e8 57 f0 9a fc eb 50 e8 50 f0 9a fc 48 8d 7b 08 48 b8 00 00 00 00 00 fc ff df 48 89 fa 48 c1 ea 03 <80> 3c 02 00 75 59 48 8d 7b 10 48 8b 43 08 48 ba 00 00 00 00 00 fc
RSP: 0018:ffff888117647cd0 EFLAGS: 00010212
RAX: dffffc0000000000 RBX: 0000000000000000 RCX: ffffffff84e9ff50
RDX: 0000000000000001 RSI: 0000000000000000 RDI: 0000000000000008
RBP: 0000000000000001 R08: 0000000000000001 R09: 0000000000000001
R10: ffffffff89427457 R11: ffff888115ad1d00 R12: ffffffff84e9ff30
R13: ffff888114943ca0 R14: 0000000000000000 R15: 0000000000000001
FS: 00007fe8167b3780(0000) GS:ffff88826b7e3000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 0000557c8c2842a8 CR3: 000000011579f005 CR4: 0000000000770ef0
PKRU: 55555554
Call Trace:
<TASK>
master_put+0x20e/0x2b0
snd_ctl_elem_write+0x37f/0x5e0
snd_ctl_ioctl+0x997/0xdd0
? __pfx_snd_ctl_ioctl+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? selinux_file_ioctl+0xaa/0x280
? __pfx_snd_ctl_ioctl+0x10/0x10
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7fe8168c291b
Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00
RSP: 002b:00007fffab0cb150 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000003 RCX: 00007fe8168c291b
RDX: 00007fffab0cb310 RSI: 00000000c4c85513 RDI: 0000000000000003
RBP: 00007fffab0cb310 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000001
R13: 00007fffab0cb1c0 R14: 0000000000000001 R15: 0000557c4f71fd10
</TASK>
Modules linked in:
---[ end trace 0000000000000000 ]---
Fixes: ee52e56e7b12 ("ALSA: hda - Fix mute-LED fixed mode")
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Assisted-by: LLM
Link: https://patch.msgid.link/pm-pmb-c2667fb9cc42fbb7943c-v4-b7bc2fe90e950accb3f7@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Like the previous fix for snd_pcm_delay() (in the commit 50f413b83b31
"ALSA: pcm: Protect delay DMA sync against concurrent HW_FREE"), the
snd_pcm_dma_buffer_sync() call in snd_pcm_forward() and
snd_pcm_rewind() needs the similar protection against the concurrent
hw_free action for avoiding potential UAFs.
Fixes: a25684a95646 ("ALSA: memalloc: Support for non-contiguous page allocation")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://patch.msgid.link/20261013120528.52586-4-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
When an error happens in snd_jack_kctl_new(), it tries to free the new
kcontrol element via snd_ctl_free_one(). But snd_ctl_free_one()
releases only the memories, and the internal linked list and hash
entries still remain, which may lead to bogus accesses to user.
Replace with the correct destructor, snd_ctl_remove(), for clearing
the whole resources of the given kcontrol, instead.
Fixes: 9058cbe1eed2 ("ALSA: jack: implement kctl creating for jack devices")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Link: https://patch.msgid.link/20261013120528.52586-2-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
In some cases (system32 and compat64) due to incorrect assignment wrong
value is being reported. Fix it.
Fixes: 3ddee7f88aaf ("ALSA: Avoid using timespec for struct snd_pcm_status")
Signed-off-by: Amadeusz Sławiński <amade@asmblr.net>
Link: https://patch.msgid.link/20261013164256.4949-1-amade@asmblr.net
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
A PCM DMA buffer must remain allocated until explicit DMA synchronization
finishes. snd_pcm_delay() calls snd_pcm_dma_buffer_sync() after dropping
the stream lock, without participating in the buffer-access exclusion
used by HW_FREE.
With a managed NONCONTIG buffer requiring explicit sync, HW_PARAMS can
allocate a separate runtime descriptor when the requested ring exceeds
the preallocation. In PREPARED state with mmap_count zero, concurrent
HWSYNC and HW_FREE calls on the same open PCM file can interleave:
1. HWSYNC checks the state in snd_pcm_delay() under the stream lock and
releases that lock.
2. The sync helper fetches runtime->dma_buffer_p and enters
snd_dma_noncontig_sync() with that descriptor.
3. HW_FREE takes the negative buffer-access count, checks PREPARED under
the stream lock, releases the lock, and frees the DMA allocation and
dynamic descriptor through snd_pcm_lib_free_pages().
4. The sync callback resumes and reads the freed descriptor.
The stream lock does not cover the allocation's release, and the sync
operation has no positive buffer-access count to prevent it. The stale
read causes a use-after-free in snd_dma_noncontig_sync(). DELAY uses the
same snd_pcm_delay() path.
Take a positive buffer-access count before checking the state and keep it
until the DMA sync finishes, as the transfer and mmap paths already do.
HW_FREE then returns -EBUSY while this access is active. If a buffer
writer has already entered, snd_pcm_delay() returns -EBUSY before using
the buffer. Keep the sync outside the stream lock and balance the count
on the state-error path as well.
KASAN report as below:
BUG: KASAN: slab-use-after-free in snd_dma_noncontig_sync+0x295/0x310 [snd_pcm]
Read of size 4 at addr ffff888108f58584 by task pcm-uaf-fixture/487
CPU: 1 UID: 0 PID: 487 Comm: pcm-uaf-fixture Not tainted 7.2.0-rc6-pmb-alsa-functional-v2+ #1 PREEMPT(lazy)
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
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? snd_dma_noncontig_sync+0x295/0x310 [snd_pcm]
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? snd_dma_noncontig_sync+0x295/0x310 [snd_pcm]
kasan_report+0xe0/0x110
? snd_dma_noncontig_sync+0x295/0x310 [snd_pcm]
? __pfx_snd_dma_noncontig_sync+0x10/0x10 [snd_pcm]
snd_dma_noncontig_sync+0x295/0x310 [snd_pcm]
? __pfx_snd_dma_noncontig_sync+0x10/0x10 [snd_pcm]
snd_dma_buffer_sync+0xc9/0x110 [snd_pcm]
snd_pcm_delay+0x3bd/0x550 [snd_pcm]
snd_pcm_common_ioctl+0x1e7/0x3aa0 [snd_pcm]
? srso_alias_return_thunk+0x5/0xfbef5
? do_vfs_ioctl+0x1f5/0x1280
? __pfx_do_vfs_ioctl+0x10/0x10
? ioctl_has_perm.constprop.0.isra.0+0x34f/0x500
? __pfx_snd_pcm_common_ioctl+0x10/0x10 [snd_pcm]
? srso_alias_return_thunk+0x5/0xfbef5
snd_pcm_ioctl+0x76/0xb0 [snd_pcm]
? __pfx_snd_pcm_ioctl+0x10/0x10 [snd_pcm]
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f1cae7ab91b
Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00
RSP: 002b:00007ffe12d544f0 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007f1cae7ab91b
RDX: 0000000000000000 RSI: 0000000000004122 RDI: 0000000000000003
RBP: 00000000000001ee R08: 0000000000000073 R09: 00000000ffffffff
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000003
R13: 0000000000000001 R14: 00005584f32b1398 R15: 00005584f32b2ce8
</TASK>
Allocated by task 487:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
snd_pcm_lib_malloc_pages+0x27c/0x9f0 [snd_pcm]
snd_pcm_hw_params+0x171c/0x1d10 [snd_pcm]
snd_pcm_common_ioctl+0x1f62/0x3aa0 [snd_pcm]
snd_pcm_ioctl+0x76/0xb0 [snd_pcm]
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 499:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
snd_pcm_lib_free_pages+0x1c9/0x420 [snd_pcm]
snd_pcm_common_ioctl+0x2bd3/0x3aa0 [snd_pcm]
snd_pcm_ioctl+0x76/0xb0 [snd_pcm]
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the object at ffff888108f58580
which belongs to the cache kmalloc-64 of size 64
The buggy address is located 4 bytes inside of
freed 64-byte region [ffff888108f58580, ffff888108f585c0)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x108f58
flags: 0x200000000000000(node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000000 ffff8881000428c0 dead000000000100 dead000000000122
raw: 0000000000000000 0000000000200020 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff888108f58480: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ffff888108f58500: 00 00 00 00 00 06 fc fc fc fc fc fc fc fc fc fc
>ffff888108f58580: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
^
ffff888108f58600: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ffff888108f58680: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
==================================================================
Disabling lock debugging due to kernel taint
------------[ cut here ]------------
kernel BUG at kernel/dma/mapping.c:417!
Oops: invalid opcode: 0000 [#1] SMP KASAN NOPTI
CPU: 1 UID: 0 PID: 487 Comm: pcm-uaf-fixture Tainted: G B 7.2.0-rc6-pmb-alsa-functional-v2+ #1 PREEMPT(lazy)
Tainted: [B]=BAD_PAGE
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
RIP: 0010:__dma_sync_sg_for_cpu+0x230/0x360
Code: df 48 c1 e8 03 80 3c 10 00 0f 85 fa 00 00 00 4c 8b 35 d4 6b 7a 09 e8 7f e2 17 00 83 fd 02 0f 86 39 fe ff ff e8 71 e2 17 00 90 <0f> 0b e8 69 e2 17 00 be 08 00 00 00 4c 89 ff e8 bc 5f 77 00 4c 89
RSP: 0018:ffff888111f3fc50 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffffffffc0250d10 RCX: ffffffff816d395f
RDX: ffff88810836ba00 RSI: ffff888108f58580 RDI: ffffffffc02510d8
RBP: 00000000ffff8881 R08: 0000000000000000 R09: fffffbfff804a239
R10: ffffffffc02511cf R11: 6e696c6261736944 R12: ffff888108f58580
R13: 0000000002ce00e5 R14: ffffffffc0258720 R15: 0000000000000000
FS: 00007f1cae69c780(0000) GS:ffff8881fd861000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055d1affa2480 CR3: 0000000108fc0003 CR4: 0000000000770ef0
PKRU: 55555554
Call Trace:
<TASK>
snd_dma_noncontig_sync+0x15a/0x310 [snd_pcm]
? __pfx_snd_dma_noncontig_sync+0x10/0x10 [snd_pcm]
snd_dma_buffer_sync+0xc9/0x110 [snd_pcm]
snd_pcm_delay+0x3bd/0x550 [snd_pcm]
snd_pcm_common_ioctl+0x1e7/0x3aa0 [snd_pcm]
? srso_alias_return_thunk+0x5/0xfbef5
? do_vfs_ioctl+0x1f5/0x1280
? __pfx_do_vfs_ioctl+0x10/0x10
? ioctl_has_perm.constprop.0.isra.0+0x34f/0x500
? __pfx_snd_pcm_common_ioctl+0x10/0x10 [snd_pcm]
? srso_alias_return_thunk+0x5/0xfbef5
snd_pcm_ioctl+0x76/0xb0 [snd_pcm]
? __pfx_snd_pcm_ioctl+0x10/0x10 [snd_pcm]
__x64_sys_ioctl+0x163/0x1d0
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f1cae7ab91b
Code: 00 48 89 44 24 18 31 c0 48 8d 44 24 60 c7 04 24 10 00 00 00 48 89 44 24 08 48 8d 44 24 20 48 89 44 24 10 b8 10 00 00 00 0f 05 <89> c2 3d 00 f0 ff ff 77 1c 48 8b 44 24 18 64 48 2b 04 25 28 00 00
RSP: 002b:00007ffe12d544f0 EFLAGS: 00000246 ORIG_RAX: 0000000000000010
RAX: ffffffffffffffda RBX: 0000000000000004 RCX: 00007f1cae7ab91b
RDX: 0000000000000000 RSI: 0000000000004122 RDI: 0000000000000003
RBP: 00000000000001ee R08: 0000000000000073 R09: 00000000ffffffff
R10: 0000000000000000 R11: 0000000000000246 R12: 0000000000000003
R13: 0000000000000001 R14: 00005584f32b1398 R15: 00005584f32b2ce8
</TASK>
Modules linked in: snd_pcmtest snd_pcm
---[ end trace 0000000000000000 ]---
RIP: 0010:__dma_sync_sg_for_cpu+0x230/0x360
Code: df 48 c1 e8 03 80 3c 10 00 0f 85 fa 00 00 00 4c 8b 35 d4 6b 7a 09 e8 7f e2 17 00 83 fd 02 0f 86 39 fe ff ff e8 71 e2 17 00 90 <0f> 0b e8 69 e2 17 00 be 08 00 00 00 4c 89 ff e8 bc 5f 77 00 4c 89
RSP: 0018:ffff888111f3fc50 EFLAGS: 00010293
RAX: 0000000000000000 RBX: ffffffffc0250d10 RCX: ffffffff816d395f
RDX: ffff88810836ba00 RSI: ffff888108f58580 RDI: ffffffffc02510d8
RBP: 00000000ffff8881 R08: 0000000000000000 R09: fffffbfff804a239
R10: ffffffffc02511cf R11: 6e696c6261736944 R12: ffff888108f58580
R13: 0000000002ce00e5 R14: ffffffffc0258720 R15: 0000000000000000
FS: 00007f1cae69c780(0000) GS:ffff8881fd861000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: 000055d1affa2480 CR3: 0000000108fc0003 CR4: 0000000000770ef0
PKRU: 55555554
Kernel panic - not syncing: Fatal exception
Kernel Offset: disabled
Rebooting in 1 seconds..
Fixes: a25684a95646 ("ALSA: memalloc: Support for non-contiguous page allocation")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-d74585d187e0b1810c08-v2-25432d0951f67fdaa1a9@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
The input runtime embeds event_work, so the work must be drained before
close_substream() frees the runtime. The cancellation in
snd_rawmidi_input_trigger() runs before close clears substream->opened,
leaving a window for snd_rawmidi_receive() to enqueue more work.
With a sequencer subscription to a USB MIDI input port, an in-flight
completion can overlap the last subscription's midisynth_unsubscribe():
1. snd_usbmidi_input_data() observes input_triggered and is delayed
before calling snd_rawmidi_receive().
2. Unsubscribe enters close_substream(), clears input_triggered through
the provider trigger callback and returns from cancel_work_sync().
The substream is still opened.
3. The completion resumes. snd_rawmidi_receive() takes substream->lock,
sees opened set and queues runtime->event_work before dropping the
lock.
4. Close clears opened under that lock, closes the provider and frees
the runtime. Stopping USB URBs does not drain the raw-MIDI work.
5. The queued work runs and snd_rawmidi_input_event_work() reads event
or substream from the freed runtime, causing a use-after-free.
Cancel input event_work again after clearing opened, before closing the
provider or releasing the runtime's private data. Receive holds
substream->lock through its opened check and work enqueue, so once close
has cleared opened under that lock, no further receive can queue work.
The final cancellation therefore drains any late work before the
runtime is freed. Keep it outside the spinlock so a running callback can
finish.
Fixes: b3c705aa9e91 ("ALSA: rawmidi - Use workq for event handling")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-98489078ab56528d8e4a-v2-9408ce8c8f3c70b5c10d@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Jack debugfs files store a raw snd_jack_kctl pointer, so their
callbacks must be drained before the attachment is freed.
snd_jack_dev_free() unlinks and frees the attachments before calling
snd_jack_dev_disconnect(). Its late snd_jack_remove_debugfs() call
then has no entries left to traverse.
With CONFIG_SND_JACK_INJECTION_DEBUG and input support enabled, an
HDA codec rebind on a live card can publish a non-phantom jack's type
file while its component is still in SNDRV_DEV_BUILD. A later
jack-control allocation failure permits the following order:
1. hda_codec_driver_probe() creates a jack and publishes its debugfs
files before reaching snd_card_register().
2. A later control-build failure calls
snd_hda_codec_cleanup_for_unbind(), then snd_hda_jack_tbl_clear()
and snd_device_free(). __snd_device_disconnect() skips BUILD
components. snd_jack_dev_free() frees the attachment before its
late disconnect, leaving the debugfs files published.
3. After cleanup, a reader opens the surviving type file and
jack_type_read() dereferences the freed attachment's jack pointer.
The card's debugfs root remains live throughout this sequence. The
result is a use-after-free even without an overlapping read. An
already admitted callback is also not drained by this cleanup.
Call snd_jack_remove_debugfs() before unlinking any controls in the
free callback. The existing debugfs_remove() rundown blocks new
accesses and waits for active callbacks while the attachment, control
and jack remain valid. Roots cleared by an earlier disconnect are
NULL, so repeating the removal is harmless.
KASAN report as below:
==================================================================
BUG: KASAN: slab-use-after-free in jack_type_read+0x1da/0x1f0
Read of size 8 at addr ffff8881085f9da0 by task python3/429
CPU: 2 UID: 0 PID: 429 Comm: python3 Not tainted 7.2.0-rc6-pmb-alsa-functional-v2+ #1 PREEMPT(lazy)
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
Call Trace:
<TASK>
dump_stack_lvl+0x93/0xd0
print_report+0xce/0x630
? jack_type_read+0x1da/0x1f0
? srso_alias_return_thunk+0x5/0xfbef5
? __virt_addr_valid+0x20d/0x410
? jack_type_read+0x1da/0x1f0
kasan_report+0xe0/0x110
? jack_type_read+0x1da/0x1f0
jack_type_read+0x1da/0x1f0
? __pfx_jack_type_read+0x10/0x10
? __pfx___debugfs_file_get+0x10/0x10
? __pfx_cp_new_stat+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? srso_alias_return_thunk+0x5/0xfbef5
? selinux_file_permission+0x122/0x570
full_proxy_read+0x11f/0x180
? __pfx_full_proxy_read+0x10/0x10
vfs_read+0x1a0/0xc20
? __pfx_vfs_read+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __do_sys_newfstat+0xa6/0x100
? find_held_lock+0x2b/0x80
? __pfx___do_sys_newfstat+0x10/0x10
ksys_read+0x111/0x200
? __pfx_ksys_read+0x10/0x10
? full_proxy_llseek+0x11e/0x170
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
RIP: 0033:0x7f7e392e7687
Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
RSP: 002b:00007fff5f7b9180 EFLAGS: 00000202 ORIG_RAX: 0000000000000000
RAX: ffffffffffffffda RBX: 00007f7e39253780 RCX: 00007f7e392e7687
RDX: 0000000000002000 RSI: 000000003d2e9b00 RDI: 0000000000000003
RBP: 0000000000000000 R08: 0000000000000000 R09: 0000000000000000
R10: 0000000000000000 R11: 0000000000000202 R12: 00007f7e39253700
R13: 0000000000002000 R14: 00007f7e38d7e2c0 R15: 0000000000a55b98
</TASK>
Allocated by task 425:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
__kasan_kmalloc+0xaa/0xb0
__kmalloc_cache_noprof+0x251/0x610
snd_jack_kctl_new+0x80/0x180
snd_jack_new+0x4b/0x490
snd_hda_jack_add_kctl_mst+0x19b/0x610
add_jack_kctl+0x204/0x320
snd_hda_jack_add_kctls+0x212/0x910
snd_hda_gen_build_controls+0x233/0x600
snd_hda_codec_build_controls+0x2e4/0x9f0
hda_codec_driver_probe+0x26e/0x590
really_probe+0x21f/0xa90
__driver_probe_device+0x1ec/0x490
device_driver_attach+0xdc/0x210
bind_store+0xec/0x180
drv_attr_store+0x79/0xb0
sysfs_kf_write+0xed/0x140
kernfs_fop_write_iter+0x34b/0x500
vfs_write+0x637/0x1010
ksys_write+0x111/0x200
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
Freed by task 425:
kasan_save_stack+0x33/0x60
kasan_save_track+0x14/0x30
kasan_save_free_info+0x3b/0x60
__kasan_slab_free+0x5f/0x80
kfree+0x307/0x580
snd_jack_kctl_private_free+0x153/0x200
__snd_ctl_remove+0x29f/0x3b0
snd_ctl_remove+0x46/0x70
snd_jack_dev_free+0x1b1/0x370
__snd_device_free+0x193/0x3f0
snd_device_free+0xcf/0x190
snd_hda_jack_tbl_clear+0x159/0x2e0
snd_hda_codec_cleanup_for_unbind+0x37e/0x9c0
hda_codec_driver_probe+0x3ae/0x590
really_probe+0x21f/0xa90
__driver_probe_device+0x1ec/0x490
device_driver_attach+0xdc/0x210
bind_store+0xec/0x180
drv_attr_store+0x79/0xb0
sysfs_kf_write+0xed/0x140
kernfs_fop_write_iter+0x34b/0x500
vfs_write+0x637/0x1010
ksys_write+0x111/0x200
do_syscall_64+0x115/0x6a0
entry_SYSCALL_64_after_hwframe+0x77/0x7f
The buggy address belongs to the object at ffff8881085f9d80
which belongs to the cache kmalloc-64 of size 64
The buggy address is located 32 bytes inside of
freed 64-byte region [ffff8881085f9d80, ffff8881085f9dc0)
The buggy address belongs to the physical page:
page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0 pfn:0x1085f9
flags: 0x200000000000000(node=0|zone=2)
page_type: f5(slab)
raw: 0200000000000000 ffff8881000428c0 dead000000000100 dead000000000122
raw: 0000000000000000 0000000000200020 00000000f5000000 0000000000000000
page dumped because: kasan: bad access detected
Memory state around the buggy address:
ffff8881085f9c80: 00 00 00 00 00 00 00 00 fc fc fc fc fc fc fc fc
ffff8881085f9d00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
>ffff8881085f9d80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
^
ffff8881085f9e00: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
ffff8881085f9e80: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
==================================================================
Fixes: 495000a38634 ("ALSA: core: Remove debugfs at disconnection")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-e1e7490bbe7ba1b3c44a-v2-3e3b6315a18c02ced60d@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
snd_ctl_led_disconnect() removes the ctl-led sysfs files while
holding card->controls_rwsem. device_unregister() waits for running
sysfs callbacks which can deadlock when a concurrent write causes
the attach or detach callback to wait for controls_rwsem.
Break kernfs active protection in the attach, detach and list
callbacks and hold a module reference instead.
Fixes: a135dfb5de15 ("ALSA: led control - add sysfs kcontrol LED marking layer")
Signed-off-by: Ali Ahmet Memiş <aliamemis@disroot.org>
Link: https://patch.msgid.link/20261011180627.1594051-1-aliamemis@disroot.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
The static snd_utimer_ids IDA must remain live until a userspace timer
controller has returned its ID. However, snd_utimer_fops has no owner,
so anon_inode_getfd() does not take a reference to snd-timer for the
controller file.
With CONFIG_SND_TIMER=m and CONFIG_SND_UTIMER=y, userspace can create a
controller with SNDRV_TIMER_IOCTL_CREATE and close the native timer
file. If no timer instances or dependent modules retain snd-timer,
ordinary module unload can then overlap the controller's final release:
Controller final release Module unload
snd_utimer_release()
snd_utimer_free()
snd_timer_free(): unlink provider
snd_utimer_put_id()
enter ida_free()
delete_module()
alsa_timer_exit()
free_module(): free MOD_DATA
access snd_utimer_ids.xa
The provider is already absent from snd_timer_free_all() when unload
runs. Neither register_mutex nor the IDA's lock keeps module storage
resident through the remaining IDA access. That access can therefore
use freed module data and fault while acquiring the XArray lock, as
shown in the Oops below.
Set snd_utimer_fops.owner to THIS_MODULE so anonymous-file creation
takes the existing module reference. The VFS drops it only after
snd_utimer_release() returns, keeping the IDA resident through
ida_free() and preventing ordinary unload during that interval.
Oops report as below:
BUG: unable to handle page fault for address: fffffbfff80480af
#PF: supervisor read access in kernel mode
#PF: error_code(0x0000) - not-present page
PGD 1a7ff6067 P4D 1a7ff6067 PUD 1a7ff2067 PMD 100ad6067 PTE 0
Oops: Oops: 0000 [#1] SMP KASAN NOPTI
CPU: 0 UID: 0 PID: 485 Comm: alsa-utimer-fix Tainted: G O 7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
Tainted: [O]=OOT_MODULE
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
RIP: 0010:kasan_byte_accessible+0x15/0x30
Code: 00 00 0f 1f 00 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 90 0f 1f 40 d6 48 b8 00 00 00 00 00 fc ff df 48 c1 ef 03 48 01 c7 <0f> b6 07 3c 07 0f 96 c0 e9 69 f1 2b ff 66 66 2e 0f 1f 84 00 00 00
RSP: 0018:ffff88811a457c48 EFLAGS: 00010086
RAX: dffffc0000000000 RBX: ffffffffc0240578 RCX: 0000000000000000
RDX: 0000000000000000 RSI: ffffffff861f111c RDI: fffffbfff80480af
RBP: ffffffffc0240578 R08: 0000000000000001 R09: 0000000000000000
R10: ffffffff891cc057 R11: ffff88811531ba00 R12: ffffffff861f111c
R13: 0000000000000000 R14: 0000000000000000 R15: 0000000000000000
FS: 00007ff190ff7780(0000) GS:ffff8881fda2a000(0000) knlGS:0000000000000000
CS: 0010 DS: 0000 ES: 0000 CR0: 0000000080050033
CR2: fffffbfff80480af CR3: 0000000116890003 CR4: 0000000000770ef0
PKRU: 55555554
Call Trace:
<TASK>
__kasan_check_byte+0x13/0x50
lock_acquire+0x113/0x2f0
? __pfx_pmbd_probe_hit_cookie+0x10/0x10
? lock_release+0xc8/0x280
? srso_alias_return_thunk+0x5/0xfbef5
_raw_spin_lock_irqsave+0x3c/0x60
? ida_free+0xd4/0x2b0
ida_free+0xd4/0x2b0
? __pfx_ida_free+0x10/0x10
? srso_alias_return_thunk+0x5/0xfbef5
? __pfx_locks_remove_file+0x10/0x10
? __fput+0x39f/0xa60
? fput_close_sync+0xff/0x200
? __pfx_fput_close_sync+0x10/0x10
? dnotify_flush+0x22/0x4b0
? __x64_sys_close+0x8c/0xf0
? do_syscall_64+0x115/0x6a0
? entry_SYSCALL_64_after_hwframe+0x77/0x7f
</TASK>
Modules linked in: snd(O) [last unloaded: snd_timer(O)]
CR2: fffffbfff80480af
---[ end trace 0000000000000000 ]---
Fixes: 37745918e0e7 ("ALSA: timer: Introduce virtual userspace-driven timers")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Link: https://patch.msgid.link/pm-pmb-98fb8f747fc7b8499fd4-v2-1c531f149a6d6c084f48@gmail.com
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
Since the port list was converted to RCU, snd_seq_delete_all_ports()
calls synchronize_rcu() once per port under register_mutex. Closing a
client with 254 ports now takes about 1.6s and every other client
open or close waits for it.
Unlink all ports first, wait for a single grace period and then free
them.
Fixes: 4c252fbc06d6 ("ALSA: seq: Use RCU for the client port list")
Signed-off-by: Ali Ahmet Memiş <aliamemis@disroot.org>
Link: https://patch.msgid.link/20261010222543.1470723-1-aliamemis@disroot.org
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
|
snd_seq_read() returns an error even if one or more events have been
successfully read before the error (except for -EAGAIN case), but this
rather doesn't follow the POSIX standard that wants the processed
bytes. Change the behavior to return the processed bytes when it's
positive, instead.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007172533.14667-8-tiwai@suse.de
|
|
When the snd_card object is initialized internally in snd_card_init(),
the error path of card->value_buf allocation returns straightly as an
error without invoking the destructor, which would leak resources.
Also, the other error paths in snd_card_init() release the card object
only via put_device(), and this misses the cleanups that are done in
snd_card_disconnect(); namely, the reserved slot bit in snd_cards_lock
is never cleared, so the card index remains occupied, and the debugfs
directory created for the card is left over.
Fix them by calling snd_card_free() at the error path, which performs
both the disconnection and the release properly. As snd_card_free()
calls snd_device_free_all() internally, the explicit call is dropped,
and the error labels are unified.
Fixes: 84446536f63d ("ALSA: control: Verify put() result when in debug mode")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007172533.14667-7-tiwai@suse.de
|
|
The fix for potential deadlock at disconnection by the commit
c7a606519533 ("ALSA: info: Fix potential deadlock at disconnection")
clears card->proc_root pointer at snd_info_card_disconnect(), in order
just to be sure. But this leads to a memory leak of card->proc_root
content that should have been released at a later call of
snd_info_card_free().
For addressing the memory leak, simply drop the card->proc_root
clearance at snd_info_card_disconnect().
Since card->proc_root might be still looked at in
snd_info_card_id_change() that may be running concurrently during the
connection procedure, add a sanity check there, too.
Fixes: c7a606519533 ("ALSA: info: Fix potential deadlock at disconnection")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20261006174002.703431-1-tiwai%40suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007172533.14667-5-tiwai@suse.de
|
|
I forgot to cover the two new fields, direction and ump_group, in
struct snd_seq_port_info for the 32bit compat ioctls of
SNDRV_SEQ_IOCTL_GET_PORT_INFO & co, which ended up with the garbage
copies in those fields. Add the handling of those two fields in the
compat layer.
Also, avoid over-copying the 64bit snd_seq_port_info but only the first
part (before the field kernel); this avoids the copy of kernel-space
garbage value in the reserved field.
Fixes: ff166a9d19fa ("ALSA: seq: Add port direction to snd_seq_port_info")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007172533.14667-2-tiwai@suse.de
|
|
snd_power_ref_and_wait() increments card->power_ref and then reads
card->shutdown (and the power state) locklessly, while
snd_card_disconnect() sets card->shutdown and then waits for
power_ref to drop to zero via snd_power_sync_ref(). Due to the
missing barrier on both sides, the caller proceeds with shutdown still
seen as false, while the disconnect side sees a zero refcount and
continues tearing down incorrectly.
For addressing the potential race, add smp_mb__after_atomic() after
the refcount increment and smp_mb() before snd_power_sync_ref() in
snd_card_disconnect().
Fixes: e94fdbd7b25d ("ALSA: control: Track in-flight control read/write/tlv accesses")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Assisted-by: LLM
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007172051.13240-9-tiwai@suse.de
|
|
snd_pcm_drop() checks the current state at the beginning, and bails
out if it's in an invalid state (OPEN or DISCONNECTED). However,
since the check is done before the PCM stream lock, this can lead to a
Time-of-Check to Time-of-Use (TOCTOU) race against the other forcible
state change like the device disconnection like below:
CPU 0 CPU 1
----- -----
snd_pcm_drop()
runtime->state check
snd_pcm_dev_disconnect()
guard(pcm_stream_lock_irq)
runtime->state = SNDRV_PCM_STATE_DISCONNECTED
guard(pcm_stream_lock_irq)
snd_pcm_stop(SNDRV_PCM_STATE_SETUP) <== inconsistent state
For avoiding the inconsistent state change, this patch moves the
runtime state check inside the stream lock guard.
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007172051.13240-3-tiwai@suse.de
|
|
In the recent refactoring with RCU, clientptr() takes guard(rcu)()
around the client table lookup, but the RCU read-side section ends as
soon as the function returns, so the returned pointer isn't protected
at all. This gives a false impression as if that the callers were
safe, and confuse reviewers including Sashiko.
Actually, the callers (snd_seq_delete_kernel_client(),
snd_seq_kernel_client_ctl() and snd_seq_kernel_client_write_poll())
never relied on any lock; the caller is the owner of the client (a
kernel client passing its own id, or a user client via its opened
file), hence the client can't be released concurrently by others.
So just drop the confusing and useless RCU guard, read the table via
rcu_dereference_protected(), and document the lifetime rule. Along
with it, fold __clientptr() into its only user client_use_ptr(); the
id range is already checked there, and it's never called with
clients_lock held, so a plain rcu_dereference() suffices.
Fixes: 7a287e4615d6 ("ALSA: seq: Use RCU for the client table")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007172051.13240-2-tiwai@suse.de
|
|
The state of the stream is set to SNDRV_PCM_STATE_DRAINING only after the
drain trigger has been sent to the driver.
Drivers can not block in the trigger callback and the drain is completed
asynchronously: snd_compr_drain_notify() can be called either from the
trigger callback itself or from a different context as soon as the
trigger returns. If that happens before the core updates the state then
the notification is lost: the state is overwritten with DRAINING right
after it and the wait for the drain to complete will not be woken up.
Set the state before the trigger is issued and restore it if the trigger
fails. The partial_drain flag is cleared on the error path as well as it
would otherwise be left set for the next drain.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Link: https://patch.msgid.link/20261007084955.1256-5-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Track open compressed streams per device so disconnect can stop
active streams and wake waiters before snd_unregister_device().
This aligns compressed stream teardown with PCM disconnect behavior
and prevents active userspace streams from running into unregister
races.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007084955.1256-4-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
The compress-offload device is the only ALSA character device family
which does not add its open files to the card's file list. Without it
the core cannot replace the file operations on disconnect, so syscalls
issued after the card is gone still reach the driver, and a card freed
with snd_card_free_when_closed() does not wait for the open compress
streams.
Call snd_card_file_add() at open and snd_card_file_remove() at release,
following the ordering used by the PCM, control, rawmidi and hwdep
devices.
Suggested-by: Takashi Iwai <tiwai@suse.de>
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007084955.1256-3-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
Take a module reference in snd_compr_open() and release it in
snd_compr_free(). This pins the card driver module for the
lifetime of an open compress stream and prevents card removal
while the stream file is still in use.
Adjust the open() cleanup paths to drop the added module
reference only when it was acquired, and keep release ordering
safe by dropping the module reference before freeing stream
data.
Signed-off-by: Peter Ujfalusi <peter.ujfalusi@linux.intel.com>
Reviewed-by: Liam Girdwood <liam.r.girdwood@intel.com>
Reviewed-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20261007084955.1256-2-peter.ujfalusi@linux.intel.com
Signed-off-by: Mark Brown <broonie@kernel.org>
|
|
We have a few cpu_latency_qos_*() calls in PCM callbacks, but they
seem suboptimal in a few aspects:
- We call them at each time when the hw_params changed, but explicitly
do remove and (re-)add; this could be
cpu_latency_qos_update_request(), instead
- The setup of cpu_latency_qos_*() doesn't have to be in hw_params at
all; it's not the place where the actual parameters are set up, but
rather better at the prepare callback.
- The hw_free calls cpu_latency_qos_remove_request() unconditionally,
which may be poking a WARNING when it wasn't queued.
For addressing the issues above, this patch cleans up and reorganize
the cpu_latency_qos_*() calls in the PCM core by a couple helper
functions. Now, they are set up at prepare callback, and cleared at
hw_free and release callbacks via the new helpers.
Link: https://patch.msgid.link/20261002150420.879056-1-tiwai@suse.de
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|