Commit 5e530967 authored by Jeremy Soller's avatar Jeremy Soller

init

parents
Pipeline #2625 failed with stages
in 46 seconds
/target
**/*.rs.bk
[[package]]
name = "libc"
version = "0.2.47"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "redox_syscall"
version = "0.1.50"
source = "registry+https://github.com/rust-lang/crates.io-index"
[[package]]
name = "rine"
version = "0.1.0"
dependencies = [
"libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)",
"redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)",
"sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)",
]
[[package]]
name = "sc"
version = "0.2.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
[metadata]
"checksum libc 0.2.47 (registry+https://github.com/rust-lang/crates.io-index)" = "48450664a984b25d5b479554c29cc04e3150c97aa4c01da5604a2d4ed9151476"
"checksum redox_syscall 0.1.50 (registry+https://github.com/rust-lang/crates.io-index)" = "52ee9a534dc1301776eff45b4fa92d2c39b1d8c3d3357e6eb593e0d795506fc2"
"checksum sc 0.2.2 (registry+https://github.com/rust-lang/crates.io-index)" = "4ebbb026ba4a707c25caec2db5ef59ad8b41f7ad77cad06257e06229c891f376"
[package]
name = "rine"
version = "0.1.0"
authors = ["Jeremy Soller <jeremy@system76.com>"]
edition = "2018"
[dependencies]
libc = "0.2"
redox_syscall = "0.1"
sc = "0.2"
# rine
Rine is not an emulator. It is a system call translator for Redox binaries
that runs on Linux. But hey, if it makes you feel better:
"(R)edox (i)n a(n) (e)mulator" is fine too.
use std::{process, ptr, slice};
use libc;
use libc::{c_char, c_int, c_void, off_t, pid_t};
use syscall::*;
fn exit(status: usize) -> Result<usize> {
process::exit(status as i32);
}
fn write(fd: usize, buffer: &[u8]) -> Result<usize> {
Error::demux(unsafe {
syscall!(WRITE, fd, buffer.as_ptr(), buffer.len())
})
}
struct Mapping {
address: usize,
length: usize,
page_address: usize,
page_length: usize,
}
impl Mapping {
unsafe fn new(fd: c_int, address: usize, length: usize, write: bool) -> Result<Mapping> {
let prot = if write {
libc::PROT_READ | libc::PROT_WRITE
} else {
libc::PROT_READ
};
let flags = libc::MAP_SHARED;
let page_size = 4096;
// Align address to page size
let page_address = address & !(page_size - 1);
// Calculate offset from page aligned address to address
let page_offset = address - page_address;
// Calculate length to the nearest page
let page_length = ((length + page_offset + page_size - 1)/page_size) * page_size;
let mapping = libc::mmap(ptr::null_mut(), page_length, prot, flags, fd, page_address as off_t);
if mapping == libc::MAP_FAILED {
libc::perror(b"mmap\0".as_ptr() as *const c_char);
Err(Error::new(EINVAL))
} else {
Ok(Mapping {
address: mapping as usize + page_offset,
length: length,
page_address: mapping as usize,
page_length: page_length
})
}
}
unsafe fn as_slice(&self) -> &[u8] {
slice::from_raw_parts(self.address as *const u8, self.length)
}
}
impl Drop for Mapping {
fn drop(&mut self) {
unsafe {
libc::munmap(self.page_address as *mut c_void, self.page_length);
}
}
}
unsafe fn process_read(pid: pid_t, address: usize, length: usize) -> Vec<u8> {
let mut buffer = vec![0; length];
let local_iov = libc::iovec {
iov_base: buffer.as_mut_ptr() as *mut libc::c_void,
iov_len: buffer.len(),
};
let remote_iov = libc::iovec {
iov_base: address as *mut libc::c_void,
iov_len: buffer.len(),
};
libc::process_vm_readv(
pid,
&local_iov as *const _,
1,
&remote_iov as *const _,
1,
0
);
buffer
}
unsafe fn process_write(pid: pid_t, address: usize, buffer: &[u8]) {
let local_iov = libc::iovec {
iov_base: buffer.as_ptr() as *mut libc::c_void,
iov_len: buffer.len(),
};
let remote_iov = libc::iovec {
iov_base: address as *mut libc::c_void,
iov_len: buffer.len(),
};
libc::process_vm_writev(
pid,
&local_iov as *const _,
1,
&remote_iov as *const _,
1,
0
);
}
pub unsafe fn handle(pid: pid_t, mem: c_int, a: usize, b: usize, c: usize, d: usize, e: usize, f: usize) -> usize {
let inner = || -> Result<usize> {
match a {
SYS_WRITE => {
println!("write({}, {:#x}, {})", b, c, d);
//let mapping = Mapping::new(mem, c, d, false)?;
//println!("Map {:#x}:{}", mapping.address, mapping.length);
write(b, &process_read(pid, c, d))
},
SYS_EXIT => {
println!("exit({})", b);
exit(b)
},
_ => {
println!("Unknown: {:#x}", a);
Err(Error::new(ENOSYS))
}
}
};
let res = inner();
println!("= {:?}", res);
Error::mux(res)
}
extern crate libc;
#[macro_use]
extern crate sc;
extern crate syscall;
use std::{ffi, mem, process, ptr};
// Constants
use libc::{
//CLONE_FILES, CLONE_FS, CLONE_PARENT, CLONE_IO, CLONE_SIGHAND, CLONE_SYSVSEM, CLONE_VM,
O_RDWR,
PTRACE_O_EXITKILL, PTRACE_GETREGS, PTRACE_SETOPTIONS, PTRACE_SETREGS, PTRACE_TRACEME,
SIGSTOP
};
const PTRACE_SYSEMU: c_uint = 31;
// Macros
use libc::{WEXITSTATUS, WIFEXITED};
// Types
use libc::{c_char, c_int, c_uint, c_void, pid_t, user_regs_struct};
// Functions
use libc::{fork, memalign, open, ptrace, raise, waitpid};
use self::handle::handle;
mod handle;
fn program() {
let array = format!("something\n");
if syscall::write(2, &array.as_bytes()).is_ok() {
syscall::exit(0);
} else {
syscall::exit(1);
}
}
extern "C" fn child() -> ! {
unsafe {
ptrace(PTRACE_TRACEME, 0, 0, 0);
raise(SIGSTOP);
};
program();
loop {}
}
unsafe fn parent(pid: pid_t) {
ptrace(PTRACE_SETOPTIONS, pid, 0, PTRACE_O_EXITKILL);
// Catch SIGSTOP
waitpid(pid, ptr::null_mut(), 0);
let path = format!("/proc/{}/mem", pid);
let mem = {
let path_c = ffi::CString::new(path.clone()).unwrap();
open(path_c.as_ptr(), O_RDWR)
};
if mem < 0 {
eprintln!("Failed to open {}", path);
}
loop {
ptrace(PTRACE_SYSEMU, pid, 0, 0);
let mut status = 0;
waitpid(pid, &mut status, 0);
if WIFEXITED(status) {
println!("Process exited with status {}", status);
process::exit(WEXITSTATUS(status));
}
let mut regs: user_regs_struct = mem::zeroed();
ptrace(PTRACE_GETREGS, pid, 0, &mut regs);
regs.rax = handle(
pid,
mem,
regs.orig_rax as usize,
regs.rbx as usize,
regs.rcx as usize,
regs.rdx as usize,
regs.rsi as usize,
regs.rdi as usize
) as u64;
ptrace(PTRACE_SETREGS, pid, 0, &regs);
}
}
fn main() {
unsafe {
/*
let stack_size = 1024 * 1024;
let child_stack = memalign(4096, stack_size);
let pid = clone(
child,
child_stack.add(stack_size),
CLONE_FILES | CLONE_FS | CLONE_PARENT | CLONE_IO | CLONE_SIGHAND | CLONE_SYSVSEM | CLONE_VM,
ptr::null_mut()
);
*/
let pid = fork();
if pid == 0 {
child();
} else if pid < 0 {
panic!("failed to clone");
} else {
parent(pid);
}
}
}
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment