Update Linux CVE patches

This commit is contained in:
Tad 2017-10-29 22:14:37 -04:00
parent 12b63c12b7
commit 3989a1b20b
958 changed files with 21074 additions and 397 deletions

View file

@ -0,0 +1,403 @@
From 2e073d2001f354982b777a38d931002a62395de1 Mon Sep 17 00:00:00 2001
From: Ben Seri <ben@armis.com>
Date: Sat, 09 Sep 2017 23:15:59 +0200
Subject: [PATCH] Bluetooth: Properly check L2CAP config option output buffer length
Validate the output buffer length for L2CAP config requests and responses
to avoid overflowing the stack buffer used for building the option blocks.
Change-Id: I7a0ff0b9dd0156c0e6383214a9c86e4ec4c0d236
Cc: stable@vger.kernel.org
Signed-off-by: Ben Seri <ben@armis.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
CVE-2017-1000251
Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
---
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index ef5e849..b868343 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -668,7 +668,7 @@
u8 l2cap_get_ident(struct l2cap_conn *conn);
void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
-int l2cap_build_conf_req(struct sock *sk, void *data);
+int l2cap_build_conf_req(struct sock *sk, void *data, size_t data_size);
int __l2cap_wait_ack(struct sock *sk);
struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index af0dcba..a4ab0ff 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -910,7 +910,7 @@
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
@@ -2892,11 +2892,14 @@
return len;
}
-static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
{
struct l2cap_conf_opt *opt = *ptr;
BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
+
+ if (size < L2CAP_CONF_OPT_SIZE + len)
+ return;
opt->type = type;
opt->len = len;
@@ -3275,12 +3278,13 @@
}
}
-int l2cap_build_conf_req(struct sock *sk, void *data)
+int l2cap_build_conf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = pi->mode };
void *ptr = req->data;
+ void *endptr = data + data_size;
BT_DBG("sk %p", sk);
@@ -3301,7 +3305,7 @@
done:
if (pi->imtu != L2CAP_DEFAULT_MTU)
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu, endptr - ptr);
switch (pi->mode) {
case L2CAP_MODE_BASIC:
@@ -3316,7 +3320,7 @@
rfc.max_pdu_size = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_MODE_ERTM:
@@ -3333,12 +3337,12 @@
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if ((pi->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW) &&
pi->extended_control) {
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2,
- pi->tx_win);
+ pi->tx_win, endptr - ptr);
}
if (pi->amp_id) {
@@ -3346,7 +3350,7 @@
struct l2cap_conf_ext_fs fs = {1, 1, 0xFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_FS,
- sizeof(fs), (unsigned long) &fs);
+ sizeof(fs), (unsigned long) &fs, endptr - ptr);
}
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
@@ -3355,7 +3359,7 @@
if (pi->fcs == L2CAP_FCS_NONE ||
pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
pi->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs, endptr - ptr);
}
break;
@@ -3369,11 +3373,11 @@
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if ((pi->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW) &&
pi->extended_control) {
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2, 0);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2, 0, endptr - ptr);
}
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
@@ -3382,7 +3386,7 @@
if (pi->fcs == L2CAP_FCS_NONE ||
pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
pi->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs, endptr - ptr);
}
break;
}
@@ -3394,12 +3398,13 @@
}
-static int l2cap_build_amp_reconf_req(struct sock *sk, void *data)
+static int l2cap_build_amp_reconf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = pi->mode };
void *ptr = req->data;
+ void *endptr = data + data_size;
BT_DBG("sk %p", sk);
@@ -3420,7 +3425,7 @@
}
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if (pi->conn->feat_mask & L2CAP_FEAT_FCS) {
/* TODO assign fcs for br/edr based on socket config option */
@@ -3431,7 +3436,7 @@
else
pi->local_conf.fcs = L2CAP_FCS_CRC16;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->local_conf.fcs);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->local_conf.fcs, endptr - ptr);
pi->fcs = pi->local_conf.fcs | pi->remote_conf.fcs;
}
@@ -3441,11 +3446,12 @@
return ptr - data;
}
-static int l2cap_parse_conf_req(struct sock *sk, void *data)
+static int l2cap_parse_conf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
+ void *endptr = data + data_size;
void *req = pi->conf_req;
int len = pi->conf_len;
int type, hint, olen;
@@ -3563,7 +3569,8 @@
return -ECONNREFUSED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc,
+ endptr - ptr);
}
@@ -3583,7 +3590,7 @@
pi->omtu = mtu;
pi->conf_state |= L2CAP_CONF_MTU_DONE;
}
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu, endptr - ptr);
switch (rfc.mode) {
case L2CAP_MODE_BASIC:
@@ -3601,11 +3608,11 @@
pi->conf_state |= L2CAP_CONF_MODE_DONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
if (pi->conf_state & L2CAP_CONF_LOCKSTEP)
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_FS,
- sizeof(fs), (unsigned long) &fs);
+ sizeof(fs), (unsigned long) &fs, endptr - ptr);
break;
@@ -3615,7 +3622,7 @@
pi->conf_state |= L2CAP_CONF_MODE_DONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
break;
@@ -3659,11 +3666,12 @@
return ptr - data;
}
-static int l2cap_parse_amp_move_reconf_req(struct sock *sk, void *data)
+static int l2cap_parse_amp_move_reconf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
+ void *endptr = data + data_size;
void *req = pi->conf_req;
int len = pi->conf_len;
int type, hint, olen;
@@ -3750,13 +3758,13 @@
BT_DBG("mtu %d omtu %d", mtu, pi->omtu);
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu, endptr - ptr);
/* Don't allow extended transmit window to change. */
if (tx_win != pi->remote_tx_win) {
result = L2CAP_CONF_UNACCEPT;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2,
- pi->remote_tx_win);
+ pi->remote_tx_win, endptr - ptr);
}
pi->remote_mps = rfc.max_pdu_size;
@@ -3769,7 +3777,7 @@
}
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
}
if (result != L2CAP_CONF_SUCCESS)
@@ -3788,11 +3796,12 @@
return ptr - data;
}
-static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
+static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, size_t size, u16 *result)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
void *ptr = req->data;
+ void *endptr = data + size;
int type, olen;
unsigned long val;
struct l2cap_conf_rfc rfc;
@@ -3815,13 +3824,13 @@
pi->imtu = L2CAP_DEFAULT_MIN_MTU;
} else
pi->imtu = val;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu, endptr - ptr);
break;
case L2CAP_CONF_FLUSH_TO:
pi->flush_to = val;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
- 2, pi->flush_to);
+ 2, pi->flush_to, endptr - ptr);
break;
case L2CAP_CONF_RFC:
@@ -3835,7 +3844,7 @@
pi->fcs = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_CONF_EXT_WINDOW:
@@ -3845,7 +3854,7 @@
pi->tx_win = L2CAP_TX_WIN_MAX_ENHANCED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW,
- 2, pi->tx_win);
+ 2, pi->tx_win, endptr - ptr);
break;
default:
@@ -4204,7 +4213,7 @@
u8 buf[128];
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
@@ -4255,7 +4264,7 @@
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, req), req);
+ l2cap_build_conf_req(sk, req, sizeof(req)), req);
l2cap_pi(sk)->num_conf_req++;
break;
@@ -4359,9 +4368,9 @@
/* Complete config. */
if (!amp_move_reconf)
- len = l2cap_parse_conf_req(sk, rspbuf);
+ len = l2cap_parse_conf_req(sk, rspbuf, sizeof(rspbuf));
else
- len = l2cap_parse_amp_move_reconf_req(sk, rspbuf);
+ len = l2cap_parse_amp_move_reconf_req(sk, rspbuf, sizeof(rspbuf));
if (len < 0) {
l2cap_send_disconn_req(conn, sk, ECONNRESET);
@@ -4410,7 +4419,7 @@
u8 buf[64];
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
@@ -4506,7 +4515,7 @@
/* throw out any old stored conf requests */
result = L2CAP_CONF_SUCCESS;
len = l2cap_parse_conf_rsp(sk, rsp->data,
- len, req, &result);
+ len, req, sizeof(req), &result);
if (len < 0) {
l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
@@ -5306,7 +5315,7 @@
l2cap_send_cmd(pi->conn,
l2cap_get_ident(pi->conn),
L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
} else {
@@ -6870,7 +6879,7 @@
pi = l2cap_pi(sk);
l2cap_send_cmd(pi->conn, l2cap_get_ident(pi->conn), L2CAP_CONF_REQ,
- l2cap_build_amp_reconf_req(sk, buf), buf);
+ l2cap_build_amp_reconf_req(sk, buf, sizeof(buf)), buf);
return err;
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6e229d1..aa17999 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1031,7 +1031,7 @@
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
release_sock(sk);

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,411 @@
From a8149a65c1db9c3980873a32e4a96331b7a61f5b Mon Sep 17 00:00:00 2001
From: Ben Seri <ben@armis.com>
Date: Sat, 09 Sep 2017 23:15:59 +0200
Subject: [PATCH] Bluetooth: Properly check L2CAP config option output buffer length
Validate the output buffer length for L2CAP config requests and responses
to avoid overflowing the stack buffer used for building the option blocks.
Change-Id: I7a0ff0b9dd0156c0e6383214a9c86e4ec4c0d236
Cc: stable@vger.kernel.org
Signed-off-by: Ben Seri <ben@armis.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
CVE-2017-1000251
Signed-off-by: Kevin F. Haggerty <haggertk@lineageos.org>
---
diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 9c2b735..8e281b4 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -670,7 +670,7 @@
u8 l2cap_get_ident(struct l2cap_conn *conn);
void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len, void *data);
-int l2cap_build_conf_req(struct sock *sk, void *data);
+int l2cap_build_conf_req(struct sock *sk, void *data, size_t data_size);
int __l2cap_wait_ack(struct sock *sk);
struct sk_buff *l2cap_create_connless_pdu(struct sock *sk, struct msghdr *msg, size_t len);
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index a554160..aba12f2 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -926,7 +926,7 @@
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
@@ -2923,11 +2923,14 @@
return len;
}
-static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
{
struct l2cap_conf_opt *opt = *ptr;
BT_DBG("type 0x%2.2x len %d val 0x%lx", type, len, val);
+
+ if (size < L2CAP_CONF_OPT_SIZE + len)
+ return;
opt->type = type;
opt->len = len;
@@ -3312,12 +3315,13 @@
}
}
-int l2cap_build_conf_req(struct sock *sk, void *data)
+int l2cap_build_conf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = pi->mode };
void *ptr = req->data;
+ void *endptr = data + data_size;
BT_DBG("sk %p mode %d", sk, pi->mode);
@@ -3338,7 +3342,7 @@
done:
if (pi->imtu != L2CAP_DEFAULT_MTU)
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu, endptr - ptr);
switch (pi->mode) {
case L2CAP_MODE_BASIC:
@@ -3352,7 +3356,7 @@
rfc.max_pdu_size = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_MODE_ERTM:
@@ -3369,12 +3373,12 @@
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if ((pi->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW) &&
pi->extended_control) {
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2,
- pi->tx_win);
+ pi->tx_win, endptr - ptr);
}
if (pi->amp_id) {
@@ -3382,7 +3386,7 @@
struct l2cap_conf_ext_fs fs = {1, 1, 0xFFFF,
0xFFFFFFFF, 0xFFFFFFFF, 0xFFFFFFFF};
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_FS,
- sizeof(fs), (unsigned long) &fs);
+ sizeof(fs), (unsigned long) &fs, endptr - ptr);
}
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
@@ -3391,7 +3395,7 @@
if (pi->fcs == L2CAP_FCS_NONE ||
pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
pi->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs, endptr - ptr);
}
break;
@@ -3406,11 +3410,11 @@
rfc.max_pdu_size = cpu_to_le16(pi->imtu);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if ((pi->conn->feat_mask & L2CAP_FEAT_EXT_WINDOW) &&
pi->extended_control) {
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2, 0);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2, 0, endptr - ptr);
}
if (!(pi->conn->feat_mask & L2CAP_FEAT_FCS))
@@ -3419,7 +3423,7 @@
if (pi->fcs == L2CAP_FCS_NONE ||
pi->conf_state & L2CAP_CONF_NO_FCS_RECV) {
pi->fcs = L2CAP_FCS_NONE;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->fcs, endptr - ptr);
}
break;
}
@@ -3431,12 +3435,13 @@
}
-static int l2cap_build_amp_reconf_req(struct sock *sk, void *data)
+static int l2cap_build_amp_reconf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = pi->mode };
void *ptr = req->data;
+ void *endptr = data + data_size;
BT_DBG("sk %p", sk);
@@ -3457,7 +3462,7 @@
}
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if (pi->conn->feat_mask & L2CAP_FEAT_FCS) {
/* TODO assign fcs for br/edr based on socket config option */
@@ -3468,7 +3473,7 @@
else
pi->local_conf.fcs = L2CAP_FCS_CRC16;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->local_conf.fcs);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1, pi->local_conf.fcs, endptr - ptr);
pi->fcs = pi->local_conf.fcs | pi->remote_conf.fcs;
}
@@ -3478,11 +3483,12 @@
return ptr - data;
}
-static int l2cap_parse_conf_req(struct sock *sk, void *data)
+static int l2cap_parse_conf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
+ void *endptr = data + data_size;
void *req = pi->conf_req;
int len = pi->conf_len;
int type, hint, olen;
@@ -3605,7 +3611,8 @@
return -ECONNREFUSED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc,
+ endptr - ptr);
}
@@ -3624,7 +3631,7 @@
pi->omtu = mtu;
pi->conf_state |= L2CAP_CONF_MTU_DONE;
}
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu, endptr - ptr);
switch (rfc.mode) {
case L2CAP_MODE_BASIC:
@@ -3642,11 +3649,11 @@
pi->conf_state |= L2CAP_CONF_MODE_DONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
if (pi->conf_state & L2CAP_CONF_LOCKSTEP)
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_FS,
- sizeof(fs), (unsigned long) &fs);
+ sizeof(fs), (unsigned long) &fs, endptr - ptr);
break;
@@ -3656,7 +3663,7 @@
pi->conf_state |= L2CAP_CONF_MODE_DONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
break;
@@ -3696,11 +3703,12 @@
return ptr - data;
}
-static int l2cap_parse_amp_move_reconf_req(struct sock *sk, void *data)
+static int l2cap_parse_amp_move_reconf_req(struct sock *sk, void *data, size_t data_size)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
+ void *endptr = data + data_size;
void *req = pi->conf_req;
int len = pi->conf_len;
int type, hint, olen;
@@ -3787,13 +3795,13 @@
BT_DBG("mtu %d omtu %d", mtu, pi->omtu);
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->omtu, endptr - ptr);
/* Don't allow extended transmit window to change. */
if (tx_win != pi->remote_tx_win) {
result = L2CAP_CONF_UNACCEPT;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW, 2,
- pi->remote_tx_win);
+ pi->remote_tx_win, endptr - ptr);
}
pi->remote_mps = rfc.max_pdu_size;
@@ -3806,7 +3814,7 @@
}
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
}
if (result != L2CAP_CONF_SUCCESS)
@@ -3825,11 +3833,12 @@
return ptr - data;
}
-static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, u16 *result)
+static int l2cap_parse_conf_rsp(struct sock *sk, void *rsp, int len, void *data, size_t size, u16 *result)
{
struct l2cap_pinfo *pi = l2cap_pi(sk);
struct l2cap_conf_req *req = data;
void *ptr = req->data;
+ void *endptr = data + size;
int type, olen;
unsigned long val;
struct l2cap_conf_rfc rfc;
@@ -3852,13 +3861,13 @@
pi->imtu = L2CAP_DEFAULT_MIN_MTU;
} else
pi->imtu = val;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, pi->imtu, endptr - ptr);
break;
case L2CAP_CONF_FLUSH_TO:
pi->flush_to = val;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
- 2, pi->flush_to);
+ 2, pi->flush_to, endptr - ptr);
break;
case L2CAP_CONF_RFC:
@@ -3872,14 +3881,14 @@
pi->fcs = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_CONF_EXT_WINDOW:
pi->ack_win = min_t(u16, val, pi->ack_win);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EXT_WINDOW,
- 2, pi->tx_win);
+ 2, pi->tx_win, endptr - ptr);
break;
default:
@@ -4262,7 +4271,7 @@
u8 buf[128];
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
@@ -4320,7 +4329,7 @@
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, req), req);
+ l2cap_build_conf_req(sk, req, sizeof(req)), req);
l2cap_pi(sk)->num_conf_req++;
break;
@@ -4427,9 +4436,9 @@
/* Complete config. */
if (!amp_move_reconf)
- len = l2cap_parse_conf_req(sk, rspbuf);
+ len = l2cap_parse_conf_req(sk, rspbuf, sizeof(rspbuf));
else
- len = l2cap_parse_amp_move_reconf_req(sk, rspbuf);
+ len = l2cap_parse_amp_move_reconf_req(sk, rspbuf, sizeof(rspbuf));
if (len < 0) {
l2cap_send_disconn_req(conn, sk, ECONNRESET);
@@ -4478,7 +4487,7 @@
u8 buf[64];
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
@@ -4575,7 +4584,7 @@
/* throw out any old stored conf requests */
result = L2CAP_CONF_SUCCESS;
len = l2cap_parse_conf_rsp(sk, rsp->data,
- len, req, &result);
+ len, req, sizeof(req), &result);
if (len < 0) {
l2cap_send_disconn_req(conn, sk, ECONNRESET);
goto done;
@@ -5397,7 +5406,7 @@
l2cap_send_cmd(pi->conn,
l2cap_get_ident(pi->conn),
L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
}
} else {
@@ -6959,7 +6968,7 @@
pi = l2cap_pi(sk);
l2cap_send_cmd(pi->conn, l2cap_get_ident(pi->conn), L2CAP_CONF_REQ,
- l2cap_build_amp_reconf_req(sk, buf), buf);
+ l2cap_build_amp_reconf_req(sk, buf, sizeof(buf)), buf);
return err;
}
@@ -7694,7 +7703,7 @@
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf),
+ l2cap_build_conf_req(sk, buf, sizeof(buf)),
buf);
l2cap_pi(sk)->num_conf_req++;
}
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index 6da494f..baf1af7 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -1036,7 +1036,7 @@
l2cap_pi(sk)->conf_state |= L2CAP_CONF_REQ_SENT;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(sk, buf), buf);
+ l2cap_build_conf_req(sk, buf, sizeof(buf)), buf);
l2cap_pi(sk)->num_conf_req++;
release_sock(sk);

