Skip to content
This repository was archived by the owner on Jul 3, 2018. It is now read-only.

Commit 92430f1

Browse files
benseri87akhilnarang
authored andcommitted
Bluetooth: Properly check L2CAP config option output buffer length
commit e860d2c904d1a9f38a24eb44c9f34b8f915a6ea3 upstream. Validate the output buffer length for L2CAP config requests and responses to avoid overflowing the stack buffer used for building the option blocks. Signed-off-by: Ben Seri <[email protected]> Signed-off-by: Marcel Holtmann <[email protected]> Signed-off-by: Linus Torvalds <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> Change-Id: I7a0ff0b9dd0156c0e6383214a9c86e4ec4c0d236
1 parent 7be24d4 commit 92430f1

File tree

1 file changed

+43
-37
lines changed

1 file changed

+43
-37
lines changed

net/bluetooth/l2cap_core.c

Lines changed: 43 additions & 37 deletions
Original file line numberDiff line numberDiff line change
@@ -52,7 +52,7 @@ static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn,
5252
u8 code, u8 ident, u16 dlen, void *data);
5353
static void l2cap_send_cmd(struct l2cap_conn *conn, u8 ident, u8 code, u16 len,
5454
void *data);
55-
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data);
55+
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size);
5656
static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err);
5757

5858
static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control,
@@ -1298,7 +1298,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn)
12981298

12991299
set_bit(CONF_REQ_SENT, &chan->conf_state);
13001300
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
1301-
l2cap_build_conf_req(chan, buf), buf);
1301+
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
13021302
chan->num_conf_req++;
13031303
}
13041304

@@ -2992,12 +2992,15 @@ static inline int l2cap_get_conf_opt(void **ptr, int *type, int *olen,
29922992
return len;
29932993
}
29942994

2995-
static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
2995+
static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val, size_t size)
29962996
{
29972997
struct l2cap_conf_opt *opt = *ptr;
29982998

29992999
BT_DBG("type 0x%2.2x len %u val 0x%lx", type, len, val);
30003000

3001+
if (size < L2CAP_CONF_OPT_SIZE + len)
3002+
return;
3003+
30013004
opt->type = type;
30023005
opt->len = len;
30033006

@@ -3022,7 +3025,7 @@ static void l2cap_add_conf_opt(void **ptr, u8 type, u8 len, unsigned long val)
30223025
*ptr += L2CAP_CONF_OPT_SIZE + len;
30233026
}
30243027

3025-
static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
3028+
static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan, size_t size)
30263029
{
30273030
struct l2cap_conf_efs efs;
30283031

@@ -3050,7 +3053,7 @@ static void l2cap_add_opt_efs(void **ptr, struct l2cap_chan *chan)
30503053
}
30513054

30523055
l2cap_add_conf_opt(ptr, L2CAP_CONF_EFS, sizeof(efs),
3053-
(unsigned long) &efs);
3056+
(unsigned long) &efs, size);
30543057
}
30553058

30563059
static void l2cap_ack_timeout(struct work_struct *work)
@@ -3194,11 +3197,12 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
31943197
chan->ack_win = chan->tx_win;
31953198
}
31963199

3197-
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
3200+
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
31983201
{
31993202
struct l2cap_conf_req *req = data;
32003203
struct l2cap_conf_rfc rfc = { .mode = chan->mode };
32013204
void *ptr = req->data;
3205+
void *endptr = data + data_size;
32023206
u16 size;
32033207

32043208
BT_DBG("chan %pK", chan);
@@ -3223,7 +3227,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
32233227

32243228
done:
32253229
if (chan->imtu != L2CAP_DEFAULT_MTU)
3226-
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
3230+
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
32273231

32283232
switch (chan->mode) {
32293233
case L2CAP_MODE_BASIC:
@@ -3239,7 +3243,7 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
32393243
rfc.max_pdu_size = 0;
32403244

32413245
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3242-
(unsigned long) &rfc);
3246+
(unsigned long) &rfc, endptr - ptr);
32433247
break;
32443248

32453249
case L2CAP_MODE_ERTM:
@@ -3259,21 +3263,21 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
32593263
L2CAP_DEFAULT_TX_WINDOW);
32603264

32613265
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3262-
(unsigned long) &rfc);
3266+
(unsigned long) &rfc, endptr - ptr);
32633267

32643268
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3265-
l2cap_add_opt_efs(&ptr, chan);
3269+
l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
32663270

32673271
if (test_bit(FLAG_EXT_CTRL, &chan->flags))
32683272
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3269-
chan->tx_win);
3273+
chan->tx_win, endptr - ptr);
32703274

