# DF-2827 — ckpt_thaw_proc: e_phnum == 0 ⇒ kmalloc(0) = ZERO_LENGTH_PTR deref (kernel page fault)

* File: `sys/kern/kern_checkpoint.c`
* Bug lines: **kern_checkpoint.c:232-240** — `nbyte = sizeof(Elf_Phdr) *
  ehdr->e_phnum` with `e_phnum == 0` ⇒ `kmalloc(0, M_TEMP, M_WAITOK)`
  returns `ZERO_LENGTH_PTR` = `(void *)-8` (sys/kern/kern_slaballoc.c:888-891);
  `elf_getphdrs(fp, phdr, 0)` reads nothing, then `phdr->p_filesz`
  (kern_checkpoint.c:240) loads from `(void*)-8 + 0x20` = **kernel VA 0x18**
  ⇒ supervisor page fault ⇒ fatal trap / panic on any kernel config.
* Gate: same as DF-2826 (`kern.ckptgroup`, wheel by default; no fhandle or
  further image content needed — the header alone is enough).

## Build / Run (guest, root)

    sh /root/df2826/build.sh                  # builds gen + triggers + images
    cd /root/df2826
    ./gen df2827.ckpt stage2.bin zero         # e_phnum = 0 variant
    ./trigger_fd3 df2827.ckpt

## Expected

    Fatal user address access from kernel mode from trigger_fd3 at ...
    Fatal trap 12: page fault while in kernel mode
    fault virtual address = 0x18
    fault code = supervisor read data, page not present
    Stopped at sys_sys_checkpoint+0x2f0: movq 0x20(%rax),%rax
    Debugger("panic")

(`0x18` = ZERO_LENGTH_PTR(-8) + offsetof(Elf64_Phdr, p_filesz)(0x20);
the instruction is exactly the `phdr->p_filesz` load feeding elf_getnotes.)

## Fix

Rejected in `../DF-2826/fix.diff` (`e_phnum == 0` → EINVAL before the
kmalloc); validated on the patched kernel (no trap, clean EINVAL).
