-
Notifications
You must be signed in to change notification settings - Fork 8.1k
Description
Describe the bug
Bug Description
A use-after-release (use-after-free) scenario exists in Zephyr's Bluetooth Controller, specifically in the scan and scan_aux LLL pipeline. The issue concerns the scheduling of ull_sched_mfy_after_cen_offset_get() using mayfly_enqueue from within lll_scan.c and lll_scan_aux.c, where a pointer to an event structure (likely a stack-allocated or MFIFO-allocated lll_event) is passed to the mayfly mechanism for deferred execution in the ULL_LOW context.
Control Path Details
- End of scan event:
lll_done(void *param)is called at the end of an LLL event (e.g., scan event). It marks the event as complete, releases resources, and may schedule a resume via mayfly if the event was preempted.
- Pipeline Management:
ull_prepare_dequeue_get()and thenMFIFO_DEQUEUE(prep)are used to dequeue and release the event buffer for reuse. This happens immediately after mayfly scheduling.
- Preempted Event Handling and Resume:
- If preempted,
mayfly_enqueue(..., lll_resume, lll_event*)is called to schedule a deferred resume.lll_resume(void *param)is called from mayfly, and invokeslll_prepare_resolve()with the event context.
- If preempted,
- Scan Prepare Callback:
- Functions like
lll_scan_prepare(void *param)handle scan event programming. If a connection is established, they prepare to schedule ULL actions.
- Functions like
- Scheduling ULL_LOW Callback:
- In
lll_scan.corlll_scan_aux.c:This schedulesif (lll->conn) { static memq_link_t link; static struct mayfly mfy_after_cen_offset_get = { 0U, 0U, &link, NULL, ull_sched_mfy_after_cen_offset_get }; mfy_after_cen_offset_get.param = p; retval = mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_LOW, 1U, &mfy_after_cen_offset_get); LL_ASSERT(!retval); }
ull_sched_mfy_after_cen_offset_get()to run in ULL_LOW context, passing a pointer to the current event/context (p).
- In
- Immediate Event Release:
- After scheduling,
MFIFO_DEQUEUE(prep)is called, releasing the buffer for reuse.
- After scheduling,
- Deferred Callback Execution:
ull_sched_mfy_after_cen_offset_get(void *param)runs in ULL_LOW context and dereferences the pointer passed, which may now point to a recycled buffer if another event was scheduled in the interim.
Path Summary with Function Call Chain
lll_done()→ (pipeline management) → if preempted:mayfly_enqueue(..., lll_resume, lll_event*)lll_resume(lll_event*)→lll_prepare_resolve()→ scan prepare callback (e.g.,lll_scan_prepare) → iflll->conn, then:mayfly_enqueue(TICKER_USER_ID_LLL, TICKER_USER_ID_ULL_LOW, ..., ull_sched_mfy_after_cen_offset_get, lll_event*)→ (immediately after): event buffer is released (MFIFO_DEQUEUE)- Later in ULL_LOW context:
ull_sched_mfy_after_cen_offset_get(lll_event*)
Critical Window:
Between mayfly_enqueue of ull_sched_mfy_after_cen_offset_get() and the execution of this callback, the pointer may be released and reused for a new event, leading to a use-after-release scenario.
Impact
- This is a memory safety bug that could cause subtle and hard-to-reproduce failures, crashes, or security vulnerabilities in Bluetooth Controller operation.
Steps to Reproduce
- Run continuous scanning with rapid preemption and rescheduling, or any case where scan events rapidly follow each other with close timing.
- Instrument the code to observe reuse of MFIFO slots and deferred execution of mayfly callbacks.
Additional Context
- The lifetime of the
lll_eventstructure (or similar context) must be guaranteed until the mayfly callback has executed. Currently, the dequeue/release happens too soon. - Any code refactoring or fix should defer MFIFO_DEQUEUE or otherwise guarantee memory validity until after the mayfly callback.
Relevant labels: bug, area: Bluetooth Controller, area: Memory Management, area: Bluetooth
Regression
- This is a regression.
Steps to reproduce
No response
Relevant log output
Impact
Functional Limitation – Some features not working as expected, but system usable.
Environment
No response
Additional Context
No response