Commit Graph

5929 Commits

Author SHA1 Message Date
Linus Torvalds
734bef548a Networking changes for 7.4.
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
 
 Signed-off-by: Paolo Abeni <pabeni@redhat.com>
 -----BEGIN PGP SIGNATURE-----
 
 iQJKBAABCgA0FiEEg1AjqC77wbdLX2LbKSR5jcyPE6QFAmraNIAWHHBhb2xvLmFi
 ZW5pQGdtYWlsLmNvbQAKCRApJHmNzI8TpBaeD/9iBxxaZzworKk3v+RalWo4noIC
 QsZ8E0Du7vDruS2nESbZpUpf0lKxNxJVnXEj/q0acObzUuGFJBaqZ8Uzn337w6WK
 nuM1YppPE9lIMNAgDhxKUIMGeVLHuQd3wQPsOs0nlywNehzrKYAfCUtcB3xD2H+I
 xaUdTRooop5l6GpSS0CP7li/kzHb5GagVI2VmoOFCb+0BPl6tr+ITW8s0/Z/oyZC
 Lx4Fl0Hhj0li4eHr0DS3vgS7jqmPFYOxo4zhGzXqCYaagPpvazR9RfFhP16BfJ/D
 TPI3oIkqcyvttrTtgwYhLDJjw1+m+r1vmhel7Tp5XLHQJ4WXuunPBGrq9w7Xd+IF
 JLd8VbUiXB2A/+fNSD3Q1nzukjRjlEsR2ZyRqAWqXWDhXYbAd0D/vptJJwem1ozm
 RRoe9Gk2N+iSsqvfAq6coTRPEKrlsh27v36uWQZgQ2jA2SnrNsTuJwlhiET0Jc6T
 kTEM0yjLDiUxsefOgGs5s10EnfLa2sL/0NWow0s83x6Dm3f3x2fvm2e0UlI3gLNI
 43AgMaNO1IsNOWEiJC/O81pt/6FuF8cX+cJXtlLBW1ZTJnEnVtNlafJVnyfblblx
 TXyzGtM0cUXyJsaS8/Qx1GUQO9N9MiWI4mCtDUWthBxvdpkn93G0pNXwnjybcnAH
 0nX3+pVqFZCrG/PmvQ==
 =ZOCE
 -----END PGP SIGNATURE-----

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
  ...
2026-10-22 15:58:00 -10:00
Nicolai Buchwitz
258c3ae4a4 net: rename skb_unshare() to skb_unclone_full()
skb_unshare() only copies cloned skbs. A shared skb that is not a clone
comes back unchanged, which the name doesn't suggest. The loopback
selftest hooks got caught by this and hit BUG_ON(skb_shared()).

Rename it to skb_unclone_full(). Like skb_unclone() it only acts on
clones, but it copies the whole skb, not just the head.

Suggested-by: Jakub Kicinski <kuba@kernel.org>
Signed-off-by: Nicolai Buchwitz <nb@tipi-net.de>
Reviewed-by: Ioana Ciornei <ioana.ciornei@nxp.com> # dpaa2
Link: https://patch.msgid.link/20261015-nb-skb-unclone-full-v1-1-0dfbf01f60f2@tipi-net.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
2026-10-20 11:28:49 -07:00
Kyle Pepper
397464709a Bluetooth: hci_sync: scan unfiltered for host-resolved RPAs
Restore unfiltered scanning for pending IRK peers when the controller
cannot resolve private addresses. Keep accept-list filtering while
suspended and when forced by periodic advertising synchronization.

Fixes: e209e5ccc5 ("Bluetooth: MGMT: Mark LL Privacy as stable")
Assisted-by: OpenCode:gpt-6.1-sol
Signed-off-by: Kyle Pepper <cochcoder@proton.me>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:29 -04:00
Luiz Augusto von Dentz
5874f8d032 Bluetooth: Fix the LE Read Connection Interval response layout
The response to HCI_OP_LE_READ_CONN_INTERVAL carries a
Minimum_Supported_Connection_Interval octet between the status and
Num_Groups, which was missing from the structure. Without it the minimum
interval was read as the number of groups, and every group after it
from one octet off.

Take the minimum interval used to clamp the default rate parameters from
that field rather than the smallest group minimum, as the number of
groups can be zero, which left it unset.

Fixes: 2f8784cfe8 ("Bluetooth: Add support for Shorter Connection Interval (SCI) feature")
Assisted-by: OpenCode:claude-opus-5.5
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:29 -04:00
Siwei Zhang
76a7545451 Bluetooth: L2CAP: Remove dead configuration state code
CONF_EWS_RECV has not been set since commit
e7b02296fb ("Bluetooth: Remove BT_HS"), which
made configuration requests with an EWS option
be refused. Remove the flag and the branch in
l2cap_parse_conf_req() that tests it.

A pending connection response no longer needs to
set CONF_CONNECT_PEND, as connection responses are
only accepted while it is already set.

No functional change.

Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:28 -04:00
Siwei Zhang
a518b9a9ef Bluetooth: L2CAP: Only accept connection responses to outstanding requests
An outgoing channel waits in BT_CONNECT until security
and the feature mask exchange complete, and only then
sends its connection request. A peer can answer it
before that with a connection response matching our
source CID. The channel then moves to BT_CONFIG,
completes configuration and becomes connected before
security has completed. If security then fails,
l2cap_security_cfm() leaves the connected channel
alone, so it stays up on a link that did not reach
the required security level.

A connection response with a zero source CID is
matched by identifier. Another channel can hold the
same identifier for a response it still has to send,
so the lookup can pick the wrong channel.

Only accept a connection response while our request
is outstanding, and only look at such channels when
matching by identifier.

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:28 -04:00
Siwei Zhang
226fa3b676 Bluetooth: L2CAP: Use default TxWindow for zero socket option
L2CAP_OPTIONS accepts a txwin_size of zero and
stores it in tx_win. The zero is then sent to the
peer in our configuration request, and if the
channel ends up in ERTM mode it is passed to
l2cap_seq_list_init().

Use the default TxWindow instead, as the mode can
still be changed to ERTM during configuration.

Fixes: 14b5aa71ec ("Bluetooth: Add sockopt configuration for txWindow on L2CAP")
Cc: stable@vger.kernel.org
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:28 -04:00
Siwei Zhang
c5ebb0245f Bluetooth: L2CAP: Reject invalid TxWindow in configuration requests
A peer can send an ERTM RFC option with a TxWindow
of zero, which is out of spec. It is stored in
remote_tx_win unchanged and later passed to
l2cap_seq_list_init(), where roundup_pow_of_two(0)
is undefined. On some architectures this results in
a ZERO_SIZE_PTR list and a remote kernel oops.

A TxWindow above 63 is out of spec as well. With
6-bit sequence numbers we would then send more
unacknowledged frames than the sequence space can
tell apart.

Reply with L2CAP_CONF_UNACCEPT and propose the
default TxWindow instead of accepting the value, so
remote_tx_win always stays within 1 to 63. Keep the
parameters of an earlier request then, and do not
treat the request as done because an earlier one was.

Also refuse a zero size in l2cap_seq_list_init(), so
any other path that reaches it with a zero TxWindow
fails the channel instead of the kernel.

Fixes: f2fcfcd670 ("Bluetooth: Add configuration support for ERTM and Streaming mode")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:28 -04:00
Siwei Zhang
6320736af7 Bluetooth: L2CAP: Reject signalling responses in invalid states
A peer can send configuration messages while an
incoming channel is in BT_CONNECT2, before the
security or deferred accept gate has completed. A
configuration response can then promote the channel
to BT_CONNECTED. Configuration responses can also
act on channels that are closing, and a late connection
response can move a disconnecting channel back to
BT_CONFIG.

Accept connection responses only while waiting in
BT_CONNECT. Answer configuration requests in
BT_CONNECT2, but defer our own request until
BT_CONFIG so configuration cannot complete before
the gate. Ignore configuration responses outside
BT_CONFIG and BT_CONNECTED, and only complete
configuration in BT_CONFIG.

Fixes: 1da177e4c3 ("Linux-2.6.12-rc2")
Cc: stable@vger.kernel.org
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:27 -04:00
Siwei Zhang
c1398cf11b Bluetooth: L2CAP: Reject mode changes on connected channels
A peer can send a configuration response with an RFC
option for another mode to a connected channel, for
example to switch it from Streaming to ERTM mode.
l2cap_parse_conf_rsp() then changes chan->mode, but
l2cap_ertm_init() is not called again, so the ERTM
sequence lists are never allocated. The next
out-of-sequence I-frame makes l2cap_seq_list_clear()
write through the NULL srej_list.list.

Refuse the channel when a response tries to change
the mode of a connected channel.

Fixes: f2fcfcd670 ("Bluetooth: Add configuration support for ERTM and Streaming mode")
Cc: stable@vger.kernel.org
Closes: https://sashiko.dev/#/patchset/20261007144717.3832330-1-oss%40fourdim.xyz
Assisted-by: Claude:claude-opus-5-5
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:27 -04:00
Kevin Dewald
91638f53ff Bluetooth: hci_event: Fix LE link drop on remote features command status
When the local controller supports peripheral-initiated features
exchange, the LE Read Remote Features procedure also runs for incoming
connections, and it fails with Unsupported Remote Feature (0x1a) if the
central does not support that feature. hci_le_remote_feat_complete_evt()
and hci_le_read_all_remote_features_evt() handle this and let the
connection transition into connected state.

A controller can also return that error in the Command Status event
instead. An Intel controller does so for a central that does not
support peripheral-initiated features exchange, presumably because it
already has the features of the central. hci_cs_le_read_remote_features()
and hci_cs_le_read_all_remote_features() then confirm the connection as
failed while it is still in BT_CONFIG, and the hci_conn_drop() in
le_read_features_complete() disconnects it right away:

  > HCI Event: LE Meta Event (0x3e) plen 31
      LE Enhanced Connection Complete (0x0a)
        Status: Success (0x00)
        Role: Peripheral (0x01)
  < HCI Command: LE Read Remote Used Features (0x08|0x0016) plen 2
  > HCI Event: Command Status (0x0f) plen 4
      LE Read Remote Used Features (0x08|0x0016) ncmd 1
        Status: Unsupported Remote Feature / Unsupported LMP Feature (0x1a)
  < HCI Command: Disconnect (0x01|0x0006) plen 3
        Reason: Remote User Terminated Connection (0x13)

Data the central sends afterwards is reported as:

  Bluetooth: hci0: ACL packet for unknown connection handle 3585

Handle Unsupported Remote Feature in the command status the same way as
in the complete events.

Fixes: 0fe29fd1cd ("Bluetooth: Read LE remote features during connection establishment")
Fixes: a106e50be7 ("Bluetooth: HCI: Add support for LL Extended Feature Set")
Assisted-by: Claude:claude-opus-5.5
Signed-off-by: Kevin Dewald <kevin@simpleble.org>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:27 -04:00
Cen Zhang
56e20c3d8a Bluetooth: MSFT: Serialize handle map cleanup with event processing
MSFT monitor handle mappings must remain valid while vendor events look
up and use them under hdev->lock. msft_do_close() removes and frees the
mappings without that lock.

hci_dev_close_sync() clears HCI_UP and drains the RX workqueue before
MSFT cleanup. However, a transport callback that already passed
hci_recv_frame()'s state check can queue a vendor event after the drain
returns, if no earlier shutdown callback has quiesced reception. The
driver close callback runs after MSFT cleanup, so event processing can
overlap the unlocked removal. msft_monitor_device_evt() can then
traverse freed list entries or read handle_data->mgmt_handle after it is
freed.

Take hdev->lock while resetting monitor states and removing handle
mappings in msft_do_close(), as normal monitor cancellation already
does. An active event reader then finishes before its mapping is freed,
and later lookups see an empty handle map.

An instrumented kernel produced this KASAN report (timestamps removed
and unrelated frames omitted):

    BUG: KASAN: slab-use-after-free in msft_vendor_evt+0x1906/0x1990
    Read of size 2 at addr ffff888104df3602 by task kworker/u17:2/502

    Workqueue: hci0 hci_rx_work
    Call Trace:
      [...]
      msft_vendor_evt+0x1906/0x1990
      hci_vendor_evt+0x6f/0x90
      hci_event_packet+0x894/0xc70
      [...]
      hci_rx_work+0x3f8/0xfa0
      [...]

    Allocated by task 499:
      [...]
      msft_add_monitor_sync+0x6a8/0x10a0
      msft_add_monitor_pattern+0x7f/0xb0
      hci_add_adv_monitor+0x1fa/0x2e0
      [...]

    Freed by task 499:
      [...]
      kfree+0x307/0x580
      msft_do_close+0x238/0x750
      hci_dev_close_sync+0x546/0x1380
      [...]

    The buggy address belongs to the object at ffff888104df3600
      which belongs to the cache kmalloc-32 of size 32
    The buggy address is located 2 bytes inside of
      freed 32-byte region [ffff888104df3600, ffff888104df3620)
    [...]

Fixes: 145373cb1b ("Bluetooth: Add framework for Microsoft vendor extension")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:26 -04:00
Luiz Augusto von Dentz
47493e62e8 Bluetooth: MGMT: Allow connection rate request as peripheral
Load Connection Subrate only issues the LE Connection Rate Request when
connected as central, but either role can initiate the Connection Rate
Update procedure, e.g. a HID device, which is the peripheral, does it
once the HID host requests a HID SCI mode with the HID Control Point.

Issue it regardless of the role.

Fixes: 19129d7037 ("Bluetooth: Add MGMT Load Connection Subrate command")
Assisted-by: OpenCode:claude-opus-5.5
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:26 -04:00
Bui Viet Dung
64aabf94ec Bluetooth: selftest: Pin module for selftest debugfs file operations
An open debugfs file retains its file_operations pointer in the
debugfs proxy state. However, test_smp_fops in net/bluetooth/smp.c and
test_ecdh_fops in net/bluetooth/selftest.c have no .owner set to
THIS_MODULE.

As a result, full_proxy_open_regular() calls fops_get() which succeeds
without taking a reference to the bluetooth module. When CONFIG_BT=m
and selftests are enabled, a userspace process can open either
/sys/kernel/debug/bluetooth/selftest_smp or
/sys/kernel/debug/bluetooth/selftest_ecdh and keep the file descriptor
open while the module is unloaded (rmmod bluetooth).

