From 6d5d2ee63cee7025badda3b74ae2ef7ab097acfa Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Fri, 8 Jan 2016 19:28:58 +0100 Subject: Bluetooth: add LED trigger for indicating HCI is powered up Add support for LED triggers to the Bluetooth subsystem and add kernel config symbol BT_LEDS for it. For now one trigger for indicating "HCI is powered up" is supported. Signed-off-by: Heiner Kallweit Signed-off-by: Marcel Holtmann --- net/bluetooth/Kconfig | 9 ++++++ net/bluetooth/Makefile | 1 + net/bluetooth/hci_core.c | 8 +++++ net/bluetooth/leds.c | 80 ++++++++++++++++++++++++++++++++++++++++++++++++ net/bluetooth/leds.h | 18 +++++++++++ 5 files changed, 116 insertions(+) create mode 100644 net/bluetooth/leds.c create mode 100644 net/bluetooth/leds.h (limited to 'net/bluetooth') diff --git a/net/bluetooth/Kconfig b/net/bluetooth/Kconfig index 95d1a66ba03a..06c31b9a68b0 100644 --- a/net/bluetooth/Kconfig +++ b/net/bluetooth/Kconfig @@ -69,6 +69,15 @@ config BT_6LOWPAN help IPv6 compression over Bluetooth Low Energy. +config BT_LEDS + bool "Enable LED triggers" + depends on BT + depends on LEDS_CLASS + select LEDS_TRIGGERS + help + This option selects a few LED triggers for different + Bluetooth events. + config BT_SELFTEST bool "Bluetooth self testing support" depends on BT && DEBUG_KERNEL diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index 2b15ae8c1def..b3ff12eb9b6d 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile @@ -17,6 +17,7 @@ bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ bluetooth-$(CONFIG_BT_BREDR) += sco.o bluetooth-$(CONFIG_BT_HS) += a2mp.o amp.o +bluetooth-$(CONFIG_BT_LEDS) += leds.o bluetooth-$(CONFIG_BT_DEBUGFS) += hci_debugfs.o bluetooth-$(CONFIG_BT_SELFTEST) += selftest.o diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 883c821a9e78..88f1ef3589d8 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -40,6 +40,7 @@ #include "hci_request.h" #include "hci_debugfs.h" #include "smp.h" +#include "leds.h" static void hci_rx_work(struct work_struct *work); static void hci_cmd_work(struct work_struct *work); @@ -1395,6 +1396,7 @@ static int hci_dev_do_open(struct hci_dev *hdev) hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); set_bit(HCI_UP, &hdev->flags); hci_sock_dev_event(hdev, HCI_DEV_UP); + hci_leds_update_powered(hdev, true); if (!hci_dev_test_flag(hdev, HCI_SETUP) && !hci_dev_test_flag(hdev, HCI_CONFIG) && !hci_dev_test_flag(hdev, HCI_UNCONFIGURED) && @@ -1532,6 +1534,8 @@ int hci_dev_do_close(struct hci_dev *hdev) return 0; } + hci_leds_update_powered(hdev, false); + /* Flush RX and TX works */ flush_work(&hdev->tx_work); flush_work(&hdev->rx_work); @@ -3067,6 +3071,8 @@ int hci_register_dev(struct hci_dev *hdev) if (error < 0) goto err_wqueue; + hci_leds_init(hdev); + hdev->rfkill = rfkill_alloc(hdev->name, &hdev->dev, RFKILL_TYPE_BLUETOOTH, &hci_rfkill_ops, hdev); @@ -3128,6 +3134,8 @@ void hci_unregister_dev(struct hci_dev *hdev) id = hdev->id; + hci_leds_exit(hdev); + write_lock(&hci_dev_list_lock); list_del(&hdev->list); write_unlock(&hci_dev_list_lock); diff --git a/net/bluetooth/leds.c b/net/bluetooth/leds.c new file mode 100644 index 000000000000..ded7c88eaccc --- /dev/null +++ b/net/bluetooth/leds.c @@ -0,0 +1,80 @@ +/* + * Copyright 2015, Heiner Kallweit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#include +#include + +#include "leds.h" + +struct hci_basic_led_trigger { + struct led_trigger led_trigger; + struct hci_dev *hdev; +}; + +#define to_hci_basic_led_trigger(arg) container_of(arg, \ + struct hci_basic_led_trigger, led_trigger) + +void hci_leds_update_powered(struct hci_dev *hdev, bool enabled) +{ + if (hdev->power_led) + led_trigger_event(hdev->power_led, + enabled ? LED_FULL : LED_OFF); +} + +static void power_activate(struct led_classdev *led_cdev) +{ + struct hci_basic_led_trigger *htrig; + bool powered; + + htrig = to_hci_basic_led_trigger(led_cdev->trigger); + powered = test_bit(HCI_UP, &htrig->hdev->flags); + + led_trigger_event(led_cdev->trigger, powered ? LED_FULL : LED_OFF); +} + +static struct led_trigger *led_allocate_basic(struct hci_dev *hdev, + void (*activate)(struct led_classdev *led_cdev), + const char *name) +{ + struct hci_basic_led_trigger *htrig; + + htrig = devm_kzalloc(&hdev->dev, sizeof(*htrig), GFP_KERNEL); + if (!htrig) + return NULL; + + htrig->hdev = hdev; + htrig->led_trigger.activate = activate; + htrig->led_trigger.name = devm_kasprintf(&hdev->dev, GFP_KERNEL, + "%s-%s", hdev->name, + name); + if (!htrig->led_trigger.name) + goto err_alloc; + + if (led_trigger_register(&htrig->led_trigger)) + goto err_register; + + return &htrig->led_trigger; + +err_register: + devm_kfree(&hdev->dev, (void *)htrig->led_trigger.name); +err_alloc: + devm_kfree(&hdev->dev, htrig); + return NULL; +} + +void hci_leds_init(struct hci_dev *hdev) +{ + /* initialize power_led */ + hdev->power_led = led_allocate_basic(hdev, power_activate, "power"); +} + +void hci_leds_exit(struct hci_dev *hdev) +{ + if (hdev->power_led) + led_trigger_unregister(hdev->power_led); +} diff --git a/net/bluetooth/leds.h b/net/bluetooth/leds.h new file mode 100644 index 000000000000..068261a4e12c --- /dev/null +++ b/net/bluetooth/leds.h @@ -0,0 +1,18 @@ +/* + * Copyright 2015, Heiner Kallweit + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ + +#if IS_ENABLED(CONFIG_BT_LEDS) +void hci_leds_update_powered(struct hci_dev *hdev, bool enabled); +void hci_leds_init(struct hci_dev *hdev); +void hci_leds_exit(struct hci_dev *hdev); +#else +static inline void hci_leds_update_powered(struct hci_dev *hdev, + bool enabled) {} +static inline void hci_leds_init(struct hci_dev *hdev) {} +static inline void hci_leds_exit(struct hci_dev *hdev) {} +#endif -- cgit v1.2.3 From b6e402fc84a76c0238b64de497920aeeaa495026 Mon Sep 17 00:00:00 2001 From: Heiner Kallweit Date: Mon, 25 Jan 2016 20:46:21 +0100 Subject: Bluetooth: Use managed version of led_trigger_register in LED trigger Recently a managed version of led_trigger_register was introduced. Using devm_led_trigger_register allows to simplify the LED trigger code. Signed-off-by: Heiner Kallweit Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 2 -- net/bluetooth/leds.c | 8 +------- net/bluetooth/leds.h | 2 -- 3 files changed, 1 insertion(+), 11 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 88f1ef3589d8..9c0a6830ff92 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -3134,8 +3134,6 @@ void hci_unregister_dev(struct hci_dev *hdev) id = hdev->id; - hci_leds_exit(hdev); - write_lock(&hci_dev_list_lock); list_del(&hdev->list); write_unlock(&hci_dev_list_lock); diff --git a/net/bluetooth/leds.c b/net/bluetooth/leds.c index ded7c88eaccc..8319c8440c89 100644 --- a/net/bluetooth/leds.c +++ b/net/bluetooth/leds.c @@ -55,7 +55,7 @@ static struct led_trigger *led_allocate_basic(struct hci_dev *hdev, if (!htrig->led_trigger.name) goto err_alloc; - if (led_trigger_register(&htrig->led_trigger)) + if (devm_led_trigger_register(&hdev->dev, &htrig->led_trigger)) goto err_register; return &htrig->led_trigger; @@ -72,9 +72,3 @@ void hci_leds_init(struct hci_dev *hdev) /* initialize power_led */ hdev->power_led = led_allocate_basic(hdev, power_activate, "power"); } - -void hci_leds_exit(struct hci_dev *hdev) -{ - if (hdev->power_led) - led_trigger_unregister(hdev->power_led); -} diff --git a/net/bluetooth/leds.h b/net/bluetooth/leds.h index 068261a4e12c..a9c4d6ea01cf 100644 --- a/net/bluetooth/leds.h +++ b/net/bluetooth/leds.h @@ -9,10 +9,8 @@ #if IS_ENABLED(CONFIG_BT_LEDS) void hci_leds_update_powered(struct hci_dev *hdev, bool enabled); void hci_leds_init(struct hci_dev *hdev); -void hci_leds_exit(struct hci_dev *hdev); #else static inline void hci_leds_update_powered(struct hci_dev *hdev, bool enabled) {} static inline void hci_leds_init(struct hci_dev *hdev) {} -static inline void hci_leds_exit(struct hci_dev *hdev) {} #endif -- cgit v1.2.3 From d82142a8b1338e6a4339920863423379c27b0b16 Mon Sep 17 00:00:00 2001 From: Wei-Ning Huang Date: Mon, 15 Feb 2016 17:09:51 +0800 Subject: Bluetooth: hci_core: cancel power off delayed work properly When the HCI_AUTO_OFF flag is cleared, the power_off delayed work need to be cancel or HCI will be powered off even if it's managed. Signed-off-by: Wei-Ning Huang Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_core.c | 1 + 1 file changed, 1 insertion(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 9c0a6830ff92..2713fc86e85a 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -2021,6 +2021,7 @@ static void hci_power_on(struct work_struct *work) if (test_bit(HCI_UP, &hdev->flags) && hci_dev_test_flag(hdev, HCI_MGMT) && hci_dev_test_and_clear_flag(hdev, HCI_AUTO_OFF)) { + cancel_delayed_work(&hdev->power_off); hci_req_sync_lock(hdev); err = __hci_req_hci_power_on(hdev); hci_req_sync_unlock(hdev); -- cgit v1.2.3 From eec7a01dc8366f7e43fc0417f4aee70eaeaca9a9 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 9 Mar 2016 17:30:32 +0200 Subject: Bluetooth: Move memset closer to where it's needed Minor fix to not do the memset until the variable it clears is actually used. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_conn.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 32575b49f4a0..7264025dc781 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -726,14 +726,14 @@ static void hci_req_add_le_create_conn(struct hci_request *req, struct hci_dev *hdev = conn->hdev; u8 own_addr_type; - memset(&cp, 0, sizeof(cp)); - /* Update random address, but set require_privacy to false so * that we never connect with an non-resolvable address. */ if (hci_update_random_address(req, false, &own_addr_type)) return; + memset(&cp, 0, sizeof(cp)); + /* Set window to be the same value as the interval to enable * continuous scanning. */ -- cgit v1.2.3 From d43efbd0d545f476be0bbef30cbe18234f8a9631 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 9 Mar 2016 17:30:33 +0200 Subject: Bluetooth: Fix adding discoverable to adv instance flags When lookup up the advertising instance flags for the default advertising instance (0) the discoverable flag should be filled in based on the HCI_DISCOVERABLE flag. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_request.c | 3 +++ 1 file changed, 3 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index c78ee2dc9323..77be344efd18 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -866,6 +866,9 @@ static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) flags |= MGMT_ADV_FLAG_CONNECTABLE; + if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) + flags |= MGMT_ADV_FLAG_DISCOV; + return flags; } -- cgit v1.2.3 From 82a37adeedd38880940e2772ec1ae27a09353e5a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 9 Mar 2016 17:30:34 +0200 Subject: Bluetooth: Add support for limited privacy mode Introduce a limited privacy mode indicated by value 0x02 to the mgmt Set Privacy command. With value 0x02 the kernel will use privacy mode with a resolvable private address. In case the controller is bondable and discoverable the identity address will be used. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- include/net/bluetooth/hci.h | 1 + net/bluetooth/hci_conn.c | 13 ++++++++++-- net/bluetooth/hci_request.c | 51 +++++++++++++++++++++++++++++++++++++++------ net/bluetooth/hci_request.h | 2 +- net/bluetooth/mgmt.c | 20 ++++++++++++++++-- 5 files changed, 76 insertions(+), 11 deletions(-) (limited to 'net/bluetooth') diff --git a/include/net/bluetooth/hci.h b/include/net/bluetooth/hci.h index 339ea57be423..5d38d980b89d 100644 --- a/include/net/bluetooth/hci.h +++ b/include/net/bluetooth/hci.h @@ -233,6 +233,7 @@ enum { HCI_SC_ENABLED, HCI_SC_ONLY, HCI_PRIVACY, + HCI_LIMITED_PRIVACY, HCI_RPA_EXPIRED, HCI_RPA_RESOLVING, HCI_HS_ENABLED, diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index 7264025dc781..bf9f8a801a2e 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -719,6 +719,13 @@ done: hci_dev_unlock(hdev); } +static bool conn_use_rpa(struct hci_conn *conn) +{ + struct hci_dev *hdev = conn->hdev; + + return hci_dev_test_flag(hdev, HCI_PRIVACY); +} + static void hci_req_add_le_create_conn(struct hci_request *req, struct hci_conn *conn) { @@ -729,7 +736,8 @@ static void hci_req_add_le_create_conn(struct hci_request *req, /* Update random address, but set require_privacy to false so * that we never connect with an non-resolvable address. */ - if (hci_update_random_address(req, false, &own_addr_type)) + if (hci_update_random_address(req, false, conn_use_rpa(conn), + &own_addr_type)) return; memset(&cp, 0, sizeof(cp)); @@ -774,7 +782,8 @@ static void hci_req_directed_advertising(struct hci_request *req, /* Set require_privacy to false so that the remote device has a * chance of identifying us. */ - if (hci_update_random_address(req, false, &own_addr_type) < 0) + if (hci_update_random_address(req, false, conn_use_rpa(conn), + &own_addr_type) < 0) return; memset(&cp, 0, sizeof(cp)); diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 77be344efd18..95a545ca9dbc 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -771,6 +771,11 @@ static u8 update_white_list(struct hci_request *req) return 0x01; } +static bool scan_use_rpa(struct hci_dev *hdev) +{ + return hci_dev_test_flag(hdev, HCI_PRIVACY); +} + void hci_req_add_le_passive_scan(struct hci_request *req) { struct hci_cp_le_set_scan_param param_cp; @@ -785,7 +790,8 @@ void hci_req_add_le_passive_scan(struct hci_request *req) * advertising with our address will be correctly reported * by the controller. */ - if (hci_update_random_address(req, false, &own_addr_type)) + if (hci_update_random_address(req, false, scan_use_rpa(hdev), + &own_addr_type)) return; /* Adding or removing entries from the white list must @@ -881,6 +887,29 @@ static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) return adv_instance->flags; } +static bool adv_use_rpa(struct hci_dev *hdev, uint32_t flags) +{ + /* If privacy is not enabled don't use RPA */ + if (!hci_dev_test_flag(hdev, HCI_PRIVACY)) + return false; + + /* If basic privacy mode is enabled use RPA */ + if (!hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) + return true; + + /* If limited privacy mode is enabled don't use RPA if we're + * both discoverable and bondable. + */ + if ((flags & MGMT_ADV_FLAG_DISCOV) && + hci_dev_test_flag(hdev, HCI_BONDABLE)) + return false; + + /* We're neither bondable nor discoverable in the limited + * privacy mode, therefore use RPA. + */ + return true; +} + void __hci_req_enable_advertising(struct hci_request *req) { struct hci_dev *hdev = req->hdev; @@ -914,7 +943,9 @@ void __hci_req_enable_advertising(struct hci_request *req) * advertising is used. In that case it is fine to use a * non-resolvable private address. */ - if (hci_update_random_address(req, !connectable, &own_addr_type) < 0) + if (hci_update_random_address(req, !connectable, + adv_use_rpa(hdev, flags), + &own_addr_type) < 0) return; memset(&cp, 0, sizeof(cp)); @@ -1328,7 +1359,7 @@ static void set_random_addr(struct hci_request *req, bdaddr_t *rpa) } int hci_update_random_address(struct hci_request *req, bool require_privacy, - u8 *own_addr_type) + bool use_rpa, u8 *own_addr_type) { struct hci_dev *hdev = req->hdev; int err; @@ -1337,7 +1368,7 @@ int hci_update_random_address(struct hci_request *req, bool require_privacy, * current RPA has expired or there is something else than * the current RPA in use, then generate a new one. */ - if (hci_dev_test_flag(hdev, HCI_PRIVACY)) { + if (use_rpa) { int to; *own_addr_type = ADDR_LE_DEV_RANDOM; @@ -1599,9 +1630,16 @@ static int discoverable_update(struct hci_request *req, unsigned long opt) /* Advertising instances don't use the global discoverable setting, so * only update AD if advertising was enabled using Set Advertising. */ - if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) + if (hci_dev_test_flag(hdev, HCI_ADVERTISING)) { __hci_req_update_adv_data(req, 0x00); + /* Discoverable mode affects the local advertising + * address in limited privacy mode. + */ + if (hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) + __hci_req_enable_advertising(req); + } + hci_dev_unlock(hdev); return 0; @@ -1944,7 +1982,8 @@ static int active_scan(struct hci_request *req, unsigned long opt) * address (when privacy feature has been enabled) or non-resolvable * private address. */ - err = hci_update_random_address(req, true, &own_addr_type); + err = hci_update_random_address(req, true, scan_use_rpa(hdev), + &own_addr_type); if (err < 0) own_addr_type = ADDR_LE_DEV_PUBLIC; diff --git a/net/bluetooth/hci_request.h b/net/bluetooth/hci_request.h index 64ff8c040d50..b2d044bdc732 100644 --- a/net/bluetooth/hci_request.h +++ b/net/bluetooth/hci_request.h @@ -89,7 +89,7 @@ static inline void hci_req_update_scan(struct hci_dev *hdev) void __hci_req_update_scan(struct hci_request *req); int hci_update_random_address(struct hci_request *req, bool require_privacy, - u8 *own_addr_type); + bool use_rpa, u8 *own_addr_type); int hci_abort_conn(struct hci_conn *conn, u8 reason); void __hci_abort_conn(struct hci_request *req, struct hci_conn *conn, diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 5a5089cb6570..2ca355519d79 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -1382,8 +1382,19 @@ static int set_bondable(struct sock *sk, struct hci_dev *hdev, void *data, if (err < 0) goto unlock; - if (changed) + if (changed) { + /* In limited privacy mode the change of bondable mode + * may affect the local advertising address. + */ + if (hdev_is_powered(hdev) && + hci_dev_test_flag(hdev, HCI_ADVERTISING) && + hci_dev_test_flag(hdev, HCI_DISCOVERABLE) && + hci_dev_test_flag(hdev, HCI_LIMITED_PRIVACY)) + queue_work(hdev->req_workqueue, + &hdev->discoverable_update); + err = new_settings(hdev, sk); + } unlock: hci_dev_unlock(hdev); @@ -4423,7 +4434,7 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, MGMT_STATUS_NOT_SUPPORTED); - if (cp->privacy != 0x00 && cp->privacy != 0x01) + if (cp->privacy != 0x00 && cp->privacy != 0x01 && cp->privacy != 0x02) return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_PRIVACY, MGMT_STATUS_INVALID_PARAMS); @@ -4442,10 +4453,15 @@ static int set_privacy(struct sock *sk, struct hci_dev *hdev, void *cp_data, changed = !hci_dev_test_and_set_flag(hdev, HCI_PRIVACY); memcpy(hdev->irk, cp->irk, sizeof(hdev->irk)); hci_dev_set_flag(hdev, HCI_RPA_EXPIRED); + if (cp->privacy == 0x02) + hci_dev_set_flag(hdev, HCI_LIMITED_PRIVACY); + else + hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY); } else { changed = hci_dev_test_and_clear_flag(hdev, HCI_PRIVACY); memset(hdev->irk, 0, sizeof(hdev->irk)); hci_dev_clear_flag(hdev, HCI_RPA_EXPIRED); + hci_dev_clear_flag(hdev, HCI_LIMITED_PRIVACY); } err = send_settings_rsp(sk, MGMT_OP_SET_PRIVACY, hdev); -- cgit v1.2.3 From 9c176cec42e4b0deeed901fc363bf4235c5ca96a Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Wed, 9 Mar 2016 17:52:24 +0200 Subject: Bluetooth: Increment management interface revision Increment the mgmt revision due to the recently added limited privacy mode. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/mgmt.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 2ca355519d79..c856fb65812c 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -38,7 +38,7 @@ #include "mgmt_util.h" #define MGMT_VERSION 1 -#define MGMT_REVISION 11 +#define MGMT_REVISION 12 static const u16 mgmt_commands[] = { MGMT_OP_READ_INDEX_LIST, -- cgit v1.2.3 From 6a19cc8c892b113fb84947207346f783de76dbd1 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 11 Mar 2016 09:56:32 +0200 Subject: Bluetooth: Fix setting correct flags in AD A recent change added MGMT_ADV_FLAG_DISCOV to the flags returned by get_adv_instance_flags(), however failed to take into account limited discoverable mode. This patch fixes the issue by setting the correct discoverability flag in the AD data. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann --- net/bluetooth/hci_request.c | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) (limited to 'net/bluetooth') diff --git a/net/bluetooth/hci_request.c b/net/bluetooth/hci_request.c index 95a545ca9dbc..6e125d76df0d 100644 --- a/net/bluetooth/hci_request.c +++ b/net/bluetooth/hci_request.c @@ -872,7 +872,9 @@ static u32 get_adv_instance_flags(struct hci_dev *hdev, u8 instance) if (hci_dev_test_flag(hdev, HCI_ADVERTISING_CONNECTABLE)) flags |= MGMT_ADV_FLAG_CONNECTABLE; - if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) + if (hci_dev_test_flag(hdev, HCI_LIMITED_DISCOVERABLE)) + flags |= MGMT_ADV_FLAG_LIMITED_DISCOV; + else if (hci_dev_test_flag(hdev, HCI_DISCOVERABLE)) flags |= MGMT_ADV_FLAG_DISCOV; return flags; -- cgit v1.2.3 From 6a0e78072c2ae7b20b14e0249d8108441ea928d2 Mon Sep 17 00:00:00 2001 From: Johan Hedberg Date: Fri, 11 Mar 2016 09:56:33 +0200 Subject: Bluetooth: Fix potential buffer overflow with Add Advertising The Add Advertising command handler does the appropriate checks for the AD and Scan Response data, however fails to take into account the general length of the mgmt command itself, which could lead to potential buffer overflows. This patch adds the necessary check that the mgmt command length is consistent with the given ad and scan_rsp lengths. Signed-off-by: Johan Hedberg Signed-off-by: Marcel Holtmann Cc: stable@vger.kernel.org --- net/bluetooth/mgmt.c | 4 ++++ 1 file changed, 4 insertions(+) (limited to 'net/bluetooth') diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index c856fb65812c..9e4b931588cf 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -5995,6 +5995,10 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, MGMT_STATUS_INVALID_PARAMS); + if (data_len != sizeof(*cp) + cp->adv_data_len + cp->scan_rsp_len) + return mgmt_cmd_status(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, + MGMT_STATUS_INVALID_PARAMS); + flags = __le32_to_cpu(cp->flags); timeout = __le16_to_cpu(cp->timeout); duration = __le16_to_cpu(cp->duration); -- cgit v1.2.3