Stub for ptrace
It's happening...
This commit is contained in:
@@ -37,6 +37,7 @@ pub mod sys_epoll;
|
||||
pub mod sys_file;
|
||||
pub mod sys_ioctl;
|
||||
pub mod sys_mman;
|
||||
pub mod sys_ptrace;
|
||||
//pub mod sys_resource;
|
||||
pub mod sys_select;
|
||||
pub mod sys_socket;
|
||||
@@ -45,6 +46,7 @@ pub mod sys_statvfs;
|
||||
pub mod sys_time;
|
||||
pub mod sys_timeb;
|
||||
//pub mod sys_times;
|
||||
pub mod sys_user;
|
||||
pub mod _wctype;
|
||||
pub mod sys_uio;
|
||||
pub mod sys_un;
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = []
|
||||
include_guard = "_SYS_PTRACE_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -0,0 +1,24 @@
|
||||
//! ptrace compatibility layer for Redox OS
|
||||
|
||||
use platform::types::*;
|
||||
use platform::{Sys, PalPtrace};
|
||||
|
||||
pub const PTRACE_PEEKTEXT: c_int = 1;
|
||||
pub const PTRACE_PEEKDATA: c_int = 2;
|
||||
pub const PTRACE_POKETEXT: c_int = 4;
|
||||
pub const PTRACE_POKEDATA: c_int = 5;
|
||||
pub const PTRACE_CONT: c_int = 7;
|
||||
pub const PTRACE_KILL: c_int = 8;
|
||||
pub const PTRACE_SINGLESTEP: c_int = 9;
|
||||
pub const PTRACE_GETREGS: c_int = 12;
|
||||
pub const PTRACE_SETREGS: c_int = 13;
|
||||
pub const PTRACE_GETFPREGS: c_int = 14;
|
||||
pub const PTRACE_SETFPREGS: c_int = 15;
|
||||
pub const PTRACE_ATTACH: c_int = 16;
|
||||
pub const PTRACE_DETACH: c_int = 17;
|
||||
|
||||
#[no_mangle]
|
||||
pub unsafe extern "C" fn ptrace(request: c_int, mut params: ...) -> c_int {
|
||||
// Musl also just grabs the arguments from the varargs...
|
||||
Sys::ptrace(request, params.arg(), params.arg(), params.arg())
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
sys_includes = []
|
||||
include_guard = "_SYS_USER_H"
|
||||
language = "C"
|
||||
style = "Tag"
|
||||
|
||||
[enum]
|
||||
prefix_with_name = true
|
||||
@@ -0,0 +1,52 @@
|
||||
//! A part of the ptrace compatibility for Redox OS
|
||||
|
||||
use platform::types::*;
|
||||
|
||||
#[repr(C)]
|
||||
pub struct user_fpregs_struct {
|
||||
cwd: u16,
|
||||
swd: u16,
|
||||
ftw: u16,
|
||||
fop: u16,
|
||||
rip: u64,
|
||||
rdp: u64,
|
||||
mxcsr: u32,
|
||||
mxcr_mask: u32,
|
||||
st_space: [u32; 32],
|
||||
xmm_space: [u32; 64],
|
||||
padding: [u32; 24]
|
||||
}
|
||||
|
||||
#[repr(C)]
|
||||
pub struct user_regs_struct {
|
||||
r15: c_ulong,
|
||||
r14: c_ulong,
|
||||
r13: c_ulong,
|
||||
r12: c_ulong,
|
||||
rbp: c_ulong,
|
||||
rbx: c_ulong,
|
||||
r11: c_ulong,
|
||||
r10: c_ulong,
|
||||
r9: c_ulong,
|
||||
r8: c_ulong,
|
||||
rax: c_ulong,
|
||||
rcx: c_ulong,
|
||||
rdx: c_ulong,
|
||||
rsi: c_ulong,
|
||||
rdi: c_ulong,
|
||||
orig_rax: c_ulong,
|
||||
rip: c_ulong,
|
||||
cs: c_ulong,
|
||||
eflags: c_ulong,
|
||||
rsp: c_ulong,
|
||||
ss: c_ulong,
|
||||
fs_base: c_ulong,
|
||||
gs_base: c_ulong,
|
||||
ds: c_ulong,
|
||||
es: c_ulong,
|
||||
fs: c_ulong,
|
||||
gs: c_ulong
|
||||
}
|
||||
|
||||
#[no_mangle]
|
||||
pub extern "C" fn _cbindgen_only_generates_structs_if_they_are_mentioned_which_is_dumb(a: user_fpregs_struct, b: user_regs_struct) {}
|
||||
+1
-1
@@ -2,7 +2,6 @@
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_upper_case_globals)]
|
||||
#![allow(unused_variables)]
|
||||
#![feature(alloc)]
|
||||
#![feature(allocator_api)]
|
||||
#![feature(asm)]
|
||||
#![feature(c_variadic)]
|
||||
@@ -13,6 +12,7 @@
|
||||
#![feature(core_intrinsics)]
|
||||
#![feature(global_asm)]
|
||||
// FIXME: Stable on nightly, remove once redox fork is updated
|
||||
#![feature(alloc)]
|
||||
#![feature(iter_copied)]
|
||||
#![feature(lang_items)]
|
||||
#![feature(linkage)]
|
||||
|
||||
@@ -15,6 +15,7 @@ use header::sys_utsname::utsname;
|
||||
use header::time::timespec;
|
||||
|
||||
mod epoll;
|
||||
mod ptrace;
|
||||
mod signal;
|
||||
mod socket;
|
||||
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
use super::super::types::*;
|
||||
use super::super::PalPtrace;
|
||||
use super::{e, Sys};
|
||||
|
||||
impl PalPtrace for Sys {
|
||||
fn ptrace(request: c_int, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> c_int {
|
||||
unsafe { e(syscall!(PTRACE, request, pid, addr, data)) as c_int }
|
||||
}
|
||||
}
|
||||
+1
-1
@@ -12,7 +12,7 @@ mod allocator;
|
||||
#[path = "allocator/ralloc.rs"]
|
||||
mod allocator;
|
||||
|
||||
pub use self::pal::{Pal, PalEpoll, PalSignal, PalSocket};
|
||||
pub use self::pal::{Pal, PalEpoll, PalPtrace, PalSignal, PalSocket};
|
||||
|
||||
mod pal;
|
||||
|
||||
|
||||
@@ -10,6 +10,9 @@ use header::time::timespec;
|
||||
pub use self::epoll::PalEpoll;
|
||||
mod epoll;
|
||||
|
||||
pub use self::ptrace::PalPtrace;
|
||||
mod ptrace;
|
||||
|
||||
pub use self::signal::PalSignal;
|
||||
mod signal;
|
||||
|
||||
|
||||
@@ -0,0 +1,6 @@
|
||||
use super::super::types::*;
|
||||
use super::super::Pal;
|
||||
|
||||
pub trait PalPtrace: Pal {
|
||||
fn ptrace(request: c_int, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> c_int;
|
||||
}
|
||||
@@ -28,6 +28,7 @@ use super::{errno, Pal, Read};
|
||||
|
||||
mod epoll;
|
||||
mod extra;
|
||||
mod ptrace;
|
||||
mod signal;
|
||||
mod socket;
|
||||
|
||||
|
||||
@@ -0,0 +1,10 @@
|
||||
use super::super::types::*;
|
||||
use super::super::PalPtrace;
|
||||
use super::{e, Sys};
|
||||
|
||||
impl PalPtrace for Sys {
|
||||
fn ptrace(request: c_int, pid: pid_t, addr: *mut c_void, data: *mut c_void) -> c_int {
|
||||
// Oh boy, this is not gonna be fun.........
|
||||
unimplemented!()
|
||||
}
|
||||
}
|
||||
@@ -15,6 +15,7 @@ EXPECT_NAMES=\
|
||||
libgen \
|
||||
locale \
|
||||
math \
|
||||
ptrace \
|
||||
regex \
|
||||
select \
|
||||
setjmp \
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
This is printed to STDOUT.
|
||||
Or, at least, that's what I thought.
|
||||
But all write(...) syscalls are actually redirected to STDERR by the tracer.
|
||||
Big surprise, right!
|
||||
@@ -0,0 +1 @@
|
||||
Child exited with status 0
|
||||
@@ -0,0 +1,64 @@
|
||||
#include <signal.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdio.h>
|
||||
#include <sys/ptrace.h>
|
||||
#include <sys/user.h>
|
||||
#include <sys/wait.h>
|
||||
#include <unistd.h>
|
||||
|
||||
#include "test_helpers.h"
|
||||
|
||||
int main() {
|
||||
int pid = fork();
|
||||
ERROR_IF(fork, pid, == -1);
|
||||
|
||||
if (pid == 0) {
|
||||
int result = ptrace(PTRACE_TRACEME, 0, NULL, NULL);
|
||||
ERROR_IF(ptrace, result, == -1);
|
||||
UNEXP_IF(ptrace, result, != 0);
|
||||
|
||||
// Alert parent: I'm ready
|
||||
result = raise(SIGSTOP);
|
||||
ERROR_IF(close, result, == -1);
|
||||
UNEXP_IF(close, result, != 0);
|
||||
|
||||
puts("This is printed to STDOUT.");
|
||||
puts("Or, at least, that's what I thought.");
|
||||
puts("But all write(...) syscalls are actually redirected to STDERR by the tracer.");
|
||||
puts("Big surprise, right!");
|
||||
} else {
|
||||
// Wait for child process to be ready
|
||||
int result = waitpid(pid, NULL, 0);
|
||||
ERROR_IF(close, result, == -1);
|
||||
|
||||
int status;
|
||||
while (true) {
|
||||
// Pre-syscall:
|
||||
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
|
||||
ERROR_IF(close, result, == -1);
|
||||
UNEXP_IF(close, result, != 0);
|
||||
result = waitpid(pid, &status, 0);
|
||||
ERROR_IF(close, result, == -1);
|
||||
if (WIFEXITED(status)) { break; }
|
||||
|
||||
struct user_regs_struct regs;
|
||||
result = ptrace(PTRACE_GETREGS, pid, NULL, ®s);
|
||||
ERROR_IF(close, result, == -1);
|
||||
|
||||
if (regs.orig_rax == 1 || regs.orig_rax == 0x21000004) { // SYS_write on Redox and Linux
|
||||
regs.rdi = 2;
|
||||
result = ptrace(PTRACE_SETREGS, pid, NULL, ®s);
|
||||
ERROR_IF(close, result, == -1);
|
||||
}
|
||||
|
||||
// Post-syscall:
|
||||
result = ptrace(PTRACE_SYSCALL, pid, NULL, NULL);
|
||||
ERROR_IF(close, result, == -1);
|
||||
UNEXP_IF(close, result, != 0);
|
||||
result = waitpid(pid, &status, 0);
|
||||
ERROR_IF(close, result, == -1);
|
||||
if (WIFEXITED(status)) { break; }
|
||||
}
|
||||
printf("Child exited with status %d\n", WEXITSTATUS(status));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user