Linux bluetooth development
 help / color / mirror / Atom feed
* [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: [v2] Bluetooth: btusb: Add TP-Link UB600 for Realtek 8761BUV
From: Nils Helmig @ 2026-05-29 13:38 UTC (permalink / raw)
  To: bluez.test.bot; +Cc: linux-bluetooth, marcel, luiz.dentz, nils.helmig
In-Reply-To: <69ed185e.050a0220.107d78.67fa@mx.google.com>

I saw that the merge request https://github.com/bluez/bluetooth-next/pull/127 is closed. Any news on this patch? Is there anything I should do?

Regards,
Nils Helmig

^ permalink raw reply

* Re: [PATCH 1/1] Bluetooth: hci_codec: validate capability record length
From: Luiz Augusto von Dentz @ 2026-05-29 14:08 UTC (permalink / raw)
  To: Ren Wei
  Cc: linux-bluetooth, marcel, kiran.k, chethan.tumkur.narayan,
	ravishankar.srivatsa, yuantan098, zcliangcn, bird, xuyq21
In-Reply-To: <4927cae4fe043f3e2aa80f4ee6bed05e4fb5a6d4.1779633761.git.xuyq21@lenovo.com>

Hi Ren,

On Fri, May 29, 2026 at 9:12 AM Ren Wei <n05ec@lzu.edu.cn> wrote:
>
> 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;

Id go with skb_pull_data instead, that could probably be used first to
pull caps, and then another time for caps->len.

>                                 len += sizeof(caps->len) + caps->len;
>                                 skb_pull(skb,  sizeof(caps->len) + caps->len);
> --
> 2.54.0
>


-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [bluetooth-next:master] BUILD SUCCESS a82ccb946ae5d399437ece698590421c332252ed
From: kernel test robot @ 2026-05-29 14:09 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: linux-bluetooth

tree/branch: https://git.kernel.org/pub/scm/linux/kernel/git/bluetooth/bluetooth-next.git master
branch HEAD: a82ccb946ae5d399437ece698590421c332252ed  Bluetooth: RFCOMM: validate skb length in MCC handlers

elapsed time: 1292m

configs tested: 187
configs skipped: 2

The following configs have been built successfully.
More configs may be tested in the coming days.

tested configs:
alpha                             allnoconfig    gcc-15.2.0
alpha                            allyesconfig    gcc-15.2.0
alpha                               defconfig    gcc-15.2.0
arc                              allmodconfig    clang-16
arc                               allnoconfig    gcc-15.2.0
arc                              allyesconfig    clang-23
arc                                 defconfig    gcc-15.2.0
arc                   randconfig-001-20260529    clang-23
arc                   randconfig-002-20260529    clang-23
arm                               allnoconfig    gcc-15.2.0
arm                              allyesconfig    clang-16
arm                                 defconfig    gcc-15.2.0
arm                   randconfig-001-20260529    clang-23
arm                   randconfig-002-20260529    clang-23
arm                   randconfig-003-20260529    clang-23
arm                   randconfig-004-20260529    clang-23
arm64                            allmodconfig    clang-23
arm64                             allnoconfig    gcc-15.2.0
arm64                               defconfig    gcc-15.2.0
arm64                 randconfig-001-20260529    clang-23
arm64                 randconfig-002-20260529    clang-23
arm64                 randconfig-003-20260529    clang-23
arm64                 randconfig-004-20260529    clang-23
csky                             allmodconfig    gcc-15.2.0
csky                              allnoconfig    gcc-15.2.0
csky                                defconfig    gcc-15.2.0
csky                  randconfig-001-20260529    clang-23
csky                  randconfig-002-20260529    clang-23
hexagon                          allmodconfig    gcc-15.2.0
hexagon                           allnoconfig    gcc-15.2.0
hexagon                             defconfig    gcc-15.2.0
hexagon               randconfig-001-20260529    gcc-8.5.0
hexagon               randconfig-002-20260529    gcc-8.5.0
i386                             allmodconfig    clang-20
i386                              allnoconfig    gcc-15.2.0
i386                             allyesconfig    clang-20
i386        buildonly-randconfig-001-20260529    gcc-12
i386        buildonly-randconfig-002-20260529    gcc-12
i386        buildonly-randconfig-003-20260529    gcc-12
i386        buildonly-randconfig-004-20260529    gcc-12
i386        buildonly-randconfig-005-20260529    gcc-12
i386        buildonly-randconfig-006-20260529    gcc-12
i386                                defconfig    gcc-15.2.0
i386                           randconfig-001    gcc-14
i386                  randconfig-001-20260529    gcc-14
i386                           randconfig-002    gcc-14
i386                  randconfig-002-20260529    gcc-14
i386                           randconfig-003    gcc-14
i386                  randconfig-003-20260529    gcc-14
i386                           randconfig-004    gcc-14
i386                  randconfig-004-20260529    gcc-14
i386                           randconfig-005    gcc-14
i386                  randconfig-005-20260529    gcc-14
i386                           randconfig-006    gcc-14
i386                  randconfig-006-20260529    gcc-14
i386                           randconfig-007    gcc-14
i386                  randconfig-007-20260529    gcc-14
i386                  randconfig-011-20260529    gcc-14
i386                  randconfig-012-20260529    gcc-14
i386                  randconfig-013-20260529    gcc-14
i386                  randconfig-014-20260529    gcc-14
i386                  randconfig-015-20260529    gcc-14
i386                  randconfig-016-20260529    gcc-14
i386                  randconfig-017-20260529    gcc-14
loongarch                        allmodconfig    clang-23
loongarch                         allnoconfig    gcc-15.2.0
loongarch                           defconfig    clang-19
loongarch             randconfig-001-20260529    gcc-8.5.0
loongarch             randconfig-002-20260529    gcc-8.5.0
m68k                             allmodconfig    gcc-15.2.0
m68k                              allnoconfig    gcc-15.2.0
m68k                             allyesconfig    clang-16
m68k                                defconfig    clang-19
microblaze                        allnoconfig    gcc-15.2.0
microblaze                       allyesconfig    gcc-15.2.0
microblaze                          defconfig    clang-19
mips                             allmodconfig    gcc-15.2.0
mips                              allnoconfig    gcc-15.2.0
mips                             allyesconfig    gcc-15.2.0
nios2                            alldefconfig    gcc-11.5.0
nios2                            allmodconfig    clang-23
nios2                             allnoconfig    clang-23
nios2                               defconfig    clang-19
nios2                 randconfig-001-20260529    gcc-8.5.0
nios2                 randconfig-002-20260529    gcc-8.5.0
openrisc                         allmodconfig    clang-23
openrisc                          allnoconfig    clang-23
openrisc                            defconfig    gcc-15.2.0
parisc                           allmodconfig    gcc-15.2.0
parisc                            allnoconfig    clang-23
parisc                           allyesconfig    clang-19
parisc                              defconfig    gcc-15.2.0
parisc                         randconfig-001    clang-19
parisc                randconfig-001-20260529    clang-19
parisc                         randconfig-002    clang-19
parisc                randconfig-002-20260529    clang-19
parisc64                            defconfig    clang-19
powerpc                          allmodconfig    gcc-15.2.0
powerpc                           allnoconfig    clang-23
powerpc                        randconfig-001    clang-19
powerpc               randconfig-001-20260529    clang-19
powerpc                        randconfig-002    clang-19
powerpc               randconfig-002-20260529    clang-19
powerpc64                      randconfig-001    clang-19
powerpc64             randconfig-001-20260529    clang-19
powerpc64                      randconfig-002    clang-19
powerpc64             randconfig-002-20260529    clang-19
riscv                            allmodconfig    clang-23
riscv                             allnoconfig    clang-23
riscv                            allyesconfig    clang-16
riscv                               defconfig    gcc-15.2.0
riscv                 randconfig-001-20260529    gcc-15.2.0
riscv                 randconfig-002-20260529    gcc-15.2.0
s390                             allmodconfig    clang-19
s390                              allnoconfig    clang-23
s390                             allyesconfig    gcc-15.2.0
s390                                defconfig    gcc-15.2.0
s390                  randconfig-001-20260529    gcc-15.2.0
s390                  randconfig-002-20260529    gcc-15.2.0
sh                               allmodconfig    gcc-15.2.0
sh                                allnoconfig    clang-23
sh                               allyesconfig    clang-19
sh                                  defconfig    gcc-14
sh                    randconfig-001-20260529    gcc-15.2.0
sh                    randconfig-002-20260529    gcc-15.2.0
sparc                             allnoconfig    clang-23
sparc                               defconfig    gcc-15.2.0
sparc                 randconfig-001-20260529    gcc-11.5.0
sparc                 randconfig-002-20260529    gcc-11.5.0
sparc64                          allmodconfig    clang-23
sparc64                             defconfig    gcc-14
sparc64               randconfig-001-20260529    gcc-11.5.0
sparc64               randconfig-002-20260529    gcc-11.5.0
um                               allmodconfig    clang-19
um                                allnoconfig    clang-23
um                               allyesconfig    gcc-15.2.0
um                                  defconfig    gcc-14
um                             i386_defconfig    gcc-14
um                    randconfig-001-20260529    gcc-11.5.0
um                    randconfig-002-20260529    gcc-11.5.0
um                           x86_64_defconfig    gcc-14
x86_64                           allmodconfig    clang-20
x86_64                            allnoconfig    clang-23
x86_64                           allyesconfig    clang-20
x86_64      buildonly-randconfig-001-20260529    gcc-14
x86_64      buildonly-randconfig-002-20260529    gcc-14
x86_64      buildonly-randconfig-003-20260529    gcc-14
x86_64      buildonly-randconfig-004-20260529    gcc-14
x86_64      buildonly-randconfig-005-20260529    gcc-14
x86_64      buildonly-randconfig-006-20260529    gcc-14
x86_64                              defconfig    gcc-14
x86_64                                  kexec    clang-20
x86_64                         randconfig-001    clang-20
x86_64                randconfig-001-20260529    clang-20
x86_64                         randconfig-002    clang-20
x86_64                randconfig-002-20260529    clang-20
x86_64                         randconfig-003    clang-20
x86_64                randconfig-003-20260529    clang-20
x86_64                         randconfig-004    clang-20
x86_64                randconfig-004-20260529    clang-20
x86_64                         randconfig-005    clang-20
x86_64                randconfig-005-20260529    clang-20
x86_64                         randconfig-006    clang-20
x86_64                randconfig-006-20260529    clang-20
x86_64                randconfig-011-20260529    clang-20
x86_64                randconfig-012-20260529    clang-20
x86_64                randconfig-013-20260529    clang-20
x86_64                randconfig-014-20260529    clang-20
x86_64                randconfig-015-20260529    clang-20
x86_64                randconfig-016-20260529    clang-20
x86_64                randconfig-071-20260529    clang-20
x86_64                randconfig-072-20260529    clang-20
x86_64                randconfig-073-20260529    clang-20
x86_64                randconfig-074-20260529    clang-20
x86_64                randconfig-075-20260529    clang-20
x86_64                randconfig-076-20260529    clang-20
x86_64                               rhel-9.4    clang-20
x86_64                           rhel-9.4-bpf    gcc-14
x86_64                          rhel-9.4-func    clang-20
x86_64                    rhel-9.4-kselftests    clang-20
x86_64                         rhel-9.4-kunit    gcc-14
x86_64                           rhel-9.4-ltp    gcc-14
x86_64                          rhel-9.4-rust    clang-20
xtensa                            allnoconfig    clang-23
xtensa                           allyesconfig    clang-23
xtensa                randconfig-001-20260529    gcc-11.5.0
xtensa                randconfig-002-20260529    gcc-11.5.0

--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki

^ permalink raw reply

* RE: [1/1] Bluetooth: hci_codec: validate capability record length
From: bluez.test.bot @ 2026-05-29 15:09 UTC (permalink / raw)
  To: linux-bluetooth, n05ec
In-Reply-To: <4927cae4fe043f3e2aa80f4ee6bed05e4fb5a6d4.1779633761.git.xuyq21@lenovo.com>

[-- Attachment #1: Type: text/plain, Size: 3355 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=1102899

---Test result---

Test Summary:
CheckPatch                    FAIL      0.60 seconds
VerifyFixes                   PASS      0.09 seconds
VerifySignedoff               PASS      0.09 seconds
GitLint                       PASS      0.25 seconds
SubjectPrefix                 PASS      0.47 seconds
BuildKernel                   PASS      26.89 seconds
CheckAllWarning               PASS      28.89 seconds
CheckSparse                   PASS      27.74 seconds
BuildKernel32                 PASS      25.94 seconds
TestRunnerSetup               PASS      574.02 seconds
TestRunner_l2cap-tester       PASS      60.78 seconds
TestRunner_iso-tester         PASS      80.04 seconds
TestRunner_bnep-tester        PASS      19.62 seconds
TestRunner_mgmt-tester        FAIL      221.48 seconds
TestRunner_rfcomm-tester      PASS      25.72 seconds
TestRunner_sco-tester         PASS      33.76 seconds
TestRunner_ioctl-tester       PASS      26.62 seconds
TestRunner_mesh-tester        FAIL      26.89 seconds
TestRunner_smp-tester         PASS      24.22 seconds
TestRunner_userchan-tester    PASS      21.02 seconds
TestRunner_6lowpan-tester     PASS      24.16 seconds
IncrementalBuild              PASS      25.60 seconds

Details
##############################
Test: CheckPatch - FAIL
Desc: Run checkpatch.pl script
Output:
[1/1] Bluetooth: hci_codec: validate capability record length
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, 8 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/14601083.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.550 seconds
Mesh - Send cancel - 2                               Timed out    1.993 seconds


https://github.com/bluez/bluetooth-next/pull/255

---
Regards,
Linux Bluetooth


^ permalink raw reply

* Re: [PATCH BlueZ] mgmt: Remove mgmt_ev[] strings of undefined MGMT events
From: patchwork-bot+bluetooth @ 2026-05-29 15:40 UTC (permalink / raw)
  To: =?utf-8?b?RnLDqWTDqXJpYyBEYW5pcyA8ZnJlZGVyaWMuZGFuaXNAY29sbGFib3JhLmNvbT4=?=
  Cc: linux-bluetooth
In-Reply-To: <20260528074938.385847-1-frederic.danis@collabora.com>

Hello:

This patch was applied to bluetooth/bluez.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Thu, 28 May 2026 09:49:38 +0200 you wrote:
> Remove event strings introduced in mgmt_ev[] but for which the MGMT
> events has not been defined.
> 
> Those events are already part of the events_le_table[] in
> monitor/packet.c
> 
> Fixes: f9557931ad36 ("monitor: Add decoding support for Sync Receiver events")
> 
> [...]

Here is the summary with links:
  - [BlueZ] mgmt: Remove mgmt_ev[] strings of undefined MGMT events
    https://git.kernel.org/pub/scm/bluetooth/bluez.git/?id=17fbb48d8f7c

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 1/1] Bluetooth: hci_sync: reject oversized Broadcast Announcement prepend
From: patchwork-bot+bluetooth @ 2026-05-29 15:50 UTC (permalink / raw)
  To: Ren Wei
  Cc: linux-bluetooth, marcel, luiz.dentz, yuantan098, zcliangcn, bird,
	xuyq21
In-Reply-To: <9089784d08f1afd038b4ce0df1fb89904f4879ee.1779634468.git.xuyq21@lenovo.com>

Hello:

This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:

On Fri, 29 May 2026 16:54:23 +0800 you wrote:
> 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.
> 
> [...]

Here is the summary with links:
  - [1/1] Bluetooth: hci_sync: reject oversized Broadcast Announcement prepend
    https://git.kernel.org/bluetooth/bluetooth-next/c/0bc614e5e938

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: L2CAP: reject BR/EDR signaling packets over MTUsig
From: patchwork-bot+bluetooth @ 2026-05-29 15:50 UTC (permalink / raw)
  To: Michael Bommarito; +Cc: marcel, luiz.dentz, linux-bluetooth
In-Reply-To: <20260521144518.1361335-1-michael.bommarito@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, 21 May 2026 10:45:17 -0400 you wrote:
> net/bluetooth/l2cap_core.c:l2cap_sig_channel() accepts BR/EDR
> signaling packets up to the channel MTU and dispatches each command
> without enforcing the signaling MTU (MTUsig). A Bluetooth BR/EDR peer
> within radio range can send a fixed-channel CID 0x0001 packet that is
> larger than MTUsig and contains many L2CAP_ECHO_REQ commands before
> pairing. In a real-radio stock-kernel run, one 681-byte signaling
> packet containing 168 zero-length ECHO_REQ commands made the target
> transmit 168 ECHO_RSP frames over about 220 ms.
> 
> [...]

Here is the summary with links:
  - [v4] Bluetooth: L2CAP: reject BR/EDR signaling packets over MTUsig
    https://git.kernel.org/bluetooth/bluetooth-next/c/a6273f046450

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 v5] Bluetooth: bnep: reject short frames before parsing
From: patchwork-bot+bluetooth @ 2026-05-29 15:50 UTC (permalink / raw)
  To: Zhang Cen
  Cc: marcel, luiz.dentz, linux-bluetooth, linux-kernel, zerocling0077,
	2045gemini
