diff options
| author | user <user@clank> | 2026-09-30 03:38:10 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-30 03:38:10 +0200 |
| commit | 3cdba2f291e48b97db299e9df2e213fdc07f648c (patch) | |
| tree | d10cf6e952fb53b64c865d988360026b09c58dae | |
| parent | finding: the ring frame's fence address is not range-checked, unlike the comm... (diff) | |
| download | amd-psp-re-3cdba2f291e48b97db299e9df2e213fdc07f648c.tar.gz amd-psp-re-3cdba2f291e48b97db299e9df2e213fdc07f648c.tar.xz amd-psp-re-3cdba2f291e48b97db299e9df2e213fdc07f648c.zip | |
record the ring-frame passes in the audit log and add the sixth trigger to the report
The audit log gains the ring-frame section: the processor writes a host-chosen value to a
host-chosen address, a destination inside the trusted region is accepted where the same
address as a command buffer is rejected, and a null destination is a sixth wedge. It also
records that corruption is not demonstrated, with the dense functional test that argues
hardware protection covers the missing check.
Three process notes are kept because each would have produced a wrong entry: the response
status was first read from a guessed offset inside another union member and reported a
completed command as never completed, the first functional spray would have hit the load
session wall, and its coverage was far too thin to support the negative it printed.
The denial-of-service report gains the sixth trigger with its recovery requirement and
fix.
| -rw-r--r-- | fw/AUDIT-TA-MEMSAFETY-HUNT.md | 37 | ||||
| -rw-r--r-- | fw/REPORT-PSP-DOS-TRIGGERS.md | 12 |
2 files changed, 49 insertions, 0 deletions
diff --git a/fw/AUDIT-TA-MEMSAFETY-HUNT.md b/fw/AUDIT-TA-MEMSAFETY-HUNT.md index 180ce4d..effce7c 100644 --- a/fw/AUDIT-TA-MEMSAFETY-HUNT.md +++ b/fw/AUDIT-TA-MEMSAFETY-HUNT.md @@ -4500,3 +4500,40 @@ command buffer, so overlap is harmless. ## Objective status after a hundred and seventeen passes **Not met.** Aliasing joins the list of correctly handled cases. No memory corruption. + +================================================================================ +# Passes 118-124: the ring frame itself — a real missing check, and a sixth wedge + +Every earlier pass varied command *content*. The **ring frame** (`psp_gfx_rb_frame`) is +equally host-controlled and carries `fence_addr` — **an address the PSP writes to** — plus +`fence_value`, the value it writes. `cmd_buf` was range-checked against the TMR in pass 87; +`fence_addr` had never been tested at all. + +**Confirmed [HW]:** + +1. The PSP writes a host-chosen value to a host-chosen address (`hw/fence_write.py`). +2. **`fence_addr` inside the TMR is accepted** — the command completes and the PSP stays + healthy, where the same address in `cmd_buf` is *rejected*. **The check on one + destination is missing on the other.** +3. **`fence_addr = 0` is a sixth DoS trigger**: command completes, heartbeat freezes at an + identical value, card unusable (`SMU msg 0x2 timeout`), ATX cycle required. + +**Not demonstrated: corruption.** Host reads of the TMR return `0xffffffff` so read-back +cannot settle it, and a dense functional test — 16,384 host-chosen dwords at 64-byte +granularity across the **whole first megabyte** of the TMR, where a loaded TA image lives — +leaves the TA's behaviour identical. Hardware protection most likely covers the missing +software check. Written up in `fw/FINDING-PSP-FENCE-ADDR-UNVALIDATED.md`. + +Process notes worth keeping: the first version of this test read the response status from a +**guessed** offset (`+0x10`, actually inside the `cmd` union) and reported "command never +completed" for a case that had completed — the real offset is **864**, obtained from the +struct rather than assumed. The first functional spray used `LOAD_TA` per write and would +have hit the 28-load session wall, and its 300-dwords-over-19-MB coverage was far too thin +to support the negative it printed; both were fixed before the result was recorded. + +## Objective status after a hundred and twenty-four passes + +**Not met.** A genuine missing validation was found in a structure never previously +examined, and it is the closest thing to a write primitive in this audit — but on this part +the write does not land, so it is a defence-in-depth gap, not an exercisable +memory-corruption primitive. diff --git a/fw/REPORT-PSP-DOS-TRIGGERS.md b/fw/REPORT-PSP-DOS-TRIGGERS.md index 5fe6ddd..88feae5 100644 --- a/fw/REPORT-PSP-DOS-TRIGGERS.md +++ b/fw/REPORT-PSP-DOS-TRIGGERS.md @@ -141,3 +141,15 @@ So the missing aperture check yields a **hang on an invalid address**, not a wri unintended one. On this single-tenant part every valid address belongs to us, so a cross-context directed write cannot be demonstrated here; the VMC faults show the hardware enforcement that would apply. + +## Sixth trigger (added): ring frame `fence_addr = 0` + +`hw/fence_tmr2.py zero`. The command **completes** (response written `0x0`), then the sOS +heartbeat `regMP0_SMN_C2PMSG_81` stops at an identical value and the card is unusable +(`SMU msg 0x2 timeout`); `work/atx_power.py cycle 25` is required. + +The PSP dies *after* completing the command, while writing the fence value to an unmapped +address. Fix: reject an unmapped or null `fence_addr` with a status rather than faulting. + +See `FINDING-PSP-FENCE-ADDR-UNVALIDATED.md`, which also records that `fence_addr` is not +range-checked against the trusted region while `cmd_buf` is. |
