⬢ DragonFlyBSD Kernel Audit
DF-4461 / amdtemp_ccd_read.sh
← back to finding ↓ download raw
#!/bin/sh
#
# DF-4461 trigger — unprivileged read of an amdtemp CCD sensor sysctl.
#
# On AMD family 17h/19h (Zen) hardware with CCD sensors probed at boot,
# `dev.amdtemp.N.ccdX` is a CTLFLAG_RD world-readable sysctl whose handler
# (amdtemp_sysctl -> amdtemp_gettemp17to19h, sys/dev/powermng/amdtemp/amdtemp.c:946)
# executes:
#
#     KASSERT((val & AMDTEMP_17H_CCD_TMP_VALID) != 0,
#         ("sensor %d: not valid", (int)sensor));          /* amdtemp.c:966 */
#
# The VALID bit (SMU::THM Tccd register bit 11) is live hardware state. The
# driver's own probe code (amdtemp.c:1012, :1070) treats this same bit as a
# value that CAN be clear (it skips such sensors gracefully). The read path
# instead asserts, so on any kernel built with `options INVARIANTS`
# (X86_64_GENERIC, sys/config/X86_64_GENERIC:56) a single clear-bit read panics
# the kernel. The 2-second periodic sensor task (amdtemp_sensor_task,
# amdtemp.c:759-763) reaches the identical KASSERT without any user action.
#
# This script is the minimal unprivileged trigger: poll every CCD sysctl in a
# tight loop, waiting for a transiently-invalid reading.
#
# Success criterion (on AMD Zen hardware, INVARIANTS kernel): kernel panic
# "sensor %d: not valid" on the serial console / panic.txt.
# On this QEMU guest: driver cannot attach (no AMD PCI host bridge), so the
# OIDs do not exist — see run.log for the honest negative.

set -e

for i in $(seq 0 11); do
    sysctl "dev.amdtemp.0.ccd${i}" >/dev/null 2>&1 || true
done
sysctl dev.amdtemp.0.core0.sensor0 >/dev/null 2>&1 || true
echo "sweep done"