From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=3.0 tests=DKIMWL_WL_HIGH,DKIM_SIGNED, DKIM_VALID,HEADER_FROM_DIFFERENT_DOMAINS,MAILING_LIST_MULTI,SIGNED_OFF_BY, SPF_HELO_NONE,SPF_PASS,URIBL_BLOCKED,USER_AGENT_GIT autolearn=unavailable autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id C5ECBC3A5AA for ; Wed, 4 Sep 2019 18:26:07 +0000 (UTC) Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.kernel.org (Postfix) with ESMTP id 9A03720882 for ; Wed, 4 Sep 2019 18:26:07 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1567621567; bh=6oDyFR38u3Sb0+w6Xro+veCFGmmBPh4sIfpRaH/O8F0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:List-ID:From; b=CnrZWmuL9JMa8Auc6NSMGYXjySWaolp56aG5xtbiLH/CQru2I7wSIpZOYxD7OMhxh t6mdukJ/s1e8CQs+Oss5cNxITAoGNhzOwlF2I4ioaA8FHNBCs1y8Vk0y7/yTYdIFZ8 RWfW4e7ripXVggpvkROvpbxc1k1gFnf/4PUXfgic= Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732610AbfIDR6q (ORCPT ); Wed, 4 Sep 2019 13:58:46 -0400 Received: from mail.kernel.org ([198.145.29.99]:37276 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S2388096AbfIDR6q (ORCPT ); Wed, 4 Sep 2019 13:58:46 -0400 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id 172B522CF5; Wed, 4 Sep 2019 17:58:43 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1567619924; bh=6oDyFR38u3Sb0+w6Xro+veCFGmmBPh4sIfpRaH/O8F0=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qOYpy6MruB3g7wD40/Z3utuiNZVAXFIcKEhpt/5aFGR6Vnhmrd0oK/RcKlacBLELa BdB0x7/vitN1geLJ+Y/7oghXKoJwHWPgwmb3+tjNrTvzM3XsXzUuF47BssVSEBYRNm U1NUbzDnbWLReuyTmfoy61teaL/sqmyuXydKg/v8= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Hui Peng , Mathias Payer , Takashi Iwai Subject: [PATCH 4.4 57/77] ALSA: usb-audio: Fix a stack buffer overflow bug in check_input_term Date: Wed, 4 Sep 2019 19:53:44 +0200 Message-Id: <20190904175308.632171167@linuxfoundation.org> X-Mailer: git-send-email 2.23.0 In-Reply-To: <20190904175303.317468926@linuxfoundation.org> References: <20190904175303.317468926@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: stable-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: stable@vger.kernel.org From: Hui Peng 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 Reported-by: Mathias Payer Signed-off-by: Hui Peng Cc: Signed-off-by: Takashi Iwai Signed-off-by: Greg Kroah-Hartman --- sound/usb/mixer.c | 29 ++++++++++++++++++++++++----- 1 file changed, 24 insertions(+), 5 deletions(-) --- a/sound/usb/mixer.c +++ b/sound/usb/mixer.c @@ -81,6 +81,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; @@ -709,15 +710,24 @@ static int get_term_name(struct mixer_bu * 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: @@ -732,7 +742,7 @@ static int check_input_term(struct mixer /* 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; @@ -764,7 +774,7 @@ static int check_input_term(struct mixer 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 */ @@ -811,6 +821,15 @@ static int check_input_term(struct mixer 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 */