GCD Queues and Concurrency Hazards

β–Ά Watch (1:51)

Grand Central Dispatch is Apple’s concurrency framework. It manages task queues and dispatch blocks without explicit thread handling. Serial queues run tasks one at a time. Concurrent queues allow multiple tasks to run in parallel. The quality of service class β€” user initiated, user interactive, background β€” controls scheduling priority. In privileged system daemons, incorrect queue targeting or QoS propagation creates temporal vulnerabilities. A queue set to concurrent instead of serial can let message handlers interleave, breaking assumptions about single-threaded state.

Priority Inversion and Dispatch Sync Deadlocks

β–Ά Watch (7:07)

A high-priority thread waiting on a low-priority thread that never runs is priority inversion. On Darwin, the scheduler preempts low-QoS threads in favor of high-QoS threads. Using spin locks or semaphores β€” which lack ownership information β€” blocks priority inheritance. Xcode’s Thread Performance Checker flags these mismatches at runtime. Dispatch sync on a serial queue from within that same queue hangs the thread. The developer who flooded worker threads with dispatch sync calls to the main queue froze the app. Use dispatch async for cross-queue calls.

Resource Starvation and Thread Explosion

β–Ά Watch (14:42)

GCD uses a worker thread pool. If tasks block without completing β€” waiting on locks, semaphores, or synchronous calls β€” the pool spawns more threads to avoid deadlock. This causes thread explosion. One developer saw dozens of threads far beyond core count after adopting libdispatch. Apple’s abandoned Security Transforms API in macOS 10.7 created a queue and thread per task. Telemetry shows high thread churn and CPU spikes. Limit concurrent dispatches and avoid blocking calls inside worker blocks.

Case Study: GSS Cred XPC Service Race

β–Ά Watch (18:20)

A 2018 CVE in com.apple.gs.cred allowed an unprivileged client to trigger memory corruption in a root service. The handler used a serial dispatch queue but never set it as the target queue for XPC connections. Messages ran on a default concurrent queue. Two requests interleaved: one handler freed a credential while another still processed it. The timing window gave controlled memory corruption and arbitrary code execution in root context. The root cause was a single queue targeting mistake that broke serialization assumptions.

Detection Engineering Patterns

β–Ά Watch (23:25)

Static review flags three patterns: missing xpc_connection_set_target_queue calls, implicit serialization assumptions around shared mutable state, and uses of dispatch sync in privileged daemons. Telemetry signals include repeated crashes near state transitions, thread churn spikes, and queue backlogs. Behavioral detection compares thread count and Q drain times against a per-daemon baseline. Rate-limiting XPC invocations from a single client may indicate race window probing. The same measurements help SRE and threat detection.

Q&A

What about new systems re-introducing old problems? Any new system will have fresh issues, but without looking at the specific subsystem, the exact problems are unknown. β–Ά 30:48

Can AI help detect these issues? Current AI struggles with macOS-specific historical context; Chat GPT could not state where logs are stored. Asking a code generator to produce bad examples helps review but AI will not flag misaligned queues, especially in Objective-C. β–Ά 31:59

Notable Quotes

the lib dispatch thread pool will spawn additional threads if the existing ones are blocked to avoid a deadlock which you know can lead to thread explosion in addition to the priority inversion problem Olivia Gallucci Β· β–Ά 16:32

a single Q targeting mistake turned a should be serialized privileged service into a concurrent handler creating a race condition window where an unprivileged client could reliably hit for memory corruption and then exploit root context code Olivia Gallucci Β· β–Ά 21:15

a crash in isolation might look like a stability bug but a repeated crash around state transitions or cleanup paths or requests handling boundaries that probably indicates a race window being hit intentionally or accidentally Olivia Gallucci Β· β–Ά 25:49

Key Takeaways

  • GCD queue targeting mistakes turn privileged services into concurrent handlers with exploitable race conditions.
  • Xcode’s Thread Performance Checker catches priority inversions by flagging QoS mismatches at runtime.
  • Telemetry signals like thread churn and queue backlogs indicate active probing of race windows.