Skip to content

Commit 89abdc0

Browse files
committed
Cleanup page fault code
1 parent ab0ab2e commit 89abdc0

File tree

2 files changed

+47
-49
lines changed

2 files changed

+47
-49
lines changed

panda/python/examples/fault.py

Lines changed: 35 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,19 +1,33 @@
11
from pandare import Panda
22

3-
panda = Panda(generic="i386")
3+
panda = Panda(generic="arm")
4+
#panda = Panda(generic="i386")
5+
#panda = Panda(generic="x86_64")
6+
#panda = Panda(generic="mips64")
7+
48
panda.load_plugin("syscalls2", {"load-info": True})
59

610
@panda.queue_blocking
711
def drive():
812
panda.revert_sync('root')
9-
print(panda.run_serial_cmd("md5sum $(which whoami); find /etc/ | md5sum"))
13+
print(panda.run_serial_cmd("md5sum $(which whoami); find /etc/ | md5sum; apt-get update -yy"))
1014
panda.end_analysis()
1115

16+
last_fault = None
17+
def fault(panda, cpu, addr, pc):
18+
global last_fault
19+
if last_fault == addr:
20+
raise MemoryError(f"Double fault of {addr:x}")
21+
last_fault = addr
22+
panda.libpanda.panda_page_fault(cpu, addr, pc)
23+
24+
1225
@panda.ppp("syscalls2", "on_all_sys_enter2")
1326
def all_sys(cpu, pc, call, rp):
1427
args = panda.ffi.cast("target_ulong**", rp.args)
1528

16-
print(f"{pc:#08x} (from block starting at {panda.current_pc(cpu):#08x}): {panda.ffi.string(call.name).decode()}(", end="")
29+
sc_name = panda.ffi.string(call.name).decode() if call.name != panda.ffi.NULL else 'err'
30+
print(f"{pc:#08x} (from block starting at {panda.current_pc(cpu):#08x}): {sc_name}(", end="")
1731
if call.nargs == 0:
1832
print(")", end="")
1933

@@ -25,29 +39,29 @@ def all_sys(cpu, pc, call, rp):
2539
if call.argt[i] not in [0x20, 0x21, 0x22]:
2640
val = int(panda.ffi.cast("unsigned int", args[i]))
2741
print(hex(val), end="")
42+
continue
43+
44+
# It's a pointer type
45+
addr = int(panda.ffi.cast("unsigned int", args[i]))
46+
if addr < 0xFFFF:
47+
# Probably not a pointer?
48+
print(hex(addr), end="")
2849
else:
29-
addr = int(panda.ffi.cast("unsigned int", args[i]))
30-
if addr < 0xFFFF:
31-
# Probably not a pointer?
32-
print(hex(addr), end="")
33-
else:
34-
try:
35-
mem = panda.virtual_memory_read(cpu, addr, 8)
36-
except ValueError:
37-
# ignore other args until fault is resolved
50+
try:
51+
s = panda.read_str(cpu, addr)
52+
except ValueError:
53+
# This argument can't be read - let's raise a fault on it
54+
if last_fault != addr:
3855
print(f"{addr:#x} => Can't read - INJECT PANDA PAGE FAULT") # newline
56+
fault(panda, cpu, addr, pc)
57+
return # Raised a fault, hope it's gonna work
58+
else:
59+
s = "still can't read"
3960

40-
# DO FAULT
41-
panda.libpanda.panda_page_fault(cpu, addr, pc)
42-
# After fault is handled, we'll then re-run the syscall insn (and the TCG-based callback)
43-
break
44-
45-
# No fault
46-
print(f"{addr:#x} => {repr(panda.read_str(cpu, addr))}", end="")
61+
# No fault
62+
print(f"{addr:#x} => {repr(s)}", end="")
4763

4864
print(sep, end="") # , or )
49-
else:
50-
print()
5165

5266
@panda.ppp("syscalls2", "on_all_sys_return2")
5367
def all_ret(cpu, pc, call, rp):

panda/src/panda_api.c

Lines changed: 12 additions & 28 deletions
Original file line numberDiff line numberDiff line change
@@ -291,8 +291,10 @@ void _panda_set_library_mode(const bool b) {
291291

292292
// Raise a page fault on address, then return execution to retaddr
293293
void panda_page_fault(CPUState* cpu, target_ulong address, target_ulong retaddr) {
294+
// Update the CPUArchstate so the PC is the desired return address, then call
295+
// tlb_fill. This ensures that we always go back to retaddr
294296

295-
#ifdef TARGET_I386
297+
#if defined(TARGET_I386) //|| defined(TARGET_X86_64)
296298
CPUX86State *env = cpu->env_ptr;
297299

298300
// We want to set up CPU state with x86_cpu_handle_mmu_fault
@@ -301,34 +303,16 @@ void panda_page_fault(CPUState* cpu, target_ulong address, target_ulong retaddr)
301303
// instead of restarting the block
302304
env->eip = retaddr;
303305
tlb_fill(cpu, address, MMU_DATA_LOAD, 0, retaddr);
306+
//#elif defined (TARGET_ARM)
307+
// CPUARMState *env = cpu->env_ptr;
308+
// env->pc = retaddr;
309+
// tlb_fill(cpu, address, MMU_DATA_LOAD, 0, retaddr);
310+
304311
#elif defined(TARGET_MIPS)
305312
CPUMIPSState *env = cpu->env_ptr;
306-
CPUState *cs = CPU(mips_env_get_cpu(env));
307-
int exception = 26; //26 is EXCP_TLBL. 27 is TLBS
308-
int error_code = 1; // EXCP_TLB_NOMATCH;
309-
310-
env->CP0_BadVAddr = address;
311-
env->CP0_Context = (env->CP0_Context & ~0x007fffff) |
312-
((address >> 9) & 0x007ffff0);
313-
target_ulong val = (env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask) |
314-
(env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) |
315-
(address & (TARGET_PAGE_MASK << 1));
316-
317-
// XXX skip panda callback here - unlike in mips/helper.c
318-
env->CP0_EntryHi = val;
319-
320-
#if defined(TARGET_MIPS64)
321-
env->CP0_EntryHi &= env->SEGMask;
322-
env->CP0_XContext =
323-
/* PTEBase */ (env->CP0_XContext & ((~0ULL) << (env->SEGBITS - 7))) |
324-
/* R */ (extract64(address, 62, 2) << (env->SEGBITS - 9)) |
325-
/* BadVPN2 */ (extract64(address, 13, env->SEGBITS - 13) << 4);
326-
#endif
327-
cs->exception_index = exception;
328-
env->error_code = error_code;
329-
330-
// Break out of the current block so the fault can be handled, then return to our current addr
331-
cpu_loop_exit_restore(cs, retaddr);
332-
313+
env->active_tc.PC = retaddr;
314+
tlb_fill(cpu, address, MMU_DATA_LOAD, 0, retaddr);
315+
#else
316+
printf("ERROR: Unsupported architecture for panda_page_fault\n");
333317
#endif
334318
}

0 commit comments

Comments
 (0)