Skip to content

[PW_SID:1127425] Bluetooth: L2CAP: take chan_l lock in ecred defer recvmsg path to fix list corruption#438

Open
BluezTestBot wants to merge 1 commit into
workflowfrom
1127425
Open

[PW_SID:1127425] Bluetooth: L2CAP: take chan_l lock in ecred defer recvmsg path to fix list corruption#438
BluezTestBot wants to merge 1 commit into
workflowfrom
1127425

Conversation

@BluezTestBot

Copy link
Copy Markdown

When a deferred L2CAP_MODE_EXT_FLOWCTL connection is accepted,
l2cap_sock_recvmsg() (BT_CONNECT2 + BT_SK_DEFER_SETUP branch) calls
__l2cap_ecred_conn_rsp_defer() while holding only lock_sock(sk). That
function walks conn->chan_l via __l2cap_chan_list_id() and, on the
authorization/refuse path, removes channels with l2cap_chan_del() ->
list_del(&chan->list) -- all without conn->lock.

conn->chan_l is serialised by conn->lock and is concurrently mutated by
the RX worker, which processes inbound signalling (e.g. an
L2CAP_DISCONN_REQ -> l2cap_chan_del()) under conn->lock. A lockless
traversal/removal racing the RX worker's list_del() corrupts the list:

list_del corruption, ...->next is LIST_POISON1 (dead000000000100)
WARNING lib/list_debug.c:56 __list_del_entry_valid_or_report
l2cap_chan_del+0xdb/0x1140
__l2cap_ecred_conn_rsp_defer+0x61d/0x700
l2cap_sock_recvmsg+0x758/0x8b0
Oops: general protection fault
KASAN: maybe wild-memory-access in range [dead000000000100-...]
__l2cap_ecred_conn_rsp_defer+0x3c6/0x700
l2cap_sock_recvmsg+0x758/0x8b0

