aboutsummaryrefslogtreecommitdiffstats

LEAD: use the anti-rollback gap to make the confirmed count-underflow reachable

Status: CLOSED NEGATIVE on its central hypothesis. The rollback does not make the count-underflow reachable. Retained because the reasoning and artifacts are reusable, and because the rollback finding itself stands independently.

Why this lead exists

Two separate results now sit next to each other:

  1. A confirmed corruption defect that is not reachable. sub_E04B68 (and clone sub_E04DFC) read a count from buf+0x88 unvalidated, use it unclamped for memcpy(glob+0x6c0, buf+8, count), then compute 0x400 - count unsigned for a second copy. Verified 14/14 mechanically and reproduced in emulation through the real dispatcher. Not host-reachable in 49.0.54: planting the count needs 0x8c bytes into the 0x33 descriptor helper (sub_E1EA54 -> sub_E18EAC, sole writer of channel+0x70), and no corpus TA delivers that much - OC 0x30 is a firmware global, AUC/OPM/FP give 0x10, GCP is auth-gated, MERIT gated. (fw/CANDIDATE-SYSDRV-E04B68-COUNT-UNDERFLOW.md)

  2. No anti-rollback. An older AMD-signed SYS_DRV boots and services requests on a part shipping 49.0.54 - 49.0.37 and 49.0.47 both verified from a cold power cycle. (fw/FINDING-PSP-SYSDRV-NO-ANTIROLLBACK.md)

The defect's unreachability is a property of one specific build's gates, and rollback lets the attacker choose the build. So the question is precise:

In 49.0.37 or 49.0.47, does any path deliver >= 0x8c caller-controlled bytes into the payload helper that writes the slot staging buffer - is the front half open in an older build?

If yes, rollback plus the existing defect is an exercisable memory-corruption primitive: choose the old build, open the front half, plant the count, trigger the unclamped copy.

Closed: the required payload does not shrink in an older build

First, a correction to this lead's own logic. The 0x8c requirement is TA-side - how many caller-controlled bytes a TA pushes into the payload helper - and TA choice is already free, since 63 corpus TA builds load on this part and the front-half survey covered all of them. So rolling back SYS_DRV only helps if the older build needs a smaller payload, i.e. reads the count at a lower offset.

It does not. Scanning both older images for every LDR.W rD,[rN,#imm12], grouped by immediate:

build LDR.W sites distinct immediates sites with imm = 0x88
49.0.37 923 260 15
49.0.47 925 265 14

Those sites cluster at file offsets 0x49e8, 0x4a10 and 0x4c7a-0x4cd8 (v37; v47 identical shifted +0xc). At the established load base 0xE00100, the two defective functions in the current build sit at file offsets 0x4A68 (sub_E04B68) and 0x4CFC (sub_E04DFC) - the same two clusters. The count is read at +0x88 in the older builds too, so the payload needed is still 0x8c and the front-half blocker is unchanged.

Caveat on strength: the offset-to-function mapping is inferential (base arithmetic plus cluster position), not a confirmed symbolisation of the older images. The conclusion therefore rests on the weaker, safer claim that +0x88 count reads are still present in the same region of both older builds, so there is no evidence the requirement shrank - and a lead needs positive evidence to stay open.

What would still be needed (if resumed)

  • Load data/rollback/sysdrv_v37.bin and sysdrv_v47.bin, taking the load base from the segment table, never from a printed address (the 0x100 trap; current build is 0xE00100).
  • Re-run the validated detectors (fw/ta_copylen_slice.py, fw/ta_bufferfield_audit.py, fw/ta_bufferfield_xfn.py) and confirm each rediscovers a known defect in that image before trusting any negative from it.
  • Locate the older equivalents of sub_E087E4 (request entry), sub_E1DC30 (53-opcode family), sub_E1EA54/sub_E18EAC (the 0x33 payload helper) and compare the length gate.
  • Also check whether sub_E04B68's count read is already clamped in an older build, which would invert the picture.

Both images are plaintext - entropy 6.74 / 6.77 over the body versus ~8.0 for encrypted - so they are directly analyzable.

Honest caveats

  • The defect shape was found in all 31 SYS_DRV builds, so the back half is presumably open in the older ones - but that must be confirmed per image, not assumed.
  • A v37/v47 string diff shows no added error messages, so there is no cheap signal that a bounds fix landed in that window; this needs real code comparison.
  • Rollback changes which SYS_DRV runs. The front-half blocker is partly about what TAs send, and TAs load separately - so the thing to look for is an older SYS_DRV with a laxer gate, not an older TA.

Artifacts

data/rollback/sysdrv_v37.bin (0x310025, 157,584 B, sha 8ff372e135a0342b8d3b...) and data/rollback/sysdrv_v47.bin (0x31002f, 157,584 B, sha 1ec6756ce3e37cea207b...), both hashed into data/MANIFEST.sha256, extracted from public linux-firmware psp_13_0_0_sos.bin by hw/rollback_inspect.py.