In-Reply-To: <20260529032209.2269753-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 Fri, 29 May 2026 11:22:09 +0800 you 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.
> 
> [...]

Here is the summary with links:
  - [v5] Bluetooth: bnep: reject short frames before parsing
    https://git.kernel.org/bluetooth/bluetooth-next/c/379b101059b4

You are awesome, thank you!
-- 
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html



^ permalink raw reply

* [bluez/bluez] 17fbb4: mgmt: Remove mgmt_ev[] strings of undefined MGMT e...
From: fdanis-oss @ 2026-05-29 16:25 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/master
  Home:   https://github.com/bluez/bluez
  Commit: 17fbb48d8f7c22d0702b3b9daf69f9c06231d774
      https://github.com/bluez/bluez/commit/17fbb48d8f7c22d0702b3b9daf69f9c06231d774
  Author: Frédéric Danis <frederic.danis@collabora.com>
  Date:   2026-05-29 (Fri, 29 May 2026)

  Changed paths:
    M lib/bluetooth/mgmt.h

  Log Message:
  -----------
  mgmt: Remove mgmt_ev[] strings of undefined MGMT events

Remove event strings introduced in mgmt_ev[] but for which the MGMT
events has not been defined.

Those events are already part of the events_le_table[] in
monitor/packet.c

Fixes: f9557931ad36 ("monitor: Add decoding support for Sync Receiver events")



To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [bluez/bluez]
From: BluezTestBot @ 2026-05-29 16:26 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1102048
  Home:   https://github.com/bluez/bluez

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* [bluez/bluez]
From: BluezTestBot @ 2026-05-29 16:26 UTC (permalink / raw)
  To: linux-bluetooth

  Branch: refs/heads/1087593
  Home:   https://github.com/bluez/bluez

To unsubscribe from these emails, change your notification settings at https://github.com/bluez/bluez/settings/notifications

^ permalink raw reply

* Re: [PATCH v5 1/1] Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()
From: Siwei Zhang @ 2026-05-29 16:33 UTC (permalink / raw)
  To: Luiz Augusto von Dentz; +Cc: Marcel Holtmann, linux-bluetooth
In-Reply-To: <c45459c5-e7d9-4ea2-bd61-903a33f8778f@app.fastmail.com>

Hi Luiz,

