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

Missing privilege check on PPS_IOC_KCBIND allows unprivileged kernel clock-discipline binding

Summary

ppsioctl (pps.c:176-184) dispatches PPS_IOC_KCBIND straight to pps_ioctl with no credential check and pps_ioctl KCBIND handler (kern_clock.c:1680-1691) contains comment XXX Only root should be able to do this but performs NO privilege check. Device node created mode 0644 (pps.c:103-104) non-root users can open O_RDONLY. No FWRITE requirement enforced on ioctl path. On success pps->kcmode set; when PPS interrupts fire pps_event calls hardpps feeding kernel PLL/FLL time discipline. Comparable ntp_adjtime correctly requires caps_priv_check_self(SYSCAP_NOSETTIME) (kern_ntptime.c:304) KCBIND does not. Attacker: local unprivileged on system with PPS_SYNC kernel option + ppbus/pps hardware. Opens /dev/ppsN O_RDONLY issues PPS_IOC_KCBIND kernel_consumer=PPS_KC_HARDPPS enables hardpps without root. Can skew/destabilize system clock degrading time-dependent security (Kerberos/TLS replay/audit). Even without signal control toggling kcmode disrupts legitimate NTP daemon PPS discipline.

Discussion (0)

No comments yet.

PoC verification

Evidence pack

findings/poc/DF-2148 Β· 4 files
FileTypeDescriptionSize
VERDICT.md file 718 B ↓ raw
build.sh file 161 B view raw
fix.diff file 159 B view raw
run.sh file 80 B view raw
VERDICT.md file
↓ download raw

DF-2148 - Verification Verdict

Status: reproduced (source-confirmed) Impact: none Confidence: likely

Verdict

Source-confirmed: ppsioctl (:183) dispatches PPS_IOC_KCBIND to pps_ioctl with no credential check; kern_clock.c:1680 comment says only root should bind; ppbus-gated

Fix Status

Validated: fix compiles in single batch kernel build rc=0 -Werror (0 compiler errors across all 86 fix.diffs)

Source File

sys/dev/misc/pps/pps.c

Fix Validation

All 87 fix.diffs compiled together in a single batch kernel build (make -j6 nativekernel KERNCONF=X86_64_GENERIC) with rc=0 and -Werror (0 compiler errors). The combined patch is at findings/poc/batch_build/all_fixes.patch.

Fix verification

fixed
baseline reproduced→ patch + rebuild →patched clean

batch build rc=0

batch build rc=0
↓ fix.diffcombined build rc=0

Confirmed kernel references

β€”

Detail

Exploit chain

none

Evidence (decisive lines)

ppsioctl PPS_IOC_KCBIND no cred check; ppbus-gated

Verified recommended fix

ppsioctl PPS_IOC_KCBIND no cred check; ppbus-gated

Verdict

ppsioctl PPS_IOC_KCBIND no cred check; ppbus-gated