File diff suppressed because one or more lines are too long

View file

@ -0,0 +1,357 @@
From e860d2c904d1a9f38a24eb44c9f34b8f915a6ea3 Mon Sep 17 00:00:00 2001
From: Ben Seri <ben@armis.com>
Date: Sat, 9 Sep 2017 23:15:59 +0200
Subject: Bluetooth: Properly check L2CAP config option output buffer length
Validate the output buffer length for L2CAP config requests and responses
to avoid overflowing the stack buffer used for building the option blocks.
Cc: stable@vger.kernel.org
Signed-off-by: Ben Seri <ben@armis.com>
Signed-off-by: Marcel Holtmann <marcel@holtmann.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
---
net/bluetooth/l2cap_core.c | 80 +++++++++++++++++++++++++---------------------
1 file changed, 43 insertions(+), 37 deletions(-)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index 303c779..43ba91c 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -58,7 +58,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
u8 code, u8 ident, u16 dlen, void *data);
static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
void *data);
-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
@@ -1473,7 +1473,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -2987,12 +2987,15 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
return len;
}
-static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
+static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
{
struct l2cap_conf_opt *opt = *ptr;
BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
+ if (size < L2CAP_CONF_OPT_SIZE + len)
+ return;
+
opt->type = type;
opt->len = len;
@@ -3017,7 +3020,7 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
*ptr += L2CAP_CONF_OPT_SIZE + len;
}
-static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
+static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
{
struct l2cap_conf_efs efs;
@@ -3045,7 +3048,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
}
l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, size);
}
static void l2cap_ack_timeout(struct work_struct *work)
@@ -3191,11 +3194,12 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
chan->ack_win = chan->tx_win;
}
-static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
+static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
{
struct l2cap_conf_req *req = data;
struct l2cap_conf_rfc rfc = { .mode = chan->mode };
void *ptr = req->data;
+ void *endptr = data + data_size;
u16 size;
BT_DBG("chan %p", chan);
@@ -3220,7 +3224,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
done:
if (chan->imtu != L2CAP_DEFAULT_MTU)
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
switch (chan->mode) {
case L2CAP_MODE_BASIC:
@@ -3239,7 +3243,7 @@ done:
rfc.max_pdu_size = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_MODE_ERTM:
@@ -3259,21 +3263,21 @@ done:
L2CAP_DEFAULT_TX_WINDOW);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
- l2cap_add_opt_efs(&ptr, chan);
+ l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
- chan->tx_win);
+ chan->tx_win, endptr - ptr);
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
if (chan->fcs == L2CAP_FCS_NONE ||
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
chan->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
- chan->fcs);
+ chan->fcs, endptr - ptr);
}
break;
@@ -3291,17 +3295,17 @@ done:
rfc.max_pdu_size = cpu_to_le16(size);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
- l2cap_add_opt_efs(&ptr, chan);
+ l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
if (chan->fcs == L2CAP_FCS_NONE ||
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
chan->fcs = L2CAP_FCS_NONE;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
- chan->fcs);
+ chan->fcs, endptr - ptr);
}
break;
}
@@ -3312,10 +3316,11 @@ done:
return ptr - data;
}
-static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
+static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
{
struct l2cap_conf_rsp *rsp = data;
void *ptr = rsp->data;
+ void *endptr = data + data_size;
void *req = chan->conf_req;
int len = chan->conf_len;
int type, hint, olen;
@@ -3417,7 +3422,7 @@ done:
return -ECONNREFUSED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
}
if (result == L2CAP_CONF_SUCCESS) {
@@ -3430,7 +3435,7 @@ done:
chan->omtu = mtu;
set_bit(CONF_MTU_DONE, &chan->conf_state);
}
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
if (remote_efs) {
if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
@@ -3444,7 +3449,7 @@ done:
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, endptr - ptr);
} else {
/* Send PENDING Conf Rsp */
result = L2CAP_CONF_PENDING;
@@ -3477,7 +3482,7 @@ done:
set_bit(CONF_MODE_DONE, &chan->conf_state);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
chan->remote_id = efs.id;
@@ -3491,7 +3496,7 @@ done:
le32_to_cpu(efs.sdu_itime);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, endptr - ptr);
}
break;
@@ -3505,7 +3510,7 @@ done:
set_bit(CONF_MODE_DONE, &chan->conf_state);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
- (unsigned long) &rfc);
+ (unsigned long) &rfc, endptr - ptr);
break;
@@ -3527,10 +3532,11 @@ done:
}
static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
- void *data, u16 *result)
+ void *data, size_t size, u16 *result)
{
struct l2cap_conf_req *req = data;
void *ptr = req->data;
+ void *endptr = data + size;
int type, olen;
unsigned long val;
struct l2cap_conf_rfc rfc = { .mode = L2CAP_MODE_BASIC };
@@ -3548,13 +3554,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
chan->imtu = L2CAP_DEFAULT_MIN_MTU;
} else
chan->imtu = val;
- l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
+ l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
break;
case L2CAP_CONF_FLUSH_TO:
chan->flush_to = val;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
- 2, chan->flush_to);
+ 2, chan->flush_to, endptr - ptr);
break;
case L2CAP_CONF_RFC:
@@ -3568,13 +3574,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
chan->fcs = 0;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
- sizeof(rfc), (unsigned long) &rfc);
+ sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
break;
case L2CAP_CONF_EWS:
chan->ack_win = min_t(u16, val, chan->ack_win);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
- chan->tx_win);
+ chan->tx_win, endptr - ptr);
break;
case L2CAP_CONF_EFS:
@@ -3587,7 +3593,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
return -ECONNREFUSED;
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
- (unsigned long) &efs);
+ (unsigned long) &efs, endptr - ptr);
break;
case L2CAP_CONF_FCS:
@@ -3692,7 +3698,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
return;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -3900,7 +3906,7 @@ sendresp:
u8 buf[128];
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -3978,7 +3984,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
break;
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, req), req);
+ l2cap_build_conf_req(chan, req, sizeof(req)), req);
chan->num_conf_req++;
break;
@@ -4090,7 +4096,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
}
/* Complete config. */
- len = l2cap_parse_conf_req(chan, rsp);
+ len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
if (len < 0) {
l2cap_send_disconn_req(chan, ECONNRESET);
goto unlock;
@@ -4124,7 +4130,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
u8 buf[64];
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
@@ -4184,7 +4190,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
char buf[64];
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
- buf, &result);
+ buf, sizeof(buf), &result);
if (len < 0) {
l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
@@ -4214,7 +4220,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
/* throw out any old stored conf requests */
result = L2CAP_CONF_SUCCESS;
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
- req, &result);
+ req, sizeof(req), &result);
if (len < 0) {
l2cap_send_disconn_req(chan, ECONNRESET);
goto done;
@@ -4791,7 +4797,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf), buf);
+ l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
chan->num_conf_req++;
}
}
@@ -7465,7 +7471,7 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
set_bit(CONF_REQ_SENT, &chan->conf_state);
l2cap_send_cmd(conn, l2cap_get_ident(conn),
L2CAP_CONF_REQ,
- l2cap_build_conf_req(chan, buf),
+ l2cap_build_conf_req(chan, buf, sizeof(buf)),
buf);
chan->num_conf_req++;
}
--
cgit v1.1