On Wed, May 27, 2026, at 12:16 AM, Siwei Zhang wrote:
> Hi Luiz,
>
> On Tue, May 26, 2026, at 4:46 PM, Luiz Augusto von Dentz wrote:
>> Hi Siwei,
>>
>> On Wed, May 20, 2026 at 12:20 PM Siwei Zhang <oss@fourdim.xyz> wrote:
>>>
>>> l2cap_sock_new_connection_cb() accesses l2cap_pi(sk)->chan after
>>> release_sock(parent). Once the parent lock is released, the child
>>> socket sk can be freed by another task.
>>>
>>> Allocate the channel outside the func to prevent this.
>>>
>>> Fixes: 8ffb929098a5 ("Bluetooth: Remove parent socket usage from l2cap_core.c")
>>> Cc: stable@kernel.org
>>> Assisted-by: Claude:claude-opus-4-6
>>> Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
>>> ---
>>>  include/net/bluetooth/l2cap.h |  8 +++--
>>>  net/bluetooth/6lowpan.c       | 14 ++++-----
>>>  net/bluetooth/l2cap_core.c    | 58 ++++++++++++++++++++++++++++-------
>>>  net/bluetooth/l2cap_sock.c    | 48 +++++++++++++++++------------
>>>  net/bluetooth/smp.c           | 13 +++-----
>>>  5 files changed, 91 insertions(+), 50 deletions(-)
>>>
>>> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
>>> index 5172afee5494..f7a11e6431f0 100644
>>> --- a/include/net/bluetooth/l2cap.h
>>> +++ b/include/net/bluetooth/l2cap.h
>>> @@ -619,7 +619,8 @@ struct l2cap_chan {
>>>  struct l2cap_ops {
>>>         char                    *name;
>>>
>>> -       struct l2cap_chan       *(*new_connection) (struct l2cap_chan *chan);
>>> +       int                     (*new_connection)(struct l2cap_chan *chan,
>>> +                                                 struct l2cap_chan *new_chan);
>>>         int                     (*recv) (struct l2cap_chan * chan,
>>>                                          struct sk_buff *skb);
>>>         void                    (*teardown) (struct l2cap_chan *chan, int err);
>>> @@ -883,9 +884,10 @@ static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
>>>         return (seq + 1) % (chan->tx_win_max + 1);
>>>  }
>>>
>>> -static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
>>> +static inline int l2cap_chan_no_new_connection(struct l2cap_chan *chan,
>>> +                                              struct l2cap_chan *new_chan)
>>>  {
>>> -       return NULL;
>>> +       return -EOPNOTSUPP;
>>>  }
>>>
>>>  static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
>>> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
>>> index 23a229ab6a33..286c0b45055b 100644
>>> --- a/net/bluetooth/6lowpan.c
>>> +++ b/net/bluetooth/6lowpan.c
>>> @@ -743,19 +743,19 @@ static inline void chan_ready_cb(struct l2cap_chan *chan)
>>>         ifup(dev->netdev);
>>>  }
>>>
>>> -static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan)
>>> +static inline int chan_new_conn_cb(struct l2cap_chan *pchan,
>>> +                                  struct l2cap_chan *chan)
>>>  {
>>> -       struct l2cap_chan *chan;
>>> -
>>> -       chan = chan_create();
>>> -       if (!chan)
>>> -               return NULL;
>>> +       l2cap_chan_set_defaults(chan);
>>>
>>> +       chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
>>> +       chan->mode = L2CAP_MODE_LE_FLOWCTL;
>>> +       chan->imtu = 1280;
>>
>> The 3 lines above make no sense.
>>
>
> chan_create code in 6lowpan.c
>
> static struct l2cap_chan *chan_create(void)
> {
> 	struct l2cap_chan *chan;
>
> 	chan = l2cap_chan_create();
> 	if (!chan)
> 		return NULL;
>
> 	l2cap_chan_set_defaults(chan);
>
> 	chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
> 	chan->mode = L2CAP_MODE_LE_FLOWCTL;
> 	chan->imtu = 1280;
>
> 	return chan;
> }
>
> Since we allocate chan outside and replace the chan_create here,
> I do think these are needed and they are specific to 6lowpan only.
>
> I can refactor it in this patch or in a follow-up patch. I would prefer it
> to be in a follow-up patch.
>

What do you think. Please let me know if you want me to change anything.

>>>         chan->ops = pchan->ops;
>>>
>>>         BT_DBG("chan %p pchan %p", chan, pchan);
>>>
>>> -       return chan;
>>> +       return 0;
>>>  }
>>>
>>>  static void unregister_dev(struct lowpan_btle_dev *dev)
>>> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
>>> index fdccd62ccca8..505f32034971 100644
>>> --- a/net/bluetooth/l2cap_core.c
>>> +++ b/net/bluetooth/l2cap_core.c
>>> @@ -4051,10 +4051,16 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
>>>                 goto response;
>>>         }
>>>
>>> -       chan = pchan->ops->new_connection(pchan);
>>> +       chan = l2cap_chan_create();
>>>         if (!chan)
>>>                 goto response;
>>>
>>> +       if (pchan->ops->new_connection(pchan, chan) < 0) {
>>> +               l2cap_chan_put(chan);
>>> +               chan = NULL;
>>> +               goto response;
>>> +       }
>>> +
>>>         /* For certain devices (ex: HID mouse), support for authentication,
>>>          * pairing and bonding is optional. For such devices, inorder to avoid
>>>          * the ACL alive for too long after L2CAP disconnection, reset the ACL
>>> @@ -4132,6 +4138,10 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
>>>                 chan->num_conf_req++;
>>>         }
>>>
>>> +       /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
>>> +       if (chan)
>>> +               l2cap_chan_put(chan);
>>> +
>>>         l2cap_chan_unlock(pchan);
>>>         l2cap_chan_put(pchan);
>>>  }
>>> @@ -4881,6 +4891,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
>>>         struct l2cap_le_conn_rsp rsp;
>>>         struct l2cap_chan *chan, *pchan;
>>>         u16 dcid, scid, credits, mtu, mps;
>>> +       u16 rsp_mtu, rsp_mps;
>>>         __le16 psm;
>>>         u8 result;
>>>
>>> @@ -4893,6 +4904,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
>>>         psm  = req->psm;
>>>         dcid = 0;
>>>         credits = 0;
>>> +       rsp_mtu = 0;
>>> +       rsp_mps = 0;
>>>
>>>         if (mtu < 23 || mps < 23)
>>>                 return -EPROTO;
>>> @@ -4953,12 +4966,19 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
>>>                 goto response_unlock;
>>>         }
>>>
>>> -       chan = pchan->ops->new_connection(pchan);
>>> +       chan = l2cap_chan_create();
>>>         if (!chan) {
>>>                 result = L2CAP_CR_LE_NO_MEM;
>>>                 goto response_unlock;
>>>         }
>>>
>>> +       if (pchan->ops->new_connection(pchan, chan) < 0) {
>>> +               l2cap_chan_put(chan);
>>> +               chan = NULL;
>>> +               result = L2CAP_CR_LE_NO_MEM;
>>> +               goto response_unlock;
>>> +       }
>>> +
>>>         bacpy(&chan->src, &conn->hcon->src);
>>>         bacpy(&chan->dst, &conn->hcon->dst);
>>>         chan->src_type = bdaddr_src_type(conn->hcon);
>>> @@ -4974,6 +4994,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
>>>
>>>         dcid = chan->scid;
>>>         credits = chan->rx_credits;
>>> +       rsp_mtu = chan->imtu;
>>> +       rsp_mps = chan->mps;
>>>
>>>         __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
>>>
>>> @@ -4993,6 +5015,9 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
>>>                 result = L2CAP_CR_LE_SUCCESS;
>>>         }
>>>
>>> +       /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
>>> +       l2cap_chan_put(chan);
>>> +
>>>  response_unlock:
>>>         l2cap_chan_unlock(pchan);
>>>         l2cap_chan_put(pchan);
>>> @@ -5001,13 +5026,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
>>>                 return 0;
>>>
>>>  response:
>>> -       if (chan) {
>>> -               rsp.mtu = cpu_to_le16(chan->imtu);
>>> -               rsp.mps = cpu_to_le16(chan->mps);
>>> -       } else {
>>> -               rsp.mtu = 0;
>>> -               rsp.mps = 0;
>>> -       }
>>> +       rsp.mtu = cpu_to_le16(rsp_mtu);
>>> +       rsp.mps = cpu_to_le16(rsp_mps);
>>>
>>>         rsp.dcid    = cpu_to_le16(dcid);
>>>         rsp.credits = cpu_to_le16(credits);
>>> @@ -5177,12 +5197,18 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
>>>                         continue;
>>>                 }
>>>
>>> -               chan = pchan->ops->new_connection(pchan);
>>> +               chan = l2cap_chan_create();
>>>                 if (!chan) {
>>>                         result = L2CAP_CR_LE_NO_MEM;
>>>                         continue;
>>>                 }
>>>
>>> +               if (pchan->ops->new_connection(pchan, chan) < 0) {
>>> +                       l2cap_chan_put(chan);
>>> +                       result = L2CAP_CR_LE_NO_MEM;
>>> +                       continue;
>>> +               }
>>> +
>>>                 bacpy(&chan->src, &conn->hcon->src);
>>>                 bacpy(&chan->dst, &conn->hcon->dst);
>>>                 chan->src_type = bdaddr_src_type(conn->hcon);
>>> @@ -5217,6 +5243,9 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
>>>                 } else {
>>>                         l2cap_chan_ready(chan);
>>>                 }
>>> +
>>> +               /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
>>> +               l2cap_chan_put(chan);
>>>         }
>>>
>>>  unlock:
>>> @@ -7399,7 +7428,11 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
>>>                         goto next;
>>>
>>>                 l2cap_chan_lock(pchan);
>>> -               chan = pchan->ops->new_connection(pchan);
>>> +               chan = l2cap_chan_create();
>>> +               if (chan && pchan->ops->new_connection(pchan, chan) < 0) {
>>> +                       l2cap_chan_put(chan);
>>> +                       chan = NULL;
>>> +               }
>>>                 if (chan) {
>>>                         bacpy(&chan->src, &hcon->src);
>>>                         bacpy(&chan->dst, &hcon->dst);
>>> @@ -7407,6 +7440,9 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
>>>                         chan->dst_type = dst_type;
>>>
>>>                         __l2cap_chan_add(conn, chan);
>>> +
>>> +                       /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
>>> +                       l2cap_chan_put(chan);
>>>                 }
>>>
>>>                 l2cap_chan_unlock(pchan);
>>> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
>>> index dede550d6031..598f24c8f704 100644
>>> --- a/net/bluetooth/l2cap_sock.c
>>> +++ b/net/bluetooth/l2cap_sock.c
>>> @@ -46,7 +46,8 @@ static struct bt_sock_list l2cap_sk_list = {
>>>  static const struct proto_ops l2cap_sock_ops;
>>>  static void l2cap_sock_init(struct sock *sk, struct sock *parent);
>>>  static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
>>> -                                    int proto, gfp_t prio, int kern);
>>> +                                    int proto, gfp_t prio, int kern,
>>> +                                    struct l2cap_chan *chan);
>>>  static void l2cap_sock_cleanup_listen(struct sock *parent);
>>>
>>>  bool l2cap_is_socket(struct socket *sock)
>>> @@ -1507,12 +1508,13 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
>>>         }
>>>  }
>>>
>>> -static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
>>> +static int l2cap_sock_new_connection_cb(struct l2cap_chan *chan,
>>> +                                       struct l2cap_chan *new_chan)
>>>  {
>>>         struct sock *sk, *parent = chan->data;
>>>
>>>         if (!parent)
>>> -               return NULL;
>>> +               return -EINVAL;
>>>
>>>         lock_sock(parent);
>>>
>>> @@ -1520,15 +1522,15 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
>>>         if (sk_acceptq_is_full(parent)) {
>>>                 BT_DBG("backlog full %d", parent->sk_ack_backlog);
>>>                 release_sock(parent);
>>> -               return NULL;
>>> +               return -ENOBUFS;
>>>         }
>>>
>>>         sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
>>> -                             GFP_ATOMIC, 0);
>>> +                             GFP_ATOMIC, 0, new_chan);
>>>         if (!sk) {
>>>                 release_sock(parent);
>>> -               return NULL;
>>> -        }
>>> +               return -ENOMEM;
>>> +       }
>>>
>>>         bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
>>>
>>> @@ -1538,7 +1540,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
>>>
>>>         release_sock(parent);
>>>
>>> -       return l2cap_pi(sk)->chan;
>>> +       return 0;
>>>  }
>>>
>>>  static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
>>> @@ -1939,10 +1941,10 @@ static struct proto l2cap_proto = {
>>>  };
>>>
>>>  static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
>>> -                                    int proto, gfp_t prio, int kern)
>>> +                                    int proto, gfp_t prio, int kern,
>>> +                                    struct l2cap_chan *chan)
>>>  {
>>>         struct sock *sk;
>>> -       struct l2cap_chan *chan;
>>>
>>>         sk = bt_sock_alloc(net, sock, &l2cap_proto, proto, prio, kern);
>>>         if (!sk)
>>> @@ -1953,14 +1955,11 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
>>>
>>>         INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy);
>>>
>>> -       chan = l2cap_chan_create();
>>> -       if (!chan) {
>>> -               sk_free(sk);
>>> -               if (sock)
>>> -                       sock->sk = NULL;
>>> -               return NULL;
>>> -       }
>>> -
>>> +       /* The sock owns two refs on chan, matching the puts in
>>> +        * l2cap_sock_kill() and l2cap_sock_destruct(). The caller keeps
>>> +        * its own ref independent of these.
>>> +        */
>>> +       l2cap_chan_hold(chan);
>>>         l2cap_chan_hold(chan);
>>>
>>>         l2cap_pi(sk)->chan = chan;
>>> @@ -1972,6 +1971,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
>>>                              int kern)
>>>  {
>>>         struct sock *sk;
>>> +       struct l2cap_chan *chan;
>>>
>>>         BT_DBG("sock %p", sock);
>>>
>>> @@ -1986,10 +1986,18 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
>>>
>>>         sock->ops = &l2cap_sock_ops;
>>>
>>> -       sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
>>> -       if (!sk)
>>> +       chan = l2cap_chan_create();
>>> +       if (!chan)
>>>                 return -ENOMEM;
>>>
>>> +       sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern, chan);
>>> +       if (!sk) {
>>> +               l2cap_chan_put(chan);
>>> +               return -ENOMEM;
>>> +       }
>>> +       /* Sock has taken its own refs on chan; drop the chan_create() ref. */
>>> +       l2cap_chan_put(chan);
>>> +
>>>         l2cap_sock_init(sk, NULL);
>>>         bt_sock_link(&l2cap_sk_list, sk);
>>>         return 0;
>>> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
>>> index 1739c1989dbd..25cb5dc580bf 100644
>>> --- a/net/bluetooth/smp.c
>>> +++ b/net/bluetooth/smp.c
>>> @@ -3204,16 +3204,11 @@ static const struct l2cap_ops smp_chan_ops = {
>>>         .get_sndtimeo           = l2cap_chan_no_get_sndtimeo,
>>>  };
>>>
>>> -static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
>>> +static inline int smp_new_conn_cb(struct l2cap_chan *pchan,
>>> +                                 struct l2cap_chan *chan)
>>>  {
>>> -       struct l2cap_chan *chan;
>>> -
>>>         BT_DBG("pchan %p", pchan);
>>>
>>> -       chan = l2cap_chan_create();
>>> -       if (!chan)
>>> -               return NULL;
>>> -
>>>         chan->chan_type = pchan->chan_type;
>>>         chan->ops       = &smp_chan_ops;
>>>         chan->scid      = pchan->scid;
>>> @@ -3229,9 +3224,9 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
>>>          */
>>>         atomic_set(&chan->nesting, L2CAP_NESTING_SMP);
>>>
>>> -       BT_DBG("created chan %p", chan);
>>> +       BT_DBG("initialised chan %p", chan);
>>>
>>> -       return chan;
>>> +       return 0;
>>>  }
>>>
>>>  static const struct l2cap_ops smp_root_chan_ops = {
>>> --
>>> 2.54.0
>>>
>>
>>
>> -- 
>> Luiz Augusto von Dentz
>
> Best,
> Siwei

Best,
Siwei

^ permalink raw reply

* Re: [PATCH v5 1/1] Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()
From: Luiz Augusto von Dentz @ 2026-05-29 16:40 UTC (permalink / raw)
  To: Siwei Zhang; +Cc: Marcel Holtmann, linux-bluetooth
In-Reply-To: <460b3909-2210-4cf3-be9e-4f8af3175160@app.fastmail.com>

Hi Siwei,

On Fri, May 29, 2026 at 12:33 PM Siwei Zhang <oss@fourdim.xyz> wrote:
>
> Hi Luiz,
>
> On Wed, May 27, 2026, at 12:16 AM, Siwei Zhang wrote:
> > Hi Luiz,
> >
> > On Tue, May 26, 2026, at 4:46 PM, Luiz Augusto von Dentz wrote:
> >> Hi Siwei,
> >>
> >> On Wed, May 20, 2026 at 12:20 PM Siwei Zhang <oss@fourdim.xyz> wrote:
> >>>
> >>> l2cap_sock_new_connection_cb() accesses l2cap_pi(sk)->chan after
> >>> release_sock(parent). Once the parent lock is released, the child
> >>> socket sk can be freed by another task.
> >>>
> >>> Allocate the channel outside the func to prevent this.
> >>>
> >>> Fixes: 8ffb929098a5 ("Bluetooth: Remove parent socket usage from l2cap_core.c")
> >>> Cc: stable@kernel.org
> >>> Assisted-by: Claude:claude-opus-4-6
> >>> Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
> >>> ---
> >>>  include/net/bluetooth/l2cap.h |  8 +++--
> >>>  net/bluetooth/6lowpan.c       | 14 ++++-----
> >>>  net/bluetooth/l2cap_core.c    | 58 ++++++++++++++++++++++++++++-------
> >>>  net/bluetooth/l2cap_sock.c    | 48 +++++++++++++++++------------
> >>>  net/bluetooth/smp.c           | 13 +++-----
> >>>  5 files changed, 91 insertions(+), 50 deletions(-)
> >>>
> >>> diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
> >>> index 5172afee5494..f7a11e6431f0 100644
> >>> --- a/include/net/bluetooth/l2cap.h
> >>> +++ b/include/net/bluetooth/l2cap.h
> >>> @@ -619,7 +619,8 @@ struct l2cap_chan {
> >>>  struct l2cap_ops {
> >>>         char                    *name;
> >>>
> >>> -       struct l2cap_chan       *(*new_connection) (struct l2cap_chan *chan);
> >>> +       int                     (*new_connection)(struct l2cap_chan *chan,
> >>> +                                                 struct l2cap_chan *new_chan);
> >>>         int                     (*recv) (struct l2cap_chan * chan,
> >>>                                          struct sk_buff *skb);
> >>>         void                    (*teardown) (struct l2cap_chan *chan, int err);
> >>> @@ -883,9 +884,10 @@ static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
> >>>         return (seq + 1) % (chan->tx_win_max + 1);
> >>>  }
> >>>
> >>> -static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
> >>> +static inline int l2cap_chan_no_new_connection(struct l2cap_chan *chan,
> >>> +                                              struct l2cap_chan *new_chan)
> >>>  {
> >>> -       return NULL;
> >>> +       return -EOPNOTSUPP;
> >>>  }
> >>>
> >>>  static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
> >>> diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
> >>> index 23a229ab6a33..286c0b45055b 100644
> >>> --- a/net/bluetooth/6lowpan.c
> >>> +++ b/net/bluetooth/6lowpan.c
> >>> @@ -743,19 +743,19 @@ static inline void chan_ready_cb(struct l2cap_chan *chan)
> >>>         ifup(dev->netdev);
> >>>  }
> >>>
> >>> -static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan)
> >>> +static inline int chan_new_conn_cb(struct l2cap_chan *pchan,
> >>> +                                  struct l2cap_chan *chan)
> >>>  {
> >>> -       struct l2cap_chan *chan;
> >>> -
> >>> -       chan = chan_create();
> >>> -       if (!chan)
> >>> -               return NULL;
> >>> +       l2cap_chan_set_defaults(chan);
> >>>
> >>> +       chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
> >>> +       chan->mode = L2CAP_MODE_LE_FLOWCTL;
> >>> +       chan->imtu = 1280;
> >>
> >> The 3 lines above make no sense.
> >>
> >
> > chan_create code in 6lowpan.c
> >
> > static struct l2cap_chan *chan_create(void)
> > {
> >       struct l2cap_chan *chan;
> >
> >       chan = l2cap_chan_create();
> >       if (!chan)
> >               return NULL;
> >
> >       l2cap_chan_set_defaults(chan);
> >
> >       chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
> >       chan->mode = L2CAP_MODE_LE_FLOWCTL;
> >       chan->imtu = 1280;
> >
> >       return chan;
> > }
> >
> > Since we allocate chan outside and replace the chan_create here,
> > I do think these are needed and they are specific to 6lowpan only.
> >
> > I can refactor it in this patch or in a follow-up patch. I would prefer it
> > to be in a follow-up patch.
> >
>
> What do you think. Please let me know if you want me to change anything.

There is something off then, because nothing is being removed that
sets similar values which is what led me to believe it was necessary
at first.

> >>>         chan->ops = pchan->ops;
> >>>
> >>>         BT_DBG("chan %p pchan %p", chan, pchan);
> >>>
> >>> -       return chan;
> >>> +       return 0;
> >>>  }
> >>>
> >>>  static void unregister_dev(struct lowpan_btle_dev *dev)
> >>> diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
> >>> index fdccd62ccca8..505f32034971 100644
> >>> --- a/net/bluetooth/l2cap_core.c
> >>> +++ b/net/bluetooth/l2cap_core.c
> >>> @@ -4051,10 +4051,16 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
> >>>                 goto response;
> >>>         }
> >>>
> >>> -       chan = pchan->ops->new_connection(pchan);
> >>> +       chan = l2cap_chan_create();
> >>>         if (!chan)
> >>>                 goto response;
> >>>
> >>> +       if (pchan->ops->new_connection(pchan, chan) < 0) {
> >>> +               l2cap_chan_put(chan);
> >>> +               chan = NULL;
> >>> +               goto response;
> >>> +       }
> >>> +
> >>>         /* For certain devices (ex: HID mouse), support for authentication,
> >>>          * pairing and bonding is optional. For such devices, inorder to avoid
> >>>          * the ACL alive for too long after L2CAP disconnection, reset the ACL
> >>> @@ -4132,6 +4138,10 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
> >>>                 chan->num_conf_req++;
> >>>         }
> >>>
> >>> +       /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
> >>> +       if (chan)
> >>> +               l2cap_chan_put(chan);
> >>> +
> >>>         l2cap_chan_unlock(pchan);
> >>>         l2cap_chan_put(pchan);
> >>>  }
> >>> @@ -4881,6 +4891,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
> >>>         struct l2cap_le_conn_rsp rsp;
> >>>         struct l2cap_chan *chan, *pchan;
> >>>         u16 dcid, scid, credits, mtu, mps;
> >>> +       u16 rsp_mtu, rsp_mps;
> >>>         __le16 psm;
> >>>         u8 result;
> >>>
> >>> @@ -4893,6 +4904,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
> >>>         psm  = req->psm;
> >>>         dcid = 0;
> >>>         credits = 0;
> >>> +       rsp_mtu = 0;
> >>> +       rsp_mps = 0;
> >>>
> >>>         if (mtu < 23 || mps < 23)
> >>>                 return -EPROTO;
> >>> @@ -4953,12 +4966,19 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
> >>>                 goto response_unlock;
> >>>         }
> >>>
> >>> -       chan = pchan->ops->new_connection(pchan);
> >>> +       chan = l2cap_chan_create();
> >>>         if (!chan) {
> >>>                 result = L2CAP_CR_LE_NO_MEM;
> >>>                 goto response_unlock;
> >>>         }
> >>>
> >>> +       if (pchan->ops->new_connection(pchan, chan) < 0) {
> >>> +               l2cap_chan_put(chan);
> >>> +               chan = NULL;
> >>> +               result = L2CAP_CR_LE_NO_MEM;
> >>> +               goto response_unlock;
> >>> +       }
> >>> +
> >>>         bacpy(&chan->src, &conn->hcon->src);
> >>>         bacpy(&chan->dst, &conn->hcon->dst);
> >>>         chan->src_type = bdaddr_src_type(conn->hcon);
> >>> @@ -4974,6 +4994,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
> >>>
> >>>         dcid = chan->scid;
> >>>         credits = chan->rx_credits;
> >>> +       rsp_mtu = chan->imtu;
> >>> +       rsp_mps = chan->mps;
> >>>
> >>>         __set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
> >>>
> >>> @@ -4993,6 +5015,9 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
> >>>                 result = L2CAP_CR_LE_SUCCESS;
> >>>         }
> >>>
> >>> +       /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
> >>> +       l2cap_chan_put(chan);
> >>> +
> >>>  response_unlock:
> >>>         l2cap_chan_unlock(pchan);
> >>>         l2cap_chan_put(pchan);
> >>> @@ -5001,13 +5026,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
> >>>                 return 0;
> >>>
> >>>  response:
> >>> -       if (chan) {
> >>> -               rsp.mtu = cpu_to_le16(chan->imtu);
> >>> -               rsp.mps = cpu_to_le16(chan->mps);
> >>> -       } else {
> >>> -               rsp.mtu = 0;
> >>> -               rsp.mps = 0;
> >>> -       }
> >>> +       rsp.mtu = cpu_to_le16(rsp_mtu);
> >>> +       rsp.mps = cpu_to_le16(rsp_mps);
> >>>
> >>>         rsp.dcid    = cpu_to_le16(dcid);
> >>>         rsp.credits = cpu_to_le16(credits);
> >>> @@ -5177,12 +5197,18 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
> >>>                         continue;
> >>>                 }
> >>>
> >>> -               chan = pchan->ops->new_connection(pchan);
> >>> +               chan = l2cap_chan_create();
> >>>                 if (!chan) {
> >>>                         result = L2CAP_CR_LE_NO_MEM;
> >>>                         continue;
> >>>                 }
> >>>
> >>> +               if (pchan->ops->new_connection(pchan, chan) < 0) {
> >>> +                       l2cap_chan_put(chan);
> >>> +                       result = L2CAP_CR_LE_NO_MEM;
> >>> +                       continue;
> >>> +               }
> >>> +
> >>>                 bacpy(&chan->src, &conn->hcon->src);
> >>>                 bacpy(&chan->dst, &conn->hcon->dst);
> >>>                 chan->src_type = bdaddr_src_type(conn->hcon);
> >>> @@ -5217,6 +5243,9 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
> >>>                 } else {
> >>>                         l2cap_chan_ready(chan);
> >>>                 }
> >>> +
> >>> +               /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
> >>> +               l2cap_chan_put(chan);
> >>>         }
> >>>
> >>>  unlock:
> >>> @@ -7399,7 +7428,11 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> >>>                         goto next;
> >>>
> >>>                 l2cap_chan_lock(pchan);
> >>> -               chan = pchan->ops->new_connection(pchan);
> >>> +               chan = l2cap_chan_create();
> >>> +               if (chan && pchan->ops->new_connection(pchan, chan) < 0) {
> >>> +                       l2cap_chan_put(chan);
> >>> +                       chan = NULL;
> >>> +               }
> >>>                 if (chan) {
> >>>                         bacpy(&chan->src, &hcon->src);
> >>>                         bacpy(&chan->dst, &hcon->dst);
> >>> @@ -7407,6 +7440,9 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
> >>>                         chan->dst_type = dst_type;
> >>>
> >>>                         __l2cap_chan_add(conn, chan);
> >>> +
> >>> +                       /* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
> >>> +                       l2cap_chan_put(chan);
> >>>                 }
> >>>
> >>>                 l2cap_chan_unlock(pchan);
> >>> diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
> >>> index dede550d6031..598f24c8f704 100644
> >>> --- a/net/bluetooth/l2cap_sock.c
> >>> +++ b/net/bluetooth/l2cap_sock.c
> >>> @@ -46,7 +46,8 @@ static struct bt_sock_list l2cap_sk_list = {
> >>>  static const struct proto_ops l2cap_sock_ops;
> >>>  static void l2cap_sock_init(struct sock *sk, struct sock *parent);
> >>>  static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
> >>> -                                    int proto, gfp_t prio, int kern);
> >>> +                                    int proto, gfp_t prio, int kern,
> >>> +                                    struct l2cap_chan *chan);
> >>>  static void l2cap_sock_cleanup_listen(struct sock *parent);
> >>>
> >>>  bool l2cap_is_socket(struct socket *sock)
> >>> @@ -1507,12 +1508,13 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
> >>>         }
> >>>  }
> >>>
> >>> -static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
> >>> +static int l2cap_sock_new_connection_cb(struct l2cap_chan *chan,
> >>> +                                       struct l2cap_chan *new_chan)
> >>>  {
> >>>         struct sock *sk, *parent = chan->data;
> >>>
> >>>         if (!parent)
> >>> -               return NULL;
> >>> +               return -EINVAL;
> >>>
> >>>         lock_sock(parent);
> >>>
> >>> @@ -1520,15 +1522,15 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
> >>>         if (sk_acceptq_is_full(parent)) {
> >>>                 BT_DBG("backlog full %d", parent->sk_ack_backlog);
> >>>                 release_sock(parent);
> >>> -               return NULL;
> >>> +               return -ENOBUFS;
> >>>         }
> >>>
> >>>         sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
> >>> -                             GFP_ATOMIC, 0);
> >>> +                             GFP_ATOMIC, 0, new_chan);
> >>>         if (!sk) {
> >>>                 release_sock(parent);
> >>> -               return NULL;
> >>> -        }
> >>> +               return -ENOMEM;
> >>> +       }
> >>>
> >>>         bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
> >>>
> >>> @@ -1538,7 +1540,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
> >>>
> >>>         release_sock(parent);
> >>>
> >>> -       return l2cap_pi(sk)->chan;
> >>> +       return 0;
> >>>  }
> >>>
> >>>  static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
> >>> @@ -1939,10 +1941,10 @@ static struct proto l2cap_proto = {
> >>>  };
> >>>
> >>>  static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
> >>> -                                    int proto, gfp_t prio, int kern)
> >>> +                                    int proto, gfp_t prio, int kern,
> >>> +                                    struct l2cap_chan *chan)
> >>>  {
> >>>         struct sock *sk;
> >>> -       struct l2cap_chan *chan;
> >>>
> >>>         sk = bt_sock_alloc(net, sock, &l2cap_proto, proto, prio, kern);
> >>>         if (!sk)
> >>> @@ -1953,14 +1955,11 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
> >>>
> >>>         INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy);
> >>>
> >>> -       chan = l2cap_chan_create();
> >>> -       if (!chan) {
> >>> -               sk_free(sk);
> >>> -               if (sock)
> >>> -                       sock->sk = NULL;
> >>> -               return NULL;
> >>> -       }
> >>> -
> >>> +       /* The sock owns two refs on chan, matching the puts in
> >>> +        * l2cap_sock_kill() and l2cap_sock_destruct(). The caller keeps
> >>> +        * its own ref independent of these.
> >>> +        */
> >>> +       l2cap_chan_hold(chan);
> >>>         l2cap_chan_hold(chan);
> >>>
> >>>         l2cap_pi(sk)->chan = chan;
> >>> @@ -1972,6 +1971,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
> >>>                              int kern)
> >>>  {
> >>>         struct sock *sk;
> >>> +       struct l2cap_chan *chan;
> >>>
> >>>         BT_DBG("sock %p", sock);
> >>>
> >>> @@ -1986,10 +1986,18 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
> >>>
> >>>         sock->ops = &l2cap_sock_ops;
> >>>
> >>> -       sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
> >>> -       if (!sk)
> >>> +       chan = l2cap_chan_create();
> >>> +       if (!chan)
> >>>                 return -ENOMEM;
> >>>
> >>> +       sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern, chan);
> >>> +       if (!sk) {
> >>> +               l2cap_chan_put(chan);
> >>> +               return -ENOMEM;
> >>> +       }
> >>> +       /* Sock has taken its own refs on chan; drop the chan_create() ref. */
> >>> +       l2cap_chan_put(chan);
> >>> +
> >>>         l2cap_sock_init(sk, NULL);
> >>>         bt_sock_link(&l2cap_sk_list, sk);
> >>>         return 0;
> >>> diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
> >>> index 1739c1989dbd..25cb5dc580bf 100644
> >>> --- a/net/bluetooth/smp.c
> >>> +++ b/net/bluetooth/smp.c
> >>> @@ -3204,16 +3204,11 @@ static const struct l2cap_ops smp_chan_ops = {
> >>>         .get_sndtimeo           = l2cap_chan_no_get_sndtimeo,
> >>>  };
> >>>
> >>> -static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
> >>> +static inline int smp_new_conn_cb(struct l2cap_chan *pchan,
> >>> +                                 struct l2cap_chan *chan)
> >>>  {
> >>> -       struct l2cap_chan *chan;
> >>> -
> >>>         BT_DBG("pchan %p", pchan);
> >>>
> >>> -       chan = l2cap_chan_create();
> >>> -       if (!chan)
> >>> -               return NULL;
> >>> -
> >>>         chan->chan_type = pchan->chan_type;
> >>>         chan->ops       = &smp_chan_ops;
> >>>         chan->scid      = pchan->scid;
> >>> @@ -3229,9 +3224,9 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
> >>>          */
> >>>         atomic_set(&chan->nesting, L2CAP_NESTING_SMP);
> >>>
> >>> -       BT_DBG("created chan %p", chan);
> >>> +       BT_DBG("initialised chan %p", chan);
> >>>
> >>> -       return chan;
> >>> +       return 0;
> >>>  }
> >>>
> >>>  static const struct l2cap_ops smp_root_chan_ops = {
> >>> --
> >>> 2.54.0
> >>>
> >>
> >>
> >> --
> >> Luiz Augusto von Dentz
> >
> > Best,
> > Siwei
>
> Best,
> Siwei



-- 
Luiz Augusto von Dentz

^ permalink raw reply

* [PATCH v6 0/1] Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()
From: Siwei Zhang @ 2026-05-29 16:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz; +Cc: linux-bluetooth, Siwei Zhang

Compared to v2, addresses comments on https://sashiko.dev/#/patchset/20260415204842.2363950-1-oss%40fourdim.xyz .

Compared to v3, rebase against bluetooth-next.

Compared to v4, allocate the channel outside the function and pass it in as an argument to avoid the use-after-free.

Compared to v5, extract the channel init to a separate function.

Siwei Zhang (1):
  Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()

 include/net/bluetooth/l2cap.h |  8 +++--
 net/bluetooth/6lowpan.c       | 27 ++++++++--------
 net/bluetooth/l2cap_core.c    | 58 ++++++++++++++++++++++++++++-------
 net/bluetooth/l2cap_sock.c    | 48 +++++++++++++++++------------
 net/bluetooth/smp.c           | 13 +++-----
 5 files changed, 98 insertions(+), 56 deletions(-)

-- 
2.54.0


^ permalink raw reply

* [PATCH v6 1/1] Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()
From: Siwei Zhang @ 2026-05-29 16:54 UTC (permalink / raw)
  To: Marcel Holtmann, Luiz Augusto von Dentz; +Cc: linux-bluetooth, Siwei Zhang
In-Reply-To: <20260529165449.3553936-1-oss@fourdim.xyz>

l2cap_sock_new_connection_cb() accesses l2cap_pi(sk)->chan after
release_sock(parent). Once the parent lock is released, the child
socket sk can be freed by another task.

Allocate the channel outside the func to prevent this.

Fixes: 8ffb929098a5 ("Bluetooth: Remove parent socket usage from l2cap_core.c")
Cc: stable@kernel.org
Assisted-by: Claude:claude-opus-4-6
Signed-off-by: Siwei Zhang <oss@fourdim.xyz>
---
 include/net/bluetooth/l2cap.h |  8 +++--
 net/bluetooth/6lowpan.c       | 27 ++++++++--------
 net/bluetooth/l2cap_core.c    | 58 ++++++++++++++++++++++++++++-------
 net/bluetooth/l2cap_sock.c    | 48 +++++++++++++++++------------
 net/bluetooth/smp.c           | 13 +++-----
 5 files changed, 98 insertions(+), 56 deletions(-)

diff --git a/include/net/bluetooth/l2cap.h b/include/net/bluetooth/l2cap.h
index 5172afee5494..f7a11e6431f0 100644
--- a/include/net/bluetooth/l2cap.h
+++ b/include/net/bluetooth/l2cap.h
@@ -619,7 +619,8 @@ struct l2cap_chan {
 struct l2cap_ops {
 	char			*name;
 
-	struct l2cap_chan	*(*new_connection) (struct l2cap_chan *chan);
+	int			(*new_connection)(struct l2cap_chan *chan,
+						  struct l2cap_chan *new_chan);
 	int			(*recv) (struct l2cap_chan * chan,
 					 struct sk_buff *skb);
 	void			(*teardown) (struct l2cap_chan *chan, int err);
@@ -883,9 +884,10 @@ static inline __u16 __next_seq(struct l2cap_chan *chan, __u16 seq)
 	return (seq + 1) % (chan->tx_win_max + 1);
 }
 
-static inline struct l2cap_chan *l2cap_chan_no_new_connection(struct l2cap_chan *chan)
+static inline int l2cap_chan_no_new_connection(struct l2cap_chan *chan,
+					       struct l2cap_chan *new_chan)
 {
-	return NULL;
+	return -EOPNOTSUPP;
 }
 
 static inline int l2cap_chan_no_recv(struct l2cap_chan *chan, struct sk_buff *skb)
diff --git a/net/bluetooth/6lowpan.c b/net/bluetooth/6lowpan.c
index 23a229ab6a33..a5830b5746d8 100644
--- a/net/bluetooth/6lowpan.c
+++ b/net/bluetooth/6lowpan.c
@@ -622,6 +622,15 @@ static bool is_bt_6lowpan(struct hci_conn *hcon)
 	return true;
 }
 
+static void chan_init(struct l2cap_chan *chan)
+{
+	l2cap_chan_set_defaults(chan);
+
+	chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
+	chan->mode = L2CAP_MODE_LE_FLOWCTL;
+	chan->imtu = 1280;
+}
+
 static struct l2cap_chan *chan_create(void)
 {
 	struct l2cap_chan *chan;
@@ -630,11 +639,7 @@ static struct l2cap_chan *chan_create(void)
 	if (!chan)
 		return NULL;
 
-	l2cap_chan_set_defaults(chan);
-
-	chan->chan_type = L2CAP_CHAN_CONN_ORIENTED;
-	chan->mode = L2CAP_MODE_LE_FLOWCTL;
-	chan->imtu = 1280;
+	chan_init(chan);
 
 	return chan;
 }
@@ -743,19 +748,15 @@ static inline void chan_ready_cb(struct l2cap_chan *chan)
 	ifup(dev->netdev);
 }
 
-static inline struct l2cap_chan *chan_new_conn_cb(struct l2cap_chan *pchan)
+static inline int chan_new_conn_cb(struct l2cap_chan *pchan,
+				   struct l2cap_chan *chan)
 {
-	struct l2cap_chan *chan;
-
-	chan = chan_create();
-	if (!chan)
-		return NULL;
-
+	chan_init(chan);
 	chan->ops = pchan->ops;
 
 	BT_DBG("chan %p pchan %p", chan, pchan);
 
-	return chan;
+	return 0;
 }
 
 static void unregister_dev(struct lowpan_btle_dev *dev)
diff --git a/net/bluetooth/l2cap_core.c b/net/bluetooth/l2cap_core.c
index fdccd62ccca8..505f32034971 100644
--- a/net/bluetooth/l2cap_core.c
+++ b/net/bluetooth/l2cap_core.c
@@ -4051,10 +4051,16 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
 		goto response;
 	}
 
-	chan = pchan->ops->new_connection(pchan);
+	chan = l2cap_chan_create();
 	if (!chan)
 		goto response;
 
+	if (pchan->ops->new_connection(pchan, chan) < 0) {
+		l2cap_chan_put(chan);
+		chan = NULL;
+		goto response;
+	}
+
 	/* For certain devices (ex: HID mouse), support for authentication,
 	 * pairing and bonding is optional. For such devices, inorder to avoid
 	 * the ACL alive for too long after L2CAP disconnection, reset the ACL
@@ -4132,6 +4138,10 @@ static void l2cap_connect(struct l2cap_conn *conn, struct l2cap_cmd_hdr *cmd,
 		chan->num_conf_req++;
 	}
 
+	/* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
+	if (chan)
+		l2cap_chan_put(chan);
+
 	l2cap_chan_unlock(pchan);
 	l2cap_chan_put(pchan);
 }
@@ -4881,6 +4891,7 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 	struct l2cap_le_conn_rsp rsp;
 	struct l2cap_chan *chan, *pchan;
 	u16 dcid, scid, credits, mtu, mps;
+	u16 rsp_mtu, rsp_mps;
 	__le16 psm;
 	u8 result;
 
@@ -4893,6 +4904,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 	psm  = req->psm;
 	dcid = 0;
 	credits = 0;
+	rsp_mtu = 0;
+	rsp_mps = 0;
 
 	if (mtu < 23 || mps < 23)
 		return -EPROTO;
@@ -4953,12 +4966,19 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 		goto response_unlock;
 	}
 
-	chan = pchan->ops->new_connection(pchan);
+	chan = l2cap_chan_create();
 	if (!chan) {
 		result = L2CAP_CR_LE_NO_MEM;
 		goto response_unlock;
 	}
 
+	if (pchan->ops->new_connection(pchan, chan) < 0) {
+		l2cap_chan_put(chan);
+		chan = NULL;
+		result = L2CAP_CR_LE_NO_MEM;
+		goto response_unlock;
+	}
+
 	bacpy(&chan->src, &conn->hcon->src);
 	bacpy(&chan->dst, &conn->hcon->dst);
 	chan->src_type = bdaddr_src_type(conn->hcon);
@@ -4974,6 +4994,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 
 	dcid = chan->scid;
 	credits = chan->rx_credits;
+	rsp_mtu = chan->imtu;
+	rsp_mps = chan->mps;
 
 	__set_chan_timer(chan, chan->ops->get_sndtimeo(chan));
 
@@ -4993,6 +5015,9 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 		result = L2CAP_CR_LE_SUCCESS;
 	}
 
+	/* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
+	l2cap_chan_put(chan);
+
 response_unlock:
 	l2cap_chan_unlock(pchan);
 	l2cap_chan_put(pchan);
@@ -5001,13 +5026,8 @@ static int l2cap_le_connect_req(struct l2cap_conn *conn,
 		return 0;
 
 response:
-	if (chan) {
-		rsp.mtu = cpu_to_le16(chan->imtu);
-		rsp.mps = cpu_to_le16(chan->mps);
-	} else {
-		rsp.mtu = 0;
-		rsp.mps = 0;
-	}
+	rsp.mtu = cpu_to_le16(rsp_mtu);
+	rsp.mps = cpu_to_le16(rsp_mps);
 
 	rsp.dcid    = cpu_to_le16(dcid);
 	rsp.credits = cpu_to_le16(credits);
@@ -5177,12 +5197,18 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
 			continue;
 		}
 
-		chan = pchan->ops->new_connection(pchan);
+		chan = l2cap_chan_create();
 		if (!chan) {
 			result = L2CAP_CR_LE_NO_MEM;
 			continue;
 		}
 
+		if (pchan->ops->new_connection(pchan, chan) < 0) {
+			l2cap_chan_put(chan);
+			result = L2CAP_CR_LE_NO_MEM;
+			continue;
+		}
+
 		bacpy(&chan->src, &conn->hcon->src);
 		bacpy(&chan->dst, &conn->hcon->dst);
 		chan->src_type = bdaddr_src_type(conn->hcon);
@@ -5217,6 +5243,9 @@ static inline int l2cap_ecred_conn_req(struct l2cap_conn *conn,
 		} else {
 			l2cap_chan_ready(chan);
 		}
+
+		/* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
+		l2cap_chan_put(chan);
 	}
 
 unlock:
@@ -7399,7 +7428,11 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 			goto next;
 
 		l2cap_chan_lock(pchan);
-		chan = pchan->ops->new_connection(pchan);
+		chan = l2cap_chan_create();
+		if (chan && pchan->ops->new_connection(pchan, chan) < 0) {
+			l2cap_chan_put(chan);
+			chan = NULL;
+		}
 		if (chan) {
 			bacpy(&chan->src, &hcon->src);
 			bacpy(&chan->dst, &hcon->dst);
@@ -7407,6 +7440,9 @@ static void l2cap_connect_cfm(struct hci_conn *hcon, u8 status)
 			chan->dst_type = dst_type;
 
 			__l2cap_chan_add(conn, chan);
+
+			/* Drop our local ref; __l2cap_chan_add() pinned chan via the conn list. */
+			l2cap_chan_put(chan);
 		}
 
 		l2cap_chan_unlock(pchan);
