]> git.ipfire.org Git - thirdparty/kernel/stable-queue.git/blame - queue-3.18/bluetooth-verify-that-l2cap_get_conf_opt-provides-large-enough-buffer.patch
patches for 3.18
[thirdparty/kernel/stable-queue.git] / queue-3.18 / bluetooth-verify-that-l2cap_get_conf_opt-provides-large-enough-buffer.patch
CommitLineData
a9214244
GKH
1From 7c9cbd0b5e38a1672fcd137894ace3b042dfbf69 Mon Sep 17 00:00:00 2001
2From: Marcel Holtmann <marcel@holtmann.org>
3Date: Fri, 18 Jan 2019 13:43:19 +0100
4Subject: Bluetooth: Verify that l2cap_get_conf_opt provides large enough buffer
5
6From: Marcel Holtmann <marcel@holtmann.org>
7
8commit 7c9cbd0b5e38a1672fcd137894ace3b042dfbf69 upstream.
9
10The function l2cap_get_conf_opt will return L2CAP_CONF_OPT_SIZE + opt->len
11as length value. The opt->len however is in control over the remote user
12and can be used by an attacker to gain access beyond the bounds of the
13actual packet.
14
15To prevent any potential leak of heap memory, it is enough to check that
16the resulting len calculation after calling l2cap_get_conf_opt is not
17below zero. A well formed packet will always return >= 0 here and will
18end with the length value being zero after the last option has been
19parsed. In case of malformed packets messing with the opt->len field the
20length value will become negative. If that is the case, then just abort
21and ignore the option.
22
23In case an attacker uses a too short opt->len value, then garbage will
24be parsed, but that is protected by the unknown option handling and also
25the option parameter size checks.
26
27Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
28Reviewed-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
29Signed-off-by: Johan Hedberg <johan.hedberg@intel.com>
30Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
31
32---
33 net/bluetooth/l2cap_core.c | 6 ++++++
34 1 file changed, 6 insertions(+)
35
36--- a/net/bluetooth/l2cap_core.c
37+++ b/net/bluetooth/l2cap_core.c
38@@ -3290,6 +3290,8 @@ static int l2cap_parse_conf_req(struct l
39
40 while (len >= L2CAP_CONF_OPT_SIZE) {
41 len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
42+ if (len < 0)
43+ break;
44
45 hint = type & L2CAP_CONF_HINT;
46 type &= L2CAP_CONF_MASK;
47@@ -3508,6 +3510,8 @@ static int l2cap_parse_conf_rsp(struct l
48
49 while (len >= L2CAP_CONF_OPT_SIZE) {
50 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
51+ if (len < 0)
52+ break;
53
54 switch (type) {
55 case L2CAP_CONF_MTU:
56@@ -3693,6 +3697,8 @@ static void l2cap_conf_rfc_get(struct l2
57
58 while (len >= L2CAP_CONF_OPT_SIZE) {
59 len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
60+ if (len < 0)
61+ break;
62
63 switch (type) {
64 case L2CAP_CONF_RFC: