# CVE-2022-0185 - Winning a $31337 Bounty after Pwning Ubuntu and Escaping Google's KCTF Containers

Integer underflow in legacy_parse_param allows unprivileged heap overflow in kmalloc-4k, exploited via msg_msg and FUSE to root Ubuntu and escape Google kCTF containers.

- Payout: $31,337
- Severity: high
- Program: Google
- Credited: Crusaders of Rust
- Disclosed: 2022-01-25
- CVE: CVE-2022-0185
- Write-up quality: 9/10
- Original: https://www.willsroot.io/2022/01/cve-2022-0185.html
- Library page: https://bugbountylibrary.com/r/blog%3Awillsroot-io-2022-01-cve-2022-0185-html
- Tags: domain:oss impact:privesc impact:rce kind:bounty platform:blog sev:high tech:linux technique:chained technique:fuzzing technique:source-review vuln:memory-corruption vuln:privilege-escalation vuln:race-condition

**Target:** Linux kernel fsconfig/legacy_parse_param (ext4/9p filesystem context)
**Root cause:** Bound check `len > PAGE_SIZE - 2 - size` underflows when size >= 4095 because size is unsigned, allowing unbounded heap overflow in the 4k legacy_data buffer.
**Steps:**
1. unshare(CLONE_NEWNS|CLONE_NEWUSER) to gain CAP_SYS_ADMIN in namespace
2. fd = fsopen("ext4", 0)
3. Loop 117x: fsconfig(fd, FSCONFIG_SET_STRING, "\x00", "AAAA...", 0) to grow data_size to 4095
4. Trigger underflow with a value whose strlen makes len exceed PAGE_SIZE-2-size, then overflow into adjacent kmalloc-4k msg_msg m_ts
5. Use MSG_COPY to OOB-read seq_operations pointers for KASLR leak
6. Use FUSE-backed mmap page to hang usercopy mid-msg_msgseg and race arbitrary write to modprobe_path
7. Write script path to modprobe_path, trigger invalid binary to run script as root, get suid bash
**How found:** Team ran syzkaller on dedicated servers; chop0 hit KASAN slab-out-of-bounds in legacy_parse_param. They minimized the C repro to fsconfig loop and read the source to spot the unsigned size underflow in the bound check.
**Exploitation:** Heap overflow corrupts msg_msg m_ts for OOB read (KASLR leak via seq_operations), then FUSE race hangs usercopy to overwrite modprobe_path with attacker script path; running an invalid binary executes script as root yielding suid bash. For kCTF: corrupt msg_msg list pointers to build arbitrary free, overlap pipe_buffer, overwrite ops with stack pivot, ROP commit_creds(prepare_kernel_cred(NULL)) + switch_task_namespaces(find_task_by_vpid(1), init_nsproxy), then setns to escape container and read other container's flag.
**Escalation:** Chained LPE to container escape: root in namespace, then setns into init namespaces and brute-force /proc/<pid>/root/flag to read another container's flag.
**Insight:** When auditing size checks, look for unsigned subtraction in bounds like `len > PAGE_SIZE - 2 - size` where size can approach the limit; also note that moving the SLUB freelist pointer to the middle (5.7+) makes string overflows into msg_msg stable since only the first 0x30 bytes need corrupting.