diff --git a/net/bluetooth/l2cap_sock.c b/net/bluetooth/l2cap_sock.c
index dede550d6031..598f24c8f704 100644
--- a/net/bluetooth/l2cap_sock.c
+++ b/net/bluetooth/l2cap_sock.c
@@ -46,7 +46,8 @@ static struct bt_sock_list l2cap_sk_list = {
 static const struct proto_ops l2cap_sock_ops;
 static void l2cap_sock_init(struct sock *sk, struct sock *parent);
 static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
-				     int proto, gfp_t prio, int kern);
+				     int proto, gfp_t prio, int kern,
+				     struct l2cap_chan *chan);
 static void l2cap_sock_cleanup_listen(struct sock *parent);
 
 bool l2cap_is_socket(struct socket *sock)
@@ -1507,12 +1508,13 @@ static void l2cap_sock_cleanup_listen(struct sock *parent)
 	}
 }
 
-static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
+static int l2cap_sock_new_connection_cb(struct l2cap_chan *chan,
+					struct l2cap_chan *new_chan)
 {
 	struct sock *sk, *parent = chan->data;
 
 	if (!parent)
-		return NULL;
+		return -EINVAL;
 
 	lock_sock(parent);
 
@@ -1520,15 +1522,15 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
 	if (sk_acceptq_is_full(parent)) {
 		BT_DBG("backlog full %d", parent->sk_ack_backlog);
 		release_sock(parent);
-		return NULL;
+		return -ENOBUFS;
 	}
 
 	sk = l2cap_sock_alloc(sock_net(parent), NULL, BTPROTO_L2CAP,
-			      GFP_ATOMIC, 0);
+			      GFP_ATOMIC, 0, new_chan);
 	if (!sk) {
 		release_sock(parent);
-		return NULL;
-        }
+		return -ENOMEM;
+	}
 
 	bt_sock_reclassify_lock(sk, BTPROTO_L2CAP);
 
@@ -1538,7 +1540,7 @@ static struct l2cap_chan *l2cap_sock_new_connection_cb(struct l2cap_chan *chan)
 
 	release_sock(parent);
 
-	return l2cap_pi(sk)->chan;
+	return 0;
 }
 
 static int l2cap_sock_recv_cb(struct l2cap_chan *chan, struct sk_buff *skb)
@@ -1939,10 +1941,10 @@ static struct proto l2cap_proto = {
 };
 
 static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
