{"dataType":"CVE_RECORD","dataVersion":"5.2","cveMetadata":{"cveId":"CVE-2026-99239","assignerOrgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","state":"PUBLISHED","assignerShortName":"Linux","dateReserved":"2026-09-25T10:25:14.403Z","datePublished":"2026-11-02T16:06:43.262Z","dateUpdated":"2026-11-03T19:13:06.554Z"},"containers":{"cna":{"providerMetadata":{"orgId":"416baaa9-dc9f-4396-8d5f-8c081fb06d67","shortName":"Linux","dateUpdated":"2026-11-03T19:13:06.554Z"},"descriptions":[{"lang":"en","value":"In the Linux kernel, the following vulnerability has been resolved:\n\nBluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn\n\nl2cap_chan may be linked to l2cap_conn at most once. This is assumed in\nseveral places, eg l2cap_chan_del cleanup.\n\nThere is a TOCTOU race where the invariant is violated:\n\n    [Task 1]                          [Task 2]\n    l2cap_chan_connect                l2cap_sock_bind\n      l2cap_chan_lock                   lock_sock\n      l2cap_state_change                if (sk->sk_state != BT_OPEN)\n        chan->state = BT_CONNECT\n        l2cap_sock_state_change_cb      chan->state = BT_BOUND\n                                        sk->sk_state = BT_BOUND\n          lock_sock <------------------ release_sock\n          sk->sk_state = BT_CONNECT\n\nl2cap_sock_connect() does not check sk->sk_state, so since chan->state\nis now BT_BOUND, subsequent connect() ends up with second\n__l2cap_chan_add.\n\nExplicitly document and check the invariant in __l2cap_chan_add with\nWARN_ON_ONCE. The only callsite where it could be hit is\nl2cap_chan_connect, so add pre-check there to avoid relying on\nchan->state. chan->state read/write is not properly guarded currently so\nthere can be other TOCTOUC problems.\n\nAdd l2cap_lock_chan in l2cap_sock_bind() to guard chan->state write."}],"metrics":[{"cvssV3_1":{"version":"3.1","vectorString":"CVSS:3.1/AV:L/AC:L/PR:L/UI:N/S:U/C:H/I:H/A:H","baseScore":7.8,"baseSeverity":"HIGH"},"scenarios":[{"lang":"en","value":"AV:L - The double add is a local TOCTOU: l2cap_sock_connect()→l2cap_chan_connect()→__l2cap_chan_add() races l2cap_sock_bind(), which overwrites chan->state to BT_BOUND so a later connect() links the same l2cap_chan again. No received L2CAP/HCI PDU carries that state; a radio peer cannot issue those syscalls.\nAC:L - The attacker owns both threads. bind() holds lock_sock while l2cap_state_change() blocks in l2cap_sock_state_change_cb(); bind() then sets chan->state=BT_BOUND. l2cap_sock_connect() never checks sk->sk_state, so a later connect() observes BT_BOUND and calls __l2cap_chan_add() again. The race is attacker-driven and retryable.\nPR:L - l2cap_sock_create() requires capable(CAP_NET_RAW) only for SOCK_RAW; SOCK_SEQPACKET/STREAM used here have no capability gate. l2cap_add_psm() auto-picks a dynamic PSM (BR/EDR >=0x1001) without CAP_NET_BIND_SERVICE. bt_sock_create() is init_net-only, so this is an ordinary unprivileged local user.\nUI:N - The attacker opens their own AF_BLUETOOTH/BTPROTO_L2CAP socket and issues bind()/connect(). hci_connect_acl() creates the hci_conn, l2cap_conn_add() publishes l2cap_data, and __l2cap_chan_add() runs before any remote Connection Complete or pairing prompt.\nS:U - __l2cap_chan_add() corrupts the host kernel l2cap_chan.list linked into l2cap_conn.chan_l, which l2cap_chan_del() and l2cap_conn_del() then walk; the impact stays in the kernel L2CAP/HCI authority and does not cross a VM, IOMMU, or sandbox boundary.\nC:H - A second __l2cap_chan_add() to another l2cap_conn list_add_tail()s the same chan->list without unlinking it from the first conn->chan_l. l2cap_conn_del()'s list_for_each_entry_safe then follows those stale pointers and treats the other conn's list head as an l2cap_chan, an adjacent-slab type confusion that can be sprayed for a kernel read.\nI:H - l2cap_chan_del() list_del()s the twice-inserted chan->list, writing next/prev of the other connection's nodes, and l2cap_conn_del() calls chan->ops->teardown/close on the type-confused object. That unlink write plus ops-pointer invocation is a write/control-flow primitive.\nA:H - Inserting chan->list into the same conn->chan_l twice makes a self-loop, so __l2cap_get_chan_by_scid(), l2cap_conn_start(), and l2cap_conn_del() hang in list_for_each_entry; after list_del() the leftover head still points at the poisoned node and oopses."}]}],"affected":[{"product":"Linux","vendor":"Linux","defaultStatus":"unaffected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["net/bluetooth/l2cap_core.c","net/bluetooth/l2cap_sock.c"],"versions":[{"version":"8f90405a4a6f1f1880dc07996b47bf57c712bd8a","lessThan":"85cc289eb08afa975375f838187369e68b429ee0","status":"affected","versionType":"git"},{"version":"32d783cafb46ff3ca58e6f9fd62c9c5f35eaf26b","lessThan":"820579652b24ce277e0097cd65b42bd9b7b8bf07","status":"affected","versionType":"git"},{"version":"8922c7940bae9ce4b1736dddb6362370793835c2","lessThan":"e618d928ec7f88cbeadfa3542adcac40f474e629","status":"affected","versionType":"git"},{"version":"91047a4396a8b1857a6f712a90cf33ec0012b189","lessThan":"fabaff1c59ff2cc89cb7e5bd0186a5e15f0c73b2","status":"affected","versionType":"git"},{"version":"0b0e2bf39cf99e458d991b9df253727e036a7d7d","lessThan":"52fe88e4ef87311eee32b45c65603e7c69e75e7d","status":"affected","versionType":"git"},{"version":"d3b739db5dc6f688a60d56da872fabaf65246032","lessThan":"10c705dd706aa93164ba41f2566f15206d6c178e","status":"affected","versionType":"git"},{"version":"b66774b48dd98f07254951f74ea6f513efe7ff8b","lessThan":"73820561d8cbfd3364a29b8fa77f1707f26029da","status":"affected","versionType":"git"},{"version":"b66774b48dd98f07254951f74ea6f513efe7ff8b","lessThan":"d3afd7803f9bc2a8c4270199497b60158b2fc647","status":"affected","versionType":"git"},{"version":"b66774b48dd98f07254951f74ea6f513efe7ff8b","lessThan":"86b55991d3cd690e73c5ef8d20b75ae4905b357a","status":"affected","versionType":"git"},{"version":"50c38d9f42a529691e4e67ea9cedf4f0bfc8d277","status":"affected","versionType":"git"},{"version":"5.10.265","lessThan":"5.10.273","status":"affected","versionType":"semver"},{"version":"5.15.216","lessThan":"5.15.224","status":"affected","versionType":"semver"},{"version":"6.1.183","lessThan":"6.1.191","status":"affected","versionType":"semver"},{"version":"6.6.145","lessThan":"6.6.161","status":"affected","versionType":"semver"},{"version":"6.12.97","lessThan":"6.12.115","status":"affected","versionType":"semver"},{"version":"6.18.39","lessThan":"6.18.60","status":"affected","versionType":"semver"},{"version":"7.1.4","lessThan":"7.2","status":"affected","versionType":"semver"}]},{"product":"Linux","vendor":"Linux","defaultStatus":"affected","repo":"https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git","programFiles":["net/bluetooth/l2cap_core.c","net/bluetooth/l2cap_sock.c"],"versions":[{"version":"7.2","status":"affected"},{"version":"0","lessThan":"7.2","status":"unaffected","versionType":"semver"},{"version":"5.10.273","lessThanOrEqual":"5.10.*","status":"unaffected","versionType":"semver"},{"version":"5.15.224","lessThanOrEqual":"5.15.*","status":"unaffected","versionType":"semver"},{"version":"6.1.191","lessThanOrEqual":"6.1.*","status":"unaffected","versionType":"semver"},{"version":"6.6.161","lessThanOrEqual":"6.6.*","status":"unaffected","versionType":"semver"},{"version":"6.12.115","lessThanOrEqual":"6.12.*","status":"unaffected","versionType":"semver"},{"version":"6.18.60","lessThanOrEqual":"6.18.*","status":"unaffected","versionType":"semver"},{"version":"7.2.14","lessThanOrEqual":"7.2.*","status":"unaffected","versionType":"semver"},{"version":"7.3.1","lessThanOrEqual":"7.3.*","status":"unaffected","versionType":"semver"},{"version":"7.4-rc1","lessThanOrEqual":"*","status":"unaffected","versionType":"original_commit_for_fix"}]}],"cpeApplicability":[{"nodes":[{"operator":"OR","negate":false,"cpeMatch":[{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"5.10.265","versionEndExcluding":"5.10.273"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"5.15.216","versionEndExcluding":"5.15.224"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.1.183","versionEndExcluding":"6.1.191"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.6.145","versionEndExcluding":"6.6.161"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.12.97","versionEndExcluding":"6.12.115"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"6.18.39","versionEndExcluding":"6.18.60"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"7.2","versionEndExcluding":"7.2.14"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"7.2","versionEndExcluding":"7.3.1"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"7.2","versionEndExcluding":"7.4-rc1"},{"vulnerable":true,"criteria":"cpe:2.3:o:linux:linux_kernel:*:*:*:*:*:*:*:*","versionStartIncluding":"7.1.4"}]}]}],"references":[{"url":"https://git.kernel.org/stable/c/85cc289eb08afa975375f838187369e68b429ee0"},{"url":"https://git.kernel.org/stable/c/820579652b24ce277e0097cd65b42bd9b7b8bf07"},{"url":"https://git.kernel.org/stable/c/e618d928ec7f88cbeadfa3542adcac40f474e629"},{"url":"https://git.kernel.org/stable/c/fabaff1c59ff2cc89cb7e5bd0186a5e15f0c73b2"},{"url":"https://git.kernel.org/stable/c/52fe88e4ef87311eee32b45c65603e7c69e75e7d"},{"url":"https://git.kernel.org/stable/c/10c705dd706aa93164ba41f2566f15206d6c178e"},{"url":"https://git.kernel.org/stable/c/73820561d8cbfd3364a29b8fa77f1707f26029da"},{"url":"https://git.kernel.org/stable/c/d3afd7803f9bc2a8c4270199497b60158b2fc647"},{"url":"https://git.kernel.org/stable/c/86b55991d3cd690e73c5ef8d20b75ae4905b357a"}],"title":"Bluetooth: L2CAP: refuse __l2cap_chan_add if chan already has conn","x_generator":{"engine":"bippy-1.2.0"}}}}