Skip to content

Commit 000d784

Browse files
holtmannjfvogel
authored andcommitted
Bluetooth: Verify that l2cap_get_conf_opt provides large enough buffer
The function l2cap_get_conf_opt will return L2CAP_CONF_OPT_SIZE + opt->len as length value. The opt->len however is in control over the remote user and can be used by an attacker to gain access beyond the bounds of the actual packet. To prevent any potential leak of heap memory, it is enough to check that the resulting len calculation after calling l2cap_get_conf_opt is not below zero. A well formed packet will always return >= 0 here and will end with the length value being zero after the last option has been parsed. In case of malformed packets messing with the opt->len field the length value will become negative. If that is the case, then just abort and ignore the option. In case an attacker uses a too short opt->len value, then garbage will be parsed, but that is protected by the unknown option handling and also the option parameter size checks. Signed-off-by: Marcel Holtmann <[email protected]> Reviewed-by: Greg Kroah-Hartman <[email protected]> Signed-off-by: Johan Hedberg <[email protected]> Orabug: 29526424 CVE: CVE-2019-3459 (cherry picked from commit 7c9cbd0) Signed-off-by: Dan Duval <[email protected]> Reviewed-by: Jack Vogel <[email protected]>
1 parent d09afa7 commit 000d784

File tree

1 file changed

+6
-0
lines changed

1 file changed

+6
-0
lines changed

net/bluetooth/l2cap_core.c

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3336,6 +3336,8 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
33363336

33373337
while (len >= L2CAP_CONF_OPT_SIZE) {
33383338
len -= l2cap_get_conf_opt(&req, &type, &olen, &val);
3339+
if (len < 0)
3340+
break;
33393341

33403342
hint = type & L2CAP_CONF_HINT;
33413343
type &= L2CAP_CONF_MASK;
@@ -3554,6 +3556,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
35543556

35553557
while (len >= L2CAP_CONF_OPT_SIZE) {
35563558
len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
3559+
if (len < 0)
3560+
break;
35573561

35583562
switch (type) {
35593563
case L2CAP_CONF_MTU:
@@ -3739,6 +3743,8 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
37393743

37403744
while (len >= L2CAP_CONF_OPT_SIZE) {
37413745
len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val);
3746+
if (len < 0)
3747+
break;
37423748

37433749
switch (type) {
37443750
case L2CAP_CONF_RFC:

0 commit comments

Comments
 (0)