aboutsummaryrefslogtreecommitdiffstats
path: root/fw
diff options
context:
space:
mode:
authoruser <user@clank>2026-10-08 14:24:59 +0200
committeruser <user@clank>2026-10-08 14:24:59 +0200
commitf21bfc6dade427b01c5b411e7578b26077aea930 (patch)
tree585b46e82de7ef80060249cc5f7dd8c0dfecb7a6 /fw
parentpush further: full crypto op (TEE_GenerateRandom 0x35) EXECUTES but pointer-b... (diff)
downloadamd-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.md79
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`.