about summary refs log tree commit diff
diff options
context:
space:
mode:
authorBaitinq <manuelpalenzuelamerino@gmail.com>2024-07-29 19:07:34 +0200
committerBaitinq <manuelpalenzuelamerino@gmail.com>2024-07-29 19:07:34 +0200
commit1808e23086d01b658569025825789094612547cc (patch)
treeb27251717d697ff7217c96e9f4e8b9af1ebb0c34
parentfs-tracer: store file offset (diff)
downloadfs-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.rs30
-rw-r--r--fs-tracer-ebpf/src/main.rs5
-rw-r--r--fs-tracer-ebpf/src/syscalls/fseek.rs76
-rw-r--r--fs-tracer-ebpf/src/syscalls/mod.rs1
-rw-r--r--fs-tracer-ebpf/src/syscalls/write.rs2
-rw-r--r--fs-tracer/src/main.rs9
-rw-r--r--fs-tracer/src/syscall_handler.rs44
-rwxr-xr-xtests/a.outbin15872 -> 15872 bytes
-rw-r--r--tests/openat.c7
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);