diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 15:58:00 -1000 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2026-10-22 15:58:00 -1000 |
| commit | 734bef548a96e8774d6eef5dfa2026c6edc4e80b (patch) | |
| tree | ce2520b2602ce3b82f9842490d21836f9838d441 /net/bluetooth | |
| parent | 864c07de0c7dcbca58b61625dfa2e461ae63b242 (diff) | |
| parent | 1a2c35c49cc7c6be860038b8442b52424a8f123c (diff) | |
Merge tag 'net-next-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next
Pull networking updates from Paolo Abeni:
"This includes a significant number of low-priority fixes - especially
in the NIC drivers area - that we deferred from the last few RCs in
the previous cycle, which can't be easily outlined in the synopsis
below.
Core & protocols:
- Continue the work on removing rtnl_lock dependencies:
- per-netns ARP and ND neighbour tables, with the default settings
now configurable per netns (inheritance from init_net is
controlled by the new net.core.neigh_inherit_init_net sysctl)
- RCU-protected configuration and rtnl_lock-less fill_info() for
hsr, netkit, sit, vlan and vxlan devices
- per-netns device unregistration for ip tunnel and gre devices
- use the netdev instance lock instead of rtnl_lock when reading
speed and duplex via sysfs
- batch the flushing of uncached routes at device unregistration
time, relieving rtnl_lock contention on netns dismantle.
- Add hardware pacing offload support, admin-controlled via a new
rtnetlink attribute, with sch_fq integration (implemented in idpf).
- Re-segment BIG TCP GSO packets into GSO packets fitting the egress
device limits instead of plain MSS-sized segments, improving
throughput for mixed BIG TCP / non-BIG TCP paths by up to 70%.
- Generate RSS keys that spread flows over all the RX queues; the
previous random keys could leave some queues unused.
- Optimize the bridge VLAN forwarding paths: cache the port-VLAN in
fdb entries and consider only VLAN members when flooding, for ~10%
more Mpps in the fdb forwarding path.
- A few TCP/IP performance improvements aimed at efficient cache
usage and reducing contention.
- Add the TCP ROCCET congestion control, a CUBIC variant aimed at
avoiding bufferbloat in cellular networks.
- Continue the conversion of getsockopt callbacks to sockopt_t.
- Add an ethtool command to list the front-facing ports of an
interface, including SFP cages and modules, using the phy_port
representation.
- Enable BIG TCP support for bareudp tunnels.
- Remove the IPV6_ADDRFORM socket option and disallow buggy TCP state
transitions (listen() + shutdown() + connect() and connect() +
connect(AF_UNSPEC) + listen()).
- Remove most BUG_ON()s from core packet processing, replacing them
with error paths.
Wireless:
- Latency improvements, including lockless station get/dump and
beacon updates, plus RTNL reduction and locking cleanups.
- Infrastructure for non-station TX/RX with MLO.
- NAN (Wi-Fi Aware) Instant Communication support and other NAN
improvements.
- Control frame Integrity Protocol (CIP) and protected TWT support.
- Improvements for AP regulatory checks.
Netfilter:
- Disable br_netfilter in user namespaces and schedule it for removal
in 2027.
- Restrict the raw table in nft_compat to the specific family, hook
and priority.
- Prepare the flowtable for mixed IPv4-over-IPv6 tunneling (and vice
versa).
- Use GFP_KERNEL_ACCOUNT for most netfilter allocations, for better
integration with memcg.
- Allow discovering conntrack zone filtering support in ctnetlink
dumps, and fix nfnetlink_hook handling of large dumps.
Deletions:
- Move the LLC type 2 sockets out of tree. There are no known users
and the code attracts a never-ending stream of LLM-driven fixes.
Device drivers:
- New drivers:
- Meta Platforms NIC (mpnic), the second-generation NIC from Meta
- initial skeleton of the Nebula-matrix NICs driver (nbl)
- X-Powers AC200/AC300 Fast Ethernet PHYs
- Ethernet high-speed NICs:
- Intel:
- i40e: XDP metadata support for RX hash and VLAN tag
- ice: expose the E825 TSPLL state via the DPLL subsystem
- nVidia/Mellanox:
- move the data direct infrastructure from IB to core, in
preparation for netdev support.
- reduce the memory used per offloaded TC rule
- Meta (fbnic):
- support large io_uring zero-copy RX buffers
- Microsoft vNIC (mana):
- add BQL support
- Ethernet NICs consumer, and embedded:
- Airoha:
- LRO offload support
- Cadence (macb):
- context swapping for ringparam and MTU changes, avoiding
buffer loss under memory pressure
- Mucse (rnpgbe):
- TX/RX and link status support
- NXP (enetc):
- SR-IOV improvements and VF support for ENETC v4
- Qualcomm (ppe):
- IPQ5424 support
- Realtek PCI (r8169):
- phylink support
- RSS support for RTL8127
- Renesas (ravb):
- gPTP support for R-Car Gen4
- Synopsys (stmmac):
- XDP multi-buffer support on the TX side
- tc mqprio hw queue priority offload
- support for RK3568 SGMII, Allwinner H616 EMAC1, UltraRISC
DP1000 and Qualcomm sa8255p
- Ethernet switches:
- Mediatek (mt7530):
- fast age and change conduit support
- Microchip (ksz):
- support for KSZ8995XA/KS8995XA
- Microchip (lan966x):
- PCIe FDMA support, ~20x throughput increase in PCIe endpoint
- Microchip (sparx5):
- Time Aware Shaper (taprio) offload
- Motorcomm (yt921x):
- LED and SerDes PCS support
- Realtek (rtl8365mb):
- EEE support
- Ethernet PHYs:
- Broadcom:
- enable jumbo frames on BCM54xx
- Realtek:
- support for RTL8261CE_CG and RTL8261D_VM
- MDIO support for RTL838x and RTL839x
- WiFi drivers:
- Broadcom (brcmfmac):
- FT/OKC roaming offload
- Intel (iwlwifi):
- UHR sniffer support
- support for newer UEFI/BIOS tables
- MediaTek (mt76):
- mt7925 NAN improvements
- offchannel/scan improvements and MLO fixes
- Morse Micro (mm81x):
- monitor mode support
- Qualcomm (ath12k):
- IPQ5332 platform infrastructure
- Realtek (rtw88):
- RTL8723BS support
- SDIO TX performance improvements
- Realtek (rtw89):
- P2P_DEVICE support
- BT-coex updates for RTL8922D
- Bluetooth:
- move H:4 reassembly into the Bluetooth core
- add generic support for vendor packets
- MGMT: add security level changed event
- Bluetooth drivers:
- btusb: support Bulk Serialization Mode
- Intel: support Draco and Titan Lake, allow unsigned firmware
- Mediatek: MT7928 support
- Qualcomm: QCC2072 support
- Broadcom: Synaptics 4384 support"
* tag 'net-next-7.4' of git://git.kernel.org/pub/scm/linux/kernel/git/netdev/net-next: (2126 commits)
Bluetooth: btusb: disable by default Qualcomm multi-subsystem
tipc: fix broadcast sender hang on last acker departure
tipc: fix use-after-free of broadcast reception link at node release
r8169: clear TX LPI on RTL8168h at link up after phylink conversion
tun: Require CAP_NET_ADMIN to attach to an ownerless device
net/sched/sch_cake: drop dead nla_nest_end() error check
net/sched/sch_cake: widen buffer_used to u64
net/sched/sch_cake: reduce parent backlog when clearing a tin
net/sched/sch_cake: serialize reconfiguration with the datapath
tg3: Add Datto SIRIS 5 1U Server to restart AER quirk table
net/mlx5e: Stop asserting for RTNL when closing channels
net: shrink the payload-only part of skb dataref to one bit
net: wwan: iosm: validate msg_head before indexing msg_ring
net: bgmac: rate limit RX error messages
selftests: net: veth: test XDP_TX to a peer with GRO enabled
veth: schedule the peer's NAPI after XDP_TX when only GRO is enabled
pppoe: delete session hash entries by pointer match
net: lan969x: don't disable hardirqs in fdma tx clear
net: sparx5/lan969x: do not clobber the PSFP cycle timer update period
net: lan969x: fix DSM calendar for empty taxis
...
Diffstat (limited to 'net/bluetooth')
| -rw-r--r-- | net/bluetooth/6lowpan.c | 50 | ||||
| -rw-r--r-- | net/bluetooth/Makefile | 2 | ||||
| -rw-r--r-- | net/bluetooth/bnep/core.c | 16 | ||||
| -rw-r--r-- | net/bluetooth/hci_conn.c | 28 | ||||
| -rw-r--r-- | net/bluetooth/hci_core.c | 57 | ||||
| -rw-r--r-- | net/bluetooth/hci_debugfs.c | 9 | ||||
| -rw-r--r-- | net/bluetooth/hci_event.c | 290 | ||||
| -rw-r--r-- | net/bluetooth/hci_h4.c | 160 | ||||
| -rw-r--r-- | net/bluetooth/hci_sock.c | 8 | ||||
| -rw-r--r-- | net/bluetooth/hci_sync.c | 138 | ||||
| -rw-r--r-- | net/bluetooth/iso.c | 18 | ||||
| -rw-r--r-- | net/bluetooth/l2cap_core.c | 371 | ||||
| -rw-r--r-- | net/bluetooth/l2cap_sock.c | 122 | ||||
| -rw-r--r-- | net/bluetooth/mgmt.c | 204 | ||||
| -rw-r--r-- | net/bluetooth/msft.c | 6 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/core.c | 6 | ||||
| -rw-r--r-- | net/bluetooth/rfcomm/sock.c | 5 | ||||
| -rw-r--r-- | net/bluetooth/sco.c | 10 | ||||
| -rw-r--r-- | net/bluetooth/selftest.c | 1 | ||||
| -rw-r--r-- | net/bluetooth/smp.c | 5 |
20 files changed, 1208 insertions, 298 deletions
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c index 30f4afa18bc8..8c51c20f6c4b 100644 --- a/net/bluetooth/6lowpan.c +++ b/net/bluetooth/6lowpan.c @@ -515,7 +515,7 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev) /* We must take a copy of the skb before we modify/replace the ipv6 * header as the header could be used elsewhere */ - skb = skb_unshare(skb, GFP_ATOMIC); + skb = skb_unclone_full(skb, GFP_ATOMIC); if (!skb) return NET_XMIT_DROP; @@ -706,6 +706,7 @@ static int setup_netdev(struct l2cap_chan *chan, struct lowpan_btle_dev **dev) spin_lock(&devices_lock); list_del_rcu(&(*dev)->list); spin_unlock(&devices_lock); + synchronize_rcu(); free_netdev(netdev); goto out; } @@ -722,6 +723,8 @@ out: } static inline void chan_ready_cb(struct l2cap_chan *chan) + __must_hold(&chan->lock) + __must_hold(&chan->conn->lock) { struct lowpan_btle_dev *dev; bool new_netdev = false; @@ -912,18 +915,27 @@ static int bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type) static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type) { struct lowpan_peer *peer; + struct l2cap_chan *chan; BT_DBG("conn %p dst type %u", conn, dst_type); + spin_lock(&devices_lock); + peer = lookup_peer(conn); - if (!peer) + if (!peer) { + spin_unlock(&devices_lock); return -ENOENT; + } + + chan = peer->chan; + l2cap_chan_hold(chan); + + spin_unlock(&devices_lock); - BT_DBG("peer %p chan %p", peer, peer->chan); + BT_DBG("peer %p chan %p", peer, chan); - l2cap_chan_lock(peer->chan); - l2cap_chan_close(peer->chan, ENOENT); - l2cap_chan_unlock(peer->chan); + l2cap_chan_close_unlocked(chan, ENOENT); + l2cap_chan_put(chan); return 0; } @@ -1025,9 +1037,9 @@ static void disconnect_all_peers(void) struct lowpan_peer *peer; int nchans; - /* l2cap_chan_close() cannot be called from RCU, and lock ordering - * chan->lock > devices_lock prevents taking write side lock, so copy - * then close. + /* l2cap_chan_close_unlocked() cannot be called from RCU, and lock + * ordering chan->lock > devices_lock prevents taking write side lock, + * so copy then close. */ rcu_read_lock(); @@ -1062,9 +1074,7 @@ done: spin_unlock(&devices_lock); for (i = 0; i < nchans; ++i) { - l2cap_chan_lock(chans[i]); - l2cap_chan_close(chans[i], ENOENT); - l2cap_chan_unlock(chans[i]); + l2cap_chan_close_unlocked(chans[i], ENOENT); l2cap_chan_put(chans[i]); } } while (nchans); @@ -1082,9 +1092,7 @@ static void do_enable_set(bool flag) mutex_lock(&set_lock); if (listen_chan) { - l2cap_chan_lock(listen_chan); - l2cap_chan_close(listen_chan, 0); - l2cap_chan_unlock(listen_chan); + l2cap_chan_close_unlocked(listen_chan, 0); l2cap_chan_put(listen_chan); } @@ -1132,9 +1140,7 @@ static ssize_t lowpan_control_write(struct file *fp, mutex_lock(&set_lock); if (listen_chan) { - l2cap_chan_lock(listen_chan); - l2cap_chan_close(listen_chan, 0); - l2cap_chan_unlock(listen_chan); + l2cap_chan_close_unlocked(listen_chan, 0); l2cap_chan_put(listen_chan); listen_chan = NULL; } @@ -1209,6 +1215,7 @@ static int lowpan_control_open(struct inode *inode, struct file *file) } static const struct file_operations lowpan_control_fops = { + .owner = THIS_MODULE, .open = lowpan_control_open, .read = seq_read, .write = lowpan_control_write, @@ -1269,7 +1276,7 @@ static int device_event(struct notifier_block *unused, if (entry->netdev == netdev) { BT_DBG("Unregistered netdev %s %p", netdev->name, netdev); - list_del(&entry->list); + list_del_rcu(&entry->list); break; } } @@ -1303,10 +1310,9 @@ static void __exit bt_6lowpan_exit(void) debugfs_remove(lowpan_control_debugfs); if (listen_chan) { - l2cap_chan_lock(listen_chan); - l2cap_chan_close(listen_chan, 0); - l2cap_chan_unlock(listen_chan); + l2cap_chan_close_unlocked(listen_chan, 0); l2cap_chan_put(listen_chan); + listen_chan = NULL; } disconnect_devices(); diff --git a/net/bluetooth/Makefile b/net/bluetooth/Makefile index ff466ea97436..b78ad98864d4 100644 --- a/net/bluetooth/Makefile +++ b/net/bluetooth/Makefile @@ -14,7 +14,7 @@ bluetooth_6lowpan-y := 6lowpan.o bluetooth-y := af_bluetooth.o hci_core.o hci_conn.o hci_event.o mgmt.o \ hci_sock.o hci_sysfs.o l2cap_core.o l2cap_sock.o smp.o lib.o \ ecdh_helper.o mgmt_util.o mgmt_config.o hci_codec.o eir.o hci_sync.o \ - hci_drv.o + hci_drv.o hci_h4.o bluetooth-$(CONFIG_DEV_COREDUMP) += coredump.o diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c index ad24d2486665..06854f46ba34 100644 --- a/net/bluetooth/bnep/core.c +++ b/net/bluetooth/bnep/core.c @@ -495,10 +495,7 @@ send: iv[il++] = (struct kvec) { skb->data, skb->len }; len += skb->len; - /* FIXME: linearize skb */ - { - len = kernel_sendmsg(sock, &s->msg, iv, il, len); - } + len = kernel_sendmsg(sock, &s->msg, iv, il, len); kfree_skb(skb); if (len > 0) { @@ -539,9 +536,12 @@ static int bnep_session(void *arg) break; /* TX */ - while ((skb = skb_dequeue(&sk->sk_write_queue))) - if (bnep_tx_frame(s, skb)) + while ((skb = skb_dequeue(&sk->sk_write_queue))) { + if (skb_linearize(skb)) + kfree_skb(skb); + else if (bnep_tx_frame(s, skb)) break; + } netif_wake_queue(dev); /* @@ -685,7 +685,7 @@ int bnep_add_connection(struct bnep_connadd_req *req, struct socket *sock) goto failed; } - strcpy(req->device, dev->name); + strscpy(req->device, dev->name, sizeof(req->device)); up_write(&bnep_session_sem); return 0; @@ -727,7 +727,7 @@ static void __bnep_copy_ci(struct bnep_conninfo *ci, struct bnep_session *s) memset(ci, 0, sizeof(*ci)); memcpy(ci->dst, s->eh.h_source, ETH_ALEN); - strcpy(ci->device, s->dev->name); + strscpy(ci->device, s->dev->name, sizeof(ci->device)); ci->flags = s->flags & valid_flags; ci->state = s->state; ci->role = s->role; diff --git a/net/bluetooth/hci_conn.c b/net/bluetooth/hci_conn.c index cf44452e0766..29da3fe2b953 100644 --- a/net/bluetooth/hci_conn.c +++ b/net/bluetooth/hci_conn.c @@ -1233,6 +1233,29 @@ static void hci_conn_unlink(struct hci_conn *conn) if (!conn->parent) { struct hci_link *link, *t; + conn->sec_level = BT_SECURITY_SDP; + clear_bit(HCI_CONN_ENCRYPT, &conn->flags); + clear_bit(HCI_CONN_AES_CCM, &conn->flags); + /* mgmt_security_level_changed() reports the reset only if + * this connection was actually reported to userspace as + * connected (it checks HCI_CONN_MGMT_CONNECTED itself), so it + * must be called before the flag is cleared below. + * Callers that already know whether the connection was + * mgmt-connected (e.g. disconnect event handlers) only peek + * at the flag, so it is still set here; this is the place + * actually clearing it. + * + * Skip the report if hdev is down: this means + * hci_dev_close_sync()/hci_conn_hash_flush() is in progress + * and no MGMT_EV_DEVICE_DISCONNECTED was ever sent for this + * connection, so sending a security level reset here would + * be a spurious, order-less event; the adapter-wide powered + * off notification is enough for userspace to reset state. + */ + if (test_bit(HCI_UP, &hdev->flags)) + mgmt_security_level_changed(conn); + clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); + list_for_each_entry_safe(link, t, &conn->link_list, list) { struct hci_conn *child = link->conn; @@ -1543,6 +1566,11 @@ struct hci_conn *hci_connect_le(struct hci_dev *hdev, bdaddr_t *dst, conn->pending_sec_level = sec_level; } + /* Do not report the security level here: conn->dst may still hold + * the peer's RPA instead of its identity address, and the connection + * is not established yet. le_conn_complete_evt() reports it once the + * connection completes and the identity address has been resolved. + */ conn->sec_level = BT_SECURITY_LOW; conn->conn_timeout = conn_timeout; conn->le_adv_phy = phy; diff --git a/net/bluetooth/hci_core.c b/net/bluetooth/hci_core.c index 74d9865e08c2..209244fd9391 100644 --- a/net/bluetooth/hci_core.c +++ b/net/bluetooth/hci_core.c @@ -1153,16 +1153,16 @@ struct smp_ltk *hci_find_ltk(struct hci_dev *hdev, bdaddr_t *bdaddr, continue; 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); + rcu_read_unlock(); return NULL; } + rcu_read_unlock(); return k; } } @@ -1617,7 +1617,7 @@ int hci_remove_adv_instance(struct hci_dev *hdev, u8 instance) if (hdev->cur_adv_instance == instance) { if (hdev->adv_instance_timeout) { cancel_delayed_work(&hdev->adv_instance_expire); - hdev->adv_instance_timeout = 0; + hdev->adv_instance_timeout = false; } hdev->cur_adv_instance = 0x00; } @@ -1647,7 +1647,7 @@ void hci_adv_instances_clear(struct hci_dev *hdev) if (hdev->adv_instance_timeout) { disable_delayed_work(&hdev->adv_instance_expire); - hdev->adv_instance_timeout = 0; + hdev->adv_instance_timeout = false; } list_for_each_entry_safe(adv_instance, n, &hdev->adv_instances, list) { @@ -2437,7 +2437,7 @@ struct hci_dev *hci_alloc_dev_priv(int sizeof_priv) hdev->adv_tx_power = HCI_TX_POWER_INVALID; hdev->adv_instance_cnt = 0; hdev->cur_adv_instance = 0x00; - hdev->adv_instance_timeout = 0; + hdev->adv_instance_timeout = false; hdev->advmon_allowlist_duration = 300; hdev->advmon_no_filter_duration = 500; @@ -2929,6 +2929,8 @@ int hci_recv_frame(struct hci_dev *hdev, struct sk_buff *skb) break; case HCI_ISODATA_PKT: break; + case HCI_VENDOR_PKT: + break; case HCI_DRV_PKT: break; default: @@ -3065,6 +3067,41 @@ static int hci_send_conn_frame(struct hci_dev *hdev, struct hci_conn *conn, return hci_send_frame(hdev, skb); } +/** + * hci_send_vendor_frame - Send an HCI_VENDOR_PKT frame to the HCI driver + * @hdev: The HCI device + * @iter: iov_iter carrying the frame + * + * Return: 0 on success, or a negative errno on failure. + */ +int hci_send_vendor_frame(struct hci_dev *hdev, struct iov_iter *iter) +{ + struct sk_buff *skb; + unsigned int len; + + if (WARN_ON(!iov_iter_is_kvec(iter))) + return -EINVAL; + + /* Vendor frames are opaque, the caller guarantees the size. */ + len = (unsigned int)iov_iter_count(iter); + if (!len) + return -EINVAL; + + skb = bt_skb_alloc(len, GFP_KERNEL); + if (!skb) + return -ENOMEM; + + if (!copy_from_iter_full(skb_put(skb, len), len, iter)) { + kfree_skb(skb); + return -EFAULT; + } + + hci_skb_pkt_type(skb) = HCI_VENDOR_PKT; + + return hci_send_frame(hdev, skb); +} +EXPORT_SYMBOL(hci_send_vendor_frame); + /* Send HCI command */ int hci_send_cmd(struct hci_dev *hdev, __u16 opcode, __u32 plen, const void *param) @@ -4102,6 +4139,14 @@ static void hci_rx_work(struct work_struct *work) hci_isodata_packet(hdev, skb); break; + case HCI_VENDOR_PKT: + BT_DBG("%s Vendor packet", hdev->name); + if (hdev->recv_vendor_pkt) + hdev->recv_vendor_pkt(hdev, skb); + else + kfree_skb(skb); + break; + default: kfree_skb(skb); break; @@ -4123,7 +4168,7 @@ static int hci_send_cmd_sync(struct hci_dev *hdev, struct sk_buff *skb) if (!hdev->sent_cmd) { skb_queue_head(&hdev->cmd_q, skb); queue_work(hdev->workqueue, &hdev->cmd_work); - return -EINVAL; + return -ENOMEM; } if (hci_skb_opcode(skb) != HCI_OP_NOP) { diff --git a/net/bluetooth/hci_debugfs.c b/net/bluetooth/hci_debugfs.c index 2559fb6324d6..cd5ef398f238 100644 --- a/net/bluetooth/hci_debugfs.c +++ b/net/bluetooth/hci_debugfs.c @@ -65,6 +65,7 @@ static ssize_t __name ## _write(struct file *file, \ } \ \ static const struct file_operations __name ## _fops = { \ + .owner = THIS_MODULE, \ .open = simple_open, \ .read = __name ## _read, \ .write = __name ## _write, \ @@ -283,6 +284,7 @@ static ssize_t use_debug_keys_read(struct file *file, char __user *user_buf, } static const struct file_operations use_debug_keys_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = use_debug_keys_read, .llseek = default_llseek, @@ -301,6 +303,7 @@ static ssize_t sc_only_mode_read(struct file *file, char __user *user_buf, } static const struct file_operations sc_only_mode_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = sc_only_mode_read, .llseek = default_llseek, @@ -437,6 +440,7 @@ static ssize_t ssp_debug_mode_read(struct file *file, char __user *user_buf, } static const struct file_operations ssp_debug_mode_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = ssp_debug_mode_read, .llseek = default_llseek, @@ -529,6 +533,7 @@ static ssize_t force_bredr_smp_write(struct file *file, } static const struct file_operations force_bredr_smp_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_bredr_smp_read, .write = force_bredr_smp_write, @@ -778,6 +783,7 @@ static ssize_t force_static_address_write(struct file *file, } static const struct file_operations force_static_address_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_static_address_read, .write = force_static_address_write, @@ -1177,6 +1183,7 @@ static ssize_t force_no_mitm_write(struct file *file, } static const struct file_operations force_no_mitm_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = force_no_mitm_read, .write = force_no_mitm_write, @@ -1315,6 +1322,7 @@ static ssize_t dut_mode_write(struct file *file, const char __user *user_buf, } static const struct file_operations dut_mode_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = dut_mode_read, .write = dut_mode_write, @@ -1371,6 +1379,7 @@ done: } static const struct file_operations vendor_diag_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = vendor_diag_read, .write = vendor_diag_write, diff --git a/net/bluetooth/hci_event.c b/net/bluetooth/hci_event.c index 2f5e21ff9752..1f80f2cf6b2c 100644 --- a/net/bluetooth/hci_event.c +++ b/net/bluetooth/hci_event.c @@ -404,10 +404,7 @@ static u8 hci_cc_write_auth_enable(struct hci_dev *hdev, void *data, if (!rp->status) { __u8 param = *((__u8 *) sent); - if (param == AUTH_ENABLED) - set_bit(HCI_AUTH, &hdev->flags); - else - clear_bit(HCI_AUTH, &hdev->flags); + assign_bit(HCI_AUTH, &hdev->flags, param == AUTH_ENABLED); } if (hci_dev_test_flag(hdev, HCI_MGMT)) @@ -436,10 +433,7 @@ static u8 hci_cc_write_encrypt_mode(struct hci_dev *hdev, void *data, param = *((__u8 *) sent); - if (param) - set_bit(HCI_ENCRYPT, &hdev->flags); - else - clear_bit(HCI_ENCRYPT, &hdev->flags); + assign_bit(HCI_ENCRYPT, &hdev->flags, param); return rp->status; } @@ -466,15 +460,9 @@ static u8 hci_cc_write_scan_enable(struct hci_dev *hdev, void *data, goto done; } - if (param & SCAN_INQUIRY) - set_bit(HCI_ISCAN, &hdev->flags); - else - clear_bit(HCI_ISCAN, &hdev->flags); + assign_bit(HCI_ISCAN, &hdev->flags, param & SCAN_INQUIRY); - if (param & SCAN_PAGE) - set_bit(HCI_PSCAN, &hdev->flags); - else - clear_bit(HCI_PSCAN, &hdev->flags); + assign_bit(HCI_PSCAN, &hdev->flags, param & SCAN_PAGE); done: hci_dev_unlock(hdev); @@ -744,6 +732,14 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data, bt_dev_err(hdev, "failed to read key size for handle %u", handle); conn->enc_key_size = 0; + clear_bit(HCI_CONN_ENCRYPT, &conn->flags); + clear_bit(HCI_CONN_AES_CCM, &conn->flags); + /* Downgrade to reflect the connection no longer being + * encrypted, instead of advertising a stale elevated + * security level alongside MGMT_CONN_SEC_ENCRYPT_NONE. + */ + if (conn->sec_level > BT_SECURITY_LOW) + conn->sec_level = BT_SECURITY_LOW; } else { u8 *key_enc_size = hci_conn_key_enc_size(conn); @@ -767,6 +763,25 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data, status = HCI_ERROR_AUTH_FAILURE; clear_bit(HCI_CONN_ENCRYPT, &conn->flags); clear_bit(HCI_CONN_AES_CCM, &conn->flags); + /* Downgrade to reflect the connection no longer being + * encrypted, instead of advertising a stale elevated + * security level alongside MGMT_CONN_SEC_ENCRYPT_NONE. + */ + if (conn->sec_level > BT_SECURITY_LOW) + conn->sec_level = BT_SECURITY_LOW; + } else { + /* Pre-apply hci_encrypt_cfm()'s own upgrade rules + * here unconditionally on success, so its internal + * change check below always finds nothing new: this + * function remains the sole place deciding whether + * and when to report the change, regardless of + * whether the caller already touched conn->sec_level + * (e.g. hci_encrypt_change_evt()) or not. + */ + if (conn->sec_level == BT_SECURITY_SDP) + conn->sec_level = BT_SECURITY_LOW; + if (conn->pending_sec_level > conn->sec_level) + conn->sec_level = conn->pending_sec_level; } /* Update the key encryption size with the connection one */ @@ -776,6 +791,13 @@ static u8 hci_cc_read_enc_key_size(struct hci_dev *hdev, void *data, hci_encrypt_cfm(conn, status); + /* mgmt_security_level_changed() only reports the change for + * connections already announced to userspace (it checks + * HCI_CONN_MGMT_CONNECTED itself); otherwise it is a no-op here and + * reporting is deferred to mgmt_device_connected(). + */ + mgmt_security_level_changed(conn); + done: hci_dev_unlock(hdev); @@ -1247,8 +1269,6 @@ static u8 hci_cc_le_read_conn_interval(struct hci_dev *hdev, void *data, struct sk_buff *skb) { struct hci_rp_le_read_conn_interval *rp = data; - u16 min_interval = 0; - int i; bt_dev_dbg(hdev, "status 0x%2.2x", rp->status); @@ -1261,17 +1281,11 @@ static u8 hci_cc_le_read_conn_interval(struct hci_dev *hdev, void *data, return HCI_ERROR_UNSPECIFIED; } - /* Store the smallest minimum supported connection interval reported by - * the controller so the default rate parameters can be clamped to it. + /* Store the minimum supported connection interval so the default rate + * parameters can be clamped to it. It is reported on its own rather + * than derived from the groups, as there may be none. */ - for (i = 0; i < rp->num_grps; i++) { - u16 min = le16_to_cpu(rp->grps[i].min); - - if (!min_interval || min < min_interval) - min_interval = min; - } - - hdev->le_min_rate_interval = min_interval; + hdev->le_min_rate_interval = rp->min; return rp->status; } @@ -1617,6 +1631,39 @@ static u8 hci_cc_le_set_adv_enable(struct hci_dev *hdev, void *data, return rp->status; } +/* Update the enabled state of the instance(s) using the advertising set + * identified by handle. + * + * Instances may share handle 0x00 with instance 0 (Global Advertising), e.g. + * when the controller supports a single advertising set, in which case the + * set is owned by the instance last enabled (hdev->cur_adv_instance) and any + * other instance sharing it shall be considered disabled. + */ +static void hci_le_ext_adv_set_enabled(struct hci_dev *hdev, u8 handle, + bool enable) +{ + struct adv_info *adv; + bool owned = false; + + list_for_each_entry(adv, &hdev->adv_instances, list) { + if (adv->handle != handle) + continue; + + adv->enabled = enable && + (handle || + adv->instance == hdev->cur_adv_instance); + owned |= adv->enabled; + } + + if (handle) + return; + + if (enable && !owned) + hci_dev_set_flag(hdev, HCI_LE_ADV_0); + else + hci_dev_clear_flag(hdev, HCI_LE_ADV_0); +} + static u8 hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, void *data, struct sk_buff *skb) { @@ -1638,18 +1685,13 @@ static u8 hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, void *data, hci_dev_lock(hdev); - if (cp->num_of_sets) - adv = hci_find_adv_instance(hdev, set->handle); - if (cp->enable) { struct hci_conn *conn; hci_dev_set_flag(hdev, HCI_LE_ADV); - if (adv) - adv->enabled = true; - else if (!set->handle) - hci_dev_set_flag(hdev, HCI_LE_ADV_0); + if (cp->num_of_sets) + hci_le_ext_adv_set_enabled(hdev, set->handle, true); conn = hci_lookup_le_connect(hdev); if (conn) @@ -1658,21 +1700,25 @@ static u8 hci_cc_le_set_ext_adv_enable(struct hci_dev *hdev, void *data, conn->conn_timeout); } else { if (cp->num_of_sets) { - if (adv) - adv->enabled = false; - else if (!set->handle) - hci_dev_clear_flag(hdev, HCI_LE_ADV_0); + hci_le_ext_adv_set_enabled(hdev, set->handle, false); /* If just one instance was disabled check if there are - * any other instance enabled before clearing HCI_LE_ADV + * any other instance enabled, including instance 0, + * before clearing HCI_LE_ADV */ + if (hci_dev_test_flag(hdev, HCI_LE_ADV_0)) + goto unlock; + list_for_each_entry_safe(adv, n, &hdev->adv_instances, list) { if (adv->enabled) goto unlock; } } else { - /* All instances shall be considered disabled */ + /* All instances shall be considered disabled, except + * instance 0 whose state is preserved so it can be + * re-enabled by hci_resume_advertising_sync. + */ list_for_each_entry_safe(adv, n, &hdev->adv_instances, list) adv->enabled = false; @@ -2774,7 +2820,11 @@ static void hci_cs_disconnect(struct hci_dev *hdev, u8 status) if (hdev->suspended) conn->state = BT_CLOSED; - mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); + /* Only peek at the flag here: hci_conn_del() (via hci_conn_unlink()) + * still needs it set to know whether to report the security level + * reset, so it is consumed there instead of here. + */ + mgmt_conn = test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); if (conn->type == ACL_LINK) { if (test_and_clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags)) @@ -2957,8 +3007,25 @@ static void hci_cs_le_read_remote_features(struct hci_dev *hdev, u8 status) hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); - if (conn && conn->state == BT_CONFIG) + if (conn && conn->state == BT_CONFIG) { + /* If the local controller supports peripheral-initiated + * features exchange, but the remote controller does not, + * then the controller may already return the error code + * 0x1a for unsupported remote feature in the command + * status. + * + * Handle it as hci_le_remote_feat_complete_evt() does and + * allow the connection to transition into connected state. + */ + if (!conn->out && + status == HCI_ERROR_UNSUPPORTED_REMOTE_FEATURE && + (hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES)) { + conn->state = BT_CONNECTED; + status = 0x00; + } + hci_connect_cfm(conn, status); + } hci_dev_unlock(hdev); } @@ -3378,6 +3445,16 @@ static void hci_conn_request_evt(struct hci_dev *hdev, void *data, bt_dev_err(hdev, "connection err: %ld", PTR_ERR(conn)); goto unlock; } + + /* Unlike outgoing BR/EDR connections, conn->sec_level is not + * set at connection request time for incoming connections, + * so it is still at its zero-initialized value + * (BT_SECURITY_SDP) here. Set it to BT_SECURITY_LOW so + * mgmt_device_connected() later reports the correct initial + * security level instead of a transient, never-really-in-use + * SDP value. + */ + conn->sec_level = BT_SECURITY_LOW; } memcpy(conn->dev_class, ev->dev_class, 3); @@ -3444,7 +3521,11 @@ static void hci_disconn_complete_evt(struct hci_dev *hdev, void *data, conn->state = BT_CLOSED; - mgmt_connected = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); + /* Only peek at the flag here: hci_conn_del() (via hci_conn_unlink()) + * still needs it set to know whether to report the security level + * reset, so it is consumed there instead of here. + */ + mgmt_connected = test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags); if (test_bit(HCI_CONN_AUTH_FAILURE, &conn->flags)) reason = MGMT_DEV_DISCONN_AUTH_FAILURE; @@ -3528,6 +3609,15 @@ static void hci_auth_complete_evt(struct hci_dev *hdev, void *data, if (!ev->status) { clear_bit(HCI_CONN_AUTH_FAILURE, &conn->flags); set_bit(HCI_CONN_AUTH, &conn->flags); + /* Authentication alone does not imply encryption: for SSP + * capable devices, encryption is only requested below, and + * for legacy devices it is requested by a separate + * HCI_OP_SET_CONN_ENCRYPT command. Do not report the new + * security level yet, to avoid userspace seeing an elevated + * level alongside no encryption; hci_encrypt_change_evt() + * (possibly via hci_cc_read_enc_key_size() for ACL links) + * reports it once encryption is actually confirmed. + */ conn->sec_level = conn->pending_sec_level; } else { if (ev->status == HCI_ERROR_PIN_OR_KEY_MISSING) @@ -3644,9 +3734,28 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data, if ((conn->type == ACL_LINK && ev->encrypt == 0x02) || conn->type == LE_LINK) set_bit(HCI_CONN_AES_CCM, &conn->flags); + + /* For ACL links the encryption key size is still + * validated below via hci_read_enc_key_size(). Its + * completion handler, hci_cc_read_enc_key_size(), + * reports the final security level so userspace does + * not see a transient "encrypted" state that a + * key-size downgrade would immediately invalidate. + */ + if (conn->type != ACL_LINK) + mgmt_security_level_changed(conn); } else { clear_bit(HCI_CONN_ENCRYPT, &conn->flags); clear_bit(HCI_CONN_AES_CCM, &conn->flags); + /* Elevated security levels (MEDIUM and above) require + * encryption, so downgrade to reflect the connection + * no longer being encrypted before reporting, instead + * of advertising a stale elevated level alongside + * MGMT_CONN_SEC_ENCRYPT_NONE. + */ + if (conn->sec_level > BT_SECURITY_LOW) + conn->sec_level = BT_SECURITY_LOW; + mgmt_security_level_changed(conn); } } @@ -3679,8 +3788,14 @@ static void hci_encrypt_change_evt(struct hci_dev *hdev, void *data, /* Try reading the encryption key size for encrypted ACL links */ if (!ev->status && ev->encrypt && conn->type == ACL_LINK) { - if (hci_read_enc_key_size(hdev, conn)) + if (hci_read_enc_key_size(hdev, conn)) { + /* Could not even issue the key-size read: report the + * security level now since hci_cc_read_enc_key_size() + * will not run to do it. + */ + mgmt_security_level_changed(conn); goto notify; + } goto unlock; } @@ -4007,8 +4122,17 @@ static void hci_cs_le_read_all_remote_features(struct hci_dev *hdev, u8 status) hci_dev_lock(hdev); conn = hci_conn_hash_lookup_handle(hdev, __le16_to_cpu(cp->handle)); - if (conn && conn->state == BT_CONFIG) + if (conn && conn->state == BT_CONFIG) { + /* See hci_cs_le_read_remote_features() */ + if (!conn->out && + status == HCI_ERROR_UNSUPPORTED_REMOTE_FEATURE && + (hdev->le_features[0] & HCI_LE_PERIPHERAL_FEATURES)) { + conn->state = BT_CONNECTED; + status = 0x00; + } + hci_connect_cfm(conn, status); + } hci_dev_unlock(hdev); } @@ -4099,6 +4223,9 @@ unlock: #define HCI_CC_STATUS(_op, _func) \ HCI_CC(_op, _func, sizeof(struct hci_ev_status)) +#define HCI_MAX_CC_PLEN \ + (HCI_MAX_EVENT_PLEN - sizeof(struct hci_ev_cmd_complete)) + static const struct hci_cc { u16 op; u8 (*func)(struct hci_dev *hdev, void *data, struct sk_buff *skb); @@ -4192,7 +4319,7 @@ static const struct hci_cc { sizeof(struct hci_rp_le_read_local_features)), HCI_CC_VL(HCI_OP_LE_READ_CONN_INTERVAL, hci_cc_le_read_conn_interval, sizeof(struct hci_rp_le_read_conn_interval), - HCI_MAX_EVENT_SIZE), + HCI_MAX_CC_PLEN), HCI_CC(HCI_OP_LE_READ_ADV_TX_POWER, hci_cc_le_read_adv_tx_power, sizeof(struct hci_rp_le_read_adv_tx_power)), HCI_CC(HCI_OP_USER_CONFIRM_REPLY, hci_cc_user_confirm_reply, @@ -4264,7 +4391,7 @@ static const struct hci_cc { HCI_CC(HCI_OP_LE_READ_BUFFER_SIZE_V2, hci_cc_le_read_buffer_size_v2, sizeof(struct hci_rp_le_read_buffer_size_v2)), HCI_CC_VL(HCI_OP_LE_SET_CIG_PARAMS, hci_cc_le_set_cig_params, - sizeof(struct hci_rp_le_set_cig_params), HCI_MAX_EVENT_SIZE), + sizeof(struct hci_rp_le_set_cig_params), HCI_MAX_CC_PLEN), HCI_CC(HCI_OP_LE_SETUP_ISO_PATH, hci_cc_le_setup_iso_path, sizeof(struct hci_rp_le_setup_iso_path)), HCI_CC(HCI_OP_LE_READ_ALL_LOCAL_FEATURES, @@ -4611,10 +4738,8 @@ static void hci_mode_change_evt(struct hci_dev *hdev, void *data, if (!test_and_clear_bit(HCI_CONN_MODE_CHANGE_PEND, &conn->flags)) { - if (conn->mode == HCI_CM_ACTIVE) - set_bit(HCI_CONN_POWER_SAVE, &conn->flags); - else - clear_bit(HCI_CONN_POWER_SAVE, &conn->flags); + assign_bit(HCI_CONN_POWER_SAVE, &conn->flags, + conn->mode == HCI_CM_ACTIVE); } if (test_and_clear_bit(HCI_CONN_SCO_SETUP_PEND, &conn->flags)) @@ -4814,10 +4939,7 @@ static void hci_link_key_notify_evt(struct hci_dev *hdev, void *data, goto unlock; } - if (persistent) - clear_bit(HCI_CONN_FLUSH_KEY, &conn->flags); - else - set_bit(HCI_CONN_FLUSH_KEY, &conn->flags); + assign_bit(HCI_CONN_FLUSH_KEY, &conn->flags, !persistent); unlock: hci_dev_unlock(hdev); @@ -5242,8 +5364,14 @@ static void hci_key_refresh_complete_evt(struct hci_dev *hdev, void *data, if (conn->type != LE_LINK) goto unlock; - if (!ev->status) + if (!ev->status) { + bool sec_level_changed = + conn->sec_level != conn->pending_sec_level; + conn->sec_level = conn->pending_sec_level; + if (sec_level_changed) + mgmt_security_level_changed(conn); + } clear_bit(HCI_CONN_ENCRYPT_PEND, &conn->flags); @@ -5872,9 +6000,16 @@ static void le_conn_complete_evt(struct hci_dev *hdev, u8 status, goto unlock; } + /* Unlike outgoing BR/EDR connections, conn->sec_level is not set at + * connection request time for LE, so it is still at its + * zero-initialized value (BT_SECURITY_SDP) here. Set it to + * BT_SECURITY_LOW before reporting the connection so + * mgmt_device_connected() reports the correct initial security level + * instead of a transient, never-really-in-use SDP value. + */ + conn->sec_level = BT_SECURITY_LOW; mgmt_device_connected(hdev, conn, NULL, 0); - conn->sec_level = BT_SECURITY_LOW; conn->state = BT_CONFIG; /* Store current advertising instance as connection advertising instance @@ -6311,6 +6446,15 @@ static void process_adv_report(struct hci_dev *hdev, u8 type, bdaddr_t *bdaddr, if (irk) { bdaddr = &irk->bdaddr; bdaddr_type = irk->addr_type; + } else { + /* The peer is on air with its identity address, so whatever + * RPA is cached for it has been abandoned. Drop it, or + * hci_connect_le() would swap it back in and dial an address + * the peer no longer answers. + */ + irk = hci_find_irk_by_addr(hdev, bdaddr, bdaddr_type); + if (irk) + bacpy(&irk->rpa, BDADDR_ANY); } bdaddr_type = ev_bdaddr_type(hdev, bdaddr_type, &bdaddr_resolved); @@ -7316,8 +7460,13 @@ static void hci_le_big_sync_lost_evt(struct hci_dev *hdev, void *data, BT_CONNECTED, HCI_ROLE_SLAVE))) { if (!mgmt_conn) { - mgmt_conn = test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, - &bis->flags); + /* Only peek at the flag here: hci_conn_del() (via + * hci_conn_unlink()) still needs it set to know + * whether to report the security level reset, so + * it is consumed there instead of here. + */ + mgmt_conn = test_bit(HCI_CONN_MGMT_CONNECTED, + &bis->flags); mgmt_device_disconnected(hdev, &bis->dst, bis->type, bis->dst_type, ev->reason, mgmt_conn); @@ -7465,6 +7614,9 @@ static void hci_le_conn_rate_change_evt(struct hci_dev *hdev, void *data, #define HCI_LE_EV_STATUS(_op, _func) \ HCI_LE_EV(_op, _func, sizeof(struct hci_ev_status)) +#define HCI_MAX_LE_SUBEVT_PLEN \ + (HCI_MAX_EVENT_PLEN - sizeof(struct hci_ev_le_meta)) + /* Entries in this table shall have their position according to the subevent * opcode they handle so the use of the macros above is recommend since it does * attempt to initialize at its proper index using Designated Initializers that @@ -7481,7 +7633,7 @@ static const struct hci_le_ev { /* [0x02 = HCI_EV_LE_ADVERTISING_REPORT] */ HCI_LE_EV_VL(HCI_EV_LE_ADVERTISING_REPORT, hci_le_adv_report_evt, sizeof(struct hci_ev_le_advertising_report), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x03 = HCI_EV_LE_CONN_UPDATE_COMPLETE] */ HCI_LE_EV(HCI_EV_LE_CONN_UPDATE_COMPLETE, hci_le_conn_update_complete_evt, @@ -7504,14 +7656,14 @@ static const struct hci_le_ev { /* [0x0b = HCI_EV_LE_DIRECT_ADV_REPORT] */ HCI_LE_EV_VL(HCI_EV_LE_DIRECT_ADV_REPORT, hci_le_direct_adv_report_evt, sizeof(struct hci_ev_le_direct_adv_report), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x0c = HCI_EV_LE_PHY_UPDATE_COMPLETE] */ HCI_LE_EV(HCI_EV_LE_PHY_UPDATE_COMPLETE, hci_le_phy_update_evt, sizeof(struct hci_ev_le_phy_update_complete)), /* [0x0d = HCI_EV_LE_EXT_ADV_REPORT] */ HCI_LE_EV_VL(HCI_EV_LE_EXT_ADV_REPORT, hci_le_ext_adv_report_evt, sizeof(struct hci_ev_le_ext_adv_report), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x0e = HCI_EV_LE_PA_SYNC_ESTABLISHED] */ HCI_LE_EV(HCI_EV_LE_PA_SYNC_ESTABLISHED, hci_le_pa_sync_established_evt, @@ -7520,7 +7672,7 @@ static const struct hci_le_ev { HCI_LE_EV_VL(HCI_EV_LE_PER_ADV_REPORT, hci_le_per_adv_report_evt, sizeof(struct hci_ev_le_per_adv_report), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x10 = HCI_EV_LE_PA_SYNC_LOST] */ HCI_LE_EV(HCI_EV_LE_PA_SYNC_LOST, hci_le_pa_sync_lost_evt, sizeof(struct hci_ev_le_pa_sync_lost)), @@ -7541,28 +7693,28 @@ static const struct hci_le_ev { HCI_LE_EV_VL(HCI_EVT_LE_CREATE_BIG_COMPLETE, hci_le_create_big_complete_evt, sizeof(struct hci_evt_le_create_big_complete), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x1d = HCI_EV_LE_BIG_SYNC_ESTABLISHED] */ HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_ESTABLISHED, hci_le_big_sync_established_evt, sizeof(struct hci_evt_le_big_sync_established), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x1e = HCI_EVT_LE_BIG_SYNC_LOST] */ HCI_LE_EV_VL(HCI_EVT_LE_BIG_SYNC_LOST, hci_le_big_sync_lost_evt, sizeof(struct hci_evt_le_big_sync_lost), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x22 = HCI_EVT_LE_BIG_INFO_ADV_REPORT] */ HCI_LE_EV_VL(HCI_EVT_LE_BIG_INFO_ADV_REPORT, hci_le_big_info_adv_report_evt, sizeof(struct hci_evt_le_big_info_adv_report), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x2b = HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE] */ HCI_LE_EV_VL(HCI_EVT_LE_ALL_REMOTE_FEATURES_COMPLETE, hci_le_read_all_remote_features_evt, sizeof(struct hci_evt_le_read_all_remote_features_complete), - HCI_MAX_EVENT_SIZE), + HCI_MAX_LE_SUBEVT_PLEN), /* [0x37 = HCI_EVT_LE_CONN_RATE_CHANGE] */ HCI_LE_EV(HCI_EVT_LE_CONN_RATE_CHANGE, hci_le_conn_rate_change_evt, sizeof(struct hci_evt_le_conn_rate_change)), diff --git a/net/bluetooth/hci_h4.c b/net/bluetooth/hci_h4.c new file mode 100644 index 000000000000..86f809018062 --- /dev/null +++ b/net/bluetooth/hci_h4.c @@ -0,0 +1,160 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Bluetooth HCI H:4 packet reassembly + * + * Copyright (C) 2000-2001 Qualcomm Incorporated + * Copyright (C) 2002-2003 Maxim Krasnyansky <maxk@qualcomm.com> + * Copyright (C) 2004-2005 Marcel Holtmann <marcel@holtmann.org> + */ + +#include <linux/export.h> +#include <linux/skbuff.h> +#include <linux/unaligned.h> + +#include <net/bluetooth/bluetooth.h> +#include <net/bluetooth/hci_core.h> +#include <net/bluetooth/hci_h4.h> + +/* h4_recv_skb - Reassemble H:4 framed packets + * @hdev: HCI device the packets are received on + * @alignment: optional packet alignment, NULL or 0 means no alignment + * @padding: optional padding state carried over between calls + * @skb: partially received packet from a previous call, may be NULL or an + * ERR_PTR returned by a previous call + * @buffer: buffer holding the received data + * @count: number of bytes in @buffer + * @pkts: table of supported packet types + * @pkts_count: number of entries in @pkts + * + * Returns the partially received packet to be passed to the next call, or an + * ERR_PTR on error. The returned value can be fed back into this function as + * is, but must be checked with IS_ERR() before being freed. + */ +struct sk_buff *h4_recv_skb(struct hci_dev *hdev, u8 *alignment, u8 *padding, + struct sk_buff *skb, const unsigned char *buffer, + int count, const struct h4_recv_pkt *pkts, + int pkts_count) +{ + u8 align = alignment && *alignment ? *alignment : 1; + + /* Check for error from previous call */ + if (IS_ERR(skb)) + skb = NULL; + + while (count) { + int i, len; + + /* remove padding bytes from buffer */ + if (padding) { + for (; (*padding) && count > 0; (*padding)--) { + count--; + buffer++; + } + } + + if (!count) + break; + + if (!skb) { + for (i = 0; i < pkts_count; i++) { + if (buffer[0] != pkts[i].type) + continue; + + skb = bt_skb_alloc(pkts[i].maxlen, + GFP_ATOMIC); + if (!skb) + return ERR_PTR(-ENOMEM); + + hci_skb_pkt_type(skb) = pkts[i].type; + hci_skb_expect(skb) = pkts[i].hlen; + break; + } + + /* Check for invalid packet type */ + if (!skb) + return ERR_PTR(-EILSEQ); + + count -= 1; + buffer += 1; + } + + len = min_t(uint, hci_skb_expect(skb) - skb->len, count); + skb_put_data(skb, buffer, len); + + count -= len; + buffer += len; + + /* Check for partial packet */ + if (skb->len < hci_skb_expect(skb)) + continue; + + for (i = 0; i < pkts_count; i++) { + if (hci_skb_pkt_type(skb) == pkts[i].type) + break; + } + + if (i >= pkts_count) { + kfree_skb(skb); + return ERR_PTR(-EILSEQ); + } + + if (skb->len == pkts[i].hlen) { + u16 dlen; + + switch (pkts[i].lsize) { + case 0: + /* No variable data length */ + dlen = 0; + break; + case 1: + /* Single octet variable length */ + dlen = skb->data[pkts[i].loff]; + hci_skb_expect(skb) += dlen; + + if (skb_tailroom(skb) < dlen) { + kfree_skb(skb); + return ERR_PTR(-EMSGSIZE); + } + break; + case 2: + /* Double octet variable length */ + dlen = get_unaligned_le16(skb->data + + pkts[i].loff); + hci_skb_expect(skb) += dlen; + + if (skb_tailroom(skb) < dlen) { + kfree_skb(skb); + return ERR_PTR(-EMSGSIZE); + } + break; + default: + /* Unsupported variable length */ + kfree_skb(skb); + return ERR_PTR(-EILSEQ); + } + + if (!dlen) { + if (padding) { + *padding = (skb->len + 1) % align; + *padding = (align - *padding) % align; + } + + /* No more data, complete frame */ + pkts[i].recv(hdev, skb); + skb = NULL; + } + } else { + if (padding) { + *padding = (skb->len + 1) % align; + *padding = (align - *padding) % align; + } + + /* Complete frame */ + pkts[i].recv(hdev, skb); + skb = NULL; + } + } + + return skb; +} +EXPORT_SYMBOL_GPL(h4_recv_skb); diff --git a/net/bluetooth/hci_sock.c b/net/bluetooth/hci_sock.c index ec45b531e387..3da994d1fe65 100644 --- a/net/bluetooth/hci_sock.c +++ b/net/bluetooth/hci_sock.c @@ -244,6 +244,7 @@ void hci_send_to_sock(struct hci_dev *hdev, struct sk_buff *skb) hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && hci_skb_pkt_type(skb) != HCI_ISODATA_PKT && + hci_skb_pkt_type(skb) != HCI_VENDOR_PKT && hci_skb_pkt_type(skb) != HCI_DRV_PKT) continue; } else { @@ -401,6 +402,12 @@ void hci_send_to_monitor(struct hci_dev *hdev, struct sk_buff *skb) else opcode = cpu_to_le16(HCI_MON_ISO_TX_PKT); break; + case HCI_VENDOR_PKT: + if (bt_cb(skb)->incoming) + opcode = cpu_to_le16(HCI_MON_VENDOR_RX_PKT); + else + opcode = cpu_to_le16(HCI_MON_VENDOR_TX_PKT); + break; case HCI_DRV_PKT: if (bt_cb(skb)->incoming) opcode = cpu_to_le16(HCI_MON_DRV_RX_PKT); @@ -1881,6 +1888,7 @@ static int hci_sock_sendmsg(struct socket *sock, struct msghdr *msg, hci_skb_pkt_type(skb) != HCI_ACLDATA_PKT && hci_skb_pkt_type(skb) != HCI_SCODATA_PKT && hci_skb_pkt_type(skb) != HCI_ISODATA_PKT && + hci_skb_pkt_type(skb) != HCI_VENDOR_PKT && hci_skb_pkt_type(skb) != HCI_DRV_PKT) { err = -EINVAL; goto drop; diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c index a92a81846e9d..03f706c1f815 100644 --- a/net/bluetooth/hci_sync.c +++ b/net/bluetooth/hci_sync.c @@ -470,7 +470,7 @@ static void reenable_adv(struct work_struct *work) static void cancel_adv_timeout(struct hci_dev *hdev) { if (hdev->adv_instance_timeout) { - hdev->adv_instance_timeout = 0; + hdev->adv_instance_timeout = false; cancel_delayed_work(&hdev->adv_instance_expire); } } @@ -570,7 +570,7 @@ static void adv_timeout_expire(struct work_struct *work) hci_dev_lock(hdev); - hdev->adv_instance_timeout = 0; + hdev->adv_instance_timeout = false; if (hdev->cur_adv_instance == 0x00) goto unlock; @@ -1158,14 +1158,38 @@ int hci_update_random_address_sync(struct hci_dev *hdev, bool require_privacy, return 0; } -static int hci_disable_ext_adv_legacy_instance_sync(struct hci_dev *hdev) +/* Check if the advertising set with handle 0x00 is in use, either by instance + * 0 or by an instance sharing its advertising set. + */ +static bool hci_ext_adv_handle_0_enabled(struct hci_dev *hdev) +{ + struct adv_info *adv; + bool enabled; + + hci_dev_lock(hdev); + + enabled = hci_dev_test_flag(hdev, HCI_LE_ADV_0); + + list_for_each_entry(adv, &hdev->adv_instances, list) { + if (!adv->handle && adv->enabled) { + enabled = true; + break; + } + } + + hci_dev_unlock(hdev); + + return enabled; +} + +int hci_disable_ext_adv_legacy_instance_sync(struct hci_dev *hdev) { struct hci_cp_le_set_ext_adv_enable *cp; struct hci_cp_ext_adv_set *set; u8 data[sizeof(*cp) + sizeof(*set) * 1]; u8 size; - if (!hci_dev_test_flag(hdev, HCI_LE_ADV_0)) + if (!hci_ext_adv_handle_0_enabled(hdev)) return 0; memset(data, 0, sizeof(data)); @@ -1411,6 +1435,9 @@ int hci_setup_ext_adv_instance_sync(struct hci_dev *hdev, u8 instance) return -EINVAL; } } else { + /* Disable the advertising set with handle 0x00, including any + * instance sharing it, since it is going to be overridden. + */ err = hci_disable_ext_adv_legacy_instance_sync(hdev); if (err) return err; @@ -1672,12 +1699,19 @@ int hci_enable_ext_advertising_sync(struct hci_dev *hdev, u8 instance) * scheduling it. */ if (adv && adv->timeout) { - u16 duration = adv->timeout * MSEC_PER_SEC; + u16 duration = adv->mesh ? adv->timeout : + adv->timeout * MSEC_PER_SEC; /* Time = N * 10 ms */ set->duration = cpu_to_le16(duration / 10); } + /* Track which instance owns the advertising set since the handle + * alone is ambiguous when instances share handle 0x00, see + * hci_cc_le_set_ext_adv_enable. + */ + hdev->cur_adv_instance = instance; + return __hci_cmd_sync_status(hdev, HCI_OP_LE_SET_EXT_ADV_ENABLE, sizeof(*cp) + sizeof(*set) * cp->num_of_sets, @@ -2100,10 +2134,11 @@ int hci_schedule_adv_instance_sync(struct hci_dev *hdev, u8 instance, /* Only use work for scheduling instances with legacy advertising */ if (!ext_adv_capable(hdev)) { - hdev->adv_instance_timeout = timeout; + hdev->adv_instance_timeout = true; queue_delayed_work(hdev->req_workqueue, &hdev->adv_instance_expire, - secs_to_jiffies(timeout)); + adv->mesh ? msecs_to_jiffies(timeout) : + secs_to_jiffies(timeout)); } /* If we're just re-scheduling the same instance again then do not @@ -2556,13 +2591,19 @@ static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev, if (!(params->flags & HCI_CONN_FLAG_DEVICE_PRIVACY)) return 0; + rcu_read_lock(); + irk = hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type); - if (!irk) + if (!irk) { + rcu_read_unlock(); return 0; + } memset(&cp, 0, sizeof(cp)); cp.bdaddr_type = irk->addr_type; bacpy(&cp.bdaddr, &irk->bdaddr); + rcu_read_unlock(); + cp.mode = HCI_DEVICE_PRIVACY; /* Note: params->privacy_mode is not updated since it is a copy */ @@ -2577,7 +2618,7 @@ static int hci_le_set_privacy_mode_sync(struct hci_dev *hdev, */ static int hci_le_add_accept_list_sync(struct hci_dev *hdev, struct conn_params *params, - u8 *num_entries) + u8 *num_entries, bool force_filter) { struct hci_cp_le_add_to_accept_list cp; int err; @@ -2590,6 +2631,11 @@ static int hci_le_add_accept_list_sync(struct hci_dev *hdev, return 0; } + /* Host-resolved peers need unfiltered scanning while awake. */ + if (!force_filter && !hdev->suspended && !ll_privacy_capable(hdev) && + hci_find_irk_by_addr(hdev, ¶ms->addr, params->addr_type)) + return -EINVAL; + /* Select filter policy to accept all advertising */ if (*num_entries >= hdev->le_accept_list_size) return -ENOSPC; @@ -2915,7 +2961,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) num_entries = 1; err = hci_le_add_accept_list_sync(hdev, &pa, - &num_entries); + &num_entries, true); goto done; } else { rcu_read_unlock(); @@ -2979,7 +3025,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) for (i = 0; i < n; ++i) { err = hci_le_add_accept_list_sync(hdev, ¶ms[i], - &num_entries); + &num_entries, false); if (err) { kvfree(params); goto done; @@ -3001,7 +3047,7 @@ static u8 hci_update_accept_list_sync(struct hci_dev *hdev) for (i = 0; i < n; ++i) { err = hci_le_add_accept_list_sync(hdev, ¶ms[i], - &num_entries); + &num_entries, false); if (err) { kvfree(params); goto done; @@ -5390,6 +5436,30 @@ static int hci_dev_init_sync(struct hci_dev *hdev) return ret; } +static void hci_dev_drop_last_cmd_req_and_close(struct hci_dev *hdev) +{ + /* Drop last sent command */ + if (hdev->sent_cmd) { + cancel_delayed_work_sync(&hdev->cmd_timer); + kfree_skb(hdev->sent_cmd); + hdev->sent_cmd = NULL; + } + + /* Drop last request */ + if (hdev->req_skb) { + kfree_skb(hdev->req_skb); + hdev->req_skb = NULL; + hci_dev_clear_flag(hdev, HCI_CMD_PENDING); + } + + clear_bit(HCI_RUNNING, &hdev->flags); + hci_sock_dev_event(hdev, HCI_DEV_CLOSE); + + /* After this point our queues are empty and no tasks are scheduled. */ + hdev->close(hdev); + hdev->flags &= BIT(HCI_RAW); +} + int hci_dev_open_sync(struct hci_dev *hdev) { int ret; @@ -5438,7 +5508,9 @@ int hci_dev_open_sync(struct hci_dev *hdev) goto done; } + hci_dev_lock(hdev); hci_devcd_reset(hdev); + hci_dev_unlock(hdev); set_bit(HCI_RUNNING, &hdev->flags); hci_sock_dev_event(hdev, HCI_DEV_OPEN); @@ -5476,23 +5548,7 @@ int hci_dev_open_sync(struct hci_dev *hdev) if (hdev->flush) hdev->flush(hdev); - if (hdev->sent_cmd) { - cancel_delayed_work_sync(&hdev->cmd_timer); - kfree_skb(hdev->sent_cmd); - hdev->sent_cmd = NULL; - } - - if (hdev->req_skb) { - kfree_skb(hdev->req_skb); - hdev->req_skb = NULL; - hci_dev_clear_flag(hdev, HCI_CMD_PENDING); - } - - clear_bit(HCI_RUNNING, &hdev->flags); - hci_sock_dev_event(hdev, HCI_DEV_CLOSE); - - hdev->close(hdev); - hdev->flags &= BIT(HCI_RAW); + hci_dev_drop_last_cmd_req_and_close(hdev); } done: @@ -5570,7 +5626,7 @@ int hci_dev_close_sync(struct hci_dev *hdev) if (hdev->adv_instance_timeout) { cancel_delayed_work_sync(&hdev->adv_instance_expire); - hdev->adv_instance_timeout = 0; + hdev->adv_instance_timeout = false; } err = hci_dev_shutdown(hdev); @@ -5659,28 +5715,10 @@ int hci_dev_close_sync(struct hci_dev *hdev) skb_queue_purge(&hdev->cmd_q); skb_queue_purge(&hdev->raw_q); - /* Drop last sent command */ - if (hdev->sent_cmd) { - cancel_delayed_work_sync(&hdev->cmd_timer); - kfree_skb(hdev->sent_cmd); - hdev->sent_cmd = NULL; - } - - /* Drop last request */ - if (hdev->req_skb) { - kfree_skb(hdev->req_skb); - hdev->req_skb = NULL; - hci_dev_clear_flag(hdev, HCI_CMD_PENDING); - } - - clear_bit(HCI_RUNNING, &hdev->flags); - hci_sock_dev_event(hdev, HCI_DEV_CLOSE); - - /* After this point our queues are empty and no tasks are scheduled. */ - hdev->close(hdev); + /* Drop last sent command, last request and close */ + hci_dev_drop_last_cmd_req_and_close(hdev); /* Clear flags */ - hdev->flags &= BIT(HCI_RAW); hci_dev_clear_volatile_flags(hdev); hci_dev_clear_flag(hdev, HCI_CMD_DRAIN_WORKQUEUE); diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c index d6ac5b1f49bc..c1fdd9846eeb 100644 --- a/net/bluetooth/iso.c +++ b/net/bluetooth/iso.c @@ -287,8 +287,11 @@ static void iso_chan_del(struct sock *sk, int err) parent = bt_sk(sk)->parent; if (parent) { + /* Unlinking the child allows the parent to be freed. */ + sock_hold(parent); bt_accept_unlink(sk); parent->sk_data_ready(parent); + sock_put(parent); } else { sk->sk_state_change(sk); } @@ -1974,10 +1977,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, if (err) break; - if (opt) - set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); - else - clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); + assign_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags, opt); break; case BT_PKT_STATUS: @@ -1985,10 +1985,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, if (err) break; - if (opt) - set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); - else - clear_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); + assign_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags, opt); break; case BT_PKT_SEQNUM: @@ -1996,10 +1993,7 @@ static int iso_sock_setsockopt(struct socket *sock, int level, int optname, if (err) break; - if (opt) - set_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags); - else - clear_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags); + assign_bit(BT_SK_PKT_SEQNUM, &bt_sk(sk)->flags, opt); break; case BT_ISO_QOS: diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c index aaa2a1cd489a..4dd56e0074fd 100644 --- a/net/bluetooth/l2cap_core.c +++ b/net/bluetooth/l2cap_core.c @@ -44,8 +44,8 @@ bool enable_ecred = IS_ENABLED(CONFIG_BT_LE_L2CAP_ECRED); static u32 l2cap_feat_mask = L2CAP_FEAT_FIXED_CHAN | L2CAP_FEAT_UCD; -static LIST_HEAD(chan_list); static DEFINE_RWLOCK(chan_list_lock); +static __guarded_by(&chan_list_lock) LIST_HEAD(chan_list); static struct sk_buff *l2cap_build_cmd(struct l2cap_conn *conn, u8 code, u8 ident, u16 dlen, void *data); @@ -59,6 +59,8 @@ static void l2cap_tx(struct l2cap_chan *chan, struct l2cap_ctrl *control, static void l2cap_retrans_timeout(struct work_struct *work); static void l2cap_monitor_timeout(struct work_struct *work); static void l2cap_ack_timeout(struct work_struct *work); +static void __l2cap_chan_close(struct l2cap_chan *chan, int reason) + __must_hold(&chan->lock) __must_hold(&chan->conn->lock); static inline u8 bdaddr_type(u8 link_type, u8 bdaddr_type) { @@ -86,6 +88,7 @@ static inline u8 bdaddr_dst_type(struct hci_conn *hcon) static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) + __must_hold(&conn->lock) { struct l2cap_chan *c; @@ -98,6 +101,7 @@ static struct l2cap_chan *__l2cap_get_chan_by_dcid(struct l2cap_conn *conn, static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) + __must_hold(&conn->lock) { struct l2cap_chan *c; @@ -109,45 +113,40 @@ static struct l2cap_chan *__l2cap_get_chan_by_scid(struct l2cap_conn *conn, } /* Find channel with given SCID. - * Returns a reference locked channel. + * Returns a reference. */ static struct l2cap_chan *l2cap_get_chan_by_scid(struct l2cap_conn *conn, u16 cid) + __must_hold(&conn->lock) { struct l2cap_chan *c; c = __l2cap_get_chan_by_scid(conn, cid); - if (c) { - /* Only lock if chan reference is not 0 */ + if (c) c = l2cap_chan_hold_unless_zero(c); - if (c) - l2cap_chan_lock(c); - } return c; } /* Find channel with given DCID. - * Returns a reference locked channel. + * Returns a reference. */ static struct l2cap_chan *l2cap_get_chan_by_dcid(struct l2cap_conn *conn, u16 cid) + __must_hold(&conn->lock) { struct l2cap_chan *c; c = __l2cap_get_chan_by_dcid(conn, cid); - if (c) { - /* Only lock if chan reference is not 0 */ + if (c) c = l2cap_chan_hold_unless_zero(c); - if (c) - l2cap_chan_lock(c); - } return c; } static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, u8 ident) + __must_hold(&conn->lock) { struct l2cap_chan *c; @@ -158,8 +157,32 @@ static struct l2cap_chan *__l2cap_get_chan_by_ident(struct l2cap_conn *conn, return NULL; } +/* Our connection request has been sent and is still outstanding */ +static bool l2cap_chan_connect_pending(struct l2cap_chan *chan) +{ + return chan->state == BT_CONNECT && + test_bit(CONF_CONNECT_PEND, &chan->conf_state); +} + +/* Other channels may hold the same ident for a response they still have + * to send, so only look at channels waiting for a connection response. + */ +static struct l2cap_chan *__l2cap_get_connect_chan_by_ident(struct l2cap_conn *conn, + u8 ident) + __must_hold(&conn->lock) +{ + struct l2cap_chan *c; + + list_for_each_entry(c, &conn->chan_l, list) { + if (c->ident == ident && l2cap_chan_connect_pending(c)) + return c; + } + return NULL; +} + static struct l2cap_chan *__l2cap_global_chan_by_addr(__le16 psm, bdaddr_t *src, u8 src_type) + __must_hold_shared(&chan_list_lock) { struct l2cap_chan *c; @@ -237,6 +260,7 @@ int l2cap_add_scid(struct l2cap_chan *chan, __u16 scid) } static u16 l2cap_alloc_cid(struct l2cap_conn *conn) + __must_hold(&conn->lock) { u16 cid, dyn_end; @@ -320,6 +344,10 @@ static int l2cap_seq_list_init(struct l2cap_seq_list *seq_list, u16 size) { size_t alloc_size, i; + /* roundup_pow_of_two(0) is undefined */ + if (!size) + return -EINVAL; + /* Allocated size is a power of 2 to map sequence numbers * (which may be up to 14 bits) in to a smaller array that is * sized for the negotiated ERTM transmit windows. @@ -430,7 +458,7 @@ static void l2cap_chan_timeout(struct work_struct *work) else reason = ETIMEDOUT; - l2cap_chan_close(chan, reason); + __l2cap_chan_close(chan, reason); chan->ops->close(chan); @@ -622,6 +650,10 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) BT_DBG("conn %p, psm 0x%2.2x, dcid 0x%4.4x", conn, __le16_to_cpu(chan->psm), chan->dcid); + /* Caller must ensure l2cap_chan is linked to l2cap_conn only once */ + if (WARN_ON_ONCE(chan->conn || test_bit(FLAG_DEL, &chan->flags))) + return; + conn->disc_reason = HCI_ERROR_REMOTE_USER_TERM; chan->conn = l2cap_conn_get(conn); @@ -673,12 +705,16 @@ void __l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) void l2cap_chan_add(struct l2cap_conn *conn, struct l2cap_chan *chan) { mutex_lock(&conn->lock); + l2cap_chan_lock(chan); __l2cap_chan_add(conn, chan); + l2cap_chan_unlock(chan); mutex_unlock(&conn->lock); } void l2cap_chan_del(struct l2cap_chan *chan, int err) { + lockdep_assert(!chan->conn || lockdep_is_held(&chan->conn->lock)); + __clear_chan_timer(chan); BT_DBG("chan %p, err %d, state %s", chan, err, @@ -733,6 +769,7 @@ EXPORT_SYMBOL_GPL(l2cap_chan_del); static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id, l2cap_chan_func_t func, void *data) + __must_hold(&conn->lock) { struct l2cap_chan *chan, *l; @@ -744,6 +781,7 @@ static void __l2cap_chan_list_id(struct l2cap_conn *conn, u16 id, static void __l2cap_chan_list(struct l2cap_conn *conn, l2cap_chan_func_t func, void *data) + __must_hold(&conn->lock) { struct l2cap_chan *chan; @@ -808,6 +846,8 @@ static void l2cap_chan_le_connect_reject(struct l2cap_chan *chan) } static void l2cap_chan_ecred_connect_reject(struct l2cap_chan *chan) + __must_hold(&chan->lock) + __must_hold(&chan->conn->lock) { l2cap_state_change(chan, BT_DISCONN); @@ -835,7 +875,7 @@ static void l2cap_chan_connect_reject(struct l2cap_chan *chan) l2cap_send_cmd(conn, chan->ident, L2CAP_CONN_RSP, sizeof(rsp), &rsp); } -void l2cap_chan_close(struct l2cap_chan *chan, int reason) +static void __l2cap_chan_close(struct l2cap_chan *chan, int reason) { struct l2cap_conn *conn = chan->conn; @@ -884,7 +924,54 @@ void l2cap_chan_close(struct l2cap_chan *chan, int reason) break; } } -EXPORT_SYMBOL(l2cap_chan_close); + +/* Take chan->lock. If chan->conn is non-NULL, take new reference on it, take + * chan->conn->lock, and return true. Otherwise return false. + */ +bool l2cap_chan_lock_conn(struct l2cap_chan *chan) + __context_unsafe(/* conditional locking */) +{ + /* Handle conn->lock > chan->lock ordering + race on chan->conn */ + for (;;) { + struct l2cap_conn *conn; + + l2cap_chan_lock(chan); + conn = chan->conn; + if (conn) + l2cap_conn_get(conn); + l2cap_chan_unlock(chan); + + if (conn) + mutex_lock(&conn->lock); + + l2cap_chan_lock(chan); + + if (chan->conn != conn) { + l2cap_chan_unlock(chan); + if (conn) { + mutex_unlock(&conn->lock); + l2cap_conn_put(conn); + } + schedule(); + continue; + } + + return chan->conn; + } +} + +void l2cap_chan_close_unlocked(struct l2cap_chan *chan, int reason) +{ + bool have_conn; + + have_conn = l2cap_chan_lock_conn(chan); + + /* Context analysis: consider chan->conn->lock held also if conn NULL */ + context_unsafe(__l2cap_chan_close(chan, reason)); + + l2cap_chan_unlock_conn(chan, have_conn); +} +EXPORT_SYMBOL(l2cap_chan_close_unlocked); static inline u8 l2cap_get_auth_type(struct l2cap_chan *chan) { @@ -1283,6 +1370,8 @@ void l2cap_send_conn_req(struct l2cap_chan *chan) } static void l2cap_chan_ready(struct l2cap_chan *chan) + __must_hold(&chan->lock) + __must_hold(&chan->conn->lock) { /* The channel may have already been flagged as connected in * case of receiving data before the L2CAP info req/rsp @@ -1384,6 +1473,7 @@ static void l2cap_ecred_defer_connect(struct l2cap_chan *chan, void *data) } static void l2cap_ecred_connect(struct l2cap_chan *chan) + __must_hold(&chan->conn->lock) { struct l2cap_conn *conn = chan->conn; struct l2cap_ecred_conn_data data; @@ -1417,6 +1507,8 @@ static void l2cap_ecred_connect(struct l2cap_chan *chan) } static void l2cap_le_start(struct l2cap_chan *chan) + __must_hold(&chan->lock) + __must_hold(&chan->conn->lock) { struct l2cap_conn *conn = chan->conn; @@ -1437,6 +1529,8 @@ static void l2cap_le_start(struct l2cap_chan *chan) } static void l2cap_start_connection(struct l2cap_chan *chan) + __must_hold(&chan->lock) + __must_hold(&chan->conn->lock) { if (chan->conn->hcon->type == LE_LINK) { l2cap_le_start(chan); @@ -1486,6 +1580,8 @@ static bool l2cap_check_enc_key_size(struct hci_conn *hcon, } static void l2cap_do_start(struct l2cap_chan *chan) + __must_hold(&chan->lock) + __must_hold(&chan->conn->lock) { struct l2cap_conn *conn = chan->conn; @@ -1552,6 +1648,7 @@ static void l2cap_send_disconn_req(struct l2cap_chan *chan, int err) /* ---- L2CAP connections ---- */ static void l2cap_conn_start(struct l2cap_conn *conn) + __must_hold(&conn->lock) { struct l2cap_chan *chan, *tmp; @@ -1560,6 +1657,8 @@ static void l2cap_conn_start(struct l2cap_conn *conn) list_for_each_entry_safe(chan, tmp, &conn->chan_l, list) { l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { l2cap_chan_ready(chan); l2cap_chan_unlock(chan); @@ -1576,7 +1675,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) if (!l2cap_mode_supported(chan->mode, conn->feat_mask) && test_bit(CONF_STATE2_DEVICE, &chan->conf_state)) { - l2cap_chan_close(chan, ECONNRESET); + __l2cap_chan_close(chan, ECONNRESET); l2cap_chan_unlock(chan); continue; } @@ -1584,7 +1683,7 @@ static void l2cap_conn_start(struct l2cap_conn *conn) if (l2cap_check_enc_key_size(conn->hcon, chan)) l2cap_start_connection(chan); else - l2cap_chan_close(chan, ECONNREFUSED); + __l2cap_chan_close(chan, ECONNREFUSED); } else if (chan->state == BT_CONNECT2) { struct l2cap_conn_rsp rsp; @@ -1676,6 +1775,8 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + if (hcon->type == LE_LINK) { l2cap_le_start(chan); } else if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) { @@ -1698,6 +1799,7 @@ static void l2cap_conn_ready(struct l2cap_conn *conn) /* Notify sockets that we cannot guaranty reliability anymore */ static void l2cap_conn_unreliable(struct l2cap_conn *conn, int err) + __must_hold(&conn->lock) { struct l2cap_chan *chan; @@ -1830,6 +1932,8 @@ static void l2cap_conn_del(struct hci_conn *hcon, int err) l2cap_chan_hold(chan); l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + l2cap_chan_del(chan, err); chan->ops->close(chan); @@ -2995,6 +3099,7 @@ static void l2cap_pass_to_tx_fbit(struct l2cap_chan *chan, /* Copy frame to all raw sockets on that connection */ static void l2cap_raw_recv(struct l2cap_conn *conn, struct sk_buff *skb) + __must_hold(&conn->lock) { struct sk_buff *nskb; struct l2cap_chan *chan; @@ -3645,18 +3750,29 @@ done: break; case L2CAP_MODE_ERTM: - if (!test_bit(CONF_EWS_RECV, &chan->conf_state)) - chan->remote_tx_win = rfc.txwin_size; - else - rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; - - chan->remote_max_tx = rfc.max_transmit; - size = min_t(u16, le16_to_cpu(rfc.max_pdu_size), chan->conn->mtu - L2CAP_EXT_HDR_SIZE - L2CAP_SDULEN_SIZE - L2CAP_FCS_SIZE); rfc.max_pdu_size = cpu_to_le16(size); - chan->remote_mps = size; + + /* The TxWindow must be within 1 to 63, otherwise + * propose the default one and keep the parameters of + * an earlier request. This overrides a PENDING result + * from the EFS check above, so the request is no + * longer pending, nor done if an earlier one was. + */ + if (!rfc.txwin_size || + rfc.txwin_size > L2CAP_DEFAULT_TX_WINDOW) { + result = L2CAP_CONF_UNACCEPT; + clear_bit(CONF_LOC_CONF_PEND, &chan->conf_state); + clear_bit(CONF_OUTPUT_DONE, &chan->conf_state); + rfc.txwin_size = L2CAP_DEFAULT_TX_WINDOW; + remote_efs = 0; + } else { + chan->remote_tx_win = rfc.txwin_size; + chan->remote_max_tx = rfc.max_transmit; + chan->remote_mps = size; + } __l2cap_set_ertm_timeouts(chan, &rfc); @@ -3798,7 +3914,11 @@ static int l2cap_parse_conf_rsp(struct l2cap_chan *chan, void *rsp, int len, } } - if (chan->mode == L2CAP_MODE_BASIC && chan->mode != rfc.mode) + /* A connected channel cannot change its mode, as the new mode would + * not be initialized. + */ + if (chan->mode != rfc.mode && + (chan->mode == L2CAP_MODE_BASIC || chan->state == BT_CONNECTED)) return -ECONNREFUSED; chan->mode = rfc.mode; @@ -3888,6 +4008,7 @@ static void l2cap_ecred_list_defer(struct l2cap_chan *chan, void *data) } struct l2cap_ecred_rsp_data { + struct l2cap_chan *locked_chan; struct { struct l2cap_ecred_conn_rsp_hdr rsp; __le16 scid[L2CAP_ECRED_MAX_CID]; @@ -3895,11 +4016,42 @@ struct l2cap_ecred_rsp_data { int count; }; +/* Lock @chan if it is not @locked_chan, and has same or lower nesting level. + * + * They must have the same chan->conn, and conn->lock must be held. + * + * Caller must ensure @chan has lock nesting level <= that of @locked_chan, as + * nested locking of l2cap_chan of different levels is allowed also without + * holding conn->lock. + * + * See l2cap.h for the global l2cap_chan locking rules. + */ +static bool l2cap_chan_try_sibling_lock(struct l2cap_chan *chan, + struct l2cap_chan *locked_chan) + __must_hold(&locked_chan->lock) + __must_hold(&locked_chan->conn->lock) + __cond_acquires(true, &chan->lock) +{ + if (chan == locked_chan) + return false; + + if (WARN_ON_ONCE(locked_chan->conn != chan->conn)) + return false; + + if (WARN_ON_ONCE(atomic_read(&locked_chan->nesting) + < atomic_read(&chan->nesting))) + return false; + + mutex_lock_nest_lock(&chan->lock, &locked_chan->conn->lock); + return true; +} + static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data) { struct l2cap_ecred_rsp_data *rsp = data; struct l2cap_ecred_conn_rsp *rsp_flex = container_of(&rsp->pdu.rsp, struct l2cap_ecred_conn_rsp, hdr); + bool locked; if (chan->mode != L2CAP_MODE_EXT_FLOWCTL) return; @@ -3911,6 +4063,22 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data) !test_and_clear_bit(FLAG_DEFER_SETUP, &chan->flags)) return; + lockdep_assert_held(&rsp->locked_chan->lock); + lockdep_assert_held(&rsp->locked_chan->conn->lock); + + l2cap_chan_hold(chan); + + locked = l2cap_chan_try_sibling_lock(chan, rsp->locked_chan); + + /* Cannot occur: PARENT channels do not appear in chan_l, and SMP + * channels never have FLAG_DEFER_SETUP. + */ + if (context_unsafe(!locked && chan != rsp->locked_chan)) + goto done; + + lockdep_assert_held(&chan->lock); + lockdep_assert_held(&chan->conn->lock); + /* Reset ident so only one response is sent */ chan->ident = 0; @@ -3923,6 +4091,12 @@ static void l2cap_ecred_rsp_defer(struct l2cap_chan *chan, void *data) rsp_flex->dcid[rsp->count++] = cpu_to_le16(chan->scid); else l2cap_chan_del(chan, ECONNRESET); + +done: + if (locked) + l2cap_chan_unlock(chan); + + l2cap_chan_put(chan); } void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan) @@ -3934,11 +4108,15 @@ void __l2cap_ecred_conn_rsp_defer(struct l2cap_chan *chan) if (!id) return; + if (!test_bit(FLAG_DEFER_SETUP, &chan->flags)) + return; BT_DBG("chan %p id %d", chan, id); memset(&data, 0, sizeof(data)); + data.locked_chan = chan; + data.pdu.rsp.mtu = cpu_to_le16(chan->imtu); data.pdu.rsp.mps = cpu_to_le16(chan->mps); data.pdu.rsp.credits = cpu_to_le16(chan->rx_credits); @@ -4048,6 +4226,7 @@ static void l2cap_conf_rfc_get(struct l2cap_chan *chan, void *rsp, int len) static inline int l2cap_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; @@ -4080,6 +4259,8 @@ static inline int l2cap_command_rej(struct l2cap_conn *conn, */ static struct l2cap_chan *l2cap_new_connection(struct l2cap_conn *conn, struct l2cap_chan *pchan) + __must_hold(&conn->lock) + __must_hold(&pchan->lock) { struct l2cap_chan *chan; @@ -4087,23 +4268,31 @@ static struct l2cap_chan *l2cap_new_connection(struct l2cap_conn *conn, if (!chan) return NULL; + l2cap_chan_lock(chan); + l2cap_chan_set_defaults(chan, pchan); chan->ops = pchan->ops; __l2cap_chan_add(conn, chan); + lockdep_assert_held(&chan->conn->lock); + if (pchan->ops->new_connection && pchan->ops->new_connection(pchan, chan) < 0) { l2cap_chan_del(chan, 0); + l2cap_chan_unlock(chan); l2cap_chan_put(chan); return NULL; } + l2cap_chan_unlock(chan); + return chan; } static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u8 *data, u8 rsp_code) + __must_hold(&conn->lock) { struct l2cap_conn_req *req = (struct l2cap_conn_req *) data; struct l2cap_conn_rsp rsp; @@ -4120,7 +4309,13 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, &conn->hcon->dst, ACL_LINK); if (!pchan) { result = L2CAP_CR_BAD_PSM; - goto response; + + rsp.scid = cpu_to_le16(scid); + rsp.dcid = cpu_to_le16(dcid); + rsp.result = cpu_to_le16(result); + rsp.status = cpu_to_le16(status); + l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); + return; } l2cap_chan_lock(pchan); @@ -4202,9 +4397,6 @@ response: rsp.status = cpu_to_le16(status); l2cap_send_cmd(conn, cmd->ident, rsp_code, sizeof(rsp), &rsp); - if (!pchan) - return; - if (result == L2CAP_CR_PEND && status == L2CAP_CS_NO_INFO) { struct l2cap_info_req info; info.type = cpu_to_le16(L2CAP_IT_FEAT_MASK); @@ -4233,6 +4425,7 @@ response: static int l2cap_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { if (cmd_len < sizeof(struct l2cap_conn_req)) return -EPROTO; @@ -4244,6 +4437,7 @@ static int l2cap_connect_req(struct l2cap_conn *conn, static int l2cap_connect_create_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_conn_rsp *rsp = (struct l2cap_conn_rsp *) data; u16 scid, dcid, result, status; @@ -4271,7 +4465,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, if (!chan) return -EBADSLT; } else { - chan = __l2cap_get_chan_by_ident(conn, cmd->ident); + chan = __l2cap_get_connect_chan_by_ident(conn, cmd->ident); if (!chan) return -EBADSLT; } @@ -4284,6 +4478,15 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + + /* Only accept a response to a connection request we sent and that + * is still outstanding. A channel waiting in BT_CONNECT for security + * or the feature mask has not sent one yet. + */ + if (!l2cap_chan_connect_pending(chan)) + goto done; + switch (result) { case L2CAP_CR_SUCCESS: if (__l2cap_get_chan_by_dcid(conn, dcid)) { @@ -4305,7 +4508,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, break; case L2CAP_CR_PEND: - set_bit(CONF_CONNECT_PEND, &chan->conf_state); + /* Our request is still outstanding */ break; default: @@ -4313,6 +4516,7 @@ static int l2cap_connect_create_rsp(struct l2cap_conn *conn, break; } +done: l2cap_chan_unlock(chan); l2cap_chan_put(chan); @@ -4361,6 +4565,7 @@ static void cmd_reject_invalid_cid(struct l2cap_conn *conn, u8 ident, static inline int l2cap_config_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_conf_req *req = (struct l2cap_conf_req *) data; u16 dcid, flags; @@ -4382,6 +4587,10 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, return 0; } + l2cap_chan_lock(chan); + + lockdep_assert_held(&chan->conn->lock); + if (chan->state != BT_CONFIG && chan->state != BT_CONNECT2 && chan->state != BT_CONNECTED) { cmd_reject_invalid_cid(conn, cmd->ident, chan->scid, @@ -4445,7 +4654,13 @@ static inline int l2cap_config_req(struct l2cap_conn *conn, goto unlock; } - if (!test_and_set_bit(CONF_REQ_SENT, &chan->conf_state)) { + /* A channel in BT_CONNECT2 has not passed security or userspace + * accept yet. Answer the peer's request, but hold our own until + * the channel reaches BT_CONFIG: the CONNECT2 -> CONFIG sites send + * it. Connected channels may also need to reconfigure. + */ + if ((chan->state == BT_CONFIG || chan->state == BT_CONNECTED) && + !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, sizeof(buf)), buf); @@ -4472,6 +4687,7 @@ unlock: static inline int l2cap_config_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_conf_rsp *rsp = (struct l2cap_conf_rsp *)data; u16 scid, flags, result; @@ -4493,6 +4709,14 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, if (!chan) return 0; + l2cap_chan_lock(chan); + + lockdep_assert_held(&chan->conn->lock); + + /* Connected channels may also receive reconfiguration responses. */ + if (chan->state != BT_CONFIG && chan->state != BT_CONNECTED) + goto done; + switch (result) { case L2CAP_CONF_SUCCESS: l2cap_conf_rfc_get(chan, rsp->data, len); @@ -4560,6 +4784,9 @@ static inline int l2cap_config_rsp(struct l2cap_conn *conn, if (test_bit(CONF_OUTPUT_DONE, &chan->conf_state)) { set_default_fcs(chan); + if (chan->state != BT_CONFIG) + goto done; + if (chan->mode == L2CAP_MODE_ERTM || chan->mode == L2CAP_MODE_STREAMING) err = l2cap_ertm_init(chan); @@ -4579,6 +4806,7 @@ done: static inline int l2cap_disconnect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_disconn_req *req = (struct l2cap_disconn_req *) data; struct l2cap_disconn_rsp rsp; @@ -4599,6 +4827,10 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, return 0; } + l2cap_chan_lock(chan); + + lockdep_assert_held(&chan->conn->lock); + rsp.dcid = cpu_to_le16(chan->scid); rsp.scid = cpu_to_le16(chan->dcid); l2cap_send_cmd(conn, cmd->ident, L2CAP_DISCONN_RSP, sizeof(rsp), &rsp); @@ -4618,6 +4850,7 @@ static inline int l2cap_disconnect_req(struct l2cap_conn *conn, static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_disconn_rsp *rsp = (struct l2cap_disconn_rsp *) data; u16 dcid, scid; @@ -4636,6 +4869,10 @@ static inline int l2cap_disconnect_rsp(struct l2cap_conn *conn, return 0; } + l2cap_chan_lock(chan); + + lockdep_assert_held(&chan->conn->lock); + if (chan->state != BT_DISCONN) { l2cap_chan_unlock(chan); l2cap_chan_put(chan); @@ -4703,6 +4940,7 @@ static inline int l2cap_information_req(struct l2cap_conn *conn, static inline int l2cap_information_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_info_rsp *rsp = (struct l2cap_info_rsp *) data; u16 type, result; @@ -4810,6 +5048,7 @@ static inline int l2cap_conn_param_update_req(struct l2cap_conn *conn, static int l2cap_le_connect_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_le_conn_rsp *rsp = (struct l2cap_le_conn_rsp *) data; struct hci_conn *hcon = conn->hcon; @@ -4846,6 +5085,8 @@ static int l2cap_le_connect_rsp(struct l2cap_conn *conn, l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + switch (result) { case L2CAP_CR_LE_SUCCESS: if (__l2cap_get_chan_by_dcid(conn, dcid)) { @@ -4916,6 +5157,7 @@ static void l2cap_put_ident(struct l2cap_conn *conn, u8 code, u8 id) static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { int err = 0; @@ -4977,6 +5219,7 @@ static inline int l2cap_bredr_sig_cmd(struct l2cap_conn *conn, static int l2cap_le_connect_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_le_conn_req *req = (struct l2cap_le_conn_req *) data; struct l2cap_le_conn_rsp rsp; @@ -5060,6 +5303,10 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, goto response_unlock; } + l2cap_chan_lock(chan); + + lockdep_assert_held(&chan->conn->lock); + bacpy(&chan->src, &conn->hcon->src); bacpy(&chan->dst, &conn->hcon->dst); chan->src_type = bdaddr_src_type(conn->hcon); @@ -5093,6 +5340,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn, result = L2CAP_CR_LE_SUCCESS; } + l2cap_chan_unlock(chan); + response_unlock: l2cap_chan_unlock(pchan); l2cap_chan_put(pchan); @@ -5121,6 +5370,7 @@ response: static inline int l2cap_le_credits(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_le_credits *pkt; struct l2cap_chan *chan; @@ -5139,6 +5389,8 @@ static inline int l2cap_le_credits(struct l2cap_conn *conn, if (!chan) return -EBADSLT; + l2cap_chan_lock(chan); + max_credits = LE_FLOWCTL_MAX_CREDITS - chan->tx_credits; if (credits > max_credits) { BT_ERR("LE credits overflow"); @@ -5168,6 +5420,7 @@ unlock: static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_ecred_conn_req *req = (void *) data; DEFINE_RAW_FLEX(struct l2cap_ecred_conn_rsp, pdu, dcid, L2CAP_ECRED_MAX_CID); @@ -5283,6 +5536,10 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, continue; } + l2cap_chan_lock(chan); + + lockdep_assert_held(&chan->conn->lock); + bacpy(&chan->src, &conn->hcon->src); bacpy(&chan->dst, &conn->hcon->dst); chan->src_type = bdaddr_src_type(conn->hcon); @@ -5315,6 +5572,8 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn, } else { l2cap_chan_ready(chan); } + + l2cap_chan_unlock(chan); } unlock: @@ -5336,6 +5595,7 @@ response: static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_ecred_conn_rsp *rsp = (void *) data; struct hci_conn *hcon = conn->hcon; @@ -5366,12 +5626,16 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, chan->state == BT_CONNECTED) continue; + l2cap_chan_hold(chan); l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + /* Check that there is a dcid for each pending channel */ if (cmd_len < sizeof(dcid)) { l2cap_chan_del(chan, ECONNREFUSED); l2cap_chan_unlock(chan); + l2cap_chan_put(chan); continue; } @@ -5410,6 +5674,8 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, __set_chan_timer(orig, 0); l2cap_chan_unlock(orig); } + + l2cap_chan_put(chan); continue; } @@ -5455,6 +5721,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, } l2cap_chan_unlock(chan); + l2cap_chan_put(chan); } return err; @@ -5463,6 +5730,7 @@ static inline int l2cap_ecred_conn_rsp(struct l2cap_conn *conn, static inline int l2cap_ecred_reconf_req(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_ecred_reconf_req *req = (void *) data; struct l2cap_ecred_reconf_rsp rsp; @@ -5561,6 +5829,7 @@ respond: static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_chan *chan, *tmp; struct l2cap_ecred_reconf_rsp *rsp = (void *)data; @@ -5589,6 +5858,8 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, continue; l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + l2cap_chan_del(chan, ECONNRESET); l2cap_chan_unlock(chan); @@ -5601,6 +5872,7 @@ static inline int l2cap_ecred_reconf_rsp(struct l2cap_conn *conn, static inline int l2cap_le_command_rej(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { struct l2cap_cmd_rej_unk *rej = (struct l2cap_cmd_rej_unk *) data; struct l2cap_chan *chan; @@ -5617,6 +5889,7 @@ static inline int l2cap_le_command_rej(struct l2cap_conn *conn, goto done; l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); l2cap_chan_del(chan, ECONNREFUSED); l2cap_chan_unlock(chan); l2cap_chan_put(chan); @@ -5628,6 +5901,7 @@ done: static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd, u16 cmd_len, u8 *data) + __must_hold(&conn->lock) { int err = 0; @@ -5692,6 +5966,7 @@ static inline int l2cap_le_sig_cmd(struct l2cap_conn *conn, static inline void l2cap_le_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) + __must_hold(&conn->lock) { struct hci_conn *hcon = conn->hcon; struct l2cap_cmd_hdr *cmd; @@ -5750,6 +6025,7 @@ static inline void l2cap_sig_send_mtu_rej(struct l2cap_conn *conn, u8 ident) static inline void l2cap_sig_channel(struct l2cap_conn *conn, struct sk_buff *skb) + __must_hold(&conn->lock) { struct hci_conn *hcon = conn->hcon; struct l2cap_cmd_hdr *cmd; @@ -6995,6 +7271,7 @@ failed: static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, struct sk_buff *skb) + __must_hold(&conn->lock) { struct l2cap_chan *chan; @@ -7006,6 +7283,10 @@ static void l2cap_data_channel(struct l2cap_conn *conn, u16 cid, return; } + l2cap_chan_lock(chan); + + lockdep_assert_held(&chan->conn->lock); + BT_DBG("chan %p, len %d", chan, skb->len); /* If we receive data on a fixed channel before the info req/rsp @@ -7101,6 +7382,7 @@ free_skb: } static void l2cap_recv_frame(struct l2cap_conn *conn, struct sk_buff *skb) + __must_hold(&conn->lock) { struct l2cap_hdr *lh = (void *) skb->data; struct hci_conn *hcon = conn->hcon; @@ -7210,9 +7492,9 @@ static struct l2cap_conn *l2cap_conn_add(struct hci_conn *hcon) hci_dev_test_flag(hcon->hdev, HCI_FORCE_BREDR_SMP))) conn->local_fixed_chan |= L2CAP_FC_SMP_BREDR; - mutex_init(&conn->lock); - - INIT_LIST_HEAD(&conn->chan_l); + scoped_guard(mutex_init, &conn->lock) { + INIT_LIST_HEAD(&conn->chan_l); + } INIT_LIST_HEAD(&conn->users); INIT_DELAYED_WORK(&conn->info_timer, l2cap_info_timeout); @@ -7416,7 +7698,8 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, } } - if (cid && __l2cap_get_chan_by_dcid(conn, cid)) { + if ((cid && __l2cap_get_chan_by_dcid(conn, cid)) || chan->conn || + test_bit(FLAG_DEL, &chan->flags)) { hci_conn_drop(hcon); err = -EBUSY; goto chan_unlock; @@ -7428,6 +7711,8 @@ int l2cap_chan_connect(struct l2cap_chan *chan, __le16 psm, u16 cid, __l2cap_chan_add(conn, chan); + lockdep_assert_held(&chan->conn->lock); + /* l2cap_chan_add takes its own ref so we can drop this one */ hci_conn_drop(hcon); @@ -7591,6 +7876,8 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status) * we left off, because the list lock would prevent calling the * potentially sleeping l2cap_chan_lock() function. */ + mutex_lock(&conn->lock); + pchan = l2cap_global_fixed_chan(NULL, hcon); while (pchan) { struct l2cap_chan *chan, *next; @@ -7615,6 +7902,8 @@ next: pchan = next; } + mutex_unlock(&conn->lock); + l2cap_conn_ready(conn); } @@ -7646,6 +7935,8 @@ static void l2cap_disconn_cfm(struct hci_conn *hcon, u8 reason) } static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) + __must_hold(&chan->lock) + __must_hold(&chan->conn->lock) { if (chan->chan_type != L2CAP_CHAN_CONN_ORIENTED) return; @@ -7655,7 +7946,7 @@ static inline void l2cap_check_encryption(struct l2cap_chan *chan, u8 encrypt) __set_chan_timer(chan, L2CAP_ENC_TIMEOUT); } else if (chan->sec_level == BT_SECURITY_HIGH || chan->sec_level == BT_SECURITY_FIPS) - l2cap_chan_close(chan, ECONNREFUSED); + __l2cap_chan_close(chan, ECONNREFUSED); } else { if (chan->sec_level == BT_SECURITY_MEDIUM) __clear_chan_timer(chan); @@ -7678,6 +7969,8 @@ static void l2cap_security_cfm(struct hci_conn *hcon, u8 status, u8 encrypt) list_for_each_entry(chan, &conn->chan_l, list) { l2cap_chan_lock(chan); + lockdep_assert_held(&chan->conn->lock); + BT_DBG("chan %p scid 0x%4.4x state %s", chan, chan->scid, state_to_string(chan->state)); diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c index 872d8fb31b6f..7a2551ef7f50 100644 --- a/net/bluetooth/l2cap_sock.c +++ b/net/bluetooth/l2cap_sock.c @@ -109,6 +109,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr_unsized *addr, i return -EINVAL; } + l2cap_chan_lock(chan); lock_sock(sk); if (sk->sk_state != BT_OPEN) { @@ -174,6 +175,7 @@ static int l2cap_sock_bind(struct socket *sock, struct sockaddr_unsized *addr, i done: release_sock(sk); + l2cap_chan_unlock(chan); return err; } @@ -813,6 +815,10 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, break; } + /* A zero TxWindow is invalid, use the default instead */ + if (!opts.txwin_size) + opts.txwin_size = L2CAP_DEFAULT_TX_WINDOW; + if (!l2cap_valid_mtu(chan, opts.imtu)) { err = -EINVAL; break; @@ -865,15 +871,11 @@ static int l2cap_sock_setsockopt_old(struct socket *sock, int optname, if (opt & L2CAP_LM_SECURE) chan->sec_level = BT_SECURITY_HIGH; - if (opt & L2CAP_LM_MASTER) - set_bit(FLAG_ROLE_SWITCH, &chan->flags); - else - clear_bit(FLAG_ROLE_SWITCH, &chan->flags); + assign_bit(FLAG_ROLE_SWITCH, &chan->flags, + opt & L2CAP_LM_MASTER); - if (opt & L2CAP_LM_RELIABLE) - set_bit(FLAG_FORCE_RELIABLE, &chan->flags); - else - clear_bit(FLAG_FORCE_RELIABLE, &chan->flags); + assign_bit(FLAG_FORCE_RELIABLE, &chan->flags, + opt & L2CAP_LM_RELIABLE); break; default: @@ -1040,10 +1042,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, } } - if (opt) - set_bit(FLAG_FLUSHABLE, &chan->flags); - else - clear_bit(FLAG_FLUSHABLE, &chan->flags); + assign_bit(FLAG_FLUSHABLE, &chan->flags, opt); break; case BT_POWER: @@ -1059,10 +1058,7 @@ static int l2cap_sock_setsockopt(struct socket *sock, int level, int optname, if (err) break; - if (pwr.force_active) - set_bit(FLAG_FORCE_ACTIVE, &chan->flags); - else - clear_bit(FLAG_FORCE_ACTIVE, &chan->flags); + assign_bit(FLAG_FORCE_ACTIVE, &chan->flags, pwr.force_active); break; case BT_CHANNEL_POLICY: @@ -1243,40 +1239,68 @@ static void l2cap_publish_rx_avail(struct l2cap_chan *chan) l2cap_chan_rx_avail(chan, -1); } -static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg, - size_t len, int flags) +static int l2cap_sock_defer(struct sock *sk) { - struct sock *sk = sock->sk; - struct l2cap_pinfo *pi = l2cap_pi(sk); - int err; + struct l2cap_chan *chan = l2cap_pi(sk)->chan; + bool have_conn; + int err = 0; - if (unlikely(flags & MSG_ERRQUEUE)) - return sock_recv_errqueue(sk, msg, len, SOL_BLUETOOTH, - BT_SCM_ERROR); + /* Fast path check */ + lock_sock(sk); + if (sk->sk_state != BT_CONNECT2) { + release_sock(sk); + return 0; + } + release_sock(sk); + have_conn = l2cap_chan_lock_conn(chan); lock_sock(sk); if (sk->sk_state == BT_CONNECT2 && test_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags)) { - if (pi->chan->mode == L2CAP_MODE_EXT_FLOWCTL) { + err = 1; + + if (!have_conn) { + release_sock(sk); + err = -ENOTCONN; + } else if (chan->mode == L2CAP_MODE_EXT_FLOWCTL) { sk->sk_state = BT_CONNECTED; - pi->chan->state = BT_CONNECTED; - __l2cap_ecred_conn_rsp_defer(pi->chan); - } else if (bdaddr_type_is_le(pi->chan->src_type)) { + chan->state = BT_CONNECTED; + release_sock(sk); + __l2cap_ecred_conn_rsp_defer(chan); + } else if (bdaddr_type_is_le(chan->src_type)) { sk->sk_state = BT_CONNECTED; - pi->chan->state = BT_CONNECTED; - __l2cap_le_connect_rsp_defer(pi->chan); + chan->state = BT_CONNECTED; + release_sock(sk); + __l2cap_le_connect_rsp_defer(chan); } else { sk->sk_state = BT_CONFIG; - pi->chan->state = BT_CONFIG; - __l2cap_connect_rsp_defer(pi->chan); + chan->state = BT_CONFIG; + release_sock(sk); + __l2cap_connect_rsp_defer(chan); } - - err = 0; - goto done; + } else { + release_sock(sk); } - release_sock(sk); + l2cap_chan_unlock_conn(chan, have_conn); + return err; +} + +static int l2cap_sock_recvmsg(struct socket *sock, struct msghdr *msg, + size_t len, int flags) +{ + struct sock *sk = sock->sk; + struct l2cap_pinfo *pi = l2cap_pi(sk); + int err; + + if (unlikely(flags & MSG_ERRQUEUE)) + return sock_recv_errqueue(sk, msg, len, SOL_BLUETOOTH, + BT_SCM_ERROR); + + err = l2cap_sock_defer(sk); + if (err) + return err < 0 ? err : 0; if (sock->type == SOCK_STREAM) err = bt_sock_stream_recvmsg(sock, msg, len, flags); @@ -1406,7 +1430,6 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) { struct sock *sk = sock->sk; struct l2cap_chan *chan; - struct l2cap_conn *conn; int err = 0; BT_DBG("sock %p, sk %p, how %d", sock, sk, how); @@ -1463,23 +1486,7 @@ static int l2cap_sock_shutdown(struct socket *sock, int how) sk->sk_shutdown |= SEND_SHUTDOWN; release_sock(sk); - l2cap_chan_lock(chan); - /* prevent conn structure from being freed */ - conn = l2cap_conn_hold_unless_zero(chan->conn); - l2cap_chan_unlock(chan); - - if (conn) - /* mutex lock must be taken before l2cap_chan_lock() */ - mutex_lock(&conn->lock); - - l2cap_chan_lock(chan); - l2cap_chan_close(chan, 0); - l2cap_chan_unlock(chan); - - if (conn) { - mutex_unlock(&conn->lock); - l2cap_conn_put(conn); - } + l2cap_chan_close_unlocked(chan, 0); lock_sock(sk); @@ -1748,8 +1755,14 @@ static void l2cap_sock_teardown_cb(struct l2cap_chan *chan, int err) sk->sk_err = err; if (parent) { + /* + * Keep the listener alive after unlinking the + * child. + */ + sock_hold(parent); bt_accept_unlink(sk); parent->sk_data_ready(parent); + sock_put(parent); } else { sk->sk_state_change(sk); } @@ -1784,6 +1797,7 @@ static void l2cap_sock_state_change_cb(struct l2cap_chan *chan, int state, static struct sk_buff *l2cap_sock_alloc_skb_cb(struct l2cap_chan *chan, unsigned long hdr_len, unsigned long len, int nb) + __must_hold(&chan->lock) { struct sock *sk = chan->data; struct sk_buff *skb; diff --git a/net/bluetooth/mgmt.c b/net/bluetooth/mgmt.c index 251a896babd5..3b9c82bd2f02 100644 --- a/net/bluetooth/mgmt.c +++ b/net/bluetooth/mgmt.c @@ -177,6 +177,7 @@ static const u16 mgmt_events[] = { MGMT_EV_CONTROLLER_RESUME, MGMT_EV_ADV_MONITOR_DEVICE_FOUND, MGMT_EV_ADV_MONITOR_DEVICE_LOST, + MGMT_EV_SECURITY_LEVEL_CHANGED, }; static const u16 mgmt_untrusted_commands[] = { @@ -301,6 +302,8 @@ static u8 mgmt_errno_status(int err) return MGMT_STATUS_ALREADY_CONNECTED; case -ENOTCONN: return MGMT_STATUS_DISCONNECTED; + case -ECANCELED: + return MGMT_STATUS_CANCELLED; } return MGMT_STATUS_FAILED; @@ -1296,7 +1299,7 @@ void mgmt_advertising_removed(struct sock *sk, struct hci_dev *hdev, static void cancel_adv_timeout(struct hci_dev *hdev) { if (hdev->adv_instance_timeout) { - hdev->adv_instance_timeout = 0; + hdev->adv_instance_timeout = false; cancel_delayed_work(&hdev->adv_instance_expire); } } @@ -4906,6 +4909,13 @@ static int set_quality_report_func(struct sock *sk, struct hci_dev *hdev, hci_req_sync_lock(hdev); + if (hci_dev_test_flag(hdev, HCI_UNREGISTER)) { + err = mgmt_cmd_status(sk, hdev->id, + MGMT_OP_SET_EXP_FEATURE, + MGMT_STATUS_INVALID_INDEX); + goto unlock_quality_report; + } + val = !!cp->param[0]; changed = (val != hci_dev_test_flag(hdev, HCI_QUALITY_REPORT)); @@ -5682,8 +5692,18 @@ static void mgmt_remove_adv_monitor_complete(struct hci_dev *hdev, struct mgmt_pending_cmd *cmd = data; struct mgmt_cp_remove_adv_monitor *cp; - if (status == -ECANCELED) + /* Reply to a cancelled command so bluetoothd's serialised mgmt queue + * is not blocked. + */ + if (status == -ECANCELED) { + cp = cmd->param; + rp.monitor_handle = cp->monitor_handle; + + mgmt_cmd_complete(cmd->sk, cmd->hdev->id, cmd->opcode, + mgmt_status(status), &rp, sizeof(rp)); + mgmt_pending_free(cmd); return; + } hci_dev_lock(hdev); @@ -6533,7 +6553,12 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) return; } - if (hci_dev_test_flag(hdev, HCI_LE_ADV)) + /* With extended advertising global advertising (instance 0) has its + * own advertising set so only consider its state, other instances may + * still be enabled. + */ + if (ext_adv_capable(hdev) ? hci_dev_test_flag(hdev, HCI_LE_ADV_0) : + hci_dev_test_flag(hdev, HCI_LE_ADV)) hci_dev_set_flag(hdev, HCI_ADVERTISING); else hci_dev_clear_flag(hdev, HCI_ADVERTISING); @@ -6553,6 +6578,34 @@ static void set_advertising_complete(struct hci_dev *hdev, void *data, int err) list_empty(&hdev->adv_instances)) return; + /* With extended advertising instances are not overridden by global + * advertising, except the ones sharing its set, so only (re)start the + * instances that are not already enabled. + * + * Lookup instances by identifier while holding hdev->lock since the + * list may change while waiting for the HCI commands to complete. + */ + if (ext_adv_capable(hdev)) { + u16 i; + + for (i = 1; i <= hdev->le_num_of_adv_sets + 1; i++) { + bool enabled; + + hci_dev_lock(hdev); + adv_instance = hci_find_adv_instance(hdev, i); + enabled = !adv_instance || adv_instance->enabled; + hci_dev_unlock(hdev); + + if (enabled) + continue; + + err = hci_schedule_adv_instance_sync(hdev, i, true); + enable_advertising_instance(hdev, err); + } + + return; + } + instance = hdev->cur_adv_instance; if (!instance) { adv_instance = list_first_entry_or_null(&hdev->adv_instances, @@ -6608,6 +6661,11 @@ static int set_adv_sync(struct hci_dev *hdev, void *data) hci_update_scan_rsp_data_sync(hdev, 0x00); hci_enable_advertising_sync(hdev); } + } else if (ext_adv_capable(hdev)) { + /* Only disable global advertising (instance 0) leaving other + * instances untouched. + */ + hci_disable_ext_adv_legacy_instance_sync(hdev); } else { hci_disable_advertising_sync(hdev); } @@ -8289,8 +8347,10 @@ static int load_conn_subrate(struct sock *sk, struct hci_dev *hdev, void *data, hci_param->cont_num = cont_num; hci_param->rate_supv_timeout = supv_timeout; - /* If the device is connected as central check if the - * connection rate parameters need to be updated. + /* If the device is connected check if the connection rate + * parameters need to be updated, either role can initiate the + * Connection Rate Update procedure, e.g. a HID device acting + * as peripheral once the HID host requests a HID SCI mode. */ if (!i && param_count == 1) { struct hci_conn *conn; @@ -8299,7 +8359,6 @@ static int load_conn_subrate(struct sock *sk, struct hci_dev *hdev, void *data, &hci_param->addr, addr_type); if (conn && conn->state == BT_CONNECTED && - conn->role == HCI_ROLE_MASTER && (conn->le_rate_interval < min || conn->le_rate_interval > max || conn->le_subrate < subrate_min || @@ -8939,6 +8998,21 @@ static bool adv_busy(struct hci_dev *hdev) return pending_find(MGMT_OP_SET_LE, hdev); } +/* Global advertising, enabled with MGMT_OP_SET_ADVERTISING, uses instance 0 + * and takes precedence over any instance that would share its advertising + * set: with legacy advertising there is only a single set so all instances + * are overridden, whereas with extended advertising only an instance using + * handle 0x00 is. + */ +static bool adv_overridden_by_global(struct hci_dev *hdev, + struct adv_info *adv) +{ + if (!hci_dev_test_flag(hdev, HCI_ADVERTISING)) + return false; + + return !ext_adv_capable(hdev) || !adv->handle; +} + static void add_adv_complete(struct hci_dev *hdev, struct sock *sk, u8 instance, int err) { @@ -9100,13 +9174,19 @@ static int add_advertising(struct sock *sk, struct hci_dev *hdev, schedule_instance = cp->instance; } - /* If the HCI_ADVERTISING flag is set or the device isn't powered or - * there is no instance to be advertised then we have no HCI - * communication to make. Simply return. + /* If the instance is overridden by global advertising or the device + * isn't powered or there is no instance to be advertised then we have + * no HCI communication to make. Simply return. */ if (!hdev_is_powered(hdev) || - hci_dev_test_flag(hdev, HCI_ADVERTISING) || + adv_overridden_by_global(hdev, adv) || !schedule_instance) { + /* Instance has been accepted so it shall no longer be + * considered pending, otherwise a later failure in + * add_adv_complete would remove it. + */ + adv->pending = false; + rp.instance = cp->instance; err = mgmt_cmd_complete(sk, hdev->id, MGMT_OP_ADD_ADVERTISING, MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); @@ -9280,20 +9360,24 @@ static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev, goto unlock; } - /* Submit request for advertising params if ext adv available */ - if (ext_adv_capable(hdev)) { + /* Submit request for advertising params if ext adv available, unless + * the set is in use by global advertising in which case the params + * will be programmed once the instance is scheduled. + */ + if (ext_adv_capable(hdev) && !adv_overridden_by_global(hdev, adv)) { cmd = mgmt_pending_new(sk, MGMT_OP_ADD_EXT_ADV_PARAMS, hdev, data, data_len); if (!cmd) { err = -ENOMEM; - hci_remove_adv_instance(hdev, cp->instance); - goto unlock; + goto remove; } err = hci_cmd_sync_queue(hdev, add_ext_adv_params_sync, cmd, add_ext_adv_params_complete); - if (err < 0) + if (err < 0) { mgmt_pending_free(cmd); + goto remove; + } } else { rp.instance = cp->instance; rp.tx_power = HCI_ADV_TX_POWER_NO_PREFERENCE; @@ -9304,6 +9388,18 @@ static int add_ext_adv_params(struct sock *sk, struct hci_dev *hdev, MGMT_STATUS_SUCCESS, &rp, sizeof(rp)); } + goto unlock; + +remove: + /* The instance may have been modified already so remove it, like it + * is done in add_ext_adv_params_complete, signaling it has been + * removed if it was previously added. + */ + if (!adv->pending) + mgmt_advertising_removed(sk, hdev, cp->instance); + + hci_remove_adv_instance(hdev, cp->instance); + unlock: hci_dev_unlock(hdev); @@ -9431,11 +9527,12 @@ static int add_ext_adv_data(struct sock *sk, struct hci_dev *hdev, void *data, schedule_instance = cp->instance; } - /* If the HCI_ADVERTISING flag is set or there is no instance to - * be advertised then we have no HCI communication to make. + /* If the instance is overridden by global advertising or there is no + * instance to be advertised then we have no HCI communication to make. * Simply return. */ - if (hci_dev_test_flag(hdev, HCI_ADVERTISING) || !schedule_instance) { + if (adv_overridden_by_global(hdev, adv_instance) || + !schedule_instance) { if (adv_instance->pending) { mgmt_advertising_added(sk, hdev, cp->instance); adv_instance->pending = false; @@ -9511,7 +9608,11 @@ static int remove_advertising_sync(struct hci_dev *hdev, void *data) if (err) return err; - if (list_empty(&hdev->adv_instances)) + /* Don't disable advertising if global advertising (instance 0) is + * enabled since it is not affected by removing instances. + */ + if (list_empty(&hdev->adv_instances) && + !hci_dev_test_flag(hdev, HCI_ADVERTISING)) err = hci_disable_advertising_sync(hdev); return err; @@ -10070,6 +10171,14 @@ void mgmt_device_connected(struct hci_dev *hdev, struct hci_conn *conn, ev->eir_len = cpu_to_le16(eir_len); mgmt_event_skb(skb, NULL); + + /* Connections that negotiated encryption as part of setup (e.g. via + * an existing link key) had their security level change suppressed + * since userspace did not know about them yet, so report it now. + * Unencrypted connections have no change to report. + */ + if (test_bit(HCI_CONN_ENCRYPT, &conn->flags)) + mgmt_security_level_changed(conn); } static void unpair_device_rsp(struct mgmt_pending_cmd *cmd, void *data) @@ -10176,7 +10285,11 @@ void mgmt_connect_failed(struct hci_dev *hdev, struct hci_conn *conn, u8 status) { struct mgmt_ev_connect_failed ev; - if (test_and_clear_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { + /* Only peek at the flag here: hci_conn_del() (via hci_conn_unlink()) + * still needs it set to know whether to report the security level + * reset, so it is consumed there instead of here. + */ + if (test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) { mgmt_device_disconnected(hdev, &conn->dst, conn->type, conn->dst_type, hci_to_mgmt_reason(status), true); @@ -10810,6 +10923,57 @@ void mgmt_device_found(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, mgmt_adv_monitor_device_found(hdev, bdaddr, report_device, skb, NULL); } +void mgmt_security_level_changed(struct hci_conn *conn) +{ + struct mgmt_ev_security_level_changed *ev; + struct mgmt_tlv *tlv; + u8 *tlv_data; + u8 tlv_len; + + if (!test_bit(HCI_CONN_MGMT_CONNECTED, &conn->flags)) + return; + + /* Only ACL, LE and BIS links are tracked as mgmt connections, so + * restrict the event to those link types. Other transports (SCO, + * CIS, PA sync, ...) share the parent's address and would otherwise + * report a spurious security level change for it. + */ + if (conn->type != ACL_LINK && conn->type != LE_LINK && + conn->type != BIS_LINK) + return; + + tlv_len = 2 * (sizeof(*tlv) + sizeof(__u8)); + ev = kzalloc_flex(*ev, tlv_data, tlv_len, GFP_KERNEL); + if (!ev) + return; + + bacpy(&ev->addr.bdaddr, &conn->dst); + ev->addr.type = link_to_bdaddr(conn->type, conn->dst_type); + ev->tlv_length = tlv_len; + + tlv_data = ev->tlv_data; + tlv = (void *)tlv_data; + tlv->type = cpu_to_le16(MGMT_SEC_LEVEL_CHANGED_PARAM_LEVEL); + tlv->length = sizeof(__u8); + tlv->value[0] = conn->sec_level; + + tlv_data += sizeof(*tlv) + sizeof(__u8); + tlv = (void *)tlv_data; + tlv->type = cpu_to_le16(MGMT_SEC_LEVEL_CHANGED_PARAM_ENC_TYPE); + tlv->length = sizeof(__u8); + if (!test_bit(HCI_CONN_ENCRYPT, &conn->flags)) + tlv->value[0] = MGMT_CONN_SEC_ENCRYPT_NONE; + else if (test_bit(HCI_CONN_AES_CCM, &conn->flags)) + tlv->value[0] = MGMT_CONN_SEC_ENCRYPT_AES_CCM; + else + tlv->value[0] = MGMT_CONN_SEC_ENCRYPT_E0; + + mgmt_event(MGMT_EV_SECURITY_LEVEL_CHANGED, conn->hdev, ev, + struct_size(ev, tlv_data, tlv_len), NULL); + + kfree(ev); +} + void mgmt_remote_name(struct hci_dev *hdev, bdaddr_t *bdaddr, u8 link_type, u8 addr_type, s8 rssi, u8 *name, u8 name_len) { diff --git a/net/bluetooth/msft.c b/net/bluetooth/msft.c index d9dd722db3eb..2559c5b1bef0 100644 --- a/net/bluetooth/msft.c +++ b/net/bluetooth/msft.c @@ -654,8 +654,10 @@ void msft_do_open(struct hci_dev *hdev) msft->features = 0; if (!read_supported_features(hdev, msft)) { + hci_dev_lock(hdev); hdev->msft_data = NULL; kfree(msft); + hci_dev_unlock(hdev); return; } @@ -681,6 +683,8 @@ void msft_do_close(struct hci_dev *hdev) bt_dev_dbg(hdev, "Cleanup of MSFT extension"); + hci_dev_lock(hdev); + /* The controller will silently remove all monitors on power off. * Therefore, remove handle_data mapping and reset monitor state. */ @@ -695,6 +699,8 @@ void msft_do_close(struct hci_dev *hdev) kfree(handle_data); } + hci_dev_unlock(hdev); + mutex_lock(&msft->filter_lock); list_for_each_entry_safe(address_filter, n, &msft->address_filters, list) { diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c index 54ec1136f87e..8a4205347c4a 100644 --- a/net/bluetooth/rfcomm/core.c +++ b/net/bluetooth/rfcomm/core.c @@ -1740,10 +1740,8 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb return 0; if (cr) { - if (msc->v24_sig & RFCOMM_V24_FC && !d->cfc) - set_bit(RFCOMM_TX_THROTTLED, &d->flags); - else - clear_bit(RFCOMM_TX_THROTTLED, &d->flags); + assign_bit(RFCOMM_TX_THROTTLED, &d->flags, + msc->v24_sig & RFCOMM_V24_FC && !d->cfc); rfcomm_dlc_lock(d); diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c index b26918dc9e9e..3fb8b5474948 100644 --- a/net/bluetooth/rfcomm/sock.c +++ b/net/bluetooth/rfcomm/sock.c @@ -724,10 +724,7 @@ static int rfcomm_sock_setsockopt(struct socket *sock, int level, int optname, if (err) break; - if (opt) - set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); - else - clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); + assign_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags, opt); break; diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c index f4a20d7b5f9c..8be48ca9f4c5 100644 --- a/net/bluetooth/sco.c +++ b/net/bluetooth/sco.c @@ -1037,10 +1037,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, if (err) break; - if (opt) - set_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); - else - clear_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags); + assign_bit(BT_SK_DEFER_SETUP, &bt_sk(sk)->flags, opt); break; case BT_VOICE: @@ -1080,10 +1077,7 @@ static int sco_sock_setsockopt(struct socket *sock, int level, int optname, if (err) break; - if (opt) - set_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); - else - clear_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags); + assign_bit(BT_SK_PKT_STATUS, &bt_sk(sk)->flags, opt); break; case BT_CODEC: diff --git a/net/bluetooth/selftest.c b/net/bluetooth/selftest.c index ae5b44bb9d3d..cdfc40e0016b 100644 --- a/net/bluetooth/selftest.c +++ b/net/bluetooth/selftest.c @@ -188,6 +188,7 @@ static ssize_t test_ecdh_read(struct file *file, char __user *user_buf, } static const struct file_operations test_ecdh_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = test_ecdh_read, .llseek = default_llseek, diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c index 2df303f6a38f..5dac8b2eae42 100644 --- a/net/bluetooth/smp.c +++ b/net/bluetooth/smp.c @@ -366,7 +366,7 @@ static int smp_e(const u8 *k, u8 *r) err = aes_prepareenckey(&aes, tmp, 16); if (err) { BT_ERR("cipher setkey failed: %d", err); - return err; + goto out_clear; } /* Most significant octet of plaintextData corresponds to data[0] */ @@ -379,6 +379,8 @@ static int smp_e(const u8 *k, u8 *r) SMP_DBG("r %16phN", r); +out_clear: + memzero_explicit(tmp, sizeof(tmp)); memzero_explicit(&aes, sizeof(aes)); return err; } @@ -3696,6 +3698,7 @@ static ssize_t test_smp_read(struct file *file, char __user *user_buf, } static const struct file_operations test_smp_fops = { + .owner = THIS_MODULE, .open = simple_open, .read = test_smp_read, .llseek = default_llseek, |
