mirror of
https://github.com/torvalds/linux.git
synced 2026-11-07 06:17:02 +01:00
ALSA: core: Serialize snd_refcount put and sync
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: dcca9b6064 ("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>
This commit is contained in:
parent
91d0048a97
commit
6904743ab7
|
|
@ -84,6 +84,7 @@ struct snd_device {
|
|||
struct snd_refcount {
|
||||
atomic_t count;
|
||||
wait_queue_head_t waiter;
|
||||
spinlock_t lock;
|
||||
};
|
||||
|
||||
void snd_refcount_init(struct snd_refcount *ref);
|
||||
|
|
|
|||
|
|
@ -183,11 +183,13 @@ void snd_refcount_init(struct snd_refcount *ref)
|
|||
{
|
||||
atomic_set(&ref->count, 0);
|
||||
init_waitqueue_head(&ref->waiter);
|
||||
spin_lock_init(&ref->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_refcount_init);
|
||||
|
||||
void snd_refcount_put(struct snd_refcount *ref)
|
||||
{
|
||||
guard(spinlock_irqsave)(&ref->lock);
|
||||
if (atomic_dec_and_test(&ref->count))
|
||||
wake_up(&ref->waiter);
|
||||
}
|
||||
|
|
@ -195,6 +197,7 @@ EXPORT_SYMBOL_GPL(snd_refcount_put);
|
|||
|
||||
void snd_refcount_sync(struct snd_refcount *ref)
|
||||
{
|
||||
wait_event(ref->waiter, !atomic_read(&ref->count));
|
||||
guard(spinlock_irq)(&ref->lock);
|
||||
wait_event_lock_irq(ref->waiter, !atomic_read(&ref->count), ref->lock);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(snd_refcount_sync);
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user