Skip to content

Commit

Permalink
Merge pull request #12 from Flamefire/bt_sec_fix
Browse files Browse the repository at this point in the history
Fix for BleedingTooth security vulnerability
  • Loading branch information
derfelot committed Oct 15, 2020
2 parents 1bf50de + 1b14f27 commit ee7b7fb
Show file tree
Hide file tree
Showing 4 changed files with 44 additions and 9 deletions.
1 change: 0 additions & 1 deletion net/bluetooth/Kconfig
Original file line number Diff line number Diff line change
Expand Up @@ -56,7 +56,6 @@ source "net/bluetooth/hidp/Kconfig"
config BT_HS
bool "Bluetooth High Speed (HS) features"
depends on BT_BREDR
default y

config BT_LE
bool "Bluetooth Low Energy (LE) features"
Expand Down
22 changes: 21 additions & 1 deletion net/bluetooth/a2mp.c
Original file line number Diff line number Diff line change
Expand Up @@ -233,6 +233,9 @@ static int a2mp_discover_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_info_req req;

found = true;

memset(&req, 0, sizeof(req));

req.id = cl->id;
a2mp_send(mgr, A2MP_GETINFO_REQ, __next_ident(mgr),
sizeof(req), &req);
Expand Down Expand Up @@ -312,6 +315,8 @@ static int a2mp_getinfo_req(struct amp_mgr *mgr, struct sk_buff *skb,
if (!hdev || hdev->dev_type != HCI_AMP) {
struct a2mp_info_rsp rsp;

memset(&rsp, 0, sizeof(rsp));

rsp.id = req->id;
rsp.status = A2MP_STATUS_INVALID_CTRL_ID;

Expand Down Expand Up @@ -355,6 +360,8 @@ static int a2mp_getinfo_rsp(struct amp_mgr *mgr, struct sk_buff *skb,
if (!ctrl)
return -ENOMEM;

memset(&req, 0, sizeof(req));

req.id = rsp->id;
a2mp_send(mgr, A2MP_GETAMPASSOC_REQ, __next_ident(mgr), sizeof(req),
&req);
Expand Down Expand Up @@ -383,6 +390,8 @@ static int a2mp_getampassoc_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_amp_assoc_rsp rsp;
rsp.id = req->id;

memset(&rsp, 0, sizeof(rsp));

if (tmp) {
rsp.status = A2MP_STATUS_COLLISION_OCCURED;
amp_mgr_put(tmp);
Expand Down Expand Up @@ -471,7 +480,6 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,
struct a2mp_cmd *hdr)
{
struct a2mp_physlink_req *req = (void *) skb->data;

struct a2mp_physlink_rsp rsp;
struct hci_dev *hdev;
struct hci_conn *hcon;
Expand All @@ -482,6 +490,8 @@ static int a2mp_createphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,

BT_DBG("local_id %d, remote_id %d", req->local_id, req->remote_id);

memset(&rsp, 0, sizeof(rsp));

rsp.local_id = req->remote_id;
rsp.remote_id = req->local_id;

Expand Down Expand Up @@ -560,6 +570,8 @@ static int a2mp_discphyslink_req(struct amp_mgr *mgr, struct sk_buff *skb,

BT_DBG("local_id %d remote_id %d", req->local_id, req->remote_id);

memset(&rsp, 0, sizeof(rsp));

rsp.local_id = req->remote_id;
rsp.remote_id = req->local_id;
rsp.status = A2MP_STATUS_SUCCESS;
Expand Down Expand Up @@ -682,6 +694,8 @@ static int a2mp_chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
if (err) {
struct a2mp_cmd_rej rej;

memset(&rej, 0, sizeof(rej));

rej.reason = cpu_to_le16(0);
hdr = (void *) skb->data;

Expand Down Expand Up @@ -905,6 +919,8 @@ void a2mp_send_getinfo_rsp(struct hci_dev *hdev)

BT_DBG("%s mgr %p", hdev->name, mgr);

memset(&rsp, 0, sizeof(rsp));

rsp.id = hdev->id;
rsp.status = A2MP_STATUS_INVALID_CTRL_ID;

Expand Down Expand Up @@ -1002,6 +1018,8 @@ void a2mp_send_create_phy_link_rsp(struct hci_dev *hdev, u8 status)
if (!mgr)
return;

memset(&rsp, 0, sizeof(rsp));

hs_hcon = hci_conn_hash_lookup_state(hdev, AMP_LINK, BT_CONNECT);
if (!hs_hcon) {
rsp.status = A2MP_STATUS_UNABLE_START_LINK_CREATION;
Expand Down Expand Up @@ -1034,6 +1052,8 @@ void a2mp_discover_amp(struct l2cap_chan *chan)

mgr->bredr_chan = chan;

memset(&req, 0, sizeof(req));

req.mtu = cpu_to_le16(L2CAP_A2MP_DEFAULT_MTU);
req.ext_feat = 0;
a2mp_send(mgr, A2MP_DISCOVER_REQ, 1, sizeof(req), &req);
Expand Down
23 changes: 17 additions & 6 deletions net/bluetooth/hci_event.c
Original file line number Diff line number Diff line change
Expand Up @@ -1133,6 +1133,9 @@ static void store_pending_adv_report(struct hci_dev *hdev, bdaddr_t *bdaddr,
{
struct discovery_state *d = &hdev->discovery;

if (len > HCI_MAX_AD_LENGTH)
return;

bacpy(&d->last_adv_addr, bdaddr);
d->last_adv_addr_type = bdaddr_type;
d->last_adv_rssi = rssi;
Expand Down Expand Up @@ -4743,7 +4746,8 @@ static struct hci_conn *check_pending_le_conn(struct hci_dev *hdev,

static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
u8 bdaddr_type, bdaddr_t *direct_addr,
u8 direct_addr_type, s8 rssi, u8 *data, u8 len)
u8 direct_addr_type, s8 rssi, u8 *data, u8 len,
bool ext_adv)
{
struct discovery_state *d = &hdev->discovery;
struct smp_irk *irk;
Expand All @@ -4752,6 +4756,11 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
u32 flags;
u8 *ptr, real_len;

if (!ext_adv && len > HCI_MAX_AD_LENGTH) {
BT_ERR_RATELIMITED("%s: legacy adv larger than 31 bytes", hdev->name);
return;
}

/* Find the end of the data in case the report contains padded zero
* bytes at the end causing an invalid length value.
*
Expand Down Expand Up @@ -4812,7 +4821,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
*/
conn = check_pending_le_conn(hdev, bdaddr, bdaddr_type, type,
direct_addr);
if (conn && type == LE_ADV_IND) {
if (!ext_adv && conn && type == LE_ADV_IND && len <= HCI_MAX_AD_LENGTH) {
/* Store report for later inclusion by
* mgmt_device_connected
*/
Expand Down Expand Up @@ -4866,7 +4875,7 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
* event or send an immediate device found event if the data
* should not be stored for later.
*/
if (!has_pending_adv_report(hdev)) {
if (!ext_adv && !has_pending_adv_report(hdev)) {
/* If the report will trigger a SCAN_REQ store it for
* later merging.
*/
Expand Down Expand Up @@ -4901,7 +4910,8 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr,
/* If the new report will trigger a SCAN_REQ store it for
* later merging.
*/
if (type == LE_ADV_IND || type == LE_ADV_SCAN_IND) {
if (!ext_adv && (type == LE_ADV_IND ||
type == LE_ADV_SCAN_IND)) {
store_pending_adv_report(hdev, bdaddr, bdaddr_type,
rssi, flags, data, len);
return;
Expand Down Expand Up @@ -4940,7 +4950,7 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
rssi = ev->data[ev->length];
process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
ev->bdaddr_type, NULL, 0, rssi,
ev->data, ev->length);
ev->data, ev->length, false);

ptr += sizeof(*ev) + ev->length + 1;
}
Expand Down Expand Up @@ -5137,7 +5147,8 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,

process_adv_report(hdev, ev->evt_type, &ev->bdaddr,
ev->bdaddr_type, &ev->direct_addr,
ev->direct_addr_type, ev->rssi, NULL, 0);
ev->direct_addr_type, ev->rssi, NULL, 0,
false);

ptr += sizeof(*ev);
}
Expand Down
7 changes: 6 additions & 1 deletion net/bluetooth/mgmt.c
Original file line number Diff line number Diff line change
Expand Up @@ -628,7 +628,8 @@ static u32 get_supported_settings(struct hci_dev *hdev)

if (lmp_ssp_capable(hdev)) {
settings |= MGMT_SETTING_SSP;
settings |= MGMT_SETTING_HS;
if (IS_ENABLED(CONFIG_BT_HS))
settings |= MGMT_SETTING_HS;
}

if (lmp_sc_capable(hdev))
Expand Down Expand Up @@ -2430,6 +2431,10 @@ static int set_hs(struct sock *sk, struct hci_dev *hdev, void *data, u16 len)

BT_DBG("request for %s", hdev->name);

if (!IS_ENABLED(CONFIG_BT_HS))
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS,
MGMT_STATUS_NOT_SUPPORTED);

status = mgmt_bredr_support(hdev);
if (status)
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_HS, status);
Expand Down

0 comments on commit ee7b7fb

Please sign in to comment.