Hpmason / retour-rs

A cross-platform detour library written in Rust
Other
99 stars 18 forks source link

More complex example for Linux #7

Closed Nereuxofficial closed 1 year ago

Nereuxofficial commented 1 year ago

I'm trying to use this crate to (for now) detour the open syscall in cat to use my own syscall, however i've run into issues with Segfaults which i am sadly unable to fix(Probably due to me being inexperienced).

Anyway here are the relevant code sections:

use ctor::ctor;
use detour::static_detour;
use std::ffi::CString;
use std::os::raw::c_char;
use std::{
    error::Error,
    fs::File,
    os::{fd::AsRawFd, raw::c_int},
};
extern "C" {
    fn open(pathname: *const c_char, flags: c_int) -> c_int;
}

static_detour! {
    static Opentour: unsafe extern "C" fn(*const c_char, c_int) -> c_int;
}

fn definitely_open(_: *const c_char, _: c_int) -> c_int {
    let file = File::open("/etc/timezone").unwrap();
    let fd = file.as_raw_fd();
    std::mem::forget(file);
    fd
}

fn main() {
    unsafe {
        let cstr = CString::new("/etc/timezone").unwrap();
        Opentour.initialize(open, definitely_open).unwrap();
        Opentour.enable().unwrap();
    }
}

And i'm calling it with: LD_PRELOAD=$PWD/target/debug/libfast_way_to_holiday.so /usr/bin/cat /etc/hosts

However that causes a Segfault.

And i wrote a test using this code:

unsafe {
            let cstr = CString::new("/etc/timezone").unwrap();
            println!("{:?}", open(cstr.as_ptr(), 0));
            Opentour.initialize(open, definitely_open).unwrap();
            Opentour.enable().unwrap();
            File::from_raw_fd(open(cstr.as_ptr(), 0));
        }

So at this point i decided to ask for help since i'm out of ideas. Also thanks for forking this crate and making it work on the latest nightly. I'd be happy to clean up my code and add another example for this repo once it works.

Hpmason commented 1 year ago

Sorry I didn't see this notification!

I don't have a Linux machine ready atm, but I'll see if I can reproduce this with WSL.

Hpmason commented 1 year ago

Looks like the Segfault is because you're calling let file = File::open("/etc/timezone").unwrap(); inside your hook. That triggers another call to open, which triggers your detour again, creating a recursive loop and overflowing the stack

Nereuxofficial commented 1 year ago

Thanks for your help! That worked, for some reason i just assumed File::open would not use a syscall but that could've easily have been prevented by using strace.