diff options
| author | user <user@clank> | 2026-10-08 14:24:59 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-10-08 14:24:59 +0200 |
| commit | f21bfc6dade427b01c5b411e7578b26077aea930 (patch) | |
| tree | 585b46e82de7ef80060249cc5f7dd8c0dfecb7a6 /fw | |
| parent | push further: full crypto op (TEE_GenerateRandom 0x35) EXECUTES but pointer-b... (diff) | |
| download | amd-psp-re-f21bfc6dade427b01c5b411e7578b26077aea930.tar.gz amd-psp-re-f21bfc6dade427b01c5b411e7578b26077aea930.tar.xz amd-psp-re-f21bfc6dade427b01c5b411e7578b26077aea930.zip | |
LEAD: crypto buffer-write is a confused-deputy write into SYS_DRV address space
Empirical ptr sweep of op 0x35 (TEE_GenerateRandom) output buffer answers two reviewer questions:
(1) Bounds are NOT a fixed [0x400000,0x800000): 0x400000 and 0x800000 are BOTH rejected (0xffff000f),
while 0x410500/0x5FF000/0x7FF000 are accepted. Matches the type-5 gate recording [msg-68, TA_end];
with msg at 0x410400 the lower bound is ~0x4103BC, so the window tracks the message location. Earlier
flat-range claim was not empirically verified; corrected.
(2) Writes land in SYS_DRV's address space (confused deputy): 0x410500 accepted + RNG ran (status 0)
but GCP's own 0x410500 stayed 0xAA -> the write does NOT reach GCP physical. 0x5FF000/0x7FF000
accepted + written + CRASHED the PSP (ring dead, grace 0xbb, FE07 garbage). So the client pointer is
validated against GCP's page map but dereferenced in the SYS_DRV handler's context -> write lands in
SYS_DRV's view of the VA; benign where SYS_DRV has innocuous RAM (0x410500), fatal at 0x5FF000/0x7FF000.
Primitive shape: VA-selectable write into SYS_DRV addr space (VA in ~[0x4103BC,0x800000)), data = crypto
op output (random for RNG; attacker-CONTROLLED for a cipher op). SYS_DRV = type-1 fuse-owner, so this
is a strong escalation candidate. Not yet established: what is mapped at those SYS_DRV pages, SYS_DRV-
vs-GCP crash attribution, and a controlled-data (cipher) end-to-end write. Wrote
fw/LEAD-GCP-CRYPTO-BUFFER-WRITE-INTO-SYSDRV.md; hw/ptr_sweep.sh added.
Diffstat (limited to 'fw')
| -rw-r--r-- | fw/LEAD-GCP-CRYPTO-BUFFER-WRITE-INTO-SYSDRV.md | 79 |
1 files changed, 79 insertions, 0 deletions
diff --git a/fw/LEAD-GCP-CRYPTO-BUFFER-WRITE-INTO-SYSDRV.md b/fw/LEAD-GCP-CRYPTO-BUFFER-WRITE-INTO-SYSDRV.md new file mode 100644 index 0000000..7734644 --- /dev/null +++ b/fw/LEAD-GCP-CRYPTO-BUFFER-WRITE-INTO-SYSDRV.md @@ -0,0 +1,79 @@ +# LEAD: crypto buffer-write is a confused-deputy write into SYS_DRV's address space + +## What prompted it + +The GCP-crypto harness showed `TEE_GenerateRandom` (op 0x35) returning status 0 but leaving our +GCP-window output buffer unchanged (pre-filled `0xAA` survived). A reviewer asked: were the pointer +bounds actually `[0x400000,0x800000)`, and do the writes land in SYS_DRV's address space (is anything +mapped there)? Empirical sweep of the RNG output pointer answered both. + +## Sweep (op 0x35 RNG, len 4; each shot ATX-cycled) + + 0x003FF000 status 0xffff000f ring ok REJECT (gate) + 0x00400000 status 0xffff000f ring ok REJECT <- the exact 0x400000 bound is rejected + 0x00410500 status 0x0 ring ok ACCEPT, write benign (GCP buffer unchanged) + 0x005FF000 status 0xbbbbbbbb ring DEAD ACCEPT + WROTE + CRASHED PSP + 0x007FF000 status 0xbbbbbbbb ring DEAD ACCEPT + WROTE + CRASHED PSP + 0x00800000 status 0xffff000f ring ok REJECT + 0x00810000 status 0xffff000f ring ok REJECT + 0x00E00000 status 0xffff000f ring ok REJECT (SYS_DRV code) + 0x00E23398 status 0xffff000f ring ok REJECT (SYS_DRV ACL table) + 0x00E575B8 status 0xffff000f ring ok REJECT (SYS_DRV crypto-ctx table) + 0x01000000 status 0xffff000f ring ok REJECT + +(`0xffff000f` = `dword_E1DF48`, the crypto dispatcher's buffer-gate-reject. `0xbbbbbbbb`/grace `0xbb` += the ROP chain never resumed after `svc 0xf2` -> the write crashed before return; ring dead, next +FE07 returns garbage.) + +## Conclusion 1 -- the accepted range is message-relative, not a fixed constant + +`0x400000` and `0x800000` are BOTH rejected; `0x410500/0x5FF000/0x7FF000` accepted. This matches the +type-5 `svc 0xf2` gate (`sub_22B4`) recording the window as `[v9 = msg-68, tcb[16] = TA_end]`. With +our message at `0x410400`, the lower bound is ~`0x4103BC`, so `0x400000` falls below it and is +rejected. The window's lower edge TRACKS the message location; it is validated against GCP's actually +mapped pages. (Earlier claims of a flat `[0x400000,0x800000)` were not empirically verified; this is +the correction.) + +## Conclusion 2 -- the write lands in SYS_DRV's address space (confused deputy) + +* `0x410500` accepted + RNG ran (status 0), yet GCP's own `0x410500` was UNCHANGED (`0xAA` survived). + So the handler's write does NOT reach GCP's physical memory. +* `0x5FF000`/`0x7FF000` accepted + written + **crashed the PSP**. So the write DOES hit real mapped + memory, and some targets are critical. +* Putting these together: the client pointer is **validated against GCP's page map** but + **dereferenced in the SYS_DRV handler's address-space context**. The write therefore lands in + SYS_DRV's view of that VA -- benign where SYS_DRV has innocuous RAM mapped (`0x410500`), fatal where + it hits critical/structure memory or an unmapped-fault (`0x5FF000`/`0x7FF000`). + +## Why this is a real lead (and the honest caveats) + +**Primitive shape:** a VA-selectable write into SYS_DRV's address space, VA constrained to +`[msg-68, TA_end]` (~`0x4103BC`..`0x800000`, i.e. the GCP TA VA band), with data = the crypto op's +output. With `TEE_GenerateRandom` the data is uncontrolled (random); with a **cipher** op (op +0x06/0x07, output = AES(attacker plaintext, attacker key)) the written bytes would be +attacker-CONTROLLED. SYS_DRV is the type-1 fuse-owner, so a controlled write into its address space is +a strong escalation candidate. + +**Not yet established:** +1. WHAT is mapped at `0x4xxxxx-0x7xxxxx` in SYS_DRV's context (benign RAM at `0x410500`; critical at + `0x5FF000`/`0x7FF000`). Need to map it: is it SYS_DRV heap/stack/page-tables, or a per-RPC bounce + region? A controlled write is only useful if it hits live SYS_DRV state (not a discarded bounce). +2. Whether the crash is a SYS_DRV fault (escalation) vs. some GCP-side effect. The `0x410500` + GCP-unchanged evidence argues SYS_DRV-side, but a controlled-write read-back / behavior-change test + is needed to prove it conclusively. +3. A CONTROLLED-data op end-to-end (cipher needs create + SetOperationKey + CipherDoFinal -- the + three-svc chain; note the buffer-marshal caveat: INPUT buffers may have the same cross-domain issue, + so the plaintext/key would also need to reach the handler, which is the open buffer-marshal + question). + +## Next steps + +* Fine-grained sweep of `[0x4103BC, 0x800000)` to map benign vs crash pages in SYS_DRV's view, and + binary-search the exact window bounds vs the message offset (move `MSG_OFF`, re-sweep lower edge). +* Identify what SYS_DRV structure sits at the benign-writable pages (correlate with the SYS_DRV + memory map / `sub_22B4`'s `sub_434` message-copy target). +* Determine whether a cipher (controlled-output) op can be driven end-to-end despite the input-buffer + marshal question; if so, attempt a controlled write to a mapped SYS_DRV structure and observe a + behavior change (the conclusive escalation test). + +Harness: `hw/gcp_rop_crypto.py` (op 0x35 = `TEE_GenerateRandom`), `hw/ptr_sweep.sh`. |
