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

sys/libkern/ffsl.c is dead, unlistable, and shadowed code (ffs-family tail, DF-5714 class)

Summary

No conf/files entry (nothing links it); every kernel TU uses the cpufunc.h __builtin_ffsl inline; compiling it in-kernel fails with redefinition-vs-inline. Latent body 0/58.45M mismatches vs the live inline + builtin (structure-complete domain: every MSB position, exhaustive low/top-22 patterns, 50M randoms). gate-or-delete fix validated. DF-5714/5700 class.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-5715 Β· 17 files
FileTypeDescriptionSize
README.md β€” 2.3 KB ↓ raw
VERDICT.md β€” 5.0 KB ↓ raw
verdict.json β€” 5.4 KB view raw
manifest.json β€” 1.1 KB view raw
p2_harness.c β€” 5.7 KB view raw
build.sh β€” 127 B view raw
run.sh β€” 90 B view raw
k_ffsl.c β€” 1.8 KB view raw
f_ffsl_gated.c β€” 1.9 KB view raw
build.log β€” 1.8 KB view raw
run.log β€” 463 B view raw
dead_compile_ffsl.log β€” 633 B view raw
fix_compile_ffsl.log β€” 277 B view raw
fix_build.log β€” 904 B view raw
fix_run.log β€” 454 B view raw
env.txt β€” 212 B view raw
fix.diff β€” 238 B view raw

DF-5715 β€” sys/libkern/ffsl.c dead-file status + latent-correctness proof

Pass-2 (GLM 5.3) verification of the ffsl tail of the ffs/fls family (family context established by DF-5714 for ffs.c; rig pattern identical).

What was machine-proven on the DragonFly guest

  1. Dead file: libkern/ffsl.c has no entry in sys/conf/files (libkern block 2195–2237; grep -c = 0 on host and guest). Nothing links it. On the only supported arch every kernel TU gets ffsl as static __inline from sys/cpu/x86_64/include/cpufunc.h:274-280 (HAVE_INLINE_FFSL, __builtin_ffsl).
  2. Cannot compile in-kernel as committed: its #include <sys/libkern.h> (ffsl.c:32) resolves fine (unlike ffs.c's string.h), but libkern.h:51 β†’ systm.h:50 β†’ machine/cpufunc.h brings the static __inline ffsl into the same TU, and the out-of-line definition at ffsl.c:37-47 collides: gcc 8.3 error: redefinition of 'ffsl' (dead_compile_ffsl.log, kernel-style -nostdinc -D_KERNEL compile per kern.pre.mk:61).
  3. Latent body is arithmetically perfect: verbatim body vs the live cpufunc.h inline and vs __builtin_ffsl: 58,454,211 cases (0, ~0, sign word, all 64 single bits, exhaustive low-22 and top-22 bit patterns, MSB-position sweep Γ—1024, 50M splitmix64 randoms), 0 mismatches (run.log T1).
  4. Fix validated at compile level: fix.diff = FreeBSD-style #if !defined(HAVE_INLINE_FFSL) gate. Gated file compiles kernel-style and defines no global ffsl symbol on x86_64 (body compiles away). Deletion is the equally-valid alternative.

Reproduce

Copy this directory to the guest and, as root:

sh build.sh   # identity pin (cksum), conf/files census, verbatim renamed
              # compiles, kernel-style deadproof, fix validation
sh run.sh     # differential harness (~3 s)

Expected decisive lines:

DEADPROOF-OK: ffsl.c cannot compile in-kernel as committed: ... error: redefinition of 'ffsl'
T1 ffsl :   58454211 cases,          0 mism vs live-inline,          0 mism vs clz-ref
HARNESS-PASS: ...
FIXCOMPILE-OK: gated ffsl.c compiles kernel-style; global ffsl symbols in object: 0

build.sh expects the guest sources at /usr/src/sys (override with S=...). Host/guest source identity: ffsl.c cksum 1444671719 1875.

VERDICT.md
↓ download raw

VERDICT β€” DF-5715: sys/libkern/ffsl.c dead-file status + latent-correctness proof

Status: reproduced (impact: none β€” dead code, Info-severity hygiene finding). Confidence: certain. Attempts: 2. All claims machine-demonstrated on the DragonFly guest (uname in env.txt; guest source cksum-identical to the audit tree: ffsl.c 1444671719 1875, flsl.c 2802750667 1878, flsll.c 1445885582 1884).

