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

DELAY()/DRIVERSLEEP() do not clamp negative arguments β€” sign-extended usec count converts to a multi-hour (i8254: multi-month) kernel spin

Summary

DODELAY consumes raw int n in unsigned 64-bit muldivu64: DELAY(-1) yields ~2.2e13 ticks (~256 days at the 1.19MHz i8254 base, ~2h at 3GHz TSC) with no escape. All in-tree callers pass constants - latent trap for future driver code. Clamp-at-entry fix.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-5331 Β· 2 files
FileTypeDescriptionSize
README.md file 1.2 KB ↓ raw
verdict.json file 1.9 KB view raw
README.md file
↓ download raw

DF-5331 β€” DELAY()/DRIVERSLEEP() do not clamp negative arguments (hardening)

File: sys/platform/pc64/isa/clock.c, pass 2 (GLM 5.3). Severity: Info.

DODELAY() (clock.c:386) computes

ticks_left = muldivu64(n, sys_cputimer->freq + 999999, 1000000);

with int n (clock.c:419). A negative n is sign-extended to u64 (0xFFFF...); muldivu64 (sys/sys/systm.h:505) then yields ~2.2e13 ticks, so DELAY(-1) spins for hours-to-years depending on the selected cputimer (β‰ˆ256 days at the 1.19 MHz i8254, β‰ˆ2 h at a 3 GHz TSC). There is no if (n <= 0) return; guard.

No in-tree caller passes a user-influenced or potentially negative value (surveyed: constants and kernel-internal tables only β€” atkbdc, ppc, lpt, igmp's IGMP_RANDOM_DELAY, etc.), so this is defense-in-depth for future drivers, not a demonstrated DoS. Fix is one line:

--- a/sys/platform/pc64/isa/clock.c
+++ b/sys/platform/pc64/isa/clock.c
@@ DODELAY(int n, int doswitch)
 {
     ssysclock_t delta, ticks_left;
     sysclock_t prev_tick, tick;

+    if (n <= 0)
+        return;
+
 #ifdef DELAYDEBUG

PoC: not built β€” DELAY() is not reachable from userland; the arithmetic above is the complete demonstration (verdict status: untested).

Fix verification

not_testable
baseline no→ patch + rebuild →patched clean

not tested (hardening finding, no runtime PoC)

per-fix-DF-5331

Confirmed kernel references

Detail

Evidence (decisive lines)

findings/poc/DF-5331/README.md (analysis + suggested one-line guard); sys/platform/pc64/isa/clock.c:419; sys/sys/systm.h:505

PoC changes

none (no PoC; hardening finding)

Verified recommended fix

Clamp n at the top of DODELAY(): if (n <= 0) return;

Verdict

Hardening only. DODELAY() (sys/platform/pc64/isa/clock.c:386) computes ticks_left = muldivu64(n, sys_cputimer->freq + 999999, 1000000) at clock.c:419 with no clamp on the int argument n; a negative n sign-extends to u64 in muldivu64 (sys/sys/systm.h:505, 128-bit intermediate) yielding ~2.2e13 ticks, i.e. DELAY(-1) would spin ~256 days at the 1.19 MHz i8254 or ~2 h at a 3 GHz TSC with no escape. Survey of in-tree callers found only constants and kernel-internal tables (atkbdc.c, ppc.c, igmp IGMP_RANDOM_DELAY, etc.), so there is no demonstrated attacker-reachable trigger today; filed as Info hardening (one-line 'if (n <= 0) return;' guard). Not executed: DELAY() is not reachable from userland without a custom KLD, and the arithmetic is the complete demonstration.