DF-5205 / analysis.txt
DF-5205 annotated walkthrough — trinity_notify_message_to_smu() fail-open
Audit target: sys/dev/drm/radeon/trinity_smc.c (DragonFlyBSD pass 2, GLM 5.3)
[L30] static int trinity_notify_message_to_smu(struct radeon_device *rdev, u32 id)
Only SMC transport in the file; all 10 exported wrappers route through it.
[L35] WREG32(SMC_MESSAGE_0, id);
id is always a compile-time constant (ppsmc.h: PPSMC_MSG_* 0x100..0x12x)
or, for the payload registers, a driver-derived level count. NOT user input.
[L36-40] for (i = 0; i < rdev->usec_timeout; i++) { if (RREG32(SMC_RESP_0) != 0) break; udelay(1); }
usec_timeout = RADEON_MAX_USEC_TIMEOUT = 100000 (radeon.h:131; radeon_device.c:1300)
-> up to 100 ms busy-wait. On timeout the loop simply exits; no error state kept.
[L41] v = RREG32(SMC_RESP_0);
RAW 32-bit read. Trinity has NO SMC_RESP_MASK (cikd.h:431's 0xffff is CIK-only;
the kv twin kv_smc.c:38,42 masks). Stray upper bits are indistinguishable here.
[L43] if (v != 1) {
[L44-46] if (v == 0xFF) { DRM_ERROR("SMC failed to handle the message!"); return -EINVAL; }
[L47-49] else if (v == 0xFE) { DRM_ERROR("Unknown SMC message!"); return -EINVAL; }
[L50] } <-- NO else. Falls through for v==0 (TIMEOUT) and v in 0x02..0xFD and any
value with stray high bits (e.g. 0x00010001).
[L53] return 0; <-- SUCCESS reported for every unhandled case. THE FAIL-OPEN.
Consumers (trinity_dpm.c):
:59 trinity_dpm_bapm_enable -> PPSMC_MSG_{Enable,Disable}BAPM
:64 trinity_dpm_config -> SMU_SCRATCH_0=0/1 + PPSMC_MSG_DPM_Config
:74 trinity_dpm_force_state -> SMU_SCRATCH_0=n + PPSMC_MSG_DPM_ForceState
:81 trinity_dpm_n_levels_disabled -> SMU_SCRATCH_0=n + PPSMC_MSG_DPM_N_LevelsDisabled
:88 trinity_uvd_dpm_config -> PPSMC_MSG_UVD_DPM_Config
:93 trinity_dpm_no_forced_level -> PPSMC_MSG_NoForcedLevel
:98 trinity_dce_enable_voltage_adjustment -> PPSMC_MSG_DCE_{Allow,Remove}VoltageAdjustment
:107 trinity_gfx_dynamic_mgpg_config -> PPSMC_MSG_PG_SIMD_Config
Downstream: trinity_dpm_enable (trinity_dpm.c:1105-1132) returns 0 unconditionally
at :1131 regardless of message outcomes -> radeon PM core marks DPM enabled on
hardware that never acked. Same for the enable/disable/thermal paths at
trinity_dpm.c:1099-1101, 1258-1273.
Family precedent: DF-5137 (radeon kv_smc.c:30-50, same shape but MASKED),
DF-5132 (amdgpu kv_smc.c). Trinity is strictly worse: unmasked response read.
Security assessment: reliability fail-open only. No memory-safety primitive, no
attacker-controlled data on the path, no unprivileged trigger. Info severity.
Fix (see fix.diff): catch-all `return -EINVAL` for any v != 1 outside the two
defined SMC error codes.