The claim, and how each part was proven

  1. ffsl.c is not compiled into any DragonFly kernel or module. - sys/conf/files libkern block (lines 2195–2237) has no ffsl.c entry β€” nor any of the ffs/fls C family (ffs.c, fls.c, ffsl.c, flsl.c, flsll.c; census in build.log: all grep -c = 0, verified on host and guest). - sys/cpu/ contains only x86_64 β€” the only supported platform β€” and every kernel TU gets ffsl as static __inline from sys/cpu/x86_64/include/cpufunc.h:274-280 (#define HAVE_INLINE_FFSL
    • __builtin_ffsl). The prototype in sys/sys/libkern.h:105-106 is itself gated by #ifndef HAVE_INLINE_FFSL, so TUs that see cpufunc.h never even see the out-of-line prototype.
  2. The file cannot compile in-kernel as committed β€” a different mechanism than ffs.c's string.h (DF-5714), same outcome. ffsl.c:32 includes <sys/libkern.h>, which resolves fine under -nostdinc; but libkern.h:51 β†’ sys/systm.h:50 β†’ machine/cpufunc.h puts the static __inline ffsl (cpufunc.h:276-280) into the same TU, and the file's own out-of-line definition (ffsl.c:37-47) then collides: ffsl.c:38:1: error: redefinition of 'ffsl' / cpufunc.h:277:1: note: previous definition (dead_compile_ffsl.log, kernel-style compile per sys/conf/kern.pre.mk:61). So re-adding the file to conf/files would break the x86_64 kernel build.
  3. The latent body is arithmetically perfect. Verbatim kernel body (only the kernel-only include line stripped, identifier renamed -Dffsl=k_ffsl, called through a volatile function pointer, -O2) vs (a) the live cpufunc.h inline implementation and (b) __builtin_ffsl: 0 / 58,454,211 mismatches (run.log T1). Domain: 0, ~0, 1<<63, all 64 single-bit words, exhaustive over all words with bits in the low 22 positions (4,194,304), exhaustive over all words with bits in the top 22 positions (4,194,304), every MSB position Γ—1024 randoms below it, and 50,000,000 splitmix64 randoms. This clears the mask == 0 β†’ 0 path (ffsl.c:42-43), sign-bit/negative inputs, and the unsigned-shift refill at ffsl.c:45 β€” for this family the output depends only on the LSB position, and the domain above covers every reachable LSB/MSB structure.
  4. Consumer census (why this is Info, not higher). No in-tree .c file calls ffsl directly; its uses are inside headers (sys/dev/misc/evdev/freebsd-bitstring.h:308,361, sys/dev/drm/include/linux/bitops.h:61 via __ffsl) and all resolve to the cpufunc.h inline. Nothing references the dead object. No memory operands exist (pure register function) β€” guard-page/overflow classes are vacuous.
  5. Fix. fix.diff: FreeBSD-style #if !defined(HAVE_INLINE_FFSL) gate around the body. Validated: gated file compiles kernel-style and the body compiles away on x86_64 β€” nm census shows 0 global ffsl symbols in the object (build.log "FIXCOMPILE-OK", fix_run.log). Deleting the file is the equally-valid alternative (maintainer's choice); the diff is the conservative variant, consistent with DF-5714's fix for ffs.c.

Why no further escalation was pursued

No memory-safety primitive exists in this file (pure register function, no pointers), and the file is not linked anywhere β€” there is no runtime kernel behavior to attack. The pass-2 deliverable is the dead-file status plus the machine-checked latent-correctness proof (precedent: DF-5714 ffs.c, DF-5700 bcmp.c, same class).

Rig honesty notes

  • First shot: build.sh (identity pin, census, verbatim compiles, deadproof, fix validation) and run.sh (differential) both succeeded on the first execution; no intermediate failed artifacts exist for this pack. One host-side slip (an aborted harness draft, p2_harness_scratch.c) was scp'd along with the rig and deleted from the guest scratch before evidence capture; it never compiled and is not part of the provenance chain (attempts counted as 2: build pass, run pass).
  • The harness's "live inline" reference implementations are copied verbatim from cpufunc.h (bsrl/bsrq asm from :110-126, ffsl from :276-280), so the comparison target is the exact code the running kernel uses.

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 reproduced

