aboutsummaryrefslogtreecommitdiffstats
path: root/hw/tmr_resetup.py
blob: ae3da9062cd165ffeec5cc0c93b635a296ebc9a6 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
#!/usr/bin/env python3
"""Can the host re-SETUP or DESTROY the TMR after boot?

Pass 87 verified the PSP range-checks host buffers against the trusted region. That check is
only meaningful if the host cannot move or remove the region. GFX_CMD_ID_SETUP_TMR (0x5) and
GFX_CMD_ID_DESTROY_TMR (0x7) are host-issuable, so this asks the platform directly.

If a second SETUP_TMR with an attacker-chosen base/size is accepted, the host controls what
counts as trusted memory and the range check becomes bypassable. Ordered least-destructive
first; a wedge is ATX-recoverable.
"""
import sys, time
sys.path.insert(0,'/root/psp/hw')
from tinygrad import Device
import tinygrad.runtime.autogen.am.am as am
from ring_wrap import install
adev=Device["AMD"].iface.dev_impl; psp=adev.psp
submit=install(psp,adev)
def alloc(n):
    pa=adev.mm.palloc(n,align=0x1000,zero=True,boot=False); return pa,adev.paddr2mc(pa)
print('current TMR: paddr=%#x size=%#x'%(psp.tmr_paddr,psp.tmr_size), flush=True)
def send(tag, build):
    c=am.struct_psp_gfx_cmd_resp(); build(c)
    t0=time.time()
    try: r=submit(c); st=r.resp.status&0xFFFFFFFF
    except Exception as e:
        try: st=int(str(e).strip().split()[-1])&0xFFFFFFFF
        except Exception: st=-1
    dt=time.time()-t0
    print('  %-44s -> %#-10x %.1fs%s'%(tag,st,dt,'  <<< HANG' if dt>5 else ''), flush=True)
    return st
# our own scratch region, deliberately NOT the real TMR
pa,mc=alloc(0x100000)
def mk_setup(c):
    c.cmd_id=am.GFX_CMD_ID_SETUP_TMR
    t=c.cmd.cmd_setup_tmr
    t.buf_phy_addr_lo, t.buf_phy_addr_hi = mc&0xFFFFFFFF, mc>>32
    t.buf_size=0x100000
send('SETUP_TMR again, attacker-chosen 1MB region', mk_setup)