diff options
author | Baitinq <manuelpalenzuelamerino@gmail.com> | 2024-07-29 19:07:34 +0200 |
---|---|---|
committer | Baitinq <manuelpalenzuelamerino@gmail.com> | 2024-07-29 19:07:34 +0200 |
commit | 1808e23086d01b658569025825789094612547cc (patch) | |
tree | b27251717d697ff7217c96e9f4e8b9af1ebb0c34 | |
parent | fs-tracer: store file offset (diff) | |
download | fs-tracer-1808e23086d01b658569025825789094612547cc.tar.gz fs-tracer-1808e23086d01b658569025825789094612547cc.tar.bz2 fs-tracer-1808e23086d01b658569025825789094612547cc.zip |
fs-tracer: handle fseek syscall
-rw-r--r-- | fs-tracer-common/src/lib.rs | 30 | ||||
-rw-r--r-- | fs-tracer-ebpf/src/main.rs | 5 | ||||
-rw-r--r-- | fs-tracer-ebpf/src/syscalls/fseek.rs | 76 | ||||
-rw-r--r-- | fs-tracer-ebpf/src/syscalls/mod.rs | 1 | ||||
-rw-r--r-- | fs-tracer-ebpf/src/syscalls/write.rs | 2 | ||||
-rw-r--r-- | fs-tracer/src/main.rs | 9 | ||||
-rw-r--r-- | fs-tracer/src/syscall_handler.rs | 44 | ||||
-rwxr-xr-x | tests/a.out | bin | 15872 -> 15872 bytes | |||
-rw-r--r-- | tests/openat.c | 7 |
9 files changed, 159 insertions, 15 deletions
diff --git a/fs-tracer-common/src/lib.rs b/fs-tracer-common/src/lib.rs index fb36b74..3cf4c80 100644 --- a/fs-tracer-common/src/lib.rs +++ b/fs-tracer-common/src/lib.rs @@ -3,8 +3,9 @@ use aya_ebpf::cty::c_long; use core::ffi::c_int; -use core::ffi::c_size_t; +use core::ffi::c_longlong; use core::ffi::CStr; +use core::ffi::{c_size_t, c_uint}; use core::fmt::{self, Formatter}; use core::str; @@ -16,6 +17,7 @@ pub enum SyscallInfo { Write(WriteSyscallBPF), Open(OpenSyscallBPF), Close(CloseSyscallBPF), + FSeek(FSeekSyscallBPF), } #[derive(Clone, Copy)] @@ -23,7 +25,7 @@ pub struct WriteSyscallBPF { pub pid: u32, pub fd: c_int, pub buf: [u8; 96], //TODO: might want to use c_char here - pub count: c_size_t, + pub count: i64, pub ret: c_long, } @@ -88,3 +90,27 @@ impl fmt::Debug for CloseSyscallBPF { .finish() } } + +#[derive(Clone, Copy)] +pub struct FSeekSyscallBPF { + pub pid: u32, + pub fd: c_int, + pub offset: i64, + pub whence: c_uint, + + pub ret: c_long, +} + +unsafe impl Sync for FSeekSyscallBPF {} + +impl fmt::Debug for FSeekSyscallBPF { + fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result { + f.debug_struct("FSeekSyscallBPF") + .field("pid", &self.pid) + .field("fd", &self.fd) + .field("offset", &self.offset) + .field("whence", &self.whence) + .field("ret", &self.ret) + .finish() + } +} diff --git a/fs-tracer-ebpf/src/main.rs b/fs-tracer-ebpf/src/main.rs index a6794f5..c67ffd1 100644 --- a/fs-tracer-ebpf/src/main.rs +++ b/fs-tracer-ebpf/src/main.rs @@ -65,10 +65,7 @@ fn handle_syscall( 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); - }*/ + 8 => syscalls::fseek::handle_sys_fseek(ctx, syscall_type), 3 => syscalls::close::handle_sys_close(ctx, syscall_type), _ => { info!(&ctx, "unhandled syscall: {}", syscall_nr); diff --git a/fs-tracer-ebpf/src/syscalls/fseek.rs b/fs-tracer-ebpf/src/syscalls/fseek.rs new file mode 100644 index 0000000..fd2317b --- /dev/null +++ b/fs-tracer-ebpf/src/syscalls/fseek.rs @@ -0,0 +1,76 @@ +use aya_ebpf::{ + cty::{c_char, c_longlong, c_uint}, + helpers::{bpf_probe_read_kernel_str_bytes, bpf_probe_read_user_str_bytes}, +}; +use core::ffi::c_size_t; +use fs_tracer_common::FSeekSyscallBPF; + +use crate::*; + +pub fn handle_sys_fseek( + ctx: TracePointContext, + syscall_type: SyscallType, +) -> Result<c_long, c_long> { + match syscall_type { + SyscallType::Enter => unsafe { handle_sys_fseek_enter(ctx) }, + SyscallType::Exit => unsafe { handle_sys_fseek_exit(ctx) }, + } +} + +unsafe fn handle_sys_fseek_enter(ctx: TracePointContext) -> Result<c_long, c_long> { + // info!(&ctx, "handle_sys_fseek start"); + #[repr(C)] + #[derive(Clone, Copy)] + struct FSeekSyscallArgs { + fd: c_int, + offset: i64, + whence: c_uint, + } + let args = ctx.read_at::<FSeekSyscallArgs>(16)?; + + // if fd is stdout, stderr or stdin, ignore + if args.fd <= 2 { + return Ok(0); + } + + info!( + &ctx, + "handle_sys_fseek fd: {} pid: {} offset: {} whence: {}", + args.fd, + ctx.pid(), + args.offset, + args.whence + ); + + let tgid: u32 = ctx.tgid(); + let _ = SYSCALL_ENTERS.insert( + &tgid, + &SyscallInfo::FSeek(FSeekSyscallBPF { + pid: ctx.pid(), + fd: args.fd, + offset: args.offset, + whence: args.whence, + ret: -9999, + }), + 0, + ); + + Ok(0) +} + +unsafe fn handle_sys_fseek_exit(ctx: TracePointContext) -> Result<c_long, c_long> { + //info!(&ctx, "handle_sys_fseek_exit start"); + let ret = ctx.read_at::<c_long>(16)?; //TODO: We cant use unwrap, thats why we couldnt use the aya helper fns + + let tgid = ctx.tgid(); + if let Some(syscall) = SYSCALL_ENTERS.get(&tgid) + && let SyscallInfo::FSeek(mut syscall_fseek) = syscall + { + syscall_fseek.ret = ret; + EVENTS.output(&ctx, &SyscallInfo::FSeek(syscall_fseek), 0); + let _ = SYSCALL_ENTERS.remove(&tgid); + return Ok(0); + } + + Err(0) +} diff --git a/fs-tracer-ebpf/src/syscalls/mod.rs b/fs-tracer-ebpf/src/syscalls/mod.rs index 8661535..c346900 100644 --- a/fs-tracer-ebpf/src/syscalls/mod.rs +++ b/fs-tracer-ebpf/src/syscalls/mod.rs @@ -1,3 +1,4 @@ pub mod close; +pub mod fseek; pub mod open; pub mod write; diff --git a/fs-tracer-ebpf/src/syscalls/write.rs b/fs-tracer-ebpf/src/syscalls/write.rs index 6010dce..ff309e9 100644 --- a/fs-tracer-ebpf/src/syscalls/write.rs +++ b/fs-tracer-ebpf/src/syscalls/write.rs @@ -23,7 +23,7 @@ unsafe fn handle_sys_write_enter(ctx: TracePointContext) -> Result<c_long, c_lon struct WriteSyscallArgs { fd: c_int, buf: *const c_char, - count: c_size_t, + count: i64, } let args = ctx.read_at::<WriteSyscallArgs>(16)?; diff --git a/fs-tracer/src/main.rs b/fs-tracer/src/main.rs index 223f35a..b7fa5e6 100644 --- a/fs-tracer/src/main.rs +++ b/fs-tracer/src/main.rs @@ -10,6 +10,7 @@ use fs_tracer_common::SyscallInfo; use log::{debug, info, warn}; use serde::Serialize; use std::env; +use std::ffi::c_long; use std::sync::{ atomic::{AtomicBool, Ordering}, Arc, @@ -56,8 +57,7 @@ async fn main() -> Result<(), anyhow::Error> { trace_enters_program.load()?; trace_enters_program.attach("syscalls", "sys_enter_openat")?; trace_enters_program.attach("syscalls", "sys_enter_write")?; - // program.attach("syscalls", "sys_exit_write")?; - //trace_enters_program.attach("syscalls", "sys_enter_lseek")?; + trace_enters_program.attach("syscalls", "sys_enter_lseek")?; trace_enters_program.attach("syscalls", "sys_enter_close")?; let trace_exits_program: &mut TracePoint = @@ -65,6 +65,7 @@ async fn main() -> Result<(), anyhow::Error> { trace_exits_program.load()?; trace_exits_program.attach("syscalls", "sys_exit_openat")?; trace_exits_program.attach("syscalls", "sys_exit_write")?; + trace_exits_program.attach("syscalls", "sys_exit_lseek")?; trace_exits_program.attach("syscalls", "sys_exit_close")?; println!("Num of cpus: {}", online_cpus()?.len()); @@ -89,7 +90,7 @@ async fn main() -> Result<(), anyhow::Error> { handles.push(tokio::spawn(async move { let mut syscall_handler = syscall_handler::SyscallHandler::new(thread_sender); let mut buffers = (0..10) - .map(|_| BytesMut::with_capacity(1024)) + .map(|_| BytesMut::with_capacity(4096)) .collect::<Vec<_>>(); loop { @@ -145,7 +146,7 @@ struct FSTracerFile { timestamp: String, absolute_path: String, contents: String, - offset: usize, + offset: i64, } fn send_request(url: &str, fs_tracer_api_key: &str, files: &Vec<FSTracerFile>) { diff --git a/fs-tracer/src/syscall_handler.rs b/fs-tracer/src/syscall_handler.rs index 9dc2946..9f9c30d 100644 --- a/fs-tracer/src/syscall_handler.rs +++ b/fs-tracer/src/syscall_handler.rs @@ -3,13 +3,15 @@ use std::ffi::CStr; use crossbeam_channel::Sender; use delay_map::HashMapDelay; -use fs_tracer_common::{CloseSyscallBPF, OpenSyscallBPF, SyscallInfo, WriteSyscallBPF}; +use fs_tracer_common::{ + CloseSyscallBPF, FSeekSyscallBPF, OpenSyscallBPF, SyscallInfo, WriteSyscallBPF, +}; use crate::FSTracerFile; pub struct SyscallHandler { resolved_files: Sender<FSTracerFile>, - open_files: HashMapDelay<(i32, u32), (String, usize)>, + open_files: HashMapDelay<(i32, u32), (String, i64)>, } impl SyscallHandler { @@ -24,6 +26,7 @@ impl SyscallHandler { match data { SyscallInfo::Write(write_syscall) => self.handle_write(write_syscall), SyscallInfo::Open(open_syscall) => self.handle_open(open_syscall), + SyscallInfo::FSeek(fseek_syscall) => self.handle_fseek(fseek_syscall), SyscallInfo::Close(close_syscall) => self.handle_close(close_syscall), } } @@ -44,7 +47,7 @@ impl SyscallHandler { .to_str() .unwrap_or_default(); println!( - "WRITE KERNEL: DATA {:?} FILENAME: {:?} OFFSET: {:?} LEN: {:?}", + "WRITE KERNEL: DATA {:?} FILENAME: {:?} STORED OFFSET: {:?} LEN: {:?}", write_syscall, filename, offset, @@ -54,7 +57,7 @@ impl SyscallHandler { timestamp: chrono::Utc::now().to_rfc3339(), absolute_path: filename.to_string(), contents: contents.to_string(), - offset: offset, + offset, }); self.open_files .remove(&(write_syscall.fd, write_syscall.pid)); @@ -65,6 +68,39 @@ impl SyscallHandler { Ok(()) } + fn handle_fseek(&mut self, fseek_syscall: FSeekSyscallBPF) -> Result<(), ()> { + let (filename, offset) = match self.open_files.get(&(fseek_syscall.fd, fseek_syscall.pid)) { + None => { + println!( + "DIDNT FIND AN OPEN FILE FOR THE FSEEK SYSCALL (fd: {}, ret: {})", + fseek_syscall.fd, fseek_syscall.ret + ); + return Ok(()); + } + Some(str) => str.clone(), + }; + println!( + "FSEEK KERNEL: DATA {:?} FILENAME: {:?} STORED OFFSET: {:?}", + fseek_syscall, filename, offset, + ); + self.open_files + .remove(&(fseek_syscall.fd, fseek_syscall.pid)); + + //TODO: treat fseek_syscall.whence + let final_offset: i64 = match fseek_syscall.whence { + 0 => fseek_syscall.offset, //SEEK_SET + 1 => offset + fseek_syscall.offset, //SEEK_CUR + 2 => -1, //SEEK_END + _ => panic!("Invalid whence value!"), + }; + + self.open_files.insert( + (fseek_syscall.fd, fseek_syscall.pid), + (filename.clone(), final_offset), + ); + Ok(()) + } + fn handle_open(&mut self, open_syscall: OpenSyscallBPF) -> Result<(), ()> { let filename = CStr::from_bytes_until_nul(&open_syscall.filename) .unwrap_or_default() diff --git a/tests/a.out b/tests/a.out index a6e5bdd..3d9e7c1 100755 --- a/tests/a.out +++ b/tests/a.out Binary files differdiff --git a/tests/openat.c b/tests/openat.c index e5f6f17..582260a 100644 --- a/tests/openat.c +++ b/tests/openat.c @@ -22,6 +22,13 @@ int main(int argc, char** argv) { printf("Write error: %s\n", strerror(errno)); } + ret = syscall(SYS_lseek, fd, 24, SEEK_SET); + printf("FSeek ret: %d\n", ret); + + if (ret == -1) { + printf("FSeek error: %s\n", strerror(errno)); + } + ret = syscall(SYS_write, fd, "\nplease", 7); printf("Write ret: %d\n", ret); |