<feed xmlns='http://www.w3.org/2005/Atom'>
<title>amd-psp-re.git/hw/gcp_fe09_configinit_offset_write.py, branch main</title>
<subtitle>AMD PSP reverse engineering, emulator and vulnerability research</subtitle>
<id>https://git.sl0p.foo/amd-psp-re.git/atom/hw/gcp_fe09_configinit_offset_write.py?h=main</id>
<link rel='self' href='https://git.sl0p.foo/amd-psp-re.git/atom/hw/gcp_fe09_configinit_offset_write.py?h=main'/>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/amd-psp-re.git/'/>
<updated>2026-10-01T22:21:50Z</updated>
<entry>
<title>GCP FE09 ConfigureInitialize: host-chosen write offset, confirmed on silicon, not corruption</title>
<updated>2026-10-01T22:21:50Z</updated>
<author>
<name>user</name>
<email>user@clank</email>
</author>
<published>2026-10-01T22:21:50Z</published>
<link rel='alternate' type='text/html' href='https://git.sl0p.foo/amd-psp-re.git/commit/?id=463c1410625fcb01d4a7fac5307e08d56edbf930'/>
<id>urn:sha1:463c1410625fcb01d4a7fac5307e08d56edbf930</id>
<content type='text'>
Found a genuine TA-side defect, confirmed it on hardware, then established it is not a memory
corruption primitive. All three steps recorded.

The defect: gcp_ConfigureInitialize takes a 32-bit write displacement straight from the request at
params+0x828 and never bounds it, then stores four bytes of zero at params+1048+displacement. The
auth-state test inside the function fails on a fresh context and its failure branch converges on the
same store, so no session state is needed. Upstream, gcp_cmdFE09 reaches it with params+0x820 == 1
through comparisons that have host-controlled values on both sides -- params+0x828 against
params+0x818, params+0x82C against params+0x414 -- so none of them is a bound. Neither 0x828 nor
0x818 is ever written by GCP; both are purely host-supplied.

Confirmed on Navi 31 with GCP 22.0.4.50, no session setup, one invoke per displacement: the zeroed
dword lands at exactly 0x418 + D for D of 0x0, 0x100, 0x200 and 0x400, moving with D. So the
displacement really is host-controlled in running firmware.

Not corruption: with the declared window shrunk to 0x3000 over an 0x8000 allocation, a target at
0x4000 is outside the window but still in memory we own, and the write does not land. Reproduced
twice. The PSP enforces the declared window, backstopping the TA exactly as the loader's one-page
floor backstops the four TAs with no length check. Inside the window the write only touches the
host's own buffer.

One misreading corrected in the document: the failing statuses looked like they encoded the faulting
page, 0x141/0x151/0x161 for 0x4000/0x5000/0x6000. They do not. They increment by 0x10 on every
invoke regardless of displacement, and a later in-window target failed too, so the first
out-of-window attempt poisons the session and the status is a counter.

Side effect worth knowing: every out-of-window attempt left the PSP dead, ring unresponsive and
AM_RESET useless because the SMU's mode1_reset also timed out. Three ATX power cycles during this
work. Distinct trigger from the cmd_buf_len=0 wedge, same DoS class, so it is recorded in this
document rather than as a separate finding. Card left healthy and verified.
</content>
</entry>
</feed>
