From 7387ffd3bdb462c4104740b261c7fb4bbcce7dbc Mon Sep 17 00:00:00 2001 From: KaraZajac Date: Sat, 16 May 2026 21:03:36 -0400 Subject: [PATCH] Add stackrot (CVE-2023-3269) + af_packet2 (CVE-2020-14386) modules MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Two more for 'THE tool' coverage breadth. stackrot CVE-2023-3269 (Ruihan Li, Jul 2023): - maple-tree VMA-split UAF — kernel R/W via use-after-RCU - **Different bug class than the netfilter-heavy 2022-2024 modules** (mm-class, broadens corpus shape) - kernel_range: 6.1 ≤ K < 6.4-rc4, backports: 6.1.37 / 6.3.10 / mainline 6.4 - Pre-6.1 immune (no maple tree); 6.5+ patched - Affects 6.1 LTS still widely deployed - ~1000-line public PoC deferred for port af_packet2 CVE-2020-14386 (Or Cohen, Sep 2020): - AF_PACKET tpacket_rcv VLAN integer underflow → heap OOB - Sibling of CVE-2017-7308; same subsystem, different code path - kernel_range: 4.6 ≤ K, backports across 4.9 / 4.14 / 4.19 / 5.4 / 5.7 / 5.8 - Family-shared 'iamroot-af-packet' audit key (one ausearch covers both CVEs from one rule deployment) Era coverage now (1 gap year remaining: 2018): 2016: dirty_cow 🟢 2017: af_packet 🔵 2019: ptrace_traceme 🟢 2020: af_packet2 🔵 2021: pwnkit, overlayfs, netfilter_xtcompat 🟢/🟢/🔵 2022: dirty_pipe, cls_route4, fuse_legacy 🟢/🔵/🔵 2023: entrybleed, stackrot 🟢/🔵 2024: nf_tables 🔵 2026: copy_fail family (×5) 🟢 18 modules total. Build clean. Scan on Debian 6.12.86: 13 OK / 5 VULN. --- CVES.md | 2 + Makefile | 12 +- core/registry.h | 2 + iamroot.c | 2 + .../iamroot_modules.c | 150 ++++++++++++++++++ .../iamroot_modules.h | 12 ++ .../stackrot_cve_2023_3269/iamroot_modules.c | 131 +++++++++++++++ .../stackrot_cve_2023_3269/iamroot_modules.h | 12 ++ 8 files changed, 322 insertions(+), 1 deletion(-) create mode 100644 modules/af_packet2_cve_2020_14386/iamroot_modules.c create mode 100644 modules/af_packet2_cve_2020_14386/iamroot_modules.h create mode 100644 modules/stackrot_cve_2023_3269/iamroot_modules.c create mode 100644 modules/stackrot_cve_2023_3269/iamroot_modules.h diff --git a/CVES.md b/CVES.md index c3aa11f..a6b539d 100644 --- a/CVES.md +++ b/CVES.md @@ -35,6 +35,8 @@ Status legend: | CVE-2021-22555 | iptables xt_compat heap-OOB → cross-cache UAF | LPE (kernel R/W via 4-byte heap OOB write + msg_msg/sk_buff groom) | mainline 5.12 / 5.11.10 (Apr 2021) | `netfilter_xtcompat` | 🔵 | Detect-only. Branch backports: 5.11.10 / 5.10.27 / 5.4.110 / 4.19.185 / 4.14.230 / 4.9.266 / 4.4.266. **Bug existed since 2.6.19 (2006) — 15 years of latent vulnerability**. Andy Nguyen's PGZ disclosure. Needs CAP_NET_ADMIN via user_ns. Full exploit (~400 lines msg_msg+sk_buff cross-cache groom) is substantial follow-up. | | CVE-2017-7308 | AF_PACKET TPACKET_V3 integer overflow → heap write-where | LPE (CAP_NET_RAW via userns) | mainline 4.11 / 4.10.6 (Mar 2017) | `af_packet` | 🔵 | Detect-only. Andrey Konovalov's research-era classic. Branch backports: 4.10.6 / 4.9.18 (RHEL 7-ish era) / 4.4.57 / 3.18.49. Needs user_ns for CAP_NET_RAW. Full exploit follows. | | CVE-2022-0185 | legacy_parse_param fsconfig heap OOB → container-escape | LPE (cross-cache UAF → cred overwrite from rootless container) | mainline 5.16.2 (Jan 2022) | `fuse_legacy` | 🔵 | Detect-only. **Container-escape angle** — relevant to rootless docker/podman/snap setups. Branch backports: 5.16.2 / 5.15.14 / 5.10.91 / 5.4.171. Needs user_ns + mount_ns. William Liu / Crusaders-of-Rust PoC reference. | +| CVE-2023-3269 | StackRot — maple-tree VMA-split UAF | LPE (kernel R/W via maple node use-after-RCU) | mainline 6.4-rc4 (Jul 2023) | `stackrot` | 🔵 | Detect-only. **Different bug class** (mm, not netfilter — broadens corpus shape). Affects 6.1.x LTS (still widely deployed) until 6.1.37; mainline 6.4-rc4. Ruihan Li's Peking University disclosure. ~1000-line PoC port deferred. | +| CVE-2020-14386 | AF_PACKET tpacket_rcv VLAN integer underflow | LPE (heap OOB write via crafted frame) | mainline 5.9 (Sep 2020) | `af_packet2` | 🔵 | Detect-only. Sibling of CVE-2017-7308; same subsystem, different code path. Branch backports: 5.8.7 / 5.7.16 / 5.4.62 / 4.19.143 / 4.14.197 / 4.9.235. Or Cohen's disclosure. Shares `iamroot-af-packet` audit key with CVE-2017-7308 module. | | CVE-TBD | Fragnesia (ESP shared-frag in-place encrypt) | LPE (page-cache write) | mainline TBD | `_stubs/fragnesia_TBD` | ⚪ | Stub. Per `findings/audit_leak_write_modprobe_backups_2026-05-16.md`, requires CAP_NET_ADMIN in userns netns — may or may not be in-scope depending on target environment. | ## Operations supported per module diff --git a/Makefile b/Makefile index 6cef10a..4705f73 100644 --- a/Makefile +++ b/Makefile @@ -86,10 +86,20 @@ FUL_DIR := modules/fuse_legacy_cve_2022_0185 FUL_SRCS := $(FUL_DIR)/iamroot_modules.c FUL_OBJS := $(patsubst %.c,$(BUILD)/%.o,$(FUL_SRCS)) +# Family: stackrot (CVE-2023-3269) +STR_DIR := modules/stackrot_cve_2023_3269 +STR_SRCS := $(STR_DIR)/iamroot_modules.c +STR_OBJS := $(patsubst %.c,$(BUILD)/%.o,$(STR_SRCS)) + +# Family: af_packet2 (CVE-2020-14386) — same family as af_packet +AFP2_DIR := modules/af_packet2_cve_2020_14386 +AFP2_SRCS := $(AFP2_DIR)/iamroot_modules.c +AFP2_OBJS := $(patsubst %.c,$(BUILD)/%.o,$(AFP2_SRCS)) + # Top-level dispatcher TOP_OBJ := $(BUILD)/iamroot.o -ALL_OBJS := $(TOP_OBJ) $(CORE_OBJS) $(CFF_OBJS) $(DP_OBJS) $(EB_OBJS) $(PK_OBJS) $(NFT_OBJS) $(OVL_OBJS) $(CR4_OBJS) $(DCOW_OBJS) $(PTM_OBJS) $(NXC_OBJS) $(AFP_OBJS) $(FUL_OBJS) +ALL_OBJS := $(TOP_OBJ) $(CORE_OBJS) $(CFF_OBJS) $(DP_OBJS) $(EB_OBJS) $(PK_OBJS) $(NFT_OBJS) $(OVL_OBJS) $(CR4_OBJS) $(DCOW_OBJS) $(PTM_OBJS) $(NXC_OBJS) $(AFP_OBJS) $(FUL_OBJS) $(STR_OBJS) $(AFP2_OBJS) .PHONY: all clean debug static help diff --git a/core/registry.h b/core/registry.h index bd52d84..7257a88 100644 --- a/core/registry.h +++ b/core/registry.h @@ -32,5 +32,7 @@ void iamroot_register_ptrace_traceme(void); void iamroot_register_netfilter_xtcompat(void); void iamroot_register_af_packet(void); void iamroot_register_fuse_legacy(void); +void iamroot_register_stackrot(void); +void iamroot_register_af_packet2(void); #endif /* IAMROOT_REGISTRY_H */ diff --git a/iamroot.c b/iamroot.c index 8684f50..ae09809 100644 --- a/iamroot.c +++ b/iamroot.c @@ -580,6 +580,8 @@ int main(int argc, char **argv) iamroot_register_netfilter_xtcompat(); iamroot_register_af_packet(); iamroot_register_fuse_legacy(); + iamroot_register_stackrot(); + iamroot_register_af_packet2(); enum mode mode = MODE_SCAN; struct iamroot_ctx ctx = {0}; diff --git a/modules/af_packet2_cve_2020_14386/iamroot_modules.c b/modules/af_packet2_cve_2020_14386/iamroot_modules.c new file mode 100644 index 0000000..25b7f41 --- /dev/null +++ b/modules/af_packet2_cve_2020_14386/iamroot_modules.c @@ -0,0 +1,150 @@ +/* + * af_packet2_cve_2020_14386 — IAMROOT module + * + * AF_PACKET tpacket_rcv() VLAN tag parsing integer underflow → heap + * write-before-allocation. Different bug from CVE-2017-7308 — same + * subsystem, different code path (rx side rather than ring setup), + * later introduction. Discovered by Or Cohen (2020). + * + * STATUS: 🔵 DETECT-ONLY. Or Cohen's public PoC works end-to-end; + * porting follows the same shape as CVE-2017-7308. + * + * Affected: kernel 4.6+ until backports: + * 5.8.x : K >= 5.8.7 + * 5.7.x : K >= 5.7.16 + * 5.4.x : K >= 5.4.62 + * 4.19.x : K >= 4.19.143 + * 4.14.x : K >= 4.14.197 + * 4.9.x : K >= 4.9.235 + * + * Preconditions: same as CVE-2017-7308 — CAP_NET_RAW (via user_ns). + * + * Coverage rationale: fills 2020 gap. Many distros (Ubuntu 18.04 + * default kernel 4.15, Ubuntu 20.04 default kernel 5.4) were vulnerable + * before backport. Embedded systems with 4.x kernels still in production. + */ + +#include "iamroot_modules.h" +#include "../../core/registry.h" +#include "../../core/kernel_range.h" + +#include +#include +#include +#include +#include +#include + +static const struct kernel_patched_from af_packet2_patched_branches[] = { + {4, 9, 235}, + {4, 14, 197}, + {4, 19, 143}, + {5, 4, 62}, + {5, 7, 16}, + {5, 8, 7}, + {5, 9, 0}, /* mainline */ +}; + +static const struct kernel_range af_packet2_range = { + .patched_from = af_packet2_patched_branches, + .n_patched_from = sizeof(af_packet2_patched_branches) / + sizeof(af_packet2_patched_branches[0]), +}; + +static int can_unshare_userns(void) +{ + pid_t pid = fork(); + if (pid < 0) return -1; + if (pid == 0) { + if (unshare(CLONE_NEWUSER | CLONE_NEWNET) == 0) _exit(0); + _exit(1); + } + int status; + waitpid(pid, &status, 0); + return WIFEXITED(status) && WEXITSTATUS(status) == 0; +} + +static iamroot_result_t af_packet2_detect(const struct iamroot_ctx *ctx) +{ + struct kernel_version v; + if (!kernel_version_current(&v)) { + fprintf(stderr, "[!] af_packet2: could not parse kernel version\n"); + return IAMROOT_TEST_ERROR; + } + + /* Bug introduced in 4.6 (tpacket_rcv VLAN path). Pre-4.6 immune. */ + if (v.major < 4 || (v.major == 4 && v.minor < 6)) { + if (!ctx->json) { + fprintf(stderr, "[+] af_packet2: kernel %s predates the bug (introduced in 4.6)\n", + v.release); + } + return IAMROOT_OK; + } + + bool patched = kernel_range_is_patched(&af_packet2_range, &v); + if (patched) { + if (!ctx->json) { + fprintf(stderr, "[+] af_packet2: kernel %s is patched\n", v.release); + } + return IAMROOT_OK; + } + + int userns_ok = can_unshare_userns(); + if (!ctx->json) { + fprintf(stderr, "[i] af_packet2: kernel %s in vulnerable range\n", v.release); + fprintf(stderr, "[i] af_packet2: user_ns+net_ns clone: %s\n", + userns_ok == 1 ? "ALLOWED" : + userns_ok == 0 ? "DENIED" : "could not test"); + } + + if (userns_ok == 0) { + if (!ctx->json) { + fprintf(stderr, "[+] af_packet2: user_ns denied → unprivileged exploit unreachable\n"); + } + return IAMROOT_PRECOND_FAIL; + } + if (!ctx->json) { + fprintf(stderr, "[!] af_packet2: VULNERABLE — kernel in range AND user_ns reachable\n"); + } + return IAMROOT_VULNERABLE; +} + +static iamroot_result_t af_packet2_exploit(const struct iamroot_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, + "[-] af_packet2: exploit not yet implemented in IAMROOT.\n" + " Status: 🔵 DETECT-ONLY. Reference: Or Cohen's PoC.\n" + " Exploit shape: unshare userns → AF_PACKET socket → setsockopt\n" + " TPACKET_V2 ring + crafted VLAN-tagged frame → heap underflow →\n" + " cross-cache groom → kernel R/W → cred overwrite.\n"); + return IAMROOT_PRECOND_FAIL; +} + +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 iamroot-af-packet\n" + "# key so one ausearch covers both. AF_PACKET socket creation from\n" + "# non-root via userns is the canonical footprint.\n" + "-a always,exit -F arch=b64 -S socket -F a0=17 -k iamroot-af-packet\n"; + +const struct iamroot_module af_packet2_module = { + .name = "af_packet2", + .cve = "CVE-2020-14386", + .summary = "AF_PACKET tpacket_rcv VLAN integer underflow → heap-OOB write", + .family = "af_packet", + .kernel_range = "4.6 ≤ K, backports: 5.8.7 / 5.7.16 / 5.4.62 / 4.19.143 / 4.14.197 / 4.9.235", + .detect = af_packet2_detect, + .exploit = af_packet2_exploit, + .mitigate = NULL, + .cleanup = NULL, + .detect_auditd = af_packet2_auditd, + .detect_sigma = NULL, + .detect_yara = NULL, + .detect_falco = NULL, +}; + +void iamroot_register_af_packet2(void) +{ + iamroot_register(&af_packet2_module); +} diff --git a/modules/af_packet2_cve_2020_14386/iamroot_modules.h b/modules/af_packet2_cve_2020_14386/iamroot_modules.h new file mode 100644 index 0000000..fe94bbc --- /dev/null +++ b/modules/af_packet2_cve_2020_14386/iamroot_modules.h @@ -0,0 +1,12 @@ +/* + * af_packet2_cve_2020_14386 — IAMROOT module registry hook + */ + +#ifndef AF_PACKET2_IAMROOT_MODULES_H +#define AF_PACKET2_IAMROOT_MODULES_H + +#include "../../core/module.h" + +extern const struct iamroot_module af_packet2_module; + +#endif diff --git a/modules/stackrot_cve_2023_3269/iamroot_modules.c b/modules/stackrot_cve_2023_3269/iamroot_modules.c new file mode 100644 index 0000000..e29bbae --- /dev/null +++ b/modules/stackrot_cve_2023_3269/iamroot_modules.c @@ -0,0 +1,131 @@ +/* + * stackrot_cve_2023_3269 — IAMROOT module + * + * "Stack Rot": UAF in maple-tree-based VMA splitting. The maple + * tree replaced the rbtree-based VMA store in 6.1; during split, + * the kernel could write to a maple node after it was freed via + * RCU. Exploitable for kernel R/W → cred overwrite. + * + * Discovered by Ruihan Li (Peking University), Jul 2023. Famous + * because it was the first significant exploit landed against the + * (then-recently-merged) maple tree code, and because the original + * disclosure included a public PoC that worked on default-config + * Ubuntu 23.04. + * + * STATUS: 🔵 DETECT-ONLY. Public PoC is ~1000 lines (heavy maple + * tree state management + RCU-grace-period timing); a clean port + * into iamroot_module form is a substantial follow-up. + * + * Affected: kernel 6.1.x — 6.4-rc4 mainline. Stable backports: + * 6.3.x : K >= 6.3.10 + * 6.1.x : K >= 6.1.37 (LTS — most relevant) + * mainline 6.4-rc4+ + * + * Pre-6.1 kernels are immune (no maple tree). 6.5+ are patched. + * + * Preconditions: + * - Unprivileged user_ns (to gain CAP_SYS_ADMIN inside userns for + * some triggers — actually the bug can be triggered without + * userns via plain mprotect/munmap split operations) + * - Default kernel config (CONFIG_USERFAULTFD recommended for + * deterministic exploitation, but not strictly required) + * + * Coverage rationale: 2023 mm-class bug. Different family than our + * netfilter-heavy 2022-2024 modules — broadens the corpus shape. + * Affects the 6.1 LTS kernels still widely deployed. + */ + +#include "iamroot_modules.h" +#include "../../core/registry.h" +#include "../../core/kernel_range.h" + +#include +#include +#include +#include + +static const struct kernel_patched_from stackrot_patched_branches[] = { + {6, 1, 37}, + {6, 3, 10}, + {6, 4, 0}, /* mainline */ +}; + +static const struct kernel_range stackrot_range = { + .patched_from = stackrot_patched_branches, + .n_patched_from = sizeof(stackrot_patched_branches) / + sizeof(stackrot_patched_branches[0]), +}; + +static iamroot_result_t stackrot_detect(const struct iamroot_ctx *ctx) +{ + struct kernel_version v; + if (!kernel_version_current(&v)) { + fprintf(stderr, "[!] stackrot: could not parse kernel version\n"); + return IAMROOT_TEST_ERROR; + } + + /* Bug introduced in 6.1 (when maple tree landed). Pre-6.1 kernels + * use rbtree-based VMAs and don't have this bug. */ + if (v.major < 6 || (v.major == 6 && v.minor < 1)) { + if (!ctx->json) { + fprintf(stderr, "[+] stackrot: kernel %s predates maple-tree VMA code (introduced in 6.1)\n", + v.release); + } + return IAMROOT_OK; + } + + bool patched = kernel_range_is_patched(&stackrot_range, &v); + if (patched) { + if (!ctx->json) { + fprintf(stderr, "[+] stackrot: kernel %s is patched\n", v.release); + } + return IAMROOT_OK; + } + if (!ctx->json) { + fprintf(stderr, "[!] stackrot: kernel %s in vulnerable range\n", v.release); + fprintf(stderr, "[i] stackrot: mm-class bug — affects default-config kernels; " + "no exotic preconditions\n"); + } + return IAMROOT_VULNERABLE; +} + +static iamroot_result_t stackrot_exploit(const struct iamroot_ctx *ctx) +{ + (void)ctx; + fprintf(stderr, + "[-] stackrot: exploit not yet implemented in IAMROOT.\n" + " Status: 🔵 DETECT-ONLY. Reference: Ruihan Li's public PoC\n" + " (~1000 lines maple-tree state + RCU grace period timing).\n" + " Exploit shape: mmap many VMAs → split via mprotect to trigger\n" + " maple node use-after-RCU → cross-cache groom → kernel R/W\n" + " → cred overwrite.\n"); + return IAMROOT_PRECOND_FAIL; +} + +static const char stackrot_auditd[] = + "# StackRot (CVE-2023-3269) — auditd detection rules\n" + "# Hard to detect via syscall hooks alone — the trigger is mprotect/\n" + "# munmap with specific VMA-split patterns. Flag unusual high-volume\n" + "# mprotect bursts from non-root processes.\n" + "-a always,exit -F arch=b64 -S mprotect -F success=1 -k iamroot-stackrot\n"; + +const struct iamroot_module stackrot_module = { + .name = "stackrot", + .cve = "CVE-2023-3269", + .summary = "maple-tree VMA-split UAF (StackRot) → kernel R/W → cred overwrite", + .family = "stackrot", + .kernel_range = "6.1 ≤ K < 6.4-rc4, backports: 6.3.10 / 6.1.37 (LTS)", + .detect = stackrot_detect, + .exploit = stackrot_exploit, + .mitigate = NULL, + .cleanup = NULL, + .detect_auditd = stackrot_auditd, + .detect_sigma = NULL, + .detect_yara = NULL, + .detect_falco = NULL, +}; + +void iamroot_register_stackrot(void) +{ + iamroot_register(&stackrot_module); +} diff --git a/modules/stackrot_cve_2023_3269/iamroot_modules.h b/modules/stackrot_cve_2023_3269/iamroot_modules.h new file mode 100644 index 0000000..df56a5c --- /dev/null +++ b/modules/stackrot_cve_2023_3269/iamroot_modules.h @@ -0,0 +1,12 @@ +/* + * stackrot_cve_2023_3269 — IAMROOT module registry hook + */ + +#ifndef STACKROT_IAMROOT_MODULES_H +#define STACKROT_IAMROOT_MODULES_H + +#include "../../core/module.h" + +extern const struct iamroot_module stackrot_module; + +#endif