From patchwork Fri Aug 30 00:13:51 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Connor Kuehl X-Patchwork-Id: 1155577 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=none (mailfrom) smtp.mailfrom=lists.ubuntu.com (client-ip=91.189.94.19; helo=huckleberry.canonical.com; envelope-from=kernel-team-bounces@lists.ubuntu.com; receiver=) Authentication-Results: ozlabs.org; dmarc=fail (p=none dis=none) header.from=canonical.com Received: from huckleberry.canonical.com (huckleberry.canonical.com [91.189.94.19]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 46KKjL3KWwz9sNC; Fri, 30 Aug 2019 10:14:30 +1000 (AEST) Received: from localhost ([127.0.0.1] helo=huckleberry.canonical.com) by huckleberry.canonical.com with esmtp (Exim 4.86_2) (envelope-from ) id 1i3UYc-0002h9-C9; Fri, 30 Aug 2019 00:14:26 +0000 Received: from youngberry.canonical.com ([91.189.89.112]) by huckleberry.canonical.com with esmtps (TLS1.0:DHE_RSA_AES_128_CBC_SHA1:128) (Exim 4.86_2) (envelope-from ) id 1i3UYY-0002fd-QQ for kernel-team@lists.ubuntu.com; Fri, 30 Aug 2019 00:14:22 +0000 Received: from mail-pg1-f198.google.com ([209.85.215.198]) by youngberry.canonical.com with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.76) (envelope-from ) id 1i3UYY-0003ph-96 for kernel-team@lists.ubuntu.com; Fri, 30 Aug 2019 00:14:22 +0000 Received: by mail-pg1-f198.google.com with SMTP id t19so2916654pgh.6 for ; Thu, 29 Aug 2019 17:14:22 -0700 (PDT) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=Ev+sV5jAA3DVdsvAB3hahDrYeovhVtmUwCNzB90haRY=; b=RqMT3NgT4g62b/k8tuLB9aEKQipnKwZ80wK5Qd7DsS4pgtNQ65vCJ/GQ4+RDS0mo94 JOBFw6nfBK7/dEDHl3eQ6BMrkSUSCyIoTM66pSzZUxxAnYvX4Sx7RXyJdJ6Khtu8gxl4 B9Mts236sQkqDLIOeNs7aMXVYQbLZomZ7bZT8oy7o+kyYLHCd8n/tXYMMYFCwDvLXL63 ygY/3KNQBsl4GOTJzKcErdkJTwWblcSdc8E26NKXsDOR6OlUuRzvpDa1xIllDpGc0YXC MKP2SodQaELmqFCkNPWABH8AvINJFySusdy85kcxhG+sGVrLkHOh5rKbBxXGXlsC1t5F a88g== X-Gm-Message-State: APjAAAVtWbFfRjz2ERwnvlX8msq3fj8tlqg2Q4XGzXb7p47L3Om/fgIL PUf+tMAbGhnwDjw3IpyHDJa+YCHfKEXQ28ToIcw1Qs7jH3zSUfl+YnC8SM24K4TxesshuSVBgxi 671TFD9tb1DlwwGLJDtFcWv9joiIPzb+jPy3E8U7o+A== X-Received: by 2002:a65:534c:: with SMTP id w12mr10699180pgr.51.1567124060285; Thu, 29 Aug 2019 17:14:20 -0700 (PDT) X-Google-Smtp-Source: APXvYqymdEyRldNTNBYkD6fsQ3+UBAvVqbnUeUTxM4kWR7VSXV32Ce5cZ2+0R9cscpWwc1AVuGuQpw== X-Received: by 2002:a65:534c:: with SMTP id w12mr10699167pgr.51.1567124059967; Thu, 29 Aug 2019 17:14:19 -0700 (PDT) Received: from localhost.localdomain (c-24-20-45-88.hsd1.or.comcast.net. [24.20.45.88]) by smtp.gmail.com with ESMTPSA id z68sm3354102pgz.88.2019.08.29.17.14.18 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Thu, 29 Aug 2019 17:14:18 -0700 (PDT) From: Connor Kuehl To: kernel-team@lists.ubuntu.com Subject: [X/B][SRU][CVE-2019-15118][PATCH 2/2] ALSA: usb-audio: Fix a stack buffer overflow bug in check_input_term Date: Thu, 29 Aug 2019 17:13:51 -0700 Message-Id: <20190830001351.3686-5-connor.kuehl@canonical.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190830001351.3686-1-connor.kuehl@canonical.com> References: <20190830001351.3686-1-connor.kuehl@canonical.com> X-BeenThere: kernel-team@lists.ubuntu.com X-Mailman-Version: 2.1.20 Precedence: list List-Id: Kernel team discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , MIME-Version: 1.0 Errors-To: kernel-team-bounces@lists.ubuntu.com Sender: "kernel-team" From: Hui Peng CVE-2019-15118 `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 Reported-by: Mathias Payer Signed-off-by: Hui Peng Cc: Signed-off-by: Takashi Iwai (backported from commit 19bce474c45be69a284ecee660aa12d8f1e88f18) [ Connor Kuehl: Manually replaced the while loop with the new for loop due to context adjustments. Some hunks were dropped as they were targeting bits of code that aren't added until mainline commit: 9a2fe9b801f5 "ALSA: usb: initial USB Audio Device Class 3.0 support" Signed-off-by: Connor Kuehl --- sound/usb/mixer.c | 30 +++++++++++++++++++++++++----- 1 file changed, 25 insertions(+), 5 deletions(-) diff --git a/sound/usb/mixer.c b/sound/usb/mixer.c index 713020741289..f743fd91a138 100644 --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -82,6 +82,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; @@ -716,16 +717,26 @@ static int get_term_name(struct mixer_build *state, struct usb_audio_term *iterm * 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 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; + switch (hdr[2]) { case UAC_INPUT_TERMINAL: if (state->mixer->protocol == UAC_VERSION_1) { @@ -739,7 +750,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; @@ -771,7 +782,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 = d->bDescriptorSubtype << 16; /* virtual type */ @@ -818,6 +829,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 */