* [PATCH v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
@ 2026-05-28 7:56 Zhang Cen
2026-05-28 10:27 ` [v2] " bluez.test.bot
2026-05-28 14:20 ` [PATCH v2] " patchwork-bot+bluetooth
0 siblings, 2 replies; 3+ messages in thread
From: Zhang Cen @ 2026-05-28 7:56 UTC (permalink / raw)
To: Marcel Holtmann, Luiz Augusto von Dentz
Cc: linux-bluetooth, linux-kernel, zerocling0077, 2045gemini
rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
but returns the selected listener after dropping that lock without
taking a reference. rfcomm_connect_ind() then locks the listener,
queues a child socket on it, and may notify it after unlocking it.
The buggy scenario involves two paths, with each column showing the
order within that path:
rfcomm_connect_ind(): listener close:
1. Find parent in 1. close() enters
rfcomm_get_sock_by_channel() rfcomm_sock_release().
2. Drop rfcomm_sk_list.lock 2. rfcomm_sock_shutdown()
without pinning parent. closes the listener.
3. Call lock_sock(parent) and 3. rfcomm_sock_kill()
bt_accept_enqueue(parent, unlinks and puts parent.
sk, true).
4. Read parent flags and may 4. parent can be freed.
call sk_state_change().
If close wins the race, parent can be freed before
rfcomm_connect_ind() reaches lock_sock(), bt_accept_enqueue(), or the
deferred-setup callback.
Take a reference on the listener before leaving rfcomm_sk_list.lock.
After lock_sock() succeeds, recheck that it is still in BT_LISTEN
before queueing a child, cache the deferred-setup bit while the parent
is locked, and drop the reference after the last parent use.
KASAN reported a slab-use-after-free in lock_sock_nested() from
rfcomm_connect_ind(), with the freeing stack going through
rfcomm_sock_kill() and rfcomm_sock_release().
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Signed-off-by: Zhang Cen <rollkingzzc@gmail.com>
---
v2:
- Wrap the interleaving description to satisfy GitLint.
- Add a Fixes tag.
net/bluetooth/rfcomm/sock.c | 26 ++++++++++++++++++++++----
1 file changed, 22 insertions(+), 4 deletions(-)
diff --git a/net/bluetooth/rfcomm/sock.c b/net/bluetooth/rfcomm/sock.c
index 38d2355114cff..ed31d5f4fc76f 100644
--- a/net/bluetooth/rfcomm/sock.c
+++ b/net/bluetooth/rfcomm/sock.c
@@ -123,7 +123,7 @@ static struct sock *__rfcomm_get_listen_sock_by_addr(u8 channel, bdaddr_t *src)
}
/* Find socket with channel and source bdaddr.
- * Returns closest match.
+ * Returns closest match with an extra reference held.
*/
static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *src)
{
@@ -137,15 +137,25 @@ static struct sock *rfcomm_get_sock_by_channel(int state, u8 channel, bdaddr_t *
if (rfcomm_pi(sk)->channel == channel) {
/* Exact match. */
- if (!bacmp(&rfcomm_pi(sk)->src, src))
+ if (!bacmp(&rfcomm_pi(sk)->src, src)) {
+ sock_hold(sk);
break;
+ }
/* Closest match */
- if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY))
+ if (!bacmp(&rfcomm_pi(sk)->src, BDADDR_ANY)) {
+ if (sk1)
+ sock_put(sk1);
+
sk1 = sk;
+ sock_hold(sk1);
+ }
}
}
+ if (sk && sk1)
+ sock_put(sk1);
+
read_unlock(&rfcomm_sk_list.lock);
return sk ? sk : sk1;
@@ -945,6 +955,7 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
{
struct sock *sk, *parent;
bdaddr_t src, dst;
+ bool defer_setup = false;
int result = 0;
BT_DBG("session %p channel %d", s, channel);
@@ -958,6 +969,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
lock_sock(parent);
+ if (parent->sk_state != BT_LISTEN)
+ goto done;
+
+ defer_setup = test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags);
+
/* Check for backlog size */
if (sk_acceptq_is_full(parent)) {
BT_DBG("backlog full %d", parent->sk_ack_backlog);
@@ -985,9 +1001,11 @@ int rfcomm_connect_ind(struct rfcomm_session *s, u8 channel, struct rfcomm_dlc *
done:
release_sock(parent);
- if (test_bit(BT_SK_DEFER_SETUP, &bt_sk(parent)->flags))
+ if (defer_setup)
parent->sk_state_change(parent);
+ sock_put(parent);
+
return result;
}
--
2.43.0
^ permalink raw reply related [flat|nested] 3+ messages in thread* RE: [v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
2026-05-28 7:56 [PATCH v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind() Zhang Cen
@ 2026-05-28 10:27 ` bluez.test.bot
2026-05-28 14:20 ` [PATCH v2] " patchwork-bot+bluetooth
1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-05-28 10:27 UTC (permalink / raw)
To: linux-bluetooth, rollkingzzc
[-- Attachment #1: Type: text/plain, Size: 1042 bytes --]
This is automated email and please do not reply to this email!
Dear submitter,
Thank you for submitting the patches to the linux bluetooth mailing list.
This is a CI test results with your patch series:
PW Link:https://patchwork.kernel.org/project/bluetooth/list/?series=1102052
---Test result---
Test Summary:
CheckPatch PASS 0.60 seconds
VerifyFixes PASS 0.09 seconds
VerifySignedoff PASS 0.09 seconds
GitLint PASS 0.23 seconds
SubjectPrefix PASS 0.08 seconds
BuildKernel PASS 26.39 seconds
CheckAllWarning PASS 29.02 seconds
CheckSparse PASS 27.78 seconds
BuildKernel32 PASS 25.61 seconds
TestRunnerSetup PASS 568.59 seconds
TestRunner_rfcomm-tester PASS 25.28 seconds
IncrementalBuild PASS 24.56 seconds
https://github.com/bluez/bluetooth-next/pull/251
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
2026-05-28 7:56 [PATCH v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind() Zhang Cen
2026-05-28 10:27 ` [v2] " bluez.test.bot
@ 2026-05-28 14:20 ` patchwork-bot+bluetooth
1 sibling, 0 replies; 3+ messages in thread
From: patchwork-bot+bluetooth @ 2026-05-28 14:20 UTC (permalink / raw)
To: Cen Zhang
Cc: marcel, luiz.dentz, linux-bluetooth, linux-kernel, zerocling0077,
2045gemini
Hello:
This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Thu, 28 May 2026 15:56:41 +0800 you wrote:
> rfcomm_get_sock_by_channel() scans rfcomm_sk_list under the list lock,
> but returns the selected listener after dropping that lock without
> taking a reference. rfcomm_connect_ind() then locks the listener,
> queues a child socket on it, and may notify it after unlocking it.
>
> The buggy scenario involves two paths, with each column showing the
> order within that path:
>
> [...]
Here is the summary with links:
- [v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind()
https://git.kernel.org/bluetooth/bluetooth-next/c/339cf04eb21a
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [flat|nested] 3+ messages in thread
end of thread, other threads:[~2026-05-28 14:20 UTC | newest]
Thread overview: 3+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-05-28 7:56 [PATCH v2] Bluetooth: RFCOMM: hold listener socket in rfcomm_connect_ind() Zhang Cen
2026-05-28 10:27 ` [v2] " bluez.test.bot
2026-05-28 14:20 ` [PATCH v2] " patchwork-bot+bluetooth
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox