From: Takashi Iwai tiwai@suse.de
stable inclusion from stable-v5.10.224 commit e7e7d2b180d8f297cea6db43ea72402fd33e1a29 category: bugfix bugzilla: https://gitee.com/src-openeuler/kernel/issues/IAOXZ4 CVE: CVE-2024-44954
Reference: https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git/commit/?id=...
--------------------------------
commit 15b7a03205b31bc5623378c190d22b7ff60026f1 upstream.
There can be concurrent accesses to line6 midibuf from both the URB completion callback and the rawmidi API access. This could be a cause of KMSAN warning triggered by syzkaller below (so put as reported-by here).
This patch protects the midibuf call of the former code path with a spinlock for avoiding the possible races.
Reported-by: syzbot+78eccfb8b3c9a85fc6c5@syzkaller.appspotmail.com Closes: https://lore.kernel.org/00000000000000949c061df288c5@google.com Cc: stable@vger.kernel.org Link: https://patch.msgid.link/20240805130129.10872-1-tiwai@suse.de Signed-off-by: Takashi Iwai tiwai@suse.de Signed-off-by: Greg Kroah-Hartman gregkh@linuxfoundation.org Conflicts: sound/usb/line6/driver.c [Fix context diff due to 6c764deba951 not merged] Signed-off-by: Yuan Can yuancan@huawei.com --- sound/usb/line6/driver.c | 5 +++++ 1 file changed, 5 insertions(+)
diff --git a/sound/usb/line6/driver.c b/sound/usb/line6/driver.c index 59faa5a9a714..1d5b41a21669 100644 --- a/sound/usb/line6/driver.c +++ b/sound/usb/line6/driver.c @@ -286,12 +286,14 @@ static void line6_data_received(struct urb *urb) { struct usb_line6 *line6 = (struct usb_line6 *)urb->context; struct midi_buffer *mb = &line6->line6midi->midibuf_in; + unsigned long flags; int done;
if (urb->status == -ESHUTDOWN) return;
if (line6->properties->capabilities & LINE6_CAP_CONTROL_MIDI) { + spin_lock_irqsave(&line6->line6midi->lock, flags); done = line6_midibuf_write(mb, urb->transfer_buffer, urb->actual_length);
@@ -300,11 +302,14 @@ static void line6_data_received(struct urb *urb) dev_dbg(line6->ifcdev, "%d %d buffer overflow - message skipped\n", done, urb->actual_length); } + spin_unlock_irqrestore(&line6->line6midi->lock, flags);
for (;;) { + spin_lock_irqsave(&line6->line6midi->lock, flags); done = line6_midibuf_read(mb, line6->buffer_message, LINE6_MIDI_MESSAGE_MAXLEN); + spin_unlock_irqrestore(&line6->line6midi->lock, flags);
if (done <= 0) break;