about summary refs log tree commit diff
path: root/fs-tracer-ebpf/src/main.rs
blob: 18f22eb33480a252e8ad750f2438d033926f5758 (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
88
89
90
91
92
#![no_std]
#![no_main]
#![feature(c_size_t)]

#![allow(warnings, unused)]
mod vmlinux;
mod syscalls;

use core::str;
use aya_bpf::cty::{c_int, c_long};
use aya_bpf::maps::HashMap;
use aya_bpf::{
    macros::{map, tracepoint},
    maps::PerfEventArray,
    programs::TracePointContext,
    BpfContext,
};
use aya_log_ebpf::info;
use fs_tracer_common::{SyscallInfo, WriteSyscallBPF};

#[map]
static EVENTS: PerfEventArray<SyscallInfo> = PerfEventArray::with_max_entries(24, 0);

// NOTE: We use this map for tracking syscalls. We have a tracepoint both at the entry
// and exit of a syscall. Since we need to get arguments from both places, we need to be
// able to correlate a syscall enter to an exit. We do this via the tgid. Since a thread
// can only execute 1 syscall at a time, we can have a map of tgid -> syscall of size =
// num_of_threads.
#[map]
static SYSCALL_ENTERS: HashMap<u32, SyscallInfo> = HashMap::with_max_entries(24, 0);

enum SyscallType {
    Enter,
    Exit,
}

#[tracepoint]
pub fn fs_tracer_enter(ctx: TracePointContext) -> c_long {
    match try_fs_tracer(ctx, SyscallType::Enter) {
        Ok(ret) => ret,
        Err(ret) => -ret,
    }
}

#[tracepoint]
pub fn fs_tracer_exit(ctx: TracePointContext) -> c_long {
    //info!(&ctx, "Hi");
    match try_fs_tracer(ctx, SyscallType::Exit) {
        Ok(ret) => ret,
        Err(ret) => -ret,
    }
}

fn try_fs_tracer(ctx: TracePointContext, syscall_type: SyscallType) -> Result<c_long, c_long> {
    let syscall_nr = unsafe { ctx.read_at::<c_int>(8)? } ;

    handle_syscall(ctx, syscall_nr, syscall_type)
}

fn handle_syscall(
    ctx: TracePointContext,
    syscall_nr: c_int,
    syscall_type: SyscallType,
) -> Result<c_long, c_long> {
    match syscall_nr {
        1 => syscalls::write::handle_sys_write(ctx, syscall_type),
        257 => syscalls::open::handle_sys_open(ctx, syscall_type),
        8 => {
            Ok(0)
            //handle_sys_lseek(ctx);
        }
        3 => {
            Ok(0)
            //handle_sys_close(ctx);
        }
        _ => {
            info!(&ctx, "unhandled syscall: {}", syscall_nr);
            Err(1)
        }
    }
}

// thread can only execute 1 syscall at a time <-

//TODO: How are we going to correlate. We have open of a filename, we need to insert that into (pid, fd) -> filename. on close we remove from map. we need some timeout to remove stale entries
//TODO: to get the fd from open, we need to know the return value of the syscall. for that we need a tracepoint on end and keep a map of (tgid, pid) -> WriteSyscallBPF). we need to differenciate the syscalls by id
//TODO: Maybe we can use git itself for the diffs etc.

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