Commit c4c57b97 authored by David S. Miller's avatar David S. Miller

Merge branch 'for-upstream' of...

Merge branch 'for-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next

Johan Hedberg says:

====================
pull request: bluetooth-next 2020-01-26

Here's (probably) the last bluetooth-next pull request for the 5.6 kernel.

 - Initial pieces of Bluetooth 5.2 Isochronous Channels support
 - mgmt: Various cleanups and a new Set Blocked Keys command
 - btusb: Added support for 04ca:3021 QCA_ROME device
 - hci_qca: Multiple fixes & cleanups
 - hci_bcm: Fixes & improved device tree support
 - Fixed attempts to create duplicate debugfs entries

Please let me know if there are any issues pulling. Thanks.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 5a44c71c 11eb85ec
......@@ -11,6 +11,7 @@ Required properties:
- compatible: should contain one of the following:
* "brcm,bcm20702a1"
* "brcm,bcm4329-bt"
* "brcm,bcm4330-bt"
* "brcm,bcm43438-bt"
* "brcm,bcm4345c5"
......@@ -22,7 +23,9 @@ Optional properties:
- max-speed: see Documentation/devicetree/bindings/serial/slave-device.txt
- shutdown-gpios: GPIO specifier, used to enable the BT module
- device-wakeup-gpios: GPIO specifier, used to wakeup the controller
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor
- host-wakeup-gpios: GPIO specifier, used to wakeup the host processor.
deprecated, replaced by interrupts and
"host-wakeup" interrupt-names
- clocks: 1 or 2 clocks as defined in clock-names below, in that order
- clock-names: names for clock inputs, matching the clocks given
- "extclk": deprecated, replaced by "txco"
......@@ -36,7 +39,8 @@ Optional properties:
- pcm-frame-type: short, long
- pcm-sync-mode: slave, master
- pcm-clock-mode: slave, master
- interrupts: must be one, used to wakeup the host processor
- interrupt-names: must be "host-wakeup"
Example:
......
......@@ -36,6 +36,7 @@ int btbcm_check_bdaddr(struct hci_dev *hdev)
HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
bt_dev_err(hdev, "BCM: Reading device address failed (%d)", err);
return err;
}
......@@ -223,6 +224,7 @@ static int btbcm_reset(struct hci_dev *hdev)
skb = __hci_cmd_sync(hdev, HCI_OP_RESET, 0, NULL, HCI_INIT_TIMEOUT);
if (IS_ERR(skb)) {
int err = PTR_ERR(skb);
bt_dev_err(hdev, "BCM: Reset failed (%d)", err);
return err;
}
......
......@@ -78,13 +78,13 @@ static inline int btbcm_set_bdaddr(struct hci_dev *hdev, const bdaddr_t *bdaddr)
return -EOPNOTSUPP;
}
int btbcm_read_pcm_int_params(struct hci_dev *hdev,
static inline int btbcm_read_pcm_int_params(struct hci_dev *hdev,
struct bcm_set_pcm_int_params *params)
{
return -EOPNOTSUPP;
}
int btbcm_write_pcm_int_params(struct hci_dev *hdev,
static inline int btbcm_write_pcm_int_params(struct hci_dev *hdev,
const struct bcm_set_pcm_int_params *params)
{
return -EOPNOTSUPP;
......
......@@ -370,11 +370,11 @@ static int rtlbt_parse_firmware(struct hci_dev *hdev,
* the end.
*/
len = patch_length;
buf = kmemdup(btrtl_dev->fw_data + patch_offset, patch_length,
GFP_KERNEL);
buf = kvmalloc(patch_length, GFP_KERNEL);
if (!buf)
return -ENOMEM;
memcpy(buf, btrtl_dev->fw_data + patch_offset, patch_length - 4);
memcpy(buf + patch_length - 4, &epatch_info->fw_version, 4);
*_buf = buf;
......@@ -460,8 +460,10 @@ static int rtl_load_file(struct hci_dev *hdev, const char *name, u8 **buff)
if (ret < 0)
return ret;
ret = fw->size;
*buff = kmemdup(fw->data, ret, GFP_KERNEL);
if (!*buff)
*buff = kvmalloc(fw->size, GFP_KERNEL);
if (*buff)
memcpy(*buff, fw->data, ret);
else
ret = -ENOMEM;
release_firmware(fw);
......@@ -499,14 +501,14 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev,
goto out;
if (btrtl_dev->cfg_len > 0) {
tbuff = kzalloc(ret + btrtl_dev->cfg_len, GFP_KERNEL);
tbuff = kvzalloc(ret + btrtl_dev->cfg_len, GFP_KERNEL);
if (!tbuff) {
ret = -ENOMEM;
goto out;
}
memcpy(tbuff, fw_data, ret);
kfree(fw_data);
kvfree(fw_data);
memcpy(tbuff + ret, btrtl_dev->cfg_data, btrtl_dev->cfg_len);
ret += btrtl_dev->cfg_len;
......@@ -519,14 +521,14 @@ static int btrtl_setup_rtl8723b(struct hci_dev *hdev,
ret = rtl_download_firmware(hdev, fw_data, ret);
out:
kfree(fw_data);
kvfree(fw_data);
return ret;
}
void btrtl_free(struct btrtl_device_info *btrtl_dev)
{
kfree(btrtl_dev->fw_data);
kfree(btrtl_dev->cfg_data);
kvfree(btrtl_dev->fw_data);
kvfree(btrtl_dev->cfg_data);
kfree(btrtl_dev);
}
EXPORT_SYMBOL_GPL(btrtl_free);
......
......@@ -145,11 +145,20 @@ static int btsdio_rx_packet(struct btsdio_data *data)
data->hdev->stat.byte_rx += len;
hci_skb_pkt_type(skb) = hdr[3];
err = hci_recv_frame(data->hdev, skb);
if (err < 0)
return err;
switch (hdr[3]) {
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
hci_skb_pkt_type(skb) = hdr[3];
err = hci_recv_frame(data->hdev, skb);
if (err < 0)
return err;
break;
default:
kfree_skb(skb);
return -EINVAL;
}
sdio_writeb(data->func, 0x00, REG_PC_RRT, NULL);
......
......@@ -266,6 +266,7 @@ static const struct usb_device_id blacklist_table[] = {
{ USB_DEVICE(0x04ca, 0x3015), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3016), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x301a), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x04ca, 0x3021), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3491), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3496), .driver_info = BTUSB_QCA_ROME },
{ USB_DEVICE(0x13d3, 0x3501), .driver_info = BTUSB_QCA_ROME },
......
......@@ -13,6 +13,7 @@
#include <linux/module.h>
#include <linux/acpi.h>
#include <linux/of.h>
#include <linux/of_irq.h>
#include <linux/property.h>
#include <linux/platform_data/x86/apple.h>
#include <linux/platform_device.h>
......@@ -53,6 +54,7 @@
*/
struct bcm_device_data {
bool no_early_set_baudrate;
bool drive_rts_on_open;
};
/**
......@@ -122,6 +124,7 @@ struct bcm_device {
bool is_suspended;
#endif
bool no_early_set_baudrate;
bool drive_rts_on_open;
u8 pcm_int_params[5];
};
......@@ -456,7 +459,9 @@ static int bcm_open(struct hci_uart *hu)
out:
if (bcm->dev) {
hci_uart_set_flow_control(hu, true);
if (bcm->dev->drive_rts_on_open)
hci_uart_set_flow_control(hu, true);
hu->init_speed = bcm->dev->init_speed;
/* If oper_speed is set, ldisc/serdev will set the baudrate
......@@ -466,7 +471,10 @@ static int bcm_open(struct hci_uart *hu)
hu->oper_speed = bcm->dev->oper_speed;
err = bcm_gpio_set_power(bcm->dev, true);
hci_uart_set_flow_control(hu, false);
if (bcm->dev->drive_rts_on_open)
hci_uart_set_flow_control(hu, false);
if (err)
goto err_unset_hu;
}
......@@ -1144,6 +1152,8 @@ static int bcm_of_probe(struct bcm_device *bdev)
device_property_read_u32(bdev->dev, "max-speed", &bdev->oper_speed);
device_property_read_u8_array(bdev->dev, "brcm,bt-pcm-int-params",
bdev->pcm_int_params, 5);
bdev->irq = of_irq_get_byname(bdev->dev->of_node, "host-wakeup");
return 0;
}
......@@ -1447,8 +1457,10 @@ static int bcm_serdev_probe(struct serdev_device *serdev)
dev_err(&serdev->dev, "Failed to power down\n");
data = device_get_match_data(bcmdev->dev);
if (data)
if (data) {
bcmdev->no_early_set_baudrate = data->no_early_set_baudrate;
bcmdev->drive_rts_on_open = data->drive_rts_on_open;
}
return hci_uart_register_device(&bcmdev->serdev_hu, &bcm_proto);
}
......@@ -1465,11 +1477,16 @@ static struct bcm_device_data bcm4354_device_data = {
.no_early_set_baudrate = true,
};
static struct bcm_device_data bcm43438_device_data = {
.drive_rts_on_open = true,
};
static const struct of_device_id bcm_bluetooth_of_match[] = {
{ .compatible = "brcm,bcm20702a1" },
{ .compatible = "brcm,bcm4329-bt" },
{ .compatible = "brcm,bcm4345c5" },
{ .compatible = "brcm,bcm4330-bt" },
{ .compatible = "brcm,bcm43438-bt" },
{ .compatible = "brcm,bcm43438-bt", .data = &bcm43438_device_data },
{ .compatible = "brcm,bcm43540-bt", .data = &bcm4354_device_data },
{ .compatible = "brcm,bcm4335a0" },
{ },
......
......@@ -103,6 +103,7 @@ static const struct h4_recv_pkt h4_recv_pkts[] = {
{ H4_RECV_ACL, .recv = hci_recv_frame },
{ H4_RECV_SCO, .recv = hci_recv_frame },
{ H4_RECV_EVENT, .recv = hci_recv_frame },
{ H4_RECV_ISO, .recv = hci_recv_frame },
};
/* Recv data */
......
......@@ -385,6 +385,7 @@ static void h5_complete_rx_pkt(struct hci_uart *hu)
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
hci_skb_pkt_type(h5->rx_skb) = H5_HDR_PKT_TYPE(hdr);
/* Remove Three-wire header */
......@@ -594,6 +595,7 @@ static int h5_enqueue(struct hci_uart *hu, struct sk_buff *skb)
break;
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
skb_queue_tail(&h5->unrel, skb);
break;
......@@ -636,6 +638,7 @@ static bool valid_packet_type(u8 type)
case HCI_ACLDATA_PKT:
case HCI_COMMAND_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
case HCI_3WIRE_LINK_PKT:
case HCI_3WIRE_ACK_PKT:
return true;
......
This diff is collapsed.
......@@ -143,6 +143,13 @@ struct h4_recv_pkt {
.lsize = 1, \
.maxlen = HCI_MAX_EVENT_SIZE
#define H4_RECV_ISO \
.type = HCI_ISODATA_PKT, \
.hlen = HCI_ISO_HDR_SIZE, \
.loff = 2, \
.lsize = 2, \
.maxlen = HCI_MAX_FRAME_SIZE \
struct sk_buff *h4_recv_buf(struct hci_dev *hdev, struct sk_buff *skb,
const unsigned char *buffer, int count,
const struct h4_recv_pkt *pkts, int pkts_count);
......
......@@ -178,6 +178,7 @@ static inline ssize_t vhci_get_user(struct vhci_data *data,
case HCI_EVENT_PKT:
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
if (!data->hdev) {
kfree_skb(skb);
return -ENODEV;
......
......@@ -129,6 +129,8 @@ void bt_warn(const char *fmt, ...);
__printf(1, 2)
void bt_err(const char *fmt, ...);
__printf(1, 2)
void bt_warn_ratelimited(const char *fmt, ...);
__printf(1, 2)
void bt_err_ratelimited(const char *fmt, ...);
#define BT_INFO(fmt, ...) bt_info(fmt "\n", ##__VA_ARGS__)
......@@ -136,8 +138,6 @@ void bt_err_ratelimited(const char *fmt, ...);
#define BT_ERR(fmt, ...) bt_err(fmt "\n", ##__VA_ARGS__)
#define BT_DBG(fmt, ...) pr_debug(fmt "\n", ##__VA_ARGS__)
#define BT_ERR_RATELIMITED(fmt, ...) bt_err_ratelimited(fmt "\n", ##__VA_ARGS__)
#define bt_dev_info(hdev, fmt, ...) \
BT_INFO("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_warn(hdev, fmt, ...) \
......@@ -147,8 +147,10 @@ void bt_err_ratelimited(const char *fmt, ...);
#define bt_dev_dbg(hdev, fmt, ...) \
BT_DBG("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_warn_ratelimited(hdev, fmt, ...) \
bt_warn_ratelimited("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
#define bt_dev_err_ratelimited(hdev, fmt, ...) \
BT_ERR_RATELIMITED("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
bt_err_ratelimited("%s: " fmt, (hdev)->name, ##__VA_ARGS__)
/* Connection and socket states */
enum {
......
......@@ -27,6 +27,7 @@
#define HCI_MAX_ACL_SIZE 1024
#define HCI_MAX_SCO_SIZE 255
#define HCI_MAX_ISO_SIZE 251
#define HCI_MAX_EVENT_SIZE 260
#define HCI_MAX_FRAME_SIZE (HCI_MAX_ACL_SIZE + 4)
......@@ -303,6 +304,7 @@ enum {
#define HCI_ACLDATA_PKT 0x02
#define HCI_SCODATA_PKT 0x03
#define HCI_EVENT_PKT 0x04
#define HCI_ISODATA_PKT 0x05
#define HCI_DIAG_PKT 0xf0
#define HCI_VENDOR_PKT 0xff
......@@ -352,6 +354,15 @@ enum {
#define ACL_ACTIVE_BCAST 0x04
#define ACL_PICO_BCAST 0x08
/* ISO PB flags */
#define ISO_START 0x00
#define ISO_CONT 0x01
#define ISO_SINGLE 0x02
#define ISO_END 0x03
/* ISO TS flags */
#define ISO_TS 0x01
/* Baseband links */
#define SCO_LINK 0x00
#define ACL_LINK 0x01
......@@ -359,6 +370,7 @@ enum {
/* Low Energy links do not have defined link type. Use invented one */
#define LE_LINK 0x80
#define AMP_LINK 0x81
#define ISO_LINK 0x82
#define INVALID_LINK 0xff
/* LMP features */
......@@ -440,6 +452,8 @@ enum {
#define HCI_LE_PHY_2M 0x01
#define HCI_LE_PHY_CODED 0x08
#define HCI_LE_CHAN_SEL_ALG2 0x40
#define HCI_LE_CIS_MASTER 0x10
#define HCI_LE_CIS_SLAVE 0x20
/* Connection modes */
#define HCI_CM_ACTIVE 0x0000
......@@ -1718,6 +1732,86 @@ struct hci_cp_le_set_adv_set_rand_addr {
bdaddr_t bdaddr;
} __packed;
#define HCI_OP_LE_READ_BUFFER_SIZE_V2 0x2060
struct hci_rp_le_read_buffer_size_v2 {
__u8 status;
__le16 acl_mtu;
__u8 acl_max_pkt;
__le16 iso_mtu;
__u8 iso_max_pkt;
} __packed;
#define HCI_OP_LE_READ_ISO_TX_SYNC 0x2061
struct hci_cp_le_read_iso_tx_sync {
__le16 handle;
} __packed;
struct hci_rp_le_read_iso_tx_sync {
__u8 status;
__le16 handle;
__le16 seq;
__le32 imestamp;
__u8 offset[3];
} __packed;
#define HCI_OP_LE_SET_CIG_PARAMS 0x2062
struct hci_cis_params {
__u8 cis_id;
__le16 m_sdu;
__le16 s_sdu;
__u8 m_phy;
__u8 s_phy;
__u8 m_rtn;
__u8 s_rtn;
} __packed;
struct hci_cp_le_set_cig_params {
__u8 cig_id;
__u8 m_interval[3];
__u8 s_interval[3];
__u8 sca;
__u8 packing;
__u8 framing;
__le16 m_latency;
__le16 s_latency;
__u8 num_cis;
struct hci_cis_params cis[0];
} __packed;
struct hci_rp_le_set_cig_params {
__u8 status;
__u8 cig_id;
__u8 num_handles;
__le16 handle[0];
} __packed;
#define HCI_OP_LE_CREATE_CIS 0x2064
struct hci_cis {
__le16 cis_handle;
__le16 acl_handle;
} __packed;
struct hci_cp_le_create_cis {
__u8 num_cis;
struct hci_cis cis[0];
} __packed;
#define HCI_OP_LE_REMOVE_CIG 0x2065
struct hci_cp_le_remove_cig {
__u8 cig_id;
} __packed;
#define HCI_OP_LE_ACCEPT_CIS 0x2066
struct hci_cp_le_accept_cis {
__le16 handle;
} __packed;
#define HCI_OP_LE_REJECT_CIS 0x2067
struct hci_cp_le_reject_cis {
__le16 handle;
__u8 reason;
} __packed;
/* ---- HCI Events ---- */
#define HCI_EV_INQUIRY_COMPLETE 0x01
......@@ -2186,6 +2280,14 @@ struct hci_ev_le_direct_adv_info {
__s8 rssi;
} __packed;
#define HCI_EV_LE_PHY_UPDATE_COMPLETE 0x0c
struct hci_ev_le_phy_update_complete {
__u8 status;
__le16 handle;
__u8 tx_phy;
__u8 rx_phy;
} __packed;
#define HCI_EV_LE_EXT_ADV_REPORT 0x0d
struct hci_ev_le_ext_adv_report {
__le16 evt_type;
......@@ -2226,6 +2328,34 @@ struct hci_evt_le_ext_adv_set_term {
__u8 num_evts;
} __packed;
#define HCI_EVT_LE_CIS_ESTABLISHED 0x19
struct hci_evt_le_cis_established {
__u8 status;
__le16 handle;
__u8 cig_sync_delay[3];
__u8 cis_sync_delay[3];
__u8 m_latency[3];
__u8 s_latency[3];
__u8 m_phy;
__u8 s_phy;
__u8 nse;
__u8 m_bn;
__u8 s_bn;
__u8 m_ft;
__u8 s_ft;
__le16 m_mtu;
__le16 s_mtu;
__le16 interval;
} __packed;
#define HCI_EVT_LE_CIS_REQ 0x1a
struct hci_evt_le_cis_req {
__le16 acl_handle;
__le16 cis_handle;
__u8 cig_id;
__u8 cis_id;
} __packed;
#define HCI_EV_VENDOR 0xff
/* Internal events generated by Bluetooth stack */
......@@ -2254,6 +2384,7 @@ struct hci_ev_si_security {
#define HCI_EVENT_HDR_SIZE 2
#define HCI_ACL_HDR_SIZE 4
#define HCI_SCO_HDR_SIZE 3
#define HCI_ISO_HDR_SIZE 4
struct hci_command_hdr {
__le16 opcode; /* OCF & OGF */
......@@ -2275,6 +2406,30 @@ struct hci_sco_hdr {
__u8 dlen;
} __packed;
struct hci_iso_hdr {
__le16 handle;
__le16 dlen;
__u8 data[0];
} __packed;
/* ISO data packet status flags */
#define HCI_ISO_STATUS_VALID 0x00
#define HCI_ISO_STATUS_INVALID 0x01
#define HCI_ISO_STATUS_NOP 0x02
#define HCI_ISO_DATA_HDR_SIZE 4
struct hci_iso_data_hdr {
__le16 sn;
__le16 slen;
};
#define HCI_ISO_TS_DATA_HDR_SIZE 8
struct hci_iso_ts_data_hdr {
__le32 ts;
__le16 sn;
__le16 slen;
};
static inline struct hci_event_hdr *hci_event_hdr(const struct sk_buff *skb)
{
return (struct hci_event_hdr *) skb->data;
......@@ -2300,4 +2455,14 @@ static inline struct hci_sco_hdr *hci_sco_hdr(const struct sk_buff *skb)
#define hci_handle(h) (h & 0x0fff)
#define hci_flags(h) (h >> 12)
/* ISO handle and flags pack/unpack */
#define hci_iso_flags_pb(f) (f & 0x0003)
#define hci_iso_flags_ts(f) ((f >> 2) & 0x0001)
#define hci_iso_flags_pack(pb, ts) ((pb & 0x03) | ((ts & 0x01) << 2))
/* ISO data length and flags pack/unpack */
#define hci_iso_data_len_pack(h, f) ((__u16) ((h) | ((f) << 14)))
#define hci_iso_data_len(h) ((h) & 0x3fff)
#define hci_iso_data_flags(h) ((h) >> 14)
#endif /* __HCI_H */
......@@ -118,6 +118,13 @@ struct bt_uuid {
u8 svc_hint;
};
struct blocked_key {
struct list_head list;
struct rcu_head rcu;
u8 type;
u8 val[16];
};
struct smp_csrk {
bdaddr_t bdaddr;
u8 bdaddr_type;
......@@ -397,6 +404,7 @@ struct hci_dev {
struct list_head le_conn_params;
struct list_head pend_le_conns;
struct list_head pend_le_reports;
struct list_head blocked_keys;
struct hci_dev_stats stat;
......@@ -493,6 +501,8 @@ struct hci_conn {
__u16 le_supv_timeout;
__u8 le_adv_data[HCI_MAX_AD_LENGTH];
__u8 le_adv_data_len;
__u8 le_tx_phy;
__u8 le_rx_phy;
__s8 rssi;
__s8 tx_power;
__s8 max_tx_power;
......@@ -1121,6 +1131,8 @@ struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
struct smp_irk *hci_add_irk(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type, u8 val[16], bdaddr_t *rpa);
void hci_remove_irk(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 addr_type);
bool hci_is_blocked_key(struct hci_dev *hdev, u8 type, u8 val[16]);
void hci_blocked_keys_clear(struct hci_dev *hdev);
void hci_smp_irks_clear(struct hci_dev *hdev);
bool hci_bdaddr_is_paired(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 type);
......
......@@ -49,6 +49,8 @@ struct hci_mon_hdr {
#define HCI_MON_CTRL_CLOSE 15
#define HCI_MON_CTRL_COMMAND 16
#define HCI_MON_CTRL_EVENT 17
#define HCI_MON_ISO_TX_PKT 18
#define HCI_MON_ISO_RX_PKT 19
struct hci_mon_new_index {
__u8 type;
......
......@@ -654,6 +654,23 @@ struct mgmt_cp_set_phy_confguration {
} __packed;
#define MGMT_SET_PHY_CONFIGURATION_SIZE 4
#define MGMT_OP_SET_BLOCKED_KEYS 0x0046
#define HCI_BLOCKED_KEY_TYPE_LINKKEY 0x00
#define HCI_BLOCKED_KEY_TYPE_LTK 0x01
#define HCI_BLOCKED_KEY_TYPE_IRK 0x02
struct mgmt_blocked_key_info {
__u8 type;
__u8 val[16];
} __packed;
struct mgmt_cp_set_blocked_keys {
__le16 key_count;
struct mgmt_blocked_key_info keys[0];
} __packed;
#define MGMT_OP_SET_BLOCKED_KEYS_SIZE 2
#define MGMT_EV_CMD_COMPLETE 0x0001
struct mgmt_ev_cmd_complete {
__le16 opcode;
......
......@@ -2311,6 +2311,33 @@ void hci_smp_irks_clear(struct hci_dev *hdev)
}
}
void hci_blocked_keys_clear(struct hci_dev *hdev)
{
struct blocked_key *b;
list_for_each_entry_rcu(b, &hdev->blocked_keys, list) {
list_del_rcu(&b->list);
kfree_rcu(b, rcu);
}
}
bool hci_is_blocked_key(struct hci_dev *hdev, u8 type, u8 val[16])
{
bool blocked = false;
struct blocked_key *b;
rcu_read_lock();
list_for_each_entry(b, &hdev->blocked_keys, list) {
if (b->type == type && !memcmp(b->val, val, sizeof(b->val))) {
blocked = true;
break;
}
}
rcu_read_unlock();
return blocked;
}
struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
{
struct link_key *k;
......@@ -2319,6 +2346,16 @@ struct link_key *hci_find_link_key(struct hci_dev *hdev, bdaddr_t *bdaddr)
list_for_each_entry_rcu(k, &hdev->link_keys, list) {
if (bacmp(bdaddr, &k->bdaddr) == 0) {
rcu_read_unlock();
if (hci_is_blocked_key(hdev,
HCI_BLOCKED_KEY_TYPE_LINKKEY,
k->val)) {
bt_dev_warn_ratelimited(hdev,
"Link key blocked for %pMR",
&k->bdaddr);
return NULL;
}
return k;
}
}
......@@ -2387,6 +2424,15 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
if (smp_ltk_is_sc(k) || ltk_role(k->type) == role) {
rcu_read_unlock();
if (hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_LTK,
k->val)) {
bt_dev_warn_ratelimited(hdev,
"LTK blocked for %pMR",
&k->bdaddr);
return NULL;
}
return k;
}
}
......@@ -2397,31 +2443,42 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr,
struct smp_irk *hci_find_irk_by_rpa(struct hci_dev *hdev, bdaddr_t *rpa)
{
struct smp_irk *irk_to_return = NULL;
struct smp_irk *irk;
rcu_read_lock();
list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
if (!bacmp(&irk->rpa, rpa)) {
rcu_read_unlock();
return irk;
irk_to_return = irk;
goto done;
}
}
list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
if (smp_irk_matches(hdev, irk->val, rpa)) {
bacpy(&irk->rpa, rpa);
rcu_read_unlock();
return irk;
irk_to_return = irk;
goto done;
}
}
done:
if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK,
irk_to_return->val)) {
bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR",
&irk_to_return->bdaddr);
irk_to_return = NULL;
}
rcu_read_unlock();
return NULL;
return irk_to_return;
}
struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
u8 addr_type)
{
struct smp_irk *irk_to_return = NULL;
struct smp_irk *irk;
/* Identity Address must be public or static random */
......@@ -2432,13 +2489,23 @@ struct smp_irk *hci_find_irk_by_addr(struct hci_dev *hdev, bdaddr_t *bdaddr,
list_for_each_entry_rcu(irk, &hdev->identity_resolving_keys, list) {
if (addr_type == irk->addr_type &&
bacmp(bdaddr, &irk->bdaddr) == 0) {
rcu_read_unlock();
return irk;
irk_to_return = irk;
goto done;
}
}
done:
if (irk_to_return && hci_is_blocked_key(hdev, HCI_BLOCKED_KEY_TYPE_IRK,
irk_to_return->val)) {
bt_dev_warn_ratelimited(hdev, "Identity key blocked for %pMR",
&irk_to_return->bdaddr);
irk_to_return = NULL;
}
rcu_read_unlock();
return NULL;
return irk_to_return;
}
struct link_key *hci_add_link_key(struct hci_dev *hdev, struct hci_conn *conn,
......@@ -3244,6 +3311,7 @@ struct hci_dev *hci_alloc_dev(void)
INIT_LIST_HEAD(&hdev->pend_le_reports);
INIT_LIST_HEAD(&hdev->conn_hash.list);
INIT_LIST_HEAD(&hdev->adv_instances);
INIT_LIST_HEAD(&hdev->blocked_keys);
INIT_WORK(&hdev->rx_work, hci_rx_work);
INIT_WORK(&hdev->cmd_work, hci_cmd_work);
......@@ -3443,6 +3511,7 @@ void hci_unregister_dev(struct hci_dev *hdev)
hci_bdaddr_list_clear(&hdev->le_resolv_list);
hci_conn_params_clear_all(hdev);
hci_discovery_filter_clear(hdev);
hci_blocked_keys_clear(hdev);
hci_dev_unlock(hdev);
hci_dev_put(hdev);
......@@ -3496,7 +3565,8 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb)
if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) {
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
kfree_skb(skb);
return -EINVAL;
}
......@@ -4218,15 +4288,10 @@ static void hci_sched_le(struct hci_dev *hdev)
if (!hci_conn_num(hdev, LE_LINK))
return;
if (!hci_dev_test_flag(hdev, HCI_UNCONFIGURED)) {
/* LE tx timeout must be longer than maximum
* link supervision timeout (40.9 seconds) */
if (!hdev->le_cnt && hdev->le_pkts &&
time_after(jiffies, hdev->le_last_tx + HZ * 45))
hci_link_tx_to(hdev, LE_LINK);
}
cnt = hdev->le_pkts ? hdev->le_cnt : hdev->acl_cnt;
__check_timeout(hdev, cnt);
tmp = cnt;
while (cnt && (chan = hci_chan_sent(hdev, LE_LINK, &quote))) {
u32 priority = (skb_peek(&chan->data_q))->priority;
......@@ -4479,6 +4544,7 @@ static void hci_rx_work(struct work_struct *work)
switch (hci_skb_pkt_type(skb)) {
case HCI_ACLDATA_PKT:
case HCI_SCODATA_PKT:
case HCI_ISODATA_PKT:
kfree_skb(skb);
continue;
}
......
......@@ -26,6 +26,7 @@
#include <net/bluetooth/bluetooth.h>
#include <net/bluetooth/hci_core.h>
#include "smp.h"
#include "hci_debugfs.h"
#define DEFINE_QUIRK_ATTRIBUTE(__name, __quirk) \
......@@ -152,6 +153,21 @@ static int blacklist_show(struct seq_file *f, void *p)
DEFINE_SHOW_ATTRIBUTE(blacklist);
static int blocked_keys_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
struct blocked_key *key;
rcu_read_lock();
list_for_each_entry_rcu(key, &hdev->blocked_keys, list)
seq_printf(f, "%u %*phN\n", key->type, 16, key->val);
rcu_read_unlock();
return 0;
}
DEFINE_SHOW_ATTRIBUTE(blocked_keys);
static int uuids_show(struct seq_file *f, void *p)
{
struct hci_dev *hdev = f->private;
......@@ -308,6 +324,8 @@ void hci_debugfs_create_common(struct hci_dev *hdev)
&device_list_fops);
debugfs_create_file("blacklist", 0444, hdev->debugfs, hdev,
&blacklist_fops);
debugfs_create_file("blocked_keys", 0444, hdev->debugfs, hdev,
&blocked_keys_fops);
debugfs_create_file("uuids", 0444, hdev->debugfs, hdev, &uuids_fops);
debugfs_create_file("remote_oob", 0400, hdev->debugfs, hdev,
&remote_oob_fops);
......@@ -972,6 +990,62 @@ static int adv_max_interval_get(void *data, u64 *val)
DEFINE_SIMPLE_ATTRIBUTE(adv_max_interval_fops, adv_max_interval_get,
adv_max_interval_set, "%llu\n");
static int min_key_size_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val > hdev->le_max_key_size || val < SMP_MIN_ENC_KEY_SIZE)
return -EINVAL;
hci_dev_lock(hdev);
hdev->le_min_key_size = val;
hci_dev_unlock(hdev);
return 0;
}
static int min_key_size_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->le_min_key_size;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(min_key_size_fops, min_key_size_get,
min_key_size_set, "%llu\n");
static int max_key_size_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
if (val > SMP_MAX_ENC_KEY_SIZE || val < hdev->le_min_key_size)
return -EINVAL;
hci_dev_lock(hdev);
hdev->le_max_key_size = val;
hci_dev_unlock(hdev);
return 0;
}
static int max_key_size_get(void *data, u64 *val)
{
struct hci_dev *hdev = data;
hci_dev_lock(hdev);
*val = hdev->le_max_key_size;
hci_dev_unlock(hdev);
return 0;
}
DEFINE_SIMPLE_ATTRIBUTE(max_key_size_fops, max_key_size_get,
max_key_size_set, "%llu\n");
static int auth_payload_timeout_set(void *data, u64 val)
{
struct hci_dev *hdev = data;
......@@ -1054,6 +1128,10 @@ void hci_debugfs_create_le(struct hci_dev *hdev)
&adv_max_interval_fops);
debugfs_create_u16("discov_interleaved_timeout", 0644, hdev->debugfs,
&hdev->discov_interleaved_timeout);
debugfs_create_file("min_key_size", 0644, hdev->debugfs, hdev,
&min_key_size_fops);
debugfs_create_file("max_key_size", 0644, hdev->debugfs, hdev,
&max_key_size_fops);
debugfs_create_file("auth_payload_timeout", 0644, hdev->debugfs, hdev,
&auth_payload_timeout_fops);
......
......@@ -5451,7 +5451,7 @@ static void hci_le_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_dev_unlock(hdev);
}
static u8 ext_evt_type_to_legacy(u16 evt_type)
static u8 ext_evt_type_to_legacy(struct hci_dev *hdev, u16 evt_type)
{
if (evt_type & LE_EXT_ADV_LEGACY_PDU) {
switch (evt_type) {
......@@ -5468,10 +5468,7 @@ static u8 ext_evt_type_to_legacy(u16 evt_type)
return LE_ADV_SCAN_RSP;
}
BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
evt_type);
return LE_ADV_INVALID;
goto invalid;
}
if (evt_type & LE_EXT_ADV_CONN_IND) {
......@@ -5491,8 +5488,9 @@ static u8 ext_evt_type_to_legacy(u16 evt_type)
evt_type & LE_EXT_ADV_DIRECT_IND)
return LE_ADV_NONCONN_IND;
BT_ERR_RATELIMITED("Unknown advertising packet type: 0x%02x",
evt_type);
invalid:
bt_dev_err_ratelimited(hdev, "Unknown advertising packet type: 0x%02x",
evt_type);
return LE_ADV_INVALID;
}
......@@ -5510,7 +5508,7 @@ static void hci_le_ext_adv_report_evt(struct hci_dev *hdev, struct sk_buff *skb)
u16 evt_type;
evt_type = __le16_to_cpu(ev->evt_type);
legacy_evt_type = ext_evt_type_to_legacy(evt_type);
legacy_evt_type = ext_evt_type_to_legacy(hdev, evt_type);
if (legacy_evt_type != LE_ADV_INVALID) {
process_adv_report(hdev, legacy_evt_type, &ev->bdaddr,
ev->bdaddr_type, NULL, 0, ev->rssi,
......@@ -5720,6 +5718,29 @@ static void hci_le_direct_adv_report_evt(struct hci_dev *hdev,
hci_dev_unlock(hdev);
}
static void hci_le_phy_update_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_phy_update_complete *ev = (void *) skb->data;
struct hci_conn *conn;
BT_DBG("%s status 0x%2.2x", hdev->name, ev->status);
if (!ev->status)
return;
hci_dev_lock(hdev);
conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(ev->handle));
if (!conn)
goto unlock;
conn->le_tx_phy = ev->tx_phy;
conn->le_rx_phy = ev->rx_phy;
unlock:
hci_dev_unlock(hdev);
}
static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
{
struct hci_ev_le_meta *le_ev = (void *) skb->data;
......@@ -5755,6 +5776,10 @@ static void hci_le_meta_evt(struct hci_dev *hdev, struct sk_buff *skb)
hci_le_direct_adv_report_evt(hdev, skb);
break;
case HCI_EV_LE_PHY_UPDATE_COMPLETE:
hci_le_phy_update_evt(hdev, skb);
break;
case HCI_EV_LE_EXT_ADV_REPORT:
hci_le_ext_adv_report_evt(hdev, skb);
break;
......
......@@ -211,7 +211,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT &&
hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT)
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
hci_skb_pkt_type(skb) != HCI_ISODATA_PKT)
continue;
if (is_filtered_packet(sk, skb))
continue;
......@@ -220,7 +221,8 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb)
continue;
if (hci_skb_pkt_type(skb) != HCI_EVENT_PKT &&
hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT)
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
hci_skb_pkt_type(skb) != HCI_ISODATA_PKT)
continue;
} else {
/* Don't send frame to other channel types */
......@@ -324,6 +326,12 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb)
else
opcode = cpu_to_le16(HCI_MON_SCO_TX_PKT);
break;
case HCI_ISODATA_PKT:
if (bt_cb(skb)->incoming)
opcode = cpu_to_le16(HCI_MON_ISO_RX_PKT);
else
opcode = cpu_to_le16(HCI_MON_ISO_TX_PKT);
break;
case HCI_DIAG_PKT:
opcode = cpu_to_le16(HCI_MON_VENDOR_DIAG);
break;
......@@ -831,6 +839,8 @@ static int hci_sock_release(struct socket *sock)
if (!sk)
return 0;
lock_sock(sk);
switch (hci_pi(sk)->channel) {
case HCI_CHANNEL_MONITOR:
atomic_dec(&monitor_promisc);
......@@ -878,6 +888,7 @@ static int hci_sock_release(struct socket *sock)
skb_queue_purge(&sk->sk_receive_queue);
skb_queue_purge(&sk->sk_write_queue);
release_sock(sk);
sock_put(sk);
return 0;
}
......@@ -1762,7 +1773,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
*/
if (hci_skb_pkt_type(skb) != HCI_COMMAND_PKT &&
hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) {
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
err = -EINVAL;
goto drop;
}
......@@ -1806,7 +1818,8 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg,
}
if (hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT &&
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT) {
hci_skb_pkt_type(skb) != HCI_SCODATA_PKT &&
hci_skb_pkt_type(skb) != HCI_ISODATA_PKT) {
err = -EINVAL;
goto drop;
}
......
......@@ -1289,6 +1289,9 @@ static void l2cap_le_connect(struct l2cap_chan *chan)
if (test_and_set_bit(FLAG_LE_CONN_REQ_SENT, &chan->flags))
return;
if (!chan->imtu)
chan->imtu = chan->conn->mtu;
l2cap_le_flowctl_init(chan, 0);
req.psm = chan->psm;
......@@ -3226,6 +3229,49 @@ static inline void l2cap_txwin_setup(struct l2cap_chan *chan)
chan->ack_win = chan->tx_win;
}
static void l2cap_mtu_auto(struct l2cap_chan *chan)
{
struct hci_conn *conn = chan->conn->hcon;
chan->imtu = L2CAP_DEFAULT_MIN_MTU;
/* The 2-DH1 packet has between 2 and 56 information bytes
* (including the 2-byte payload header)
*/
if (!(conn->pkt_type & HCI_2DH1))
chan->imtu = 54;
/* The 3-DH1 packet has between 2 and 85 information bytes
* (including the 2-byte payload header)
*/
if (!(conn->pkt_type & HCI_3DH1))
chan->imtu = 83;
/* The 2-DH3 packet has between 2 and 369 information bytes
* (including the 2-byte payload header)
*/
if (!(conn->pkt_type & HCI_2DH3))
chan->imtu = 367;
/* The 3-DH3 packet has between 2 and 554 information bytes
* (including the 2-byte payload header)
*/
if (!(conn->pkt_type & HCI_3DH3))
chan->imtu = 552;
/* The 2-DH5 packet has between 2 and 681 information bytes
* (including the 2-byte payload header)
*/
if (!(conn->pkt_type & HCI_2DH5))
chan->imtu = 679;
/* The 3-DH5 packet has between 2 and 1023 information bytes
* (including the 2-byte payload header)
*/
if (!(conn->pkt_type & HCI_3DH5))
chan->imtu = 1021;
}
static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data_size)
{
struct l2cap_conf_req *req = data;
......@@ -3255,8 +3301,12 @@ static int l2cap_build_conf_req(struct l2cap_chan *chan, void *data, size_t data
}
done:
if (chan->imtu != L2CAP_DEFAULT_MTU)
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu, endptr - ptr);
if (chan->imtu != L2CAP_DEFAULT_MTU) {
if (!chan->imtu)
l2cap_mtu_auto(chan);
l2cap_add_conf_opt(&ptr, L2CAP_CONF_MTU, 2, chan->imtu,
endptr - ptr);
}
switch (chan->mode) {
case L2CAP_MODE_BASIC:
......@@ -5031,7 +5081,6 @@ static inline int l2cap_move_channel_req(struct l2cap_conn *conn,
chan->move_role = L2CAP_MOVE_ROLE_RESPONDER;
l2cap_move_setup(chan);
chan->move_id = req->dest_amp_id;
icid = chan->dcid;
if (req->dest_amp_id == AMP_ID_BREDR) {
/* Moving to BR/EDR */
......
......@@ -183,6 +183,22 @@ void bt_err(const char *format, ...)
}
EXPORT_SYMBOL(bt_err);
void bt_warn_ratelimited(const char *format, ...)
{
struct va_format vaf;
va_list args;
va_start(args, format);
vaf.fmt = format;
vaf.va = &args;
pr_warn_ratelimited("%pV", &vaf);
va_end(args);
}
EXPORT_SYMBOL(bt_warn_ratelimited);
void bt_err_ratelimited(const char *format, ...)
{
struct va_format vaf;
......
......@@ -38,7 +38,7 @@
#include "mgmt_util.h"
#define MGMT_VERSION 1
#define MGMT_REVISION 14
#define MGMT_REVISION 15
static const u16 mgmt_commands[] = {
MGMT_OP_READ_INDEX_LIST,
......@@ -106,6 +106,7 @@ static const u16 mgmt_commands[] = {
MGMT_OP_START_LIMITED_DISCOVERY,
MGMT_OP_READ_EXT_INFO,
MGMT_OP_SET_APPEARANCE,
MGMT_OP_SET_BLOCKED_KEYS,
};
static const u16 mgmt_events[] = {
......@@ -175,7 +176,7 @@ static const u16 mgmt_untrusted_events[] = {
"\x00\x00\x00\x00\x00\x00\x00\x00"
/* HCI to MGMT error code conversion table */
static u8 mgmt_status_table[] = {
static const u8 mgmt_status_table[] = {
MGMT_STATUS_SUCCESS,
MGMT_STATUS_UNKNOWN_COMMAND, /* Unknown Command */
MGMT_STATUS_NOT_CONNECTED, /* No Connection */
......@@ -2341,6 +2342,14 @@ static int load_link_keys(struct sock *sk, struct hci_dev *hdev, void *data,
for (i = 0; i < key_count; i++) {
struct mgmt_link_key_info *key = &cp->keys[i];
if (hci_is_blocked_key(hdev,
HCI_BLOCKED_KEY_TYPE_LINKKEY,
key->val)) {
bt_dev_warn(hdev, "Skipping blocked link key for %pMR",
&key->addr.bdaddr);
continue;
}
/* Always ignore debug keys and require a new pairing if
* the user wants to use them.
*/
......@@ -3282,7 +3291,7 @@ static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
struct mgmt_cp_set_appearance *cp = data;
u16 apperance;
u16 appearance;
int err;
BT_DBG("");
......@@ -3291,12 +3300,12 @@ static int set_appearance(struct sock *sk, struct hci_dev *hdev, void *data,
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_APPEARANCE,
MGMT_STATUS_NOT_SUPPORTED);
apperance = le16_to_cpu(cp->appearance);
appearance = le16_to_cpu(cp->appearance);
hci_dev_lock(hdev);
if (hdev->appearance != apperance) {
hdev->appearance = apperance;
if (hdev->appearance != appearance) {
hdev->appearance = appearance;
if (hci_dev_test_flag(hdev, HCI_LE_ADV))
adv_expire(hdev, MGMT_ADV_FLAG_APPEARANCE);
......@@ -3531,6 +3540,55 @@ static int set_phy_configuration(struct sock *sk, struct hci_dev *hdev,
return err;
}
static int set_blocked_keys(struct sock *sk, struct hci_dev *hdev, void *data,
u16 len)
{
int err = MGMT_STATUS_SUCCESS;
struct mgmt_cp_set_blocked_keys *keys = data;
const u16 max_key_count = ((U16_MAX - sizeof(*keys)) /
sizeof(struct mgmt_blocked_key_info));
u16 key_count, expected_len;
int i;
BT_DBG("request for %s", hdev->name);
key_count = __le16_to_cpu(keys->key_count);
if (key_count > max_key_count) {
bt_dev_err(hdev, "too big key_count value %u", key_count);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
expected_len = struct_size(keys, keys, key_count);
if (expected_len != len) {
bt_dev_err(hdev, "expected %u bytes, got %u bytes",
expected_len, len);
return mgmt_cmd_status(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
MGMT_STATUS_INVALID_PARAMS);
}
hci_dev_lock(hdev);
hci_blocked_keys_clear(hdev);
for (i = 0; i < keys->key_count; ++i) {
struct blocked_key *b = kzalloc(sizeof(*b), GFP_KERNEL);
if (!b) {
err = MGMT_STATUS_NO_RESOURCES;
break;
}
b->type = keys->keys[i].type;
memcpy(b->val, keys->keys[i].val, sizeof(b->val));
list_add_rcu(&b->list, &hdev->blocked_keys);
}
hci_dev_unlock(hdev);
return mgmt_cmd_complete(sk, hdev->id, MGMT_OP_SET_BLOCKED_KEYS,
err, NULL, 0);
}
static void read_local_oob_data_complete(struct hci_dev *hdev, u8 status,
u16 opcode, struct sk_buff *skb)
{
......@@ -5051,6 +5109,14 @@ static int load_irks(struct sock *sk, struct hci_dev *hdev, void *cp_data,
for (i = 0; i < irk_count; i++) {
struct mgmt_irk_info *irk = &cp->irks[i];
if (hci_is_blocked_key(hdev,
HCI_BLOCKED_KEY_TYPE_IRK,
irk->val)) {
bt_dev_warn(hdev, "Skipping blocked IRK for %pMR",
&irk->addr.bdaddr);
continue;
}
hci_add_irk(hdev, &irk->addr.bdaddr,
le_addr_type(irk->addr.type), irk->val,
BDADDR_ANY);
......@@ -5134,6 +5200,14 @@ static int load_long_term_keys(struct sock *sk, struct hci_dev *hdev,
struct mgmt_ltk_info *key = &cp->keys[i];
u8 type, authenticated;
if (hci_is_blocked_key(hdev,
HCI_BLOCKED_KEY_TYPE_LTK,
key->val)) {
bt_dev_warn(hdev, "Skipping blocked LTK for %pMR",
&key->addr.bdaddr);
continue;
}
switch (key->type) {
case MGMT_LTK_UNAUTHENTICATED:
authenticated = 0x00;
......@@ -6914,6 +6988,8 @@ static const struct hci_mgmt_handler mgmt_handlers[] = {
{ set_appearance, MGMT_SET_APPEARANCE_SIZE },
{ get_phy_configuration, MGMT_GET_PHY_CONFIGURATION_SIZE },
{ set_phy_configuration, MGMT_SET_PHY_CONFIGURATION_SIZE },
{ set_blocked_keys, MGMT_OP_SET_BLOCKED_KEYS_SIZE,
HCI_MGMT_VAR_LEN },
};
void mgmt_index_added(struct hci_dev *hdev)
......
......@@ -2453,6 +2453,15 @@ static int smp_cmd_encrypt_info(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(*rp))
return SMP_INVALID_PARAMS;
/* Pairing is aborted if any blocked keys are distributed */
if (hci_is_blocked_key(conn->hcon->hdev, HCI_BLOCKED_KEY_TYPE_LTK,
rp->ltk)) {
bt_dev_warn_ratelimited(conn->hcon->hdev,
"LTK blocked for %pMR",
&conn->hcon->dst);
return SMP_INVALID_PARAMS;
}
SMP_ALLOW_CMD(smp, SMP_CMD_MASTER_IDENT);
skb_pull(skb, sizeof(*rp));
......@@ -2509,6 +2518,15 @@ static int smp_cmd_ident_info(struct l2cap_conn *conn, struct sk_buff *skb)
if (skb->len < sizeof(*info))
return SMP_INVALID_PARAMS;
/* Pairing is aborted if any blocked keys are distributed */
if (hci_is_blocked_key(conn->hcon->hdev, HCI_BLOCKED_KEY_TYPE_IRK,
info->irk)) {
bt_dev_warn_ratelimited(conn->hcon->hdev,
"Identity key blocked for %pMR",
&conn->hcon->dst);
return SMP_INVALID_PARAMS;
}
SMP_ALLOW_CMD(smp, SMP_CMD_IDENT_ADDR_INFO);
skb_pull(skb, sizeof(*info));
......@@ -3355,94 +3373,6 @@ static const struct file_operations force_bredr_smp_fops = {
.llseek = default_llseek,
};
static ssize_t le_min_key_size_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[4];
snprintf(buf, sizeof(buf), "%2u\n", hdev->le_min_key_size);
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}
static ssize_t le_min_key_size_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[32];
size_t buf_size = min(count, (sizeof(buf) - 1));
u8 key_size;
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
sscanf(buf, "%hhu", &key_size);
if (key_size > hdev->le_max_key_size ||
key_size < SMP_MIN_ENC_KEY_SIZE)
return -EINVAL;
hdev->le_min_key_size = key_size;
return count;
}
static const struct file_operations le_min_key_size_fops = {
.open = simple_open,
.read = le_min_key_size_read,
.write = le_min_key_size_write,
.llseek = default_llseek,
};
static ssize_t le_max_key_size_read(struct file *file,
char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[4];
snprintf(buf, sizeof(buf), "%2u\n", hdev->le_max_key_size);
return simple_read_from_buffer(user_buf, count, ppos, buf, strlen(buf));
}
static ssize_t le_max_key_size_write(struct file *file,
const char __user *user_buf,
size_t count, loff_t *ppos)
{
struct hci_dev *hdev = file->private_data;
char buf[32];
size_t buf_size = min(count, (sizeof(buf) - 1));
u8 key_size;
if (copy_from_user(buf, user_buf, buf_size))
return -EFAULT;
buf[buf_size] = '\0';
sscanf(buf, "%hhu", &key_size);
if (key_size > SMP_MAX_ENC_KEY_SIZE ||
key_size < hdev->le_min_key_size)
return -EINVAL;
hdev->le_max_key_size = key_size;
return count;
}
static const struct file_operations le_max_key_size_fops = {
.open = simple_open,
.read = le_max_key_size_read,
.write = le_max_key_size_write,
.llseek = default_llseek,
};
int smp_register(struct hci_dev *hdev)
{
struct l2cap_chan *chan;
......@@ -3467,11 +3397,6 @@ int smp_register(struct hci_dev *hdev)
hdev->smp_data = chan;
debugfs_create_file("le_min_key_size", 0644, hdev->debugfs, hdev,
&le_min_key_size_fops);
debugfs_create_file("le_max_key_size", 0644, hdev->debugfs, hdev,
&le_max_key_size_fops);
/* If the controller does not support BR/EDR Secure Connections
* feature, then the BR/EDR SMP channel shall not be present.
*
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment