tokenize() writes one pointer per token into the fixed 64-entry static token[] with no bound: kernel static-data overflow β control-flow hijack (kernel executes attacker bytes)
Summary
parse_config passes the static token[MAXTOKEN=64] to tokenize(), which executes token[tokennr]=cptr for every token with no bound check - MAXTOKEN is enforced nowhere. A VINUM_CREATE config line with >64 tokens overwrites kernel .bss with pointers into the attacker's ioctl buffer; the smashed statics include the command_fail jmp_buf, so the parse-error longjmp restores an attacker-smashed RIP. LIVE-REPRODUCED twice from fresh boots: 'Fatal trap 1: privileged instruction fault', RIP inside the kmalloc'd ioctl buffer, 'Stopped at popal' (0x61 = the token byte) - KERNEL EXECUTING ATTACKER-SUPPLIED BYTES. Quoted tokens permit NOP sleds/shellcode. Also reachable from a vinum-labelled disk (vinum read, boot autodetect). Fix validated on rebuilt kernel: PoC returns cleanly, guest stable. Root-gated via 0600 /dev/vinum/control but the crafted-disk vector makes it attacker-reachable.
Discussion (0)
PoC verification
Evidence pack
findings/poc/DF-4132 Β· 8 files| File | Type | Description | Size | |
|---|---|---|---|---|
| vinum_tokensmash.c | β | 2.7 KB | view raw | |
| vinum_codeexec.c | β | 1.8 KB | view raw | |
| panic.txt | β | 1.4 KB | view raw | |
| serial_full_crash1.txt | β | 2.3 KB | view raw | |
| run.log | β | 1.1 KB | view raw | |
| fix.diff | β | 2.0 KB | view raw | |
| verdict.json | β | 3.7 KB | view raw | |
| env.txt | β | 388 B | view raw |
Fix verification
fixedApplied fix.diff to guest /usr/src, rebuilt kernel (#1 Fri Sep 18 04:22) + vinum.ko, rebooted, re-ran ./vinum_tokensmash 500: tokenize returns -1, reply.error=-1, guest stays up (run.log). Bad behavior gone.
run.log fixed section; build.log (BUILD_RC=0); dmesg clean after run.
Confirmed kernel references
Detail
Exploit chain
VINUM_CREATE ioctl (0xC4004640) with 500-token line -> sys_ioctl kmalloc(1024)+copyin -> parse_user_config -> parse_config -> tokenize writes token[64..499] past the 512-byte static array (~3.5KB of .bss smashed with heap pointers) -> command_fail jmp_buf saved RIP/RSP replaced by token pointers -> config error -> throw_rude_remark -> longjmp(command_fail) -> kernel jumps into the attacker buffer -> executes token bytes (0x61='a'=POPAL observed; quoted tokens allow arbitrary opcodes incl. NOP sleds). Escape/impact ceiling: arbitrary kernel code execution for anyone with /dev/vinum/control (0600 root:wheel) or with their media read by vinum.
Evidence (decisive lines)
panic.txt (two crash signatures), serial_full_crash1.txt, run.log (baseline panic vs fixed-kernel clean return), fix.diff, vinum_tokensmash.c + vinum_codeexec.c
PoC changes
Added lowercase /dev/vinum/control fallback (non-debug kernels reject the uppercase Control node); computed VINUM_CREATE via _IOC macros; staged token counts for reach control.
Verified recommended fix
Pass the token array size to tokenize() and return -1 instead of writing past it (fix.diff: signature + bound check + call site).
Verdict
tokenize() (vinumparser.c:163) writes one pointer per token into the caller's fixed 64-entry static array token[MAXTOKEN] (vinumconfig.c:78) with no bound check, via parse_config (vinumconfig.c:1627). A VINUM_CREATE ioctl line with >64 tokens overwrites kernel static data with pointers into the attacker's ioctl buffer; on the tested build the smashed statics include the command_fail jmp_buf, so the parse-error longjmp restores an attacker-smashed RIP and the kernel EXECUTES attacker-supplied bytes (demonstrated twice: Fatal trap 1, RIP inside the kmalloc'd ioctl buffer, executing 0x61 'a' token bytes decoded as popal). Same parser runs on config text read verbatim from vinum-labelled disks (vinum read / vinum.drives autodetect), so malicious media reaches the identical overflow. Root/operator-gated on the ioctl path; malicious-media vector for the disk path. Fix (bound the write by the caller's array size) validated on a rebuilt kernel: identical PoC returns cleanly, no overflow, guest stable.
No comments yet.