# DF-2772 — VERDICT

**REPRODUCED (panic / DoS, root-gated).**

## Root cause (sys/kern/link_elf_obj.c)

REL/RELA sections are recorded with their raw `sh_info` as the target-section
number, with no validation that the target is (or will be) a loaded
PROGBITS/NOBITS section:

```c
772:		case SHT_REL:
773:			ef->reltab[rl].rel = kmalloc(shdr[i].sh_size, ...);
774:			ef->reltab[rl].nrel = shdr[i].sh_size / sizeof(Elf_Rel);
775:			ef->reltab[rl].sec = shdr[i].sh_info;      /* raw, unchecked */
...
791:			ef->relatab[ra].sec = shdr[i].sh_info;      /* raw, unchecked */
```

Later, `findbase()` (:940-953) returns 0 unless some progtab entry carries
that exact section index, and both relocation drivers turn 0 into a panic:

```c
975:		base = findbase(ef, ef->reltab[i].sec);
976:		if (base == 0)
977:			panic("lost base for reltab");
...
1002:		base = findbase(ef, ef->relatab[i].sec);
1003:		if (base == 0)
1004:			panic("lost base for relatab");
```

and identically in `link_elf_obj_reloc_local` (:1243-1245, :1265-1267), which
runs from `link_elf_obj_load_file:818` (kldload path) and
`link_elf_obj_preload_file:368` (boot path). Any crafted module with a
nonempty REL/RELA section whose `sh_info` names the NULL section (0), a
STRTAB/SYMTAB section, an index ≥ e_shnum, or a size-0 PROGBITS section
(size-0 sections are never entered into progtab, :518-519/:697-698) panics
the kernel instead of being rejected with an error.

## Reproduction (baseline, stock kernel)

Guest: `DragonFly dfbsd 6.5-DEVELOPMENT #0: Thu Jul  2 06:02:54 UTC 2026 …
X86_64_GENERIC`, securelevel -1. `gen_module.py df2772.ko panic-rela` emits a
514-byte ET_REL object: .text, .symtab (1 null sym), .strtab, .shstrtab, and
one .rela (24 bytes, sh_info=0). `kldload /tmp/df2772.ko` → ssh hangs;
serial console (panic.txt):

```
panic: lost base for relatab
link_elf_obj_reloc_local() at link_elf_obj_reloc_local+0x28f
link_elf_obj_load_file() at link_elf_obj_load_file+0xb6f
linker_load_file.part.3() at linker_load_file.part.3+0x92
linker_load_module() at linker_load_module+0x116
sys_kldload() at sys_kldload+0xc6
Debugger("panic")
```

Reproduced twice on fresh `vm.sh reset with-src` boots (first run, then a
re-run on a fresh reset to capture the clean excerpt).

## Impact ceiling

Deterministic kernel panic from a crafted module — a robustness/DoS defect,
not a corruption primitive (nothing is written; the panic is the whole
effect). kldload is root-only (`caps_priv_check_self(SYSCAP_NOKLD)`,
kern_linker.c:792; blocked at securelevel>0), so unprivileged reach is nil;
the interesting real-world framing is a corrupted or substituted module
(incl. a preloaded one, which converts this into a boot-time brick). Low
severity, consistent with DF-0040/0041/0042 calibration.

## Fix validation

`fix.diff` (same combined patch as DF-2771/DF-2773): new
`elf_obj_reloc_target_ok()` validates `sh_info < e_shnum` + target type
PROGBITS/NOBITS (+ nonempty for the file case) in **both** scan loops
(preload :234-239, file :530-535) before the section is counted, and the four
`panic("lost base …")` sites become `return (ENOEXEC)` with the error
propagated (`link_elf_obj_reloc_local` becomes int-returning; callers :368
and :818 check it). Rebuilt kernel (`make -j6 nativekernel
KERNCONF=X86_64_GENERIC`, build.log, -Werror clean), installed as `#1: Tue
Sep  1 01:04:57 UTC 2026`, rebooted. Same PoC:

```
kldload: an error occurred while loading module /tmp/df2772.ko. Please check dmesg(8)
dmesg: linker_load_file: Unsupported file type
RC=1, guest stays up (ALL-SURVIVED), 0 panics
```

Baseline panic gone → fix_status=fixed.

## Note on scope

The scan-time rejection intentionally runs *before* the `nprogtab`/`nsym`
checks; the goto-out it takes was made safe by the DF-2773 unload guard in
the same patch (previously a scan-time rejection with nrelatab>0 and
relatab==NULL would itself have NULL-derefed in unload).
