about summary refs log tree commit diff
path: root/fs-tracer-ebpf/src/main.rs
blob: 36365d88fa88dab272c6886d53af205801843622 (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
#![no_std]
#![no_main]

use core::ffi::c_void;
use core::str;

use aya_bpf::{
    macros::tracepoint,
    programs::TracePointContext, BpfContext, helpers::gen
};
use aya_log_ebpf::info;

#[tracepoint]
pub fn fs_tracer(ctx: TracePointContext) -> u32 {
    match try_fs_tracer(ctx) {
        Ok(ret) => ret,
        Err(ret) => ret,
    }
}

#[inline(always)]
fn ptr_at<T>(ctx: &TracePointContext, offset: usize) -> Option<*const T> {
    let start = ctx.as_ptr();

    Some(unsafe { start.add(offset) } as *const T)
}

fn try_fs_tracer(ctx: TracePointContext) -> Result<u32, u32> {
    let syscall_nr = unsafe { * ptr_at::<i32>(&ctx, 8).unwrap() };
    
    return handle_syscall(ctx, syscall_nr);
}

fn handle_syscall(ctx: TracePointContext, syscall_nr: i32) -> Result<u32, u32> {
    match syscall_nr {
        1 => {
            return handle_sys_write(ctx);
        },
        2 => {
            return Ok(0)
            //handle_sys_open(ctx);
        },
        8 => {
            return Ok(0)
            //handle_sys_lseek(ctx);
        },
        3 => {
            return Ok(0)
            //handle_sys_close(ctx);
        },
        _ => {
            info!(&ctx, "unhandled syscall: {}", syscall_nr);
            panic!("syscall: {}",syscall_nr);
        }
    }
}

#[derive(Clone, Copy)]
struct WriteArgs {
    fd: u64,
    buf: *const u8,
    count: u64,
}

fn handle_sys_write(ctx: TracePointContext) -> Result<u32, u32> {
    info!(&ctx, "handle_sys_write start");
    let args = unsafe { *ptr_at::<WriteArgs>(&ctx, 16).unwrap() };

    info!(&ctx, "argfs fd: {}", args.fd);
    let mut buf = [0u8; 256];
    get_string_from_userspace(args.buf, &mut buf);
    let buf_ref = &buf;
    info!(&ctx, "buf: {}", unsafe { str::from_utf8_unchecked(buf_ref) });
    info!(&ctx, "count: {}", args.count);

    info!(&ctx, "handle_sys_write end");
    return Ok(0)
} //TODO: Communicate with userspace (share a some data structure in memory?)

fn get_string_from_userspace(ptr: *const u8, buf: &mut [u8]) {
    unsafe { gen::bpf_probe_read_user_str( buf.as_mut_ptr() as *mut c_void, buf.len() as u32, ptr as *const c_void) };
}

#[panic_handler]
fn panic(_info: &core::panic::PanicInfo) -> ! {
    unsafe { core::hint::unreachable_unchecked() }
}