From 31ddd6c6e3a6481785f6990b6dff0a5bb2591ae4 Mon Sep 17 00:00:00 2001 From: sectordistrict <157201659+sectordistrict@users.noreply.github.com> Date: Sun, 1 Dec 2024 12:07:30 +0200 Subject: [PATCH] statx/sendmsg fixes --- src/one_line_formatter.rs | 80 +++++++++++++++++++-------------------- src/syscall_object.rs | 12 +++--- src/syscalls_map.rs | 3 +- 3 files changed, 46 insertions(+), 49 deletions(-) diff --git a/src/one_line_formatter.rs b/src/one_line_formatter.rs index 847f04b..bc35c01 100644 --- a/src/one_line_formatter.rs +++ b/src/one_line_formatter.rs @@ -18,7 +18,7 @@ use nix::{ errno::Errno, fcntl::{self, AtFlags, FallocateFlags}, libc::{ - cpu_set_t, pid_t, rlimit, timespec, timeval, AT_FDCWD, EPOLL_CLOEXEC, EPOLL_CTL_ADD, + msghdr, iovec, cpu_set_t, pid_t, rlimit, timespec, timeval, AT_FDCWD, EPOLL_CLOEXEC, EPOLL_CTL_ADD, EPOLL_CTL_DEL, EPOLL_CTL_MOD, FUTEX_CLOCK_REALTIME, FUTEX_CMP_REQUEUE, FUTEX_CMP_REQUEUE_PI, FUTEX_FD, FUTEX_LOCK_PI, FUTEX_LOCK_PI2, FUTEX_PRIVATE_FLAG, FUTEX_REQUEUE, FUTEX_TRYLOCK_PI, FUTEX_UNLOCK_PI, FUTEX_WAIT, FUTEX_WAIT_BITSET, @@ -35,7 +35,9 @@ use nix::{ MAP_SYNC, MCL_CURRENT, MCL_FUTURE, MCL_ONFAULT, O_APPEND, O_ASYNC, O_CLOEXEC, O_CREAT, O_DIRECT, O_DIRECTORY, O_DSYNC, O_EXCL, O_LARGEFILE, O_NDELAY, O_NOATIME, O_NOCTTY, O_NOFOLLOW, O_NONBLOCK, O_PATH, O_SYNC, O_TMPFILE, O_TRUNC, PRIO_PGRP, PRIO_PROCESS, - PRIO_USER, P_ALL, P_PGID, P_PID, P_PIDFD, AT_REMOVEDIR, RENAME_EXCHANGE, RENAME_NOREPLACE, RENAME_WHITEOUT + PRIO_USER, P_ALL, P_PGID, P_PID, P_PIDFD, AT_REMOVEDIR, RENAME_EXCHANGE, RENAME_NOREPLACE, + RENAME_WHITEOUT, AT_EMPTY_PATH, AT_NO_AUTOMOUNT, AT_SYMLINK_NOFOLLOW, AT_STATX_SYNC_AS_STAT, + AT_STATX_FORCE_SYNC, AT_STATX_DONT_SYNC }, sys::{ eventfd, @@ -491,54 +493,50 @@ impl SyscallObject { } Sysno::statx => { let dirfd = self.args[0] as i32; - let dirfd_parsed = self.pavfol(0); - let filename: String = self.pavfol(1); - let flags: rustix::fs::AtFlags = - unsafe { std::mem::transmute(self.args[2] as u32) }; - let statx_mask: rustix::fs::StatxFlags = - unsafe { std::mem::transmute(self.args[3] as u32) }; + let pathname: String = self.pavfol(1); + // let flags: rustix::fs::AtFlags = unsafe { std::mem::transmute(self.args[2] as i32) }; + let flags_num = self.args[2] as i32; match self.state { Entering => { - self.one_line.push("get the stats of the file: ".white()); - handle_path_file(filename, &mut self.one_line); - let mut flag_directive = vec![]; - if flags.contains(rustix::fs::AtFlags::SYMLINK_NOFOLLOW) { - flag_directive.push( - "operate on the symbolic link if found, do not recurse it".yellow(), - ); + self.one_line.push("get the stats of the file: ".white()); + + // statx logic for when the pathname is empty + if pathname.is_empty() && (flags_num & AT_EMPTY_PATH) > 0 { + // if pathname is empty and AT_EMPTY_PATH is given, dirfd is used + let dirfd_parsed = self.pavfol(0); + self.one_line.push(dirfd_parsed.yellow()); + } else { + handle_path_file(pathname, &mut self.one_line); } - if flags.contains(rustix::fs::AtFlags::EACCESS) { - flag_directive.push("check using effective user & group ids".yellow()); + + let mut flag_directive = vec![]; + if (flags_num & AT_NO_AUTOMOUNT) > 0 { + flag_directive.push("don't automount the basename of the path if its an automount directory".yellow()); } - if flags.contains(rustix::fs::AtFlags::SYMLINK_FOLLOW) { - flag_directive.push("recurse symbolic links if found".yellow()); + if (flags_num & AT_SYMLINK_NOFOLLOW) > 0 { + flag_directive.push("if the path is a symbolic link, get its stats, do not recurse it".yellow()); } - if flags.contains(rustix::fs::AtFlags::NO_AUTOMOUNT) { - flag_directive.push( - "don't automount the basename of the path if its an automount directory" - .yellow(), - ); + if (flags_num & AT_STATX_SYNC_AS_STAT) > 0 { + flag_directive.push("behave similar to the `stat` syscall".yellow()); } - if flags.contains(rustix::fs::AtFlags::EMPTY_PATH) { - flag_directive.push( - "operate on the anchor directory if pathname is empty".yellow(), - ); + if (flags_num & AT_STATX_FORCE_SYNC) > 0 { + flag_directive.push("force synchronization / guarantee up to date information".yellow()); } - if flag_directive.len() > 0 { - self.one_line.push(" (".white()); - let mut flag_directive_iter = flag_directive.into_iter().peekable(); - if flag_directive_iter.peek().is_some() { - self.one_line.push(flag_directive_iter.next().unwrap()); - } - for entry in flag_directive_iter { - self.one_line.push(", ".white()); - self.one_line.push(entry); - } - self.one_line.push(")".white()); + if (flags_num & AT_STATX_DONT_SYNC) > 0 { + flag_directive.push("don't force synchronization / retrieve whatever information is cached".yellow()); } + // if flags.contains(rustix::fs::AtFlags::EACCESS) { + // flag_directive.push("check using effective user & group ids".yellow()); + // } + // if flags.contains(rustix::fs::AtFlags::SYMLINK_FOLLOW) { + // flag_directive.push("recurse symbolic links if found".yellow()); + // } + directives_handler(flag_directive, &mut self.one_line); + // TODO! - // println!("{:?}", statx_mask); + // unnecessary information + // statx_mask is currently unhandled because it's unnecessary information } Exiting => { let eph_return = self.get_syscall_return(); @@ -4831,7 +4829,7 @@ impl SyscallObject { Entering => { if (futex_ops_num & FUTEX_WAIT) == FUTEX_WAIT { self.one_line.push( - "if comparison succeeds block and wait for FUTEX_WAKE".yellow(), + "block and wait for FUTEX_WAKE if comparison succeeds".yellow(), ); } else if (futex_ops_num & FUTEX_WAKE) == FUTEX_WAKE { self.one_line.push("wake a maximum of ".white()); diff --git a/src/syscall_object.rs b/src/syscall_object.rs index 770b8e6..6f9bb50 100644 --- a/src/syscall_object.rs +++ b/src/syscall_object.rs @@ -14,8 +14,7 @@ use nix::{ errno::Errno, fcntl::{self, AtFlags, FallocateFlags, OFlag, RenameFlags}, libc::{ - cpu_set_t, user_regs_struct, AT_FDCWD, CPU_ISSET, CPU_SETSIZE, MAP_FAILED, PRIO_PGRP, - PRIO_PROCESS, PRIO_USER, + cpu_set_t, iovec, msghdr, sockaddr, user_regs_struct, AT_FDCWD, CPU_ISSET, CPU_SETSIZE, MAP_FAILED, PRIO_PGRP, PRIO_PROCESS, PRIO_USER }, sys::{ eventfd, @@ -969,7 +968,6 @@ impl SyscallObject { if self.sysno == Sysno::execve { continue; } - // p!(self.sysno.name()); let array_of_texts = SyscallObject::string_from_array_of_strings( self.args[index], self.child, @@ -1035,9 +1033,7 @@ impl SyscallObject { Sysno::from(orig_rax) } pub(crate) fn build(registers: &user_regs_struct, child: Pid) -> Self { - // println!("{:?}", registers.orig_rax as i32); let sysno = Sysno::from(registers.orig_rax as i32); - // println!("{}", sysno); let syscall = match SYSCALL_MAP.get(&sysno) { Some(( category, @@ -1392,8 +1388,10 @@ impl SyscallObject { // Use process_vm_readv(2) fn string_from_pointer(address: u64, child: Pid) -> String { // TODO! execve multi-threaded fails here for some reason - let data = SyscallObject::read_bytes_until_null(address as usize, child).unwrap(); - String::from_utf8_lossy(&data).into_owned() + match SyscallObject::read_bytes_until_null(address as usize, child) { + Some(data) => String::from_utf8_lossy(&data).into_owned(), + None => "".to_owned() + } } fn string_from_array_of_strings(address: u64, child: Pid) -> Vec { // TODO! execve fails this diff --git a/src/syscalls_map.rs b/src/syscalls_map.rs index 17c48a1..8860e5a 100644 --- a/src/syscalls_map.rs +++ b/src/syscalls_map.rs @@ -1531,7 +1531,8 @@ pub fn initialize_syscall_map() -> HashMap { "send a message to another socket", &[ (["sockfd", "file descriptor of the sending socket"], Normal(File_Descriptor(""))), - (["buf", "pointer to a buffer containing the message to be sent and the length of the message"], Normal(Pointer_To_Struct)), + (["buf", "pointer to a buffer containing the message to be sent and the length of the message"], Normal(Pointer_To_Text(""))), + (["len", "size of the message buffer in bytes"], Normal(Length_Of_Bytes_Specific)), (["flags", "flags to customize syscall behaviour"], Normal(General_Flag(SocketMessageFlag))), // WILL BE USED if connection-less (like UDP) // WILL BE IGNORED if connection-mode (like TCP, or SEQ) and must be null or 0