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)
PoC verification
Evidence pack
findings/poc/DF-0063 Β· 5 files| File | Type | Description | Size | |
|---|---|---|---|---|
| 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 |
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.
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
- File:
sys/kern/link_elf.c - References: sys/kern/link_elf.c:812, sys/kern/link_elf.c:838
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 -p1andpatch -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).
Recommended fix
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
fixedVALIDATED via combined kernel build rc=0.
baseline: no cycle limit / patched: chain_limit = nchains, build rc=0.
Confirmed kernel references
- s
- y
- s
- /
- k
- e
- r
- n
- /
- l
- i
- n
- k
- _
- e
- l
- f
- .
- c
- :
- 8
- 1
- 2
- s
- y
- s
- /
- k
- e
- r
- n
- /
- l
- i
- n
- k
- _
- e
- l
- f
- .
- c
- :
- 8
- 3
- 8
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.
No comments yet.