-				     int proto, gfp_t prio, int kern)
+				     int proto, gfp_t prio, int kern,
+				     struct l2cap_chan *chan)
 {
 	struct sock *sk;
-	struct l2cap_chan *chan;
 
 	sk = bt_sock_alloc(net, sock, &l2cap_proto, proto, prio, kern);
 	if (!sk)
@@ -1953,14 +1955,11 @@ static struct sock *l2cap_sock_alloc(struct net *net, struct socket *sock,
 
 	INIT_LIST_HEAD(&l2cap_pi(sk)->rx_busy);
 
-	chan = l2cap_chan_create();
-	if (!chan) {
-		sk_free(sk);
-		if (sock)
-			sock->sk = NULL;
-		return NULL;
-	}
-
+	/* The sock owns two refs on chan, matching the puts in
+	 * l2cap_sock_kill() and l2cap_sock_destruct(). The caller keeps
+	 * its own ref independent of these.
+	 */
+	l2cap_chan_hold(chan);
 	l2cap_chan_hold(chan);
 
 	l2cap_pi(sk)->chan = chan;
@@ -1972,6 +1971,7 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 			     int kern)
 {
 	struct sock *sk;
+	struct l2cap_chan *chan;
 
 	BT_DBG("sock %p", sock);
 
@@ -1986,10 +1986,18 @@ static int l2cap_sock_create(struct net *net, struct socket *sock, int protocol,
 
 	sock->ops = &l2cap_sock_ops;
 
-	sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern);
-	if (!sk)
+	chan = l2cap_chan_create();
+	if (!chan)
 		return -ENOMEM;
 
+	sk = l2cap_sock_alloc(net, sock, protocol, GFP_ATOMIC, kern, chan);
+	if (!sk) {
+		l2cap_chan_put(chan);
+		return -ENOMEM;
+	}
+	/* Sock has taken its own refs on chan; drop the chan_create() ref. */
+	l2cap_chan_put(chan);
+
 	l2cap_sock_init(sk, NULL);
 	bt_sock_link(&l2cap_sk_list, sk);
 	return 0;
diff --git a/net/bluetooth/smp.c b/net/bluetooth/smp.c
index 1739c1989dbd..25cb5dc580bf 100644
--- a/net/bluetooth/smp.c
+++ b/net/bluetooth/smp.c
@@ -3204,16 +3204,11 @@ static const struct l2cap_ops smp_chan_ops = {
 	.get_sndtimeo		= l2cap_chan_no_get_sndtimeo,
 };
 
-static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
+static inline int smp_new_conn_cb(struct l2cap_chan *pchan,
+				  struct l2cap_chan *chan)
 {
-	struct l2cap_chan *chan;
-
 	BT_DBG("pchan %p", pchan);
 
-	chan = l2cap_chan_create();
-	if (!chan)
-		return NULL;
-
 	chan->chan_type	= pchan->chan_type;
 	chan->ops	= &smp_chan_ops;
 	chan->scid	= pchan->scid;
@@ -3229,9 +3224,9 @@ static inline struct l2cap_chan *smp_new_conn_cb(struct l2cap_chan *pchan)
 	 */
 	atomic_set(&chan->nesting, L2CAP_NESTING_SMP);
 
-	BT_DBG("created chan %p", chan);
+	BT_DBG("initialised chan %p", chan);
 
-	return chan;
+	return 0;
 }
 
 static const struct l2cap_ops smp_root_chan_ops = {
-- 
2.54.0


^ permalink raw reply related

* [PATCH v1 0/2] Bluetooth: Fix data-race on dst/src in connect paths
From: SeungJu Cheon @ 2026-05-29 17:33 UTC (permalink / raw)
  To: marcel, luiz.dentz
  Cc: linux-bluetooth, linux-kernel, me, skhan, linux-kernel-mentees,
	SeungJu Cheon

Two KCSAN-reported data races on socket address fields passed to
hci_get_route() without proper synchronization.

Patch 1/2 fixes ISO: iso_connect_bis(), iso_connect_cis(),
iso_listen_bis(), and iso_conn_big_sync() read iso_pi(sk)->dst/src
without lock_sock before calling hci_get_route().

Patch 2/2 fixes SCO: sco_connect() reads sco_pi(sk)->dst after
lock_sock has been released by the caller.

Both races were confirmed with KCSAN using VHCI-based reproducers.

SeungJu Cheon (2):
  Bluetooth: ISO: Fix data-race on iso_pi fields in hci_get_route calls
  Bluetooth: SCO: Fix data-race on dst in sco_connect

 net/bluetooth/iso.c | 51 ++++++++++++++++++++++++++++++++++-----------
 net/bluetooth/sco.c | 11 +++++++---
 2 files changed, 47 insertions(+), 15 deletions(-)

-- 
2.52.0


^ permalink raw reply

* [PATCH v1 1/2] Bluetooth: ISO: Fix data-race on iso_pi fields in hci_get_route calls
From: SeungJu Cheon @ 2026-05-29 17:33 UTC (permalink / raw)
  To: marcel, luiz.dentz
  Cc: linux-bluetooth, linux-kernel, me, skhan, linux-kernel-mentees,
	SeungJu Cheon
In-Reply-To: <20260529173347.43967-1-suunj1331@gmail.com>

iso_connect_bis(), iso_connect_cis(), iso_listen_bis(), and
iso_conn_big_sync() all call hci_get_route() reading iso_pi(sk)->dst,
iso_pi(sk)->src, and iso_pi(sk)->src_type without holding lock_sock.

These fields can be concurrently written by another thread calling
connect() or setsockopt() on the same socket, leading to torn reads
or TOCTOU mismatches.

Fix by snapshotting dst, src, and src_type into local variables under
lock_sock before calling hci_get_route() in all four functions.

BUG: KCSAN: data-race in memcmp+0x45/0xb0

race at unknown origin, with read to 0xffff8880122135cf of 1 bytes by task 333 on cpu 1:
 memcmp+0x45/0xb0
 hci_get_route+0x27e/0x490
 iso_connect_cis+0x4c/0xa10
 iso_sock_connect+0x60e/0xb30
 __sys_connect_file+0xbd/0xe0
 __sys_connect+0xe0/0x110
 __x64_sys_connect+0x40/0x50
 x64_sys_call+0xcad/0x1c60
 do_syscall_64+0x133/0x590
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Fixes: 241f51931c35 ("Bluetooth: ISO: Avoid circular locking dependency")
Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
---
 net/bluetooth/iso.c | 51 ++++++++++++++++++++++++++++++++++-----------
 1 file changed, 39 insertions(+), 12 deletions(-)

diff --git a/net/bluetooth/iso.c b/net/bluetooth/iso.c
index d7af617cda45..58bb3a10d49f 100644
--- a/net/bluetooth/iso.c
+++ b/net/bluetooth/iso.c
@@ -337,12 +337,19 @@ static int iso_connect_bis(struct sock *sk)
 	struct iso_conn *conn;
 	struct hci_conn *hcon;
 	struct hci_dev  *hdev;
+	bdaddr_t src, dst;
+	u8 src_type;
 	int err;
 
-	BT_DBG("%pMR (SID 0x%2.2x)", &iso_pi(sk)->src, iso_pi(sk)->bc_sid);
+	lock_sock(sk);
+	bacpy(&dst, &iso_pi(sk)->dst);
+	bacpy(&src, &iso_pi(sk)->src);
+	src_type = iso_pi(sk)->src_type;
+	release_sock(sk);
+
+	BT_DBG("%pMR (SID 0x%2.2x)", &src, iso_pi(sk)->bc_sid);
 
-	hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
-			     iso_pi(sk)->src_type);
+	hdev = hci_get_route(&dst, &src, src_type);
 	if (!hdev)
 		return -EHOSTUNREACH;
 
@@ -430,12 +437,19 @@ static int iso_connect_cis(struct sock *sk)
 	struct iso_conn *conn;
 	struct hci_conn *hcon;
 	struct hci_dev  *hdev;
+	bdaddr_t src, dst;
+	u8 src_type;
 	int err;
 
-	BT_DBG("%pMR -> %pMR", &iso_pi(sk)->src, &iso_pi(sk)->dst);
+	lock_sock(sk);
+	bacpy(&dst, &iso_pi(sk)->dst);
+	bacpy(&src, &iso_pi(sk)->src);
+	src_type = iso_pi(sk)->src_type;
+	release_sock(sk);
+
+	BT_DBG("%pMR -> %pMR", &src, &dst);
 
-	hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
-			     iso_pi(sk)->src_type);
+	hdev = hci_get_route(&dst, &src, src_type);
 	if (!hdev)
 		return -EHOSTUNREACH;
 
@@ -1210,11 +1224,18 @@ static int iso_listen_bis(struct sock *sk)
 {
 	struct hci_dev *hdev;
 	int err = 0;
+	bdaddr_t src, dst;
+	u8 src_type;
 	struct iso_conn *conn;
 	struct hci_conn *hcon;
 
-	BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &iso_pi(sk)->src,
-	       &iso_pi(sk)->dst, iso_pi(sk)->bc_sid);
+	lock_sock(sk);
+	bacpy(&dst, &iso_pi(sk)->dst);
+	bacpy(&src, &iso_pi(sk)->src);
+	src_type = iso_pi(sk)->src_type;
+	release_sock(sk);
+
+	BT_DBG("%pMR -> %pMR (SID 0x%2.2x)", &src, &dst, iso_pi(sk)->bc_sid);
 
 	write_lock(&iso_sk_list.lock);
 
@@ -1227,8 +1248,7 @@ static int iso_listen_bis(struct sock *sk)
 	if (err)
 		return err;
 
-	hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
-			     iso_pi(sk)->src_type);
+	hdev = hci_get_route(&dst, &src, src_type);
 	if (!hdev)
 		return -EHOSTUNREACH;
 
@@ -1564,9 +1584,16 @@ static void iso_conn_big_sync(struct sock *sk)
 {
 	int err;
 	struct hci_dev *hdev;
+	bdaddr_t src, dst;
+	u8 src_type;
+
+	lock_sock(sk);
+	bacpy(&dst, &iso_pi(sk)->dst);
+	bacpy(&src, &iso_pi(sk)->src);
+	src_type = iso_pi(sk)->src_type;
+	release_sock(sk);
 
-	hdev = hci_get_route(&iso_pi(sk)->dst, &iso_pi(sk)->src,
-			     iso_pi(sk)->src_type);
+	hdev = hci_get_route(&dst, &src, src_type);
 
 	if (!hdev)
 		return;
-- 
2.52.0


^ permalink raw reply related

* [PATCH v1 2/2] Bluetooth: SCO: Fix data-race on dst in sco_connect
From: SeungJu Cheon @ 2026-05-29 17:33 UTC (permalink / raw)
  To: marcel, luiz.dentz
  Cc: linux-bluetooth, linux-kernel, me, skhan, linux-kernel-mentees,
	SeungJu Cheon
In-Reply-To: <20260529173347.43967-1-suunj1331@gmail.com>

sco_sock_connect() copies the destination address into
sco_pi(sk)->dst under lock_sock, then releases the lock and calls
sco_connect(), which reads dst back without holding any lock in
hci_get_route() and hci_connect_sco().

If two threads call connect() on the same socket concurrently with
different addresses, one thread can overwrite dst before the other
thread's sco_connect() reads it.

Fix by snapshotting dst into a local variable under lock_sock at
the start of sco_connect(), matching the approach used for ISO in
the previous patch.

BUG: KCSAN: data-race in memcmp+0x45/0xb0

race at unknown origin, with read to 0xffff88800e6b0dd0 of 1 bytes by task 315 on cpu 0:
 memcmp+0x45/0xb0
 hci_connect_acl+0x1b7/0x6b0
 hci_connect_sco+0x4d/0xb30
 sco_sock_connect+0x27b/0xd60
 __sys_connect_file+0xbd/0xe0
 __sys_connect+0xe0/0x110
 __x64_sys_connect+0x40/0x50
 x64_sys_call+0xcad/0x1c60
 do_syscall_64+0x133/0x590
 entry_SYSCALL_64_after_hwframe+0x77/0x7f

Fixes: 9a8ec9e8ebb5 ("Bluetooth: Fix three socket race condition bugs in sco.c")
Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
---
 net/bluetooth/sco.c | 11 ++++++++---
 1 file changed, 8 insertions(+), 3 deletions(-)

diff --git a/net/bluetooth/sco.c b/net/bluetooth/sco.c
index f1799c6a6f87..c9f6a8aaee57 100644
--- a/net/bluetooth/sco.c
+++ b/net/bluetooth/sco.c
@@ -312,11 +312,16 @@ static int sco_connect(struct sock *sk)
 	struct sco_conn *conn;
 	struct hci_conn *hcon;
 	struct hci_dev  *hdev;
+	bdaddr_t dst;
 	int err, type;
 
-	BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &sco_pi(sk)->dst);
+	lock_sock(sk);
+	bacpy(&dst, &sco_pi(sk)->dst);
+	release_sock(sk);
+
+	BT_DBG("%pMR -> %pMR", &sco_pi(sk)->src, &dst);
 
-	hdev = hci_get_route(&sco_pi(sk)->dst, &sco_pi(sk)->src, BDADDR_BREDR);
+	hdev = hci_get_route(&dst, &sco_pi(sk)->src, BDADDR_BREDR);
 	if (!hdev)
 		return -EHOSTUNREACH;
 
@@ -336,7 +341,7 @@ static int sco_connect(struct sock *sk)
 		break;
 	}
 
