From 660d9292688861c8b3504bf4fb1b67f8e2fcda47 Mon Sep 17 00:00:00 2001 From: Divik Chotani Date: Mon, 4 Aug 2025 18:43:43 -0700 Subject: [PATCH 1/7] added dup and pipe, need to fix dependencies for them however --- src/bpf/hs_trace.bpf.c | 152 ++++++++++++++++++++++++++++++- src/dep_tracer.rs | 199 +++++++++++++++++++++++++++++++++++++---- src/main.rs | 8 +- 3 files changed, 340 insertions(+), 19 deletions(-) diff --git a/src/bpf/hs_trace.bpf.c b/src/bpf/hs_trace.bpf.c index c5ccb0a..1836537 100644 --- a/src/bpf/hs_trace.bpf.c +++ b/src/bpf/hs_trace.bpf.c @@ -20,6 +20,13 @@ struct { __uint(max_entries, 1); } missed_events SEC(".maps"); +struct { + __uint(type, BPF_MAP_TYPE_HASH); + __type(key, u32); + __type(value, u64); + __uint(max_entries, 1024*1024); +} pipe_tracker SEC(".maps"); + // struct { // __uint(type, BPF_MAP_TYPE_HASH); // __type(key, struct unique_file_t); @@ -48,6 +55,115 @@ enum syscall_event_type { SYS_EXIT }; +SEC("tracepoint/syscalls/sys_enter_pipe2") +int +hs_trace_create_pipe(struct trace_event_raw_sys_enter *tp) +{ + u64 pid_tgid = bpf_get_current_pid_tgid(); + u32 pid = pid_tgid & 0xFFFFFFFF; + + if (bpf_map_lookup_elem(&pid_set, &pid) == NULL) { + return 0; + } + + u64 ptr = (u64)tp->args[0]; + if (bpf_map_update_elem(&pipe_tracker, &pid, &ptr, BPF_ANY) < 0) { + bpf_printk("failed to update pipe_tracker with pid %d\n", pid); + return 0; + } + + return 0; +} + +SEC("tracepoint/syscalls/sys_exit_pipe2") +int +hs_trace_create_pipe_exit(struct trace_event_raw_sys_exit *tp) +{ + + struct sys_enter_info2_t *enter2; + + u64 pid_tgid = bpf_get_current_pid_tgid(); + u32 pid = pid_tgid & 0xFFFFFFFF; + if (bpf_map_lookup_elem(&pid_set, &pid) == NULL) { + // bpf_printk("pid %d is not in set\n", pid); + return 0; + } + long ret = tp -> ret; + if (ret < 0) { + return 0; + } + + u64 *fds_pointers = bpf_map_lookup_elem(&pipe_tracker, &pid); + + if (!fds_pointers) { + return 0; + } + if ((enter2 = bpf_ringbuf_reserve( + &output, sizeof(struct sys_enter_info2_t), 0)) == + NULL) { + // bpf_printk("FAILED to reserve space in ring buffer + // for " + // "event_type == " + // "SYS_ENTER2\n"); + u32 key = 0; + u32 *missed = bpf_map_lookup_elem(&missed_events, &key); + if (missed) { + __sync_fetch_and_add(missed, 1); + } + + return 0; + } + + enter2 -> pid = pid_tgid; + enter2 -> syscall_nr = tp -> id; + enter2 -> flags = -1; + bpf_map_delete_elem(&pipe_tracker, &pid); + + int fds[2]; + bpf_probe_read_user(&fds, sizeof(fds), (void *)(*fds_pointers)); + + enter2 -> fd = fds[0]; + enter2 -> fd2 = fds[1]; + char *path2 = NULL; + char pipe_str[32]; + __u64 pid_data = pid; + bpf_snprintf(pipe_str, sizeof(pipe_str), "/pipe%d", &pid_data, sizeof(pid_data)); + + // Copy the formatted string to enter2->path + int i; + #pragma unroll + for (i = 0; i < 31 && pipe_str[i] != '\0'; i++) { + enter2->path[i] = pipe_str[i]; + } + enter2->path[i] = '\0'; + + bpf_probe_read_user_str(&enter2->path2, sizeof(enter2->path2), path2); + + bpf_ringbuf_submit(enter2, 0); + + + struct sys_exit_info_t *exit; + if ((exit = bpf_ringbuf_reserve(&output, sizeof(struct sys_exit_info_t), + 0)) == NULL) { + // bpf_printk( + // "FAILED to reserve space in ring buffer for event_type == + // " "SYS_EXIT\n"); + u32 key = 0; + u32 *missed = bpf_map_lookup_elem(&missed_events, &key); + if (missed) { + __sync_fetch_and_add(missed, 1); + } + + return 0; + } + exit->pid = pid_tgid; + exit->ret = tp -> ret; + bpf_ringbuf_submit(exit, 0); + + return 0; +} + + SEC("tp_btf/sched_process_fork") int @@ -152,6 +268,14 @@ BPF_PROG(hs_trace_sys_enter, struct pt_regs *regs, long syscall_id) event_type = SYS_ENTER1; break; #endif +#ifdef __NR_openat2 + case __NR_openat2: /* individually */ + fd = (int)PT_REGS_PARM1_CORE(regs); + path = (char *)PT_REGS_PARM2_CORE(regs); + flags = (int)PT_REGS_PARM3_CORE(regs); + event_type = SYS_ENTER1; + break; +#endif #ifdef __NR_open case __NR_open: path = (char *)PT_REGS_PARM1_CORE(regs); @@ -217,6 +341,22 @@ BPF_PROG(hs_trace_sys_enter, struct pt_regs *regs, long syscall_id) event_type = SYS_ENTER1; break; #endif +#ifdef __NR_dup2 + case __NR_dup2: +#endif +#ifdef __NR_dup3 + case __NR_dup3: + fd = (int)PT_REGS_PARM1_CORE(regs); + fd2 = (int)PT_REGS_PARM2_CORE(regs); + event_type = SYS_ENTER2; + break; +#endif +#ifdef __NR_dup + case __NR_dup: + fd = (int)PT_REGS_PARM1_CORE(regs); + event_type = SYS_ENTER1; + break; +#endif #ifdef __NR_execve case __NR_execve: /* r_first_path_set */ #endif @@ -431,7 +571,6 @@ struct sys_exit_args { }; SEC("tracepoint/raw_syscalls/sys_exit") - int BPF_PROG(hs_trace_sys_exit) { @@ -448,6 +587,9 @@ BPF_PROG(hs_trace_sys_exit) #ifdef __NR_openat case __NR_openat: /* individually */ #endif +#ifdef __NR_openat2 + case __NR_openat2: /* individually */ +#endif #ifdef __NR_open case __NR_open: #endif @@ -478,6 +620,14 @@ BPF_PROG(hs_trace_sys_exit) #ifdef __NR_execve case __NR_execve: /* r_first_path_set */ #endif +#ifdef __NR_dup2 + case __NR_dup2: +#endif +#ifdef __NR_dup3 + case __NR_dup3: +#endif +#ifdef __NR_dup +#endif #ifdef __NR_statfs case __NR_statfs: #endif diff --git a/src/dep_tracer.rs b/src/dep_tracer.rs index d81679b..4bf6125 100644 --- a/src/dep_tracer.rs +++ b/src/dep_tracer.rs @@ -168,12 +168,16 @@ impl Logs { } pub fn dump_log(&mut self) { - for (pid_tgid, log) in self.log.iter() { - println!( - "log for pid {} tgid {}:", - pid_tgid & 0xFFFFFFFF, - pid_tgid >> 32 - ); + let mut sorted_logs: Vec<_> = self + .log + .iter() + .map(|(pid_tgid, logs)| (pid_tgid & 0xFFFFFFFF, pid_tgid >> 32, logs)) + .collect(); + + sorted_logs.sort_by(|(a, b, c), (d, e, f)| a.cmp(d)); + + for (pid, tgid, log) in sorted_logs { + println!("log for pid {} tgid {}:", pid, tgid); for e in log.iter() { match e { SyscallEvent::Enter0(e) => { @@ -215,6 +219,7 @@ pub struct Context { cwd_map: HashMap, process_graph: HashMap, dirfd_map: HashMap<(u64, i32), PathBuf>, + openfds_map: HashMap<(i32, i32), PathBuf>, } impl Context { @@ -223,6 +228,7 @@ impl Context { cwd_map: HashMap::new(), process_graph: HashMap::new(), dirfd_map: HashMap::new(), + openfds_map: HashMap::new(), } } pub fn init_pid(&mut self, pid: u64, cwd: PathBuf) { @@ -230,10 +236,37 @@ impl Context { } pub fn do_clone(&mut self, parent_pid_tgid: u64, child_pid_tgid: u64) -> () { + // let parent_id = ((parent_pid_tgid >> 32) as i32); + // let child_id = ((child_pid_tgid >> 32) as i32); self.process_graph.insert(child_pid_tgid, parent_pid_tgid); let parent_cwd = self.cwd_map.get(&parent_pid_tgid).unwrap(); self.cwd_map.insert(child_pid_tgid, parent_cwd.clone()); + let new_pid_fds: Vec<_> = self + .openfds_map + .iter() + .filter(|&((pid, fd), path)| { + if *pid == (parent_pid_tgid & 0xFFFFFFFF) as i32 { + true + } else { + false + } + }) + .map(|(&key, path)| (key, path.clone())) + .collect(); + for ((_old_pid, fd), path) in new_pid_fds { + self.map_fds((child_pid_tgid & 0xFFFFFFFF) as i32, fd, path.to_owned()) + } + let c = &self.openfds_map; + } + + pub fn map_fds(&mut self, pid: i32, fd: i32, path: PathBuf) { + self.openfds_map.insert((pid, fd), path); } + + pub fn get_path_from_fd(&self, pid: i32, fd: i32) -> Option { + self.openfds_map.get(&(pid, fd)).map(|path| path.clone()) + } + } pub struct RWSet { @@ -335,10 +368,13 @@ fn on_event_update_rw_sets(event: SyscallInfo) { fd, path, } => match syscall_nr { + libc::SYS_dup => { + parse_dup(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) + } libc::SYS_inotify_add_watch => parse_SYS_inotify_add_watch( &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, ), - libc::SYS_openat => { + libc::SYS_openat | libc::SYS_openat2 => { parse_openat(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) } @@ -395,7 +431,7 @@ fn on_event_update_rw_sets(event: SyscallInfo) { | libc::SYS_mknodat | libc::SYS_fchownat | libc::SYS_fchmodat => { - parse_r_fd_path_e1(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) + parse_w_fd_path_e1(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) } // libc::SYS_futimeat => {} _ => {} @@ -410,11 +446,18 @@ fn on_event_update_rw_sets(event: SyscallInfo) { fd2, path2, } => match syscall_nr { + libc::SYS_dup3 => parse_dup23( + &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, fd2, &path2, + ), // libc::SYS_link => {} // libc::SYS_rename => {} libc::SYS_renameat | libc::SYS_renameat2 => parse_renameat( &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, fd2, &path2, ), + + libc::SYS_pipe2 => parse_pipe2( + &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, fd2, &path2, + ), _ => {} }, } @@ -475,6 +518,75 @@ enum AccessKind { Write, } +fn parse_dup( + ctxt: &mut Context, + _sets: &mut RWSet, + pid: u64, + ret: i64, + _syscall_nr: i64, + _flags: u32, + fd: i32, + _path: &str, +) { + if ret < 0 { + return; + } + let c = (pid & 0xFFFF_FFFF) as i32; + + let new_fd = match i32::try_from(ret) { + Ok(x) => x, + Err(_) => return, + }; + + let pid: i32 = (pid & 0xFFFF_FFFF) as i32; + + if let Some(p) = ctxt.get_path_from_fd(pid, fd) { + ctxt.map_fds(pid, fd, p.clone()); + ctxt.map_fds(pid, new_fd, p); + } +} + +fn parse_dup23( + ctxt: &mut Context, + sets: &mut RWSet, + pid: u64, + ret: i64, + syscall_nr: i64, + flags: u32, + fd: i32, + path: &str, + fd2: i32, + path2: &str, +) { + let pid = (pid & 0xFFFFFFFF) as i32; + + if ret >= 0 { + let new_map = ctxt.get_path_from_fd(pid, fd); + if let Some(valid_path) = new_map { + ctxt.map_fds(pid, fd2, valid_path); + } + } +} + +fn parse_pipe2( + ctxt: &mut Context, + sets: &mut RWSet, + pid: u64, + ret: i64, + syscall_nr: i64, + flags: u32, + fd: i32, + path: &str, + fd2: i32, + path2: &str, +) { + let path = convert_absolute(ctxt, pid, path, None); + let pid = (pid & 0xFFFFFFFF) as i32; + println!("{pid}"); + + ctxt.map_fds(pid, fd, path.clone()); + ctxt.map_fds(pid, fd2, path); +} fn parse_SYS_inotify_add_watch( ctxt: &mut Context, sets: &mut RWSet, @@ -493,6 +605,36 @@ fn parse_SYS_inotify_add_watch( insert_with_ancestors(sets, abs, AccessKind::Read); } +// fn parse_openat( +// ctxt: &mut Context, +// sets: &mut RWSet, +// pid: u64, +// ret: i64, +// syscall_nr: i64, +// flags: u32, +// fd: i32, +// path: &str, +// ) { +// let abs = convert_absolute(&ctxt, pid, &path, Some(fd)); +// if ret >= 0 { +// let new_fd = ret as i32; +// ctxt.map_fds((pid & 0xFFFFFFFF) as i32, new_fd, abs.clone()); + +// if (flags & libc::O_DIRECTORY as u32) != 0 { +// ctxt.dirfd_map.insert((pid, new_fd), abs.clone()); +// } +// } + +// let kind = if ret < 0 { +// AccessKind::Read +// } else if (flags & libc::O_RDONLY as u32) != 0 { +// AccessKind::Read +// } else { +// AccessKind::Write +// }; +// insert_with_ancestors(sets, abs, kind); +// } + fn parse_openat( ctxt: &mut Context, sets: &mut RWSet, @@ -504,19 +646,40 @@ fn parse_openat( path: &str, ) { let abs = convert_absolute(&ctxt, pid, &path, Some(fd)); + if ret >= 0 { + let new_fd = ret as i32; + ctxt.map_fds((pid & 0xFFFFFFFF) as i32, new_fd, abs.clone()); - if ret >= 0 && (flags & libc::O_DIRECTORY as u32) != 0 { - ctxt.dirfd_map.insert((pid, ret as i32), abs.clone()); + if (flags & libc::O_DIRECTORY as u32) != 0 { + ctxt.dirfd_map.insert((pid, new_fd), abs.clone()); + } } - let kind = if ret < 0 { - AccessKind::Read - } else if (flags & libc::O_RDONLY as u32) != 0 { - AccessKind::Read + if ret < 0 { + // Failed open is always a read attempt + insert_with_ancestors(sets, abs, AccessKind::Read); } else { - AccessKind::Write - }; - insert_with_ancestors(sets, abs, kind); + // Check the access mode (lower 2 bits of flags) + let access_mode = (flags & libc::O_ACCMODE as u32) as i32; + + match access_mode { + libc::O_RDONLY => { + insert_with_ancestors(sets, abs, AccessKind::Read); + } + libc::O_WRONLY => { + insert_with_ancestors(sets, abs, AccessKind::Write); + } + libc::O_RDWR => { + // File is opened for both reading and writing + insert_with_ancestors(sets, abs.clone(), AccessKind::Read); + insert_with_ancestors(sets, abs, AccessKind::Write); + } + _ => { + // Shouldn't happen, but default to read + insert_with_ancestors(sets, abs, AccessKind::Read); + } + } + } } fn parse_open( @@ -572,6 +735,8 @@ fn parse_clone( if ret < 0 { return; }; + let a = (pid & 0xFFFFFFFF) as i32; + let r = ret as i32; ctxt.do_clone(pid, ret as u64) } diff --git a/src/main.rs b/src/main.rs index 4114a85..3e840ba 100644 --- a/src/main.rs +++ b/src/main.rs @@ -111,6 +111,12 @@ fn main() -> Result<()> { ctxt.init_pid(pid_tgid, cwd.clone()); // Also initialize with just the pid (lower 32 bits) since some events might use that ctxt.init_pid(target_pid as u64, cwd.clone()); + for entry in std::fs::read_dir(format!("/proc/{}/fd", target_pid))? { + let entry = entry?; + let fd: i32 = entry.file_name().to_string_lossy().parse().unwrap(); + let path = std::fs::read_link(entry.path())?; + ctxt.map_fds(target_pid, fd, path); + } } let skel_builder = HsTraceSkelBuilder::default(); @@ -205,7 +211,7 @@ fn main() -> Result<()> { Err(_) => {} } let _ = stream_handler.join(); - + let ctxt = CTXT.lock().unwrap(); let mut logs = LOGS.lock().unwrap(); logs.dump_log(); From 19bae8728d810cb6c3921f4e16cf7181aee2fef2 Mon Sep 17 00:00:00 2001 From: Dan Liu Date: Thu, 7 Aug 2025 23:19:00 -0400 Subject: [PATCH 2/7] format bpf code + use BPF_PROG and struct casting + BPF_SNPRINTF --- src/bpf/hs_trace.bpf.c | 105 ++++++++++++++++++++++------------------- 1 file changed, 57 insertions(+), 48 deletions(-) diff --git a/src/bpf/hs_trace.bpf.c b/src/bpf/hs_trace.bpf.c index 1836537..bc0696b 100644 --- a/src/bpf/hs_trace.bpf.c +++ b/src/bpf/hs_trace.bpf.c @@ -24,7 +24,7 @@ struct { __uint(type, BPF_MAP_TYPE_HASH); __type(key, u32); __type(value, u64); - __uint(max_entries, 1024*1024); + __uint(max_entries, 1024 * 1024); } pipe_tracker SEC(".maps"); // struct { @@ -55,31 +55,51 @@ enum syscall_event_type { SYS_EXIT }; +struct sys_enter_pipe2_args { + unsigned short common_type; + unsigned char common_flags; + unsigned char common_preempt_count; + int common_pid; + int id; // syscall number + int *fildes; // pipe fds + long flags; // flags +}; + SEC("tracepoint/syscalls/sys_enter_pipe2") + int -hs_trace_create_pipe(struct trace_event_raw_sys_enter *tp) +BPF_PROG(hs_trace_create_pipe) { u64 pid_tgid = bpf_get_current_pid_tgid(); - u32 pid = pid_tgid & 0xFFFFFFFF; - - if (bpf_map_lookup_elem(&pid_set, &pid) == NULL) { - return 0; - } - - u64 ptr = (u64)tp->args[0]; - if (bpf_map_update_elem(&pipe_tracker, &pid, &ptr, BPF_ANY) < 0) { - bpf_printk("failed to update pipe_tracker with pid %d\n", pid); - return 0; - } - - return 0; + u32 pid = pid_tgid & 0xFFFFFFFF; + + if (bpf_map_lookup_elem(&pid_set, &pid) == NULL) { + return 0; + } + + u64 ptr = (u64)((struct sys_enter_pipe2_args *)ctx)->fildes; + if (bpf_map_update_elem(&pipe_tracker, &pid, &ptr, BPF_ANY) < 0) { + bpf_printk("failed to update pipe_tracker with pid %d\n", pid); + return 0; + } + + return 0; } +struct sys_exit_pipe2_args { + unsigned short common_type; + unsigned char common_flags; + unsigned char common_preempt_count; + int common_pid; + int id; // syscall number + long ret; // return value +}; + SEC("tracepoint/syscalls/sys_exit_pipe2") -int -hs_trace_create_pipe_exit(struct trace_event_raw_sys_exit *tp) -{ +int +BPF_PROG(hs_trace_create_pipe_exit) +{ struct sys_enter_info2_t *enter2; u64 pid_tgid = bpf_get_current_pid_tgid(); @@ -88,19 +108,17 @@ hs_trace_create_pipe_exit(struct trace_event_raw_sys_exit *tp) // bpf_printk("pid %d is not in set\n", pid); return 0; } - long ret = tp -> ret; - if (ret < 0) { + if (((struct sys_exit_pipe2_args *)ctx)->ret < 0) { return 0; } - - u64 *fds_pointers = bpf_map_lookup_elem(&pipe_tracker, &pid); - if (!fds_pointers) { + u64 *fds_pointers; + if ((fds_pointers = bpf_map_lookup_elem(&pipe_tracker, &pid)) == NULL) { return 0; } + if ((enter2 = bpf_ringbuf_reserve( - &output, sizeof(struct sys_enter_info2_t), 0)) == - NULL) { + &output, sizeof(struct sys_enter_info2_t), 0)) == NULL) { // bpf_printk("FAILED to reserve space in ring buffer // for " // "event_type == " @@ -114,33 +132,23 @@ hs_trace_create_pipe_exit(struct trace_event_raw_sys_exit *tp) return 0; } - enter2 -> pid = pid_tgid; - enter2 -> syscall_nr = tp -> id; - enter2 -> flags = -1; + enter2->pid = pid_tgid; + enter2->syscall_nr = ((struct sys_exit_pipe2_args *)ctx)->id; + enter2->flags = -1; bpf_map_delete_elem(&pipe_tracker, &pid); int fds[2]; - bpf_probe_read_user(&fds, sizeof(fds), (void *)(*fds_pointers)); + bpf_probe_read_user(&fds, sizeof(fds), (void *)(*fds_pointers)); + enter2->fd = fds[0]; + enter2->fd2 = fds[1]; - enter2 -> fd = fds[0]; - enter2 -> fd2 = fds[1]; char *path2 = NULL; char pipe_str[32]; - __u64 pid_data = pid; - bpf_snprintf(pipe_str, sizeof(pipe_str), "/pipe%d", &pid_data, sizeof(pid_data)); - - // Copy the formatted string to enter2->path - int i; - #pragma unroll - for (i = 0; i < 31 && pipe_str[i] != '\0'; i++) { - enter2->path[i] = pipe_str[i]; - } - enter2->path[i] = '\0'; - - bpf_probe_read_user_str(&enter2->path2, sizeof(enter2->path2), path2); + BPF_SNPRINTF(enter2->path, sizeof(pipe_str), "/pipe%d", pid); - bpf_ringbuf_submit(enter2, 0); + bpf_probe_read_user_str(&enter2->path2, sizeof(enter2->path2), path2); + bpf_ringbuf_submit(enter2, 0); struct sys_exit_info_t *exit; if ((exit = bpf_ringbuf_reserve(&output, sizeof(struct sys_exit_info_t), @@ -157,9 +165,9 @@ hs_trace_create_pipe_exit(struct trace_event_raw_sys_exit *tp) return 0; } exit->pid = pid_tgid; - exit->ret = tp -> ret; + exit->ret = ((struct sys_exit_pipe2_args *)ctx)->ret; bpf_ringbuf_submit(exit, 0); - + return 0; } @@ -355,7 +363,7 @@ BPF_PROG(hs_trace_sys_enter, struct pt_regs *regs, long syscall_id) case __NR_dup: fd = (int)PT_REGS_PARM1_CORE(regs); event_type = SYS_ENTER1; - break; + break; #endif #ifdef __NR_execve case __NR_execve: /* r_first_path_set */ @@ -571,6 +579,7 @@ struct sys_exit_args { }; SEC("tracepoint/raw_syscalls/sys_exit") + int BPF_PROG(hs_trace_sys_exit) { @@ -621,7 +630,7 @@ BPF_PROG(hs_trace_sys_exit) case __NR_execve: /* r_first_path_set */ #endif #ifdef __NR_dup2 - case __NR_dup2: + case __NR_dup2: #endif #ifdef __NR_dup3 case __NR_dup3: From 038129e9951e2dd9ec464a9b967f53908e469d20 Mon Sep 17 00:00:00 2001 From: Divik Chotani Date: Sat, 16 Aug 2025 23:31:44 -0700 Subject: [PATCH 3/7] handled files with dup1 and 3 --- src/dep_tracer.rs | 26 ++++++++++++++++++++++++-- 1 file changed, 24 insertions(+), 2 deletions(-) diff --git a/src/dep_tracer.rs b/src/dep_tracer.rs index 4bf6125..6950d9d 100644 --- a/src/dep_tracer.rs +++ b/src/dep_tracer.rs @@ -890,13 +890,35 @@ pub fn event_stream_handler(rx: mpsc::Receiver>) -> Result< let mut logs = LOGS.lock().unwrap(); logs.update_log(pid, SyscallEvent::Enter0(e)) } - Ok(Some(SyscallEvent::Enter1(e))) => { + Ok(Some(SyscallEvent::Enter1(mut e))) => { let pid = e.pid as u64; + { + let ctxt = CTXT.lock().unwrap(); + if libc::SYS_dup == e.syscall_nr { + let a = (e.pid & 0xFFFFFFFF) as i32; + if let Some(p) = ctxt.get_path_from_fd(a, e.fd) { + let path = p.to_str().unwrap().as_bytes(); + let len = e.path.len().min(path.len()); + e.path[..len].copy_from_slice(path); + } + } + } let mut logs = LOGS.lock().unwrap(); logs.update_log(pid, SyscallEvent::Enter1(e)) } - Ok(Some(SyscallEvent::Enter2(e))) => { + Ok(Some(SyscallEvent::Enter2(mut e))) => { let pid = e.pid as u64; + { + let ctxt = CTXT.lock().unwrap(); + if libc::SYS_dup3 == e.syscall_nr { + let a = (e.pid & 0xFFFFFFFF) as i32; + if let Some(p) = ctxt.get_path_from_fd(a, e.fd) { + let path = p.to_str().unwrap().as_bytes(); + let len = e.path.len().min(path.len()); + e.path[..len].copy_from_slice(path); + } + } + } let mut logs = LOGS.lock().unwrap(); logs.update_log(pid, SyscallEvent::Enter2(e)) } From 43d9df2fe09a9477d39cd489478384b23a3612b3 Mon Sep 17 00:00:00 2001 From: Dan Liu Date: Sun, 17 Aug 2025 08:38:55 -0400 Subject: [PATCH 4/7] refactor event struct field pid to pid_tgid --- src/bpf/hs_trace.bpf.c | 16 ++-- src/bpf/hs_trace.h | 14 +-- src/dep_tracer.rs | 200 +++++++++++++++++++++-------------------- 3 files changed, 118 insertions(+), 112 deletions(-) diff --git a/src/bpf/hs_trace.bpf.c b/src/bpf/hs_trace.bpf.c index bc0696b..f5e97ba 100644 --- a/src/bpf/hs_trace.bpf.c +++ b/src/bpf/hs_trace.bpf.c @@ -132,7 +132,7 @@ BPF_PROG(hs_trace_create_pipe_exit) return 0; } - enter2->pid = pid_tgid; + enter2->pid_tgid = pid_tgid; enter2->syscall_nr = ((struct sys_exit_pipe2_args *)ctx)->id; enter2->flags = -1; bpf_map_delete_elem(&pipe_tracker, &pid); @@ -164,7 +164,7 @@ BPF_PROG(hs_trace_create_pipe_exit) return 0; } - exit->pid = pid_tgid; + exit->pid_tgid = pid_tgid; exit->ret = ((struct sys_exit_pipe2_args *)ctx)->ret; bpf_ringbuf_submit(exit, 0); @@ -209,7 +209,7 @@ BPF_PROG(hs_trace_process_fork, struct task_struct *parent, } return 0; } - enter0->pid = p_pid_tgid; + enter0->pid_tgid = p_pid_tgid; enter0->syscall_nr = __NR_clone; enter0->flags = 0; bpf_ringbuf_submit(enter0, 0); @@ -228,7 +228,7 @@ BPF_PROG(hs_trace_process_fork, struct task_struct *parent, return 0; } - exit->pid = p_pid_tgid; + exit->pid_tgid = p_pid_tgid; exit->ret = c_pid_tgid; bpf_ringbuf_submit(exit, 0); return 0; @@ -511,7 +511,7 @@ BPF_PROG(hs_trace_sys_enter, struct pt_regs *regs, long syscall_id) return 0; } - enter0->pid = pid_tgid; + enter0->pid_tgid = pid_tgid; enter0->syscall_nr = syscall_id; enter0->flags = flags; bpf_ringbuf_submit(enter0, 0); @@ -531,7 +531,7 @@ BPF_PROG(hs_trace_sys_enter, struct pt_regs *regs, long syscall_id) return 0; } - enter1->pid = pid_tgid; + enter1->pid_tgid = pid_tgid; enter1->syscall_nr = syscall_id; enter1->flags = flags; enter1->fd = fd; @@ -554,7 +554,7 @@ BPF_PROG(hs_trace_sys_enter, struct pt_regs *regs, long syscall_id) return 0; } - enter2->pid = pid_tgid; + enter2->pid_tgid = pid_tgid; enter2->syscall_nr = syscall_id; enter2->flags = flags; enter2->fd = fd; @@ -760,7 +760,7 @@ BPF_PROG(hs_trace_sys_exit) return 0; } - exit->pid = pid_tgid; + exit->pid_tgid = pid_tgid; exit->ret = ((struct sys_exit_args *)ctx)->ret; bpf_ringbuf_submit(exit, 0); diff --git a/src/bpf/hs_trace.h b/src/bpf/hs_trace.h index 2edca37..5bf6161 100644 --- a/src/bpf/hs_trace.h +++ b/src/bpf/hs_trace.h @@ -7,31 +7,31 @@ struct unique_file_t { }; struct sys_enter_info0_t { - long int pid; + long int pid_tgid; long int syscall_nr; int flags; // for special handling: open*, clone, linkat, etc. }; struct sys_enter_info1_t { - long int pid; + long int pid_tgid; long int syscall_nr; int flags; // for special handling: open*, clone, linkat, etc. - int fd; // for -at syscalls: could be AT_FDCWD + int fd; // for -at syscalls: could be AT_FDCWD char path[4096]; }; struct sys_enter_info2_t { - long int pid; + long int pid_tgid; long int syscall_nr; int flags; // for special handling: open*, clone, linkat, etc. - int fd; // for -at syscalls: could be AT_FDCWD - int fd2; // for renameat2 and linkat + int fd; // for -at syscalls: could be AT_FDCWD + int fd2; // for renameat2 and linkat char path[4096]; char path2[4096]; }; struct sys_exit_info_t { - long int pid; + long int pid_tgid; long int ret; }; diff --git a/src/dep_tracer.rs b/src/dep_tracer.rs index 6950d9d..6887503 100644 --- a/src/dep_tracer.rs +++ b/src/dep_tracer.rs @@ -7,6 +7,7 @@ use std::path::{Component, PathBuf}; use std::sync::mpsc; use std::sync::{Mutex, RwLock}; use trace_v3::*; + #[cfg(target_arch = "x86_64")] pub fn individually_handled_syscall_map() -> HashMap { let mut m = HashMap::new(); @@ -257,7 +258,7 @@ impl Context { self.map_fds((child_pid_tgid & 0xFFFFFFFF) as i32, fd, path.to_owned()) } let c = &self.openfds_map; - } + } pub fn map_fds(&mut self, pid: i32, fd: i32, path: PathBuf) { self.openfds_map.insert((pid, fd), path); @@ -266,7 +267,6 @@ impl Context { pub fn get_path_from_fd(&self, pid: i32, fd: i32) -> Option { self.openfds_map.get(&(pid, fd)).map(|path| path.clone()) } - } pub struct RWSet { @@ -322,13 +322,13 @@ pub static SETS: Lazy> = Lazy::new(|| Mutex::new(RWSet::new())); pub static LOGS: Lazy> = Lazy::new(|| Mutex::new(Logs::new())); enum SyscallInfo { Event0 { - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, }, Event1 { - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -336,7 +336,7 @@ enum SyscallInfo { path: String, }, Event2 { - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -352,57 +352,60 @@ fn on_event_update_rw_sets(event: SyscallInfo) { let mut sets = SETS.lock().unwrap(); match event { SyscallInfo::Event0 { - pid, + pid_tgid, ret, syscall_nr, flags, } => match syscall_nr { - libc::SYS_clone => parse_clone(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags), + libc::SYS_clone => parse_clone(&mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags), _ => {} }, SyscallInfo::Event1 { - pid, + pid_tgid, ret, syscall_nr, flags, fd, path, } => match syscall_nr { - libc::SYS_dup => { - parse_dup(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) - } + libc::SYS_dup => parse_dup( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ), libc::SYS_inotify_add_watch => parse_SYS_inotify_add_watch( - &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ), + libc::SYS_openat | libc::SYS_openat2 => parse_openat( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, ), - libc::SYS_openat | libc::SYS_openat2 => { - parse_openat(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) - } - // #[cfg(target_arch = "x86_64")] // libc::SYS_open => { // let mut ctxt = CTXT.lock().unwrap(); // let mut sets = SETS.lock().unwrap(); - // parse_open(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) + // parse_open( + // &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + // ) // } - libc::SYS_chdir => { - parse_chdir(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) - } - libc::SYS_symlinkat => { - parse_symlinkat(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) - } + libc::SYS_chdir => parse_chdir( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ), + libc::SYS_symlinkat => parse_symlinkat( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ), // libc::SYS_symlink => {} // r path libc::SYS_execve | libc::SYS_statfs | libc::SYS_getxattr | libc::SYS_lgetxattr => { - parse_r_first_path_e1(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) + parse_r_first_path_e1( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ) } // libc::SYS_stat => {} // libc::SYS_lstat => {} // libc::SYS_access => {} // libc::SYS_readlink => {} // w path - libc::SYS_truncate | libc::SYS_acct => { - parse_w_first_path_e1(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) - } + libc::SYS_truncate | libc::SYS_acct => parse_w_first_path_e1( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ), // libc::SYS_mkdir => {} // libc::SYS_rmdir => {} // libc::SYS_creat => {} @@ -420,9 +423,9 @@ fn on_event_update_rw_sets(event: SyscallInfo) { | libc::SYS_readlinkat | libc::SYS_faccessat | libc::SYS_faccessat2 - | libc::SYS_execveat => { - parse_r_fd_path_e1(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) - } + | libc::SYS_execveat => parse_r_fd_path_e1( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ), // w fd path libc::SYS_linkat | libc::SYS_unlinkat @@ -430,14 +433,14 @@ fn on_event_update_rw_sets(event: SyscallInfo) { | libc::SYS_mkdirat | libc::SYS_mknodat | libc::SYS_fchownat - | libc::SYS_fchmodat => { - parse_w_fd_path_e1(&mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path) - } + | libc::SYS_fchmodat => parse_w_fd_path_e1( + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, + ), // libc::SYS_futimeat => {} _ => {} }, SyscallInfo::Event2 { - pid, + pid_tgid, ret, syscall_nr, flags, @@ -447,43 +450,46 @@ fn on_event_update_rw_sets(event: SyscallInfo) { path2, } => match syscall_nr { libc::SYS_dup3 => parse_dup23( - &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, fd2, &path2, + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, fd2, &path2, ), // libc::SYS_link => {} // libc::SYS_rename => {} libc::SYS_renameat | libc::SYS_renameat2 => parse_renameat( - &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, fd2, &path2, + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, fd2, &path2, ), - libc::SYS_pipe2 => parse_pipe2( - &mut ctxt, &mut sets, pid, ret, syscall_nr, flags, fd, &path, fd2, &path2, + &mut ctxt, &mut sets, pid_tgid, ret, syscall_nr, flags, fd, &path, fd2, &path2, ), _ => {} }, } } + fn is_absolute_path(path: &str) -> bool { !path.is_empty() && path.starts_with('/') } -fn convert_absolute(ctxt: &Context, pid: u64, raw_path: &str, dirfd: Option) -> PathBuf { +fn convert_absolute(ctxt: &Context, pid_tgid: u64, raw_path: &str, dirfd: Option) -> PathBuf { let binding = if is_absolute_path(raw_path) { PathBuf::from(raw_path) } else { let base = if let Some(fd) = dirfd { if fd == libc::AT_FDCWD { ctxt.cwd_map - .get(&pid) - .expect("pid not found bc pid not in cwd") + .get(&pid_tgid) + .expect("pid_tgid not found bc pid_tgid not in cwd") .clone() } else { ctxt.dirfd_map - .get(&(pid, fd)) - .expect("fd or pid not found in map") + .get(&(pid_tgid, fd)) + .expect("fd or pid_tgid not found in map") .clone() } } else { - ctxt.cwd_map.get(&pid).expect("pid not found").clone() + ctxt.cwd_map + .get(&pid_tgid) + .expect("pid_tgid not found") + .clone() }; base.join(raw_path) }; @@ -521,7 +527,7 @@ enum AccessKind { fn parse_dup( ctxt: &mut Context, _sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, _syscall_nr: i64, _flags: u32, @@ -531,14 +537,13 @@ fn parse_dup( if ret < 0 { return; } - let c = (pid & 0xFFFF_FFFF) as i32; let new_fd = match i32::try_from(ret) { Ok(x) => x, Err(_) => return, }; - let pid: i32 = (pid & 0xFFFF_FFFF) as i32; + let pid: i32 = (pid_tgid & 0xFFFF_FFFF) as i32; if let Some(p) = ctxt.get_path_from_fd(pid, fd) { ctxt.map_fds(pid, fd, p.clone()); @@ -549,7 +554,7 @@ fn parse_dup( fn parse_dup23( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -558,7 +563,7 @@ fn parse_dup23( fd2: i32, path2: &str, ) { - let pid = (pid & 0xFFFFFFFF) as i32; + let pid = (pid_tgid & 0xFFFFFFFF) as i32; if ret >= 0 { let new_map = ctxt.get_path_from_fd(pid, fd); @@ -571,7 +576,7 @@ fn parse_dup23( fn parse_pipe2( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -580,17 +585,18 @@ fn parse_pipe2( fd2: i32, path2: &str, ) { - let path = convert_absolute(ctxt, pid, path, None); - let pid = (pid & 0xFFFFFFFF) as i32; + let path = convert_absolute(ctxt, pid_tgid, path, None); + let pid = (pid_tgid & 0xFFFFFFFF) as i32; println!("{pid}"); ctxt.map_fds(pid, fd, path.clone()); ctxt.map_fds(pid, fd2, path); } + fn parse_SYS_inotify_add_watch( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -600,7 +606,7 @@ fn parse_SYS_inotify_add_watch( if path.is_empty() { return; } - let abs = convert_absolute(ctxt, pid, path, None); + let abs = convert_absolute(ctxt, pid_tgid, path, None); insert_with_ancestors(sets, abs, AccessKind::Read); } @@ -638,20 +644,20 @@ fn parse_SYS_inotify_add_watch( fn parse_openat( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, fd: i32, path: &str, ) { - let abs = convert_absolute(&ctxt, pid, &path, Some(fd)); + let abs = convert_absolute(&ctxt, pid_tgid, &path, Some(fd)); if ret >= 0 { let new_fd = ret as i32; - ctxt.map_fds((pid & 0xFFFFFFFF) as i32, new_fd, abs.clone()); + ctxt.map_fds((pid_tgid & 0xFFFFFFFF) as i32, new_fd, abs.clone()); if (flags & libc::O_DIRECTORY as u32) != 0 { - ctxt.dirfd_map.insert((pid, new_fd), abs.clone()); + ctxt.dirfd_map.insert((pid_tgid, new_fd), abs.clone()); } } @@ -661,7 +667,7 @@ fn parse_openat( } else { // Check the access mode (lower 2 bits of flags) let access_mode = (flags & libc::O_ACCMODE as u32) as i32; - + match access_mode { libc::O_RDONLY => { insert_with_ancestors(sets, abs, AccessKind::Read); @@ -685,16 +691,16 @@ fn parse_openat( fn parse_open( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, fd: i32, path: &str, ) { - let abs = convert_absolute(&ctxt, pid, &path, None); + let abs = convert_absolute(&ctxt, pid_tgid, &path, None); if ret >= 0 && (flags & libc::O_DIRECTORY as u32) != 0 { - ctxt.dirfd_map.insert((pid, ret as i32), abs.clone()); + ctxt.dirfd_map.insert((pid_tgid, ret as i32), abs.clone()); } let kind = if ret < 0 { @@ -710,16 +716,16 @@ fn parse_open( fn parse_chdir( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, fd: i32, path: &str, ) { - let abs = convert_absolute(ctxt, pid, &path, None); + let abs = convert_absolute(ctxt, pid_tgid, &path, None); if ret == 0 { - ctxt.cwd_map.insert(pid, abs.clone()); + ctxt.cwd_map.insert(pid_tgid, abs.clone()); } insert_with_ancestors(sets, abs, AccessKind::Read); } @@ -727,7 +733,7 @@ fn parse_chdir( fn parse_clone( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -735,22 +741,22 @@ fn parse_clone( if ret < 0 { return; }; - let a = (pid & 0xFFFFFFFF) as i32; + let pid = (pid_tgid & 0xFFFFFFFF) as i32; let r = ret as i32; - ctxt.do_clone(pid, ret as u64) + ctxt.do_clone(pid_tgid, ret as u64) } fn parse_symlinkat( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, fd: i32, path: &str, ) { - let abs = convert_absolute(ctxt, pid, &path, Some(fd)); + let abs = convert_absolute(ctxt, pid_tgid, &path, Some(fd)); let kind = if ret != 0 { AccessKind::Read } else { @@ -763,7 +769,7 @@ fn parse_symlinkat( fn parse_r_first_path_e1( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -773,7 +779,7 @@ fn parse_r_first_path_e1( if path.is_empty() { return; } - let abs = convert_absolute(ctxt, pid, &path, None); + let abs = convert_absolute(ctxt, pid_tgid, &path, None); insert_with_ancestors(sets, abs, AccessKind::Read); } @@ -781,7 +787,7 @@ fn parse_r_first_path_e1( fn parse_w_first_path_e1( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -792,7 +798,7 @@ fn parse_w_first_path_e1( return; } - let abs = convert_absolute(ctxt, pid, path, None); + let abs = convert_absolute(ctxt, pid_tgid, path, None); let kind = if ret == 0 { AccessKind::Write } else { @@ -805,7 +811,7 @@ fn parse_w_first_path_e1( fn parse_r_fd_path_e1( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -816,7 +822,7 @@ fn parse_r_fd_path_e1( return; } - let abs = convert_absolute(ctxt, pid, path, Some(fd)); + let abs = convert_absolute(ctxt, pid_tgid, path, Some(fd)); insert_with_ancestors(sets, abs, AccessKind::Read); } @@ -824,7 +830,7 @@ fn parse_r_fd_path_e1( fn parse_w_fd_path_e1( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -835,7 +841,7 @@ fn parse_w_fd_path_e1( return; } - let abs = convert_absolute(ctxt, pid, path, Some(fd)); + let abs = convert_absolute(ctxt, pid_tgid, path, Some(fd)); let kind = if ret != 0 { AccessKind::Read @@ -849,7 +855,7 @@ fn parse_w_fd_path_e1( fn parse_renameat( ctxt: &mut Context, sets: &mut RWSet, - pid: u64, + pid_tgid: u64, ret: i64, syscall_nr: i64, flags: u32, @@ -858,8 +864,8 @@ fn parse_renameat( fd2: i32, path2: &str, ) { - let abs_path_1 = convert_absolute(ctxt, pid, path, Some(fd)); - let abs_path_2 = convert_absolute(ctxt, pid, path2, Some(fd2)); + let abs_path_1 = convert_absolute(ctxt, pid_tgid, path, Some(fd)); + let abs_path_2 = convert_absolute(ctxt, pid_tgid, path2, Some(fd2)); insert_with_ancestors(sets, abs_path_1, AccessKind::Write); insert_with_ancestors(sets, abs_path_2, AccessKind::Write); @@ -886,17 +892,17 @@ pub fn event_stream_handler(rx: mpsc::Receiver>) -> Result< loop { match rx.recv() { Ok(Some(SyscallEvent::Enter0(e))) => { - let pid = e.pid as u64; + let pid_tgid = e.pid_tgid as u64; let mut logs = LOGS.lock().unwrap(); - logs.update_log(pid, SyscallEvent::Enter0(e)) + logs.update_log(pid_tgid, SyscallEvent::Enter0(e)) } Ok(Some(SyscallEvent::Enter1(mut e))) => { - let pid = e.pid as u64; + let pid_tgid = e.pid_tgid as u64; { let ctxt = CTXT.lock().unwrap(); if libc::SYS_dup == e.syscall_nr { - let a = (e.pid & 0xFFFFFFFF) as i32; - if let Some(p) = ctxt.get_path_from_fd(a, e.fd) { + let pid = (e.pid_tgid & 0xFFFFFFFF) as i32; + if let Some(p) = ctxt.get_path_from_fd(pid, e.fd) { let path = p.to_str().unwrap().as_bytes(); let len = e.path.len().min(path.len()); e.path[..len].copy_from_slice(path); @@ -904,15 +910,15 @@ pub fn event_stream_handler(rx: mpsc::Receiver>) -> Result< } } let mut logs = LOGS.lock().unwrap(); - logs.update_log(pid, SyscallEvent::Enter1(e)) + logs.update_log(pid_tgid, SyscallEvent::Enter1(e)) } Ok(Some(SyscallEvent::Enter2(mut e))) => { - let pid = e.pid as u64; + let pid_tgid = e.pid_tgid as u64; { let ctxt = CTXT.lock().unwrap(); if libc::SYS_dup3 == e.syscall_nr { - let a = (e.pid & 0xFFFFFFFF) as i32; - if let Some(p) = ctxt.get_path_from_fd(a, e.fd) { + let pid = (e.pid_tgid & 0xFFFFFFFF) as i32; + if let Some(p) = ctxt.get_path_from_fd(pid, e.fd) { let path = p.to_str().unwrap().as_bytes(); let len = e.path.len().min(path.len()); e.path[..len].copy_from_slice(path); @@ -920,20 +926,20 @@ pub fn event_stream_handler(rx: mpsc::Receiver>) -> Result< } } let mut logs = LOGS.lock().unwrap(); - logs.update_log(pid, SyscallEvent::Enter2(e)) + logs.update_log(pid_tgid, SyscallEvent::Enter2(e)) } Ok(Some(SyscallEvent::Exit(exit_info))) => { - let pid = exit_info.pid as u64; + let pid_tgid = exit_info.pid_tgid as u64; let mut logs = LOGS.lock().unwrap(); - logs.update_log(pid, SyscallEvent::Exit(exit_info)); - let event_queue = logs.log.get(&pid).unwrap(); + logs.update_log(pid_tgid, SyscallEvent::Exit(exit_info)); + let event_queue = logs.log.get(&pid_tgid).unwrap(); let len = event_queue.len(); if len >= 2 { let enter_event = &event_queue[len - 2]; match enter_event { SyscallEvent::Enter0(e) => { on_event_update_rw_sets(SyscallInfo::Event0 { - pid: e.pid as u64, + pid_tgid: e.pid_tgid as u64, ret: exit_info.ret, syscall_nr: e.syscall_nr, flags: e.flags as u32, @@ -943,7 +949,7 @@ pub fn event_stream_handler(rx: mpsc::Receiver>) -> Result< let path_cstr = unsafe { CStr::from_ptr(e.path.as_ptr()) }; on_event_update_rw_sets(SyscallInfo::Event1 { - pid: e.pid as u64, + pid_tgid: e.pid_tgid as u64, ret: exit_info.ret, syscall_nr: e.syscall_nr, flags: e.flags as u32, @@ -956,7 +962,7 @@ pub fn event_stream_handler(rx: mpsc::Receiver>) -> Result< let path2_cstr = unsafe { CStr::from_ptr(e.path2.as_ptr()) }; on_event_update_rw_sets(SyscallInfo::Event2 { - pid: e.pid as u64, + pid_tgid: e.pid_tgid as u64, ret: exit_info.ret, syscall_nr: e.syscall_nr, flags: e.flags as u32, From 141521f39c97c8729c04f58c05a4215b692b5566 Mon Sep 17 00:00:00 2001 From: Dan Liu Date: Sun, 17 Aug 2025 09:09:58 -0400 Subject: [PATCH 5/7] minor cleanup for do clone and dump logs --- src/dep_tracer.rs | 14 +++----------- 1 file changed, 3 insertions(+), 11 deletions(-) diff --git a/src/dep_tracer.rs b/src/dep_tracer.rs index 6887503..abada87 100644 --- a/src/dep_tracer.rs +++ b/src/dep_tracer.rs @@ -175,7 +175,7 @@ impl Logs { .map(|(pid_tgid, logs)| (pid_tgid & 0xFFFFFFFF, pid_tgid >> 32, logs)) .collect(); - sorted_logs.sort_by(|(a, b, c), (d, e, f)| a.cmp(d)); + sorted_logs.sort_by(|(pid1, _, _), (pid2, _, _)| pid1.cmp(pid2)); for (pid, tgid, log) in sorted_logs { println!("log for pid {} tgid {}:", pid, tgid); @@ -237,27 +237,18 @@ impl Context { } pub fn do_clone(&mut self, parent_pid_tgid: u64, child_pid_tgid: u64) -> () { - // let parent_id = ((parent_pid_tgid >> 32) as i32); - // let child_id = ((child_pid_tgid >> 32) as i32); self.process_graph.insert(child_pid_tgid, parent_pid_tgid); let parent_cwd = self.cwd_map.get(&parent_pid_tgid).unwrap(); self.cwd_map.insert(child_pid_tgid, parent_cwd.clone()); let new_pid_fds: Vec<_> = self .openfds_map .iter() - .filter(|&((pid, fd), path)| { - if *pid == (parent_pid_tgid & 0xFFFFFFFF) as i32 { - true - } else { - false - } - }) + .filter(|((pid, _), _)| *pid == (parent_pid_tgid & 0xFFFFFFFF) as i32) .map(|(&key, path)| (key, path.clone())) .collect(); for ((_old_pid, fd), path) in new_pid_fds { self.map_fds((child_pid_tgid & 0xFFFFFFFF) as i32, fd, path.to_owned()) } - let c = &self.openfds_map; } pub fn map_fds(&mut self, pid: i32, fd: i32, path: PathBuf) { @@ -320,6 +311,7 @@ impl RWSet { pub static CTXT: Lazy> = Lazy::new(|| Mutex::new(Context::new())); pub static SETS: Lazy> = Lazy::new(|| Mutex::new(RWSet::new())); pub static LOGS: Lazy> = Lazy::new(|| Mutex::new(Logs::new())); + enum SyscallInfo { Event0 { pid_tgid: u64, From 117a5bf34d389263c4fea74b213f406c722ccf29 Mon Sep 17 00:00:00 2001 From: Divik Chotani Date: Tue, 19 Aug 2025 17:36:41 -0700 Subject: [PATCH 6/7] read the inode number of the pipe --- src/bpf/hs_trace.bpf.c | 25 ++++++++++++++++++++++++- src/dep_tracer.rs | 5 ++++- 2 files changed, 28 insertions(+), 2 deletions(-) diff --git a/src/bpf/hs_trace.bpf.c b/src/bpf/hs_trace.bpf.c index f5e97ba..866ff01 100644 --- a/src/bpf/hs_trace.bpf.c +++ b/src/bpf/hs_trace.bpf.c @@ -136,15 +136,38 @@ BPF_PROG(hs_trace_create_pipe_exit) enter2->syscall_nr = ((struct sys_exit_pipe2_args *)ctx)->id; enter2->flags = -1; bpf_map_delete_elem(&pipe_tracker, &pid); + + int fds[2]; bpf_probe_read_user(&fds, sizeof(fds), (void *)(*fds_pointers)); enter2->fd = fds[0]; enter2->fd2 = fds[1]; + bpf_rcu_read_lock(); + + struct task_struct *t = (void *)bpf_get_current_task_btf(); + struct files_struct *files = BPF_CORE_READ(t, files); + struct fdtable *fdtp = NULL; + + bpf_probe_read_kernel(&fdtp, sizeof(fdtp), &files->fdt); + + struct file **fd_array = NULL; + bpf_probe_read_kernel(&fd_array, sizeof(fd_array), &fdtp->fd); + + + int fd0 = fds[0]; + struct file *file0 = NULL; + bpf_probe_read_kernel(&file0, sizeof(file0), &fd_array[fd0]); + + + u64 ino = 0; + ino = BPF_CORE_READ(file0, f_inode, i_ino); + bpf_rcu_read_unlock(); + char *path2 = NULL; char pipe_str[32]; - BPF_SNPRINTF(enter2->path, sizeof(pipe_str), "/pipe%d", pid); + BPF_SNPRINTF(enter2->path, sizeof(pipe_str), "/pipe:[%d]", ino); bpf_probe_read_user_str(&enter2->path2, sizeof(enter2->path2), path2); diff --git a/src/dep_tracer.rs b/src/dep_tracer.rs index abada87..ee3013d 100644 --- a/src/dep_tracer.rs +++ b/src/dep_tracer.rs @@ -582,7 +582,10 @@ fn parse_pipe2( println!("{pid}"); ctxt.map_fds(pid, fd, path.clone()); - ctxt.map_fds(pid, fd2, path); + ctxt.map_fds(pid, fd2, path.clone()); + insert_with_ancestors(sets, path.clone(), AccessKind::Read); + insert_with_ancestors(sets, path, AccessKind::Write); + } fn parse_SYS_inotify_add_watch( From 4d035f6fe2523fdffcdbafdeef3f7c2f3c1e3e60 Mon Sep 17 00:00:00 2001 From: Divik Chotani Date: Tue, 19 Aug 2025 18:27:31 -0700 Subject: [PATCH 7/7] removed rcu lock function --- src/bpf/hs_trace.bpf.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/src/bpf/hs_trace.bpf.c b/src/bpf/hs_trace.bpf.c index 866ff01..5b9670f 100644 --- a/src/bpf/hs_trace.bpf.c +++ b/src/bpf/hs_trace.bpf.c @@ -144,7 +144,7 @@ BPF_PROG(hs_trace_create_pipe_exit) enter2->fd = fds[0]; enter2->fd2 = fds[1]; - bpf_rcu_read_lock(); + // bpf_rcu_read_lock(); struct task_struct *t = (void *)bpf_get_current_task_btf(); struct files_struct *files = BPF_CORE_READ(t, files); @@ -163,7 +163,7 @@ BPF_PROG(hs_trace_create_pipe_exit) u64 ino = 0; ino = BPF_CORE_READ(file0, f_inode, i_ino); - bpf_rcu_read_unlock(); + // bpf_rcu_read_unlock(); char *path2 = NULL; char pipe_str[32];