crustmemoryfilesystemsmemory-safety

Is it possible to read an executable and run it without writing it into another file?


I want something like where i have an executable and I can read that executable and I am able to read and store it into some variable and than with some interaction with that variable I can run the executable.

fn main() -> io::Result<()> {

        const BUFFER_SIZE: usize = 4096; 
    
        let input_path = "/home/ubuntu/Desktop/exp/target/debug/exp";
    
        let mut file = File::open(input_path)?;
        let mut contents = Vec::new();
        file.read_to_end(&mut contents)?;
    
        let bytes_to_copy = contents.len().min(BUFFER_SIZE);
    
        unsafe {
            let mem_address = libc::mmap(
                ptr::null_mut(),
                bytes_to_copy,
                libc::PROT_READ | libc::PROT_WRITE | libc::PROT_EXEC,
                libc::MAP_PRIVATE | libc::MAP_ANONYMOUS,
                -1,
                0,
            );
    
            if mem_address == libc::MAP_FAILED {
                panic!("mmap failed: {}", io::Error::last_os_error());
            }
    
            ptr::copy_nonoverlapping(contents.as_ptr(), mem_address as *mut u8, bytes_to_copy);
    
            // Ensure memory is executable
            let result = libc::mprotect(
                mem_address,
                bytes_to_copy,
                libc::PROT_READ | libc::PROT_EXEC,
            );
    
            if result != 0 {
                panic!("mprotect failed: {}", io::Error::last_os_error());
            }
    
            // Cast the memory address to a function pointer and call it
            let code: extern "C" fn() = std::mem::transmute(mem_address as *const ());
            code();
        }
    
        Ok(())
    }

So I tried this but it gives me seg fault. What am I doing wrong?


Solution

  • The memfd_create + fexecve combo might just work for you (assuming a unix-like system): using memfd_create and fexecve to run ELF from memory