When the userspace process subsequently closes the descriptor,
full_proxy_release() accesses the already unmapped file_operations
structure, triggering a kernel oops in full_proxy_release():

  BUG: unable to handle page fault for address: fffffbfff8056f03
  #PF: supervisor read access in kernel mode
  Oops: 0000 [#1] SMP KASAN NOPTI
  RIP: 0010:full_proxy_release+0x8e/0x140
  Call Trace:
   <TASK>
   __fput+0x39f/0xa60
   fput_close_sync+0xff/0x200
   __x64_sys_close+0x8c/0xf0
   do_syscall_64+0x115/0x6a0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f
   </TASK>

The issue was discovered via manual code audit of net/bluetooth/smp.c
and net/bluetooth/selftest.c.

Set .owner = THIS_MODULE on test_smp_fops and test_ecdh_fops so that
debugfs keeps the module pinned until the file descriptors are closed.

Fixes: 64dd374eac ("Bluetooth: Export SMP selftest result in debugfs")
Fixes: 6de50f9fdb ("Bluetooth: Export ECDH selftest result in debugfs")
Cc: stable@vger.kernel.org
Signed-off-by: Bui Viet Dung <dungvn2345@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:25 -04:00
Cen Zhang
4020751fd0 Bluetooth: L2CAP: Hold the listener while notifying child teardown
A pending child's listener must remain alive until the child's teardown
callback finishes notifying it. l2cap_sock_teardown_cb() saves the raw
bt_sk(sk)->parent pointer, calls bt_accept_unlink(), then invokes
parent->sk_data_ready(). The accept queue holds a reference to the
child, but the callback takes no reference to the listener across
unlink.

When an incoming child has not been accepted, HCI disconnection can
reach l2cap_conn_del() and the child's teardown callback while another
task closes the listener. The listener channel has no connection, so the
child's connection and channel locks do not serialize listener release.
The following ordering is possible:

  HCI child teardown                 Listener release
  lock the child socket
  save parent
  bt_accept_unlink(sk)
                                     drain the empty accept queue
                                     bt_sock_unlink()
                                     shut down the listener channel
                                     sock_orphan()
                                     l2cap_sock_kill()
  parent->sk_data_ready(parent)

If no other reference delays freeing the listener, the final
notification reads sk_data_ready through freed socket storage. The child
lock cannot stop listener release once the child is no longer on the
accept queue.

Take a listener socket reference before unlinking the child and release
it after sk_data_ready() returns. While the child remains queued, its
socket lock prevents listener cleanup from completing the dequeue, so
the listener is still alive when the reference is acquired. The
reference then protects the notification after unlink without changing
lock order or the ordering of queue removal and wakeup.

KASAN report as below:

    ==================================================================
    BUG: KASAN: slab-use-after-free in l2cap_sock_teardown_cb+0x467/0x490
    Read of size 8 at addr ffff88810b99b188 by task kworker/u17:3/516

    Workqueue: hci1 hci_rx_work
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? l2cap_sock_teardown_cb+0x467/0x490
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? l2cap_sock_teardown_cb+0x467/0x490
     kasan_report+0xe0/0x110
     ? l2cap_sock_teardown_cb+0x467/0x490
     l2cap_sock_teardown_cb+0x467/0x490
     l2cap_chan_del+0x123/0x8f0
     l2cap_conn_del+0x31b/0x740
     ? hci_cmd_sync_submit+0x264/0x320
     ? __pfx_l2cap_disconn_cfm+0x10/0x10
     l2cap_disconn_cfm+0x87/0xd0
     hci_disconn_complete_evt+0x30f/0x990
     ? srso_alias_return_thunk+0x5/0xfbef5
     hci_event_packet+0x894/0xc70
     ? __pfx_hci_disconn_complete_evt+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_hci_event_packet+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? free_zapped_rcu+0xd0/0x1e0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lockdep_hardirqs_on_prepare+0xea/0x1a0
     ? __pfx_hci_cmd_sync_complete+0x10/0x10
     ? trace_hardirqs_on+0x18/0x160
     ? srso_alias_return_thunk+0x5/0xfbef5
     hci_rx_work+0x367/0xf00
     ? srso_alias_return_thunk+0x5/0xfbef5
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>

    Allocated by task 502:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_noprof+0x2d7/0x770
     sk_prot_alloc+0x13e/0x260
     sk_alloc+0x37/0xb40
     bt_sock_alloc+0x40/0x3b0
     l2cap_sock_create+0x116/0x310
     bt_sock_create+0x171/0x330
     __sock_create+0x2c4/0x730
     __sys_socket+0x141/0x210
     __x64_sys_socket+0x77/0xc0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    Freed by task 502:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     kfree+0x307/0x580
     __sk_destruct+0x64f/0x790
     sk_destruct+0xb3/0xd0
     __sk_free+0xdd/0x370
     sk_free+0x51/0x80
     l2cap_sock_kill+0x17a/0x2a0
     l2cap_sock_release+0x1d0/0x310
     __sock_release+0xb8/0x270
     sock_close+0x21/0x30
     __fput+0x39f/0xa60
     fput_close_sync+0xff/0x200
     __x64_sys_close+0x8c/0xf0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    The buggy address belongs to the object at ffff88810b99b000
                                                                which
                                belongs to the cache kmalloc-2k of size
                                2048
    The buggy address is located 392 bytes inside of
                                                                freed
                                2048-byte region [ffff88810b99b000,
                                ffff88810b99b800)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
    pfn:0x10b998
    head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
    flags: 0x200000000000040(head|node=0|zone=2)
    page_type: f5(slab)
        raw: 0200000000000040 ffff888100042f00 dead000000000100
    dead000000000122
        raw: 0000000000000000 0000000000080008 00000000f5000000
    0000000000000000
        head: 0200000000000040 ffff888100042f00 dead000000000100
    dead000000000122
        head: 0000000000000000 0000000000080008 00000000f5000000
    0000000000000000
        head: 0200000000000003 fffffffffffffe01 00000000ffffffff
    00000000ffffffff
        head: 0000000000000000 0000000000000000 00000000ffffffff
    0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
     ffff88810b99b080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff88810b99b100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    >ffff88810b99b180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                          ^
     ffff88810b99b200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff88810b99b280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ==================================================================

Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:25 -04:00
Cen Zhang
4b76fa3621 Bluetooth: hci_sync: Protect IRK identity reads with RCU
hci_le_set_privacy_mode_sync() needs the IRK returned by
hci_find_irk_by_addr() to remain allocated until its identity address
and type have been copied into the command. The finder drops its RCU
read lock before returning this borrowed pointer, leaving the later
field reads unprotected.

When a privacy-capable controller has a pending peer with address
resolution and device privacy enabled, accept-list programming can
reach this helper while management reloads the IRKs. The request
worker holds hdev->req_lock, whereas load_irks() takes hdev->lock,
allowing the following ordering:

  Request worker                     Management / RCU reclaim
  hci_le_set_privacy_mode_sync()
    hci_find_irk_by_addr()
      rcu_read_lock()
      find matching IRK
      rcu_read_unlock()
      return borrowed IRK
                                     load_irks()
                                       hci_dev_lock(hdev)
                                       hci_smp_irks_clear()
                                         list_del_rcu()
                                         kfree_rcu()
                                       hci_dev_unlock(hdev)
                                     RCU grace period and IRK free
    read irk->addr_type
    copy irk->bdaddr

The request then accesses a freed IRK. KASAN reports a one-byte
use-after-free read of addr_type on this path.

Keep an outer RCU read-side critical section across the lookup and
both identity-field copies. The finder's nested unlock then leaves
the IRK protected until the caller finishes copying it. Release RCU
on a lookup miss and after copying the fields, before the synchronous
HCI command can sleep.

KASAN report as below:

    ==================================================================
        BUG: KASAN: slab-use-after-free in
    hci_le_add_accept_list_sync+0x90f/0x940
    Read of size 1 at addr ffff88810aa6072c by task kworker/u17:0/493

    Workqueue: hci0 hci_cmd_sync_work
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? hci_le_add_accept_list_sync+0x90f/0x940
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? hci_le_add_accept_list_sync+0x90f/0x940
     kasan_report+0xe0/0x110
     ? hci_le_add_accept_list_sync+0x90f/0x940
     hci_le_add_accept_list_sync+0x90f/0x940
     ? __pfx_hci_le_add_accept_list_sync+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? conn_params_copy+0x3a0/0x650
     hci_passive_scan_sync+0x8c9/0x1e80
     ? __pfx_hci_passive_scan_sync+0x10/0x10
     ? find_held_lock+0x2b/0x80
     ? hci_lookup_le_connect+0x181/0x3c0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? find_held_lock+0x2b/0x80
     ? hci_update_passive_scan_sync+0x437/0x950
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_release+0xc8/0x280
     hci_update_passive_scan_sync+0x461/0x950
     hci_cmd_sync_work+0x1b3/0x450
     ? srso_alias_return_thunk+0x5/0xfbef5
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>

    Allocated by task 507:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_cache_noprof+0x251/0x610
     hci_add_irk+0xb6/0x220
     load_irks+0x5ef/0x7e0
     hci_sock_sendmsg+0x128b/0x22e0
     __sys_sendto+0x425/0x470
     __x64_sys_sendto+0xe5/0x1c0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    Freed by task 0:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     __rcu_free_sheaf_prepare+0x65/0x2a0
     rcu_free_sheaf+0x1f/0xe0
     rcu_core+0x661/0x1d10
     handle_softirqs+0x201/0x930
     __irq_exit_rcu+0x110/0x1e0
     irq_exit_rcu+0xe/0x20
     sysvec_apic_timer_interrupt+0x6c/0x80
     asm_sysvec_apic_timer_interrupt+0x1a/0x20

    The buggy address belongs to the object at ffff88810aa60700
     which belongs to the cache kmalloc-64 of size 64
    The buggy address is located 44 bytes inside of
     freed 64-byte region [ffff88810aa60700, ffff88810aa60740)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
    pfn:0x10aa60
    flags: 0x200000000000000(node=0|zone=2)
    page_type: f5(slab)
        raw: 0200000000000000 ffff8881000428c0 dead000000000100
    dead000000000122
        raw: 0000000000000000 0000000000200020 00000000f5000000
    0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
     ffff88810aa60600: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
     ffff88810aa60680: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
    >ffff88810aa60700: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
                                      ^
     ffff88810aa60780: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
     ffff88810aa60800: fa fb fb fb fb fb fb fb fc fc fc fc fc fc fc fc
    ==================================================================
    Disabling lock debugging due to kernel taint

Fixes: adae20cb2d ("Bluetooth: Convert IRK list to RCU")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:24 -04:00
Bui Viet Dung
2a3e228787 Bluetooth: hci_debugfs: Pin module for debugfs file operations
An open debugfs file retains its file_operations pointer in the
debugfs proxy state. However, the file_operations defined in
hci_debugfs.c (use_debug_keys_fops, sc_only_mode_fops,
ssp_debug_mode_fops, force_bredr_smp_fops, force_static_address_fops,
force_no_mitm_fops, dut_mode_fops, vendor_diag_fops, and the
DEFINE_QUIRK_ATTRIBUTE macro) have no .owner set to THIS_MODULE.

As a result, full_proxy_open_regular() calls fops_get() which succeeds
without taking a reference to the bluetooth module. When a userspace
process opens any of these debugfs files, a subsequent controller removal
and module unload (rmmod bluetooth) can succeed while the file descriptor
remains open.

When the userspace process subsequently closes the descriptor,
full_proxy_release() accesses the already unmapped file_operations
structure, triggering a kernel oops in full_proxy_release():

  BUG: unable to handle page fault for address: fffffbfff8056f03
  #PF: supervisor read access in kernel mode
  Oops: 0000 [#1] SMP KASAN NOPTI
  RIP: 0010:full_proxy_release+0x8e/0x140
  Call Trace:
   <TASK>
   __fput+0x39f/0xa60
   fput_close_sync+0xff/0x200
   __x64_sys_close+0x8c/0xf0
   do_syscall_64+0x115/0x6a0
   entry_SYSCALL_64_after_hwframe+0x77/0x7f
   </TASK>

The issue was discovered via manual code audit of
net/bluetooth/hci_debugfs.c and verified on a Linux 7.3-rc6 test VM
with CONFIG_BT=m.

Set .owner = THIS_MODULE on all debugfs file_operations tables in
hci_debugfs.c so that debugfs keeps the module loaded until close has
finished.

Fixes: 0886aea6ac ("Bluetooth: Expose debug keys usage setting via debugfs")
Cc: stable@vger.kernel.org
Signed-off-by: Bui Viet Dung <dungvn2345@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:24 -04:00
Bui Viet Dung
8368f0c2cd Bluetooth: 6lowpan: Pin module for 6lowpan_control debugfs file
An open debugfs file retains lowpan_control_fops in the debugfs proxy
state. However, lowpan_control_fops has no .owner set to THIS_MODULE.
As a result, full_proxy_open_regular() calls fops_get() which succeeds
without taking a reference to the bluetooth_6lowpan module.

With CONFIG_BT_6LOWPAN=m, a userspace process can keep the debugfs file
descriptor for 6lowpan_control open across module unload
(delete_module / rmmod bluetooth_6lowpan). When the process subsequently
closes the file descriptor, full_proxy_release() accesses the already
freed and unmapped lowpan_control_fops table, causing a kernel page fault
or oops.

The issue was discovered via manual code audit of
net/bluetooth/6lowpan.c.

Set .owner = THIS_MODULE on lowpan_control_fops so that debugfs pins
the module until all open file descriptors have finished.

Fixes: 6b8d4a6a03 ("Bluetooth: 6LoWPAN: Use connected oriented channel instead of fixed one")
Cc: stable@vger.kernel.org
Signed-off-by: Bui Viet Dung <dungvn2345@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:23 -04:00
Cen Zhang
ebba800d14 Bluetooth: 6lowpan: Drain RCU readers on registration failure
A lowpan_btle_dev is embedded in its net_device allocation and must
remain alive until readers of bt_6lowpan_devices have left their RCU
sections. setup_netdev() publishes it before registration, but its
error path only unlinks it before calling free_netdev().

If a second controller's registration fails while multicast is sent
on an existing 6LoWPAN interface, send_mcast_pkt() can already have
selected the new entry. It reads entry->netdev before checking which
interface owns it. An early failure, such as allocating the device's
name node, leaves NETREG_UNINITIALIZED, so free_netdev() releases the
storage immediately.

The following ordering frees the selected entry before the reader
loads its netdev field:

  Adapter creation (controller B)       Multicast on controller A
  setup_netdev()
    list_add_rcu()
                                       rcu_read_lock()
                                       select B's entry
    lowpan_register_netdev() fails
    list_del_rcu()
    free_netdev()
                                       read entry->netdev
                                       rcu_read_unlock()

Removing the list node does not wait for that reader, and
devices_lock does not serialize the multicast reader. The subsequent
field load is a use-after-free, reported by KASAN in bt_xmit().

Wait for an RCU grace period after dropping devices_lock and before
free_netdev(). This keeps the failed adapter allocated until traversals
that could have selected it complete. The callback is already sleepable,
and the wait happens outside the list spinlock.

KASAN report as below:

    ==================================================================
    BUG: KASAN: slab-use-after-free in bt_xmit+0x1d06/0x21e0
    Read of size 8 at addr ffff88810ef45030 by task python3/556

    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? bt_xmit+0x1d06/0x21e0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? bt_xmit+0x1d06/0x21e0
     kasan_report+0xe0/0x110
     ? bt_xmit+0x1d06/0x21e0
     bt_xmit+0x1d06/0x21e0
     ? __pfx_bt_xmit+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_acquire+0x17b/0x2f0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? dev_hard_start_xmit+0x187/0x660
     ? __pfx_bt_xmit+0x10/0x10
     dev_hard_start_xmit+0x187/0x660
     sch_direct_xmit+0x153/0x850
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_sch_direct_xmit+0x10/0x10
     ? do_raw_spin_lock+0x130/0x270
     ? __pfx_do_raw_spin_lock+0x10/0x10
     ? lock_is_held_type+0x8f/0x100
     __dev_queue_xmit+0x3111/0x3aa0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? look_up_lock_class+0x59/0x130
     ? register_lock_class+0x41/0x790
     ? __pfx___dev_queue_xmit+0x10/0x10
     ? __lock_acquire+0x466/0x2260
     ? find_held_lock+0x2b/0x80
     ? ___neigh_create+0x1690/0x2540
     ? __local_bh_enable_ip+0xa6/0x120
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lockdep_hardirqs_on_prepare+0xea/0x1a0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_acquire+0x17b/0x2f0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? find_held_lock+0x2b/0x80
     ? ip6_finish_output2+0x8be/0x1840
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? neigh_connected_output+0x39f/0x4e0
     ? srso_alias_return_thunk+0x5/0xfbef5
     neigh_connected_output+0x33f/0x4e0
     ip6_finish_output2+0x8be/0x1840
     ip6_finish_output+0x424/0xd50
     ip6_output+0x210/0x640
     ? __pfx_ip6_mr_output+0x10/0x10
     ip6_local_out+0x193/0x1c0
     ip6_send_skb+0xfb/0x3e0
     udp_v6_send_skb+0x6e1/0x1180
     udpv6_sendmsg+0x1f9b/0x2a00
     ? get_random_u32+0xaf/0x640
     ? __pfx_udpv6_sendmsg+0x10/0x10
     ? lock_release+0xc8/0x280
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lockdep_hardirqs_on_prepare+0xea/0x1a0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? trace_hardirqs_on+0x18/0x160
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __local_bh_enable_ip+0xa6/0x120
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_udpv6_sendmsg+0x10/0x10
     ? inet6_sendmsg+0xff/0x140
     inet6_sendmsg+0xff/0x140
     __sys_sendto+0x320/0x470
     ? __pfx___sys_sendto+0x10/0x10
     ? exc_page_fault+0x5c/0xc0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_release+0xc8/0x280
     ? handle_mm_fault+0x12e/0x580
     __x64_sys_sendto+0xe5/0x1c0
     ? lockdep_hardirqs_on_prepare+0xea/0x1a0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? trace_hardirqs_on+0x18/0x160
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f
    Allocated by task 502:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kvmalloc_node_noprof+0x353/0x930
     alloc_netdev_mqs+0xa0/0x1250
     chan_ready_cb+0x198/0x1110
     l2cap_recv_frame+0x6dc0/0x8830
     l2cap_recv_acldata+0xe9f/0x10e0
     hci_rx_work+0x5a6/0xf00
     process_one_work+0x908/0x19c0
     worker_thread+0x65c/0xe40
     kthread+0x34f/0x460
     ret_from_fork+0x659/0x940
     ret_from_fork_asm+0x1a/0x30

    Freed by task 502:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     kfree+0x307/0x580
     free_netdev+0x6ca/0x8f0
     chan_ready_cb+0xd91/0x1110
     l2cap_recv_frame+0x6dc0/0x8830
     l2cap_recv_acldata+0xe9f/0x10e0
     hci_rx_work+0x5a6/0xf00
     process_one_work+0x908/0x19c0
     worker_thread+0x65c/0xe40
     kthread+0x34f/0x460
     ret_from_fork+0x659/0x940
     ret_from_fork_asm+0x1a/0x30

    The buggy address belongs to the object at ffff88810ef44000
                                                                which
                                belongs to the cache kmalloc-8k of size
                                8192
    The buggy address is located 4144 bytes inside of
                                                                freed
                                8192-byte region [ffff88810ef44000,
                                ffff88810ef46000)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
    pfn:0x10ef40
    head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
    flags: 0x200000000000040(head|node=0|zone=2)
    page_type: f5(slab)
        raw: 0200000000000040 ffff888100043180 dead000000000100
    dead000000000122
        raw: 0000000000000000 0000000000020002 00000000f5000000
    0000000000000000
        head: 0200000000000040 ffff888100043180 dead000000000100
    dead000000000122
        head: 0000000000000000 0000000000020002 00000000f5000000
    0000000000000000
        head: 0200000000000003 fffffffffffffe01 00000000ffffffff
    00000000ffffffff
        head: ffff88810ef41a80 0000000000000000 00000000ffffffff
    0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
     ffff88810ef44f00: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff88810ef44f80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    >ffff88810ef45000: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                                         ^
     ffff88810ef45080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff88810ef45100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ==================================================================
    Disabling lock debugging due to kernel taint

Fixes: 5857d1dbae ("Bluetooth: 6lowpan: Fix possible race")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:23 -04:00
Cen Zhang
21895f20fe Bluetooth: msft: Lock failed probe cleanup against feature readers
The MSFT data must remain allocated while msft_get_features() reads
its features. read_adv_mon_features() protects that access with
hdev->lock, but msft_do_open() clears hdev->msft_data and frees the
object without that lock when read_supported_features() fails.

After a successful probe, the data survives a normal close. A later
open can fail the probe while a management feature request is running.
hci_mgmt_cmd() permits requests during HCI_INIT, and the opener's
hdev->req_lock does not serialize the management reader:

  Management feature request            HCI open
                                        hold hdev->req_lock
                                        msft_do_open()
  hold hdev->lock
  msft_get_features(): save msft
                                        read_supported_features() fails
                                        hdev->msft_data = NULL
                                        kfree(msft)
  read msft->features
  release hdev->lock                     release hdev->req_lock

The saved pointer then refers to freed memory, causing a use-after-free
read. Advertisement reporting through mgmt_device_found() also reads
the features with hdev->lock held.

Take hdev->lock around clearing and freeing msft_data in the failure
branch. An existing feature reader finishes before the free, while a
reader starting after cleanup sees NULL. Keep the synchronous probe
outside this critical section, following the existing req_lock to
hdev->lock ordering.

KASAN report as below:

    ==================================================================
    BUG: KASAN: slab-use-after-free in msft_monitor_supported+0xa9/0xb0
    Read of size 8 at addr ffff88811573ee00 by task mgmt-read-adv-m/532

        CPU: 2 UID: 0 PID: 532 Comm: mgmt-read-adv-m Not tainted
    7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
        Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps
    fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? msft_monitor_supported+0xa9/0xb0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? msft_monitor_supported+0xa9/0xb0
     kasan_report+0xe0/0x110
     ? msft_monitor_supported+0xa9/0xb0
     msft_monitor_supported+0xa9/0xb0
     read_adv_mon_features+0xdf/0x640
     ? trace_hardirqs_on+0x18/0x160
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_read_adv_mon_features+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? do_raw_read_unlock+0x49/0xe0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? _raw_read_unlock+0x23/0x40
     hci_sock_sendmsg+0x12b5/0x2270
     ? __pfx_hci_sock_sendmsg+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? selinux_socket_sendmsg+0x160/0x280
     __sys_sendto+0x425/0x470
     ? __pfx_hci_sock_sendmsg+0x10/0x10
     ? __pfx___sys_sendto+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __sys_setsockopt+0x119/0x180
     __x64_sys_sendto+0xe5/0x1c0
     ? lockdep_hardirqs_on_prepare+0xea/0x1a0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? trace_hardirqs_on+0x18/0x160
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f
    RIP: 0033:0x7f9ceb04a687
        Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48
    83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b>
    c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
    RSP: 002b:00007ffe6ab96a70 EFLAGS: 00000202 ORIG_RAX: 000000000000002c
    RAX: ffffffffffffffda RBX: 00007f9ceafb8780 RCX: 00007f9ceb04a687
    RDX: 0000000000000006 RSI: 00007ffe6ab96aea RDI: 0000000000000003
    RBP: 0000000000000002 R08: 0000000000000000 R09: 0000000000000000
    R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000003
    R13: 00007ffe6ab96d50 R14: 00007f9ceb1f6000 R15: 00005625e427dd68
     </TASK>

    Allocated by task 506:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_cache_noprof+0x251/0x610
     msft_register+0x54/0x260
     hci_register_dev+0x6b7/0xc80
     __vhci_create_device+0x330/0x840
     vhci_write+0x287/0x440
     vfs_write+0x637/0x1010
     ksys_write+0x111/0x200
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    Freed by task 529:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     kfree+0x307/0x580
     msft_do_open+0x604/0x9e0
     hci_dev_open_sync+0x94a/0x2110
     hci_dev_do_open+0x2f/0xb0
     hci_dev_open+0x17d/0x300
     hci_sock_ioctl+0x3c6/0x710
     sock_do_ioctl+0x120/0x2b0
     sock_ioctl+0x41b/0x670
     __x64_sys_ioctl+0x163/0x1d0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    The buggy address belongs to the object at ffff88811573ee00
     which belongs to the cache kmalloc-256 of size 256
    The buggy address is located 0 bytes inside of
     freed 256-byte region [ffff88811573ee00, ffff88811573ef00)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000 index:0x0
    pfn:0x11573e
    head: order:1 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
    flags: 0x200000000000040(head|node=0|zone=2)
    page_type: f5(slab)
        raw: 0200000000000040 ffff888100042b40 dead000000000100
    dead000000000122
        raw: 0000000000000000 0000000000100010 00000000f5000000
    0000000000000000
        head: 0200000000000040 ffff888100042b40 dead000000000100
    dead000000000122
        head: 0000000000000000 0000000000100010 00000000f5000000
    0000000000000000
        head: 0200000000000001 ffffffffffffff81 00000000ffffffff
    00000000ffffffff
        head: 0000000000000000 0000000000000000 00000000ffffffff
    0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
     ffff88811573ed00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
     ffff88811573ed80: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    >ffff88811573ee00: fa fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                       ^
     ffff88811573ee80: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff88811573ef00: fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc fc
    ==================================================================

Fixes: 5031ffcc79 ("Bluetooth: Keep MSFT ext info throughout a hci_dev's life cycle")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:23 -04:00
Cen Zhang
213e7a99be Bluetooth: MGMT: Reject quality report requests during unregister
A quality report request must not call a driver callback after its
module text has been released. hci_mgmt_cmd() holds an hci_dev reference
through set_exp_feature(), but that reference only preserves the device
allocation. set_quality_report_func() takes req_lock and invokes
hdev->set_quality_report without checking HCI_UNREGISTER.

This is unsafe when a SET_EXP_FEATURE request for an Intel controller
would change HCI_QUALITY_REPORT and is delayed before taking req_lock
while the controller is removed. With btintel_pcie and btintel built as
modules and no other btintel dependents, the following order is
possible:

  Management request                Removal and module unload
  ------------------                -------------------------
  hci_mgmt_cmd(): retain hdev
                                    hci_unregister_dev():
                                      set HCI_UNREGISTER
                                      remove hdev from lookup
                                      close under req_lock
                                      release req_lock
                                    btintel_pcie_remove(): return
                                    unload btintel_pcie, then btintel
  set_quality_report_func():
    take req_lock
    call hdev->set_quality_report

When the request resumes after btintel unload, the indirect call targets
released module text and can cause an instruction-fetch page fault. The
close operation serializes with a running callback but does not prevent
a delayed management handler from invoking it afterwards.

Check HCI_UNREGISTER immediately after acquiring the existing req_lock
and return MGMT_STATUS_INVALID_INDEX via the common unlock path. If
unregister passed its close section first, the request now rejects the
removed controller before accessing the callback. If the request passes
the check first, hci_dev_do_close() must wait for req_lock until the
callback has returned, so unregister cannot finish before the use.

Oops report as below:

    BUG: unable to handle page fault for address: ffffffffc0408e10
    #PF: supervisor instruction fetch in kernel mode
    #PF: error_code(0x0010) - not-present page
    PGD 80a9067 P4D 80a9067 PUD 80ab067 PMD 0
    Oops: Oops: 0010 [#1] SMP KASAN NOPTI
    CPU: 1 UID: 0 PID: 439 Comm: btmgmt Tainted: G           O        7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
    Tainted: [O]=OOT_MODULE
    Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    RIP: 0010:0xffffffffc0408e10
    Code: Unable to access opcode bytes at 0xffffffffc0408de6.
    RSP: 0018:ffff888110927838 EFLAGS: 00010293
    RAX: 0000000000000000 RBX: 1ffff11022124f0c RCX: ffffffff85b1a1b6
    RDX: ffff888117511d00 RSI: 0000000000000001 RDI: ffff888117598000
    RBP: ffff888110927950 R08: 0000000000000001 R09: 0000000000000001
    R10: ffffffff893d3057 R11: ffff888117511d00 R12: ffff888117598000
    R13: 0000000000000001 R14: ffffffffc0408e10 R15: ffff888117599970
    FS:  00007f15453f2040(0000) GS:ffff8881fd852000(0000) knlGS:0000000000000000
    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: ffffffffc0408de6 CR3: 000000010b832005 CR4: 0000000000770ef0
    PKRU: 55555554
    Call Trace:
     <TASK>
     ? set_quality_report_func+0x232/0x660
     ? __pfx_set_quality_report_func+0x10/0x10
     ? pmbd_gate_maybe+0x47/0x60
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? pmbd_probe_hit_cookie+0xe7/0x1c0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? pmbd_probe_hit_cookie+0xee/0x1c0
     set_exp_feature+0xf7/0x260
     ? set_exp_feature+0xf7/0x260
     ? hci_sock_sendmsg+0x12b2/0x2400
     ? __pfx_hci_sock_sendmsg+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? selinux_socket_sendmsg+0x160/0x280
     ? sock_write_iter+0x4c0/0x550
     ? __pfx_hci_sock_sendmsg+0x10/0x10
     ? __pfx_sock_write_iter+0x10/0x10
     ? __file_has_perm+0x25e/0x420
     ? __pfx___file_has_perm+0x10/0x10
     ? do_iter_readv_writev+0x59c/0x860
     ? __pfx_do_iter_readv_writev+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? security_file_permission+0x26/0x80
     ? vfs_writev+0x30e/0xc10
     ? __pfx_vfs_writev+0x10/0x10
     ? __pfx_do_epoll_wait+0x10/0x10
     ? __pfx_do_epoll_ctl+0x10/0x10
     ? do_writev+0x241/0x2f0
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? do_writev+0x241/0x2f0
     ? __pfx_do_writev+0x10/0x10
     ? irqentry_exit+0xbe/0x820
     ? do_syscall_64+0x115/0x6a0
     ? entry_SYSCALL_64_after_hwframe+0x77/0x7f
     </TASK>
    Modules linked in: [last unloaded: btintel(O)]
    CR2: ffffffffc0408e10
    ---[ end trace 0000000000000000 ]---
    RIP: 0010:0xffffffffc0408e10
    Code: Unable to access opcode bytes at 0xffffffffc0408de6.
    RSP: 0018:ffff888110927838 EFLAGS: 00010293
    RAX: 0000000000000000 RBX: 1ffff11022124f0c RCX: ffffffff85b1a1b6
    RDX: ffff888117511d00 RSI: 0000000000000001 RDI: ffff888117598000
    RBP: ffff888110927950 R08: 0000000000000001 R09: 0000000000000001
    R10: ffffffff893d3057 R11: ffff888117511d00 R12: ffff888117598000
    R13: 0000000000000001 R14: ffffffffc0408e10 R15: ffff888117599970
    FS:  00007f15453f2040(0000) GS:ffff8881fd852000(0000) knlGS:0000000000000000
    CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    CR2: ffffffffc0408de6 CR3: 000000010b832005 CR4: 0000000000770ef0
    PKRU: 55555554
    Kernel panic - not syncing: Fatal exception
    Kernel Offset: disabled
    Rebooting in 1 seconds..

Fixes: ae7d925b5c ("Bluetooth: Support the quality report events")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:23 -04:00
Cen Zhang
b4a00dedc5 Bluetooth: ISO: Hold the listener during disconnect notification
An ISO listener must remain alive until a queued child's disconnect
notification completes. bt_accept_enqueue() retains only the child and
stores a raw parent pointer; iso_conn_ready() drops its temporary
listener reference after setup. iso_chan_del() saves that pointer,
unlinks the child and then calls parent->sk_data_ready() without holding
a listener reference.

With an incoming CIS child still queued, disconnect and listener release
can proceed in this order:

  HCI disconnect                   Listener release
  iso_conn_del(): lock child
  iso_chan_del(): save parent
  bt_accept_unlink(child)
                                   iso_sock_cleanup_listen():
                                     drain empty accept queue
                                   iso_sock_release():
                                     orphan and kill listener
                                     final sock_put(listener)
  parent->sk_data_ready(parent)

After unlink, listener cleanup no longer has to take the child socket
lock. The listener can therefore be freed before iso_chan_del() reads
sk_data_ready, causing a use-after-free.

Take a temporary parent reference before bt_accept_unlink() and drop it
after the notification. The child lock excludes accept dequeue while the
child is still queued, so listener cleanup cannot complete before
sock_hold(). The reference then keeps the listener alive across unlink
and through the callback without changing lock order.

KASAN report as below:

    ==================================================================
    BUG: KASAN: slab-use-after-free in iso_chan_del+0x302/0x320
    Read of size 8 at addr ffff888105ca2188 by task kworker/2:1/50

        CPU: 2 UID: 0 PID: 50 Comm: kworker/2:1 Not tainted
    7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
        Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps
    fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    Workqueue: events iso_fixture_disconnect_work
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     print_report+0xce/0x630
     ? iso_chan_del+0x302/0x320
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __virt_addr_valid+0x20d/0x410
     ? iso_chan_del+0x302/0x320
     kasan_report+0xe0/0x110
     ? iso_chan_del+0x302/0x320
     iso_chan_del+0x302/0x320
     iso_conn_del+0x19d/0x3c0
     ? __pfx_iso_disconn_cfm+0x10/0x10
     iso_disconn_cfm+0x78/0x120
     hci_disconn_complete_evt+0x319/0xa30
     ? find_held_lock+0x2b/0x80
     hci_test_iso_disconn_event+0x85/0xb0
     ? __pfx_hci_test_iso_disconn_event+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? _raw_read_unlock+0x23/0x40
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __hci_dev_get+0x15d/0x280
     iso_fixture_disconnect_work+0x67/0x290
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __kthread_parkme+0x175/0x220
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>

    Allocated by task 521:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     __kasan_kmalloc+0xaa/0xb0
     __kmalloc_noprof+0x2d7/0x770
     sk_prot_alloc+0x13e/0x260
     sk_alloc+0x37/0xb40
     bt_sock_alloc+0x40/0x3b0
     iso_sock_alloc.constprop.0+0x3a/0x360
     iso_sock_create+0xc7/0x160
     bt_sock_create+0x171/0x330
     __sock_create+0x2c4/0x730
     __sys_socket+0x141/0x210
     __x64_sys_socket+0x77/0xc0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    Freed by task 521:
     kasan_save_stack+0x33/0x60
     kasan_save_track+0x14/0x30
     kasan_save_free_info+0x3b/0x60
     __kasan_slab_free+0x5f/0x80
     kfree+0x307/0x580
     __sk_destruct+0x64f/0x790
     sk_destruct+0xb3/0xd0
     __sk_free+0xdd/0x370
     sk_free+0x51/0x80
     iso_sock_release+0x46d/0x5b0
     __sock_release+0xb8/0x270
     sock_close+0x21/0x30
     __fput+0x39f/0xa60
     task_work_run+0x144/0x230
     do_exit+0x834/0x2830
     do_group_exit+0xc7/0x280
     get_signal+0x20a9/0x2400
     arch_do_signal_or_restart+0x94/0x6f0
     exit_to_user_mode_loop+0xcf/0x570
     do_syscall_64+0x4f0/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    The buggy address belongs to the object at ffff888105ca2000
                                                                which
                                belongs to the cache kmalloc-2k of size
                                2048
    The buggy address is located 392 bytes inside of
                                                                freed
                                2048-byte region [ffff888105ca2000,
                                ffff888105ca2800)

    The buggy address belongs to the physical page:
        page: refcount:0 mapcount:0 mapping:0000000000000000
    index:0xffff888105ca5000 pfn:0x105ca0
    head: order:3 mapcount:0 entire_mapcount:0 nr_pages_mapped:0 pincount:0
    flags: 0x200000000000240(workingset|head|node=0|zone=2)
    page_type: f5(slab)
        raw: 0200000000000240 ffff888100042f00 ffffea00042cd010
    ffffea00042c9210
        raw: ffff888105ca5000 0000000000080005 00000000f5000000
    0000000000000000
        head: 0200000000000240 ffff888100042f00 ffffea00042cd010
    ffffea00042c9210
        head: ffff888105ca5000 0000000000080005 00000000f5000000
    0000000000000000
        head: 0200000000000003 fffffffffffffe01 00000000ffffffff
    00000000ffffffff
        head: ffff888105ca1000 0000000000000000 00000000ffffffff
    0000000000000000
    page dumped because: kasan: bad access detected

    Memory state around the buggy address:
     ffff888105ca2080: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff888105ca2100: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    >ffff888105ca2180: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
                          ^
     ffff888105ca2200: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
     ffff888105ca2280: fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb fb
    ==================================================================

Fixes: f764a6c2c1 ("Bluetooth: ISO: Add broadcast support")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:22 -04:00
Cen Zhang
6d91353f6d Bluetooth: hci_sync: Serialize devcoredump reset during device open
An ACTIVE devcoredump's buffer cursors must remain valid from the
packet handler's state check through its copy. hci_devcd_rx() holds
hdev->lock across that interval, and hci_devcd_reset() requires the
same lock. However, hci_dev_open_sync() invokes reset without taking
it.

A registered VHCI controller can collect a dump through its debugfs
interface while the controller is down. If a successful open overlaps
with handling a nonempty dump packet, reset can run after the receiver's
ACTIVE check and before its copy:

  hci_devcd_rx()                    hci_dev_open_sync()
    dequeue nonempty skb
    hci_dev_lock(hdev)
    handler observes ACTIVE
                                     hdev->open(hdev) succeeds
                                     hci_devcd_reset(hdev)
                                       dump.tail = NULL
                                       dump.state = IDLE
    hci_devcd_copy()
      compare against old dump.end
      memcpy(NULL, ..., skb->len)
    hci_dev_unlock(hdev)

Reset leaves dump.end pointing at the old buffer and purges only queued
packets, so it cannot discard the skb already dequeued by the receiver.
The bounds check can pass with a NULL tail, leading to a nonempty copy
to address zero. KASAN reported a 24-byte NULL write in hci_devcd_rx().

Take hdev->lock around the open-time reset. The receiver then finishes
its state check and copy using valid cursors before reset, or observes
IDLE after reset and skips the copy.

KASAN report as below:

    BUG: KASAN: null-ptr-deref in hci_devcd_rx+0x5d5/0x1a80
    Write of size 24 at addr 0000000000000000 by task kworker/u17:0/496

        CPU: 0 UID: 0 PID: 496 Comm: kworker/u17:0 Not tainted
    7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
        Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps
    fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    Workqueue: hci0 hci_devcd_rx
    Call Trace:
     <TASK>
     dump_stack_lvl+0x93/0xd0
     kasan_report+0xe0/0x110
     ? hci_devcd_rx+0x5d5/0x1a80
     kasan_check_range+0x105/0x1b0
     __asan_memcpy+0x3c/0x60
     hci_devcd_rx+0x5d5/0x1a80
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_hci_devcd_rx+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_release+0xc8/0x280
     ? srso_alias_return_thunk+0x5/0xfbef5
     process_one_work+0x908/0x19c0
     ? __pfx_process_one_work+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? lock_is_held_type+0x8f/0x100
     ? srso_alias_return_thunk+0x5/0xfbef5
     worker_thread+0x65c/0xe40
     ? __pfx_worker_thread+0x10/0x10
     kthread+0x34f/0x460
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __pfx_kthread+0x10/0x10
     ret_from_fork+0x659/0x940
     ? __pfx_ret_from_fork+0x10/0x10
     ? srso_alias_return_thunk+0x5/0xfbef5
     ? __switch_to+0x74f/0xf80
     ? __pfx_kthread+0x10/0x10
     ret_from_fork_asm+0x1a/0x30
     </TASK>
    ==================================================================
    Disabling lock debugging due to kernel taint

Fixes: 9695ef876f ("Bluetooth: Add support for hci devcoredump")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:22 -04:00
Cen Zhang
817cbcab91 Bluetooth: hci_core: Keep RCU protection through LTK filtering
The LTK selected by hci_find_ltk() must remain allocated while its
value is checked against the blocked-key list. The finder releases RCU
before passing k->val to hci_is_blocked_key(). The helper's own RCU
section protects the blocked-key list, but the selected LTK may already
have been reclaimed before that section starts.

An LE ATT socket security request can reach smp_ltk_encrypt() without
holding hdev->lock. With a matching stored LTK and an LTK-type
blocked-key entry present, a concurrent MGMT_OP_LOAD_LONG_TERM_KEYS can
remove the selected LTK in the following order:

  Socket security                 Management / RCU reclamation
  hci_find_ltk()
    rcu_read_lock()
    select k
    rcu_read_unlock()
                                  load_long_term_keys()
                                    hci_dev_lock(hdev)
                                    hci_smp_ltks_clear(hdev)
                                      list_del_rcu(&k->list)
                                      kfree_rcu(k, rcu)
                                  grace period ends; k is freed
    hci_is_blocked_key(..., k->val)
      memcmp(b->val, val, ...)

The final comparison reads freed LTK bytes. Entering a new RCU section
in hci_is_blocked_key() cannot protect a pointer obtained before the
completed grace period.

Keep the finder's RCU read-side section active through the blocked-key
comparison and the warning that reads k->bdaddr. Release it before
returning on either matched-key path. This delays reclamation until the
finder has finished using the selected record, following the existing
IRK lookup pattern.

KFENCE report as below:

    ==================================================================
    BUG: KFENCE: use-after-free read in hci_is_blocked_key+0xdf/0x240

    Use-after-free read at 0x00000000b9ee38e4 (in kfence-#249):
     hci_is_blocked_key+0xdf/0x240
     blocked_key_wrapper+0xc5/0x140 [pmbd_ltk_probe]
     hci_find_ltk+0x1aa/0x3e0
     smp_ltk_encrypt.isra.0+0xad/0x340
     smp_conn_security+0x3b8/0x8c0
     l2cap_sock_setsockopt+0x1c4b/0x2270
     do_sock_setsockopt+0x1fb/0x430
     __sys_setsockopt+0x106/0x180
     __x64_sys_setsockopt+0xc2/0x160
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    kfence-#249: 0x00000000121f2ad9-0x000000005b5bfb3d, size=72, cache=kmalloc-96

    allocated by task 495 on cpu 0 at 36.722380s (2.603973s ago):
     hci_add_ltk+0x1f5/0x3a0
     load_long_term_keys+0x6d0/0x860
     hci_sock_sendmsg+0x128b/0x22e0
     __sys_sendto+0x425/0x470
     __x64_sys_sendto+0xe5/0x1c0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    freed by task 533 on cpu 0 at 36.993097s (2.339769s ago):
     __rcu_free_sheaf_prepare+0x261/0x2a0
     rcu_free_sheaf+0x1f/0xe0
     rcu_core+0x661/0x1d10
     handle_softirqs+0x201/0x930
     __irq_exit_rcu+0x110/0x1e0
     irq_exit_rcu+0xe/0x20
     sysvec_apic_timer_interrupt+0x6c/0x80
     asm_sysvec_apic_timer_interrupt+0x1a/0x20
     srso_alias_return_thunk+0x0/0xfbef5
     __asan_memcpy+0x23/0x60
     create_monitor_ctrl_event+0x1a2/0x460
     mgmt_cmd_complete+0x2da/0x580
     load_long_term_keys+0x741/0x860
     hci_sock_sendmsg+0x128b/0x22e0
     __sys_sendto+0x425/0x470
     __x64_sys_sendto+0xe5/0x1c0
     do_syscall_64+0x115/0x6a0
     entry_SYSCALL_64_after_hwframe+0x77/0x7f

    CPU: 1 UID: 0 PID: 495 Comm: python3 Tainted: G           O        7.2.0-rc6-pmb-bt-functional-v1+ #1 PREEMPT(lazy)
    Tainted: [O]=OOT_MODULE
    Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    ==================================================================

Fixes: 600a87490f ("Bluetooth: Implementation of MGMT_OP_SET_BLOCKED_KEYS.")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:22 -04:00
Cen Zhang
8c27d7d06e Bluetooth: 6LoWPAN: Use RCU-safe device list removal
RCU readers of bt_6lowpan_devices must be able to follow an adapter's
forward link until their read-side critical section ends. The entries
are published with list_add_rcu(), but device_event() removes an entry
on NETDEV_UNREGISTER with list_del(), poisoning that link.

When an adapter is being unregistered and 6LoWPAN is enabled, a
6lowpan_control debugfs write with an existing LE L2CAP connection can
enter lookup_peer() after unregister's first synchronize_net(). If the
connection has no peer on that adapter, the reader must advance to the
next list entry. Neither RTNL nor devices_lock excludes this RCU reader.

The last peer's chan_close_cb() schedules delete_netdev(), which reaches
unregister_netdevice_many_notify() through unregister_dev() and
lowpan_unregister_netdev(). The following ordering is possible:

  Unregister worker                 Control writer
  -----------------                 --------------
  synchronize_net() returns
                                    lowpan_control_write()
                                    lookup_peer(): rcu_read_lock()
                                    reach adapter; no matching peer
  device_event(): devices_lock
  list_del(&entry->list)
  spin_unlock(&devices_lock)
                                    follow poisoned next link
                                    read invalid adapter address
  post-notifier synchronize_net()
    waits for the reader

This invalid pointer access can fault in lookup_peer(). The first grace
period drains existing readers but permits new ones to start, and the
later grace period cannot prevent the intervening poisoned-link access.

Use list_del_rcu() under the existing devices_lock to preserve the
forward link for readers that already reached the adapter. The existing
post-notifier synchronize_net() waits for those readers before netdevice
teardown frees the private storage containing lowpan_btle_dev.

KASAN report as below:

    [...]
    [   45.867526] Oops: general protection fault, probably for non-canonical address 0xfbd59c0000000023: 0000 [#1] SMP KASAN NOPTI
    [   45.869489] KASAN: maybe wild-memory-access in range [0xdead000000000118-0xdead00000000011f]
    [   45.870981] CPU: 1 UID: 0 PID: 646 Comm: sh Not tainted 7.2.0-rc6-pmb-bt-functional-v1+ #4 PREEMPT(lazy)
    [   45.872609] Hardware name: QEMU Ubuntu 24.04 PC v2 (i440FX + PIIX, arch_caps fix, 1996), BIOS 1.16.3-debian-1.16.3-2 04/01/2014
    [   45.874380] RIP: 0010:lookup_peer+0x1ba/0x320
    [   45.875067] Code: 48 89 d9 ba 04 00 00 00 4c 89 fe bf a0 06 00 00 e8 2b e8 ad fb e9 56 ff ff ff e8 01 1e c3 fb 49 8d 7f 18 48 89 f8 48 c1 e8 03 <80> 3c 28 00 0f 85 4a 01 00 00 4d 8b 47 18 4c 89 f1 ba 04 00 00 00
    [   45.878206] RSP: 0018:ffff888114d67b90 EFLAGS: 00010212
    [   45.879106] RAX: 1bd5a00000000023 RBX: 0000000000000000 RCX: ffffffff85c1d19f
    [   45.880334] RDX: ffff88810dc35700 RSI: 0000000000000000 RDI: dead000000000118
    [   45.881455] RBP: dffffc0000000000 R08: 0000000000000001 R09: 0000000000000001
    [   45.882546] R10: ffffffff893d3057 R11: ffff88810dc35700 R12: ffff88810a690000
    [   45.883839] R13: ffff888115451038 R14: ffff88810a690000 R15: dead000000000100
    [   45.885186] FS:  00007fa889bac780(0000) GS:ffff8881fd852000(0000) knlGS:0000000000000000
    [   45.886539] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    [   45.887527] CR2: 00007ffe304f2f80 CR3: 0000000104f64005 CR4: 0000000000770ef0
    [   45.888687] PKRU: 55555554
    [   45.889183] Call Trace:
    [   45.889666]  <TASK>
    [   45.890061]  lowpan_control_write+0x445/0x9e0
    [   45.890854]  ? __pfx_lowpan_control_write+0x10/0x10
    [   45.891738]  ? srso_alias_return_thunk+0x5/0xfbef5
    [   45.892603]  ? srso_alias_return_thunk+0x5/0xfbef5
    [   45.893383]  ? __debugfs_file_get+0x1bd/0x7f0
    [   45.894057]  ? srso_alias_return_thunk+0x5/0xfbef5
    [   45.894902]  ? lock_acquire+0x17b/0x2f0
    [   45.895593]  ? ksys_write+0x111/0x200
    [   45.896290]  full_proxy_write+0x11f/0x180
    [   45.896991]  vfs_write+0x25a/0x1010
    [   45.897642]  ? __pfx_full_proxy_write+0x10/0x10
    [   45.898440]  ? __pfx_vfs_write+0x10/0x10
    [   45.899178]  ? lock_release+0x11f/0x280
    [   45.899855]  ksys_write+0x111/0x200
    [   45.900435]  ? __pfx_ksys_write+0x10/0x10
    [   45.901074]  ? irqentry_exit+0xbe/0x820
    [   45.901722]  ? srso_alias_return_thunk+0x5/0xfbef5
    [   45.902489]  do_syscall_64+0x115/0x6a0
    [   45.903064]  entry_SYSCALL_64_after_hwframe+0x77/0x7f
    [   45.903813] RIP: 0033:0x7fa889c3e687
    [   45.904359] Code: 48 89 fa 4c 89 df e8 58 b3 00 00 8b 93 08 03 00 00 59 5e 48 83 f8 fc 74 1a 5b c3 0f 1f 84 00 00 00 00 00 48 8b 44 24 10 0f 05 <5b> c3 0f 1f 80 00 00 00 00 83 e2 39 83 fa 08 75 de e8 23 ff ff ff
    [   45.906981] RSP: 002b:00007ffd7651b960 EFLAGS: 00000202 ORIG_RAX: 0000000000000001
    [   45.908070] RAX: ffffffffffffffda RBX: 00007fa889bac780 RCX: 00007fa889c3e687
    [   45.909102] RDX: 000000000000001c RSI: 00005570f25e8d10 RDI: 0000000000000001
    [   45.910133] RBP: 00005570f25e8d10 R08: 0000000000000000 R09: 0000000000000000
    [   45.911162] R10: 0000000000000000 R11: 0000000000000202 R12: 0000000000000001
    [   45.912190] R13: 000000000000001c R14: 0000000000000000 R15: 00005570f25e8a78
    [   45.913208]  </TASK>
    [   45.913530] Modules linked in:
    [   45.914022] ---[ end trace 0000000000000000 ]---
    [   45.914709] RIP: 0010:lookup_peer+0x1ba/0x320
    [   45.915436] Code: 48 89 d9 ba 04 00 00 00 4c 89 fe bf a0 06 00 00 e8 2b e8 ad fb e9 56 ff ff ff e8 01 1e c3 fb 49 8d 7f 18 48 89 f8 48 c1 e8 03 <80> 3c 28 00 0f 85 4a 01 00 00 4d 8b 47 18 4c 89 f1 ba 04 00 00 00
    [   45.919191] RSP: 0018:ffff888114d67b90 EFLAGS: 00010212
    [   45.920046] RAX: 1bd5a00000000023 RBX: 0000000000000000 RCX: ffffffff85c1d19f
    [   45.921129] RDX: ffff88810dc35700 RSI: 0000000000000000 RDI: dead000000000118
    [   45.922553] RBP: dffffc0000000000 R08: 0000000000000001 R09: 0000000000000001
    [   45.923653] R10: ffffffff893d3057 R11: ffff88810dc35700 R12: ffff88810a690000
    [   45.925119] R13: ffff888115451038 R14: ffff88810a690000 R15: dead000000000100
    [   45.926180] FS:  00007fa889bac780(0000) GS:ffff8881fd852000(0000) knlGS:0000000000000000
    [   45.927817] CS:  0010 DS: 0000 ES: 0000 CR0: 0000000080050033
    [   45.928726] CR2: 00007ffe304f2f80 CR3: 0000000104f64005 CR4: 0000000000770ef0
    [   45.930069] PKRU: 55555554
    [   45.930456] Kernel panic - not syncing: Fatal exception
    [   45.931542] Kernel Offset: disabled
    [   45.932040] Rebooting in 1 seconds..

Fixes: 9030582963 ("Bluetooth: 6lowpan: Converting rwlocks to use RCU")
Assisted-by: LLM
Signed-off-by: Cen Zhang <zzzccc427@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:21 -04:00
Luiz Augusto von Dentz
f7f0d0a9eb Bluetooth: MGMT: Fix leaking instance on Add Extended Advertising Parameters
If queueing the command fails the instance is never removed, despite it
having already been added or modified by hci_add_adv_instance, so remove
it as it is done by add_ext_adv_params_complete on failure, signaling
it has been removed if it was previously added.

Fixes: cba6b75871 ("Bluetooth: hci_sync: Make use of hci_cmd_sync_queue set 2")
Assisted-by: OpenCode:claude-opus-5.5
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:21 -04:00
Luiz Augusto von Dentz
5548fb51aa Bluetooth: MGMT: Fix pending state of instances added without HCI traffic
When Add Advertising completes without HCI communication, e.g. when the
device is not powered or the instance is overridden by Global
Advertising, the instance is left marked as pending, so a subsequent
failure in add_adv_complete would remove it despite it having been
successfully added.

Fix this by clearing the pending state before completing the command.

Fixes: fffd38bca5 ("Bluetooth: mgmt/hci_core: multi-adv for add_advertising*()")
Assisted-by: OpenCode:claude-opus-5.5
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:21 -04:00
Luiz Augusto von Dentz
1bfecdbd03 Bluetooth: HCI: Fix tracking of instances sharing handle 0x00
When the controller supports a single advertising set, instance 1 uses
handle 0x00 which is the same handle used by instance 0 (Global
Advertising), but hci_cc_le_set_ext_adv_enable would lookup the instance
using the handle as instance identifier, marking instance 0 as
enabled/disabled instead of instance 1, leaving its state out of sync.

Fix this by matching instances by handle and, for handle 0x00, using
hdev->cur_adv_instance, now set when enabling an instance, to determine
which instance owns the set. Also disable the instance sharing the
advertising set of instance 0 before overriding it.

Fixes: e77f43d531 ("Bluetooth: hci_core: Fix not handling hdev->le_num_of_adv_sets=1")
Assisted-by: OpenCode:claude-opus-5.5
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:21 -04:00
Luiz Augusto von Dentz
0ad48c88a2 Bluetooth: MGMT: Fix advertising instances with Global Advertising
Global Advertising, enabled with MGMT_OP_SET_ADVERTISING, uses instance
0 and with extended advertising it has its own advertising set, but
instances were still being treated as if they shared the same set:

 - Add Advertising and Add Extended Advertising Data would return
   success without ever enabling the instance.
 - Removing the last instance would disable all advertising sets,
   stopping Global Advertising while leaving its setting enabled.
 - Disabling Global Advertising would disable all sets, including
   active instances.

Fix this by only overriding instances that share the advertising set of
Global Advertising, and by tracking HCI_LE_ADV_0 rather than HCI_LE_ADV
to determine the state of Global Advertising.

Fixes: 0d92808024 ("Bluetooth: HCI: Fix tracking of advertisement set/instance 0x00")
Assisted-by: OpenCode:claude-opus-5.5
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:20 -04:00
Pauli Virtanen
3d9526b171 Bluetooth: make hdev->adv_instance_timeout a boolean
Mesh uses millisecond time units for advertisements instead of seconds
as normally. These values go to hdev->adv_instance_timeout, which then
has mixed units.  hdev->adv_instance_timeout is however only used as a
true/false flag.

Make hdev->adv_instance_timeout boolean flag, to avoid possible future
problems with its mixed-units values.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:20 -04:00
Pauli Virtanen
8a8d51eeed Bluetooth: hci_sync: fix mesh adv timeout units
Mesh adv instance timeout and duration are in milliseconds, see
mesh_send_sync, hci_add_adv_instance.  hci_schedule_adv_instance_sync()
and hci_enable_ext_advertising_sync() ignore this, and scale the timeout
wrong.

Fix for mesh instances by using msecs_to_jiffies() in
hci_schedule_adv_instance_sync and fixing the scaling in
hci_enable_ext_advertising_sync.

Fixes BlueZ "Mesh - Send cancel" test failures.

Fixes: b338d91703 ("Bluetooth: Implement support for Mesh")
Assisted-by: opencode:qwen3.8-flash-next sashiko
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:20 -04:00
Frédéric Danis
1b723bd294 Bluetooth: MGMT: Add management security level changed event
Add an event on device security level or encryption type change to
let user space know which level is currently in use.
Reset security level to 0 on disconnection so further connections
will correctly report security level changes.

This will be used for BlueZ qualification automation.

Assisted-by: GPT:GPT-5.3-Codex
Assisted-by: Copilot:claude-sonnet-5
Signed-off-by: Frédéric Danis <frederic.danis@collabora.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:19 -04:00
Peng Fan
c4154fc347 Bluetooth: use assign_bit() where applicable
Convert open-coded if/else with set_bit/clear_bit the assign_bit API.

Done with Coccinelle semantic patch:
    // set_bit -> clear_bit => assign_bit

    @@
    expression cond, bit, addr;
    @@

    -if (cond)
    -        set_bit(bit, addr);
    -else
    -        clear_bit(bit, addr);
    +assign_bit(bit, addr, cond);

    @@
    expression cond, bit, addr;
    @@

    -if (cond)
    -        clear_bit(bit, addr);
    -else
    -        set_bit(bit, addr);
    +assign_bit(bit, addr, !cond);

Signed-off-by: Peng Fan <peng.fan@nxp.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:16 -04:00
Zijun Hu
366cdec7fe Bluetooth: Add generic support for vendor packets
The virtual HCI_VENDOR_PKT (0xff) has been defined but never used by
the BT core. Now, there is a requirement to implement it, as follows:

For Qualcomm multi-subsystem BT chips, the transport wire carries both
BT-HCI and PERI-HCI packets, where PERI is a subsystem in the chip, take
the upcoming QCC2072 as an example:

    Packet type                 BT-HCI indicator   PERI-HCI indicator
    -----------------------------------------------------------------
    CMD (Host -> Controller)    0x01               0x31
    ACL Data (bidirectional)    0x02               0x32
    EVENT (Controller -> Host)  0x04               0x34

There are also BT ACL packets with vendor-reserved handles found in
existing device drivers, as shown below:

+--------+--------+---------------------------+
| Vendor | Handle | Purpose                   |
+--------+--------+---------------------------+
| QCOM   | 0xEDD  | Firmware coredump         |
|        | 0xEDC  | Firmware enhanced logging |
+--------+--------+---------------------------+
| MTK    | 0xFC6F | Firmware coredump         |
|        | 0x05FF | Firmware debug logging 1  |
|        | 0x05FE | Firmware debug logging 2  |
+--------+--------+---------------------------+
| NXP    | 0xFFF  | Firmware coredump         |
+--------+--------+---------------------------+

Implement HCI_VENDOR_PKT to generically support such vendor packets,
which don't follow BT SIG's vendor-extension framework:

- Log them in btmon as they appear on the wire.
- Add hdev->recv_vendor_pkt() to handle them in hci_rx_work().
- Add hci_send_vendor_frame() to send them to the device driver.
- Allow them to flow over HCI_CHANNEL_USER, nested inside HCI_VENDOR_PKT.

Also solve the same issues that the commit below fixes for
HCI_EV_VENDOR, which follows BT SIG's vendor-extension framework:

commit 0bd606b31d ("Bluetooth: hci_event: Introduce
handle_ev_vendor() for HCI_EV_VENDOR")

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:15 -04:00
Zijun Hu
51589ddae3 Bluetooth: hci_event: Use 252 as max CC event payload length in hci_cc_table[]
hci_cc_func() validates skb->len against cc->max_len from the entry in
hci_cc_table[], But By then, the HCI event and CC headers have already been
stripped by skb_pull(). So the max CC payload is 252, but hci_cc_table[]
still uses HCI_MAX_EVENT_SIZE (260) for it, which is imprecise.

Fix by defining HCI_MAX_CC_PLEN (252) and using it instead.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:14 -04:00
Zijun Hu
9822887f0d Bluetooth: hci_event: Use 254 as max LE Meta subevent payload length in hci_le_ev_table[]
hci_le_meta_evt() validates skb->len against subev->max_len from the entry
in hci_le_ev_table[], By then, the HCI event header and LE Meta subevent
header have already been stripped by skb_pull(), So the max LE Meta
subevent payload is 254, but hci_le_ev_table[] still uses
HCI_MAX_EVENT_SIZE (260) for it, which is imprecise.

Fix by defining HCI_MAX_LE_SUBEVT_PLEN (254) and using it instead.

Signed-off-by: Zijun Hu <zijun.hu@oss.qualcomm.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:13 -04:00
Thomas Huth
c930a69fec Bluetooth: SMP: Zeroize raw key data on the stack in smp_e()
smp_e() already clears the AES key in its "struct aes_enckey aes"
on the stack before leaving the function - but the very same
information is also available as raw key data in the tmp[] array,
so this should get cleared, too.

Signed-off-by: Thomas Huth <thuth@redhat.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:13 -04:00
Adriano Cordova
9cc144d95e Bluetooth: bnep: linearize skb before sending
kernel_sendmsg expects contiguous data. Linearize the skb in the
bnep_session() loop, before bnep_tx_frame builds its kvec, so it
is not split across non-linear pages. Drop the dead block and
FIXME.

Signed-off-by: Adriano Cordova <adrianox@gmail.com>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:12 -04:00
Radek Podgorny
3889a5fcd0 Bluetooth: forget a peer's RPA once it advertises its identity address
hci_connect_le() dials the RPA cached in the peer's IRK whenever one is
set, on the assumption that a peer holding an IRK is on air with a
resolvable private address. A peer that stops using privacy breaks that
assumption: it advertises its identity address, the cached RPA keeps the
value it had before the change, and the host aims at an address the peer
has abandoned.

Nothing clears the cache. hci_find_irk_by_rpa() refreshes irk->rpa each
time an advertisement resolves, so it tracks rotation, but a peer that
stops sending RPAs stops producing the reports that would update it, and
the stale address then survives until the adapter is powered off.

On the path that creates the connection object this is currently masked:
__hci_conn_add() resolves the cached RPA back to the identity address, so
that is what goes on air. It is not masked on the reuse branch, which
copies the swapped address straight into an existing conn->dst, and the
next patch removes the conversion for the case where the controller
cannot translate an identity address, so the stale RPA would be dialled
there too.

Clear the cached RPA when the peer is seen on its identity address.
hci_find_irk_by_addr() only matches public and static random addresses,
so an unresolved RPA belonging to some other device cannot reach this
path.

Assisted-by: Claude:claude-opus-5
Signed-off-by: Radek Podgorny <radek@podgorny.cz>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 14:38:12 -04:00
Luiz Augusto von Dentz
5299db91df Bluetooth: Move H:4 reassembly into the Bluetooth core
h4_recv_buf() is currently implemented in hci_h4.c which is only built as
part of the hci_uart module, and only when CONFIG_BT_HCIUART_H4 is
enabled. That makes the H:4 reassembly logic unusable by drivers which do
not depend on hci_uart, e.g. btusb which needs it to implement Bulk
Serialization Mode.

Move the transport agnostic part into the Bluetooth core as
h4_recv_skb(), which takes a struct hci_dev instead of a struct hci_uart,
along with struct h4_recv_pkt and the H4_RECV_* helpers, and keep
h4_recv_buf() as a thin wrapper for the hci_uart protocols.

Since every Bluetooth driver already depends on the bluetooth module this
introduces no new module dependency and no new Kconfig symbol.

Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:29:26 -04:00
Pauli Virtanen
86b55991d3 Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn
l2cap_chan may be linked to l2cap_conn at most once. This is assumed in
several places, eg l2cap_chan_del cleanup.

There is a TOCTOU race where the invariant is violated:

    [Task 1]                          [Task 2]
    l2cap_chan_connect                l2cap_sock_bind
      l2cap_chan_lock                   lock_sock
      l2cap_state_change                if (sk->sk_state != BT_OPEN)
        chan->state = BT_CONNECT
        l2cap_sock_state_change_cb      chan->state = BT_BOUND
                                        sk->sk_state = BT_BOUND
          lock_sock <------------------ release_sock
          sk->sk_state = BT_CONNECT

l2cap_sock_connect() does not check sk->sk_state, so since chan->state
is now BT_BOUND, subsequent connect() ends up with second
__l2cap_chan_add.

Explicitly document and check the invariant in __l2cap_chan_add with
WARN_ON_ONCE. The only callsite where it could be hit is
l2cap_chan_connect, so add pre-check there to avoid relying on
chan->state. chan->state read/write is not properly guarded currently so
there can be other TOCTOUC problems.

Add l2cap_lock_chan in l2cap_sock_bind() to guard chan->state write.

Fixes: b66774b48d ("Bluetooth: L2CAP: Fix UAF in channel timeout by holding conn ref")
Assisted-by: deepseek-4-flash # finding the race condition
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:29:05 -04:00
Pauli Virtanen
a0c672c410 Bluetooth: L2CAP: annotate locking for l2cap_ops callbacks
Annotate current locking context for l2cap_ops callbacks.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:28:45 -04:00
Pauli Virtanen
0e4d951a2f Bluetooth: L2CAP: annotate locking for l2cap_chan_del()
Add context analysis annotations for chan->lock and chan->conn->lock
involving l2cap_chan_del() usage.

Add necessary annotations and related lockdep_assert_held to callers.

Move struct l2cap_ops definition after struct l2cap_conn, so that the
callbacks can be annotated.

In l2cap_chan_close_unlocked() we consider chan->conn->lock as locked
even if chan->conn == NULL, to avoid needing to define separate
__l2cap_chan_close/del for this NULL case.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:28:24 -04:00
Pauli Virtanen
dc1ddc65f0 Bluetooth: L2CAP: take lock for l2cap_chan_del in l2cap_ecred_rsp_defer
l2cap_ecred_rsp_defer() calls l2cap_chan_del without holding chan->lock,
which ends up calling ops->teardown() with wrong lock context.

Fix by taking chan->lock in l2cap_ecred_rsp_defer().  AB-BA deadlocks
between sibling l2cap_chan are avoided here via requiring l2cap_conn::lock
to serialize all nested l2cap_chan locking on same nesting level.

In current code, there is no nested l2cap_chan locking on same nesting
level, so we can add this new requirement.

Also return early from  __l2cap_ecred_conn_rsp_defer() if chan did not
have FLAG_DEFER_SETUP, as then no RSP shall be sent for it, to make sure
SMP channels are excluded.

Also hold chan reference over l2cap_chan_del(), in case chan_l reference
was the last.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:28:03 -04:00
Pauli Virtanen
6098ed784e Bluetooth: L2CAP: remove conditional locking from l2cap_connect()
Context analysis does not understand conditional locking.

Restructure l2cap_connect() by removing conditional locking at the cost
of some code duplication, so that static analysis can see its content.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:27:42 -04:00
Pauli Virtanen
b508a2a2d8 Bluetooth: L2CAP: hold chan in l2cap_ecred_conn_rsp()
l2cap_chan_del() calls l2cap_chan_put() to drop the conn->chan_l
reference.  If this was the last reference, UAF follows.

l2cap_ecred_conn_rsp() iterates chan_l list and calls l2cap_chan_del()
on some members, without holding chan reference.

Fix by holding refcount while using chan after l2cap_chan_del().

Since orig is looked up by dcid provided by remote, it's also possible
orig == chan, so reference needs to be held also after orig use.

Fixes: 41c2713b20 ("Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp")
Assisted-by: deepseek-v4-flash
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:26:59 -04:00
Pauli Virtanen
889dfdde79 Bluetooth: L2CAP: add annotations for l2cap_chan list locking
Add context analysis annotations for l2cap_conn::chan_l and chan_list
locking.

Add corresponding required annotations to accessors and callers.

This is not complete chan_l annotation, l2cap_chan::list and
l2cap_chan_del() locking is currently not fully correct, and needs
separate fix + annotations.

Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:26:36 -04:00
Pauli Virtanen
115e6a21c8 Bluetooth: L2CAP: hold l2cap_conn::lock in l2cap_connect_cfm()
l2cap_new_connection() -> __l2cap_chan_add() modifies
l2cap_conn::chan_l, which is guarded by l2cap_conn::lock. The lock is
not held in l2cap_connect_cfm().

Fix by holding conn->lock in l2cap_connect_cfm() to make the locking
systematic.

Fixes: ab4eedb790 ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:26:15 -04:00
Pauli Virtanen
32d86e048d Bluetooth: L2CAP: hold conn->lock for __l2cap_ecred_conn_rsp_defer
__l2cap_ecred_conn_rsp_defer() > __l2cap_chan_list_id() accesses
conn->chan_l which is guarded by conn->lock. The lock fails to be held
when calling from l2cap_sock.c.

Fix by using l2cap_chan_conn_lock(), and taking the locks in required
order l2cap_conn::lock > l2cap_chan::lock > sk.  Leave fast path with
sk->sk_state precheck.  Move the L2CAP defer handling to
l2cap_sock_defer().

The code should also take l2cap_chan_lock() for sibling channels, but
that needs separate fix due to lock nesting.

Fixes: ab4eedb790 ("Bluetooth: L2CAP: Fix corrupted list in hci_chan_del")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:25:55 -04:00
Pauli Virtanen
df5175dfcf Bluetooth: 6lowpan: avoid concurrent peer_del() in bt_6lowpan_disconnect
bt_6lowpan_disconnect() looks up and accesses peer->chan, without
holding locks guaranteeing peer_del() cannot free the peer concurrently.

Take devices_lock to ensure peer can be dereferenced safely.

Fixes: 15f32cabf4 ("Bluetooth: 6lowpan: add missing l2cap_chan_lock()")
Signed-off-by: Pauli Virtanen <pav@iki.fi>
Signed-off-by: Luiz Augusto von Dentz <luiz.von.dentz@intel.com>
2026-10-14 13:25:36 -04:00