From 6d132345ee2eb2f780702a2ff7b3e5ee53840fb6 Mon Sep 17 00:00:00 2001 From: 4lDO2 <4lDO2@protonmail.com> Date: Sun, 2 Jan 2022 11:57:34 +0100 Subject: [PATCH] WIP: Replace fexec with exec. --- src/call.rs | 17 +++++++++++++---- src/data.rs | 30 ++++++++++++++++++++++++++++++ src/number.rs | 2 +- 3 files changed, 44 insertions(+), 5 deletions(-) diff --git a/src/call.rs b/src/call.rs index f6eb89c..8cf2876 100644 --- a/src/call.rs +++ b/src/call.rs @@ -1,5 +1,5 @@ use super::arch::*; -use super::data::{Map, SigAction, Stat, StatVfs, TimeSpec}; +use super::data::{ExecMemRange, Map, SigAction, Stat, StatVfs, TimeSpec}; use super::error::Result; use super::flag::*; use super::number::*; @@ -85,9 +85,18 @@ pub fn fcntl(fd: usize, cmd: usize, arg: usize) -> Result { unsafe { syscall3(SYS_FCNTL, fd, cmd, arg) } } -/// Replace the current process with a new executable -pub fn fexec(fd: usize, args: &[[usize; 2]], vars: &[[usize; 2]]) -> Result { - unsafe { syscall5(SYS_FEXEC, fd, args.as_ptr() as usize, args.len(), vars.as_ptr() as usize, vars.len()) } +// TODO: Support specifying FDs to keep/close (for FDs not included in that list, it would take +// into account O_CLOEXEC). +// TODO: Allow setting all registers of the target process? +/// Replace the current process with a new executable, allowing the user to specify memory ranges +/// to either keep, move, or add. It will then jump to [`instruction_ptr`] in the new process +/// memory specified by the range map, with the stack pointer set accordingly. This syscall does +/// not support setuid/setgid; instead, privilege escalation must be done by a higher-privileged +/// process performing these actions via ptrace. +// TODO: never type +pub fn exec(memranges: &[ExecMemRange], instruction_ptr: usize, stack_ptr: usize) -> Result { + unsafe { syscall4(SYS_EXEC, memranges.as_ptr() as usize, memranges.len(), instruction_ptr, stack_ptr)?; } + panic!("SYS_EXEC should only return in case of an error"); } /// Map a file into memory, but with the ability to set the address to map into, either as a hint diff --git a/src/data.rs b/src/data.rs index 45d2dd8..efd1bc2 100644 --- a/src/data.rs +++ b/src/data.rs @@ -295,3 +295,33 @@ macro_rules! ptrace_event { } } } + +#[repr(C)] +pub struct ExecMemRange { + /// The address where the range is intended to be. + pub address: usize, + /// The size of the memory range. + pub size: usize, + /// Flags describing permissions (i.e. R/W/X) + pub flags: MapFlags, + /// If this equals [`address`], the range is kept untouched although flags can change, and the + /// range can be shortened or partly zeroed. If it is different, it will move `[old_address, + /// old_address+size)` to `[address, address+size]`. + pub old_address: usize, +} +impl Deref for ExecMemRange { + type Target = [u8]; + fn deref(&self) -> &[u8] { + unsafe { + slice::from_raw_parts(self as *const ExecMemRange as *const u8, mem::size_of::()) + } + } +} + +impl DerefMut for ExecMemRange { + fn deref_mut(&mut self) -> &mut [u8] { + unsafe { + slice::from_raw_parts_mut(self as *mut ExecMemRange as *mut u8, mem::size_of::()) + } + } +} diff --git a/src/number.rs b/src/number.rs index 1f037eb..1d6f17b 100644 --- a/src/number.rs +++ b/src/number.rs @@ -26,7 +26,6 @@ pub const SYS_FCHMOD: usize = SYS_CLASS_FILE | 94; pub const SYS_FCHOWN: usize = SYS_CLASS_FILE | 207; pub const SYS_FCNTL: usize = SYS_CLASS_FILE | 55; pub const SYS_FEVENT: usize = SYS_CLASS_FILE | 927; -pub const SYS_FEXEC: usize = SYS_CLASS_FILE | 11; pub const SYS_FMAP_OLD: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 90; pub const SYS_FMAP: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 900; pub const SYS_FUNMAP_OLD: usize = SYS_CLASS_FILE | 91; @@ -39,6 +38,7 @@ pub const SYS_FSYNC: usize = SYS_CLASS_FILE | 118; pub const SYS_FTRUNCATE: usize = SYS_CLASS_FILE | 93; pub const SYS_FUTIMENS: usize = SYS_CLASS_FILE | SYS_ARG_SLICE | 320; +pub const SYS_EXEC: usize = 101; pub const SYS_CHDIR: usize = 12; pub const SYS_CLOCK_GETTIME: usize = 265; pub const SYS_CLONE: usize = 120;