From 27960a3cc407d7039e8145748c6d36bd63d9e0c2 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 3 Jul 2019 16:24:37 +0200 Subject: [PATCH] WIP(ptrace): Test memory access --- src/main.rs | 37 +++++++++++++++++++++++++++++++++++-- 1 file changed, 35 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 79fd3e1..bea534c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -54,7 +54,8 @@ fn page_fault_test() -> Result<(), String> { fn ptrace() -> Result<(), String> { use std::{ fs::File, - io::prelude::*, + io::{prelude::*, SeekFrom}, + mem, os::{raw::c_int, unix::io::{AsRawFd, FromRawFd}} }; @@ -83,6 +84,12 @@ fn ptrace() -> Result<(), String> { pop rax pop rax + // Test memory access + push 3 + push 2 + push 1 + add rsp, 3 // pop 3 items, ignore values + // Test behavior if tracer aborts a breakpoint before it's reached call wait_for_a_while @@ -131,6 +138,7 @@ fn ptrace() -> Result<(), String> { .map_err(|e| format!("dup failed: {}", e))? as c_int ) }; + let mut mem_file = File::open(format!("proc:{}/mem", pid)).map_err(|e| format!("open failed: {}", e))?; println!("Schedule restart of process when resumed..."); syscall::kill(pid, syscall::SIGCONT).map_err(|e| format!("kill failed: {}", e))?; @@ -153,7 +161,7 @@ fn ptrace() -> Result<(), String> { }; println!("Stepping away from the syscall instruction..."); - let _ = next(syscall::PTRACE_SINGLESTEP)?; + next(syscall::PTRACE_SINGLESTEP)?; println!("Testing basic singlestepping..."); assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); @@ -163,6 +171,30 @@ fn ptrace() -> Result<(), String> { assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); + println!("Testing memory access..."); + next(syscall::PTRACE_SINGLESTEP)?; + next(syscall::PTRACE_SINGLESTEP)?; + + let rsp = next(syscall::PTRACE_SINGLESTEP)?.rsp; + mem_file.seek(SeekFrom::Start(rsp as u64)).map_err(|e| format!("memory seek failed: {}", e))?; + + unsafe { + union Stack { + words: [usize; 3], + bytes: [u8; 3 * mem::size_of::()] + } + let mut out = Stack { words: [0; 3] }; + mem_file.read(&mut out.bytes).map_err(|e| format!("memory read failed: {}", e))?; + assert_eq!(out.words, [1, 2, 3]); + assert_eq!( + mem_file.seek(SeekFrom::Current(0)).map_err(|e| format!("memory seek failed: {}", e))? as usize, + rsp + out.bytes.len() + ); + } + + next(syscall::PTRACE_SINGLESTEP)?; + + // Activate nonblock let old_flags = syscall::fcntl(proc_file.as_raw_fd() as usize, syscall::F_GETFL, 0) .map_err(|e| format!("fcntl get failed: {}", e))?; let new_flags = old_flags | syscall::O_NONBLOCK; @@ -194,6 +226,7 @@ fn ptrace() -> Result<(), String> { regs.rax = 123; setregs(®s)?; + // Deactivate nonblock syscall::fcntl(proc_file.as_raw_fd() as usize, syscall::F_SETFL, old_flags) .map_err(|e| format!("fcntl set failed: {}", e))?;