diff --git a/omo/src/errors.rs b/omo/src/errors.rs index 202f58e..d9d98ec 100644 --- a/omo/src/errors.rs +++ b/omo/src/errors.rs @@ -1,4 +1,4 @@ -use std::io; +use std::{io, io::Error}; use thiserror::Error; use unicorn_engine::unicorn_const::uc_error; @@ -15,6 +15,10 @@ pub enum EmulatorError { Custom(#[from] anyhow::Error), } +pub fn from_raw_syscall_ret(ret: i64) -> EmulatorError { + EmulatorError::IOError(Error::from_raw_os_error(-ret as i32)) +} + impl From for EmulatorError { fn from(e: uc_error) -> Self { Self::UcError(e) diff --git a/omo/src/os/linux/file.rs b/omo/src/os/linux/file.rs index a76e89f..b045164 100644 --- a/omo/src/os/linux/file.rs +++ b/omo/src/os/linux/file.rs @@ -1,127 +1,133 @@ -use std::io; +use crate::{ + errors::{from_raw_syscall_ret, EmulatorError}, + os::linux::syscall::*, +}; -use crate::{errors::EmulatorError, os::linux::syscall::*}; - -pub fn open(path: &str, flags: u64, mode: u64) -> Result { +pub fn open(path: *const u8, flags: u64, mode: u64) -> Result { + let flags = flags & 0xffffffff; let open_mode = mode & 0x7fffffff; - let fd = syscall_3( - LinuxSysCalls::Open as u64, - path.as_ptr() as u64, - flags, - open_mode, - ); + let fd = unsafe { syscall_3(LinuxSysCalls::Open as u64, path as u64, flags, open_mode) }; if fd < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(fd)) } else { Ok(fd) } } -pub fn read(fd: u64, buf: u64, size: u64) -> Result { - let size = syscall_3(LinuxSysCalls::Read as u64, fd, buf, size); +pub fn read(fd: u64, buf: *mut u8, size: u64) -> Result { + let size = unsafe { syscall_3(LinuxSysCalls::Read as u64, fd, buf as u64, size) }; if size < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(size)) } else { Ok(size) } } -pub fn write(fd: u64, data: u64, len: u64) -> Result { - let size = syscall_3(LinuxSysCalls::Write as u64, fd, data, len); +pub fn write(fd: u64, data: *const u8, len: u64) -> Result { + let size = unsafe { syscall_3(LinuxSysCalls::Write as u64, fd, data as u64, len) }; if size < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(size)) } else { Ok(size) } } pub fn close(fd: u64) -> Result { - let ret = syscall_1(LinuxSysCalls::Close as u64, fd); + let ret = unsafe { syscall_1(LinuxSysCalls::Close as u64, fd) }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } } pub fn lseek(fd: u64, offset: u64, whence: u64) -> Result { - let off = syscall_3(LinuxSysCalls::Lseek as u64, fd, offset, whence); + let off = unsafe { syscall_3(LinuxSysCalls::Lseek as u64, fd, offset, whence) }; if off < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(off)) } else { Ok(off) } } pub fn fcntl(fd: u64, cmd: u64, arg: u64) -> Result { - let ret = syscall_3(LinuxSysCalls::Fcntl as u64, fd, cmd, arg); + let ret = unsafe { syscall_3(LinuxSysCalls::Fcntl as u64, fd, cmd, arg) }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } } -pub fn readlink(path: &str, buf: u64, buf_size: u64) -> Result { - let ret = syscall_3( - LinuxSysCalls::Readlink as u64, - path.as_ptr() as u64, - buf, - buf_size, - ); +pub fn readlink(path: *const u8, buf: *mut u8, buf_size: u64) -> Result { + let ret = unsafe { + syscall_3( + LinuxSysCalls::Readlink as u64, + path as u64, + buf as u64, + buf_size, + ) + }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } } -pub fn stat(path: &str, stat_buf: u64) -> Result { - let ret = syscall_2(LinuxSysCalls::Stat as u64, path.as_ptr() as u64, stat_buf); +pub fn stat(path: *const u8, stat_buf: *mut StatX8664) -> Result { + let ret = unsafe { syscall_2(LinuxSysCalls::Stat as u64, path as u64, stat_buf as u64) }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } } -pub fn fstat(fd: u64, stat_buf: u64) -> Result { - let ret = syscall_2(LinuxSysCalls::Fstat as u64, fd, stat_buf); +pub fn fstat(fd: u64, stat_buf: *mut StatX8664) -> Result { + let ret = unsafe { syscall_2(LinuxSysCalls::Fstat as u64, fd, stat_buf as u64) }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } } -pub fn lstat(path: &str, stat_buf: u64) -> Result { - let ret = syscall_2(LinuxSysCalls::Lstat as u64, path.as_ptr() as u64, stat_buf); +pub fn lstat(path: *const u8, stat_buf: *mut StatX8664) -> Result { + let ret = unsafe { syscall_2(LinuxSysCalls::Lstat as u64, path as u64, stat_buf as u64) }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } } -pub fn fstatat64(dir_fd: u64, path: &str, stat_buf: u64, flags: u64) -> Result { - let ret = syscall_4( - LinuxSysCalls::Newfstatat as u64, - dir_fd, - path.as_ptr() as u64, - stat_buf, - flags, - ); +pub fn fstatat64( + dir_fd: u64, + path: *const u8, + stat_buf: *mut StatX8664, + flags: u64, +) -> Result { + let ret = unsafe { + syscall_4( + LinuxSysCalls::Newfstatat as u64, + dir_fd, + path as u64, + stat_buf as u64, + flags, + ) + }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } } pub fn ioctl(fd: u64, cmd: u64, arg: u64) -> Result { - let ret = syscall_3(LinuxSysCalls::Ioctl as u64, fd, cmd, arg); + let ret = unsafe { syscall_3(LinuxSysCalls::Ioctl as u64, fd, cmd, arg) }; if ret < 0 { - Err(EmulatorError::IOError(io::Error::last_os_error())) + Err(from_raw_syscall_ret(ret)) } else { Ok(ret) } diff --git a/omo/src/os/linux/syscall.rs b/omo/src/os/linux/syscall.rs index b41225f..90f282b 100644 --- a/omo/src/os/linux/syscall.rs +++ b/omo/src/os/linux/syscall.rs @@ -26,61 +26,54 @@ pub enum LinuxSysCalls { } // x86_64 raw syscall. -pub fn syscall_1(trap: u64, arg1: u64) -> i64 { +pub unsafe fn syscall_1(trap: u64, arg1: u64) -> i64 { let res; - unsafe { - asm!( - "syscall", - in("rax") trap, - in("rdi") arg1, - lateout("rax") res, - ); - } + asm!( + "syscall", + in("rax") trap, + in("rdi") arg1, + lateout("rax") res, + ); res } -pub fn syscall_2(trap: u64, arg1: u64, arg2: u64) -> i64 { +pub unsafe fn syscall_2(trap: u64, arg1: u64, arg2: u64) -> i64 { let res; - unsafe { - asm!( - "syscall", - in("rax") trap, - in("rdi") arg1, - in("rsi") arg2, - lateout("rax") res, - ); - } + asm!( + "syscall", + in("rax") trap, + in("rdi") arg1, + in("rsi") arg2, + lateout("rax") res, + ); res } -pub fn syscall_3(trap: u64, arg1: u64, arg2: u64, arg3: u64) -> i64 { +pub unsafe fn syscall_3(trap: u64, arg1: u64, arg2: u64, arg3: u64) -> i64 { let res; - unsafe { - asm!( - "syscall", - in("rax") trap, - in("rdi") arg1, - in("rsi") arg2, - in("rdx") arg3, - lateout("rax") res, - ); - } + asm!( + "syscall", + in("rax") trap, + in("rdi") arg1, + in("rsi") arg2, + in("rdx") arg3, + lateout("rax") res, + ); + res } -pub fn syscall_4(trap: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64 { +pub unsafe fn syscall_4(trap: u64, arg1: u64, arg2: u64, arg3: u64, arg4: u64) -> i64 { let res; - unsafe { - asm!( - "syscall", - in("rax") trap, - in("rdi") arg1, - in("rsi") arg2, - in("rdx") arg3, - in("r10") arg4, - lateout("rax") res, - ); - } + asm!( + "syscall", + in("rax") trap, + in("rdi") arg1, + in("rsi") arg2, + in("rdx") arg3, + in("r10") arg4, + lateout("rax") res, + ); res }