diff options
| author | user <user@clank> | 2026-09-29 14:05:16 +0200 |
|---|---|---|
| committer | user <user@clank> | 2026-09-29 14:05:16 +0200 |
| commit | 413925356e78d4098fd8214eb2823e180ba47291 (patch) | |
| tree | 033393ed396ba9356ff4ea9fe10c9e42974216b3 | |
| parent | fw: measure annotation coverage (238/622 fns) and document the stale-.i64 wor... (diff) | |
| download | amd-psp-re-413925356e78d4098fd8214eb2823e180ba47291.tar.gz amd-psp-re-413925356e78d4098fd8214eb2823e180ba47291.tar.xz amd-psp-re-413925356e78d4098fd8214eb2823e180ba47291.zip | |
ASD 0x301 is correctly bounded: OPM lead deflates to reachability-without-impact
Settled the last open question on the OPM path. The length is indeed host
derived: ASD's handler takes it in arg1, OPM's thunk maps R1 to arg1, and R1 is
loaded from host_params+0x1018 with OPM only checking it non-zero, while the
source is host_params+0x101C.
But ASD bounds it correctly. The handler memsets a 0x1400-byte destination, then
subtracts 0x30 from the length and rejects unsigned-above 0x13D0, so the
accepted range is 0x30 to 0x1400 inclusive, exactly the buffer size, and a length
below 0x30 wraps and is rejected too. Two further gates follow. So the host
controls content and length within range and the copy fits; this is not a
memory-corruption primitive.
Also corrected our own phrasing, which is what sent me down this path: the
existing finding describes 0x301 as a content-controlled write of up to 5120
bytes, and 5120 is 0x1400, the size of the bounded destination rather than an
overrun. Read quickly it sounds like an overflow.
Net for OPM: reachability real, impact nil, recorded precisely so a proven
reachability is not allowed to imply a vulnerability. The GCP to ASD 0x202 result
is unaffected, being an uninitialised-memory read whose destination is the host
page and whose blocker is ASD's crypto gate rather than a bound.
| -rw-r--r-- | fw/AUDIT-NEW-TAS-RE.md | 64 |
1 files changed, 64 insertions, 0 deletions
diff --git a/fw/AUDIT-NEW-TAS-RE.md b/fw/AUDIT-NEW-TAS-RE.md index 6f0273e..9879164 100644 --- a/fw/AUDIT-NEW-TAS-RE.md +++ b/fw/AUDIT-NEW-TAS-RE.md @@ -665,3 +665,67 @@ Two traps while diagnosing it: Re-annotating a TA after deleting its database costs one scripted pipeline run (`ta_symbols` -> `annotate_ta` -> `ta_rpc_names` -> `ta_final_note`), which is exactly why those steps are scripts and not hand-work. + +================================================================================ +# ASD 0x301 is correctly bounded — the OPM lead deflates + +Chasing the last open question on the OPM path: is the 0x301 write length host-derived? +**Yes** — and it does not matter, because ASD bounds it. + +## The length is host-controlled + +ASD's 0x301 handler `sub_D132A8` takes the length in **arg1**: + +``` +0xd132b4 MOV R4, R1 ; r4 = arg1 +... +0xd132fc MOV R2, R4 +0xd132fe BLX memcpy ; length = arg1 +``` + +OPM's thunk stores `{R0,R1,R2,R3}` into `req[1..4]`, so `arg1 = R1` at the call site, and +at `0x401536`: + +``` +0x401532 MOVW R0, #0x1018 +0x401536 LDR R1, [R7,R0] ; R1 = *(host_params + 0x1018) <- the length +0x401538 CMP R1, #0 ; BEQ skip ; only checked non-zero by OPM +0x40153c R2 = R7 + 0x101C ; source = host_params + 0x101C +0x401544 BL opm_asd_rpc_301 +``` + +So the host supplies both the source bytes **and** the length, and OPM itself only checks +the length is non-zero. + +## ASD checks it properly, and the check is correct + +``` +0xd132c4 MOV R0, SP ; MOV.W R1, #0x1400 ; BL memset ; 0x1400-byte destination +0xd132ce SUB.W R1, R4, #0x30 +0xd132d2 MOVW R2, #0x13D0 +0xd132d8 CMP R1, R2 +0xd132da BHI reject ; 0x30 <= len <= 0x1400 +``` + +`0x13D0 + 0x30 = 0x1400`, exactly the buffer size, and because the comparison is unsigned +after subtracting `0x30`, a length below `0x30` wraps to a huge value and is also rejected. +Two further gates follow (`R6 != 0`, a helper at `0xD12E90`, and a bound on `R5`). + +**So this is not a memory-corruption primitive.** The host controls up to `0x1400` bytes of +*content* and the length within `[0x30, 0x1400]`, and the copy fits its destination. + +## Correcting our own phrasing + +`FINDING-ASD-IS-DRIVER-CLASS-NOT-INVOKABLE.md` lists this as +*"`asd 0x301` — content-controlled write of up to 5120 bytes"*, in a sentence about defects +that "would be host-reachable if the host could invoke ASD". Read quickly — as I did when +I first flagged OPM — that sounds like an overflow worth chasing. It is not: 5120 = `0x1400` +is the **size of the bounded destination**, not an overrun. The wording describes attacker +*content*, and the bound was never claimed to be missing. + +Net result for the OPM path: **reachability real, impact nil.** Worth recording precisely +because the reachability work (host params -> ASD 0x301 with host length) is genuinely new, +and the temptation is to let a proven reachability imply a vulnerability. It does not here. + +The GCP -> ASD 0x202 result is unaffected: that one is an *uninitialised-memory read*, its +destination is the host page, and its blocker is ASD's crypto gate rather than a bound. |