Validation is at the compile level, which is exactly the level where the defect manifests (the file is linked nowhere, so there is no runtime behavior to A/B and no kernel rebuild to do). Baseline reproduced: the committed ffsl.c fails kernel-style compile with 'redefinition of ffsl' against cpufunc.h:277's static __inline (DEADPROOF-OK, dead_compile_ffsl.log). Patched (fix.diff = HAVE_INLINE_FFSL gate around the body): compiles kernel-style with zero errors (fix_compile_ffsl.log contains only the pre-existing harmless 'conflicting types for built-in log' warning from systm.h:216) and the nm census shows 0 global ffsl symbols in the object β€” the body compiles away on x86_64 exactly as the live tree expects (FIXCOMPILE-OK, fix_run.log).

dead_compile_ffsl.log (baseline failure: error: redefinition of 'ffsl', previous definition at cpufunc.h:277); fix_compile_ffsl.log (gated compile, error-free); fix_run.log (baseline symbol k_ffsl present vs patched census 0); build.log sections '== dead-file proof' / '== fix validation'; fix.diff
↓ fix.diffper-fix-DF-5715

Confirmed kernel references

Detail

Evidence (decisive lines)

build.log sections '== conf/files census' (libkern/ffsl.c in conf/files: 0) and '== dead-file proof' (DEADPROOF-OK: ffsl.c ... error: redefinition of 'ffsl'; cpufunc.h:277 previous definition) with full gcc output in dead_compile_ffsl.log; run.log 'T1 ffsl : 58454211 cases, 0 mism vs live-inline, 0 mism vs clz-ref' + HARNESS-PASS; 'FIXCOMPILE-OK: gated ffsl.c compiles kernel-style; global ffsl symbols in object: 0' (fix validation); env.txt pins guest cksums == audit tree (ffsl.c 1444671719 1875).

PoC changes

No seed PoC existed (pass 1 filed nothing). Rig authored per the DF-5714 pattern: verbatim bodies compiled from the guest's own /usr/src with only the kernel-only include line stripped and identifiers renamed via -D; kernel-style deadproof uses the machine/ union include dir (platform/pc64 + cpu/x86_64) with -D_KERNEL; fix variants generated by awk exactly as fix.diff. First-shot success; one host-side aborted harness draft (p2_harness_scratch.c) was accidentally scp'd with the rig and removed from the guest scratch before evidence capture (never compiled, not part of provenance).

Verified recommended fix

Adopt fix.diff (#if !defined(HAVE_INLINE_FFSL) gate around the body), or simply delete sys/libkern/ffsl.c β€” it is unreferenced by conf/files and cannot compile in-kernel as committed.

Verdict

sys/libkern/ffsl.c is dead code with a latent build hazard, completing the ffs-family picture of DF-5714: absent from sys/conf/files (libkern block 2195-2237; grep -c = 0 verified on host and guest), superseded on the only supported arch by the cpufunc.h:274-280 static __inline ffsl (__builtin_ffsl, HAVE_INLINE_FFSL; the libkern.h:105-106 prototype is itself gated), and non-compilable in-kernel as committed: the #include at ffsl.c:32 resolves fine (unlike ffs.c's string.h) but drags in libkern.h:51 -> systm.h:50 -> machine/cpufunc.h, so the out-of-line definition at ffsl.c:37-47 collides with the static __inline β€” gcc 8.3 'error: redefinition of ffsl' vs 'previous definition' at cpufunc.h:277 (dead_compile_ffsl.log, kernel-style -nostdinc -D_KERNEL compile per kern.pre.mk:61). The latent body was proven arithmetically correct: verbatim body vs the live cpufunc.h inline and vs __builtin_ffsl, 0 mismatches over 58,454,211 structure-complete cases (0, ~0, sign word, all 64 single bits, exhaustive low-22 and top-22 bit patterns, MSB-position sweep x1024, 50M splitmix64 randoms). Consumer census: no .c call site calls ffsl directly (uses are inside evdev freebsd-bitstring.h:308,361 and drm linux/bitops.h:61 via __ffsl); all resolve to the inline. Impact none (nothing links the file); Info hygiene finding, same class as DF-5714 (ffs.c) and DF-5700 (bcmp.c).