PT-2026-82983 · Linux · Linux

CVE-2026-80683

·

Published

2026-08-28

·

Updated

2026-08-28

CVSS v3.1

8.8

High

VectorAV:A/AC:L/PR:N/UI:N/S:U/C:H/I:H/A:H
In the Linux kernel, the following vulnerability has been resolved:
Bluetooth: SCO: give the socket its own sco conn reference
sco conn del() drops a reference it does not own. It takes one transient reference via sco conn hold unless zero() and releases it with the sco conn put() that follows sco sock hold(); the additional put in the !sk branch releases a second one:
conn = sco conn hold unless zero(conn); ... sk = sco sock hold(conn); sco conn unlock(conn); sco conn put(conn);
if (!sk) { sco conn put(conn); return; }
When close() races the controller's Disconnection Complete, sco chan del() clears conn->sk and drops the socket's reference while sco conn del() is running. sco conn del() then sees sk == NULL, its own put drops the count to zero and frees the conn, and the second put writes to the freed kref:
BUG: KASAN: slab-use-after-free in sco conn put.part.0+0x1a/0x190 Write of size 4 at addr ffff8881099dec74 by task kworker/u17:3/413 Workqueue: hci1 hci rx work Call Trace: sco conn put.part.0+0x1a/0x190 hci disconn complete evt+0x1ee/0x3e0 hci event packet+0x54a/0x650 hci rx work+0x321/0x3d0 Allocated by task 413: sco conn add+0x72/0x1a0 sco connect cfm+0x88/0x670 Freed by task 413: sco conn del.isra.0+0x3f/0xf0 hci disconn complete evt+0x1ee/0x3e0 refcount t: underflow; use-after-free.
The root cause is that the socket stores the connection without holding a reference of its own. sco chan add() does:
sco pi(sk)->conn = conn;
so the socket borrows whatever reference its caller happened to hold, and the callers paper over that with ad-hoc holds and puts. Give the socket a counted reference instead: sco chan add() takes one and it is released together with the channel (sco chan del()) and in sco sock destruct(). With the socket holding its own reference, sco conn del() no longer needs the extra put and the redundant hold in sco conn ready() goes away.
Making the socket own its reference means the connection is now actually freed on the error paths of sco connect() where it used to leak, which in turn runs sco conn free() and its hci conn drop(conn->hcon). To keep the hci conn accounting balanced, make that ownership explicit as well: sco conn add() consumes one hci conn reference and the sco conn owns it for its lifetime. sco connect() hands over the reference returned by hci connect sco() and no longer drops it on the error paths; sco connect cfm(), which is not given a reference, takes one with hci conn hold() before handing it to sco conn add() (and drops it again if the allocation fails); and the explicit hci conn hold() in sco conn ready() is removed. Every reference then has a single, clear owner.

Fix

Found an issue in the description? Have something to add? Feel free to write us 👾

Related Identifiers

CVE-2026-80683

Affected Products

Linux