ALSA: usb-audio: Fix a stack buffer overflow bug in check_input_term
(CVE-2019-15118)
This commit is contained in:
parent
aa8fb19232
commit
782d6ea880
|
@ -2,6 +2,8 @@ linux (4.19.67-2+deb10u1) UNRELEASED; urgency=medium
|
|||
|
||||
[ Romain Perier ]
|
||||
* ALSA: usb-audio: Fix an OOB bug in parse_audio_mixer_unit (CVE-2019-15117)
|
||||
* ALSA: usb-audio: Fix a stack buffer overflow bug in check_input_term
|
||||
(CVE-2019-15118)
|
||||
|
||||
-- Romain Perier <romain.perier@gmail.com> Wed, 28 Aug 2019 13:28:09 +0200
|
||||
|
||||
|
|
134
debian/patches/bugfix/all/ALSA-usb-audio-Fix-a-stack-buffer-overflow-bug-in-check_input_term.patch
vendored
Normal file
134
debian/patches/bugfix/all/ALSA-usb-audio-Fix-a-stack-buffer-overflow-bug-in-check_input_term.patch
vendored
Normal file
|
@ -0,0 +1,134 @@
|
|||
From: Hui Peng <benquike@gmail.com>
|
||||
Date: Thu, 15 Aug 2019 00:31:34 -0400
|
||||
Subject: ALSA: usb-audio: Fix a stack buffer overflow bug in check_input_term
|
||||
Bug-Debian-Security: https://security-tracker.debian.org/tracker/CVE-2019-15118
|
||||
Origin: https://git.kernel.org/linus/19bce474c45be69a284ecee660aa12d8f1e88f18
|
||||
|
||||
commit 19bce474c45be69a284ecee660aa12d8f1e88f18 upstream.
|
||||
|
||||
`check_input_term` recursively calls itself with input from
|
||||
device side (e.g., uac_input_terminal_descriptor.bCSourceID)
|
||||
as argument (id). In `check_input_term`, if `check_input_term`
|
||||
is called with the same `id` argument as the caller, it triggers
|
||||
endless recursive call, resulting kernel space stack overflow.
|
||||
|
||||
This patch fixes the bug by adding a bitmap to `struct mixer_build`
|
||||
to keep track of the checked ids and stop the execution if some id
|
||||
has been checked (similar to how parse_audio_unit handles unitid
|
||||
argument).
|
||||
|
||||
Reported-by: Hui Peng <benquike@gmail.com>
|
||||
Reported-by: Mathias Payer <mathias.payer@nebelwelt.net>
|
||||
Signed-off-by: Hui Peng <benquike@gmail.com>
|
||||
Cc: <stable@vger.kernel.org>
|
||||
Signed-off-by: Takashi Iwai <tiwai@suse.de>
|
||||
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||||
---
|
||||
sound/usb/mixer.c | 35 +++++++++++++++++++++++++++--------
|
||||
1 file changed, 27 insertions(+), 8 deletions(-)
|
||||
|
||||
diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c
|
||||
index 7e1c6c2dc99e..996126a28072 100644
|
||||
--- a/sound/usb/mixer.c
|
||||
+++ b/sound/usb/mixer.c
|
||||
@@ -83,6 +83,7 @@ struct mixer_build {
|
||||
unsigned char *buffer;
|
||||
unsigned int buflen;
|
||||
DECLARE_BITMAP(unitbitmap, MAX_ID_ELEMS);
|
||||
+ DECLARE_BITMAP(termbitmap, MAX_ID_ELEMS);
|
||||
struct usb_audio_term oterm;
|
||||
const struct usbmix_name_map *map;
|
||||
const struct usbmix_selector_map *selector_map;
|
||||
@@ -788,16 +789,25 @@ static int uac_mixer_unit_get_channels(struct mixer_build *state,
|
||||
* parse the source unit recursively until it reaches to a terminal
|
||||
* or a branched unit.
|
||||
*/
|
||||
-static int check_input_term(struct mixer_build *state, int id,
|
||||
+static int __check_input_term(struct mixer_build *state, int id,
|
||||
struct usb_audio_term *term)
|
||||
{
|
||||
int protocol = state->mixer->protocol;
|
||||
int err;
|
||||
void *p1;
|
||||
+ unsigned char *hdr;
|
||||
|
||||
memset(term, 0, sizeof(*term));
|
||||
- while ((p1 = find_audio_control_unit(state, id)) != NULL) {
|
||||
- unsigned char *hdr = p1;
|
||||
+ for (;;) {
|
||||
+ /* a loop in the terminal chain? */
|
||||
+ if (test_and_set_bit(id, state->termbitmap))
|
||||
+ return -EINVAL;
|
||||
+
|
||||
+ p1 = find_audio_control_unit(state, id);
|
||||
+ if (!p1)
|
||||
+ break;
|
||||
+
|
||||
+ hdr = p1;
|
||||
term->id = id;
|
||||
|
||||
if (protocol == UAC_VERSION_1 || protocol == UAC_VERSION_2) {
|
||||
@@ -815,7 +825,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
||||
|
||||
/* call recursively to verify that the
|
||||
* referenced clock entity is valid */
|
||||
- err = check_input_term(state, d->bCSourceID, term);
|
||||
+ err = __check_input_term(state, d->bCSourceID, term);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -849,7 +859,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
||||
case UAC2_CLOCK_SELECTOR: {
|
||||
struct uac_selector_unit_descriptor *d = p1;
|
||||
/* call recursively to retrieve the channel info */
|
||||
- err = check_input_term(state, d->baSourceID[0], term);
|
||||
+ err = __check_input_term(state, d->baSourceID[0], term);
|
||||
if (err < 0)
|
||||
return err;
|
||||
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
|
||||
@@ -912,7 +922,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
||||
|
||||
/* call recursively to verify that the
|
||||
* referenced clock entity is valid */
|
||||
- err = check_input_term(state, d->bCSourceID, term);
|
||||
+ err = __check_input_term(state, d->bCSourceID, term);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -963,7 +973,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
||||
case UAC3_CLOCK_SELECTOR: {
|
||||
struct uac_selector_unit_descriptor *d = p1;
|
||||
/* call recursively to retrieve the channel info */
|
||||
- err = check_input_term(state, d->baSourceID[0], term);
|
||||
+ err = __check_input_term(state, d->baSourceID[0], term);
|
||||
if (err < 0)
|
||||
return err;
|
||||
term->type = UAC3_SELECTOR_UNIT << 16; /* virtual type */
|
||||
@@ -979,7 +989,7 @@ static int check_input_term(struct mixer_build *state, int id,
|
||||
return -EINVAL;
|
||||
|
||||
/* call recursively to retrieve the channel info */
|
||||
- err = check_input_term(state, d->baSourceID[0], term);
|
||||
+ err = __check_input_term(state, d->baSourceID[0], term);
|
||||
if (err < 0)
|
||||
return err;
|
||||
|
||||
@@ -997,6 +1007,15 @@ static int check_input_term(struct mixer_build *state, int id,
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
+
|
||||
+static int check_input_term(struct mixer_build *state, int id,
|
||||
+ struct usb_audio_term *term)
|
||||
+{
|
||||
+ memset(term, 0, sizeof(*term));
|
||||
+ memset(state->termbitmap, 0, sizeof(state->termbitmap));
|
||||
+ return __check_input_term(state, id, term);
|
||||
+}
|
||||
+
|
||||
/*
|
||||
* Feature Unit
|
||||
*/
|
||||
--
|
||||
cgit 1.2-0.3.lf.el7
|
||||
|
|
@ -163,6 +163,7 @@ debian/i386-686-pae-pci-set-pci-nobios-by-default.patch
|
|||
debian/ntfs-mark-it-as-broken.patch
|
||||
bugfix/all/netfilter-conntrack-use-consistent-ct-id-hash-calcul.patch
|
||||
bugfix/all/ALSA-usb-audio-Fix-an-OOB-bug-in-parse_audio_mixer_unit.patch
|
||||
bugfix/all/ALSA-usb-audio-Fix-a-stack-buffer-overflow-bug-in-check_input_term.patch
|
||||
|
||||
# Fix exported symbol versions
|
||||
bugfix/all/module-disable-matching-missing-version-crc.patch
|
||||
|
|
Loading…
Reference in New Issue