Received: by 2002:a25:4158:0:0:0:0:0 with SMTP id o85csp491987yba; Mon, 1 Apr 2019 10:22:13 -0700 (PDT) X-Google-Smtp-Source: APXvYqwQPxxgxdoWOGcaeO5PHjzl4uVSe/1J1E+gIA1zE8+/dHe8gDgmlIBwjpvC5mZCZYqxhg8p X-Received: by 2002:a62:e412:: with SMTP id r18mr12131736pfh.207.1554139333733; Mon, 01 Apr 2019 10:22:13 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1554139333; cv=none; d=google.com; s=arc-20160816; b=Rr7mNgX1yLpcjKgWl+LOKX9rBzKIuo8TXZIdk6j1a6W6u5H7hq5F3KSQTvdQFYgxI5 tv7JlQdel9bsDGBCZ2XwO8ZuehCbgsLWGdHSUL1g2ra3C8j0NnOeEneQHRhP+8LJzIkj sxBp9JJxBz5xOCaSkDq4/6nqeihW94JR+aVglRR/QfiNf7wni0m/03wU+nzWneR/UCvh whYGYM04aJUioEkVllqphiZURQsBh2awqKpSnsZVvlwe0AqOldJuxiwNwaiRegQzHRej S4kqYOgePOanig2kWvT51DxW1PbqJ61zrq7Q5TOvp9IIoGMI8lZ48f3JlmZZ9g1AW07y ej4w== 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=ETJbbmk1W/Yt/H83lNoPlEhxlWmFi7wHtKd2Y/LFCYg=; b=bOhdnbwLmAA1NRHbrVmEyFilQWzdNBfXHrj4nRLogKu0GOkUd2CVPd6mJPN7+KfELs q0IMGoxbGbFQIDRn9pNfDK4PiGExWjSty3tLUNosB9mHIj6+0pQohz5NDMtaIfp6bpYT +XfmBYmry/roClS3TUpr7ajfQ1hzb+s4SJ9p7udPxonuDUoZU+ryWcRAeS6ooHrVxVc6 83LpDlti7tDhbWC975/SpPGj92NvtYI0EylvSxh3HeSRkRe7aa0Se2jWlMGF/QBuY/Iz bx9HdUpTcFlp2AogoYekMsHz5KPmJhR3vbO8/4eSWL0C5O7FCgJJtFkODLgBYoyBH2L3 s3Gg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="L4dX/qHJ"; 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 h11si9034458pgs.432.2019.04.01.10.21.57; Mon, 01 Apr 2019 10:22:13 -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="L4dX/qHJ"; 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 S1731611AbfDARUE (ORCPT + 99 others); Mon, 1 Apr 2019 13:20:04 -0400 Received: from mail.kernel.org ([198.145.29.99]:48130 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1730811AbfDARUB (ORCPT ); Mon, 1 Apr 2019 13:20:01 -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 434DE206DD; Mon, 1 Apr 2019 17:19:59 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1554139199; bh=q9+aon7/n223PjlDBFyxZwOkKx6i81bdDkVW7qVCubk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=L4dX/qHJHNJpUN36bgmDQ8pw+mk0rpBtL3jMR6evVAB3F2QPY9hqvGQSkfWi4DwTh YOYDeUxpQwb0r51wYgzm/ViLUdbafvCAUNMX8VzSHJpJaLha9g3skeMzCfZm8itxYs BslZhWQPBTyzZYRr1byXPDhrB1qi8oIplCNmZNOw= 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.14 001/107] Bluetooth: Check L2CAP option sizes returned from l2cap_get_conf_opt Date: Mon, 1 Apr 2019 19:01:16 +0200 Message-Id: <20190401170045.390837116@linuxfoundation.org> X-Mailer: git-send-email 2.21.0 In-Reply-To: <20190401170045.246405031@linuxfoundation.org> References: <20190401170045.246405031@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.14-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 @@ -3342,10 +3342,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; @@ -3353,26 +3357,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; @@ -3382,7 +3390,6 @@ static int l2cap_parse_conf_req(struct l default: if (hint) break; - result = L2CAP_CONF_UNKNOWN; *((u8 *) ptr++) = type; break; @@ -3550,55 +3557,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, @@ -3730,10 +3742,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; }