blob: aa1cbc7c87779fb5a8c0d1ec985892ed0b09d698 (
plain) (
blame)
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
|
# RAS error-injection range check — empirically mapped, protects the TMR exactly
## What this closes
RAS cmd 2 (TRIGGER_ERROR) is host-reachable (see
FINDING-RAS-IS-REACHABLE-AND-AUDITED.md) and feeds a **host-supplied 64-bit DRAM
address** into the UMC error-injection address registers:
ras_parse_trigger_request -> ras_dram_range_config -> ras_configure_blocks
v5 = host 64-bit (request+16/+20)
v33 = v33 & 0xFFFFF000 | WORD2(v5) & 0xFFF -> reg 0x48FC0574
v32 = v5 & 0xFFFFFFC1 | ... | 1 -> reg 0x48FC0570
If unvalidated, the host could inject ECC/parity errors into PSP-trusted DRAM.
## A wrong hypothesis I formed, and how it died
`dram_range_query` (SYS_DRV RPC 0x7008) returns:
0xFFFF0001 address found in a range-table entry
0 address NOT found in any entry (also: uninit / recovery)
0xFFFF0006 address has bits set above bit 43
and `ras_dram_range_config` does `BL ...7008 ; CBZ R0 -> proceed`. Reading the
table as a list of **allowed** ranges, that is inverted — "not found" would
mean "proceed". I was about to write that up as a vulnerability.
It is wrong. The table lists **protected** ranges, so non-zero means "you hit a
protected region, refuse". The polarity is correct.
## Empirical proof — the boundary is the TMR, to the page
`psp.tmr_paddr = 0x300000`, `tmr_size = 0x1300000`, so TMR = [0x300000,0x1600000).
0x00002ff000 -> allow (one page below TMR)
0x0000300000 -> REJECT (exact TMR base)
0x0000301000 -> REJECT
0x0000400000 -> REJECT
0x0000800000 -> REJECT
0x0000c00000 -> REJECT
0x0001000000 -> REJECT
0x00015ff000 -> REJECT (last page inside)
0x0001600000 -> REJECT (boundary; compare is inclusive)
0x0001601000 -> allow (one page past TMR)
0x0001700000 -> allow
0x0010000000 -> allow
Also correct: an address with bits above bit 43 (`0x1ffffffff000`) is rejected
(`0xFFFF0006` path). Ordinary VRAM we own (`0x9a000`, `0x1648000`) is allowed —
injecting into ordinary VRAM is the legitimate RAS use case.
## Verdict
The host can aim RAS error injection at ordinary VRAM (by design) but **cannot
aim it at the PSP TMR**. The protection is exact at both edges. No bug.
## Method note
The disassembly alone genuinely reads as an inverted check; only the hardware
sweep distinguished "allowed-list" from "protected-list" semantics. Static
reasoning about a range table's *polarity* is not safe without knowing what the
table contains — and the contents were only observable at runtime.
|