DF-5206 / analysis.txt
DF-5206 annotated walkthrough โ trinity_acquire_mutex() void fail-open
Audit target: sys/dev/drm/radeon/trinity_smc.c (DragonFlyBSD pass 2, GLM 5.3)
[L112] void trinity_acquire_mutex(struct radeon_device *rdev)
VOID return: a failed mutex acquisition is UNREPORTABLE by construction.
Unique to Trinity in the radeon SMC family: si/ci/sumo/kv have no
host-side SMC-mutex grant wait in their *_smc.c files (checked:
rg acquire_mutex over sys/dev/drm/radeon/ -> only trinity files).
[L116] WREG32(SMC_INT_REQ, 1);
Register 0x220 (trinityd.h:167). This is the host->SMC mutex REQUEST.
[L117-121] for (i = 0; i < rdev->usec_timeout; i++) {
if ((RREG32(SMC_INT_REQ) & 0xffff) == 1) break;
udelay(1);
}
Poll for grant, up to RADEON_MAX_USEC_TIMEOUT = 100000 us = 100 ms
(radeon.h:131, set at radeon_device.c:1300). On timeout the loop just
exits โ no error latch, no retry, no warning.
[L122] }
Falls out with the mutex NOT held and the caller none the wiser.
Callers that then program SMC state assuming exclusivity (trinity_dpm.c):
:1099 trinity_dpm_enable_bapm (acquire; bapm_enable msg; release)
:1109 trinity_dpm_enable (acquire; full DPM enable program; release)
:1138 trinity_dpm_late_enable (acquire; clock/power gating; release)
:1158 trinity_dpm_disable (acquire; full DPM teardown; release)
:1258 trinity_dpm_set_power_state (acquire; power-state transition; release)
:1288 trinity_dpm_setup_asic (acquire; sstp/smu-control init; release)
:1300 inside #if 0 (dead code, left untouched by fix.diff)
Contrast within the same file: trinity_notify_message_to_smu at least has an
int return (it merely validates fail-open โ that is DF-5205); the mutex grant
cannot even be checked by callers. And contrast ni.c:41-58: the indirect SMC
SRAM accessors tn_smc_rreg/tn_smc_wreg DO take rdev->smc_idx_lock, so the
DF-2135 class (missing kernel-side idx lock) is NOT present on TN โ the gap
here is host-vs-SMC-firmware exclusivity, which smc_idx_lock does not cover.
Security assessment: reliability fail-open on a hardware wait; no unprivileged
trigger, no attacker-controlled data, no memory-safety primitive. Info severity.
Fix (see fix.diff): int trinity_acquire_mutex() returning 0/-ETIME (backing off
the request on failure), prototype updated in trinity_dpm.h, all six live call
sites in trinity_dpm.c bail out on failure.