Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp517394yba; Mon, 1 Apr 2019 10:53:50 -0700 (PDT) X-Google-Smtp-Source: APXvYqzqjScjH5xGX00uFpqtRW1aO1eHkVl7XjttmnTh9GNgxE8pFWWmO71Uxf2dF2cLLWwAjcDG X-Received: by 2002:a65:518b:: with SMTP id h11mr62110318pgq.41.1554141230501; Mon, 01 Apr 2019 10:53:50 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554141230; cv=none; d=google.com; s=arc-20160816; b=iPLcQvCNah/Pb5IlpklttX+50Xd4L5UPlCdWUtrYcXO5LX1kKmm4Qh7LhDrxAfLT3h ZMhsShvvj/udvRZ1FWmlH249fZ0zqnC1+1E/L/vr3klm9MBXBK0WhnF7UXQuasiZoM0J EV72+VkiMCk7JBfBnnoSa7z110+8nM1ZMJXQQIrGcvZi/CcoRmgpqKWEXpPHYgSfOzwu h2ZWwNtg2Bl/9U4CoURJjqApQNcPAzoYSddX2GVfhA6W6bNkVEsfC26fcmdeVSs2c3ID qk441U5nXr5mLjttn2IGpT/YAZ7Q/tp6NZEyQsMzDvoVJjof5IhGhGK9nBI1vBkwx6YZ DGkw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=cC3kl8DIvHHbXRhyNNqH7yiDtRJF765OE7A88pgV/B0=; b=czN+kkMTCS8SElkvyG9PozIILNOlR72Gei0JwtMoykoQhlEg3vfacxlSvRKTCCgKkt BXmdmYtB60esVmmu1gADT1cvY3JQyznD7o2rClyMvTBBXSxD9G/jU82SqJl7ZSsTuOP7 33Zpj9Y+o0FjgQ4LgiuF4jwXPgfptJA+GAjWJE9nanDcxtJZrGL8wGl10HWcX3TSxP66 RW9C4TjgiM/NidRV1RI/4T6QGYg7tsp4MhO083GfmCj/N8vJWigx6vdwHh9JhbtJK/Fi mcTg+94ML/3926T+SG3gTfwyG9ojbNp2Qd8EGBbrJhJeIZ6WLGTppxKhszLWiugtbW9Y Rqxw== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=E7VrVbY7; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id g6si8959632pgq.506.2019.04.01.10.53.34; Mon, 01 Apr 2019 10:53:50 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b=E7VrVbY7; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1732525AbfDAR0T (ORCPT + 99 others); Mon, 1 Apr 2019 13:26:19 -0400 Received: from mail.kernel.org ([198.145.29.99]:58276 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1732346AbfDAR0S (ORCPT ); Mon, 1 Apr 2019 13:26:18 -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 54A4D20830; Mon, 1 Apr 2019 17:26:16 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1554139576; bh=ME9LcCpUP7ZU5rb4x7KtAmDrzMdcpc7Np4bSmPMrlKE=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=E7VrVbY7/F6TarRN+/oSiAUQfDDwcfjiQmrlA5NMNY4thXlden5OLwxViiKluo0m3 aUse7uF7aANy25P+GUFHdKLmgwufPjE2nBnXpKMuq+vGOdkU3laqIXXhUCsfTMH0kD D/dSJCD10FOy2dv0JJG24RNnpWHg5C0A1O8iK9po= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org Cc: Greg Kroah-Hartman , stable@vger.kernel.org, Marcel Holtmann , Johan Hedberg Subject: [PATCH 4.9 01/56] Bluetooth: Check L2CAP option sizes returned from l2cap_get_conf_opt Date: Mon, 1 Apr 2019 19:02:17 +0200 Message-Id: <20190401170103.496563071@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401170103.398401360@linuxfoundation.org> References: <20190401170103.398401360@linuxfoundation.org> User-Agent: quilt/0.65 X-stable: review X-Patchwork-Hint: ignore MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org 4.9-stable review patch. If anyone has any objections, please let me know. ------------------ From: Marcel Holtmann commit af3d5d1c87664a4f150fcf3534c6567cb19909b0 upstream. When doing option parsing for standard type values of 1, 2 or 4 octets, the value is converted directly into a variable instead of a pointer. To avoid being tricked into being a pointer, check that for these option types that sizes actually match. In L2CAP every option is fixed size and thus it is prudent anyway to ensure that the remote side sends us the right option size along with option paramters. If the option size is not matching the option type, then that option is silently ignored. It is a protocol violation and instead of trying to give the remote attacker any further hints just pretend that option is not present and proceed with the default values. Implementation following the specification and its qualification procedures will always use the correct size and thus not being impacted here. To keep the code readable and consistent accross all options, a few cosmetic changes were also required. Signed-off-by: Marcel Holtmann Reviewed-by: Greg Kroah-Hartman Signed-off-by: Johan Hedberg Signed-off-by: Greg Kroah-Hartman --- net/bluetooth/l2cap_core.c | 77 ++++++++++++++++++++++++++------------------- 1 file changed, 46 insertions(+), 31 deletions(-) --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -3332,10 +3332,14 @@ static int l2cap_parse_conf_req(struct l switch (type) { case L2CAP_CONF_MTU: + if (olen != 2) + break; mtu = val; break; case L2CAP_CONF_FLUSH_TO: + if (olen != 2) + break; chan->flush_to = val; break; @@ -3343,26 +3347,30 @@ static int l2cap_parse_conf_req(struct l break; case L2CAP_CONF_RFC: - if (olen == sizeof(rfc)) - memcpy(&rfc, (void *) val, olen); + if (olen != sizeof(rfc)) + break; + memcpy(&rfc, (void *) val, olen); break; case L2CAP_CONF_FCS: + if (olen != 1) + break; if (val == L2CAP_FCS_NONE) set_bit(CONF_RECV_NO_FCS, &chan->conf_state); break; case L2CAP_CONF_EFS: - if (olen == sizeof(efs)) { - remote_efs = 1; - memcpy(&efs, (void *) val, olen); - } + if (olen != sizeof(efs)) + break; + remote_efs = 1; + memcpy(&efs, (void *) val, olen); break; case L2CAP_CONF_EWS: + if (olen != 2) + break; if (!(chan->conn->local_fixed_chan & L2CAP_FC_A2MP)) return -ECONNREFUSED; - set_bit(FLAG_EXT_CTRL, &chan->flags); set_bit(CONF_EWS_RECV, &chan->conf_state); chan->tx_win_max = L2CAP_DEFAULT_EXT_WINDOW; @@ -3372,7 +3380,6 @@ static int l2cap_parse_conf_req(struct l default: if (hint) break; - result = L2CAP_CONF_UNKNOWN; *((u8 *) ptr++) = type; break; @@ -3540,55 +3547,60 @@ static int l2cap_parse_conf_rsp(struct l switch (type) { case L2CAP_CONF_MTU: + if (olen != 2) + break; if (val < L2CAP_DEFAULT_MIN_MTU) { *result = L2CAP_CONF_UNACCEPT; chan->imtu = L2CAP_DEFAULT_MIN_MTU; } else chan->imtu = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, + endptr - ptr); break; case L2CAP_CONF_FLUSH_TO: + if (olen != 2) + break; chan->flush_to = val; - l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, - 2, chan->flush_to, endptr - ptr); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO, 2, + chan->flush_to, endptr - ptr); break; case L2CAP_CONF_RFC: - if (olen == sizeof(rfc)) - memcpy(&rfc, (void *)val, olen); - + if (olen != sizeof(rfc)) + break; + memcpy(&rfc, (void *)val, olen); if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) && rfc.mode != chan->mode) return -ECONNREFUSED; - chan->fcs = 0; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, - sizeof(rfc), (unsigned long) &rfc, endptr - ptr); + l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc), + (unsigned long) &rfc, endptr - ptr); break; case L2CAP_CONF_EWS: + if (olen != 2) + break; chan->ack_win = min_t(u16, val, chan->ack_win); l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2, chan->tx_win, endptr - ptr); break; case L2CAP_CONF_EFS: - if (olen == sizeof(efs)) { - memcpy(&efs, (void *)val, olen); - - if (chan->local_stype != L2CAP_SERV_NOTRAFIC && - efs.stype != L2CAP_SERV_NOTRAFIC && - efs.stype != chan->local_stype) - return -ECONNREFUSED; - - l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), - (unsigned long) &efs, endptr - ptr); - } + if (olen != sizeof(efs)) + break; + memcpy(&efs, (void *)val, olen); + if (chan->local_stype != L2CAP_SERV_NOTRAFIC && + efs.stype != L2CAP_SERV_NOTRAFIC && + efs.stype != chan->local_stype) + return -ECONNREFUSED; + l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs), + (unsigned long) &efs, endptr - ptr); break; case L2CAP_CONF_FCS: + if (olen != 1) + break; if (*result == L2CAP_CONF_PENDING) if (val == L2CAP_FCS_NONE) set_bit(CONF_RECV_NO_FCS, @@ -3720,10 +3732,13 @@ static void l2cap_conf_rfc_get(struct l2 switch (type) { case L2CAP_CONF_RFC: - if (olen == sizeof(rfc)) - memcpy(&rfc, (void *)val, olen); + if (olen != sizeof(rfc)) + break; + memcpy(&rfc, (void *)val, olen); break; case L2CAP_CONF_EWS: + if (olen != 2) + break; txwin_ext = val; break; }