diff --git a/modules/af_packet2_cve_2020_14386/skeletonkey_modules.c b/modules/af_packet2_cve_2020_14386/skeletonkey_modules.c index eea318e..339aa11 100644 --- a/modules/af_packet2_cve_2020_14386/skeletonkey_modules.c +++ b/modules/af_packet2_cve_2020_14386/skeletonkey_modules.c @@ -45,9 +45,6 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" -#include "../../core/offsets.h" -#include "../../core/finisher.h" #include #include @@ -55,13 +52,18 @@ #include #include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" +#include "../../core/offsets.h" +#include "../../core/finisher.h" + #include #include #include #include #include - -#ifdef __linux__ #include #include #include @@ -72,52 +74,6 @@ #include #include #include -#endif - -/* ---------- macOS / non-linux build stubs --------------------------- - * Modules in SKELETONKEY are dev-built on macOS and run-built on Linux. - * Provide empty stubs so syntax checks pass without Linux headers. - * The exploit path is gated at runtime on the kernel version anyway, - * so the stubs are never reached on macOS targets. */ -#ifndef __linux__ -#define CLONE_NEWUSER 0x10000000 -#define CLONE_NEWNET 0x40000000 -#define ETH_P_ALL 0x0003 -#define ETH_P_8021Q 0x8100 -#define ETH_P_8021AD 0x88A8 -#define ETH_P_IP 0x0800 -#define ETH_ALEN 6 -#define ETH_HLEN 14 -#define VLAN_HLEN 4 -#define IFF_UP 0x01 -#define IFF_RUNNING 0x40 -#define SIOCSIFFLAGS 0x8914 -#define SIOCGIFINDEX 0x8933 -#define SIOCGIFFLAGS 0x8913 -#define SOL_PACKET 263 -#define PACKET_RX_RING 5 -#define PACKET_VERSION 10 -#define PACKET_QDISC_BYPASS 20 -#define TPACKET_V2 1 -#define PACKET_HOST 0 -struct sockaddr_ll { unsigned short sll_family; unsigned short sll_protocol; int sll_ifindex; int dummy; }; -struct ifreq { char name[16]; union { int ifr_ifindex; short ifr_flags; } u; }; -struct tpacket_req { unsigned int tp_block_size, tp_block_nr, tp_frame_size, tp_frame_nr; }; -struct tpacket2_hdr { unsigned int tp_status, tp_len, tp_snaplen; unsigned short tp_mac, tp_net; }; -struct pollfd { int fd; short events, revents; }; -#define POLLIN 0x001 -__attribute__((unused)) static int ioctl(int a, unsigned long b, ...) { (void)a; (void)b; errno=ENOSYS; return -1; } -__attribute__((unused)) static void *mmap(void *a, size_t b, int c, int d, int e, long f) { (void)a;(void)b;(void)c;(void)d;(void)e;(void)f; errno=ENOSYS; return (void*)-1; } -__attribute__((unused)) static int munmap(void *a, size_t b) { (void)a;(void)b; return -1; } -__attribute__((unused)) static int setsockopt(int a, int b, int c, const void *d, unsigned int e) { (void)a;(void)b;(void)c;(void)d;(void)e; errno=ENOSYS; return -1; } -__attribute__((unused)) static int poll(struct pollfd *a, unsigned long b, int c) { (void)a;(void)b;(void)c; errno=ENOSYS; return -1; } -__attribute__((unused)) static unsigned short htons(unsigned short x) { return x; } -#define MAP_SHARED 0x01 -#define MAP_LOCKED 0x2000 -#define PROT_READ 0x1 -#define PROT_WRITE 0x2 -#define MAP_FAILED ((void *)-1) -#endif static const struct kernel_patched_from af_packet2_patched_branches[] = { {4, 9, 235}, @@ -223,8 +179,6 @@ static skeletonkey_result_t af_packet2_detect(const struct skeletonkey_ctx *ctx) * the primitive. It does not land cred overwrite. */ -#ifdef __linux__ - /* sendmmsg spray helper — best-effort skb groom. Adjacent kernel slab * objects are sprayed so the OOB write lands on attacker bytes. */ static void af_packet2_skb_spray(int n_iters) @@ -440,15 +394,6 @@ static int af_packet2_primitive_child(const struct skeletonkey_ctx *ctx) return 0; } -#else /* !__linux__: provide a stub for macOS sanity builds */ -static int af_packet2_primitive_child(const struct skeletonkey_ctx *ctx) -{ - (void)ctx; - fprintf(stderr, "[-] af_packet2: linux-only primitive — non-linux build\n"); - return -1; -} -#endif - /* ---- Full-chain finisher (--full-chain, x86_64 only) ---------------- * * Arb-write strategy (Or Cohen's sk_buff-data-pointer hijack): @@ -490,7 +435,7 @@ struct afp2_arb_ctx { int n_attempts; /* spray/fire rounds before giving up */ }; -#if defined(__x86_64__) && defined(__linux__) +#if defined(__x86_64__) static int afp2_arb_write(uintptr_t kaddr, const void *buf, size_t len, void *vctx) { struct afp2_arb_ctx *c = (struct afp2_arb_ctx *)vctx; @@ -508,9 +453,7 @@ static int afp2_arb_write(uintptr_t kaddr, const void *buf, size_t len, void *vc * frame would then write our payload (the modprobe_path string) * into the forged ->data target. */ for (int i = 0; i < c->n_attempts; i++) { -#ifdef __linux__ af_packet2_skb_spray(8); -#endif pid_t p = fork(); if (p < 0) return -1; if (p == 0) { @@ -535,9 +478,7 @@ static int afp2_arb_write(uintptr_t kaddr, const void *buf, size_t len, void *vc } int st; waitpid(p, &st, 0); -#ifdef __linux__ af_packet2_skb_spray(8); -#endif } /* LAST-RESORT depth: we have fired the trigger + spray but cannot @@ -664,7 +605,7 @@ static skeletonkey_result_t af_packet2_exploit(const struct skeletonkey_ctx *ctx " skeletonkey intentionally does not embed per-kernel offsets.\n"); } if (ctx->full_chain) { -#if defined(__x86_64__) && defined(__linux__) +#if defined(__x86_64__) /* --full-chain: resolve kernel offsets and run the Or-Cohen * sk_buff-data-pointer hijack via the shared modprobe_path * finisher. Per the verified-vs-claimed bar: if we can't @@ -703,6 +644,29 @@ static skeletonkey_result_t af_packet2_exploit(const struct skeletonkey_ctx *ctx } } +#else /* !__linux__ */ + +/* Non-Linux dev builds: AF_PACKET + TPACKET_V2 + tpacket_rcv VLAN + * underflow are Linux-only kernel surface. Stub out cleanly so the + * module still registers and `--list` / `--detect-rules` work on + * macOS/BSD dev boxes — and so the top-level `make` actually completes + * there. */ +static skeletonkey_result_t af_packet2_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] af_packet2: Linux-only module " + "(AF_PACKET TPACKET_V2 + user_ns) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t af_packet2_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] af_packet2: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} + +#endif /* __linux__ */ + static const char af_packet2_auditd[] = "# AF_PACKET VLAN LPE (CVE-2020-14386) — auditd detection rules\n" "# Same syscall surface as CVE-2017-7308 — share the skeletonkey-af-packet\n" diff --git a/modules/af_packet_cve_2017_7308/skeletonkey_modules.c b/modules/af_packet_cve_2017_7308/skeletonkey_modules.c index 0470952..fa5fb66 100644 --- a/modules/af_packet_cve_2017_7308/skeletonkey_modules.c +++ b/modules/af_packet_cve_2017_7308/skeletonkey_modules.c @@ -60,17 +60,22 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" -#include "../../core/offsets.h" -#include "../../core/finisher.h" #include #include #include #include +#include +#include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" +#include "../../core/offsets.h" +#include "../../core/finisher.h" + #include #include -#include #include #include #include @@ -858,6 +863,30 @@ static skeletonkey_result_t af_packet_exploit(const struct skeletonkey_ctx *ctx) #endif } +#else /* !__linux__ */ + +/* Non-Linux dev builds: AF_PACKET + unshare(CLONE_NEWUSER|CLONE_NEWNET) + * + TPACKET_V3 ring are Linux-only kernel surface; the TPACKET_V3 + * integer-overflow primitive is structurally unreachable elsewhere. + * Stub out cleanly so the module still registers and `--list` / + * `--detect-rules` work on macOS/BSD dev boxes — and so the top-level + * `make` actually completes there. */ +static skeletonkey_result_t af_packet_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] af_packet: Linux-only module " + "(AF_PACKET TPACKET_V3 + user_ns) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t af_packet_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] af_packet: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} + +#endif /* __linux__ */ + static const char af_packet_auditd[] = "# AF_PACKET TPACKET_V3 LPE (CVE-2017-7308) — auditd detection rules\n" "# Flag AF_PACKET socket creation from non-root via userns.\n" diff --git a/modules/cgroup_release_agent_cve_2022_0492/skeletonkey_modules.c b/modules/cgroup_release_agent_cve_2022_0492/skeletonkey_modules.c index ae04b24..f41b75a 100644 --- a/modules/cgroup_release_agent_cve_2022_0492/skeletonkey_modules.c +++ b/modules/cgroup_release_agent_cve_2022_0492/skeletonkey_modules.c @@ -38,7 +38,6 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" #include #include @@ -46,6 +45,10 @@ #include #include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" #include #include #include @@ -303,6 +306,34 @@ static skeletonkey_result_t cgroup_ra_cleanup(const struct skeletonkey_ctx *ctx) return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: unshare(CLONE_NEWUSER|CLONE_NEWNS) + cgroup v1 + * mount are Linux-only kernel surface; the release_agent primitive is + * structurally unreachable elsewhere. Stub out cleanly so the module + * still registers and `--list` / `--detect-rules` work on macOS/BSD + * dev boxes — and so the top-level `make` actually completes there. */ +static skeletonkey_result_t cgroup_ra_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] cgroup_release_agent: Linux-only module " + "(user_ns + cgroup v1 release_agent) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t cgroup_ra_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] cgroup_release_agent: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t cgroup_ra_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + static const char cgroup_ra_auditd[] = "# cgroup_release_agent (CVE-2022-0492) — auditd detection rules\n" "# Flag unshare(NEWUSER|NEWNS) + mount(cgroup) + writes to release_agent.\n" diff --git a/modules/cls_route4_cve_2022_2588/skeletonkey_modules.c b/modules/cls_route4_cve_2022_2588/skeletonkey_modules.c index d75e927..0cc6ad6 100644 --- a/modules/cls_route4_cve_2022_2588/skeletonkey_modules.c +++ b/modules/cls_route4_cve_2022_2588/skeletonkey_modules.c @@ -40,9 +40,6 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" -#include "../../core/offsets.h" -#include "../../core/finisher.h" #include #include @@ -50,6 +47,13 @@ #include #include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" +#include "../../core/offsets.h" +#include "../../core/finisher.h" + #include #include #include @@ -412,8 +416,6 @@ static long slab_active_kmalloc_1k(void) * Honest scope: this is structurally-fires-on-vuln + sentinel-arbitrated, * not a deterministic R/W. Same shape and same depth as xtcompat. */ -#ifdef __linux__ - struct cls_route4_arb_ctx { /* msg_msg queues kept hot inside the userns child. The arb-write * sprays additional kaddr-tagged payloads into these and re-fires @@ -544,8 +546,6 @@ static int cls4_arb_write(uintptr_t kaddr, return 0; } -#endif /* __linux__ */ - /* ---- Exploit driver ----------------------------------------------- */ static skeletonkey_result_t cls_route4_exploit(const struct skeletonkey_ctx *ctx) @@ -565,11 +565,6 @@ static skeletonkey_result_t cls_route4_exploit(const struct skeletonkey_ctx *ctx return SKELETONKEY_PRECOND_FAIL; } -#ifndef __linux__ - fprintf(stderr, "[-] cls_route4: linux-only exploit; non-linux build\n"); - (void)ctx; - return SKELETONKEY_PRECOND_FAIL; -#else /* Full-chain pre-check: resolve offsets before forking. If * modprobe_path can't be resolved, refuse early — no point doing * the userns + tc + spray + trigger dance if we can't finish. */ @@ -782,7 +777,6 @@ static skeletonkey_result_t cls_route4_exploit(const struct skeletonkey_ctx *ctx } return SKELETONKEY_EXPLOIT_FAIL; } -#endif /* __linux__ */ } /* ---- Cleanup ----------------------------------------------------- */ @@ -803,6 +797,34 @@ static skeletonkey_result_t cls_route4_cleanup(const struct skeletonkey_ctx *ctx return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: cls_route4 / tc / netlink / msg_msg are + * Linux-only kernel surface; the route4 dead-UAF is structurally + * unreachable elsewhere. Stub out cleanly so the module still + * registers and `--list` / `--detect-rules` work on macOS/BSD dev + * boxes — and so the top-level `make` actually completes there. */ +static skeletonkey_result_t cls_route4_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] cls_route4: Linux-only module " + "(net/sched cls_route4 + msg_msg) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t cls_route4_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] cls_route4: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t cls_route4_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + static const char cls_route4_auditd[] = "# cls_route4 dead UAF (CVE-2022-2588) — auditd detection rules\n" "# Flag tc filter operations with route4 classifier from non-root.\n" diff --git a/modules/dirty_cow_cve_2016_5195/skeletonkey_modules.c b/modules/dirty_cow_cve_2016_5195/skeletonkey_modules.c index 95ca46d..222e133 100644 --- a/modules/dirty_cow_cve_2016_5195/skeletonkey_modules.c +++ b/modules/dirty_cow_cve_2016_5195/skeletonkey_modules.c @@ -43,15 +43,18 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" #include #include -#include #include #include -#include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" +#include +#include #include #include #include @@ -318,6 +321,34 @@ static skeletonkey_result_t dirty_cow_cleanup(const struct skeletonkey_ctx *ctx) return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: the Dirty COW primitive (writer thread via + * /proc/self/mem + madvise(MADV_DONTNEED)) is Linux-only kernel + * surface. Stub out cleanly so the module still registers and + * `--list` / `--detect-rules` work on macOS/BSD dev boxes — and so + * the top-level `make` actually completes there. */ +static skeletonkey_result_t dirty_cow_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] dirty_cow: Linux-only module " + "(/proc/self/mem + madvise race) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t dirty_cow_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] dirty_cow: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t dirty_cow_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + /* ---- Embedded detection rules ---- */ static const char dirty_cow_auditd[] = diff --git a/modules/dirty_pipe_cve_2022_0847/skeletonkey_modules.c b/modules/dirty_pipe_cve_2022_0847/skeletonkey_modules.c index 6288a83..f49ab4f 100644 --- a/modules/dirty_pipe_cve_2022_0847/skeletonkey_modules.c +++ b/modules/dirty_pipe_cve_2022_0847/skeletonkey_modules.c @@ -32,7 +32,6 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" /* _GNU_SOURCE is passed via -D in the top-level Makefile; do not * redefine here (warning: redefined). */ @@ -42,6 +41,10 @@ #include #include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" /* used inside this block only */ #include #include #include @@ -407,6 +410,34 @@ static skeletonkey_result_t dirty_pipe_cleanup(const struct skeletonkey_ctx *ctx return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: splice() / F_GETPIPE_SZ / posix_fadvise() are + * Linux-only kernel surface; the Dirty Pipe primitive is structurally + * unreachable elsewhere. Stub out cleanly so the module still + * registers and `--list` / `--detect-rules` work on macOS/BSD dev + * boxes — and so the top-level `make` actually completes there. */ +static skeletonkey_result_t dirty_pipe_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] dirty_pipe: Linux-only module " + "(splice + PIPE_BUF_FLAG_CAN_MERGE) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t dirty_pipe_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] dirty_pipe: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t dirty_pipe_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + /* Embedded detection rules — keep the binary self-contained so * `skeletonkey --detect-rules --format=auditd` works without a separate * data-dir install. */ diff --git a/modules/fuse_legacy_cve_2022_0185/skeletonkey_modules.c b/modules/fuse_legacy_cve_2022_0185/skeletonkey_modules.c index 0d34b5a..44093de 100644 --- a/modules/fuse_legacy_cve_2022_0185/skeletonkey_modules.c +++ b/modules/fuse_legacy_cve_2022_0185/skeletonkey_modules.c @@ -59,15 +59,20 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" + +#include +#include +#include +#include +#include + +#ifdef __linux__ + #include "../../core/kernel_range.h" #include "../../core/offsets.h" #include "../../core/finisher.h" -#include -#include #include -#include -#include #include #include #include @@ -378,7 +383,6 @@ struct fuse_arb_ctx { bool trigger_armed; }; -#ifdef __linux__ static int fuse_arb_write(uintptr_t kaddr, const void *buf, size_t len, void *ctx_void) { @@ -504,15 +508,6 @@ static int fuse_arb_write(uintptr_t kaddr, const void *buf, size_t len, (unsigned long)kaddr); return 0; } -#else -static int fuse_arb_write(uintptr_t kaddr, const void *buf, size_t len, - void *ctx_void) -{ - (void)kaddr; (void)buf; (void)len; (void)ctx_void; - fprintf(stderr, "[-] fuse_arb_write: linux-only primitive\n"); - return -1; -} -#endif /* __linux__ */ /* ------------------------------------------------------------------ */ /* exploit */ @@ -732,7 +727,6 @@ static skeletonkey_result_t fuse_legacy_exploit(const struct skeletonkey_ctx *ct * runs because the arb_write primitive re-fires the trigger and * needs the live spray. * --------------------------------------------------------------- */ -#ifdef __linux__ if (ctx->full_chain) { if (!ctx->json) { fprintf(stderr, "[*] fuse_legacy: --full-chain requested — resolving " @@ -792,7 +786,6 @@ static skeletonkey_result_t fuse_legacy_exploit(const struct skeletonkey_ctx *ct } return SKELETONKEY_EXPLOIT_FAIL; } -#endif /* __linux__ */ /* Clean up our IPC queues and mapping. The kernel slab state * after the overflow may be unstable; we exit cleanly on success @@ -826,6 +819,28 @@ static skeletonkey_result_t fuse_legacy_exploit(const struct skeletonkey_ctx *ct return SKELETONKEY_EXPLOIT_FAIL; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: fsopen/fsconfig + userns+mountns clone are + * Linux-only kernel surface. Stub out cleanly so the module still + * registers and `--list` / `--detect-rules` work on macOS/BSD dev + * boxes — and so the top-level `make` actually completes there. */ +static skeletonkey_result_t fuse_legacy_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] fuse_legacy: Linux-only module " + "(fsopen + fsconfig + userns mount) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t fuse_legacy_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] fuse_legacy: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} + +#endif /* __linux__ */ + /* ------------------------------------------------------------------ */ /* embedded detection rules */ /* ------------------------------------------------------------------ */ diff --git a/modules/netfilter_xtcompat_cve_2021_22555/skeletonkey_modules.c b/modules/netfilter_xtcompat_cve_2021_22555/skeletonkey_modules.c index 3ba5778..00ffe83 100644 --- a/modules/netfilter_xtcompat_cve_2021_22555/skeletonkey_modules.c +++ b/modules/netfilter_xtcompat_cve_2021_22555/skeletonkey_modules.c @@ -58,16 +58,20 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" + +#include +#include +#include +#include +#include + +#ifdef __linux__ + #include "../../core/kernel_range.h" #include "../../core/offsets.h" #include "../../core/finisher.h" -#include -#include #include -#include -#include -#include #include #include #include @@ -76,8 +80,6 @@ #include #include #include - -#ifdef __linux__ #include #include #include @@ -91,31 +93,6 @@ #ifndef SOL_IP #define SOL_IP 0 #endif -#endif - -/* ---------- macOS / non-linux build stubs --------------------------- - * SKELETONKEY modules are dev-built on macOS (clangd / syntax check) and - * run-built on Linux. The Linux-only types and IPT_SO_SET_REPLACE - * constants are absent on Darwin; stub them so the .c file compiles - * cleanly under either toolchain. The actual exploit body is gated - * by `#ifdef __linux__` at runtime entry. */ -#ifndef __linux__ -#define CLONE_NEWUSER 0x10000000 -#define CLONE_NEWNET 0x40000000 -#define IPPROTO_RAW 255 -#define SOL_IP 0 -#define IPT_SO_SET_REPLACE 64 -struct ipt_replace { char dummy; }; -__attribute__((unused)) static int msgget(int a, int b) { (void)a;(void)b; errno=ENOSYS; return -1; } -__attribute__((unused)) static int msgsnd(int a, const void *b, size_t c, int d) { (void)a;(void)b;(void)c;(void)d; errno=ENOSYS; return -1; } -__attribute__((unused)) static ssize_t msgrcv(int a, void *b, size_t c, long d, int e) { (void)a;(void)b;(void)c;(void)d;(void)e; errno=ENOSYS; return -1; } -__attribute__((unused)) static int msgctl(int a, int b, void *c) { (void)a;(void)b;(void)c; errno=ENOSYS; return -1; } -#define IPC_PRIVATE 0 -#define IPC_CREAT 01000 -#define IPC_NOWAIT 04000 -#define IPC_RMID 0 -#define MSG_COPY 040000 -#endif /* ---- Kernel range ------------------------------------------------- */ @@ -202,8 +179,6 @@ static skeletonkey_result_t netfilter_xtcompat_detect(const struct skeletonkey_c /* ---- Exploit: userns reach + trigger + groom ---------------------- */ -#ifdef __linux__ - /* Write uid_map and gid_map after unshare so we're root in userns. * This is the standard setgroups=deny pattern; without it the uid_map * write is rejected on modern kernels for unprivileged callers. */ @@ -471,8 +446,6 @@ static int xtcompat_fire_trigger(int *out_errno) return 0; } -#endif /* __linux__ — close original primitive block */ - /* ---- Full-chain arb-write primitive -------------------------------- * * Pattern (FALLBACK — see module top-comment): the xt_compat 4-byte OOB @@ -509,8 +482,6 @@ static int xtcompat_fire_trigger(int *out_errno) * patched kernel the trigger returns EINVAL on step 2 and arb_write * returns -1 without ever queueing the follow-up. */ -#ifdef __linux__ - struct xtcompat_arb_ctx { /* Spray queues kept hot across multiple arb_write calls. The * msg_msg slots seeded here are what the finisher uses as @@ -636,8 +607,6 @@ static int xtcompat_arb_write(uintptr_t kaddr, return 0; } -#endif /* __linux__ */ - /* ---- Exploit driver ---------------------------------------------- */ static skeletonkey_result_t netfilter_xtcompat_exploit(const struct skeletonkey_ctx *ctx) @@ -661,11 +630,6 @@ static skeletonkey_result_t netfilter_xtcompat_exploit(const struct skeletonkey_ return SKELETONKEY_PRECOND_FAIL; } -#ifndef __linux__ - fprintf(stderr, "[-] netfilter_xtcompat: linux-only exploit; non-linux build\n"); - (void)ctx; - return SKELETONKEY_PRECOND_FAIL; -#else /* Full-chain pre-check: resolve offsets before forking. If * modprobe_path can't be resolved, refuse early with the manual- * workflow help — no point doing the userns + spray + trigger @@ -944,7 +908,6 @@ static skeletonkey_result_t netfilter_xtcompat_exploit(const struct skeletonkey_ fprintf(stderr, "[-] netfilter_xtcompat: child exit %d unexpected\n", rc); return SKELETONKEY_EXPLOIT_FAIL; } -#endif /* __linux__ */ } /* ---- Cleanup ----------------------------------------------------- */ @@ -963,6 +926,33 @@ static skeletonkey_result_t netfilter_xtcompat_cleanup(const struct skeletonkey_ return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: setsockopt(IPT_SO_SET_REPLACE) + nfnetlink + + * userns is Linux-only kernel surface. Stub out cleanly so the module + * still registers and `--list` / `--detect-rules` work on macOS/BSD + * dev boxes — and so the top-level `make` actually completes there. */ +static skeletonkey_result_t netfilter_xtcompat_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] netfilter_xtcompat: Linux-only module " + "(xt_compat_target_to_user via SET_REPLACE) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t netfilter_xtcompat_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] netfilter_xtcompat: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t netfilter_xtcompat_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + /* ---- Detection rules --------------------------------------------- */ static const char netfilter_xtcompat_auditd[] = diff --git a/modules/nf_tables_cve_2024_1086/skeletonkey_modules.c b/modules/nf_tables_cve_2024_1086/skeletonkey_modules.c index ebdd097..57f5f46 100644 --- a/modules/nf_tables_cve_2024_1086/skeletonkey_modules.c +++ b/modules/nf_tables_cve_2024_1086/skeletonkey_modules.c @@ -57,16 +57,20 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" + +#include +#include +#include +#include +#include + +#ifdef __linux__ + #include "../../core/kernel_range.h" #include "../../core/offsets.h" #include "../../core/finisher.h" -#include -#include #include -#include -#include -#include #include #include #include @@ -618,7 +622,6 @@ static long slabinfo_active(const char *slab) * Factored out so --full-chain can re-fire the trigger between * msg_msg sprays without duplicating the batch-building logic. * ------------------------------------------------------------------ */ -#ifdef __linux__ static size_t build_trigger_batch(uint8_t *batch, size_t cap, uint32_t *seq) { (void)cap; @@ -792,7 +795,6 @@ static int nft_arb_write(uintptr_t kaddr, const void *buf, size_t len, void *vct usleep(20 * 1000); return 0; } -#endif /* __linux__ */ /* ------------------------------------------------------------------ * The exploit body. @@ -825,7 +827,6 @@ static skeletonkey_result_t nf_tables_exploit(const struct skeletonkey_ctx *ctx) } } -#ifdef __linux__ /* --- --full-chain path --------------------------------------- * * Resolve offsets BEFORE doing anything destructive so we can * refuse cleanly on hosts where we have no modprobe_path. We run @@ -906,7 +907,6 @@ static skeletonkey_result_t nf_tables_exploit(const struct skeletonkey_ctx *ctx) close(sock); return r; } -#endif /* --- primitive-only path: fork-isolated trigger -------------- * * Fork: child enters userns+netns and fires the bug. If the @@ -1070,6 +1070,28 @@ static skeletonkey_result_t nf_tables_exploit(const struct skeletonkey_ctx *ctx) return SKELETONKEY_EXPLOIT_FAIL; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: nfnetlink + nf_tables UAF + userns is + * Linux-only kernel surface. Stub out cleanly so the module still + * registers and `--list` / `--detect-rules` work on macOS/BSD dev + * boxes — and so the top-level `make` actually completes there. */ +static skeletonkey_result_t nf_tables_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] nf_tables: Linux-only module " + "(nft_verdict_init UAF via nfnetlink) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t nf_tables_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] nf_tables: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} + +#endif /* __linux__ */ + /* ----- Embedded detection rules ----- */ static const char nf_tables_auditd[] = diff --git a/modules/nft_fwd_dup_cve_2022_25636/skeletonkey_modules.c b/modules/nft_fwd_dup_cve_2022_25636/skeletonkey_modules.c index 2be3332..de57e70 100644 --- a/modules/nft_fwd_dup_cve_2022_25636/skeletonkey_modules.c +++ b/modules/nft_fwd_dup_cve_2022_25636/skeletonkey_modules.c @@ -43,16 +43,20 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" + +#include +#include +#include +#include +#include + +#ifdef __linux__ + #include "../../core/kernel_range.h" #include "../../core/offsets.h" #include "../../core/finisher.h" -#include -#include #include -#include -#include -#include #include #include #include @@ -585,7 +589,6 @@ static int bring_lo_up(void) return 0; } -#ifdef __linux__ static size_t build_trigger_batch(uint8_t *batch, uint32_t *seq) { size_t off = 0; @@ -596,7 +599,6 @@ static size_t build_trigger_batch(uint8_t *batch, uint32_t *seq) put_batch_end(batch, &off, (*seq)++); return off; } -#endif /* ------------------------------------------------------------------ * --full-chain arb-write context. The technique: @@ -617,8 +619,6 @@ static size_t build_trigger_batch(uint8_t *batch, uint32_t *seq) * mismatches as SKELETONKEY_EXPLOIT_FAIL rather than fake success. * ------------------------------------------------------------------ */ -#ifdef __linux__ - #define SPRAY_QUEUES_ARB 32 struct fwd_arb_ctx { @@ -721,8 +721,6 @@ static int nft_fwd_dup_arb_write(uintptr_t kaddr, return 0; } -#endif /* __linux__ */ - /* ------------------------------------------------------------------ * Exploit driver. * ------------------------------------------------------------------ */ @@ -748,11 +746,6 @@ static skeletonkey_result_t nft_fwd_dup_exploit(const struct skeletonkey_ctx *ct return pre; } -#ifndef __linux__ - fprintf(stderr, "[-] nft_fwd_dup: linux-only exploit; non-linux build\n"); - (void)ctx; - return SKELETONKEY_PRECOND_FAIL; -#else if (!ctx->json) { if (ctx->full_chain) { fprintf(stderr, "[*] nft_fwd_dup: --full-chain — trigger + OOB-write " @@ -946,7 +939,6 @@ static skeletonkey_result_t nft_fwd_dup_exploit(const struct skeletonkey_ctx *ct fprintf(stderr, "[-] nft_fwd_dup: unexpected child rc=%d\n", rc); } return SKELETONKEY_EXPLOIT_FAIL; -#endif /* __linux__ */ } /* ------------------------------------------------------------------ @@ -958,7 +950,6 @@ static skeletonkey_result_t nft_fwd_dup_cleanup(const struct skeletonkey_ctx *ct if (!ctx->json) { fprintf(stderr, "[*] nft_fwd_dup: cleaning up sysv queues + log\n"); } -#ifdef __linux__ /* Best-effort drain of any leftover msg queues with IPC_PRIVATE * key owned by us. SysV doesn't enumerate by key, but msgctl * IPC_STAT walks /proc/sysvipc/msg to find them. */ @@ -979,13 +970,38 @@ static skeletonkey_result_t nft_fwd_dup_cleanup(const struct skeletonkey_ctx *ct } fclose(f); } -#endif if (unlink("/tmp/skeletonkey-nft_fwd_dup.log") < 0 && errno != ENOENT) { /* harmless */ } return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: nf_tables / NETLINK_NETFILTER / SysV msg_msg + * groom — all Linux-only kernel surface. Stub out so the module still + * registers and the top-level `make` completes on macOS/BSD dev boxes. */ +static skeletonkey_result_t nft_fwd_dup_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] nft_fwd_dup: Linux-only module " + "(nf_tables HW-offload OOB) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t nft_fwd_dup_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] nft_fwd_dup: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t nft_fwd_dup_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + /* ------------------------------------------------------------------ * Embedded detection rules. * ------------------------------------------------------------------ */ diff --git a/modules/nft_payload_cve_2023_0179/skeletonkey_modules.c b/modules/nft_payload_cve_2023_0179/skeletonkey_modules.c index 0a67a64..09857b2 100644 --- a/modules/nft_payload_cve_2023_0179/skeletonkey_modules.c +++ b/modules/nft_payload_cve_2023_0179/skeletonkey_modules.c @@ -49,16 +49,20 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" + +#include +#include +#include +#include +#include + +#ifdef __linux__ + #include "../../core/kernel_range.h" #include "../../core/offsets.h" #include "../../core/finisher.h" -#include -#include #include -#include -#include -#include #include #include #include @@ -71,13 +75,10 @@ #include #include #include - -#ifdef __linux__ #include #include #include #include -#endif /* ------------------------------------------------------------------ * Kernel-range table @@ -187,8 +188,6 @@ static skeletonkey_result_t nft_payload_detect(const struct skeletonkey_ctx *ctx return SKELETONKEY_VULNERABLE; } -#ifdef __linux__ - /* ------------------------------------------------------------------ * userns + netns entry: become root in the new user_ns so subsequent * netlink writes carry CAP_NET_ADMIN over our private net_ns. @@ -801,8 +800,6 @@ static int nft_payload_arb_write(uintptr_t kaddr, const void *buf, size_t len, return 0; } -#endif /* __linux__ */ - /* ------------------------------------------------------------------ * Exploit body. * ------------------------------------------------------------------ */ @@ -838,11 +835,6 @@ static skeletonkey_result_t nft_payload_exploit(const struct skeletonkey_ctx *ct } } -#ifndef __linux__ - (void)ctx; - fprintf(stderr, "[-] nft_payload: linux-only exploit; non-linux build\n"); - return SKELETONKEY_PRECOND_FAIL; -#else /* --- --full-chain path: resolve offsets in parent before doing * anything destructive. */ if (ctx->full_chain) { @@ -1074,7 +1066,6 @@ static skeletonkey_result_t nft_payload_exploit(const struct skeletonkey_ctx *ct fprintf(stderr, "[-] nft_payload: unexpected child rc=%d\n", rc); } return SKELETONKEY_EXPLOIT_FAIL; -#endif /* __linux__ */ } /* ------------------------------------------------------------------ @@ -1092,6 +1083,32 @@ static skeletonkey_result_t nft_payload_cleanup(const struct skeletonkey_ctx *ct return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: nf_tables / NETLINK_NETFILTER / SysV msg_msg + * groom — all Linux-only kernel surface. Stub out so the module still + * registers and the top-level `make` completes on macOS/BSD dev boxes. */ +static skeletonkey_result_t nft_payload_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] nft_payload: Linux-only module " + "(nf_tables regset OOB) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t nft_payload_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] nft_payload: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t nft_payload_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + /* ------------------------------------------------------------------ * Detection rule corpus. * ------------------------------------------------------------------ */ diff --git a/modules/overlayfs_cve_2021_3493/skeletonkey_modules.c b/modules/overlayfs_cve_2021_3493/skeletonkey_modules.c index 36d989f..7912650 100644 --- a/modules/overlayfs_cve_2021_3493/skeletonkey_modules.c +++ b/modules/overlayfs_cve_2021_3493/skeletonkey_modules.c @@ -37,13 +37,16 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" #include #include #include #include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" #include #include #include @@ -446,6 +449,28 @@ fail_workdir: return SKELETONKEY_EXPLOIT_FAIL; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: overlayfs / unshare(CLONE_NEWUSER|CLONE_NEWNS) / + * setxattr("security.capability") are all Linux-only. Stub out so the + * module still registers and the top-level `make` completes on + * macOS/BSD dev boxes. */ +static skeletonkey_result_t overlayfs_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] overlayfs: Linux-only module " + "(Ubuntu userns-overlayfs) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t overlayfs_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] overlayfs: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} + +#endif /* __linux__ */ + /* ----- Embedded detection rules ----- */ static const char overlayfs_auditd[] = diff --git a/modules/overlayfs_setuid_cve_2023_0386/skeletonkey_modules.c b/modules/overlayfs_setuid_cve_2023_0386/skeletonkey_modules.c index 5458607..e3ada98 100644 --- a/modules/overlayfs_setuid_cve_2023_0386/skeletonkey_modules.c +++ b/modules/overlayfs_setuid_cve_2023_0386/skeletonkey_modules.c @@ -40,14 +40,17 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" #include #include -#include #include #include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" +#include #include #include #include @@ -371,6 +374,32 @@ static skeletonkey_result_t overlayfs_setuid_cleanup(const struct skeletonkey_ct return SKELETONKEY_OK; } +#else /* !__linux__ */ + +/* Non-Linux dev builds: overlayfs copy-up / unshare(CLONE_NEWUSER|CLONE_NEWNS) + * / mount("overlay", ...) are Linux-only. Stub out so the module still + * registers and the top-level `make` completes on macOS/BSD dev boxes. */ +static skeletonkey_result_t overlayfs_setuid_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] overlayfs_setuid: Linux-only module " + "(overlayfs setuid copy-up) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t overlayfs_setuid_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] overlayfs_setuid: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t overlayfs_setuid_cleanup(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + return SKELETONKEY_OK; +} + +#endif /* __linux__ */ + static const char overlayfs_setuid_auditd[] = "# overlayfs setuid copy-up (CVE-2023-0386) — auditd detection rules\n" "# Same surface as CVE-2021-3493; share the skeletonkey-overlayfs key.\n" diff --git a/modules/ptrace_traceme_cve_2019_13272/skeletonkey_modules.c b/modules/ptrace_traceme_cve_2019_13272/skeletonkey_modules.c index e299f90..52defd6 100644 --- a/modules/ptrace_traceme_cve_2019_13272/skeletonkey_modules.c +++ b/modules/ptrace_traceme_cve_2019_13272/skeletonkey_modules.c @@ -28,13 +28,16 @@ #include "skeletonkey_modules.h" #include "../../core/registry.h" -#include "../../core/kernel_range.h" #include #include #include #include #include + +#ifdef __linux__ + +#include "../../core/kernel_range.h" #include #include #include @@ -277,6 +280,27 @@ static skeletonkey_result_t ptrace_traceme_exploit(const struct skeletonkey_ctx #endif } +#else /* !__linux__ */ + +/* Non-Linux dev builds: PTRACE_TRACEME / PTRACE_ATTACH / user_regs_struct + * are Linux-only ABI surface. Stub out so the module still registers and + * the top-level `make` completes on macOS/BSD dev boxes. */ +static skeletonkey_result_t ptrace_traceme_detect(const struct skeletonkey_ctx *ctx) +{ + if (!ctx->json) + fprintf(stderr, "[i] ptrace_traceme: Linux-only module " + "(PTRACE_TRACEME cred-escalation) — not applicable here\n"); + return SKELETONKEY_PRECOND_FAIL; +} +static skeletonkey_result_t ptrace_traceme_exploit(const struct skeletonkey_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, "[-] ptrace_traceme: Linux-only module — cannot run here\n"); + return SKELETONKEY_PRECOND_FAIL; +} + +#endif /* __linux__ */ + static const char ptrace_traceme_auditd[] = "# PTRACE_TRACEME LPE (CVE-2019-13272) — auditd detection rules\n" "# Flag PTRACE_TRACEME (request 0) followed by parent execve of\n"