# DF-2810 VERDICT — reproduced (NULL-symtab wild read, panic at VA 0x18)

**Status: reproduced.** Stock guest kernel
`DragonFly 6.5-DEVELOPMENT #0 Thu Jul 2 06:02:54 UTC 2026 X86_64_GENERIC`,
fresh `vm.sh reset with-src` before the run.

## Evidence
```
Fatal trap 12: page fault while in kernel mode
cpuid = 5; lapic id = 5
fault virtual address  = 0x18
fault code             = supervisor read data, page not present
instruction pointer    = 0x8:0xffffffff80626deb
current process        = 833
Stopped at      relocate_file+0x7b:      movl    (%rax),%esi
```
(run.log, panic.txt)

`0x18` is exactly `sizeof(Elf64_Sym) * symidx(1)` — the load of
`ref->st_name` from `ref = ef->symtab + ELF_R_SYM(r_info)` with
`ef->symtab == NULL` in `symbol_name()` (sys/kern/link_elf.c:696-698),
called from the relocation-failure path of relocate_file
(sys/kern/link_elf.c:719). The module legitimately supplies DT_REL/DT_RELSZ
but omits DT_SYMTAB/DT_STRTAB/DT_HASH; parse_dynamic
(sys/kern/link_elf.c:238-299) never cross-validates tag presence, and every
consumer (symbol_name :697-698, elf_lookup :1016, link_elf_lookup_symbol
:818/:824) dereferences the NULL bases with attacker-supplied indices.

## Impact
Root-gated (kldload) crafted-module NULL-offset wild read → kernel panic
(DoS). Read offset is attacker-influenced (st_name up to 2^32-1 once a
strtab-less DT_SYMTAB variant is used, or symidx via r_info) so it is the
"missing required-tag validation" sibling of DF-0060/DF-0062, which fixed
the *bounds* but not the *presence* dimension. Low per the root-supplied
rubric.

## Fix validation
fix.diff adds a post-loop presence check in parse_dynamic: any of
rel/rela/pltrel/pltrela/buckets present without both strtab and symtab →
ENOEXEC at load. Patched kernel: `kldload: Missing DT_STRTAB/DT_SYMTAB for
relocations`, RC=1, guest stays up. See run_fix.log.