32713275
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
32723276
if (chan->fcs == L2CAP_FCS_NONE ||
32733277
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
32743278
chan->fcs = L2CAP_FCS_NONE;
32753279
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3276-
chan->fcs);
3280+
chan->fcs, endptr - ptr);
32773281
}
32783282
break;
32793283

@@ -3291,17 +3295,17 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
32913295
rfc.max_pdu_size = cpu_to_le16(size);
32923296

32933297
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3294-
(unsigned long) &rfc);
3298+
(unsigned long) &rfc, endptr - ptr);
32953299

32963300
if (test_bit(FLAG_EFS_ENABLE, &chan->flags))
3297-
l2cap_add_opt_efs(&ptr, chan);
3301+
l2cap_add_opt_efs(&ptr, chan, endptr - ptr);
32983302

32993303
if (chan->conn->feat_mask & L2CAP_FEAT_FCS)
33003304
if (chan->fcs == L2CAP_FCS_NONE ||
33013305
test_bit(CONF_RECV_NO_FCS, &chan->conf_state)) {
33023306
chan->fcs = L2CAP_FCS_NONE;
33033307
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FCS, 1,
3304-
chan->fcs);
3308+
chan->fcs, endptr - ptr);
33053309
}
33063310
break;
33073311
}
@@ -3312,10 +3316,11 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data)
33123316
return ptr - data;
33133317
}
33143318

3315-
static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
3319+
static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
33163320
{
33173321
struct l2cap_conf_rsp *rsp = data;
33183322
void *ptr = rsp->data;
3323+
void *endptr = data + data_size;
33193324
void *req = chan->conf_req;
33203325
int len = chan->conf_len;
33213326
int type, hint, olen;
@@ -3417,7 +3422,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34173422
return -ECONNREFUSED;
34183423

34193424
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3420-
(unsigned long) &rfc);
3425+
(unsigned long) &rfc, endptr - ptr);
34213426
}
34223427

34233428
if (result == L2CAP_CONF_SUCCESS) {
@@ -3430,7 +3435,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34303435
chan->omtu = mtu;
34313436
set_bit(CONF_MTU_DONE, &chan->conf_state);
34323437
}
3433-
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu);
3438+
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->omtu, endptr - ptr);
34343439

34353440
if (remote_efs) {
34363441
if (chan->local_stype != L2CAP_SERV_NOTRAFIC &&
@@ -3444,7 +3449,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34443449

34453450
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
34463451
sizeof(efs),
3447-
(unsigned long) &efs);
3452+
(unsigned long) &efs, endptr - ptr);
34483453
} else {
34493454
/* Send PENDING Conf Rsp */
34503455
result = L2CAP_CONF_PENDING;
@@ -3477,7 +3482,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34773482
set_bit(CONF_MODE_DONE, &chan->conf_state);
34783483

34793484
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3480-
sizeof(rfc), (unsigned long) &rfc);
3485+
sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
34813486

34823487
if (test_bit(FLAG_EFS_ENABLE, &chan->flags)) {
34833488
chan->remote_id = efs.id;
@@ -3491,7 +3496,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
34913496
le32_to_cpu(efs.sdu_itime);
34923497
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS,
34933498
sizeof(efs),
3494-
(unsigned long) &efs);
3499+
(unsigned long) &efs, endptr - ptr);
34953500
}
34963501
break;
34973502

@@ -3505,7 +3510,7 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
35053510
set_bit(CONF_MODE_DONE, &chan->conf_state);
35063511

35073512
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC, sizeof(rfc),
3508-
(unsigned long) &rfc);
3513+
(unsigned long) &rfc, endptr - ptr);
35093514

35103515
break;
35113516

@@ -3527,10 +3532,11 @@ static int l2cap_parse_conf_req(struct l2cap_chan *chan, void *data)
35273532
}
35283533

35293534
static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
3530-
void *data, u16 *result)
3535+
void *data, size_t size, u16 *result)
35313536
{
35323537
struct l2cap_conf_req *req = data;
35333538
void *ptr = req->data;
3539+
void *endptr = data + size;
35343540
int type, olen;
35353541
unsigned long val;
35363542
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,
35483554
chan->imtu = L2CAP_DEFAULT_MIN_MTU;
35493555
} else
35503556
chan->imtu = val;
3551-
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu);
3557+
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
35523558
break;
35533559

35543560
case L2CAP_CONF_FLUSH_TO:
35553561
chan->flush_to = val;
35563562
l2cap_add_conf_opt(&ptr, L2CAP_CONF_FLUSH_TO,
3557-
2, chan->flush_to);
3563+
2, chan->flush_to, endptr - ptr);
35583564
break;
35593565

35603566
case L2CAP_CONF_RFC:
@@ -3568,13 +3574,13 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
35683574
chan->fcs = 0;
35693575

