Skip to content

Bluetooth: Controller: Use-after-release of lll_event in mayfly_enqueue path in lll_scan.c/lll_scan_aux.c #97967

@cvinayak

Description

@cvinayak

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

  1. 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.
  2. Pipeline Management:
    • ull_prepare_dequeue_get() and then MFIFO_DEQUEUE(prep) are used to dequeue and release the event buffer for reuse. This happens immediately after mayfly scheduling.
  3. 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 invokes lll_prepare_resolve() with the event context.
  4. 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.
  5. Scheduling ULL_LOW Callback:
    • In lll_scan.c or lll_scan_aux.c:
      if (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);
      }
      This schedules ull_sched_mfy_after_cen_offset_get() to run in ULL_LOW context, passing a pointer to the current event/context (p).
  6. Immediate Event Release:
    • After scheduling, MFIFO_DEQUEUE(prep) is called, releasing the buffer for reuse.
  7. 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

  1. lll_done() → (pipeline management) → if preempted: mayfly_enqueue(..., lll_resume, lll_event*)
  2. lll_resume(lll_event*)lll_prepare_resolve() → scan prepare callback (e.g., lll_scan_prepare) → if lll->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)
  3. 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_event structure (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

Metadata

Metadata

Assignees

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions