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
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
|
"""Round 2: deep field fuzz of the unlocked subcommand parsers (3,7,8,12,17,18),
different seed, avoid cmd 1 (blocking open) and subcmd12 large-N hang. Crash oracle detector."""
import ctypes, struct, time, random
from tinygrad import Device
from tinygrad.runtime.autogen.am import am
from tinygrad.helpers import lo32, hi32
d=Device["AMD"]; adev=d.iface.dev_impl; psp=adev.psp
SZ=ctypes.sizeof(am.struct_psp_gfx_cmd_resp); C2P=90112+64
def crash(): return tuple(adev.rreg(C2P+n) for n in (82,83,84,85,86,88))
def stat(): return int.from_bytes(bytes(adev.vram.view(psp.cmd_paddr,SZ)[:])[864:868],"little")
def alloc(n):
pa=adev.mm.palloc(n,align=0x1000,zero=True); return pa,adev.paddr2mc(pa)
P='/Users/user/dev/amd-psp-re/psp_out/'
def load(cmd,blob):
ap,amc=alloc(0x40000); cp,cmc=alloc(0x8000)
adev.vram.view(ap,len(blob))[:]=blob; adev.gmc.flush_hdp()
adev.vram.view(psp.cmd_paddr,SZ)[:]=b"\x00"*SZ
c=am.struct_psp_gfx_cmd_resp(cmd_id=cmd); t=c.cmd.cmd_load_ta
t.app_phy_addr_hi,t.app_phy_addr_lo=hi32(amc),lo32(amc); t.app_len=len(blob)
t.cmd_buf_phy_addr_hi,t.cmd_buf_phy_addr_lo=hi32(cmc),lo32(cmc); t.cmd_buf_len=0x8000
r=psp._ring_submit(c); return r.resp.session_id,cp
load(am.GFX_CMD_ID_LOAD_ASD, open(P+'asd_full.bin','rb').read())
dtm_sid,dtm_shm=load(am.GFX_CMD_ID_LOAD_TA, open(P+'dtm_full.bin','rb').read())
sid,shm=load(am.GFX_CMD_ID_LOAD_TA, open(P+'hdcp_full.bin','rb').read())
def inv(s,sh,buf,tc):
adev.vram.view(sh,0x8000)[:]=bytes(buf); adev.gmc.flush_hdp()
adev.vram.view(psp.cmd_paddr,SZ)[:]=b"\x00"*SZ
ic=am.struct_psp_gfx_cmd_resp(cmd_id=am.GFX_CMD_ID_INVOKE_CMD); iv=ic.cmd.cmd_invoke_cmd
iv.session_id,iv.ta_cmd_id=s,tc; t0=time.time()
try: psp._ring_submit(ic); return 0, time.time()-t0
except RuntimeError: return stat(), time.time()-t0
except TimeoutError: return "TO", time.time()-t0
def topo(h):
b=bytearray(0x8000); struct.pack_into('<I',b,0,2)
struct.pack_into('<10I',b,0x10,h,1,1,0,0,0,0,0,0,0); inv(dtm_sid,dtm_shm,b,2)
for h in range(8): topo(h)
for dv in (0x11,0x22,0x33):
b=bytearray(0x8000); struct.pack_into('<I',b,0,0x0E); struct.pack_into('<I',b,0xC,dv); inv(sid,shm,b,0x0E)
rng=random.Random(0x1337BEEF); base=crash(); KNOWN={0x40433c,0x40173e,0x0}
print("baseline:",[hex(x) for x in base]); hits=[];n=0;t0=time.time()
SUB=[3,6,7,8,10,12,17,18,20]
try:
for it in range(1500):
b=bytearray(0x8000); struct.pack_into('<I',b,0,0x0F)
struct.pack_into('<I',b,0xC, rng.choice([0,1,2,3])) # slot
sc=rng.choice(SUB)
struct.pack_into('<I',b,0x10, sc) # desc1.id
struct.pack_into('<I',b,0x14, rng.choice([5,6,31,176,200,rng.randint(1,540)])) # desc1.len bounded
struct.pack_into('<I',b,0x18, rng.choice(SUB))
struct.pack_into('<I',b,0x1C, rng.choice([5,6,31,rng.randint(1,300)]))
b[0x28]=sc
for k in range(0x29,0x29+0x180): b[k]=rng.randint(0,255)
if sc==12: b[0x2B]=rng.randint(0,49) # keep N<50 (avoid MAC hang)
r,dt=inv(sid,shm,b,0x0F); n+=1
if r=="TO" or dt>2.0 or not psp.is_sos_alive():
print("!! ANOMALY it=%d sc=%s r=%s dt=%.2f alive=%s crash=%s"%(it,sc,r,dt,psp.is_sos_alive(),[hex(x) for x in crash()])); hits.append(it); break
c=crash()
if c!=base and c[2] not in KNOWN:
print("!! CRASH it=%d sc=%s faultPC=%#x crash=%s"%(it,sc,c[2],[hex(x) for x in c])); hits.append(it); base=c
except Exception as e: print("exc:",repr(e))
print("ran %d in %.1fs hits=%d alive=%s"%(n,time.time()-t0,len(hits),psp.is_sos_alive()))
|