This is the recvmsg-path sibling of commit 41c2713 ("Bluetooth:
L2CAP: Fix possible crash on l2cap_ecred_conn_rsp"), which addressed the
same conn->chan_l manipulation on the signalling (l2cap_ecred_conn_rsp)
side; the deferred-accept path was left unguarded.

Take conn->lock around __l2cap_ecred_conn_rsp_defer(). The established
lock order is conn->lock -> chan->lock -> sk_lock (the RX worker reaches
the socket via l2cap_chan_del() -> l2cap_sock_teardown_cb() ->
lock_sock_nested()), so the socket lock is dropped before conn->lock is
taken, mirroring l2cap_sock_shutdown() and l2cap_sock_cleanup_listen().
The conn is pinned with l2cap_conn_hold_unless_zero() across the
unlocked window. Only the EXT_FLOWCTL branch needs this; the LE and
BR/EDR defer paths respond for a single channel and do not walk
conn->chan_l.

Found by 0sec (https://0sec.ai).
Fixes: 15f02b9 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
Cc: stable@vger.kernel.org
Assisted-by: 0sec
Signed-off-by: Doruk Tan Ozturk doruk@0sec.ai

net/bluetooth/l2cap_sock.c | 34 ++++++++++++++++++++++++++++++++--
1 file changed, 32 insertions(+), 2 deletions(-)

… list corruption

When a deferred L2CAP_MODE_EXT_FLOWCTL connection is accepted,
l2cap_sock_recvmsg() (BT_CONNECT2 + BT_SK_DEFER_SETUP branch) calls
__l2cap_ecred_conn_rsp_defer() while holding only lock_sock(sk).  That
function walks conn->chan_l via __l2cap_chan_list_id() and, on the
authorization/refuse path, removes channels with l2cap_chan_del() ->
list_del(&chan->list) -- all without conn->lock.

conn->chan_l is serialised by conn->lock and is concurrently mutated by
the RX worker, which processes inbound signalling (e.g. an
L2CAP_DISCONN_REQ -> l2cap_chan_del()) under conn->lock.  A lockless
traversal/removal racing the RX worker's list_del() corrupts the list:

  list_del corruption, ...->next is LIST_POISON1 (dead000000000100)
  WARNING lib/list_debug.c:56 __list_del_entry_valid_or_report
   l2cap_chan_del+0xdb/0x1140
   __l2cap_ecred_conn_rsp_defer+0x61d/0x700
   l2cap_sock_recvmsg+0x758/0x8b0
  Oops: general protection fault
  KASAN: maybe wild-memory-access in range [dead000000000100-...]
   __l2cap_ecred_conn_rsp_defer+0x3c6/0x700
   l2cap_sock_recvmsg+0x758/0x8b0

This is the recvmsg-path sibling of commit 41c2713 ("Bluetooth:
L2CAP: Fix possible crash on l2cap_ecred_conn_rsp"), which addressed the
same conn->chan_l manipulation on the signalling (l2cap_ecred_conn_rsp)
side; the deferred-accept path was left unguarded.

Take conn->lock around __l2cap_ecred_conn_rsp_defer().  The established
lock order is conn->lock -> chan->lock -> sk_lock (the RX worker reaches
the socket via l2cap_chan_del() -> l2cap_sock_teardown_cb() ->
lock_sock_nested()), so the socket lock is dropped before conn->lock is
taken, mirroring l2cap_sock_shutdown() and l2cap_sock_cleanup_listen().
The conn is pinned with l2cap_conn_hold_unless_zero() across the
unlocked window.  Only the EXT_FLOWCTL branch needs this; the LE and
BR/EDR defer paths respond for a single channel and do not walk
conn->chan_l.

Found by 0sec (https://0sec.ai).
Fixes: 15f02b9 ("Bluetooth: L2CAP: Add initial code for Enhanced Credit Based Mode")
Cc: stable@vger.kernel.org
Assisted-by: 0sec
Signed-off-by: Doruk Tan Ozturk <doruk@0sec.ai>
@github-actions

Copy link
Copy Markdown

CheckPatch
Desc: Run checkpatch.pl script
Duration: 0.59 seconds
Result: FAIL
Output:

Bluetooth: L2CAP: take chan_l lock in ecred defer recvmsg path to fix list corruption
WARNING: Assisted-by expects 'AGENT_NAME:MODEL_VERSION [TOOL1] [TOOL2]' format
#139: 
Assisted-by: 0sec

total: 0 errors, 1 warnings, 0 checks, 41 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/14686349.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.


@github-actions

Copy link
Copy Markdown

VerifyFixes
Desc: Verify Fixes tag format and validity
Duration: 0.08 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

VerifySignedoff
Desc: Verify Signed-off-by chain
Duration: 0.07 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

GitLint
Desc: Run gitlint
Duration: 0.21 seconds
Result: FAIL
Output:

Bluetooth: L2CAP: take chan_l lock in ecred defer recvmsg path to fix list corruption

1: T1 Title exceeds max length (85>80): "Bluetooth: L2CAP: take chan_l lock in ecred defer recvmsg path to fix list corruption"

@github-actions

Copy link
Copy Markdown

SubjectPrefix
Desc: Check subject contains "Bluetooth" prefix
Duration: 0.07 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

BuildKernel
Desc: Build Kernel for Bluetooth
Duration: 26.65 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

CheckAllWarning
Desc: Run linux kernel with all warning enabled
Duration: 29.65 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

CheckSparse
Desc: Run sparse tool with linux kernel
Duration: 27.95 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

BuildKernel32
Desc: Build 32bit Kernel for Bluetooth
Duration: 26.37 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

CheckKernelLLVM
Desc: Build kernel with LLVM + context analysis
Duration: 0.00 seconds
Result: SKIP
Output:

Clang not found

@github-actions

Copy link
Copy Markdown

TestRunnerSetup
Desc: Setup kernel and bluez for test-runner
Duration: 505.78 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

TestRunner_l2cap-tester
Desc: Run l2cap-tester with test-runner
Duration: 63.67 seconds
Result: PASS

@github-actions

Copy link
Copy Markdown

IncrementalBuild
Desc: Incremental build with the patches in the series
Duration: 26.67 seconds
Result: PASS

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants