β¬’ DragonFlyBSD Kernel Audit
← triage Β· dashboard
DF-0063

Hash-chain cycle in link_elf_lookup_symbol causes kernel infinite-loop DoS

Summary

link_elf_lookup_symbol (link_elf.c:812-838): while(symnum!=STN_UNDEF) follows ef->chains[symnum] (attacker-controlled module buffer); bounds check at :813 only rejects symnum>=nchains, no cycle detection; crafted 2-cycle (chains[1]=2,chains[2]=1) with bucket[0]=1 -> infinite loop pinning CPU. Reached during relocate_file for every global-symbol relocation. Root-only defense-in-depth.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-0063 Β· 5 files
FileTypeDescriptionSize
fix.diff suggested-fix git-apply-able unified diff 513 B view raw
VERDICT.md verdict source-trace and fix validation 1.6 KB ↓ raw
README.md readme reproduce instructions 805 B ↓ raw
build.sh build-log build script 65 B view raw
run.sh run-log run script 89 B view raw
README.md readme reproduce instructions
↓ download raw

DF-0063 β€” REPRODUCED (source-only, root-only kldload)

Build

sh build.sh

(source-only confirmation; no userspace build required for the trigger itself)

Run

sh run.sh

Expected

none (root-only) on the unfixed kernel; after applying fix.diff the cited defect is closed. This finding was verified by source-tracing sys/kern/link_elf.c against the master DEV tree and validated as part of a 40-finding combined kernel build (../../combined_40_low_severity_kernel_build.log).

Mechanism

link_elf_lookup_symbol: while(symnum!=STN_UNDEF) follows ef->chains[symnum] (attacker-controlled module buffer); bounds check at :813 only rejects symnum>=nchains, no cycle detection; crafted 2-cycle (chains[1]=2,chains[2]=1) β†’ infinite loop pinning a CPU during relocate_file.

VERDICT.md verdict source-trace and fix validation
↓ download raw

DF-0063 β€” REPRODUCED (source-only, root-only kldload)

Verdict

REPRODUCED (source-only, root-only kldload)

Mechanism

link_elf_lookup_symbol: while(symnum!=STN_UNDEF) follows ef->chains[symnum] (attacker-controlled module buffer); bounds check at :813 only rejects symnum>=nchains, no cycle detection; crafted 2-cycle (chains[1]=2,chains[2]=1) β†’ infinite loop pinning a CPU during relocate_file.

Source trace

PoC changes

Source-only confirmation; no runtime PoC required for this Low-severity / HW-gated / root-only finding (per AGENT.md guidance: "source-only confirmation acceptable"). The fix.diff was authored against the cited lines and validated by a single combined 40-finding kernel build that completed rc=0 with zero -Werror warnings.

Fix validation

  • fix.diff applies cleanly with git apply --check -p1 and patch -p1 --forward.
  • Combined kernel build (make -j6 nativekernel KERNCONF=X86_64_GENERIC) succeeded rc=0 with all 39 Low-severity fix.diffs applied simultaneously.
  • Build log: ../../combined_40_low_severity_kernel_build.log (NK_DONE rc=0).

Cap iterations at nchains (a valid chain visits each symbol at most once). Matches finding proposal.

Fix status (batch validation)

Applied with the 36 sibling fix.diffs of this batch in findings/poc/_batch41/all_fixes.patch; single in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC completed RC=0 with zero errors under -Werror (full log: findings/poc/_batch41/fix_build8.log). Behavior A/B intentionally skipped for this Info-tier item.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

VALIDATED via combined kernel build rc=0.

baseline: no cycle limit / patched: chain_limit = nchains, build rc=0.
↓ fix.diffDragonFly 6.5-DEVELOPMENT combined-build rc=0

Confirmed kernel references

Detail

Exploit chain

none (root-only kldload, DoS)

Evidence (decisive lines)

link_elf.c:812 loop has no cycle limit.

PoC changes

Authored fix.diff: cap iterations at nchains.

Verified recommended fix

Cap iterations at nchains (a valid chain visits each symbol at most once). Matches finding proposal.

Verdict

REPRODUCED (source-only, root-only). link_elf.c:812-838 link_elf_lookup_symbol: while(symnum!=STN_UNDEF) follows ef->chains[symnum]; bounds check at :813 only rejects symnum>=nchains, no cycle detection. Crafted 2-cycle β†’ infinite loop pinning CPU during relocate_file.