diff options
author | Baitinq <manuelpalenzuelamerino@gmail.com> | 2024-01-14 19:32:22 +0100 |
---|---|---|
committer | Baitinq <manuelpalenzuelamerino@gmail.com> | 2024-01-14 19:32:22 +0100 |
commit | 7bab8b108c1e2c238f9e5745ebdc2860a7cc5fcf (patch) | |
tree | a4252a8a019d1392cc2959b024248edf34ff24a2 | |
parent | Handle write syscall (diff) | |
download | fs-tracer-7bab8b108c1e2c238f9e5745ebdc2860a7cc5fcf.tar.gz fs-tracer-7bab8b108c1e2c238f9e5745ebdc2860a7cc5fcf.tar.bz2 fs-tracer-7bab8b108c1e2c238f9e5745ebdc2860a7cc5fcf.zip |
Send write_syscall events to userspace
-rw-r--r-- | fs-tracer-common/src/lib.rs | 25 | ||||
-rw-r--r-- | fs-tracer-ebpf/src/main.rs | 66 | ||||
-rw-r--r-- | fs-tracer/Cargo.toml | 1 | ||||
-rw-r--r-- | fs-tracer/src/main.rs | 37 |
4 files changed, 109 insertions, 20 deletions
diff --git a/fs-tracer-common/src/lib.rs b/fs-tracer-common/src/lib.rs index 0c9ac1a..b8fcb1a 100644 --- a/fs-tracer-common/src/lib.rs +++ b/fs-tracer-common/src/lib.rs @@ -1 +1,26 @@ #![no_std] + +use core::fmt::{Formatter, self}; +use core::str; + + +#[derive(Clone, Copy)] +pub struct WriteSyscallBPF { + pub pid: u32, + pub fd: u64, + pub buf: [u8; 128], + pub count: u64, +} + +unsafe impl Sync for WriteSyscallBPF {} + +impl fmt::Debug for WriteSyscallBPF { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("WriteSyscallArgs") + .field("pid", &self.pid) + .field("fd", &self.fd) + .field("buf", &unsafe { str::from_utf8_unchecked(&self.buf) }) + .field("count", &self.count) + .finish() + } +} \ No newline at end of file diff --git a/fs-tracer-ebpf/src/main.rs b/fs-tracer-ebpf/src/main.rs index 36365d8..b14154d 100644 --- a/fs-tracer-ebpf/src/main.rs +++ b/fs-tracer-ebpf/src/main.rs @@ -5,10 +5,24 @@ use core::ffi::c_void; use core::str; use aya_bpf::{ - macros::tracepoint, - programs::TracePointContext, BpfContext, helpers::gen + macros::{tracepoint, map}, + programs::TracePointContext, BpfContext, helpers::{gen::{self, bpf_probe_read_kernel_str}, bpf_probe_read_kernel_str_bytes}, maps::{PerfEventArray, PerCpuArray}, }; use aya_log_ebpf::info; +use fs_tracer_common::WriteSyscallBPF; + +#[derive(Clone, Copy)] + struct WriteSyscallArgs { + fd: u64, + buf: *const u8, + count: u64, +} + +#[map] +static EVENTS: PerfEventArray<WriteSyscallBPF> = PerfEventArray::with_max_entries(1024, 0); + +//#[map] +//static mut READ_FROM_USERSPACE_BUFFER: PerCpuArray<[u8;2048]> = PerCpuArray::with_max_entries(1, 0); #[tracepoint] pub fn fs_tracer(ctx: TracePointContext) -> u32 { @@ -55,27 +69,47 @@ fn handle_syscall(ctx: TracePointContext, syscall_nr: i32) -> Result<u32, u32> { } } -#[derive(Clone, Copy)] -struct WriteArgs { - fd: u64, - buf: *const u8, - count: u64, -} +/*static mut read_from_userspace_buffer: [u8; 2048] = [0u8; 2048]; +static mut write_to_userspace_buffer: [u8; 2048] = [0u8; 2048]; +static mut write_syscall_bpf: WriteSyscallBPF = WriteSyscallBPF { + fd: 0, + buf: [0u8; 2048], + count: 0, +};*/ 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, "handle_sys_write start"); + let args = unsafe { *ptr_at::<WriteSyscallArgs>(&ctx, 16).unwrap() }; - info!(&ctx, "argfs fd: {}", args.fd); - let mut buf = [0u8; 256]; + // if fd is stdout, stderr or stdin, ignore + if args.fd <= 2 { + return Ok(0) + } + + // info!(&ctx, "argfs fd: {}", args.fd); + let mut buf = [0u8; 128]; + //get_string_from_userspace(args.buf, unsafe { &mut *READ_FROM_USERSPACE_BUFFER.get_ptr_mut(0).unwrap() }); 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, "buf: {}", unsafe { str::from_utf8_unchecked(buf_ref) }); + //info!(&ctx, "count: {}", args.count); "; + + let mut anotherbuf = [0u8; 128]; + unsafe { bpf_probe_read_kernel_str(anotherbuf.as_mut_ptr() as *mut c_void, 128, buf_ref.as_ptr() as *const c_void) }; - info!(&ctx, "handle_sys_write end"); + EVENTS.output(&ctx, &WriteSyscallBPF { + pid: ctx.pid(), + fd: args.fd, + buf: anotherbuf, + count: args.count, + }, 0); + + //info!(&ctx, "handle_sys_write end"); return Ok(0) -} //TODO: Communicate with userspace (share a some data structure in memory?) +} + +//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) 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) }; diff --git a/fs-tracer/Cargo.toml b/fs-tracer/Cargo.toml index 03ca947..ea9021d 100644 --- a/fs-tracer/Cargo.toml +++ b/fs-tracer/Cargo.toml @@ -12,6 +12,7 @@ anyhow = "1" env_logger = "0.10" libc = "0.2" log = "0.4" +bytes = "1.5.0" tokio = { version = "1.25", features = ["macros", "rt", "rt-multi-thread", "net", "signal"] } [[bin]] diff --git a/fs-tracer/src/main.rs b/fs-tracer/src/main.rs index 721c893..25edeb7 100644 --- a/fs-tracer/src/main.rs +++ b/fs-tracer/src/main.rs @@ -1,8 +1,14 @@ +use std::fmt::Write; + +use aya::maps::AsyncPerfEventArray; use aya::programs::TracePoint; +use aya::util::online_cpus; use aya::{include_bytes_aligned, Bpf}; use aya_log::BpfLogger; use log::{info, warn, debug}; -use tokio::signal; +use tokio::{signal, task}; +use bytes::BytesMut; +use fs_tracer_common::WriteSyscallBPF; #[tokio::main] async fn main() -> Result<(), anyhow::Error> { @@ -37,10 +43,33 @@ async fn main() -> Result<(), anyhow::Error> { } let program: &mut TracePoint = bpf.program_mut("fs_tracer").unwrap().try_into()?; program.load()?; - program.attach("syscalls", "sys_enter_open")?; + //program.attach("syscalls", "sys_enter_open")?; program.attach("syscalls", "sys_enter_write")?; - program.attach("syscalls", "sys_enter_lseek")?; - program.attach("syscalls", "sys_enter_close")?; + //program.attach("syscalls", "sys_enter_lseek")?; + //program.attach("syscalls", "sys_enter_close")?; + + println!("Num of cpus: {}", online_cpus()?.len()); + + let mut perf_array = + AsyncPerfEventArray::try_from(bpf.take_map("EVENTS").unwrap())?; + for cpu_id in online_cpus()? { + let mut buf = perf_array.open(cpu_id, None)?; + + task::spawn(async move { + let mut buffers = (0..10) + .map(|_| BytesMut::with_capacity(1024)) + .collect::<Vec<_>>(); + + loop { + let events = buf.read_events(&mut buffers).await.unwrap(); + for buf in buffers.iter_mut().take(events.read) { + let ptr = buf.as_ptr() as *const WriteSyscallBPF; + let data = unsafe { ptr.read_unaligned() }; + println!("KERNEL: DATA {:?}", data); + } + } + }); + } info!("Waiting for Ctrl-C..."); signal::ctrl_c().await?; |