-	hcon = hci_connect_sco(hdev, type, &sco_pi(sk)->dst,
+	hcon = hci_connect_sco(hdev, type, &dst,
 			       sco_pi(sk)->setting, &sco_pi(sk)->codec,
 			       READ_ONCE(sk->sk_sndtimeo));
 	if (IS_ERR(hcon)) {
-- 
2.52.0


^ permalink raw reply related

* [PATCH 1/4] dt-bindings: bluetooth: qcom,qcc2072-bt: add bindings for QCC2072
From: Yepuri Siddu @ 2026-05-29 17:53 UTC (permalink / raw)
  To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Konrad Dybcio, Balakrishna Godavarthi, Rocky Liao
  Cc: quic_mohamull, quic_hbandi, rahul.samana, harshitha.reddy,
	dishank.garg, linux-arm-msm, linux-bluetooth, devicetree,
	linux-kernel, Yepuri Siddu

Document the YAML binding schema for the Qualcomm QCC2072 UART-based
Bluetooth controller.

Unlike other Qualcomm Bluetooth chips, QCC2072 requires no external
voltage regulators. The schema inherits common Qualcomm Bluetooth
properties via qcom,bluetooth-common.yaml and serial peripheral
interface properties for the UART link.

Signed-off-by: Yepuri Siddu <yepuri.siddu@oss.qualcomm.com>
---
 .../net/bluetooth/qcom,qcc2072-bt.yaml        | 38 +++++++++++++++++++
 1 file changed, 38 insertions(+)
 create mode 100644 Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml

diff --git a/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml
new file mode 100644
index 000000000000..8e2f15a75d62
--- /dev/null
+++ b/Documentation/devicetree/bindings/net/bluetooth/qcom,qcc2072-bt.yaml
@@ -0,0 +1,38 @@
+# SPDX-License-Identifier: (GPL-2.0 OR BSD-2-Clause)
+%YAML 1.2
+---
+$id: http://devicetree.org/schemas/net/bluetooth/qcom,qcc2072-bt.yaml#
+$schema: http://devicetree.org/meta-schemas/core.yaml#
+
+title: Qualcomm QCC2072 Bluetooth
+
+maintainers:
+  - Balakrishna Godavarthi <quic_bgodavar@quicinc.com>
+  - Rocky Liao <quic_rjliao@quicinc.com>
+
+description:
+  Qualcomm QCC2072 is a UART-based Bluetooth controller.
+
+properties:
+  compatible:
+    enum:
+      - qcom,qcc2072-bt
+
+required:
+  - compatible
+
+allOf:
+  - $ref: bluetooth-controller.yaml#
+  - $ref: qcom,bluetooth-common.yaml#
+  - $ref: /schemas/serial/serial-peripheral-props.yaml#
+
+unevaluatedProperties: false
+
+examples:
+  - |
+    serial {
+        bluetooth {
+            compatible = "qcom,qcc2072-bt";
+            max-speed = <3200000>;
+        };
+    };
-- 
2.34.1


^ permalink raw reply related

* [PATCH 2/4] Bluetooth: qca: add QCC2072 support
From: Yepuri Siddu @ 2026-05-29 17:58 UTC (permalink / raw)
  To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Konrad Dybcio, Balakrishna Godavarthi, Rocky Liao
  Cc: quic_mohamull, quic_hbandi, rahul.samana, harshitha.reddy,
	dishank.garg, linux-arm-msm, linux-bluetooth, linux-kernel,
	Yepuri Siddu

QCC2072 is a BT/WiFi combo SoC that uses different firmware
filenames and requires no external voltage regulators, so add
it as a new SoC type.

The chip supports the wideband speech and valid LE states
capabilities. Its firmware is named using the "orn" prefix and
follows the standard rom-version-based scheme:
    - qca/ornbtfw<ver>.tlv
    - qca/ornnv<ver>.bin

These firmware files are already present in the linux-firmware
repository.

Signed-off-by: Yepuri Siddu <yepuri.siddu@oss.qualcomm.com>
---
 drivers/bluetooth/btqca.c   |  9 +++++++++
 drivers/bluetooth/btqca.h   |  1 +
 drivers/bluetooth/hci_qca.c | 24 ++++++++++++++++++++++++
 3 files changed, 34 insertions(+)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index dda76365726f..0ef7546e7c7a 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -843,6 +843,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
 			snprintf(config.fwname, sizeof(config.fwname),
 				 "qca/hmtbtfw%02x.tlv", rom_ver);
 			break;
+		case QCA_QCC2072:
+			snprintf(config.fwname, sizeof(config.fwname),
+				 "qca/ornbtfw%02x.tlv", rom_ver);
+			break;
 		default:
 			snprintf(config.fwname, sizeof(config.fwname),
 				 "qca/rampatch_%08x.bin", soc_ver);
@@ -937,6 +941,10 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
 			qca_get_nvm_name_by_board(config.fwname, sizeof(config.fwname),
 				 "hmtnv", soc_type, ver, rom_ver, boardid);
 			break;
+		case QCA_QCC2072:
+			snprintf(config.fwname, sizeof(config.fwname),
+				 "qca/ornnv%02x.bin", rom_ver);
+			break;
 		default:
 			snprintf(config.fwname, sizeof(config.fwname),
 				 "qca/nvm_%08x.bin", soc_ver);
@@ -999,6 +1007,7 @@ int qca_uart_setup(struct hci_dev *hdev, uint8_t baudrate,
 	case QCA_WCN6750:
 	case QCA_WCN6855:
 	case QCA_WCN7850:
+	case QCA_QCC2072:
 		/* get fw build info */
 		err = qca_read_fw_build_info(hdev);
 		if (err < 0)
diff --git a/drivers/bluetooth/btqca.h b/drivers/bluetooth/btqca.h
index 8f3c1b1c77b3..a175ac31e7b2 100644
--- a/drivers/bluetooth/btqca.h
+++ b/drivers/bluetooth/btqca.h
@@ -158,6 +158,7 @@ enum qca_btsoc_type {
 	QCA_WCN6750,
 	QCA_WCN6855,
 	QCA_WCN7850,
+	QCA_QCC2072,
 };
 
 #if IS_ENABLED(CONFIG_BT_QCA)
diff --git a/drivers/bluetooth/hci_qca.c b/drivers/bluetooth/hci_qca.c
index ed280399bf47..fc67ba0e4984 100644
--- a/drivers/bluetooth/hci_qca.c
+++ b/drivers/bluetooth/hci_qca.c
@@ -1372,6 +1372,7 @@ static int qca_set_baudrate(struct hci_dev *hdev, uint8_t baudrate)
 
 	/* Give the controller time to process the request */
 	switch (qca_soc_type(hu)) {
+	case QCA_QCC2072:
 	case QCA_WCN3950:
 	case QCA_WCN3988:
 	case QCA_WCN3990:
@@ -1459,6 +1460,7 @@ static unsigned int qca_get_speed(struct hci_uart *hu,
 static int qca_check_speeds(struct hci_uart *hu)
 {
 	switch (qca_soc_type(hu)) {
+	case QCA_QCC2072:
 	case QCA_WCN3950:
 	case QCA_WCN3988:
 	case QCA_WCN3990:
@@ -1510,6 +1512,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
 		case QCA_WCN6750:
 		case QCA_WCN6855:
 		case QCA_WCN7850:
+		case QCA_QCC2072:
 			hci_uart_set_flow_control(hu, true);
 			break;
 
@@ -1545,6 +1548,7 @@ static int qca_set_speed(struct hci_uart *hu, enum qca_speed_type speed_type)
 		case QCA_WCN6750:
 		case QCA_WCN6855:
 		case QCA_WCN7850:
+		case QCA_QCC2072:
 			hci_uart_set_flow_control(hu, false);
 			break;
 
@@ -1861,6 +1865,7 @@ static int qca_power_on(struct hci_dev *hdev)
 	case QCA_WCN6750:
 	case QCA_WCN6855:
 	case QCA_WCN7850:
+	case QCA_QCC2072:
 		ret = qca_regulator_init(hu);
 		break;
 
@@ -1957,6 +1962,10 @@ static int qca_setup(struct hci_uart *hu)
 		soc_name = "wcn7850";
 		break;
 
+	case QCA_QCC2072:
+		soc_name = "qcc2072";
+		break;
+
 	default:
 		soc_name = "ROME/QCA6390";
 	}
@@ -1980,6 +1989,7 @@ static int qca_setup(struct hci_uart *hu)
 	case QCA_WCN6750:
 	case QCA_WCN6855:
 	case QCA_WCN7850:
+	case QCA_QCC2072:
 		if (qcadev->bdaddr_property_broken)
 			hci_set_quirk(hdev, HCI_QUIRK_BDADDR_PROPERTY_BROKEN);
 
@@ -2013,6 +2023,7 @@ static int qca_setup(struct hci_uart *hu)
 	case QCA_WCN6750:
 	case QCA_WCN6855:
 	case QCA_WCN7850:
+	case QCA_QCC2072:
 		break;
 
 	default:
@@ -2166,6 +2177,12 @@ static const struct qca_device_data qca_soc_data_wcn3998 __maybe_unused = {
 	.num_vregs = 4,
 };
 
+static const struct qca_device_data qca_soc_data_qcc2072 __maybe_unused = {
+	.soc_type = QCA_QCC2072,
+	.num_vregs = 0,
+	.capabilities = QCA_CAP_WIDEBAND_SPEECH | QCA_CAP_VALID_LE_STATES,
+};
+
 static const struct qca_device_data qca_soc_data_wcn6750 __maybe_unused = {
 	.soc_type = QCA_WCN6750,
 	.vregs = (struct qca_vreg []) {
@@ -2268,6 +2285,7 @@ static void qca_power_off(struct hci_uart *hu)
 
 	case QCA_WCN6750:
 	case QCA_WCN6855:
+	case QCA_QCC2072:
 		gpiod_set_value_cansleep(qcadev->bt_en, 0);
 		msleep(100);
 		qca_regulator_disable(qcadev);
@@ -2414,6 +2432,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
 		qcadev->btsoc_type = QCA_ROME;
 
 	switch (qcadev->btsoc_type) {
+	case QCA_QCC2072:
 	case QCA_QCA6390:
 	case QCA_WCN3950:
 	case QCA_WCN3988:
@@ -2434,6 +2453,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
 	}
 
 	switch (qcadev->btsoc_type) {
+	case QCA_QCC2072:
 	case QCA_WCN3950:
 	case QCA_WCN3988:
 	case QCA_WCN3990:
@@ -2484,6 +2504,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
 		if (!qcadev->bt_en &&
 		    (data->soc_type == QCA_WCN6750 ||
 		     data->soc_type == QCA_WCN6855 ||
+		     data->soc_type == QCA_QCC2072 ||
 		     data->soc_type == QCA_WCN7850))
 			power_ctrl_enabled = false;
 
@@ -2492,6 +2513,7 @@ static int qca_serdev_probe(struct serdev_device *serdev)
 		if (IS_ERR(qcadev->sw_ctrl) &&
 		    (data->soc_type == QCA_WCN6750 ||
 		     data->soc_type == QCA_WCN6855 ||
+		     data->soc_type == QCA_QCC2072 ||
 		     data->soc_type == QCA_WCN7850)) {
 			dev_err(&serdev->dev, "failed to acquire SW_CTRL gpio\n");
 			return PTR_ERR(qcadev->sw_ctrl);
@@ -2570,6 +2592,7 @@ static void qca_serdev_remove(struct serdev_device *serdev)
 	struct qca_power *power = qcadev->bt_power;
 
 	switch (qcadev->btsoc_type) {
+	case QCA_QCC2072:
 	case QCA_WCN3988:
 	case QCA_WCN3990:
 	case QCA_WCN3991:
@@ -2779,6 +2802,7 @@ static const struct of_device_id qca_bluetooth_of_match[] = {
 	{ .compatible = "qcom,wcn6750-bt", .data = &qca_soc_data_wcn6750},
 	{ .compatible = "qcom,wcn6855-bt", .data = &qca_soc_data_wcn6855},
 	{ .compatible = "qcom,wcn7850-bt", .data = &qca_soc_data_wcn7850},
+	{ .compatible = "qcom,qcc2072-bt", .data = &qca_soc_data_qcc2072},
 	{ /* sentinel */ }
 };
 MODULE_DEVICE_TABLE(of, qca_bluetooth_of_match);
-- 
2.34.1


^ permalink raw reply related

* [PATCH 4/4] Bluetooth: qca: combine NVM and calibration data for QCC2072
From: Yepuri Siddu @ 2026-05-29 18:04 UTC (permalink / raw)
  To: Bartosz Golaszewski, Marcel Holtmann, Luiz Augusto von Dentz,
	Rob Herring, Krzysztof Kozlowski, Conor Dooley, Bjorn Andersson,
	Konrad Dybcio, Balakrishna Godavarthi, Rocky Liao
  Cc: quic_mohamull, quic_hbandi, rahul.samana, harshitha.reddy,
	dishank.garg, linux-arm-msm, linux-bluetooth, linux-kernel,
	Yepuri Siddu

QCC2072 requires the NVM and calibration data to be delivered to the
controller bundled together in an outer TLV of type 4. After loading
the NVM file, load the calibration file (qca/ornbcscal<ver>.bin) and
combine both into a single buffer with the outer TLV header before
passing it to qca_tlv_check_data().

The outer TLV header encodes the combined payload length in the high
24 bits and type 4 in the low 8 bits of the type_len field.

If the calibration file is unavailable, fall back to downloading the
NVM alone.

Signed-off-by: Yepuri Siddu <yepuri.siddu@oss.qualcomm.com>
---
 drivers/bluetooth/btqca.c | 47 +++++++++++++++++++++++++++++++++++++++
 1 file changed, 47 insertions(+)

diff --git a/drivers/bluetooth/btqca.c b/drivers/bluetooth/btqca.c
index 0ef7546e7c7a..37db1cd9e8cf 100644
--- a/drivers/bluetooth/btqca.c
+++ b/drivers/bluetooth/btqca.c
@@ -612,6 +612,53 @@ static int qca_download_firmware(struct hci_dev *hdev,
 	memcpy(data, fw->data, size);
 	release_firmware(fw);
 
+	/* For QCC2072, combine the NVM (type 2) with the calibration file
+	 * into a single TLV of outer type 4.
+	 */
+	if (soc_type == QCA_QCC2072 && config->type == TLV_TYPE_NVM) {
+		const struct firmware *calib_fw = NULL;
+		char calib_name[32];
+		u8 *combined_data = NULL;
+		size_t inner_len, combined_size;
+		struct tlv_type_hdr *outer_hdr;
+		int err;
+
+		snprintf(calib_name, sizeof(calib_name),
+			 "qca/ornbcscal%02x.bin", rom_ver);
+		err = request_firmware(&calib_fw, calib_name, &hdev->dev);
+		if (err) {
+			bt_dev_err(hdev, "QCA Failed to request file: %s (%d)",
+				   calib_name, err);
+			goto skip_combination;
+		}
+
+		bt_dev_info(hdev, "QCA Downloading %s", calib_name);
+
+		inner_len = size + calib_fw->size;
+		combined_size = sizeof(*outer_hdr) + inner_len;
+		combined_data = vmalloc(combined_size);
+		if (!combined_data) {
+			bt_dev_warn(hdev,
+				   "QCA Failed to allocate memory for file: %s",
+				   calib_name);
+			release_firmware(calib_fw);
+			goto skip_combination;
+		}
+
+		outer_hdr = (struct tlv_type_hdr *)combined_data;
+		/* high 24 bits = payload length, low 8 bits = type */
+		outer_hdr->type_len = cpu_to_le32((inner_len << 8) | 4);
+		memcpy(combined_data + sizeof(*outer_hdr), data, size);
+		memcpy(combined_data + sizeof(*outer_hdr) + size,
+		       calib_fw->data, calib_fw->size);
+		release_firmware(calib_fw);
+		vfree(data);
+		data = combined_data;
+		size = combined_size;
+skip_combination:
+		;
+	}
+
 	ret = qca_tlv_check_data(hdev, config, data, size, soc_type);
 	if (ret)
 		goto out;
-- 
2.34.1


^ permalink raw reply related

* Re: [PATCH v1 1/1] Bluetooth: L2CAP: fix heap over-read in l2cap_get_conf_opt
From: Paul Menzel @ 2026-05-29 18:15 UTC (permalink / raw)
  To: Muhammad Bilal
  Cc: linux-bluetooth, marcel, luiz.dentz, gregkh, linux-kernel, stable
In-Reply-To: <20260527051808.47220-1-meatuni001@gmail.com>

Dear Muhammad,


Am 27.05.26 um 07:18 schrieb Muhammad Bilal:

>> By any chance, do you have a reproducer?
> 
> No standalone reproducer is available. The issue can be triggered by
> a malformed L2CAP configuration request where opt->len exceeds the
> remaining buffer, i.e. a crafted packet from a remote peer.

Understood.

>> I always wonder, if Linux should log a debug message or even warning.
> 
> Existing callers generally handle malformed configuration options by
> silently aborting parsing, so I followed the same pattern. Adding a
> BT_ERR() on -EINVAL could be reasonable; I can include that in a v2
> if preferred.

Thank you for sharing the reasoning. It makes sense, and no need to add 
it then.


Kind regards,

Paul

^ permalink raw reply

* Re: [GIT PULL] bluetooth 2026-05-28
From: Jakub Kicinski @ 2026-05-29 18:20 UTC (permalink / raw)
  To: Paolo Abeni; +Cc: Luiz Augusto von Dentz, davem, linux-bluetooth, netdev
In-Reply-To: <de887211-1005-43cf-b1d3-ddf1a82c283e@redhat.com>

On Fri, 29 May 2026 09:35:20 +0200 Paolo Abeni wrote:
> 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.

That's a pretty costly fix. It takes me ~3h to generate the PR I suspect
it takes you similar amount of time. So it's not going to help the
patch review queue if we waste time generating multiple PRs.

Luiz, simply run this bash script before you send the PR:

github.com/linux-netdev/nipa/blob/master/tests/patch/verify_signedoff/verify_signedoff.sh

it's not the first time you're missing SoBs

^ permalink raw reply

* RE: Bluetooth: L2CAP: Fix use-after-free in l2cap_sock_new_connection_cb()
From: bluez.test.bot @ 2026-05-29 18:21 UTC (permalink / raw)
  To: linux-bluetooth, oss
In-Reply-To: <20260529165449.3553936-2-oss@fourdim.xyz>

[-- Attachment #1: Type: text/plain, Size: 11948 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=1103029

---Test result---

Test Summary:
CheckPatch                    PASS      1.68 seconds
VerifyFixes                   PASS      0.14 seconds
VerifySignedoff               PASS      0.14 seconds
GitLint                       PASS      0.35 seconds
SubjectPrefix                 PASS      0.13 seconds
BuildKernel                   PASS      25.47 seconds
CheckAllWarning               PASS      27.77 seconds
CheckSparse                   PASS      26.54 seconds
BuildKernel32                 PASS      24.52 seconds
TestRunnerSetup               PASS      530.14 seconds
TestRunner_l2cap-tester       FAIL      55.83 seconds
TestRunner_smp-tester         FAIL      23.82 seconds
TestRunner_6lowpan-tester     FAIL      22.93 seconds
IncrementalBuild              PASS      25.60 seconds

Details
##############################
Test: TestRunner_l2cap-tester - FAIL
Desc: Run l2cap-tester with test-runner
Output:
WARNING: held lock freed!
7.1.0-rc1-g5f2fcd0833d0 #1 Not tainted
-------------------------
memcheck-amd64-/34 is freeing memory ffff888002762000-ffff8880027627ff, with a lock still held there!
ffff888002762508 (&chan->lock#4){+.+.}-{4:4}, at: l2cap_conn_del+0x33b/0x660
5 locks held by memcheck-amd64-/34:
 #0: ffff8880026e0e80 (&hdev->req_lock){+.+.}-{4:4}, at: hci_dev_do_close+0x5d/0x90
 #1: ffff8880026e00b0 (&hdev->lock){+.+.}-{4:4}, at: hci_dev_close_sync+0x2ca/0xfa0
 #2: ffffffffb92bc278 (hci_cb_list_lock){+.+.}-{4:4}, at: hci_conn_hash_flush+0xed/0x230
 #3: ffff8880022ec2f0 (&conn->lock){+.+.}-{4:4}, at: l2cap_conn_del+0x9b/0x660
 #4: ffff888002762508 (&chan->lock#4){+.+.}-{4:4}, at: l2cap_conn_del+0x33b/0x660

stack backtrace:
CPU: 0 UID: 0 PID: 34 Comm: memcheck-amd64- Not tainted 7.1.0-rc1-g5f2fcd0833d0 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 debug_check_no_locks_freed+0x102/0x140
 ? l2cap_chan_del+0x220/0x770
 kfree+0x22b/0x4c0
 ? _raw_write_unlock+0x1e/0x40
 l2cap_chan_del+0x220/0x770
 l2cap_conn_del+0x346/0x660
 hci_conn_hash_flush+0x135/0x230
 hci_dev_close_sync+0x4f8/0xfa0
 hci_dev_do_close+0x65/0x90
 hci_unregister_dev+0x254/0x510
 vhci_release+0x183/0x240
 __fput+0x356/0x9c0
 ? lock_is_held_type+0x9b/0x110
 fput_close_sync+0xd6/0x180
 ? __pfx_fput_close_sync+0x10/0x10
 __x64_sys_close+0x78/0xd0
 do_syscall_64+0x9f/0x560
 entry_SYSCALL_64_after_hwframe+0x74/0x7c
RIP: 0033:0x5805ccc9
Code: 00 e8 eb a4 fe ff 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <c3> 66 0f 1f 44 00 00 f3 0f 1e fa 8d 87 ff 0f 00 00 89 fa 89 ff 3d
RSP: 002b:0000001002db9d08 EFLAGS: 00000206 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 0000001002386d90 RCX: 000000005805ccc9
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000007
...
BUG: KASAN: slab-use-after-free in l2cap_chan_del+0x6ee/0x770
Write of size 8 at addr ffff888002762000 by task memcheck-amd64-/34

CPU: 0 UID: 0 PID: 34 Comm: memcheck-amd64- Not tainted 7.1.0-rc1-g5f2fcd0833d0 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 print_report+0x108/0x5c0
 ? __virt_addr_valid+0x21c/0x3f0
 ? l2cap_chan_del+0x6ee/0x770
 kasan_report+0x94/0xc0
 ? l2cap_chan_del+0x6ee/0x770
 l2cap_chan_del+0x6ee/0x770
 l2cap_conn_del+0x346/0x660
 hci_conn_hash_flush+0x135/0x230
 hci_dev_close_sync+0x4f8/0xfa0
 hci_dev_do_close+0x65/0x90
 hci_unregister_dev+0x254/0x510
 vhci_release+0x183/0x240
 __fput+0x356/0x9c0
 ? lock_is_held_type+0x9b/0x110
 fput_close_sync+0xd6/0x180
 ? __pfx_fput_close_sync+0x10/0x10
 __x64_sys_close+0x78/0xd0
 do_syscall_64+0x9f/0x560
 entry_SYSCALL_64_after_hwframe+0x74/0x7c
RIP: 0033:0x5805ccc9
Code: 00 e8 eb a4 fe ff 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <c3> 66 0f 1f 44 00 00 f3 0f 1e fa 8d 87 ff 0f 00 00 89 fa 89 ff 3d
RSP: 002b:0000001002db9d08 EFLAGS: 00000206 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 0000001002386d90 RCX: 000000005805ccc9
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000007
RBP: 0000000000000001 R08: 0000000005229e80 R09: 0000000000000040
R10: 00000000000002fa R11: 0000000000000206 R12: 0000001002386e20
R13: 0000001002008360 R14: 0000000000000003 R15: 0000001002db9d70
Total: 96, Passed: 96 (100.0%), Failed: 0, Not Run: 0
##############################
Test: TestRunner_smp-tester - FAIL
Desc: Run smp-tester with test-runner
Output:
WARNING: held lock freed!
7.1.0-rc1-g5f2fcd0833d0 #1 Not tainted
-------------------------
memcheck-amd64-/34 is freeing memory ffff8880021b6000-ffff8880021b67ff, with a lock still held there!
ffff8880021b6508 (&chan->lock#3){+.+.}-{4:4}, at: l2cap_conn_del+0x33b/0x660
5 locks held by memcheck-amd64-/34:
 #0: ffff8880024e4e80 (&hdev->req_lock){+.+.}-{4:4}, at: hci_dev_do_close+0x5d/0x90
 #1: ffff8880024e40b0 (&hdev->lock){+.+.}-{4:4}, at: hci_dev_close_sync+0x2ca/0xfa0
 #2: ffffffffb6ebc278 (hci_cb_list_lock){+.+.}-{4:4}, at: hci_conn_hash_flush+0xed/0x230
 #3: ffff8880022fb2f0 (&conn->lock){+.+.}-{4:4}, at: l2cap_conn_del+0x9b/0x660
 #4: ffff8880021b6508 (&chan->lock#3){+.+.}-{4:4}, at: l2cap_conn_del+0x33b/0x660

stack backtrace:
CPU: 0 UID: 0 PID: 34 Comm: memcheck-amd64- Not tainted 7.1.0-rc1-g5f2fcd0833d0 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 debug_check_no_locks_freed+0x102/0x140
 ? l2cap_chan_del+0x220/0x770
 kfree+0x22b/0x4c0
 ? _raw_write_unlock+0x1e/0x40
 l2cap_chan_del+0x220/0x770
 l2cap_conn_del+0x346/0x660
 hci_conn_hash_flush+0x135/0x230
 hci_dev_close_sync+0x4f8/0xfa0
 hci_dev_do_close+0x65/0x90
 hci_unregister_dev+0x254/0x510
 vhci_release+0x183/0x240
 __fput+0x356/0x9c0
 ? lock_is_held_type+0x9b/0x110
 fput_close_sync+0xd6/0x180
 ? __pfx_fput_close_sync+0x10/0x10
 __x64_sys_close+0x78/0xd0
 do_syscall_64+0x9f/0x560
 entry_SYSCALL_64_after_hwframe+0x74/0x7c
RIP: 0033:0x5805ccc9
Code: 00 e8 eb a4 fe ff 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <c3> 66 0f 1f 44 00 00 f3 0f 1e fa 8d 87 ff 0f 00 00 89 fa 89 ff 3d
RSP: 002b:0000001002db5d08 EFLAGS: 00000206 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 0000001002386d90 RCX: 000000005805ccc9
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 000000000000000a
...
BUG: KASAN: slab-use-after-free in l2cap_chan_del+0x6ee/0x770
Write of size 8 at addr ffff8880021b6000 by task memcheck-amd64-/34

CPU: 0 UID: 0 PID: 34 Comm: memcheck-amd64- Not tainted 7.1.0-rc1-g5f2fcd0833d0 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 print_report+0x108/0x5c0
 ? __virt_addr_valid+0x21c/0x3f0
 ? l2cap_chan_del+0x6ee/0x770
 kasan_report+0x94/0xc0
 ? l2cap_chan_del+0x6ee/0x770
 l2cap_chan_del+0x6ee/0x770
 l2cap_conn_del+0x346/0x660
 hci_conn_hash_flush+0x135/0x230
 hci_dev_close_sync+0x4f8/0xfa0
 hci_dev_do_close+0x65/0x90
 hci_unregister_dev+0x254/0x510
 vhci_release+0x183/0x240
 __fput+0x356/0x9c0
 ? lock_is_held_type+0x9b/0x110
 fput_close_sync+0xd6/0x180
 ? __pfx_fput_close_sync+0x10/0x10
 __x64_sys_close+0x78/0xd0
 do_syscall_64+0x9f/0x560
 entry_SYSCALL_64_after_hwframe+0x74/0x7c
RIP: 0033:0x5805ccc9
Code: 00 e8 eb a4 fe ff 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <c3> 66 0f 1f 44 00 00 f3 0f 1e fa 8d 87 ff 0f 00 00 89 fa 89 ff 3d
RSP: 002b:0000001002db5d08 EFLAGS: 00000206 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 0000001002386d90 RCX: 000000005805ccc9
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 000000000000000a
RBP: 0000000000000001 R08: 0000000004c198e0 R09: 0000000000000040
R10: 0000000000000002 R11: 0000000000000206 R12: 0000001002386e20
R13: 0000001002008360 R14: 0000000000000003 R15: 0000001002db5d70
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0
##############################
Test: TestRunner_6lowpan-tester - FAIL
Desc: Run 6lowpan-tester with test-runner
Output:
WARNING: held lock freed!
7.1.0-rc1-g5f2fcd0833d0 #1 Not tainted
-------------------------
memcheck-amd64-/34 is freeing memory ffff8880026af000-ffff8880026af7ff, with a lock still held there!
ffff8880026af508 (&chan->lock#4){+.+.}-{4:4}, at: l2cap_conn_del+0x33b/0x660
5 locks held by memcheck-amd64-/34:
 #0: ffff8880025ece80 (&hdev->req_lock){+.+.}-{4:4}, at: hci_dev_do_close+0x5d/0x90
 #1: ffff8880025ec0b0 (&hdev->lock){+.+.}-{4:4}, at: hci_dev_close_sync+0x2ca/0xfa0
 #2: ffffffff84ebc278 (hci_cb_list_lock){+.+.}-{4:4}, at: hci_conn_hash_flush+0xed/0x230
 #3: ffff888001fcbaf0 (&conn->lock){+.+.}-{4:4}, at: l2cap_conn_del+0x9b/0x660
 #4: ffff8880026af508 (&chan->lock#4){+.+.}-{4:4}, at: l2cap_conn_del+0x33b/0x660

stack backtrace:
CPU: 0 UID: 0 PID: 34 Comm: memcheck-amd64- Not tainted 7.1.0-rc1-g5f2fcd0833d0 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 debug_check_no_locks_freed+0x102/0x140
 ? l2cap_chan_del+0x220/0x770
 kfree+0x22b/0x4c0
 ? _raw_write_unlock+0x1e/0x40
 l2cap_chan_del+0x220/0x770
 l2cap_conn_del+0x346/0x660
 hci_conn_hash_flush+0x135/0x230
 hci_dev_close_sync+0x4f8/0xfa0
 hci_dev_do_close+0x65/0x90
 hci_unregister_dev+0x254/0x510
 vhci_release+0x183/0x240
 __fput+0x356/0x9c0
 ? lock_is_held_type+0x9b/0x110
 fput_close_sync+0xd6/0x180
 ? __pfx_fput_close_sync+0x10/0x10
 __x64_sys_close+0x78/0xd0
 do_syscall_64+0x9f/0x560
 entry_SYSCALL_64_after_hwframe+0x74/0x7c
RIP: 0033:0x5805ccc9
Code: 00 e8 eb a4 fe ff 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <c3> 66 0f 1f 44 00 00 f3 0f 1e fa 8d 87 ff 0f 00 00 89 fa 89 ff 3d
RSP: 002b:0000001002cb5d08 EFLAGS: 00000206 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 0000001002386d90 RCX: 000000005805ccc9
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000007
...
BUG: KASAN: slab-use-after-free in l2cap_chan_del+0x6ee/0x770
Write of size 8 at addr ffff8880026af000 by task memcheck-amd64-/34

CPU: 0 UID: 0 PID: 34 Comm: memcheck-amd64- Not tainted 7.1.0-rc1-g5f2fcd0833d0 #1 PREEMPT(lazy) 
Hardware name: QEMU Standard PC (Q35 + ICH9, 2009), BIOS 1.13.0-1ubuntu1.1 04/01/2014
Call Trace:
 <TASK>
 print_report+0x108/0x5c0
 ? __virt_addr_valid+0x21c/0x3f0
 ? l2cap_chan_del+0x6ee/0x770
 kasan_report+0x94/0xc0
 ? l2cap_chan_del+0x6ee/0x770
 l2cap_chan_del+0x6ee/0x770
 l2cap_conn_del+0x346/0x660
 hci_conn_hash_flush+0x135/0x230
 hci_dev_close_sync+0x4f8/0xfa0
 hci_dev_do_close+0x65/0x90
 hci_unregister_dev+0x254/0x510
 vhci_release+0x183/0x240
 __fput+0x356/0x9c0
 ? lock_is_held_type+0x9b/0x110
 fput_close_sync+0xd6/0x180
 ? __pfx_fput_close_sync+0x10/0x10
 __x64_sys_close+0x78/0xd0
 do_syscall_64+0x9f/0x560
 entry_SYSCALL_64_after_hwframe+0x74/0x7c
RIP: 0033:0x5805ccc9
Code: 00 e8 eb a4 fe ff 66 2e 0f 1f 84 00 00 00 00 00 90 48 89 f8 48 89 f7 48 89 d6 48 89 ca 4d 89 c2 4d 89 c8 4c 8b 4c 24 08 0f 05 <c3> 66 0f 1f 44 00 00 f3 0f 1e fa 8d 87 ff 0f 00 00 89 fa 89 ff 3d
RSP: 002b:0000001002cb5d08 EFLAGS: 00000206 ORIG_RAX: 0000000000000003
RAX: ffffffffffffffda RBX: 0000001002386d90 RCX: 000000005805ccc9
RDX: 0000000000000000 RSI: 0000000000000000 RDI: 0000000000000007
RBP: 0000000000000001 R08: 0000000004c205f0 R09: 0000000000000040
R10: 0000000000000002 R11: 0000000000000206 R12: 0000001002386e20
R13: 0000001002008360 R14: 0000000000000003 R15: 0000001002cb5d70
Total: 8, Passed: 8 (100.0%), Failed: 0, Not Run: 0


https://github.com/bluez/bluetooth-next/pull/256

---
Regards,
Linux Bluetooth


^ permalink raw reply


This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox