DragonFlyBSD Kernel Audit
DF-0070 / run.leak.log
← back to finding ↓ download raw
=== DF-0070 run.leak.log (leak mode -- slab-adjacent OOB) ===
Guest: same kernel, post second reset.
Caller: root.

Command:
    cd /tmp/df70 && (./df0070 evil2.ckpt leak) 2>&1; echo RUN_EXIT=$?

$ ./df0070 evil2.ckpt leak
[*] DF-0070 PoC: building evil2.ckpt  (notesz=880, n_namesz=0x35c, n_descsz=120, mode=leak)
[*] calling sys_checkpoint(CKPT_THAW, fd=3, pid=-1, retval=0) [syscall #467]...
[!] sys_checkpoint returned -1, errno=22 (Invalid argument)
RUN_EXIT=1

-- vm.sh status after run: up (guest alive, no panic) --

Analysis:  In leak mode n_namesz = 880 - 12 - 8 = 860, so *off after the
first elf_getnote advances to 12 + roundup2(860,8) = 12 + 864 = 876.  The
bcopy at kern_checkpoint.c:346 then reads 120 bytes from src+876 -- the
note buffer is only 880 bytes (kmalloc-1024 bucket), so this is a 116-byte
slab-adjacent OOB read (stays inside the same 1024-byte slab chunk +
padding, hence no page fault, no panic).  The leaked garbage fills psinfo;
elf_loadnotes then runs the validation at :292-301:

    if (status->pr_version != PRSTATUS_VERSION ||       // 1
        status->pr_statussz != sizeof(prstatus_t) ||    // 248
        ...
        psinfo->pr_version != PRPSINFO_VERSION ||       // 1
        psinfo->pr_psinfosz != sizeof(prpsinfo_t)) {    // 120
        error = EINVAL; ...

The leaked bytes almost never satisfy PRSTATUS_VERSION=1 etc., so the
path returns EINVAL and never reaches the strlcpy(p->p_comm, ...) at :306.
The OOB read is real but silent; the dominant observable impact is the
panic (DoS) demonstrated in run.log / run.2.log.