* [PATCH v3] Bluetooth: RFCOMM: validate skb length in MCC handlers
@ 2026-05-25 11:04 SeungJu Cheon
2026-05-25 14:21 ` [v3] " bluez.test.bot
2026-05-28 14:20 ` [PATCH v3] " patchwork-bot+bluetooth
0 siblings, 2 replies; 3+ messages in thread
From: SeungJu Cheon @ 2026-05-25 11:04 UTC (permalink / raw)
To: linux-bluetooth
Cc: marcel, luiz.dentz, pmenzel, me, linux-kernel,
linux-kernel-mentees, skhan, SeungJu Cheon, Muhammad Bilal
The RFCOMM MCC handlers cast skb->data to protocol-specific structs
without validating skb->len first. A malicious remote device can send
truncated MCC frames and trigger out-of-bounds reads in these handlers.
Fix this by using skb_pull_data() to validate and access the required
data before dereferencing it.
rfcomm_recv_rpn() requires special handling since ETSI TS 07.10 allows
1-byte RPN requests. Handle this by validating only the DLCI byte first,
and validating the full struct only when len > 1.
Fixes: 1da177e4c3f4 ("Linux-2.6.12-rc2")
Suggested-by: Muhammad Bilal <meatuni001@gmail.com>
Signed-off-by: SeungJu Cheon <suunj1331@gmail.com>
---
v3:
- Apply skb_pull_data() in rfcomm_recv_mcc() before accessing the
MCC header
- Return -EILSEQ instead of -EINVAL for malformed frames
v2:
- Use skb_pull_data() instead of manual length checks (Luiz)
- Add MCC header length validation in rfcomm_recv_mcc() (Paul)
- Allow 1-byte RPN requests per ETSI TS 07.10 (Paul)
Testing:
Tested under QEMU with VHCI and KASAN enabled by injecting both
well-formed and malformed RFCOMM MCC frames.
Well-formed PN/MSC/RLS frames and both valid RPN variants (full
8-byte form and 1-byte query form) are parsed identically to the
pre-patch behavior.
The following malformed frames are rejected before reaching the
MCC sub-handlers:
- truncated MCC headers
- PN/MSC/RLS/RPN payloads shorter than the fixed struct size
- invalid intermediate RPN lengths (len != 1 && len < 8)
- MCC payload lengths larger than the actual skb data
Frames with cr=0 are still silently dropped, and oversized frames
continue to ignore trailing bytes as before.
net/bluetooth/rfcomm/core.c | 67 +++++++++++++++++++++++++++----------
1 file changed, 49 insertions(+), 18 deletions(-)
diff --git a/net/bluetooth/rfcomm/core.c b/net/bluetooth/rfcomm/core.c
index d11bd5337d57..364b9381c2dc 100644
--- a/net/bluetooth/rfcomm/core.c
+++ b/net/bluetooth/rfcomm/core.c
@@ -1431,10 +1431,15 @@ static int rfcomm_apply_pn(struct rfcomm_dlc *d, int cr, struct rfcomm_pn *pn)
static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
{
- struct rfcomm_pn *pn = (void *) skb->data;
+ struct rfcomm_pn *pn;
struct rfcomm_dlc *d;
- u8 dlci = pn->dlci;
+ u8 dlci;
+
+ pn = skb_pull_data(skb, sizeof(*pn));
+ if (!pn)
+ return -EILSEQ;
+ dlci = pn->dlci;
BT_DBG("session %p state %ld dlci %d", s, s->state, dlci);
if (!dlci)
@@ -1483,8 +1488,8 @@ static int rfcomm_recv_pn(struct rfcomm_session *s, int cr, struct sk_buff *skb)
static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_buff *skb)
{
- struct rfcomm_rpn *rpn = (void *) skb->data;
- u8 dlci = __get_dlci(rpn->dlci);
+ struct rfcomm_rpn *rpn;
+ u8 dlci;
u8 bit_rate = 0;
u8 data_bits = 0;
@@ -1495,15 +1500,16 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
u8 xoff_char = 0;
u16 rpn_mask = RFCOMM_RPN_PM_ALL;
- BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
- dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
- rpn->xon_char, rpn->xoff_char, rpn->param_mask);
+ if (len == 1) {
+ rpn = skb_pull_data(skb, 1);
+ if (!rpn)
+ return -EILSEQ;
- if (!cr)
- return 0;
+ dlci = __get_dlci(rpn->dlci);
+
+ if (!cr)
+ return 0;
- if (len == 1) {
- /* This is a request, return default (according to ETSI TS 07.10) settings */
bit_rate = RFCOMM_RPN_BR_9600;
data_bits = RFCOMM_RPN_DATA_8;
stop_bits = RFCOMM_RPN_STOP_1;
@@ -1514,6 +1520,19 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
goto rpn_out;
}
+ rpn = skb_pull_data(skb, sizeof(*rpn));
+ if (!rpn)
+ return -EILSEQ;
+
+ dlci = __get_dlci(rpn->dlci);
+
+ BT_DBG("dlci %d cr %d len 0x%x bitr 0x%x line 0x%x flow 0x%x xonc 0x%x xoffc 0x%x pm 0x%x",
+ dlci, cr, len, rpn->bit_rate, rpn->line_settings, rpn->flow_ctrl,
+ rpn->xon_char, rpn->xoff_char, rpn->param_mask);
+
+ if (!cr)
+ return 0;
+
/* Check for sane values, ignore/accept bit_rate, 8 bits, 1 stop bit,
* no parity, no flow control lines, normal XON/XOFF chars */
@@ -1589,9 +1608,14 @@ static int rfcomm_recv_rpn(struct rfcomm_session *s, int cr, int len, struct sk_
static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb)
{
- struct rfcomm_rls *rls = (void *) skb->data;
- u8 dlci = __get_dlci(rls->dlci);
+ struct rfcomm_rls *rls;
+ u8 dlci;
+ rls = skb_pull_data(skb, sizeof(*rls));
+ if (!rls)
+ return -EILSEQ;
+
+ dlci = __get_dlci(rls->dlci);
BT_DBG("dlci %d cr %d status 0x%x", dlci, cr, rls->status);
if (!cr)
@@ -1608,10 +1632,15 @@ static int rfcomm_recv_rls(struct rfcomm_session *s, int cr, struct sk_buff *skb
static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb)
{
- struct rfcomm_msc *msc = (void *) skb->data;
+ struct rfcomm_msc *msc;
struct rfcomm_dlc *d;
- u8 dlci = __get_dlci(msc->dlci);
+ u8 dlci;
+
+ msc = skb_pull_data(skb, sizeof(*msc));
+ if (!msc)
+ return -EILSEQ;
+ dlci = __get_dlci(msc->dlci);
BT_DBG("dlci %d cr %d v24 0x%x", dlci, cr, msc->v24_sig);
d = rfcomm_dlc_get(s, dlci);
@@ -1644,17 +1673,19 @@ static int rfcomm_recv_msc(struct rfcomm_session *s, int cr, struct sk_buff *skb
static int rfcomm_recv_mcc(struct rfcomm_session *s, struct sk_buff *skb)
{
- struct rfcomm_mcc *mcc = (void *) skb->data;
+ struct rfcomm_mcc *mcc;
u8 type, cr, len;
+ mcc = skb_pull_data(skb, sizeof(*mcc));
+ if (!mcc)
+ return -EILSEQ;
+
cr = __test_cr(mcc->type);
type = __get_mcc_type(mcc->type);
len = __get_mcc_len(mcc->len);
BT_DBG("%p type 0x%x cr %d", s, type, cr);
- skb_pull(skb, 2);
-
switch (type) {
case RFCOMM_PN:
rfcomm_recv_pn(s, cr, skb);
--
2.52.0
^ permalink raw reply related [flat|nested] 3+ messages in thread
* RE: [v3] Bluetooth: RFCOMM: validate skb length in MCC handlers
2026-05-25 11:04 [PATCH v3] Bluetooth: RFCOMM: validate skb length in MCC handlers SeungJu Cheon
@ 2026-05-25 14:21 ` bluez.test.bot
2026-05-28 14:20 ` [PATCH v3] " patchwork-bot+bluetooth
1 sibling, 0 replies; 3+ messages in thread
From: bluez.test.bot @ 2026-05-25 14:21 UTC (permalink / raw)
To: linux-bluetooth, suunj1331
[-- 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=1100421
---Test result---
Test Summary:
CheckPatch PASS 0.59 seconds
VerifyFixes PASS 0.07 seconds
VerifySignedoff PASS 0.07 seconds
GitLint PASS 1.31 seconds
SubjectPrefix PASS 0.09 seconds
BuildKernel PASS 26.59 seconds
CheckAllWarning PASS 29.34 seconds
CheckSparse PASS 28.00 seconds
BuildKernel32 PASS 25.80 seconds
TestRunnerSetup PASS 573.06 seconds
TestRunner_rfcomm-tester PASS 25.38 seconds
IncrementalBuild PASS 25.10 seconds
https://github.com/bluez/bluetooth-next/pull/236
---
Regards,
Linux Bluetooth
^ permalink raw reply [flat|nested] 3+ messages in thread
* Re: [PATCH v3] Bluetooth: RFCOMM: validate skb length in MCC handlers
2026-05-25 11:04 [PATCH v3] Bluetooth: RFCOMM: validate skb length in MCC handlers SeungJu Cheon
2026-05-25 14:21 ` [v3] " 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: SeungJu Cheon
Cc: linux-bluetooth, marcel, luiz.dentz, pmenzel, me, linux-kernel,
linux-kernel-mentees, skhan, meatuni001
Hello:
This patch was applied to bluetooth/bluetooth-next.git (master)
by Luiz Augusto von Dentz <luiz.von.dentz@intel.com>:
On Mon, 25 May 2026 20:04:43 +0900 you wrote:
> The RFCOMM MCC handlers cast skb->data to protocol-specific structs
> without validating skb->len first. A malicious remote device can send
> truncated MCC frames and trigger out-of-bounds reads in these handlers.
>
> Fix this by using skb_pull_data() to validate and access the required
> data before dereferencing it.
>
> [...]
Here is the summary with links:
- [v3] Bluetooth: RFCOMM: validate skb length in MCC handlers
https://git.kernel.org/bluetooth/bluetooth-next/c/a82ccb946ae5
You are awesome, thank you!
--
Deet-doot-dot, I am a bot.
https://korg.docs.kernel.org/patchwork/pwbot.html
^ permalink raw reply [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-25 11:04 [PATCH v3] Bluetooth: RFCOMM: validate skb length in MCC handlers SeungJu Cheon
2026-05-25 14:21 ` [v3] " bluez.test.bot
2026-05-28 14:20 ` [PATCH v3] " 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