|
|
e336be |
From 20614b74e481f0c9f94032ae99f110d4647b65a6 Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
|
e336be |
Date: Thu, 10 Jan 2019 07:28:33 +0100
|
|
|
e336be |
Subject: [PATCH 1/2] Bluetooth: check message types in l2cap_get_conf_opt
|
|
|
e336be |
|
|
|
e336be |
l2cap_get_conf_opt can handle a "default" message type, but it needs to
|
|
|
e336be |
be verified that it really is the correct type (CONF_EFS or CONF_RFC)
|
|
|
e336be |
before passing it back to the caller. To do this we need to check the
|
|
|
e336be |
return value of this call now and handle the error correctly up the
|
|
|
e336be |
stack.
|
|
|
e336be |
|
|
|
e336be |
Based on a patch from Ran Menscher.
|
|
|
e336be |
|
|
|
e336be |
Reported-by: Ran Menscher <ran.menscher@karambasecurity.com>
|
|
|
e336be |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
|
e336be |
Signed-off-by: Jeremy Cline <jcline@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
net/bluetooth/l2cap_core.c | 25 +++++++++++++++++++------
|
|
|
e336be |
1 file changed, 19 insertions(+), 6 deletions(-)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
|
|
|
e336be |
index d17a4736e47c..a0ce6e8e5ef7 100644
|
|
|
e336be |
--- a/net/bluetooth/l2cap_core.c
|
|
|
e336be |
+++ b/net/bluetooth/l2cap_core.c
|
|
|
e336be |
@@ -2979,6 +2979,10 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
|
|
|
e336be |
break;
|
|
|
e336be |
|
|
|
e336be |
default:
|
|
|
e336be |
+ /* Only CONF_EFS and CONF_RFC are allowed here */
|
|
|
e336be |
+ if ((opt->type != L2CAP_CONF_EFS) &&
|
|
|
e336be |
+ (opt->type != L2CAP_CONF_RFC))
|
|
|
e336be |
+ return -EPROTO;
|
|
|
e336be |
*val = (unsigned long) opt->val;
|
|
|
e336be |
break;
|
|
|
e336be |
}
|
|
|
e336be |
@@ -3323,7 +3327,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
|
|
|
e336be |
void *endptr = data + data_size;
|
|
|
e336be |
void *req = chan->conf_req;
|
|
|
e336be |
int len = chan->conf_len;
|
|
|
e336be |
- int type, hint, olen;
|
|
|
e336be |
+ int type, hint, olen, err;
|
|
|
e336be |
unsigned long val;
|
|
|
e336be |
struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
|
|
|
e336be |
struct l2cap_conf_efs efs;
|
|
|
e336be |
@@ -3335,7 +3339,10 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
|
|
|
e336be |
BT_DBG("chan %p", chan);
|
|
|
e336be |
|
|
|
e336be |
while (len >= L2CAP_CONF_OPT_SIZE) {
|
|
|
e336be |
- len -= l2cap_get_conf_opt(&req, &type, &olen, &val;;
|
|
|
e336be |
+ err = l2cap_get_conf_opt(&req, &type, &olen, &val;;
|
|
|
e336be |
+ if (err < 0)
|
|
|
e336be |
+ return err;
|
|
|
e336be |
+ len -= err;
|
|
|
e336be |
|
|
|
e336be |
hint = type & L2CAP_CONF_HINT;
|
|
|
e336be |
type &= L2CAP_CONF_MASK;
|
|
|
e336be |
@@ -3538,7 +3545,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
|
|
e336be |
struct l2cap_conf_req *req = data;
|
|
|
e336be |
void *ptr = req->data;
|
|
|
e336be |
void *endptr = data + size;
|
|
|
e336be |
- int type, olen;
|
|
|
e336be |
+ int type, olen, err;
|
|
|
e336be |
unsigned long val;
|
|
|
e336be |
struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
|
|
|
e336be |
struct l2cap_conf_efs efs;
|
|
|
e336be |
@@ -3546,7 +3553,10 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
|
|
e336be |
BT_DBG("chan %p, rsp %p, len %d, req %p", chan, rsp, len, data);
|
|
|
e336be |
|
|
|
e336be |
while (len >= L2CAP_CONF_OPT_SIZE) {
|
|
|
e336be |
- len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val;;
|
|
|
e336be |
+ err = l2cap_get_conf_opt(&rsp, &type, &olen, &val;;
|
|
|
e336be |
+ if (err < 0)
|
|
|
e336be |
+ return err;
|
|
|
e336be |
+ len -= err;
|
|
|
e336be |
|
|
|
e336be |
switch (type) {
|
|
|
e336be |
case L2CAP_CONF_MTU:
|
|
|
e336be |
@@ -3706,7 +3716,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
|
|
|
e336be |
|
|
|
e336be |
static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
|
|
|
e336be |
{
|
|
|
e336be |
- int type, olen;
|
|
|
e336be |
+ int type, olen, err;
|
|
|
e336be |
unsigned long val;
|
|
|
e336be |
/* Use sane default values in case a misbehaving remote device
|
|
|
e336be |
* did not send an RFC or extended window size option.
|
|
|
e336be |
@@ -3726,7 +3736,10 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len)
|
|
|
e336be |
return;
|
|
|
e336be |
|
|
|
e336be |
while (len >= L2CAP_CONF_OPT_SIZE) {
|
|
|
e336be |
- len -= l2cap_get_conf_opt(&rsp, &type, &olen, &val;;
|
|
|
e336be |
+ err = l2cap_get_conf_opt(&rsp, &type, &olen, &val;;
|
|
|
e336be |
+ if (err < 0)
|
|
|
e336be |
+ return;
|
|
|
e336be |
+ len -= err;
|
|
|
e336be |
|
|
|
e336be |
switch (type) {
|
|
|
e336be |
case L2CAP_CONF_RFC:
|
|
|
e336be |
--
|
|
|
e336be |
2.20.1
|
|
|
e336be |
|
|
|
e336be |
From 50cd5314f5ffa264906f4986f414750d648c4ece Mon Sep 17 00:00:00 2001
|
|
|
e336be |
From: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
|
e336be |
Date: Thu, 10 Jan 2019 07:29:17 +0100
|
|
|
e336be |
Subject: [PATCH 2/2] Bluetooth: check the buffer size for some messages before
|
|
|
e336be |
parsing
|
|
|
e336be |
|
|
|
e336be |
The L2CAP_CONF_EFS and L2CAP_CONF_RFC messages can be sent from
|
|
|
e336be |
userspace so their structure sizes need to be checked before parsing
|
|
|
e336be |
them.
|
|
|
e336be |
|
|
|
e336be |
Based on a patch from Ran Menscher.
|
|
|
e336be |
|
|
|
e336be |
Reported-by: Ran Menscher <ran.menscher@karambasecurity.com>
|
|
|
e336be |
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
|
|
e336be |
Signed-off-by: Jeremy Cline <jcline@redhat.com>
|
|
|
e336be |
---
|
|
|
e336be |
net/bluetooth/l2cap_core.c | 12 ++++++++----
|
|
|
e336be |
1 file changed, 8 insertions(+), 4 deletions(-)
|
|
|
e336be |
|
|
|
e336be |
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
|
|
|
e336be |
index a0ce6e8e5ef7..d8d3cbdc0d29 100644
|
|
|
e336be |
--- a/net/bluetooth/l2cap_core.c
|
|
|
e336be |
+++ b/net/bluetooth/l2cap_core.c
|
|
|
e336be |
@@ -3360,7 +3360,8 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
|
|
|
e336be |
break;
|
|
|
e336be |
|
|
|
e336be |
case L2CAP_CONF_RFC:
|
|
|
e336be |
- if (olen == sizeof(rfc))
|
|
|
e336be |
+ if ((olen == sizeof(rfc)) &&
|
|
|
e336be |
+ (endptr - ptr >= L2CAP_CONF_OPT_SIZE + sizeof(rfc)))
|
|
|
e336be |
memcpy(&rfc, (void *) val, olen);
|
|
|
e336be |
break;
|
|
|
e336be |
|
|
|
e336be |
@@ -3370,7 +3371,8 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data
|
|
|
e336be |
break;
|
|
|
e336be |
|
|
|
e336be |
case L2CAP_CONF_EFS:
|
|
|
e336be |
- if (olen == sizeof(efs)) {
|
|
|
e336be |
+ if ((olen == sizeof(efs)) &&
|
|
|
e336be |
+ (endptr - ptr >= L2CAP_CONF_OPT_SIZE + sizeof(efs))) {
|
|
|
e336be |
remote_efs = 1;
|
|
|
e336be |
memcpy(&efs, (void *) val, olen);
|
|
|
e336be |
}
|
|
|
e336be |
@@ -3575,7 +3577,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
|
|
e336be |
break;
|
|
|
e336be |
|
|
|
e336be |
case L2CAP_CONF_RFC:
|
|
|
e336be |
- if (olen == sizeof(rfc))
|
|
|
e336be |
+ if ((olen == sizeof(rfc)) &&
|
|
|
e336be |
+ (endptr - ptr >= L2CAP_CONF_OPT_SIZE + sizeof(rfc)))
|
|
|
e336be |
memcpy(&rfc, (void *)val, olen);
|
|
|
e336be |
|
|
|
e336be |
if (test_bit(CONF_STATE2_DEVICE, &chan->conf_state) &&
|
|
|
e336be |
@@ -3595,7 +3598,8 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
|
|
|
e336be |
break;
|
|
|
e336be |
|
|
|
e336be |
case L2CAP_CONF_EFS:
|
|
|
e336be |
- if (olen == sizeof(efs)) {
|
|
|
e336be |
+ if ((olen == sizeof(efs)) &&
|
|
|
e336be |
+ (endptr - ptr >= L2CAP_CONF_OPT_SIZE + sizeof(efs))) {
|
|
|
e336be |
memcpy(&efs, (void *)val, olen);
|
|
|
e336be |
|
|
|
e336be |
if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
|
|
|
e336be |
--
|
|
|
e336be |
2.20.1
|
|
|
e336be |
|