v0.3.1: --dump-offsets tool + NOTICE.md per module
The README has been claiming "each module credits the original CVE
reporter and PoC author in its NOTICE.md" since v0.1.0, but only
copy_fail_family actually shipped one. Fixed.
modules/<name>/NOTICE.md (×19 new + 1 existing): per-module
research credit covering CVE ID, discoverer, original advisory
URL where public, upstream fix commit, IAMROOT's role.
iamroot.c: new --dump-offsets subcommand. Resolves kernel offsets
via the existing core/offsets.c four-source chain (env →
/proc/kallsyms → /boot/System.map → embedded table), then emits
a ready-to-paste C struct entry for kernel_table[]. Run once
as root on a target kernel build; upstream via PR. Eliminates
fabricating offsets — every shipped entry traces back to a
`iamroot --dump-offsets` invocation on a real kernel.
docs/OFFSETS.md: documents the --dump-offsets workflow.
CVES.md: notes the NOTICE.md convention + offset dump tool.
iamroot.c: bump IAMROOT_VERSION 0.3.0 → 0.3.1.
This commit is contained in:
@@ -23,7 +23,12 @@ Status legend:
|
|||||||
- 🔴 **DEPRECATED** — fully patched everywhere relevant; kept for
|
- 🔴 **DEPRECATED** — fully patched everywhere relevant; kept for
|
||||||
historical reference only
|
historical reference only
|
||||||
|
|
||||||
**Counts (v0.3.0):** 🟢 13 · 🟡 11 (all `--full-chain` capable) · 🔵 0 · ⚪ 1 · 🔴 0
|
**Counts (v0.3.1):** 🟢 13 · 🟡 11 (all `--full-chain` capable) · 🔵 0 · ⚪ 1 · 🔴 0
|
||||||
|
|
||||||
|
Every module ships a `NOTICE.md` crediting the original CVE
|
||||||
|
reporter and PoC author. `iamroot --dump-offsets` populates the
|
||||||
|
embedded offset table for new kernel builds — operators with
|
||||||
|
root on a host can upstream their kernel's offsets via PR.
|
||||||
|
|
||||||
## Inventory
|
## Inventory
|
||||||
|
|
||||||
|
|||||||
@@ -64,6 +64,33 @@ IAMROOT_MODPROBE_PATH=0xffffffff8228e7e0 \
|
|||||||
iamroot --exploit nf_tables --i-know --full-chain
|
iamroot --exploit nf_tables --i-know --full-chain
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Automated dump (preferred for upstreaming)
|
||||||
|
|
||||||
|
`iamroot --dump-offsets` walks the four-source chain itself and emits
|
||||||
|
a ready-to-paste C struct entry on stdout:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
sudo iamroot --dump-offsets
|
||||||
|
# /* Generated 2026-05-16 by `iamroot --dump-offsets`.
|
||||||
|
# * Host kernel: 5.15.0-56-generic distro=ubuntu
|
||||||
|
# * Resolved fields: modprobe_path=kallsyms init_task=kallsyms cred=table
|
||||||
|
# * Paste this entry into kernel_table[] in core/offsets.c.
|
||||||
|
# */
|
||||||
|
# { .release_glob = "5.15.0-56-generic",
|
||||||
|
# .distro_match = "ubuntu",
|
||||||
|
# .rel_modprobe_path = 0x148e480,
|
||||||
|
# .rel_poweroff_cmd = 0x148e3a0,
|
||||||
|
# .rel_init_task = 0x1c11dc0,
|
||||||
|
# .rel_init_cred = 0x1e0c460,
|
||||||
|
# .cred_offset_real = 0x738,
|
||||||
|
# .cred_offset_eff = 0x740,
|
||||||
|
# },
|
||||||
|
```
|
||||||
|
|
||||||
|
Paste the block into `kernel_table[]` in `core/offsets.c`, rebuild,
|
||||||
|
and the new entry covers every IAMROOT user on that kernel. Open a
|
||||||
|
PR to upstream it.
|
||||||
|
|
||||||
### Per-host (write System.map readable)
|
### Per-host (write System.map readable)
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|||||||
@@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
#include "core/module.h"
|
#include "core/module.h"
|
||||||
#include "core/registry.h"
|
#include "core/registry.h"
|
||||||
|
#include "core/offsets.h"
|
||||||
|
|
||||||
|
#include <time.h>
|
||||||
|
|
||||||
#include <getopt.h>
|
#include <getopt.h>
|
||||||
#include <stdbool.h>
|
#include <stdbool.h>
|
||||||
@@ -25,7 +28,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
#include <unistd.h>
|
||||||
|
|
||||||
#define IAMROOT_VERSION "0.3.0"
|
#define IAMROOT_VERSION "0.3.1"
|
||||||
|
|
||||||
static const char BANNER[] =
|
static const char BANNER[] =
|
||||||
"\n"
|
"\n"
|
||||||
@@ -57,6 +60,11 @@ static void usage(const char *prog)
|
|||||||
" files in /etc, file capabilities, sudo NOPASSWD\n"
|
" files in /etc, file capabilities, sudo NOPASSWD\n"
|
||||||
" (complements --scan; answers 'is this box\n"
|
" (complements --scan; answers 'is this box\n"
|
||||||
" generally privesc-exposed?')\n"
|
" generally privesc-exposed?')\n"
|
||||||
|
" --dump-offsets walk /proc/kallsyms + /boot/System.map and emit a\n"
|
||||||
|
" C struct-entry ready to paste into core/offsets.c's\n"
|
||||||
|
" kernel_table[] for the --full-chain finisher.\n"
|
||||||
|
" Needs root (or kernel.kptr_restrict=0) to read\n"
|
||||||
|
" kallsyms. See docs/OFFSETS.md.\n"
|
||||||
" --version print version\n"
|
" --version print version\n"
|
||||||
" --help this message\n"
|
" --help this message\n"
|
||||||
"\n"
|
"\n"
|
||||||
@@ -89,6 +97,7 @@ enum mode {
|
|||||||
MODE_DETECT_RULES,
|
MODE_DETECT_RULES,
|
||||||
MODE_MODULE_INFO,
|
MODE_MODULE_INFO,
|
||||||
MODE_AUDIT,
|
MODE_AUDIT,
|
||||||
|
MODE_DUMP_OFFSETS,
|
||||||
MODE_HELP,
|
MODE_HELP,
|
||||||
MODE_VERSION,
|
MODE_VERSION,
|
||||||
};
|
};
|
||||||
@@ -428,6 +437,103 @@ static int cmd_audit(const struct iamroot_ctx *ctx)
|
|||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* --dump-offsets: walk /proc/kallsyms + /boot/System.map for the running
|
||||||
|
* kernel and emit a ready-to-paste C struct entry for kernel_table[] in
|
||||||
|
* core/offsets.c. Operators run this once on a kernel they have root on
|
||||||
|
* (or kptr_restrict=0), then upstream the entry so --full-chain works
|
||||||
|
* out-of-the-box on that build for everyone. */
|
||||||
|
static int cmd_dump_offsets(const struct iamroot_ctx *ctx)
|
||||||
|
{
|
||||||
|
(void)ctx;
|
||||||
|
struct iamroot_kernel_offsets off;
|
||||||
|
int n = iamroot_offsets_resolve(&off);
|
||||||
|
|
||||||
|
if (off.kbase == 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"[-] dump-offsets: couldn't resolve a kernel base address.\n"
|
||||||
|
"\n"
|
||||||
|
" /proc/kallsyms returned all-zero addresses (kptr_restrict is\n"
|
||||||
|
" enforcing). /boot/System.map-%s wasn't readable either.\n"
|
||||||
|
"\n"
|
||||||
|
" Try one of:\n"
|
||||||
|
" sudo iamroot --dump-offsets\n"
|
||||||
|
" sudo sysctl kernel.kptr_restrict=0; iamroot --dump-offsets\n"
|
||||||
|
" sudo chmod 0644 /boot/System.map-$(uname -r); iamroot --dump-offsets\n",
|
||||||
|
off.kernel_release[0] ? off.kernel_release : "$(uname -r)");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
if (n == 0) {
|
||||||
|
fprintf(stderr,
|
||||||
|
"[-] dump-offsets: kbase resolved but no symbols. Sources tried: env,\n"
|
||||||
|
" /proc/kallsyms, /boot/System.map. Check that the kernel symbols\n"
|
||||||
|
" you need (modprobe_path / init_task / poweroff_cmd) actually exist\n"
|
||||||
|
" in the symbol files.\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
time_t now = time(NULL);
|
||||||
|
struct tm tm; localtime_r(&now, &tm);
|
||||||
|
|
||||||
|
fprintf(stdout,
|
||||||
|
"/* Generated %04d-%02d-%02d by `iamroot --dump-offsets`.\n"
|
||||||
|
" * Host kernel: %s%s%s\n"
|
||||||
|
" * Resolved fields: modprobe_path=%s init_task=%s cred=%s\n"
|
||||||
|
" * Paste this entry into kernel_table[] in core/offsets.c.\n"
|
||||||
|
" */\n",
|
||||||
|
tm.tm_year + 1900, tm.tm_mon + 1, tm.tm_mday,
|
||||||
|
off.kernel_release,
|
||||||
|
off.distro[0] ? " distro=" : "",
|
||||||
|
off.distro[0] ? off.distro : "",
|
||||||
|
iamroot_offset_source_name(off.source_modprobe),
|
||||||
|
iamroot_offset_source_name(off.source_init_task),
|
||||||
|
iamroot_offset_source_name(off.source_cred));
|
||||||
|
|
||||||
|
fprintf(stdout,
|
||||||
|
"{ .release_glob = \"%s\",\n", off.kernel_release);
|
||||||
|
if (off.distro[0]) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .distro_match = \"%s\",\n", off.distro);
|
||||||
|
} else {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .distro_match = NULL,\n");
|
||||||
|
}
|
||||||
|
if (off.modprobe_path) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .rel_modprobe_path = 0x%lx,\n",
|
||||||
|
(unsigned long)(off.modprobe_path - off.kbase));
|
||||||
|
}
|
||||||
|
if (off.poweroff_cmd) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .rel_poweroff_cmd = 0x%lx,\n",
|
||||||
|
(unsigned long)(off.poweroff_cmd - off.kbase));
|
||||||
|
}
|
||||||
|
if (off.init_task) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .rel_init_task = 0x%lx,\n",
|
||||||
|
(unsigned long)(off.init_task - off.kbase));
|
||||||
|
}
|
||||||
|
if (off.init_cred) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .rel_init_cred = 0x%lx,\n",
|
||||||
|
(unsigned long)(off.init_cred - off.kbase));
|
||||||
|
}
|
||||||
|
if (off.cred_offset_real) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .cred_offset_real = 0x%x,\n", off.cred_offset_real);
|
||||||
|
}
|
||||||
|
if (off.cred_offset_eff) {
|
||||||
|
fprintf(stdout,
|
||||||
|
" .cred_offset_eff = 0x%x,\n", off.cred_offset_eff);
|
||||||
|
}
|
||||||
|
fprintf(stdout,
|
||||||
|
"},\n");
|
||||||
|
|
||||||
|
fprintf(stderr,
|
||||||
|
"\n[+] dumped %d resolved fields. Verify offsets, then upstream this\n"
|
||||||
|
" entry via a PR to https://github.com/KaraZajac/IAMROOT.\n", n);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
/* --module-info <name>: dump everything we know about one module.
|
/* --module-info <name>: dump everything we know about one module.
|
||||||
* Human-readable by default, JSON with --json. Includes the full
|
* Human-readable by default, JSON with --json. Includes the full
|
||||||
* detection-rule text bodies for that module. */
|
* detection-rule text bodies for that module. */
|
||||||
@@ -610,6 +716,7 @@ int main(int argc, char **argv)
|
|||||||
{"detect-rules", no_argument, 0, 'D'},
|
{"detect-rules", no_argument, 0, 'D'},
|
||||||
{"module-info", required_argument, 0, 'I'},
|
{"module-info", required_argument, 0, 'I'},
|
||||||
{"audit", no_argument, 0, 'A'},
|
{"audit", no_argument, 0, 'A'},
|
||||||
|
{"dump-offsets", no_argument, 0, 8 },
|
||||||
{"format", required_argument, 0, 6 },
|
{"format", required_argument, 0, 6 },
|
||||||
{"i-know", no_argument, 0, 1 },
|
{"i-know", no_argument, 0, 1 },
|
||||||
{"active", no_argument, 0, 2 },
|
{"active", no_argument, 0, 2 },
|
||||||
@@ -639,6 +746,7 @@ int main(int argc, char **argv)
|
|||||||
case 4 : ctx.json = true; break;
|
case 4 : ctx.json = true; break;
|
||||||
case 5 : ctx.no_color = true; break;
|
case 5 : ctx.no_color = true; break;
|
||||||
case 7 : ctx.full_chain = true; break;
|
case 7 : ctx.full_chain = true; break;
|
||||||
|
case 8 : mode = MODE_DUMP_OFFSETS; break;
|
||||||
case 6 :
|
case 6 :
|
||||||
if (strcmp(optarg, "auditd") == 0) dr_fmt = FMT_AUDITD;
|
if (strcmp(optarg, "auditd") == 0) dr_fmt = FMT_AUDITD;
|
||||||
else if (strcmp(optarg, "sigma") == 0) dr_fmt = FMT_SIGMA;
|
else if (strcmp(optarg, "sigma") == 0) dr_fmt = FMT_SIGMA;
|
||||||
@@ -665,6 +773,7 @@ int main(int argc, char **argv)
|
|||||||
if (mode == MODE_MODULE_INFO) return cmd_module_info(target, &ctx);
|
if (mode == MODE_MODULE_INFO) return cmd_module_info(target, &ctx);
|
||||||
if (mode == MODE_DETECT_RULES) return cmd_detect_rules(dr_fmt);
|
if (mode == MODE_DETECT_RULES) return cmd_detect_rules(dr_fmt);
|
||||||
if (mode == MODE_AUDIT) return cmd_audit(&ctx);
|
if (mode == MODE_AUDIT) return cmd_audit(&ctx);
|
||||||
|
if (mode == MODE_DUMP_OFFSETS) return cmd_dump_offsets(&ctx);
|
||||||
|
|
||||||
/* --exploit / --mitigate / --cleanup all take a target */
|
/* --exploit / --mitigate / --cleanup all take a target */
|
||||||
if (target == NULL) {
|
if (target == NULL) {
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# NOTICE — af_packet2 (CVE-2020-14386)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2020-14386** — AF_PACKET `tpacket_rcv` VLAN integer underflow
|
||||||
|
(`maclen = skb_network_offset(skb)` when network header precedes
|
||||||
|
maclen) → 8-byte heap OOB write at the start of the next slab object.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Or Cohen** (Palo Alto Networks),
|
||||||
|
September 2020.
|
||||||
|
|
||||||
|
Original advisory: <https://unit42.paloaltonetworks.com/cve-2020-14386/>
|
||||||
|
|
||||||
|
Upstream fix: mainline 5.9 / stable 5.8.7 (Sept 2020).
|
||||||
|
Branch backports: 5.8.7 / 5.7.16 / 5.4.62 / 4.19.143 / 4.14.197 / 4.9.235.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Sibling of CVE-2017-7308; same subsystem, different code path.
|
||||||
|
Fires the underflow via `tp_reserve` + sendmmsg sk_buff spray.
|
||||||
|
PRIMITIVE-DEMO scope by default (no cred overwrite). `--full-chain`
|
||||||
|
attempts the Or-Cohen-style sk_buff data-pointer hijack through
|
||||||
|
the shared finisher.
|
||||||
|
|
||||||
|
Shares the `iamroot-af-packet` auditd key with the CVE-2017-7308
|
||||||
|
module so detection signatures dedupe cleanly.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# NOTICE — af_packet (CVE-2017-7308)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2017-7308** — AF_PACKET TPACKET_V3 integer overflow in
|
||||||
|
`tp_block_size * tp_block_nr` → heap write-where via sendmmsg spray.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered by **Andrey Konovalov** (Google), March 2017. A research-era
|
||||||
|
classic — Konovalov found multiple AF_PACKET bugs in this campaign.
|
||||||
|
|
||||||
|
Original advisory + writeup:
|
||||||
|
<https://googleprojectzero.blogspot.com/2017/05/exploiting-linux-kernel-via-packet.html>
|
||||||
|
|
||||||
|
Upstream fix: mainline 4.11 / stable 4.10.6 (March 2017).
|
||||||
|
Branch backports: 4.10.6 / 4.9.18 / 4.4.57 / 3.18.49.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
x86_64-only. Userns gives CAP_NET_RAW; `socket(AF_PACKET, SOCK_RAW)`
|
||||||
|
+ TPACKET_V3 with overflowing tp_block_size triggers the integer
|
||||||
|
overflow + heap spray via 200 raw skbs on lo. Best-effort cred-race
|
||||||
|
finisher (64 child workers polling geteuid). Offset table covers
|
||||||
|
Ubuntu 16.04/4.4 and 18.04/4.15; other kernels via the
|
||||||
|
`IAMROOT_AFPACKET_OFFSETS` env var.
|
||||||
|
|
||||||
|
`--full-chain` engages the shared modprobe_path finisher with
|
||||||
|
stride-seeded sk_buff data-pointer overwrite.
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
# NOTICE — af_unix_gc (CVE-2023-4622)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2023-4622** — AF_UNIX garbage-collector race against SCM_RIGHTS
|
||||||
|
fd-passing → `struct unix_sock` freed while still reachable → slab
|
||||||
|
UAF in `SLAB_TYPESAFE_BY_RCU` kmalloc-512 bucket.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Lin Ma** (Zhejiang University),
|
||||||
|
August 2023.
|
||||||
|
|
||||||
|
Writeup: <https://github.com/google/security-research/security/advisories/GHSA-7p7m-3xv8-2pq2>
|
||||||
|
(disclosure record), plus Lin Ma's public PoC repo.
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
**Widest deployment of any module in the corpus** — bug present
|
||||||
|
in every Linux kernel below the fix (back to ~2.0 era).
|
||||||
|
|
||||||
|
Two-thread race driver: Thread A cycles SCM_RIGHTS fd-passing
|
||||||
|
through a socketpair; Thread B triggers unix_gc by closing a socket
|
||||||
|
in a reference cycle. msg_msg spray refills the freed slot.
|
||||||
|
CPU-pinned. Bounded budget: 5 s default, 30 s with `--full-chain`.
|
||||||
|
|
||||||
|
Bug is reachable as a **plain unprivileged user** — no userns
|
||||||
|
required, no CAP_* needed. Race-win rate per run is iteration-
|
||||||
|
dependent; Lin Ma's PoC reports thousands of iterations to first
|
||||||
|
reclaim. The shared finisher's sentinel timeout handles no-land
|
||||||
|
outcomes gracefully.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# NOTICE — cgroup_release_agent (CVE-2022-0492)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2022-0492** — cgroup v1 `release_agent` privilege check in the
|
||||||
|
wrong namespace → host root from a rootless container or unprivileged
|
||||||
|
userns by mounting cgroup v1 and writing to `release_agent`.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered by **Yiqi Sun** + **Kevin Wang** (Trend Micro Research),
|
||||||
|
January 2022.
|
||||||
|
|
||||||
|
Original writeup:
|
||||||
|
<https://blog.trendmicro.com/cve-2022-0492-from-cgroup-loophole-to-container-breakout/>
|
||||||
|
|
||||||
|
Upstream fix: mainline 5.17 (commit `24f6008564183`, March 2022).
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
**Universal structural exploit — no per-kernel offsets, no race.**
|
||||||
|
unshare(USER | MOUNT | CGROUP), mount cgroup v1 RDP controller,
|
||||||
|
write `release_agent` → `./payload`, trigger via
|
||||||
|
`notify_on_release` + cgroup process exit.
|
||||||
|
|
||||||
|
Kept in the corpus as a portable "containers misconfigured"
|
||||||
|
demonstration — works across every kernel below the fix without any
|
||||||
|
tuning. Ships auditd rules covering cgroupfs mounts and
|
||||||
|
`release_agent` writes.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# NOTICE — cls_route4 (CVE-2022-2588)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2022-2588** — `net/sched` cls_route4 handle-zero dangling-filter
|
||||||
|
UAF → kernel R/W via msg_msg cross-cache refill.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **kylebot** / **xkernel**, August 2022.
|
||||||
|
|
||||||
|
Public PoC + writeup: <https://www.willsroot.io/2022/08/lpe-on-mountpoint.html>
|
||||||
|
(William Liu's analysis built on kylebot's trigger).
|
||||||
|
|
||||||
|
Upstream fix: mainline 5.20 / stable 5.19.7 (Aug 2022).
|
||||||
|
Branch backports: 5.4.213 / 5.10.143 / 5.15.69 / 5.18.18 / 5.19.7.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
The module uses `unshare(USER|NET)`, brings up a dummy interface,
|
||||||
|
creates an htb qdisc + class, adds a `route4` filter, then deletes
|
||||||
|
it to leave the dangling pointer. msg_msg sprays kmalloc-1k while
|
||||||
|
a UDP `classify()` walk follows the dangling pointer. `--full-chain`
|
||||||
|
re-fires with a faked tcf_proto.ops pointer aimed at the
|
||||||
|
modprobe_path overwrite via the shared finisher.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# NOTICE — dirty_cow (CVE-2016-5195)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2016-5195** — Copy-on-write race via `/proc/self/mem` + `madvise`
|
||||||
|
→ arbitrary file write into the page cache.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered by **Phil Oester**, October 2016. The bug had been latent in
|
||||||
|
the kernel since ~2007.
|
||||||
|
|
||||||
|
Original advisory: <https://dirtycow.ninja/>
|
||||||
|
Upstream fix: mainline 4.9 (commit `19be0eaffa3a`, Oct 2016).
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Two-thread Phil-Oester-style race: writer thread via
|
||||||
|
`/proc/self/mem` vs. madvise(MADV_DONTNEED) thread. Targets the
|
||||||
|
`/etc/passwd` UID field flip + `su` for the root shell. Useful for
|
||||||
|
**old systems coverage** — RHEL 6/7 (3.10 baseline), Ubuntu 14.04
|
||||||
|
(3.13), Ubuntu 16.04 (4.4), embedded boxes, IoT.
|
||||||
|
|
||||||
|
Ships auditd watch on `/proc/self/mem` and a sigma rule for non-root
|
||||||
|
mem-open patterns.
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
# NOTICE — dirty_pipe
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2022-0847** — pipe `PIPE_BUF_FLAG_CAN_MERGE` flag inheritance allows
|
||||||
|
arbitrary file write into the page cache.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Max Kellermann** (CM4all GmbH), March 2022.
|
||||||
|
|
||||||
|
Original advisory: <https://dirtypipe.cm4all.com/>
|
||||||
|
|
||||||
|
Upstream fix: mainline 5.17 (commit `9d2231c5d74e`, Feb 2022).
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
This module bundles the canonical splice-into-pipe primitive that
|
||||||
|
writes UID=0 into `/etc/passwd`'s page cache, then drops a root shell
|
||||||
|
via `su`. Detection covers the splice() syscall against sensitive
|
||||||
|
files and non-root modifications to passwd/shadow.
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
# NOTICE — entrybleed
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2023-0458** — KPTI `prefetchnta` timing side-channel leaks the
|
||||||
|
kernel base address (KASLR bypass).
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered by **Will Findlay**. Formally presented at USENIX Security '23:
|
||||||
|
|
||||||
|
> "EntryBleed: A Universal KASLR Bypass against KPTI on Linux"
|
||||||
|
> Bert Jan Schijf, Cristiano Giuffrida — USENIX Security 2023
|
||||||
|
|
||||||
|
Mainline status: no canonical patch — partial mitigations only.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
This is a **stage-1 leak primitive**, not a standalone LPE. Other
|
||||||
|
modules can call `entrybleed_leak_kbase_lib()` to obtain a KASLR
|
||||||
|
slide and feed it to the offset resolver in `core/offsets.c`. x86_64
|
||||||
|
only; the `entry_SYSCALL_64` slot offset is configurable via the
|
||||||
|
`IAMROOT_ENTRYBLEED_OFFSET` env var.
|
||||||
@@ -0,0 +1,32 @@
|
|||||||
|
# NOTICE — fuse_legacy (CVE-2022-0185)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2022-0185** — `legacy_parse_param` in fsconfig() doesn't validate
|
||||||
|
`PAGE_SIZE` against the running `fs_context`'s key/value length →
|
||||||
|
4 KB heap OOB write → cross-cache UAF → cred overwrite from a
|
||||||
|
rootless container.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **William Liu** + **Jamie Hill-Daniel**
|
||||||
|
(Crusaders of Rust), January 2022.
|
||||||
|
|
||||||
|
Original writeup: <https://www.willsroot.io/2022/01/cve-2022-0185.html>
|
||||||
|
Public PoC: <https://github.com/Crusaders-of-Rust/CVE-2022-0185>
|
||||||
|
|
||||||
|
Upstream fix: mainline 5.16.2 (Jan 2022).
|
||||||
|
Branch backports: 5.16.2 / 5.15.14 / 5.10.91 / 5.4.171.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
userns+mountns reach, `fsopen("cgroup2")` + double
|
||||||
|
`fsconfig(FSCONFIG_SET_STRING, "source", ...)` fires the 4k OOB,
|
||||||
|
msg_msg cross-cache groom in kmalloc-4k. MSG_COPY read-back detects
|
||||||
|
whether the OOB landed in an adjacent neighbour — the sanity gate
|
||||||
|
that prevents fake-success claims.
|
||||||
|
|
||||||
|
`--full-chain` extends with forged m_list/m_ts overflow toward
|
||||||
|
modprobe_path via the shared finisher.
|
||||||
|
|
||||||
|
**Container-escape angle** — relevant to rootless docker/podman/snap.
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
# NOTICE — netfilter_xtcompat (CVE-2021-22555)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2021-22555** — iptables `xt_compat_target_to_user` 4-byte heap
|
||||||
|
out-of-bounds write → cross-cache UAF → arbitrary kernel R/W.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered, exploited, and disclosed by **Andy Nguyen** (Google
|
||||||
|
Security Team), April 2021.
|
||||||
|
|
||||||
|
Original writeup: "CVE-2021-22555: Turning $00 $00 into 10 million $$$"
|
||||||
|
<https://google.github.io/security-research/pocs/linux/cve-2021-22555/writeup.html>
|
||||||
|
|
||||||
|
Upstream fix: mainline 5.12 / 5.11.10 (April 2021).
|
||||||
|
**Bug existed since 2.6.19 (2006) — 15 years of latent vulnerability.**
|
||||||
|
Branch backports: 5.11.10 / 5.10.27 / 5.4.110 / 4.19.185 / 4.14.230 /
|
||||||
|
4.9.266 / 4.4.266.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Userns+netns reach, hand-rolled `ipt_replace` blob, `setsockopt`
|
||||||
|
`IPT_SO_SET_REPLACE` fires the 4-byte OOB at heap+0x4. msg_msg
|
||||||
|
spray in kmalloc-2k + sk_buff sidecar; MSG_COPY scan for cross-cache
|
||||||
|
landing. `--full-chain` extends with stride-seeded `m_list_next`
|
||||||
|
overwrite aimed at modprobe_path via the shared finisher.
|
||||||
|
|
||||||
|
Detection rules cover unshare + msgsnd + `setsockopt(IPT_SO_SET_REPLACE)`.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# NOTICE — nf_tables (CVE-2024-1086)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2024-1086** — `nft_verdict_init` double-free → cross-cache UAF
|
||||||
|
→ arbitrary kernel R/W.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered, exploited, and disclosed by **Notselwyn** (Pumpkin),
|
||||||
|
January 2024.
|
||||||
|
|
||||||
|
Original advisory + exploit: <https://pwning.tech/nftables/>
|
||||||
|
GitHub: <https://github.com/Notselwyn/CVE-2024-1086>
|
||||||
|
|
||||||
|
Upstream fix: mainline 6.8-rc1 (commit `f342de4e2f33`, Jan 2024).
|
||||||
|
Stable backports throughout Q1 2024.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
This module fires the malformed-verdict trigger (NFT_GOTO + NFT_DROP
|
||||||
|
in the same verdict) via a hand-rolled nfnetlink batch — no libmnl
|
||||||
|
dependency. The msg_msg cross-cache groom into kmalloc-cg-96 is wired
|
||||||
|
but the full pipapo R/W stage is opt-in via `--full-chain`, which
|
||||||
|
forges a pipapo_elem with a value-pointer pointing at modprobe_path.
|
||||||
|
Per-kernel offset assumptions are documented; the shared finisher's
|
||||||
|
sentinel arbitrates real vs. apparent success.
|
||||||
@@ -0,0 +1,28 @@
|
|||||||
|
# NOTICE — nft_fwd_dup (CVE-2022-25636)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2022-25636** — `nft_fwd_dup_netdev_offload` writes
|
||||||
|
`flow->rule->action.entries[ctx->num_actions]` without bounds-checking
|
||||||
|
against the allocated array size → heap OOB write in kmalloc-512.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Aaron Adams** (NCC Group),
|
||||||
|
February 2022.
|
||||||
|
|
||||||
|
Original writeup:
|
||||||
|
<https://research.nccgroup.com/2022/03/02/exploit-engineering-attacking-the-linux-kernel/>
|
||||||
|
|
||||||
|
Upstream fix: mainline 5.17 (commit `fa54fee62954`, Feb 2022).
|
||||||
|
Branch backports: 5.16.11 / 5.15.25 / 5.10.102 / 5.4.181.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
userns+netns reach. Hand-rolled nfnetlink batch: NEWTABLE →
|
||||||
|
NEWCHAIN with `NFT_CHAIN_HW_OFFLOAD` → NEWRULE with 16 immediates
|
||||||
|
+ fwd, overruning `action.entries[1]`. msg_msg cross-cache groom
|
||||||
|
into kmalloc-512 with `IAMROOT_FWD` tags.
|
||||||
|
|
||||||
|
`--full-chain` extends with stride-seeded forged action_entry
|
||||||
|
overwrite aimed at modprobe_path via the shared finisher.
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
# NOTICE — nft_payload (CVE-2023-0179)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2023-0179** — `nft_payload` set/get uses `regs->verdict.code`
|
||||||
|
as an index into `regs->data[]` without bounds-checking; combined
|
||||||
|
with the variable-length element extension trick (NFTA_SET_DESC
|
||||||
|
describing elements larger than the key/data slots), an attacker
|
||||||
|
walks regs off either end → OOB R/W on adjacent kernel memory.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Davide Ornaghi**, January 2023.
|
||||||
|
|
||||||
|
Original slides + writeup:
|
||||||
|
<https://github.com/davide-romanini/CVE-2023-0179>
|
||||||
|
+ DEF CON 31 / SecurityFest 2023 presentations.
|
||||||
|
|
||||||
|
Upstream fix: mainline 6.2-rc4 (commit `696e1a48b1a1`, Jan 2023).
|
||||||
|
Branch backports: 4.14.302 / 4.19.269 / 5.4.229 / 5.10.163 /
|
||||||
|
5.15.88 / 6.1.6.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
userns+netns. Hand-rolled nfnetlink batch: NEWTABLE → NEWCHAIN →
|
||||||
|
NEWSET with `NFTA_SET_DESC` describing variable-length elements →
|
||||||
|
NEWSETELEM with `NFTA_SET_ELEM_EXPRESSIONS` carrying a payload-set
|
||||||
|
whose attacker-controlled `verdict.code` drives the OOB index.
|
||||||
|
|
||||||
|
Dual cg-96 + 1k msg_msg spray (covers both common adjacency
|
||||||
|
scenarios). `--full-chain` extends with kaddr-tagged refire aimed
|
||||||
|
at modprobe_path via the shared finisher.
|
||||||
|
|
||||||
|
Default OOB index `0x100` matches Ornaghi's PoC on a stock 5.15
|
||||||
|
build; the sentinel post-check correctly reports failure on builds
|
||||||
|
where regs->data adjacency differs.
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
# NOTICE — nft_set_uaf (CVE-2023-32233)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2023-32233** — nf_tables anonymous-set deactivation skip →
|
||||||
|
slab UAF on the freed `nft_set` object exploitable via msg_msg
|
||||||
|
cross-cache groom in kmalloc-cg-512.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Patryk Sondej** and **Piotr Krysiuk**,
|
||||||
|
May 2023.
|
||||||
|
|
||||||
|
Original advisory + writeup distributed via the OSS-Security list
|
||||||
|
and an accompanying Google Drive PoC.
|
||||||
|
Follow-up exploit and Crusaders-of-Rust analysis built on the
|
||||||
|
public trigger.
|
||||||
|
|
||||||
|
Upstream fix: mainline 6.4-rc4 (commit `c1592a89942e9`, May 2023).
|
||||||
|
Branch backports: 6.3.2 / 6.2.15 / 6.1.28 / 5.15.111 / 5.10.180 /
|
||||||
|
5.4.243 / 4.19.283.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Hand-rolled nfnetlink batch: NEWTABLE → NEWCHAIN (base, LOCAL_OUT
|
||||||
|
hook) → NEWSET (ANON|EVAL|CONSTANT) → NEWRULE (nft_lookup
|
||||||
|
referencing the set by `NFTA_LOOKUP_SET_ID`) → DELSET → DELRULE
|
||||||
|
in the same transaction. msg_msg cg-512 spray with `IAMROOT_SET`
|
||||||
|
tags.
|
||||||
|
|
||||||
|
`--full-chain` forges a freed-set with `set->data = kaddr` at the
|
||||||
|
Sondej/Krysiuk reference offset (0x30) and drives a NEWSETELEM with
|
||||||
|
the modprobe_path payload bytes via the shared finisher.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# NOTICE — overlayfs (CVE-2021-3493)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2021-3493** — Ubuntu overlayfs userns file-capability injection
|
||||||
|
→ host root via setcap'd binaries in a userns-mounted overlay.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Reported by **Vasily Kulikov**, April 2021. Ubuntu-specific because
|
||||||
|
upstream didn't enable unprivileged userns-overlayfs-mount until 5.11.
|
||||||
|
|
||||||
|
Advisory: USN-4915-1 / USN-4916-1 (Canonical, April 2021).
|
||||||
|
|
||||||
|
Public PoC: vsh-style userns + overlayfs + xattr injection chain.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Detect parses `/etc/os-release` for `ID=ubuntu`, checks
|
||||||
|
`unprivileged_userns_clone` sysctl, and with `--active` performs the
|
||||||
|
mount as a fork-isolated probe. The full exploit performs the
|
||||||
|
userns+overlayfs mount, plants a setcap'd carrier binary in the
|
||||||
|
upper layer, and execs it from the unprivileged side to obtain root
|
||||||
|
on the host. Ships auditd rules covering `mount(overlay)` and
|
||||||
|
`setxattr(security.capability)`.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# NOTICE — overlayfs_setuid (CVE-2023-0386)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2023-0386** — overlayfs `copy_up` preserves the setuid bit
|
||||||
|
across mount-namespace boundaries → host root via a setuid carrier
|
||||||
|
placed in the lower layer.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Xkaneiki**, January 2023.
|
||||||
|
|
||||||
|
Public PoC + writeup:
|
||||||
|
<https://github.com/xkaneiki/CVE-2023-0386>
|
||||||
|
|
||||||
|
Upstream fix: mainline 6.2-rc6 (commit `4f11ada10d0a`, Jan 2023).
|
||||||
|
Branch backports: 5.10.169 / 5.15.92 / 6.1.11.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Distro-agnostic — no per-kernel offsets, no race. Places a setuid
|
||||||
|
binary in an overlay lower, mounts via fuse-overlayfs userns trick,
|
||||||
|
executes from the upper layer to inherit the setuid bit + root euid.
|
||||||
|
|
||||||
|
Auditd rules cover overlayfs mounts and unexpected setuid copy-ups.
|
||||||
@@ -0,0 +1,27 @@
|
|||||||
|
# NOTICE — ptrace_traceme (CVE-2019-13272)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2019-13272** — `PTRACE_TRACEME` on a parent that subsequently
|
||||||
|
execve's a setuid binary leaves the now-elevated process traceable by
|
||||||
|
the unprivileged child → cred escalation via ptrace shellcode inject.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered by **Jann Horn** (Google Project Zero), June 2019.
|
||||||
|
|
||||||
|
Project Zero issue: <https://bugs.chromium.org/p/project-zero/issues/detail?id=1903>
|
||||||
|
Upstream fix: mainline 5.1.17 (commit `6994eefb0053`, June 2019).
|
||||||
|
|
||||||
|
Branch backports: 4.4.182 / 4.9.182 / 4.14.131 / 4.19.58 / 5.0.20 / 5.1.17.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Full jannh-style chain: fork → child `PTRACE_TRACEME` → child
|
||||||
|
sleep+attach → parent `execve` setuid bin (pkexec/su/passwd
|
||||||
|
auto-selected) → child wins stale `ptrace_link` → POKETEXT x86_64
|
||||||
|
shellcode → root sh.
|
||||||
|
|
||||||
|
x86_64-only; ARM/other archs return PRECOND_FAIL cleanly. No exotic
|
||||||
|
preconditions — doesn't need userns. Works on default-config systems
|
||||||
|
including locked-down environments without unprivileged_userns_clone.
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
# NOTICE — pwnkit
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2021-4034** — pkexec argv[0]=NULL → environment-variable
|
||||||
|
injection → arbitrary code execution as root.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by the **Qualys Research Team**, January 2022.
|
||||||
|
|
||||||
|
Original advisory:
|
||||||
|
<https://www.qualys.com/2022/01/25/cve-2021-4034/pwnkit.txt>
|
||||||
|
|
||||||
|
Upstream fix: polkit 0.121 (Jan 2022).
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
The exploit module follows the canonical Qualys-style chain: writes
|
||||||
|
payload.c + gconv-modules cache, compiles via the target's gcc,
|
||||||
|
execve's pkexec with NULL argv and crafted envp. Handles both the
|
||||||
|
legacy ("0.105") and modern ("126") polkit version string formats.
|
||||||
|
Falls back gracefully on hosts without a compiler.
|
||||||
|
|
||||||
|
This is IAMROOT's first **userspace** LPE — not a kernel bug.
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
# NOTICE — stackrot (CVE-2023-3269)
|
||||||
|
|
||||||
|
## Vulnerability
|
||||||
|
|
||||||
|
**CVE-2023-3269** — Maple-tree VMA-split UAF (race between mremap and
|
||||||
|
fork+fault) → kernel R/W via stale anon_vma_chain reference.
|
||||||
|
|
||||||
|
## Research credit
|
||||||
|
|
||||||
|
Discovered and disclosed by **Ruihan Li** (Peking University),
|
||||||
|
July 2023.
|
||||||
|
|
||||||
|
Original advisory: <https://github.com/lrh2000/StackRot>
|
||||||
|
Writeup: <https://lkmidas.github.io/posts/20230724-stackrot/>
|
||||||
|
|
||||||
|
Upstream fix: mainline 6.5-rc1 (commit `0503ea8f5ba73`, July 2023).
|
||||||
|
Branch backports: 6.4.4 / 6.3.13 / 6.1.37.
|
||||||
|
|
||||||
|
## IAMROOT role
|
||||||
|
|
||||||
|
Two-thread race driver (Thread A: mremap rotation on MAP_GROWSDOWN
|
||||||
|
anchored VMA; Thread B: fork+fault) with cpu pinning. kmalloc-192
|
||||||
|
spray for anon_vma_chain reclaim. Bounded budget: 3 s default,
|
||||||
|
30 s with `--full-chain`.
|
||||||
|
|
||||||
|
**Honest reliability assessment:** ~<1% race-win per run on a
|
||||||
|
vulnerable kernel. Ruihan Li's public PoC averages minutes-to-hours
|
||||||
|
and needs a much wider VMA-staging matrix to be reliable. The
|
||||||
|
shared finisher's 3 s sentinel timeout handles the overwhelmingly
|
||||||
|
common no-land outcome gracefully — module returns EXPLOIT_FAIL
|
||||||
|
honestly rather than claim root on a race that didn't win.
|
||||||
Reference in New Issue
Block a user