From b356ddc3aafb1cc5f3dead438840bcec5e91e645 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 1 Jul 2019 12:32:22 +0200 Subject: [PATCH 01/19] WIP(ptrace): Add test for singlesteps --- Cargo.lock | 7 +++++ Cargo.toml | 1 + src/main.rs | 80 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 3 files changed, 87 insertions(+), 1 deletion(-) diff --git a/Cargo.lock b/Cargo.lock index b6d66d6..bc6a0c8 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,6 +4,7 @@ name = "acid" version = "0.1.0" dependencies = [ + "redox_syscall 0.1.54 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -201,6 +202,11 @@ dependencies = [ "bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "redox_syscall" +version = "0.1.54" +source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#a7aff4b60d537e6f336ff7e8affe8801a92c20f0" + [[package]] name = "rustc-serialize" version = "0.3.24" @@ -284,6 +290,7 @@ dependencies = [ "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" +"checksum redox_syscall 0.1.54 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" diff --git a/Cargo.toml b/Cargo.toml index f57ab6d..bccefe0 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,3 +5,4 @@ authors = ["Jeremy Soller "] [dependencies] x86 = "0.7" +redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } diff --git a/src/main.rs b/src/main.rs index 7e7ef7d..56aed2c 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,5 +1,5 @@ //!Acid testing program -#![feature(thread_local)] +#![feature(thread_local, asm)] extern crate x86; @@ -51,6 +51,83 @@ fn page_fault_test() -> Result<(), String> { Ok(()) } +fn ptrace() -> Result<(), String> { + use std::{ + fs::File, + io::prelude::*, + os::{raw::c_int, unix::io::{AsRawFd, FromRawFd}} + }; + + let pid = unsafe { syscall::clone(0).map_err(|e| format!("clone failed: {}", e))? }; + if pid == 0 { + unsafe { + asm!(" + mov rax, 20 // GETPID + syscall + + mov rdi, rax + + mov rax, 37 // SYS_KILL + mov rsi, 19 // SIGSTOP + syscall + + // Start of body + mov rax, 1 + push rax + mov rax, 2 + push rax + mov rax, 3 + pop rax + pop rax + // End of body + + mov rax, 1 // SYS_EXIT + mov rdi, 0 + syscall + " + : : : : "intel", "volatile" + ); + } + } + + // Wait until child is ready to be traced + let mut status = 0; + syscall::waitpid(pid, &mut status, syscall::WUNTRACED).map_err(|e| format!("waitpid failed: {}", e))?; + + // Stop & attach process + get handle to registers + let mut proc_file = File::open(format!("proc:{}/trace", pid)).map_err(|e| format!("open failed: {}", e))?; + let mut regs_file = unsafe { + File::from_raw_fd( + syscall::dup(proc_file.as_raw_fd() as usize, b"regs/int") + .map_err(|e| format!("dup failed: {}", e))? as c_int + ) + }; + + // Schedule restart of process when resumed + syscall::kill(pid, syscall::SIGCONT).map_err(|e| format!("kill failed: {}", e))?; + + let mut next = move |op| -> Result { + proc_file.write(&[op]).map_err(|e| format!("ptrace operation failed: {}", e))?; + + let mut regs: syscall::IntRegisters = syscall::IntRegisters::default(); + regs_file.read(&mut regs).map_err(|e| format!("reading registers failed: {}", e))?; + Ok(regs) + }; + + // Step out of syscall down to the next instruction + let _ = next(syscall::PTRACE_SINGLESTEP)?; + assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); + assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); + assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); + assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 3); + assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); + assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); + + assert_eq!(next(syscall::PTRACE_SYSCALL)?.rax, syscall::SYS_EXIT); + + Ok(()) +} + fn switch_test() -> Result<(), String> { use std::thread; use x86::time::rdtscp; @@ -181,6 +258,7 @@ fn main() { let mut tests: BTreeMap<&'static str, fn() -> Result<(), String>> = BTreeMap::new(); tests.insert("create_test", create_test); tests.insert("page_fault", page_fault_test); + tests.insert("ptrace", ptrace); tests.insert("switch", switch_test); tests.insert("tcp_fin", tcp_fin_test); tests.insert("thread", thread_test); From 1f47418f307d8f91b0a17de94b73c4fa2fcb7f41 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 1 Jul 2019 16:18:13 +0200 Subject: [PATCH 02/19] WIP(ptrace): Non-blocking tests --- Cargo.lock | 4 +- Cargo.toml | 3 +- src/main.rs | 110 +++++++++++++++++++++++++++++++++++++++++++++------- 3 files changed, 98 insertions(+), 19 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index bc6a0c8..ed855ae 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,7 @@ name = "acid" version = "0.1.0" dependencies = [ - "redox_syscall 0.1.54 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", + "redox_syscall 0.1.54", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -205,7 +205,6 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.1.54" -source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#a7aff4b60d537e6f336ff7e8affe8801a92c20f0" [[package]] name = "rustc-serialize" @@ -290,7 +289,6 @@ dependencies = [ "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" -"checksum redox_syscall 0.1.54 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" diff --git a/Cargo.toml b/Cargo.toml index bccefe0..5219f13 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -5,4 +5,5 @@ authors = ["Jeremy Soller "] [dependencies] x86 = "0.7" -redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } +# redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } +redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } diff --git a/src/main.rs b/src/main.rs index 56aed2c..79fd3e1 100644 --- a/src/main.rs +++ b/src/main.rs @@ -62,6 +62,7 @@ fn ptrace() -> Result<(), String> { if pid == 0 { unsafe { asm!(" + // Wait until tracer is started mov rax, 20 // GETPID syscall @@ -71,7 +72,9 @@ fn ptrace() -> Result<(), String> { mov rsi, 19 // SIGSTOP syscall - // Start of body + // Start of body: + + // Test basic singlestepping mov rax, 1 push rax mov rax, 2 @@ -79,43 +82,80 @@ fn ptrace() -> Result<(), String> { mov rax, 3 pop rax pop rax - // End of body - mov rax, 1 // SYS_EXIT - mov rdi, 0 + // Test behavior if tracer aborts a breakpoint before it's reached + call wait_for_a_while + + mov rax, 158 // SYS_YIELD syscall + + mov rax, 37 // SYS_KILL + mov rsi, 19 // SIGSTOP + syscall + + // Test nonblock & sysemu + call wait_for_a_while + + mov rax, 20 // GETPID + syscall + + mov rdi, rax + mov rax, 1 // SYS_EXIT + syscall + + // Without a jump, this code is unreachable. Therefore function definitions go here. + + wait_for_a_while: + mov rax, 4294967295 + .loop: + sub rax, 1 + jne .loop + ret " : : : : "intel", "volatile" ); } } - // Wait until child is ready to be traced + println!("Waiting until child is ready to be traced..."); let mut status = 0; syscall::waitpid(pid, &mut status, syscall::WUNTRACED).map_err(|e| format!("waitpid failed: {}", e))?; - // Stop & attach process + get handle to registers - let mut proc_file = File::open(format!("proc:{}/trace", pid)).map_err(|e| format!("open failed: {}", e))?; - let mut regs_file = unsafe { + println!("Done! Attaching tracer..."); + + // Stop and attach process + get handle to registers + let proc_file = File::open(format!("proc:{}/trace", pid)).map_err(|e| format!("open failed: {}", e))?; + let regs_file = unsafe { File::from_raw_fd( syscall::dup(proc_file.as_raw_fd() as usize, b"regs/int") .map_err(|e| format!("dup failed: {}", e))? as c_int ) }; - // Schedule restart of process when resumed + println!("Schedule restart of process when resumed..."); syscall::kill(pid, syscall::SIGCONT).map_err(|e| format!("kill failed: {}", e))?; - let mut next = move |op| -> Result { - proc_file.write(&[op]).map_err(|e| format!("ptrace operation failed: {}", e))?; - + let getregs = || -> Result { let mut regs: syscall::IntRegisters = syscall::IntRegisters::default(); - regs_file.read(&mut regs).map_err(|e| format!("reading registers failed: {}", e))?; + (®s_file).read(&mut regs).map_err(|e| format!("reading registers failed: {}", e))?; Ok(regs) }; - // Step out of syscall down to the next instruction + let setregs = |regs: &syscall::IntRegisters| -> Result<(), String> { + (®s_file).write(®s).map_err(|e| format!("writing registers failed: {}", e))?; + Ok(()) + }; + + let next = |op| -> Result { + (&proc_file).write(&[op]).map_err(|e| format!("ptrace operation failed: {}", e))?; + + getregs() + }; + + println!("Stepping away from the syscall instruction..."); let _ = next(syscall::PTRACE_SINGLESTEP)?; + + println!("Testing basic singlestepping..."); assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); @@ -123,7 +163,47 @@ fn ptrace() -> Result<(), String> { assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); - assert_eq!(next(syscall::PTRACE_SYSCALL)?.rax, syscall::SYS_EXIT); + 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; + syscall::fcntl(proc_file.as_raw_fd() as usize, syscall::F_SETFL, new_flags) + .map_err(|e| format!("fcntl set failed: {}", e))?; + + println!("Testing behavior of obsolete breakpoints..."); + next(syscall::PTRACE_SYSCALL)?; + next(syscall::PTRACE_CONT)?; + println!("Tracee RAX: {}", getregs()?.rax); + + println!("Waiting for next signal from tracee that it's ready to be traced again..."); + syscall::waitpid(pid, &mut status, syscall::WUNTRACED).map_err(|e| format!("waitpid failed: {}", e))?; + + println!("Setting sysemu breakpoint..."); + next(syscall::PTRACE_SYSCALL | syscall::PTRACE_SYSEMU)?; + + println!("Schedule restart of process after breakpoint is set..."); + syscall::kill(pid, syscall::SIGCONT).map_err(|e| format!("kill failed: {}", e))?; + + println!("After non-blocking ptrace, execution continues as normal:"); + for _ in 0..5 { + println!("Tracee RAX: {}", getregs()?.rax); + } + + println!("Overriding GETPID call..."); + let mut regs = next(syscall::PTRACE_WAIT)?; + assert_eq!(regs.rax, syscall::SYS_GETPID); + regs.rax = 123; + setregs(®s)?; + + syscall::fcntl(proc_file.as_raw_fd() as usize, syscall::F_SETFL, old_flags) + .map_err(|e| format!("fcntl set failed: {}", e))?; + + println!("Checking exit status..."); + let regs = next(syscall::PTRACE_SYSCALL)?; + assert_eq!(regs.rax, syscall::SYS_EXIT); + assert_eq!(regs.rdi, 123); + assert_eq!((&proc_file).write(&[syscall::PTRACE_SYSCALL]).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + + println!("All done and tested!"); Ok(()) } From 27960a3cc407d7039e8145748c6d36bd63d9e0c2 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 3 Jul 2019 16:24:37 +0200 Subject: [PATCH 03/19] 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))?; From 197dc3044529191c4f761cc30e6b27bab47f16e3 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Thu, 4 Jul 2019 15:19:37 +0200 Subject: [PATCH 04/19] WIP(ptrace): Test floating point registers --- Cargo.lock | 25 +++++++--- Cargo.toml | 7 ++- src/main.rs | 139 +++++++++++++++++++++++++++------------------------- 3 files changed, 95 insertions(+), 76 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index ed855ae..cc93e45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,7 +4,8 @@ name = "acid" version = "0.1.0" dependencies = [ - "redox_syscall 0.1.54", + "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", + "strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -15,7 +16,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "bitflags" -version = "1.0.4" +version = "1.1.0" source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] @@ -28,7 +29,7 @@ name = "cloudabi" version = "0.0.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] [[package]] @@ -45,7 +46,7 @@ name = "fuchsia-zircon" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -204,7 +205,8 @@ dependencies = [ [[package]] name = "redox_syscall" -version = "0.1.54" +version = "0.1.56" +source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#49dd22260bd8bada8b835d12ee8e460a5a1c4af4" [[package]] name = "rustc-serialize" @@ -233,6 +235,15 @@ name = "siphasher" version = "0.2.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "strace" +version = "0.1.0" +source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#e64d9fb900c825e6f370da7d4bef89f10adff475" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", +] + [[package]] name = "winapi" version = "0.3.6" @@ -266,7 +277,7 @@ dependencies = [ [metadata] "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" -"checksum bitflags 1.0.4 (registry+https://github.com/rust-lang/crates.io-index)" = "228047a76f468627ca71776ecdebd732a3423081fcf5125585bcd7c49886ce12" +"checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" @@ -289,10 +300,12 @@ dependencies = [ "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" +"checksum redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)" = "" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 5219f13..55df79d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -2,8 +2,11 @@ name = "acid" version = "0.1.0" authors = ["Jeremy Soller "] +edition = "2018" [dependencies] x86 = "0.7" -# redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } -redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } +redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } +# redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } +strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox" } +# strace = { path = "/home/user/Coding/Rust/strace-redox" } diff --git a/src/main.rs b/src/main.rs index bea534c..60d73c9 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,7 +1,9 @@ //!Acid testing program #![feature(thread_local, asm)] -extern crate x86; +fn e(error: Result) -> Result { + error.map_err(|e| e.to_string()) +} fn create_test() -> Result<(), String> { use std::fs; @@ -51,15 +53,15 @@ fn page_fault_test() -> Result<(), String> { Ok(()) } -fn ptrace() -> Result<(), String> { +pub fn ptrace() -> Result<(), String> { use std::{ fs::File, - io::{prelude::*, SeekFrom}, mem, - os::{raw::c_int, unix::io::{AsRawFd, FromRawFd}} + os::unix::io::{AsRawFd, FromRawFd, RawFd} }; + use strace::*; - let pid = unsafe { syscall::clone(0).map_err(|e| format!("clone failed: {}", e))? }; + let pid = e(unsafe { syscall::clone(0) })?; if pid == 0 { unsafe { asm!(" @@ -88,7 +90,13 @@ fn ptrace() -> Result<(), String> { push 3 push 2 push 1 - add rsp, 3 // pop 3 items, ignore values + add rsp, 8*3 // pop 3 items, ignore values + + // Testing floating point + push 32 + fild QWORD PTR [rsp] + fsqrt + add rsp, 8 // pop 1 item, ignore value // Test behavior if tracer aborts a breakpoint before it's reached call wait_for_a_while @@ -126,57 +134,49 @@ fn ptrace() -> Result<(), String> { println!("Waiting until child is ready to be traced..."); let mut status = 0; - syscall::waitpid(pid, &mut status, syscall::WUNTRACED).map_err(|e| format!("waitpid failed: {}", e))?; + e(syscall::waitpid(pid, &mut status, syscall::WUNTRACED))?; println!("Done! Attaching tracer..."); - // Stop and attach process + get handle to registers - let proc_file = File::open(format!("proc:{}/trace", pid)).map_err(|e| format!("open failed: {}", e))?; + // Stop and attach process + get handle to registers. + // This also tests the behaviour of dup(...) + let proc_file = e(File::open(format!("proc:{}/trace", pid)))?; let regs_file = unsafe { - File::from_raw_fd( - syscall::dup(proc_file.as_raw_fd() as usize, b"regs/int") - .map_err(|e| format!("dup failed: {}", e))? as c_int - ) + File::from_raw_fd(e(syscall::dup(proc_file.as_raw_fd() as usize, b"regs/int"))? as RawFd) + }; + let regs_file_float = unsafe { + File::from_raw_fd(e(syscall::dup(regs_file.as_raw_fd() as usize, b"regs/float"))? as RawFd) + }; + + let mut tracer = Tracer { + file: proc_file, + regs: Registers { + float: regs_file_float, + int: regs_file + }, + mem: e(Memory::attach(pid))? }; - 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))?; - - let getregs = || -> Result { - let mut regs: syscall::IntRegisters = syscall::IntRegisters::default(); - (®s_file).read(&mut regs).map_err(|e| format!("reading registers failed: {}", e))?; - Ok(regs) - }; - - let setregs = |regs: &syscall::IntRegisters| -> Result<(), String> { - (®s_file).write(®s).map_err(|e| format!("writing registers failed: {}", e))?; - Ok(()) - }; - - let next = |op| -> Result { - (&proc_file).write(&[op]).map_err(|e| format!("ptrace operation failed: {}", e))?; - - getregs() - }; + e(syscall::kill(pid, syscall::SIGCONT))?; println!("Stepping away from the syscall instruction..."); - next(syscall::PTRACE_SINGLESTEP)?; + e(tracer.next(Stop::INSTRUCTION))?; println!("Testing basic singlestepping..."); - assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); - assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); - assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); - assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 3); - assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 2); - assert_eq!(next(syscall::PTRACE_SINGLESTEP)?.rax, 1); + assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 1); + assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 2); + assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 2); + assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 3); + assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 2); + assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 1); println!("Testing memory access..."); - next(syscall::PTRACE_SINGLESTEP)?; - next(syscall::PTRACE_SINGLESTEP)?; + e(tracer.next(Stop::INSTRUCTION))?; + e(tracer.next(Stop::INSTRUCTION))?; - let rsp = next(syscall::PTRACE_SINGLESTEP)?.rsp; - mem_file.seek(SeekFrom::Start(rsp as u64)).map_err(|e| format!("memory seek failed: {}", e))?; + e(tracer.next(Stop::INSTRUCTION))?; + let regs = e(tracer.regs.get_int())?; unsafe { union Stack { @@ -184,57 +184,60 @@ fn ptrace() -> Result<(), String> { 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))?; + e(tracer.mem.read(regs.rsp as *const _, &mut out.bytes))?; 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() - ); + assert_eq!(e(tracer.mem.cursor())? as usize, regs.rsp + out.bytes.len()); } - next(syscall::PTRACE_SINGLESTEP)?; + e(tracer.next(Stop::INSTRUCTION))?; + + println!("Testing floating point..."); + for _ in 0..3 { + e(tracer.next(Stop::INSTRUCTION))?; + } + let regs = e(tracer.regs.get_float())?; + let f = regs.st_space_nth(0); + let fs = regs.st_space(); + assert_eq!(fs, [f, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]); + assert!((f - 5.65685424949238).abs() < std::f64::EPSILON); // 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; - syscall::fcntl(proc_file.as_raw_fd() as usize, syscall::F_SETFL, new_flags) - .map_err(|e| format!("fcntl set failed: {}", e))?; + let mut tracer = e(tracer.nonblocking())?; println!("Testing behavior of obsolete breakpoints..."); - next(syscall::PTRACE_SYSCALL)?; - next(syscall::PTRACE_CONT)?; - println!("Tracee RAX: {}", getregs()?.rax); + e(tracer.next(Stop::SYSCALL))?; + e(tracer.next(Stop::COMPLETION))?; + println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax); println!("Waiting for next signal from tracee that it's ready to be traced again..."); - syscall::waitpid(pid, &mut status, syscall::WUNTRACED).map_err(|e| format!("waitpid failed: {}", e))?; + e(syscall::waitpid(pid, &mut status, syscall::WUNTRACED))?; println!("Setting sysemu breakpoint..."); - next(syscall::PTRACE_SYSCALL | syscall::PTRACE_SYSEMU)?; + e(tracer.next(Stop::SYSCALL | Stop::SYSEMU))?; println!("Schedule restart of process after breakpoint is set..."); - syscall::kill(pid, syscall::SIGCONT).map_err(|e| format!("kill failed: {}", e))?; + e(syscall::kill(pid, syscall::SIGCONT))?; println!("After non-blocking ptrace, execution continues as normal:"); for _ in 0..5 { - println!("Tracee RAX: {}", getregs()?.rax); + println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax); } println!("Overriding GETPID call..."); - let mut regs = next(syscall::PTRACE_WAIT)?; + e(tracer.wait())?; + let mut regs = e(tracer.regs.get_int())?; assert_eq!(regs.rax, syscall::SYS_GETPID); regs.rax = 123; - setregs(®s)?; + e(tracer.regs.set_int(®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))?; + let mut tracer = e(tracer.blocking())?; println!("Checking exit status..."); - let regs = next(syscall::PTRACE_SYSCALL)?; + e(tracer.next(Stop::SYSCALL))?; + let regs = e(tracer.regs.get_int())?; assert_eq!(regs.rax, syscall::SYS_EXIT); assert_eq!(regs.rdi, 123); - assert_eq!((&proc_file).write(&[syscall::PTRACE_SYSCALL]).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + assert_eq!(tracer.next(Stop::SYSCALL).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); println!("All done and tested!"); From 666e28d18cf7f99c11d7fde6866e525fab9ba3d3 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 17 Jul 2019 10:16:34 +0200 Subject: [PATCH 05/19] WIP(ptrace): Add test for waitpid WNOHANG --- src/main.rs | 8 +++++++- 1 file changed, 7 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 60d73c9..6ce4224 100644 --- a/src/main.rs +++ b/src/main.rs @@ -232,13 +232,19 @@ pub fn ptrace() -> Result<(), String> { let mut tracer = e(tracer.blocking())?; - println!("Checking exit status..."); + println!("Checking exit syscall..."); e(tracer.next(Stop::SYSCALL))?; let regs = e(tracer.regs.get_int())?; assert_eq!(regs.rax, syscall::SYS_EXIT); assert_eq!(regs.rdi, 123); assert_eq!(tracer.next(Stop::SYSCALL).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + println!("Checking exit status (waitpid nohang)..."); + let mut status = 0; + e(syscall::waitpid(pid, &mut status, syscall::WNOHANG))?; + assert!(syscall::wifexited(status)); + assert_eq!(syscall::wexitstatus(status), 123); + println!("All done and tested!"); Ok(()) From 532621cbe60a3eefec793b5d51c887ef79dd1271 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 17 Jul 2019 16:04:07 +0200 Subject: [PATCH 06/19] WIP(ptrace): Test ptrace security --- src/main.rs | 12 +++++++++++- 1 file changed, 11 insertions(+), 1 deletion(-) diff --git a/src/main.rs b/src/main.rs index 6ce4224..d89f480 100644 --- a/src/main.rs +++ b/src/main.rs @@ -132,7 +132,8 @@ pub fn ptrace() -> Result<(), String> { } } - println!("Waiting until child is ready to be traced..."); + println!("My PID: {}", e(syscall::getpid())?); + println!("Waiting until child (pid {}) is ready to be traced...", pid); let mut status = 0; e(syscall::waitpid(pid, &mut status, syscall::WUNTRACED))?; @@ -245,6 +246,15 @@ pub fn ptrace() -> Result<(), String> { assert!(syscall::wifexited(status)); assert_eq!(syscall::wexitstatus(status), 123); + println!("Trying to do illegal things..."); + for id in 0..=1_000_000 { + let err = File::open(format!("proc:{}/regs/int", id)).map(|_| None).unwrap_or_else(|err| err.raw_os_error()); + assert!( + err == Some(syscall::EPERM) || err == Some(syscall::ESRCH), + "The cops ignored that I tried to illegally open PID {}: {:?}", id, err + ); + } + println!("All done and tested!"); Ok(()) From ed1536d60fac61f0230ad0a5f185c69e3682c863 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Fri, 19 Jul 2019 21:55:17 +0200 Subject: [PATCH 07/19] WIP(ptrace): Test event system --- Cargo.lock | 4 +-- Cargo.toml | 1 + src/main.rs | 70 ++++++++++++++++++++++++++++++++++++++++++++++++++--- 3 files changed, 70 insertions(+), 5 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index cc93e45..eb24363 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,7 +206,7 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.1.56" -source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#49dd22260bd8bada8b835d12ee8e460a5a1c4af4" +source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#eddcb80eb7c2d43dedf0ba2ee514b54b0b8fafc7" [[package]] name = "rustc-serialize" @@ -238,7 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strace" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#e64d9fb900c825e6f370da7d4bef89f10adff475" +source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#b5740938279dbc8334e361d3a8bfc9a4ca64c9ce" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", diff --git a/Cargo.toml b/Cargo.toml index 55df79d..b34d235 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,6 +6,7 @@ edition = "2018" [dependencies] x86 = "0.7" +# redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } # redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox" } diff --git a/src/main.rs b/src/main.rs index d89f480..ecd326f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,6 +56,7 @@ fn page_fault_test() -> Result<(), String> { pub fn ptrace() -> Result<(), String> { use std::{ fs::File, + io, mem, os::unix::io::{AsRawFd, FromRawFd, RawFd} }; @@ -98,12 +99,39 @@ pub fn ptrace() -> Result<(), String> { fsqrt add rsp, 8 // pop 1 item, ignore value + // Make sure event is raised when child forks + mov rax, 120 // SYS_CLONE + xor rdi, rdi + syscall + test rax, rax + je .exit + + // Wait for child process, to make sure an ignored process is continued + mov rdi, rax + mov rax, 7 + push 0 + mov rsi, rsp + add rsp, 8 + xor rdx, rdx + syscall + + // Another fork attempt, but test what happens when not ignored + mov rax, 120 // SYS_CLONE + xor rdi, rdi + syscall + test rax, rax + je .exit + // Test behavior if tracer aborts a breakpoint before it's reached call wait_for_a_while mov rax, 158 // SYS_YIELD syscall + mov rax, 20 // GETPID + syscall + + mov rdi, rax mov rax, 37 // SYS_KILL mov rsi, 19 // SIGSTOP syscall @@ -111,20 +139,22 @@ pub fn ptrace() -> Result<(), String> { // Test nonblock & sysemu call wait_for_a_while + .exit: mov rax, 20 // GETPID syscall mov rdi, rax mov rax, 1 // SYS_EXIT syscall + ud2 // Without a jump, this code is unreachable. Therefore function definitions go here. wait_for_a_while: mov rax, 4294967295 - .loop: + .wait_for_a_while_loop: sub rax, 1 - jne .loop + jne .wait_for_a_while_loop ret " : : : : "intel", "volatile" @@ -202,6 +232,36 @@ pub fn ptrace() -> Result<(), String> { assert_eq!(fs, [f, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0, 0.0]); assert!((f - 5.65685424949238).abs() < std::f64::EPSILON); + println!("Testing fork event"); + let mut handler = e(tracer.next_event(Stop::COMPLETION))?.ok_or("Program completed without yielding fork event")?; + let events = e(handler.iter().collect::>>())?; + + assert_eq!(events.len(), 1); + match events[0] { + PtraceEvent::Clone(pid) => println!("Got clone: {}", pid), + ref e => return Err(format!("Wrong event type: {:?}", e)) + } + + println!("Testing fork event - but actually handling the fork"); + handler = e(handler.retry())?.ok_or("Program completed without yielding fork event")?; + let events = e(handler.iter().collect::>>())?; + assert_eq!(events.len(), 1); + match events[0] { + PtraceEvent::Clone(pid) => { + let mut child = e(Tracer::attach(pid))?; + println!("-> Fork attached (PID {})", pid); + + assert_eq!(e(e(child.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETPID); + e(child.next(Stop::SYSCALL))?; + println!("-> Fork executed GETPID"); + + assert_eq!(e(e(child.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_EXIT); + assert_eq!(child.next(Stop::COMPLETION).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + println!("-> Fork executed EXIT"); + }, + ref e => return Err(format!("Wrong event type: {:?}", e)) + } + // Activate nonblock let mut tracer = e(tracer.nonblocking())?; @@ -224,8 +284,12 @@ pub fn ptrace() -> Result<(), String> { println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax); } + println!("Waiting... Five times. To make sure it doesn't get stuck forever"); + for _ in 0..5 { + e(tracer.wait())?; + } + println!("Overriding GETPID call..."); - e(tracer.wait())?; let mut regs = e(tracer.regs.get_int())?; assert_eq!(regs.rax, syscall::SYS_GETPID); regs.rax = 123; From c788e22e4670e6d2b7410cbe2e96ac686505c471 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sat, 20 Jul 2019 22:23:36 +0200 Subject: [PATCH 08/19] WIP(ptrace): Test signal behaviors --- src/main.rs | 97 ++++++++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 82 insertions(+), 15 deletions(-) diff --git a/src/main.rs b/src/main.rs index ecd326f..eee0891 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,10 +64,35 @@ pub fn ptrace() -> Result<(), String> { let pid = e(unsafe { syscall::clone(0) })?; if pid == 0 { + extern "C" fn sighandler(_: usize) { + unsafe { + asm!(" + mov rax, 158 // SYS_YIELD + syscall + " + : : : : "intel", "volatile"); + } + } + extern "C" fn sigreturn() { + unsafe { + asm!(" + mov rax, 119 // SYS_SIGRETURN + syscall + ud2 + " + : : : : "intel", "volatile"); + } + } unsafe { asm!(" + // Push any arguments from rust to the stack so we're + // free to use whatever registers we want + push $1 + push $0 + mov rbp, rsp + // Wait until tracer is started - mov rax, 20 // GETPID + mov rax, 20 // SYS_GETPID syscall mov rdi, rax @@ -104,23 +129,44 @@ pub fn ptrace() -> Result<(), String> { xor rdi, rdi syscall test rax, rax - je .exit + je exit // Wait for child process, to make sure an ignored process is continued mov rdi, rax mov rax, 7 push 0 mov rsi, rsp - add rsp, 8 xor rdx, rdx syscall + add rsp, 8 // Another fork attempt, but test what happens when not ignored mov rax, 120 // SYS_CLONE xor rdi, rdi syscall test rax, rax - je .exit + je exit + + // Test behavior of signals + mov rax, 67 // SYS_SIGACTION + mov rdi, 10 // SIGUSR1 + push 0 // sa_flags + push 0 // sa_mask[1] + push 0 // sa_mask[0] + push [rbp] // sa_handler + mov rsi, rsp + xor rdx, rdx + mov r10, [rbp+0x8] + syscall + add rsp, 8*4 + + mov rax, 20 // SYS_GETPID + syscall + + mov rdi, rax + mov rax, 37 // SYS_KILL + mov rsi, 10 // SIGUSR1 + syscall // Test behavior if tracer aborts a breakpoint before it's reached call wait_for_a_while @@ -128,7 +174,7 @@ pub fn ptrace() -> Result<(), String> { mov rax, 158 // SYS_YIELD syscall - mov rax, 20 // GETPID + mov rax, 20 // SYS_GETPID syscall mov rdi, rax @@ -139,8 +185,8 @@ pub fn ptrace() -> Result<(), String> { // Test nonblock & sysemu call wait_for_a_while - .exit: - mov rax, 20 // GETPID + exit: + mov rax, 20 // SYS_GETPID syscall mov rdi, rax @@ -152,12 +198,15 @@ pub fn ptrace() -> Result<(), String> { wait_for_a_while: mov rax, 4294967295 - .wait_for_a_while_loop: + wait_for_a_while_loop: sub rax, 1 - jne .wait_for_a_while_loop + jne wait_for_a_while_loop ret " - : : : : "intel", "volatile" + : // no outputs + : "r"(sighandler as usize), "r"(sigreturn as usize) + : // no clobbers + : "intel", "volatile" ); } } @@ -169,8 +218,8 @@ pub fn ptrace() -> Result<(), String> { println!("Done! Attaching tracer..."); - // Stop and attach process + get handle to registers. - // This also tests the behaviour of dup(...) + // Stop and attach process + get handle to registers. This also + // tests the behavior of dup(...) let proc_file = e(File::open(format!("proc:{}/trace", pid)))?; let regs_file = unsafe { File::from_raw_fd(e(syscall::dup(proc_file.as_raw_fd() as usize, b"regs/int"))? as RawFd) @@ -233,17 +282,22 @@ pub fn ptrace() -> Result<(), String> { assert!((f - 5.65685424949238).abs() < std::f64::EPSILON); println!("Testing fork event"); - let mut handler = e(tracer.next_event(Stop::COMPLETION))?.ok_or("Program completed without yielding fork event")?; + assert!(e(tracer.next_event(Stop::SYSCALL))?.is_none()); // pre-syscall + let mut handler = e(tracer.next_event(Stop::SYSCALL))?.ok_or("Syscall completed without yielding fork event")?; // post-syscall let events = e(handler.iter().collect::>>())?; assert_eq!(events.len(), 1); match events[0] { - PtraceEvent::Clone(pid) => println!("Got clone: {}", pid), + PtraceEvent::Clone(pid) => println!("Obtained fork (PID {})", pid), ref e => return Err(format!("Wrong event type: {:?}", e)) } println!("Testing fork event - but actually handling the fork"); - handler = e(handler.retry())?.ok_or("Program completed without yielding fork event")?; + for _ in 0..3 { // pre-post-waitpid, pre-clone + assert!(e(tracer.next_event(Stop::SYSCALL))?.is_none()); + } + let mut handler = e(tracer.next_event(Stop::SYSCALL))?.ok_or("Syscall completed without yielding fork event")?; + // handler = e(handler.retry())?.ok_or("Program completed without yielding fork event")?; let events = e(handler.iter().collect::>>())?; assert_eq!(events.len(), 1); match events[0] { @@ -262,6 +316,19 @@ pub fn ptrace() -> Result<(), String> { ref e => return Err(format!("Wrong event type: {:?}", e)) } + println!("Testing signals"); + assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGACTION); + e(tracer.next(Stop::SYSCALL))?; // post-syscall sigaction + assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETPID); + e(tracer.next(Stop::SYSCALL))?; // post-syscall getpid + assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_KILL); + // kill doesn't return *yet* + assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_YIELD); + e(tracer.next(Stop::SYSCALL))?; // post-syscall yield + assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGRETURN); + // sigreturn doesn't return + e(tracer.next(Stop::SYSCALL))?; // post-syscall kill! + // Activate nonblock let mut tracer = e(tracer.nonblocking())?; From c72af623d099a59146e52c7a03474e06d8a19e90 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sun, 21 Jul 2019 20:25:16 +0200 Subject: [PATCH 09/19] WIP(ptrace): Test new signal behavior --- Cargo.lock | 4 ++-- src/main.rs | 40 ++++++++++++++++++++++++++++++++++------ 2 files changed, 36 insertions(+), 8 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index eb24363..7aac70f 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -206,7 +206,7 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.1.56" -source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#eddcb80eb7c2d43dedf0ba2ee514b54b0b8fafc7" +source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#844650c4fb9725cd9029de6277826bfe0fb19909" [[package]] name = "rustc-serialize" @@ -238,7 +238,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strace" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#b5740938279dbc8334e361d3a8bfc9a4ca64c9ce" +source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#b1ea95f266029e1fc82892c3ce8a10521840135c" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", diff --git a/src/main.rs b/src/main.rs index eee0891..e7453cc 100644 --- a/src/main.rs +++ b/src/main.rs @@ -168,6 +168,10 @@ pub fn ptrace() -> Result<(), String> { mov rsi, 10 // SIGUSR1 syscall + // aaand again + mov rax, 37 // SYS_KILL + syscall + // Test behavior if tracer aborts a breakpoint before it's reached call wait_for_a_while @@ -291,6 +295,7 @@ pub fn ptrace() -> Result<(), String> { PtraceEvent::Clone(pid) => println!("Obtained fork (PID {})", pid), ref e => return Err(format!("Wrong event type: {:?}", e)) } + assert!(e(handler.retry())?.is_none()); println!("Testing fork event - but actually handling the fork"); for _ in 0..3 { // pre-post-waitpid, pre-clone @@ -315,6 +320,7 @@ pub fn ptrace() -> Result<(), String> { }, ref e => return Err(format!("Wrong event type: {:?}", e)) } + assert!(e(handler.retry())?.is_none()); println!("Testing signals"); assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGACTION); @@ -323,11 +329,33 @@ pub fn ptrace() -> Result<(), String> { e(tracer.next(Stop::SYSCALL))?; // post-syscall getpid assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_KILL); // kill doesn't return *yet* - assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_YIELD); - e(tracer.next(Stop::SYSCALL))?; // post-syscall yield - assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGRETURN); - // sigreturn doesn't return - e(tracer.next(Stop::SYSCALL))?; // post-syscall kill! + + let mut handler = e(tracer.next_event(Stop::SYSCALL))?.ok_or("Syscall completed without yielding event")?; + let events = e(handler.iter().collect::>>())?; + + assert_eq!(events.len(), 1); + match events[0] { + PtraceEvent::Signal(signal) => { + assert_eq!(signal, syscall::SIGUSR1); + println!("Obtained signal"); + }, + ref e => return Err(format!("Wrong event type: {:?}", e)) + } + + assert!(e(handler.retry())?.is_none()); + for i in 0..2 { + assert_eq!(e(tracer.regs.get_int())?.rax, syscall::SYS_YIELD); + e(tracer.next(Stop::SYSCALL))?; // post-syscall yield + assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGRETURN); + // sigreturn doesn't return + e(tracer.next(Stop::SYSCALL))?; // post-syscall kill! + + if i == 0 { + e(tracer.next(Stop::SIGNAL))?; + assert_eq!(e(tracer.regs.get_int())?.rax, syscall::SYS_KILL); + e(tracer.next(Stop::SYSCALL))?; + } + } // Activate nonblock let mut tracer = e(tracer.nonblocking())?; @@ -351,7 +379,7 @@ pub fn ptrace() -> Result<(), String> { println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax); } - println!("Waiting... Five times. To make sure it doesn't get stuck forever"); + println!("Waiting... Five times... To make sure it doesn't get stuck forever..."); for _ in 0..5 { e(tracer.wait())?; } From 4896069e462302262b1bcf03086b8c21d8114aac Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Fri, 26 Jul 2019 10:31:35 +0200 Subject: [PATCH 10/19] Update tests for ptrace overhaul --- Cargo.lock | 10 ++-- Cargo.toml | 8 ++-- src/main.rs | 134 ++++++++++++++++++++++++++++------------------------ 3 files changed, 79 insertions(+), 73 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 7aac70f..0e10041 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,8 +4,8 @@ name = "acid" version = "0.1.0" dependencies = [ - "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", - "strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)", + "redox_syscall 0.1.56", + "strace 0.1.0", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -206,7 +206,6 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.1.56" -source = "git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace#844650c4fb9725cd9029de6277826bfe0fb19909" [[package]] name = "rustc-serialize" @@ -238,10 +237,9 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strace" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#b1ea95f266029e1fc82892c3ce8a10521840135c" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)", + "redox_syscall 0.1.56", ] [[package]] @@ -300,12 +298,10 @@ dependencies = [ "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" -"checksum redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/jD91mZM2/syscall.git?branch=ptrace)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)" = "" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index b34d235..97de28a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,7 +7,7 @@ edition = "2018" [dependencies] x86 = "0.7" # redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } -redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } -# redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } -strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox" } -# strace = { path = "/home/user/Coding/Rust/strace-redox" } +# redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } +redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } +# strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox", branch = "wip" } +strace = { path = "/home/user/Coding/Rust/strace-redox" } diff --git a/src/main.rs b/src/main.rs index e7453cc..a7848f0 100644 --- a/src/main.rs +++ b/src/main.rs @@ -55,10 +55,12 @@ fn page_fault_test() -> Result<(), String> { pub fn ptrace() -> Result<(), String> { use std::{ - fs::File, + fs::{File, OpenOptions}, io, mem, - os::unix::io::{AsRawFd, FromRawFd, RawFd} + os::unix::io::{AsRawFd, FromRawFd, RawFd}, + thread, + time::Duration, }; use strace::*; @@ -224,7 +226,7 @@ pub fn ptrace() -> Result<(), String> { // Stop and attach process + get handle to registers. This also // tests the behavior of dup(...) - let proc_file = e(File::open(format!("proc:{}/trace", pid)))?; + let proc_file = e(OpenOptions::new().read(true).write(true).truncate(true).open(format!("proc:{}/trace", pid)))?; let regs_file = unsafe { File::from_raw_fd(e(syscall::dup(proc_file.as_raw_fd() as usize, b"regs/int"))? as RawFd) }; @@ -241,25 +243,34 @@ pub fn ptrace() -> Result<(), String> { mem: e(Memory::attach(pid))? }; + fn next(tracer: &mut Tracer, flags: Flags) -> io::Result<&mut Tracer> { + let event = tracer.next(flags)?; + assert_eq!(event.cause & flags, event.cause); + Ok(tracer) + } + println!("Schedule restart of process when resumed..."); e(syscall::kill(pid, syscall::SIGCONT))?; + println!("But the process won't be restarted until then"); + thread::sleep(Duration::from_secs(1)); + println!("Stepping away from the syscall instruction..."); - e(tracer.next(Stop::INSTRUCTION))?; + e(next(&mut tracer, Flags::STOP_SINGLESTEP))?; println!("Testing basic singlestepping..."); - assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 1); - assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 2); - assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 2); - assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 3); - assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 2); - assert_eq!(e(e(tracer.next(Stop::INSTRUCTION))?.regs.get_int())?.rax, 1); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SINGLESTEP))?.regs.get_int())?.rax, 1); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SINGLESTEP))?.regs.get_int())?.rax, 2); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SINGLESTEP))?.regs.get_int())?.rax, 2); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SINGLESTEP))?.regs.get_int())?.rax, 3); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SINGLESTEP))?.regs.get_int())?.rax, 2); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SINGLESTEP))?.regs.get_int())?.rax, 1); println!("Testing memory access..."); - e(tracer.next(Stop::INSTRUCTION))?; - e(tracer.next(Stop::INSTRUCTION))?; + e(next(&mut tracer, Flags::STOP_SINGLESTEP))?; + e(next(&mut tracer, Flags::STOP_SINGLESTEP))?; - e(tracer.next(Stop::INSTRUCTION))?; + e(next(&mut tracer, Flags::STOP_SINGLESTEP))?; let regs = e(tracer.regs.get_int())?; unsafe { @@ -273,11 +284,11 @@ pub fn ptrace() -> Result<(), String> { assert_eq!(e(tracer.mem.cursor())? as usize, regs.rsp + out.bytes.len()); } - e(tracer.next(Stop::INSTRUCTION))?; + e(next(&mut tracer, Flags::STOP_SINGLESTEP))?; println!("Testing floating point..."); for _ in 0..3 { - e(tracer.next(Stop::INSTRUCTION))?; + e(next(&mut tracer, Flags::STOP_SINGLESTEP))?; } let regs = e(tracer.regs.get_float())?; let f = regs.st_space_nth(0); @@ -286,74 +297,72 @@ pub fn ptrace() -> Result<(), String> { assert!((f - 5.65685424949238).abs() < std::f64::EPSILON); println!("Testing fork event"); - assert!(e(tracer.next_event(Stop::SYSCALL))?.is_none()); // pre-syscall - let mut handler = e(tracer.next_event(Stop::SYSCALL))?.ok_or("Syscall completed without yielding fork event")?; // post-syscall - let events = e(handler.iter().collect::>>())?; + e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::EVENT_CLONE))?; + let mut handler = e(tracer.next_event(Flags::STOP_POST_SYSCALL | Flags::EVENT_CLONE))?; - assert_eq!(events.len(), 1); - match events[0] { - PtraceEvent::Clone(pid) => println!("Obtained fork (PID {})", pid), + let event = e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; + match event.data { + EventData::EventClone(pid) => println!("Obtained fork (PID {})", pid), ref e => return Err(format!("Wrong event type: {:?}", e)) } - assert!(e(handler.retry())?.is_none()); + + e(handler.retry())?; + let event = e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; + assert_eq!(event.cause, Flags::STOP_POST_SYSCALL); println!("Testing fork event - but actually handling the fork"); - for _ in 0..3 { // pre-post-waitpid, pre-clone - assert!(e(tracer.next_event(Stop::SYSCALL))?.is_none()); - } - let mut handler = e(tracer.next_event(Stop::SYSCALL))?.ok_or("Syscall completed without yielding fork event")?; - // handler = e(handler.retry())?.ok_or("Program completed without yielding fork event")?; - let events = e(handler.iter().collect::>>())?; - assert_eq!(events.len(), 1); - match events[0] { - PtraceEvent::Clone(pid) => { + assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::EVENT_CLONE))?.regs.get_int())?.rax, syscall::SYS_WAITPID); + e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?; + assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_CLONE); + let mut handler = e(tracer.next_event(Flags::STOP_PRE_SYSCALL | Flags::EVENT_CLONE))?; + + let event = e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; + match event.data { + EventData::EventClone(pid) => { let mut child = e(Tracer::attach(pid))?; println!("-> Fork attached (PID {})", pid); - assert_eq!(e(e(child.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETPID); - e(child.next(Stop::SYSCALL))?; + assert_eq!(e(e(next(&mut child, Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETPID); + e(child.next(Flags::STOP_POST_SYSCALL))?; println!("-> Fork executed GETPID"); - assert_eq!(e(e(child.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_EXIT); - assert_eq!(child.next(Stop::COMPLETION).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + assert_eq!(e(e(next(&mut child, Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_EXIT); + assert_eq!(child.next(Flags::empty()).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); println!("-> Fork executed EXIT"); }, ref e => return Err(format!("Wrong event type: {:?}", e)) } - assert!(e(handler.retry())?.is_none()); + e(handler.retry())?; + e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; println!("Testing signals"); - assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGACTION); - e(tracer.next(Stop::SYSCALL))?; // post-syscall sigaction - assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETPID); - e(tracer.next(Stop::SYSCALL))?; // post-syscall getpid - assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_KILL); - // kill doesn't return *yet* + assert_eq!(e(tracer.regs.get_int())?.rax, syscall::SYS_SIGACTION); + e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?; + assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETPID); + e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?; + assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_KILL); - let mut handler = e(tracer.next_event(Stop::SYSCALL))?.ok_or("Syscall completed without yielding event")?; - let events = e(handler.iter().collect::>>())?; + let event = e(tracer.next(Flags::STOP_PRE_SYSCALL | Flags::STOP_SIGNAL))?; - assert_eq!(events.len(), 1); - match events[0] { - PtraceEvent::Signal(signal) => { + assert_eq!(event.cause, Flags::STOP_SIGNAL); + match event.data { + EventData::StopSignal(signal, handler) => { assert_eq!(signal, syscall::SIGUSR1); - println!("Obtained signal"); + assert_ne!(handler, syscall::SIG_DFL); + assert_ne!(handler, syscall::SIG_IGN); }, ref e => return Err(format!("Wrong event type: {:?}", e)) } - assert!(e(handler.retry())?.is_none()); for i in 0..2 { - assert_eq!(e(tracer.regs.get_int())?.rax, syscall::SYS_YIELD); - e(tracer.next(Stop::SYSCALL))?; // post-syscall yield - assert_eq!(e(e(tracer.next(Stop::SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGRETURN); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_YIELD); + e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?; + assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_SIGRETURN); // sigreturn doesn't return - e(tracer.next(Stop::SYSCALL))?; // post-syscall kill! + e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?; // post-syscall kill! if i == 0 { - e(tracer.next(Stop::SIGNAL))?; - assert_eq!(e(tracer.regs.get_int())?.rax, syscall::SYS_KILL); - e(tracer.next(Stop::SYSCALL))?; + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SIGNAL))?.regs.get_int())?.rax, syscall::SYS_KILL); } } @@ -361,15 +370,15 @@ pub fn ptrace() -> Result<(), String> { let mut tracer = e(tracer.nonblocking())?; println!("Testing behavior of obsolete breakpoints..."); - e(tracer.next(Stop::SYSCALL))?; - e(tracer.next(Stop::COMPLETION))?; + e(tracer.next(Flags::STOP_PRE_SYSCALL | Flags::STOP_POST_SYSCALL))?; + e(tracer.next(Flags::empty()))?; println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax); println!("Waiting for next signal from tracee that it's ready to be traced again..."); e(syscall::waitpid(pid, &mut status, syscall::WUNTRACED))?; println!("Setting sysemu breakpoint..."); - e(tracer.next(Stop::SYSCALL | Stop::SYSEMU))?; + e(tracer.next(Flags::STOP_PRE_SYSCALL))?; println!("Schedule restart of process after breakpoint is set..."); e(syscall::kill(pid, syscall::SIGCONT))?; @@ -381,7 +390,8 @@ pub fn ptrace() -> Result<(), String> { println!("Waiting... Five times... To make sure it doesn't get stuck forever..."); for _ in 0..5 { - e(tracer.wait())?; + e(tracer.next(Flags::FLAG_WAIT))?; + tracer.events().for_each(|_| ()); } println!("Overriding GETPID call..."); @@ -393,11 +403,11 @@ pub fn ptrace() -> Result<(), String> { let mut tracer = e(tracer.blocking())?; println!("Checking exit syscall..."); - e(tracer.next(Stop::SYSCALL))?; + e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::FLAG_SYSEMU))?; let regs = e(tracer.regs.get_int())?; assert_eq!(regs.rax, syscall::SYS_EXIT); assert_eq!(regs.rdi, 123); - assert_eq!(tracer.next(Stop::SYSCALL).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + assert_eq!(next(&mut tracer, Flags::STOP_POST_SYSCALL).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); println!("Checking exit status (waitpid nohang)..."); let mut status = 0; From 05ba87573a0e220642e41fa8d57021e554c2b1bf Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sat, 27 Jul 2019 16:07:43 +0200 Subject: [PATCH 11/19] Update dependencies --- Cargo.lock | 137 ++++++++++++++++++++++++++++++++++++++++++++++++++++ src/main.rs | 4 +- 2 files changed, 139 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 0e10041..9f16b27 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -9,6 +9,23 @@ dependencies = [ "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "ansi_term" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "atty" +version = "0.2.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", + "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "bitflags" version = "0.7.0" @@ -24,6 +41,20 @@ name = "byteorder" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "clap" +version = "2.33.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", + "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", + "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", + "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "cloudabi" version = "0.0.3" @@ -55,6 +86,14 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" +[[package]] +name = "heck" +version = "0.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "libc" version = "0.2.43" @@ -160,6 +199,22 @@ dependencies = [ "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "proc-macro2" +version = "0.4.30" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "quote" +version = "0.6.13" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", +] + [[package]] name = "rand" version = "0.4.3" @@ -206,6 +261,9 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.1.56" +dependencies = [ + "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] [[package]] name = "rustc-serialize" @@ -240,8 +298,72 @@ version = "0.1.0" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56", + "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", ] +[[package]] +name = "strsim" +version = "0.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "structopt" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", + "structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "structopt-derive" +version = "0.2.18" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "syn" +version = "0.15.42" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", + "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", + "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "textwrap" +version = "0.11.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +dependencies = [ + "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", +] + +[[package]] +name = "unicode-segmentation" +version = "1.3.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-width" +version = "0.1.5" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "unicode-xid" +version = "0.1.0" +source = "registry+https://github.com/rust-lang/crates.io-index" + +[[package]] +name = "vec_map" +version = "0.8.1" +source = "registry+https://github.com/rust-lang/crates.io-index" + [[package]] name = "winapi" version = "0.3.6" @@ -274,13 +396,17 @@ dependencies = [ ] [metadata] +"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" +"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" +"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" +"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" @@ -293,6 +419,8 @@ dependencies = [ "checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad" "checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" "checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" +"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" +"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" @@ -302,6 +430,15 @@ dependencies = [ "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" +"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" +"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" +"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" +"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" +"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" +"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" +"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" +"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/src/main.rs b/src/main.rs index a7848f0..3c4e145 100644 --- a/src/main.rs +++ b/src/main.rs @@ -64,7 +64,7 @@ pub fn ptrace() -> Result<(), String> { }; use strace::*; - let pid = e(unsafe { syscall::clone(0) })?; + let pid = e(unsafe { syscall::clone(syscall::CloneFlags::empty()) })?; if pid == 0 { extern "C" fn sighandler(_: usize) { unsafe { @@ -391,7 +391,7 @@ pub fn ptrace() -> Result<(), String> { println!("Waiting... Five times... To make sure it doesn't get stuck forever..."); for _ in 0..5 { e(tracer.next(Flags::FLAG_WAIT))?; - tracer.events().for_each(|_| ()); + e(tracer.events())?.for_each(|_| ()); } println!("Overriding GETPID call..."); From 6234cb4d1350d575a5390b52d904dac4ff44708e Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Tue, 30 Jul 2019 15:54:45 +0200 Subject: [PATCH 12/19] Test ignoring signals --- src/main.rs | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index 3c4e145..2962730 100644 --- a/src/main.rs +++ b/src/main.rs @@ -170,9 +170,15 @@ pub fn ptrace() -> Result<(), String> { mov rsi, 10 // SIGUSR1 syscall - // aaand again + // and again mov rax, 37 // SYS_KILL syscall + // aaaaand yet again... + mov rax, 37 // SYS_KILL + syscall + + mov rax, 158 // SYS_KILL + syscall // Test behavior if tracer aborts a breakpoint before it's reached call wait_for_a_while @@ -366,6 +372,11 @@ pub fn ptrace() -> Result<(), String> { } } + println!("Testing ignoring signals"); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_SIGNAL))?.regs.get_int())?.rax, syscall::SYS_KILL); + assert_eq!(e(e(next(&mut tracer, Flags::FLAG_IGNORE | Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_YIELD); + assert_eq!(e(e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?.regs.get_int())?.rax, 0); + // Activate nonblock let mut tracer = e(tracer.nonblocking())?; @@ -403,7 +414,7 @@ pub fn ptrace() -> Result<(), String> { let mut tracer = e(tracer.blocking())?; println!("Checking exit syscall..."); - e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::FLAG_SYSEMU))?; + e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::FLAG_IGNORE))?; let regs = e(tracer.regs.get_int())?; assert_eq!(regs.rax, syscall::SYS_EXIT); assert_eq!(regs.rdi, 123); From f49822d82abb0ef1eb21ca7700e37bc5119f01ab Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Wed, 31 Jul 2019 17:01:31 +0200 Subject: [PATCH 13/19] Test int3 --- src/main.rs | 22 +++++++++++++++++----- 1 file changed, 17 insertions(+), 5 deletions(-) diff --git a/src/main.rs b/src/main.rs index 2962730..eb19619 100644 --- a/src/main.rs +++ b/src/main.rs @@ -176,8 +176,10 @@ pub fn ptrace() -> Result<(), String> { // aaaaand yet again... mov rax, 37 // SYS_KILL syscall + // test int3 + int3 - mov rax, 158 // SYS_KILL + mov rax, 200 // SYS_GETGID syscall // Test behavior if tracer aborts a breakpoint before it's reached @@ -372,10 +374,20 @@ pub fn ptrace() -> Result<(), String> { } } - println!("Testing ignoring signals"); - assert_eq!(e(e(next(&mut tracer, Flags::STOP_SIGNAL))?.regs.get_int())?.rax, syscall::SYS_KILL); - assert_eq!(e(e(next(&mut tracer, Flags::FLAG_IGNORE | Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_YIELD); - assert_eq!(e(e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?.regs.get_int())?.rax, 0); + println!("Test ignoring signal"); + let event = e(tracer.next(Flags::STOP_SIGNAL | Flags::STOP_POST_SYSCALL))?; + assert_eq!(e(tracer.regs.get_int())?.rax, syscall::SYS_KILL); + assert_eq!(event.cause, Flags::STOP_SIGNAL); + match event.data { + EventData::StopSignal(signal, _) => assert_eq!(signal, syscall::SIGUSR1), + ref e => return Err(format!("Wrong event type: {:?}", e)) + } + + println!("Test ignoring int3"); + let event = e(tracer.next(Flags::FLAG_IGNORE | Flags::STOP_BREAKPOINT))?; + assert_eq!(event.cause, Flags::STOP_BREAKPOINT); + assert_eq!(e(e(next(&mut tracer, Flags::FLAG_IGNORE | Flags::STOP_PRE_SYSCALL))?.regs.get_int())?.rax, syscall::SYS_GETGID); + e(next(&mut tracer, Flags::STOP_POST_SYSCALL))?; // Activate nonblock let mut tracer = e(tracer.nonblocking())?; From b5045b3cecd8989c9ac80e2591d23bef31136e3d Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Thu, 15 Aug 2019 14:27:34 +0200 Subject: [PATCH 14/19] Add ptrace exit breakpoint This will let you stop at process exit and inspect it right before the process dies. --- src/main.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index eb19619..a8a6c1d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -426,13 +426,26 @@ pub fn ptrace() -> Result<(), String> { let mut tracer = e(tracer.blocking())?; println!("Checking exit syscall..."); - e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::FLAG_IGNORE))?; + e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::STOP_EXIT | Flags::FLAG_IGNORE))?; let regs = e(tracer.regs.get_int())?; assert_eq!(regs.rax, syscall::SYS_EXIT); assert_eq!(regs.rdi, 123); - assert_eq!(next(&mut tracer, Flags::STOP_POST_SYSCALL).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + + println!("Checking exit breakpoint..."); + let event = e(tracer.next(Flags::STOP_POST_SYSCALL | Flags::STOP_EXIT))?; + + assert_eq!(event.cause, Flags::STOP_EXIT); + match event.data { + EventData::StopExit(status) => { + assert!(syscall::wifexited(status)); + assert_eq!(syscall::wexitstatus(status), 123); + }, + ref e => return Err(format!("Wrong event type: {:?}", e)) + } println!("Checking exit status (waitpid nohang)..."); + assert_eq!(next(&mut tracer, Flags::STOP_POST_SYSCALL | Flags::STOP_EXIT).unwrap_err().raw_os_error(), Some(syscall::ESRCH)); + let mut status = 0; e(syscall::waitpid(pid, &mut status, syscall::WNOHANG))?; assert!(syscall::wifexited(status)); From 2221bf91ac8221a41e7ca8a9950d6a00672ac77a Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Sat, 16 May 2020 14:20:16 +0200 Subject: [PATCH 15/19] Use published git versions of everything --- Cargo.lock | 144 +++-------------------------------------------------- Cargo.toml | 7 +-- 2 files changed, 9 insertions(+), 142 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 9f16b27..6f89fb7 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -4,28 +4,11 @@ name = "acid" version = "0.1.0" dependencies = [ - "redox_syscall 0.1.56", - "strace 0.1.0", + "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)", + "strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "ansi_term" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "atty" -version = "0.2.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)", - "winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "bitflags" version = "0.7.0" @@ -41,20 +24,6 @@ name = "byteorder" version = "0.5.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "clap" -version = "2.33.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)", - "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)", - "textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", - "vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "cloudabi" version = "0.0.3" @@ -86,14 +55,6 @@ name = "fuchsia-zircon-sys" version = "0.3.3" source = "registry+https://github.com/rust-lang/crates.io-index" -[[package]] -name = "heck" -version = "0.3.1" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "libc" version = "0.2.43" @@ -199,22 +160,6 @@ dependencies = [ "siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "proc-macro2" -version = "0.4.30" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "quote" -version = "0.6.13" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", -] - [[package]] name = "rand" version = "0.4.3" @@ -261,6 +206,7 @@ dependencies = [ [[package]] name = "redox_syscall" version = "0.1.56" +source = "git+https://gitlab.redox-os.org/redox-os/syscall.git#8d0015be8693a81c2a4459f3c09fb47b98ff07b1" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -295,75 +241,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strace" version = "0.1.0" +source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#d9ac25ad730fdb1c1810cd69b00df59dddb60f3f" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", - "redox_syscall 0.1.56", - "structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", + "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)", ] -[[package]] -name = "strsim" -version = "0.8.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "structopt" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)", - "structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "structopt-derive" -version = "0.2.18" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)", - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "syn" -version = "0.15.42" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)", - "quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)", - "unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "textwrap" -version = "0.11.0" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "unicode-segmentation" -version = "1.3.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-width" -version = "0.1.5" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "unicode-xid" -version = "0.1.0" -source = "registry+https://github.com/rust-lang/crates.io-index" - -[[package]] -name = "vec_map" -version = "0.8.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "winapi" version = "0.3.6" @@ -396,17 +279,13 @@ dependencies = [ ] [metadata] -"checksum ansi_term 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ee49baf6cb617b853aa8d93bf420db2383fab46d314482ca2803b40d5fde979b" -"checksum atty 0.2.13 (registry+https://github.com/rust-lang/crates.io-index)" = "1803c647a3ec87095e7ae7acfca019e98de5ec9a7d01343f611cf3152ed71a90" "checksum bitflags 0.7.0 (registry+https://github.com/rust-lang/crates.io-index)" = "aad18937a628ec6abcd26d1489012cc0e18c21798210f491af69ded9b881106d" "checksum bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "3d155346769a6855b86399e9bc3814ab343cd3d62c7e985113d46a0ec3c281fd" "checksum byteorder 0.5.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0fc10e8cc6b2580fda3f36eb6dc5316657f812a3df879a44a66fc9f0fdbc4855" -"checksum clap 2.33.0 (registry+https://github.com/rust-lang/crates.io-index)" = "5067f5bb2d80ef5d68b4c87db81601f0b75bca627bc2ef76b141d7b846a3c6d9" "checksum cloudabi 0.0.3 (registry+https://github.com/rust-lang/crates.io-index)" = "ddfc5b9aa5d4507acaf872de71051dfd0e309860e88966e1051e462a077aac4f" "checksum csv 0.14.7 (registry+https://github.com/rust-lang/crates.io-index)" = "266c1815d7ca63a5bd86284043faf91e8c95e943e55ce05dc0ae08e952de18bc" "checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" "checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" -"checksum heck 0.3.1 (registry+https://github.com/rust-lang/crates.io-index)" = "20564e78d53d2bb135c343b3f47714a56af2061f1c928fdb541dc7b9fdd94205" "checksum libc 0.2.43 (registry+https://github.com/rust-lang/crates.io-index)" = "76e3a3ef172f1a0b9a9ff0dd1491ae5e6c948b94479a3021819ba7d860c8645d" "checksum num 0.1.42 (registry+https://github.com/rust-lang/crates.io-index)" = "4703ad64153382334aa8db57c637364c322d3372e097840c72000dabdcf6156e" "checksum num-bigint 0.1.44 (registry+https://github.com/rust-lang/crates.io-index)" = "e63899ad0da84ce718c14936262a41cee2c79c981fc0a0e7c7beb47d5a07e8c1" @@ -419,26 +298,17 @@ dependencies = [ "checksum phf_codegen 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "7d187f00cd98d5afbcd8898f6cf181743a449162aeb329dcd2f3849009e605ad" "checksum phf_generator 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "03dc191feb9b08b0dc1330d6549b795b9d81aec19efe6b4a45aec8d4caee0c4b" "checksum phf_shared 0.7.23 (registry+https://github.com/rust-lang/crates.io-index)" = "b539898d22d4273ded07f64a05737649dc69095d92cb87c7097ec68e3f150b93" -"checksum proc-macro2 0.4.30 (registry+https://github.com/rust-lang/crates.io-index)" = "cf3d2011ab5c909338f7887f4fc896d35932e29146c12c8d01da6b22a80ba759" -"checksum quote 0.6.13 (registry+https://github.com/rust-lang/crates.io-index)" = "6ce23b6b870e8f94f81fb0a363d65d86675884b34a09043c81e5562f11c1f8e1" "checksum rand 0.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "8356f47b32624fef5b3301c1be97e5944ecdd595409cc5da11d05f211db6cfbd" "checksum rand 0.5.5 (registry+https://github.com/rust-lang/crates.io-index)" = "e464cd887e869cddcae8792a4ee31d23c7edd516700695608f5b98c67ee0131c" "checksum rand_core 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "1961a422c4d189dfb50ffa9320bf1f2a9bd54ecb92792fb9477f99a1045f3372" "checksum rand_core 0.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "0905b6b7079ec73b314d4c748701f6931eb79fd97c668caa3f1899b22b32c6db" "checksum raw-cpuid 2.0.2 (registry+https://github.com/rust-lang/crates.io-index)" = "13b844e4049605ff38fed943f5c7b2c691fad68d9d5bf074d2720554c4e48246" +"checksum redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)" = "" "checksum rustc-serialize 0.3.24 (registry+https://github.com/rust-lang/crates.io-index)" = "dcf128d1287d2ea9d80910b5f1120d0b8eede3fbf1abe91c40d39ea7d51e6fda" "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum strsim 0.8.0 (registry+https://github.com/rust-lang/crates.io-index)" = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" -"checksum structopt 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "16c2cdbf9cc375f15d1b4141bc48aeef444806655cd0e904207edc8d68d86ed7" -"checksum structopt-derive 0.2.18 (registry+https://github.com/rust-lang/crates.io-index)" = "53010261a84b37689f9ed7d395165029f9cc7abb9f56bbfe86bee2597ed25107" -"checksum syn 0.15.42 (registry+https://github.com/rust-lang/crates.io-index)" = "eadc09306ca51a40555dd6fc2b415538e9e18bc9f870e47b1a524a79fe2dcf5e" -"checksum textwrap 0.11.0 (registry+https://github.com/rust-lang/crates.io-index)" = "d326610f408c7a4eb6f51c37c330e496b08506c9457c9d34287ecc38809fb060" -"checksum unicode-segmentation 1.3.0 (registry+https://github.com/rust-lang/crates.io-index)" = "1967f4cdfc355b37fd76d2a954fb2ed3871034eb4f26d60537d88795cfc332a9" -"checksum unicode-width 0.1.5 (registry+https://github.com/rust-lang/crates.io-index)" = "882386231c45df4700b275c7ff55b6f3698780a650026380e72dabe76fa46526" -"checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" -"checksum vec_map 0.8.1 (registry+https://github.com/rust-lang/crates.io-index)" = "05c78687fb1a80548ae3250346c3db86a80a7cdd77bda190189f2d0a0987c81a" +"checksum strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)" = "" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 97de28a..d90b442 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -6,8 +6,5 @@ edition = "2018" [dependencies] x86 = "0.7" -# redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } -# redox_syscall = { git = "https://gitlab.redox-os.org/jD91mZM2/syscall.git", branch = "ptrace" } -redox_syscall = { path = "/home/user/redox-nix/redox/kernel/syscall" } -# strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox", branch = "wip" } -strace = { path = "/home/user/Coding/Rust/strace-redox" } +redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } +strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox", default-features = false } From 0aa7ee8007c0be5a11c1b71dab4b73325fce7caa Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 15 Jun 2020 14:00:46 +0200 Subject: [PATCH 16/19] Make sure SIGSTOP works --- src/main.rs | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/src/main.rs b/src/main.rs index a8a6c1d..4ee6ff2 100644 --- a/src/main.rs +++ b/src/main.rs @@ -58,7 +58,10 @@ pub fn ptrace() -> Result<(), String> { fs::{File, OpenOptions}, io, mem, - os::unix::io::{AsRawFd, FromRawFd, RawFd}, + os::unix::{ + fs::OpenOptionsExt, + io::{AsRawFd, FromRawFd, RawFd}, + }, thread, time::Duration, }; @@ -230,11 +233,20 @@ pub fn ptrace() -> Result<(), String> { let mut status = 0; e(syscall::waitpid(pid, &mut status, syscall::WUNTRACED))?; + println!("The process is stopped, of course, so it shouldn't mind if we sleep here"); + thread::sleep(Duration::from_secs(1)); + println!("Done! Attaching tracer..."); // Stop and attach process + get handle to registers. This also // tests the behavior of dup(...) - let proc_file = e(OpenOptions::new().read(true).write(true).truncate(true).open(format!("proc:{}/trace", pid)))?; + let proc_file = e( + OpenOptions::new() + .read(true) + .write(true) + .truncate(true) + .custom_flags(syscall::O_EXCL as i32) + .open(format!("proc:{}/trace", pid)))?; let regs_file = unsafe { File::from_raw_fd(e(syscall::dup(proc_file.as_raw_fd() as usize, b"regs/int"))? as RawFd) }; From 79ca7e884115aee50b19616e5b70807ff6e252e3 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Mon, 15 Jun 2020 17:17:09 +0200 Subject: [PATCH 17/19] Additional checks related to cloning/forking --- src/main.rs | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/main.rs b/src/main.rs index 4ee6ff2..c53ac01 100644 --- a/src/main.rs +++ b/src/main.rs @@ -317,18 +317,22 @@ pub fn ptrace() -> Result<(), String> { assert!((f - 5.65685424949238).abs() < std::f64::EPSILON); println!("Testing fork event"); - e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::EVENT_CLONE))?; + assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::EVENT_CLONE))?.regs.get_int())?.rax, syscall::SYS_CLONE); let mut handler = e(tracer.next_event(Flags::STOP_POST_SYSCALL | Flags::EVENT_CLONE))?; let event = e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; - match event.data { - EventData::EventClone(pid) => println!("Obtained fork (PID {})", pid), + let clone_pid = match event.data { + EventData::EventClone(pid) => { + println!("Obtained fork (PID {})", pid); + pid + }, ref e => return Err(format!("Wrong event type: {:?}", e)) - } + }; e(handler.retry())?; let event = e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; assert_eq!(event.cause, Flags::STOP_POST_SYSCALL); + assert_eq!(e(tracer.regs.get_int())?.rax, clone_pid); println!("Testing fork event - but actually handling the fork"); assert_eq!(e(e(next(&mut tracer, Flags::STOP_PRE_SYSCALL | Flags::EVENT_CLONE))?.regs.get_int())?.rax, syscall::SYS_WAITPID); From 0985142bcb7cf8f087c2c3a23841303fbb132f66 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Tue, 16 Jun 2020 14:02:01 +0200 Subject: [PATCH 18/19] Add missing wait in ptrace test --- Cargo.lock | 4 +--- Cargo.toml | 3 ++- src/main.rs | 28 ++++++++++++++++++++-------- 3 files changed, 23 insertions(+), 12 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 6f89fb7..890b95d 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ name = "acid" version = "0.1.0" dependencies = [ "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)", - "strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)", + "strace 0.1.0", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -241,7 +241,6 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strace" version = "0.1.0" -source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#d9ac25ad730fdb1c1810cd69b00df59dddb60f3f" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)", @@ -308,7 +307,6 @@ dependencies = [ "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" -"checksum strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)" = "" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index d90b442..0255671 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,4 +7,5 @@ edition = "2018" [dependencies] x86 = "0.7" redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } -strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox", default-features = false } +strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox", branch = "wip", default-features = false } +#strace = { path = "../../strace/source", default-features = false } diff --git a/src/main.rs b/src/main.rs index c53ac01..f5eb681 100644 --- a/src/main.rs +++ b/src/main.rs @@ -56,7 +56,7 @@ fn page_fault_test() -> Result<(), String> { pub fn ptrace() -> Result<(), String> { use std::{ fs::{File, OpenOptions}, - io, + io::{self, prelude::*}, mem, os::unix::{ fs::OpenOptionsExt, @@ -329,7 +329,6 @@ pub fn ptrace() -> Result<(), String> { ref e => return Err(format!("Wrong event type: {:?}", e)) }; - e(handler.retry())?; let event = e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; assert_eq!(event.cause, Flags::STOP_POST_SYSCALL); assert_eq!(e(tracer.regs.get_int())?.rax, clone_pid); @@ -356,7 +355,6 @@ pub fn ptrace() -> Result<(), String> { }, ref e => return Err(format!("Wrong event type: {:?}", e)) } - e(handler.retry())?; e(e(handler.pop_one())?.ok_or("Expected event but none occured"))?; println!("Testing signals"); @@ -411,11 +409,23 @@ pub fn ptrace() -> Result<(), String> { println!("Testing behavior of obsolete breakpoints..."); e(tracer.next(Flags::STOP_PRE_SYSCALL | Flags::STOP_POST_SYSCALL))?; e(tracer.next(Flags::empty()))?; + + // also, we're nonblocking, can't wait for next event like that + assert_eq!(e(tracer.events())?.next().unwrap().unwrap_err().kind(), io::ErrorKind::WouldBlock); + println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax); println!("Waiting for next signal from tracee that it's ready to be traced again..."); e(syscall::waitpid(pid, &mut status, syscall::WUNTRACED))?; + println!("Preparing event scheme"); + let mut eventfd = e(File::open("event:"))?; + e(eventfd.write(&syscall::Event { + id: tracer.file.as_raw_fd() as usize, + flags: syscall::EVENT_READ, + data: 0, + }))?; + println!("Setting sysemu breakpoint..."); e(tracer.next(Flags::STOP_PRE_SYSCALL))?; @@ -427,11 +437,13 @@ pub fn ptrace() -> Result<(), String> { println!("Tracee RAX: {}", e(tracer.regs.get_int())?.rax); } - println!("Waiting... Five times... To make sure it doesn't get stuck forever..."); - for _ in 0..5 { - e(tracer.next(Flags::FLAG_WAIT))?; - e(tracer.events())?.for_each(|_| ()); - } + println!("Waiting using event scheme"); + let mut event = syscall::Event::default(); + e(eventfd.read(&mut event))?; + + println!("Consuming events"); + + e(tracer.events())?.for_each(|_| ()); println!("Overriding GETPID call..."); let mut regs = e(tracer.regs.get_int())?; From b0f677c4f1813d41d1644c0d04fc6f7ad1118b38 Mon Sep 17 00:00:00 2001 From: jD91mZM2 Date: Tue, 16 Jun 2020 15:33:23 +0200 Subject: [PATCH 19/19] Use master branch of strace-redox --- Cargo.lock | 4 +++- Cargo.toml | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/Cargo.lock b/Cargo.lock index 890b95d..04fd227 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -5,7 +5,7 @@ name = "acid" version = "0.1.0" dependencies = [ "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)", - "strace 0.1.0", + "strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)", "x86 0.7.2 (registry+https://github.com/rust-lang/crates.io-index)", ] @@ -241,6 +241,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" [[package]] name = "strace" version = "0.1.0" +source = "git+https://gitlab.redox-os.org/redox-os/strace-redox#d7f7921f50bb03fe855f27a439d2d9c2eac45646" dependencies = [ "bitflags 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)", "redox_syscall 0.1.56 (git+https://gitlab.redox-os.org/redox-os/syscall.git)", @@ -307,6 +308,7 @@ dependencies = [ "checksum serde 0.6.15 (registry+https://github.com/rust-lang/crates.io-index)" = "c97b18e9e53de541f11e497357d6c5eaeb39f0cb9c8734e274abe4935f6991fa" "checksum serde_json 0.6.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b5aaee47e038bf9552d30380d3973fff2593ee0a76d81ad4c581f267cdcadf36" "checksum siphasher 0.2.3 (registry+https://github.com/rust-lang/crates.io-index)" = "0b8de496cf83d4ed58b6be86c3a275b8602f6ffe98d3024a869e124147a9a3ac" +"checksum strace 0.1.0 (git+https://gitlab.redox-os.org/redox-os/strace-redox)" = "" "checksum winapi 0.3.6 (registry+https://github.com/rust-lang/crates.io-index)" = "92c1eb33641e276cfa214a0522acad57be5c56b10cb348b3c5117db75f3ac4b0" "checksum winapi-i686-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ac3b87c63620426dd9b991e5ce0329eff545bccbbb34f3be09ff6fb6ab51b7b6" "checksum winapi-x86_64-pc-windows-gnu 0.4.0 (registry+https://github.com/rust-lang/crates.io-index)" = "712e227841d057c1ee1cd2fb22fa7e5a5461ae8e48fa2ca79ec42cfc1931183f" diff --git a/Cargo.toml b/Cargo.toml index 0255671..789cad1 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -7,5 +7,5 @@ edition = "2018" [dependencies] x86 = "0.7" redox_syscall = { git = "https://gitlab.redox-os.org/redox-os/syscall.git" } -strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox", branch = "wip", default-features = false } +strace = { git = "https://gitlab.redox-os.org/redox-os/strace-redox", default-features = false } #strace = { path = "../../strace/source", default-features = false }