Skip to content

nix::sys::ptrace desperately needs documentation #649

Open
@marmistrz

Description

@marmistrz

Hi!

First of all - I'm eager to contribute the documentation, once I've understood, how the module should be used.

I was quite new to ptrace and I'm still learning, so I might have missed something obvious, keep this in mind please :)

I had this small piece of code, which simply printed a message, whenever a syscall was entered or exited.

int main() {
    pid_t child = fork();
    if (child == 0) {
        ptrace(PTRACE_TRACEME, 0, NULL, NULL);
        execl("/bin/ls", "ls", NULL);
    } else {
        for (;;) {
            int status;
            wait(&status);
            if (WIFEXITED(status))
                break;
            long orig_rax = ptrace(PTRACE_PEEKUSER, child, 8 * ORIG_RAX, NULL);
            printf("Syscall %ld\n", orig_rax);
            ptrace(PTRACE_SYSCALL, child, NULL, NULL);
        }
    }
    return 0;
}

This worked very well. Now I translated this into Rust.

extern crate colored;
extern crate spawn_ptrace;
extern crate nix;

use std::process::Command;
use nix::sys::ptrace::ptrace;
use nix::sys::ptrace::ptrace::*;
use nix::sys::wait::{wait, WaitStatus};
use std::ptr;
use nix::libc::c_void;

const RAX: i64 = 8 * 15;

fn main() {

    use spawn_ptrace::CommandPtraceSpawn;
    let child = Command::new("ls").arg("-l").spawn_ptrace().unwrap();
    let pid = child.id() as i32;

    loop {
        match wait() {
            Ok(WaitStatus::Exited(_, code)) => assert_eq!(code, 0),
            Ok(WaitStatus::Stopped(_, sig)) => {
                println!("Stopped with a signal: {:?}", sig);
            }
            Ok(s) => panic!("Unexpected stop reason: {:?}", s),
            Err(e) => panic!("Unexpected waitpid error: {:?}", e),
        }

        let orig_rax = ptrace(PTRACE_PEEKUSER, pid, RAX as *mut c_void, ptr::null_mut()).unwrap();
        println!("We've got syscall: {}", orig_rax);

        ptrace(PTRACE_SYSCALL, pid, ptr::null_mut(), ptr::null_mut()).unwrap();
    }
}

No good. Nothing displays, the process is stuck at the wait() forever.

I took a look at the spawn-ptrace crate, which doesn't call wait() before, so next try:

extern crate colored;
extern crate spawn_ptrace;
extern crate nix;

use std::process::Command;
use nix::sys::ptrace::ptrace;
use nix::sys::ptrace::ptrace::*;
use nix::sys::wait::{wait, WaitStatus};
use std::ptr;
use nix::libc::c_void;

const RAX: i64 = 8 * 15;

fn main() {

    use spawn_ptrace::CommandPtraceSpawn;
    let child = Command::new("ls").arg("-l").spawn_ptrace().unwrap();
    let pid = child.id() as i32;

    loop {
        let orig_rax = ptrace(PTRACE_PEEKUSER, pid, RAX as *mut c_void, ptr::null_mut()).unwrap();
        println!("We've got syscall: {}", orig_rax);

        ptrace(PTRACE_SYSCALL, pid, ptr::null_mut(), ptr::null_mut()).unwrap();

        match wait() {
            Ok(WaitStatus::Exited(_, code)) => assert_eq!(code, 0),
            Ok(WaitStatus::Stopped(_, sig)) => {
                println!("Stopped with a signal: {:?}", sig);
            }
            Ok(s) => panic!("Unexpected stop reason: {:?}", s),
            Err(e) => panic!("Unexpected waitpid error: {:?}", e),
        }
    }
}

This displays all syscalls, compared to the C version, but panicks at the end, because the process is not in the stopped state.

We've got syscall: 3
Stopped with a signal: SIGTRAP
We've got syscall: 3
Stopped with a signal: SIGTRAP
We've got syscall: 231
thread 'main' panicked at 'called `Result::unwrap()` on an `Err` value: Sys(ESRCH)', src/libcore/result.rs:859
stack backtrace:
   0: std::sys::imp::backtrace::tracing::imp::unwind_backtrace
   1: std::sys_common::backtrace::_print
   2: std::panicking::default_hook::{{closure}}
   3: std::panicking::default_hook
   4: std::panicking::rust_panic_with_hook
   5: std::panicking::begin_panic
   6: std::panicking::begin_panic_fmt
   7: rust_begin_unwind
   8: core::panicking::panic_fmt
   9: core::result::unwrap_failed
             at /build/rust/src/rustc-1.18.0-src/src/libcore/macros.rs:29
  10: <core::result::Result<T, E>>::unwrap
             at /build/rust/src/rustc-1.18.0-src/src/libcore/result.rs:737
  11: ptrace_rust::main
             at ./src/main.rs:21
  12: __rust_maybe_catch_panic
  13: std::rt::lang_start
  14: main
  15: __libc_start_main
  16: _start

Could anyone explain, how the nix::sys::ptrace module should be used? I'll be happy to contribute the documentation in return.

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions