DF-5330 / verdict.json
{ "finding_id": "DF-5330", "status": "reproduced", "reproduced": true, "impact": "dos", "confidence": "certain", "verdict": "resettodr() in sys/platform/pc64/isa/clock.c stores the wall clock in an unsigned long (tm = tv.tv_sec, clock.c:1158-1159) and converts it to RTC Y/M/D with an unbounded year-subtraction loop (clock.c:1175-1178) executed under crit_enter() (clock.c:1161). settimeofday({tv_sec:-1}) as root reaches this synchronously (sys_settimeofday -> settime -> resettodr, kern/kern_time.c:655/127/167); the negative time wraps tm to ~1.8e19 and the loop spins ~5e16 iterations with preemption/interrupts deferred and masterclock_lock held. Verified live on the QEMU guest: the syscall never returned, follow-up ssh sessions hung (RUN_RC=124), kill -9 undeliverable, guest could not even be shut down, no panic/dump. One-line range guard (fix.diff) validated by full in-guest kernel rebuild: on the patched kernel settimeofday returns instantly and the guest stays healthy, while the normal in-range resettodr path (RTC write) still works. Privileged (root/SYSCAP_NOSETTIME) local permanent kernel hang -> Low severity DoS.", "exploit_chain": "root: settimeofday({tv_sec:-1}) -> sys_settimeofday (kern_time.c:655, privilege ok) -> settime (kern_time.c:127) -> set_timeofday + synchronous resettodr (kern_time.c:167) -> microtime returns pre-epoch time -> tm=(unsigned long)-1 -> year loop clock.c:1175 spins ~5e16 iterations inside crit_enter with masterclock_lock held -> cpu0 unrecoverable, timer/clock subsystem degraded system-wide, no panic, no dump, shutdown path (resettodr_on_shutdown, clock.c:1063) hangs identically. Unprivileged escalation: none (time-setting syscalls are SYSCAP_NOSETTIME-gated).", "evidence": "run.log: trigger printed DF-5330: setting wall clock to tv_sec=-1 ... and settimeofday NEVER returned (no RETURNED marker); observation session RUN_RC=124; the ps/kill session also RC=124; dmesg+serial console show no panic; guest ignored shutdown (had to kill -9 qemu). run.2.log: same PoC on fix.diff-patched kernel prints settimeofday RETURNED (bug did not trigger) with POC_RC=0, ps works, guest healthy, and valid-time settimeofday still runs the normal resettodr path (clock set to ... ok (resettodr ran, returned)).", "kernel_refs": [ "sys/platform/pc64/isa/clock.c:1148", "sys/platform/pc64/isa/clock.c:1158", "sys/platform/pc64/isa/clock.c:1161", "sys/platform/pc64/isa/clock.c:1167", "sys/platform/pc64/isa/clock.c:1175", "sys/kern/kern_time.c:655", "sys/kern/kern_time.c:127", "sys/kern/kern_time.c:167" ], "poc_changes": "Seed concept only; wrote the 20-line trigger from scratch (settimeofday with tv_sec=-1, marker before/after). No fixes needed; built first try with base gcc80.", "attempts": 2, "guest_uname": "DragonFly dfbsd 6.5-DEVELOPMENT DragonFly 6.5-DEVELOPMENT #0: Thu Jul 2 06:02:54 UTC 2026 root@dfbsd:/usr/obj/usr/src/sys/X86_64_GENERIC x86_64", "runtime_sec": 90, "guest_dirty": 0, "build_cmd": "cc -O -o /root/df5330 /tmp/df5330.c", "run_cmd": "( /root/df5330 > /root/df5330.log 2>&1 & ); sleep 12; cat /root/df5330.log; ps axl | grep df5330", "code_hash": "00dd319dab6e8305ca5fdc77cdbb8e1b8884079fabcc9cb80500b7393d55dc43", "notes": "Baseline on vulnerable kernel (snapshot with-src, kernel 2026-07-02, kern.securelevel=-1): permanent half-frozen hang, silent, dump-less. Fix validated by in-guest make -j6 nativekernel KERNCONF=X86_64_GENERIC + installkernel + reboot + identical PoC re-run (see run.2.log and VERDICT.md). Guest reset to with-src afterwards (guest_dirty=0). Also protects the unbounded month loop at clock.c:1185 indirectly. Sibling hardening finding DF-5331 (DELAY negative-arg) filed separately.", "recommended_fix": "In resettodr(), after computing local time (tm -= tz/adjkerntz), range-check tm (bail out restoring rtc_statusb if tm > seconds-to-year-9999, which also catches all pre-epoch wraps) before the Y/M/D conversion loops; see fix.diff.", "fix_status": "fixed", "fix_baseline_reproduced": true, "fix_patched_reproduced": false, "fix_verdict": "fix.diff applied to guest /usr/src, kernel rebuilt (nativekernel, RC=0), installed, rebooted; exact PoC re-run: settimeofday returns immediately (POC_RC=0, RETURNED marker printed), ps/uptime healthy, and the normal in-range path still executes resettodr fully (valid settimeofday returns and clock changes apply). The previously-observed permanent hang is gone on the patched kernel.", "fix_evidence": "run.2.log (patched-kernel PoC run + valid-time resettodr run); build/install logs quoted therein (Kernel build completed Fri Oct 2 22:24:14 UTC 2026, install RC=0, uname -v #1: Fri Oct 2 22:20:46 UTC 2026)." } |