ALSA sequencer code has an open race between the timer setup ioctl and
the close of the client. This was triggered by syzkaller fuzzer, and
a use-after-free was caught there as a result.
This patch papers over it by adding a proper queue->timer_mutex lock
around the timer-related calls in the relevant code path.
snd_seq_ioctl_remove_events() calls snd_seq_fifo_clear()
unconditionally even if there is no FIFO assigned, and this leads to
an Oops due to NULL dereference. The fix is just to add a proper NULL
check.
The 'umidi' object will be free'd on the error path by snd_usbmidi_free()
when tearing down the rawmidi interface. So we shouldn't try to free it
in snd_usbmidi_create() after having registered the rawmidi interface.
Found by KASAN.
Signed-off-by: Andrey Konovalov <email address hidden>
Acked-by: Clemens Ladisch <email address hidden>
Signed-off-by: Takashi Iwai <email address hidden>
Signed-off-by: Ben Hutchings <email address hidden>
[wt: file is sound/midi/usbmidi.c in 2.6.32]
Signed-off-by: Willy Tarreau <w@1wt.eu>
snd_timer_user_read() has a potential race among parallel reads, as
qhead and qused are updated outside the critical section due to
copy_to_user() calls. Move them into the critical section, and also
sanitize the relevant code a bit.
Signed-off-by: Takashi Iwai <email address hidden>
[bwh: Backported to 3.2: there's no check for tu->connected to fix up]
Signed-off-by: Ben Hutchings <email address hidden>
Signed-off-by: Willy Tarreau <w@1wt.eu>
In snd_timer_notify1(), the wrong timer instance was passed for slave
ccallback function. This leads to the access to the wrong data when
an incompatible master is handled (e.g. the master is the sequencer
timer and the slave is a user timer), as spotted by syzkaller fuzzer.
ALSA timer ioctls have an open race and this may lead to a
use-after-free of timer instance object. A simplistic fix is to make
each ioctl exclusive. We have already tread_sem for controlling the
tread, and extend this as a global mutex to be applied to each ioctl.
The downside is, of course, the worse concurrency. But these ioctls
aren't to be parallel accessible, in anyway, so it should be fine to
serialize there.
In ALSA timer core, the active timer instance is managed in
active_list linked list. Each element is added / removed dynamically
at timer start, stop and in timer interrupt. The problem is that
snd_timer_interrupt() has a thinko and leaves the element in
active_list when it's the last opened element. This eventually leads
to list corruption or use-after-free error.
This hasn't been revealed because we used to delete the list forcibly
in snd_timer_stop() in the past. However, the recent fix avoids the
double-stop behavior (in commit [f784beb75ce8: ALSA: timer: Fix link
corruption due to double start or stop]), and this leak hits reality.
This patch fixes the link management in snd_timer_interrupt(). Now it
simply unlinks no matter which stream is.