1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
|
# FINDING: the PSP ring base is accepted misaligned, then wedges on first submit
**Evidence class: [HW]** — Navi 31 / RX 7900 XTX, sOS/SYS_DRV 0.49.0.54.
**Status: missing check CONFIRMED. Eighth DoS trigger. No memory corruption.**
## The ring-creation surface
The ring is created by writing its base (`C2PMSG_69/70`), its size (`_71`) and a create
command to `_64`, whose low 16 bits are the PSP's own status — so the firmware reports
acceptance directly and nothing has to be inferred. `hw/ring_create_fuzz.py`, one case per
fresh boot:
| case | status | outcome |
|---|---|---|
| control: correct base and size | `0x0` | accepted, commands execute |
| size `0` | **`0x4`** | rejected |
| size `1` | **`0x4`** | rejected |
| size `0xFFFFFFFF` | **`0x4`** | rejected |
| size `0x80000000` | **`0x5`** | rejected |
| **base inside the TMR** | **`0xa`** | **rejected — explicitly range-checked** |
| base `0` | — | rejected (ready bit never set) |
| **base misaligned (+1)** | **`0x0`** | **ACCEPTED**, then wedges |
This validation layer is otherwise **good**: four distinct rejection codes, and the trusted
region is explicitly excluded from the ring base.
## The defect
`hw/ring_unalign.py` runs the aligned control **first in the same boot** — it succeeds, the
heartbeat advances — and only then creates a ring at `base + 1`:
```
aligned base (control) create status=0x0 ACCEPTED submit resp=0x0 hb_advancing=True
base+0x1 create status=0x0 ACCEPTED submit resp=TIMEOUT hb_advancing=False
```
The misaligned base is **accepted at creation** and the PSP then **dies on the first submit**.
Because the control passed moments earlier in the same boot, this is not an inherited dead
PSP — the failure mode that produced phantom hits twice in this audit.
## Why it is a real inconsistency, not a policy choice
Alignment *is* enforced everywhere else in this interface:
* `cmd_buf` misaligned ⇒ rejected `0x6` (even at `+0x800`),
* TA image misaligned ⇒ rejected `0x34`,
* ring base inside the trusted region ⇒ rejected `0xa`,
* ring size bogus ⇒ rejected `0x4` / `0x5`.
Only the ring base's **alignment** is unchecked, and the consequence is deferred to first use.
This is the same shape as `LOAD_TA` with `cmd_buf_len = 0` (accepted at load, hangs on first
invoke): a parameter validated incompletely, with the failure surfacing later as a hang.
## Not memory corruption
The PSP hangs; it does not write anywhere it should not. Recovery requires
`work/atx_power.py cycle 25`; GPU/AM reset is insufficient.
## Suggested fix
Check the ring base's alignment at creation and reject it with a status, as the size and the
trusted-region overlap already are.
|