35703576
l2cap_add_conf_opt(&ptr, L2CAP_CONF_RFC,
3571-
sizeof(rfc), (unsigned long) &rfc);
3577+
sizeof(rfc), (unsigned long) &rfc, endptr - ptr);
35723578
break;
35733579

35743580
case L2CAP_CONF_EWS:
35753581
chan->ack_win = min_t(u16, val, chan->ack_win);
35763582
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EWS, 2,
3577-
chan->tx_win);
3583+
chan->tx_win, endptr - ptr);
35783584
break;
35793585

35803586
case L2CAP_CONF_EFS:
@@ -3587,7 +3593,7 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len,
35873593
return -ECONNREFUSED;
35883594

35893595
l2cap_add_conf_opt(&ptr, L2CAP_CONF_EFS, sizeof(efs),
3590-
(unsigned long) &efs);
3596+
(unsigned long) &efs, endptr - ptr);
35913597
break;
35923598

35933599
case L2CAP_CONF_FCS:
@@ -3677,7 +3683,7 @@ void __l2cap_connect_rsp_defer(struct l2cap_chan *chan)
36773683
return;
36783684

36793685
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3680-
l2cap_build_conf_req(chan, buf), buf);
3686+
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
36813687
chan->num_conf_req++;
36823688
}
36833689

@@ -3885,7 +3891,7 @@ static struct l2cap_chan *l2cap_connect(struct l2cap_conn *conn,
38853891
u8 buf[128];
38863892
set_bit(CONF_REQ_SENT, &chan->conf_state);
38873893
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3888-
l2cap_build_conf_req(chan, buf), buf);
3894+
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
38893895
chan->num_conf_req++;
38903896
}
38913897

@@ -3965,7 +3971,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn,
39653971
break;
39663972

39673973
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
3968-
l2cap_build_conf_req(chan, req), req);
3974+
l2cap_build_conf_req(chan, req, sizeof(req)), req);
39693975
chan->num_conf_req++;
39703976
break;
39713977

@@ -4069,7 +4075,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
40694075
}
40704076

40714077
/* Complete config. */
4072-
len = l2cap_parse_conf_req(chan, rsp);
4078+
len = l2cap_parse_conf_req(chan, rsp, sizeof(rsp));
40734079
if (len < 0) {
40744080
l2cap_send_disconn_req(chan, ECONNRESET);
40754081
goto unlock;
@@ -4103,7 +4109,7 @@ static inline int l2cap_config_req(struct l2cap_conn *conn,
41034109
if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) {
41044110
u8 buf[64];
41054111
l2cap_send_cmd(conn, l2cap_get_ident(conn), L2CAP_CONF_REQ,
4106-
l2cap_build_conf_req(chan, buf), buf);
4112+
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
41074113
chan->num_conf_req++;
41084114
}
41094115

@@ -4163,7 +4169,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
41634169
char buf[64];
41644170

41654171
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4166-
buf, &result);
4172+
buf, sizeof(buf), &result);
41674173
if (len < 0) {
41684174
l2cap_send_disconn_req(chan, ECONNRESET);
41694175
goto done;
@@ -4193,7 +4199,7 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn,
41934199
/* throw out any old stored conf requests */
41944200
result = L2CAP_CONF_SUCCESS;
41954201
len = l2cap_parse_conf_rsp(chan, rsp->data, len,
4196-
req, &result);
4202+
req, sizeof(req), &result);
41974203
if (len < 0) {
41984204
l2cap_send_disconn_req(chan, ECONNRESET);
41994205
goto done;
@@ -4776,7 +4782,7 @@ static void l2cap_do_create(struct l2cap_chan *chan, int result,
47764782
set_bit(CONF_REQ_SENT, &chan->conf_state);
47774783
l2cap_send_cmd(chan->conn, l2cap_get_ident(chan->conn),
47784784
L2CAP_CONF_REQ,
4779-
l2cap_build_conf_req(chan, buf), buf);
4785+
l2cap_build_conf_req(chan, buf, sizeof(buf)), buf);
47804786
chan->num_conf_req++;
47814787
}
47824788
}
@@ -6662,7 +6668,7 @@ int l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt)
66626668
set_bit(CONF_REQ_SENT, &chan->conf_state);
66636669
l2cap_send_cmd(conn, l2cap_get_ident(conn),
66646670
L2CAP_CONF_REQ,
6665-
l2cap_build_conf_req(chan, buf),
6671+
l2cap_build_conf_req(chan, buf, sizeof(buf)),
66666672
buf);
66676673
chan->num_conf_req++;
66686674
}

0 commit comments

Comments
 (0)