diff options
| author | Takashi Iwai <tiwai@suse.de> | 2026-06-09 13:50:53 +0200 |
|---|---|---|
| committer | Takashi Iwai <tiwai@suse.de> | 2026-06-10 09:36:28 +0200 |
| commit | ccd0db6671d2cae986b2daa1c538b6d541a9d62c (patch) | |
| tree | c46c45e75df4d63b18a19bdd8ebf02ddf6deacc4 /include | |
| parent | 98e157916f83c26a41448267180944048d2f1460 (diff) | |
ALSA: timer: Manage timer object with kref
So far we've tried to address UAFs in ALSA timer code by applying the
locks at various places, but the fundamental problem is that the timer
object may be released while the belonging timer instance objects are
still present and accessing to it. This patch is a more proper fix to
address that issue, namely, by refcounting and keeping the timer
object.
The basic implementation is to use kref for the refcount of the timer
object, and take/release the reference at assigning/releasing the
instance, as well as at referring from ioctls or ALSA sequencer code.
The reference from ioctl or ALSA sequencer is abstracted with
snd_timeri_timer auto-cleanup.
Note that this change assumes that the code already took the fix
commit da3039e91d1f ("ALSA: timer: Forcibly close timer instances at
closing"); otherwise the refcount may be unbalanced when the timer is
freed while slave instances are still present.
Signed-off-by: Takashi Iwai <tiwai@suse.de>
Link: https://patch.msgid.link/20260609115100.806869-2-tiwai@suse.de
Diffstat (limited to 'include')
| -rw-r--r-- | include/sound/timer.h | 6 |
1 files changed, 6 insertions, 0 deletions
diff --git a/include/sound/timer.h b/include/sound/timer.h index 83bafe70cf33..e549eab7145b 100644 --- a/include/sound/timer.h +++ b/include/sound/timer.h @@ -75,6 +75,7 @@ struct snd_timer { struct list_head ack_list_head; struct list_head sack_list_head; /* slow ack list head */ struct work_struct task_work; + struct kref kref; int max_instances; /* upper limit of timer instances */ int num_instances; /* current number of timer instances */ }; @@ -131,4 +132,9 @@ int snd_timer_pause(struct snd_timer_instance *timeri); void snd_timer_interrupt(struct snd_timer *timer, unsigned long ticks_left); +struct snd_timer *snd_timeri_timer_get(struct snd_timer_instance *timeri); +void snd_timeri_timer_put(struct snd_timer *timer); + +DEFINE_FREE(snd_timeri_timer, struct snd_timer *, if (_T) snd_timeri_timer_put(_T)) + #endif /* __SOUND_TIMER_H */ |
