use nix::libc::{self, user_regs_struct};
use nix::unistd::Pid;
use crate::event::DecodedArg;
use crate::memory;
pub fn extract_syscall_entry(regs: &user_regs_struct) -> (u64, [u64; 6]) {
let number = regs.regs[8];
let args = [
regs.regs[0],
regs.regs[1],
regs.regs[2],
regs.regs[3],
regs.regs[4],
regs.regs[5],
];
(number, args)
}
pub fn extract_return_value(regs: &user_regs_struct) -> i64 {
regs.regs[0] as i64
}
pub fn syscall_name(number: u64) -> Option<&'static str> {
SYSCALL_NAMES.get(number as usize).copied().flatten()
}
pub fn decode_entry_args(pid: Pid, number: u64, args: &[u64; 6]) -> Vec<DecodedArg> {
match number {
17 => vec![DecodedArg::Addr(args[0]), DecodedArg::Size(args[1])],
23 => vec![DecodedArg::Fd(args[0] as i32)],
24 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Fd(args[1] as i32),
DecodedArg::Raw(args[2]),
],
25 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Int(args[1] as i64),
DecodedArg::Raw(args[2]),
],
29 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Raw(args[1]),
DecodedArg::Addr(args[2]),
],
48 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
decode_access_mode(args[2]),
],
49 => vec![read_path(pid, args[0])],
56 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
decode_open_flags(args[2]),
DecodedArg::Int(args[3] as i64),
],
57 => vec![DecodedArg::Fd(args[0] as i32)],
62 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Int(args[1] as i64),
decode_whence(args[2]),
],
63 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Addr(args[1]),
DecodedArg::Size(args[2]),
],
64 => {
let count = args[2] as usize;
let buf = read_buf(pid, args[1], count.min(32));
vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Buf(buf, count),
DecodedArg::Size(args[2]),
]
}
67 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Addr(args[1]),
DecodedArg::Size(args[2]),
DecodedArg::Int(args[3] as i64),
],
78 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Size(args[3]),
],
79 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Raw(args[3]),
],
80 => vec![DecodedArg::Fd(args[0] as i32), DecodedArg::Addr(args[1])],
93 => vec![DecodedArg::Int(args[0] as i64)],
94 => vec![DecodedArg::Int(args[0] as i64)],
96 => vec![DecodedArg::Addr(args[0])],
99 => vec![DecodedArg::Addr(args[0]), DecodedArg::Size(args[1])],
134 => vec![
DecodedArg::Int(args[0] as i64),
DecodedArg::Addr(args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Size(args[3]),
],
135 => vec![
DecodedArg::Int(args[0] as i64),
DecodedArg::Addr(args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Size(args[3]),
],
172 | 173 | 174 | 175 | 176 | 177 | 178 => vec![],
214 => vec![DecodedArg::Addr(args[0])],
215 => vec![DecodedArg::Addr(args[0]), DecodedArg::Size(args[1])],
221 => vec![
read_path(pid, args[0]),
DecodedArg::Addr(args[1]),
DecodedArg::Addr(args[2]),
],
222 => vec![
DecodedArg::Addr(args[0]),
DecodedArg::Size(args[1]),
decode_mmap_prot(args[2]),
decode_mmap_flags(args[3]),
DecodedArg::Fd(args[4] as i32),
DecodedArg::Int(args[5] as i64),
],
226 => vec![
DecodedArg::Addr(args[0]),
DecodedArg::Size(args[1]),
decode_mmap_prot(args[2]),
],
261 => vec![
DecodedArg::Int(args[0] as i64),
DecodedArg::Int(args[1] as i64),
DecodedArg::Addr(args[2]),
DecodedArg::Addr(args[3]),
],
278 => vec![
DecodedArg::Addr(args[0]),
DecodedArg::Size(args[1]),
DecodedArg::Raw(args[2]),
],
293 => vec![
DecodedArg::Addr(args[0]),
DecodedArg::Size(args[1]),
DecodedArg::Raw(args[2]),
DecodedArg::Raw(args[3]),
],
_ => args.iter().map(|&a| DecodedArg::Raw(a)).collect(),
}
}
pub fn decode_exit_args(
pid: Pid,
number: u64,
args: &[u64; 6],
ret: i64,
decoded: &mut Vec<DecodedArg>,
) {
match number {
63 if ret > 0 => {
let count = ret as usize;
let buf = read_buf(pid, args[1], count.min(32));
if decoded.len() > 1 {
decoded[1] = DecodedArg::Buf(buf, count);
}
}
_ => {}
}
}
fn read_path(pid: Pid, addr: u64) -> DecodedArg {
match memory::read_string(pid, addr, 256) {
Ok(s) => DecodedArg::Path(s),
Err(_) => DecodedArg::Addr(addr),
}
}
fn read_buf(pid: Pid, addr: u64, len: usize) -> Vec<u8> {
memory::read_bytes(pid, addr, len).unwrap_or_default()
}
fn decode_open_flags(flags: u64) -> DecodedArg {
let access = flags & 0o3;
let mut parts = vec![match access {
0 => "O_RDONLY",
1 => "O_WRONLY",
2 => "O_RDWR",
_ => "O_???",
}];
let bits: [(u64, &str); 14] = [
(libc::O_CREAT as u64, "O_CREAT"),
(libc::O_EXCL as u64, "O_EXCL"),
(libc::O_NOCTTY as u64, "O_NOCTTY"),
(libc::O_TRUNC as u64, "O_TRUNC"),
(libc::O_APPEND as u64, "O_APPEND"),
(libc::O_NONBLOCK as u64, "O_NONBLOCK"),
(libc::O_DSYNC as u64, "O_DSYNC"),
(libc::O_DIRECT as u64, "O_DIRECT"),
(libc::O_DIRECTORY as u64, "O_DIRECTORY"),
(libc::O_NOFOLLOW as u64, "O_NOFOLLOW"),
(libc::O_NOATIME as u64, "O_NOATIME"),
(libc::O_CLOEXEC as u64, "O_CLOEXEC"),
(libc::O_SYNC as u64, "O_SYNC"),
(libc::O_PATH as u64, "O_PATH"),
];
for (bit, name) in bits {
if bit != 0 && (flags & bit) == bit {
parts.push(name);
}
}
DecodedArg::Flags(parts.join("|"))
}
fn decode_mmap_prot(prot: u64) -> DecodedArg {
if prot == 0 {
return DecodedArg::Flags("PROT_NONE".to_string());
}
let mut parts = Vec::new();
if prot & libc::PROT_READ as u64 != 0 { parts.push("PROT_READ"); }
if prot & libc::PROT_WRITE as u64 != 0 { parts.push("PROT_WRITE"); }
if prot & libc::PROT_EXEC as u64 != 0 { parts.push("PROT_EXEC"); }
DecodedArg::Flags(parts.join("|"))
}
fn decode_mmap_flags(flags: u64) -> DecodedArg {
let mut parts = Vec::new();
if flags & libc::MAP_SHARED as u64 != 0 { parts.push("MAP_SHARED"); }
if flags & libc::MAP_PRIVATE as u64 != 0 { parts.push("MAP_PRIVATE"); }
if flags & libc::MAP_FIXED as u64 != 0 { parts.push("MAP_FIXED"); }
if flags & libc::MAP_ANONYMOUS as u64 != 0 { parts.push("MAP_ANONYMOUS"); }
if flags & libc::MAP_GROWSDOWN as u64 != 0 { parts.push("MAP_GROWSDOWN"); }
if flags & libc::MAP_DENYWRITE as u64 != 0 { parts.push("MAP_DENYWRITE"); }
if flags & libc::MAP_STACK as u64 != 0 { parts.push("MAP_STACK"); }
if parts.is_empty() {
DecodedArg::Raw(flags)
} else {
DecodedArg::Flags(parts.join("|"))
}
}
fn decode_access_mode(mode: u64) -> DecodedArg {
if mode == 0 {
return DecodedArg::Flags("F_OK".to_string());
}
let mut parts = Vec::new();
if mode & libc::R_OK as u64 != 0 { parts.push("R_OK"); }
if mode & libc::W_OK as u64 != 0 { parts.push("W_OK"); }
if mode & libc::X_OK as u64 != 0 { parts.push("X_OK"); }
DecodedArg::Flags(parts.join("|"))
}
fn decode_whence(whence: u64) -> DecodedArg {
DecodedArg::Flags(match whence as i32 {
libc::SEEK_SET => "SEEK_SET".to_string(),
libc::SEEK_CUR => "SEEK_CUR".to_string(),
libc::SEEK_END => "SEEK_END".to_string(),
_ => format!("{}", whence),
})
}
static SYSCALL_NAMES: &[Option<&str>] = &[
Some("io_setup"),
Some("io_destroy"),
Some("io_submit"),
Some("io_cancel"),
Some("io_getevents"),
Some("setxattr"),
Some("lsetxattr"),
Some("fsetxattr"),
Some("getxattr"),
Some("lgetxattr"),
Some("fgetxattr"),
Some("listxattr"),
Some("llistxattr"),
Some("flistxattr"),
Some("removexattr"),
Some("lremovexattr"),
Some("fremovexattr"),
Some("getcwd"),
Some("lookup_dcookie"),
Some("eventfd2"),
Some("epoll_create1"),
Some("epoll_ctl"),
Some("epoll_pwait"),
Some("dup"),
Some("dup3"),
Some("fcntl"),
Some("inotify_init1"),
Some("inotify_add_watch"),
Some("inotify_rm_watch"),
Some("ioctl"),
Some("ioprio_set"),
Some("ioprio_get"),
Some("flock"),
Some("mknodat"),
Some("mkdirat"),
Some("unlinkat"),
Some("symlinkat"),
Some("linkat"),
Some("renameat"),
Some("umount2"),
Some("mount"),
Some("pivot_root"),
Some("nfsservctl"),
Some("statfs"),
Some("fstatfs"),
Some("truncate"),
Some("ftruncate"),
Some("fallocate"),
Some("faccessat"),
Some("chdir"),
Some("fchdir"),
Some("chroot"),
Some("fchmod"),
Some("fchmodat"),
Some("fchownat"),
Some("fchown"),
Some("openat"),
Some("close"),
Some("vhangup"),
Some("pipe2"),
Some("quotactl"),
Some("getdents64"),
Some("lseek"),
Some("read"),
Some("write"),
Some("readv"),
Some("writev"),
Some("pread64"),
Some("pwrite64"),
Some("preadv"),
Some("pwritev"),
Some("sendfile"),
Some("pselect6"),
Some("ppoll"),
Some("signalfd4"),
Some("vmsplice"),
Some("splice"),
Some("tee"),
Some("readlinkat"),
Some("newfstatat"),
Some("fstat"),
Some("sync"),
Some("fsync"),
Some("fdatasync"),
Some("sync_file_range2"),
Some("timerfd_create"),
Some("timerfd_settime"),
Some("timerfd_gettime"),
Some("utimensat"),
Some("acct"),
Some("capget"),
Some("capset"),
Some("personality"),
Some("exit"),
Some("exit_group"),
Some("waitid"),
Some("set_tid_address"),
Some("unshare"),
Some("futex"),
Some("set_robust_list"),
Some("get_robust_list"),
Some("nanosleep"),
Some("getitimer"),
Some("setitimer"),
Some("kexec_load"),
Some("init_module"),
Some("delete_module"),
Some("timer_create"),
Some("timer_gettime"),
Some("timer_getoverrun"),
Some("timer_settime"),
Some("timer_delete"),
Some("clock_settime"),
Some("clock_gettime"),
Some("clock_getres"),
Some("clock_nanosleep"),
Some("syslog"),
Some("ptrace"),
Some("sched_setparam"),
Some("sched_setscheduler"),
Some("sched_getscheduler"),
Some("sched_getparam"),
Some("sched_setaffinity"),
Some("sched_getaffinity"),
Some("sched_yield"),
Some("sched_get_priority_max"),
Some("sched_get_priority_min"),
Some("sched_rr_get_interval"),
Some("restart_syscall"),
Some("kill"),
Some("tkill"),
Some("tgkill"),
Some("sigaltstack"),
Some("rt_sigsuspend"),
Some("rt_sigaction"),
Some("rt_sigprocmask"),
Some("rt_sigpending"),
Some("rt_sigtimedwait"),
Some("rt_sigqueueinfo"),
Some("rt_sigreturn"),
Some("setpriority"),
Some("getpriority"),
Some("reboot"),
Some("setregid"),
Some("setgid"),
Some("setreuid"),
Some("setuid"),
Some("setresuid"),
Some("getresuid"),
Some("setresgid"),
Some("getresgid"),
Some("setfsuid"),
Some("setfsgid"),
Some("times"),
Some("setpgid"),
Some("getpgid"),
Some("getsid"),
Some("setsid"),
Some("getgroups"),
Some("setgroups"),
Some("uname"),
Some("sethostname"),
Some("setdomainname"),
Some("getrlimit"),
Some("setrlimit"),
Some("getrusage"),
Some("umask"),
Some("prctl"),
Some("getcpu"),
Some("gettimeofday"),
Some("settimeofday"),
Some("adjtimex"),
Some("getpid"),
Some("getppid"),
Some("getuid"),
Some("geteuid"),
Some("getgid"),
Some("getegid"),
Some("gettid"),
Some("sysinfo"),
Some("mq_open"),
Some("mq_unlink"),
Some("mq_timedsend"),
Some("mq_timedreceive"),
Some("mq_notify"),
Some("mq_getsetattr"),
Some("msgget"),
Some("msgctl"),
Some("msgrcv"),
Some("msgsnd"),
Some("semget"),
Some("semctl"),
Some("semtimedop"),
Some("semop"),
Some("shmget"),
Some("shmctl"),
Some("shmat"),
Some("shmdt"),
Some("socket"),
Some("socketpair"),
Some("bind"),
Some("listen"),
Some("accept"),
Some("connect"),
Some("getsockname"),
Some("getpeername"),
Some("sendto"),
Some("recvfrom"),
Some("setsockopt"),
Some("getsockopt"),
Some("shutdown"),
Some("sendmsg"),
Some("recvmsg"),
Some("readahead"),
Some("brk"),
Some("munmap"),
Some("mremap"),
Some("add_key"),
Some("request_key"),
Some("keyctl"),
Some("clone"),
Some("execve"),
Some("mmap"),
Some("fadvise64"),
Some("swapon"),
Some("swapoff"),
Some("mprotect"),
Some("msync"),
Some("mlock"),
Some("munlock"),
Some("mlockall"),
Some("munlockall"),
Some("mincore"),
Some("madvise"),
Some("remap_file_pages"),
Some("mbind"),
Some("get_mempolicy"),
Some("set_mempolicy"),
Some("migrate_pages"),
Some("move_pages"),
Some("rt_tgsigqueueinfo"),
Some("perf_event_open"),
Some("accept4"),
Some("recvmmsg"),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
Some("wait4"),
Some("prlimit64"),
Some("fanotify_init"),
Some("fanotify_mark"),
Some("name_to_handle_at"),
Some("open_by_handle_at"),
Some("clock_adjtime"),
Some("syncfs"),
Some("setns"),
Some("sendmmsg"),
Some("process_vm_readv"),
Some("process_vm_writev"),
Some("kcmp"),
Some("finit_module"),
Some("sched_setattr"),
Some("sched_getattr"),
Some("renameat2"),
Some("seccomp"),
Some("getrandom"),
Some("memfd_create"),
Some("bpf"),
Some("execveat"),
Some("userfaultfd"),
Some("membarrier"),
Some("mlock2"),
Some("copy_file_range"),
Some("preadv2"),
Some("pwritev2"),
Some("pkey_mprotect"),
Some("pkey_alloc"),
Some("pkey_free"),
Some("statx"),
Some("io_pgetevents"),
Some("rseq"),
Some("kexec_file_load"),
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
None,
Some("clock_gettime64"),
Some("clock_settime64"),
Some("clock_adjtime64"),
Some("clock_getres_time64"),
Some("clock_nanosleep_time64"),
Some("timer_gettime64"),
Some("timer_settime64"),
Some("timerfd_gettime64"),
Some("timerfd_settime64"),
Some("utimensat_time64"),
Some("pselect6_time64"),
Some("ppoll_time64"),
None,
Some("io_pgetevents_time64"),
Some("recvmmsg_time64"),
Some("mq_timedsend_time64"),
Some("mq_timedreceive_time64"),
Some("semtimedop_time64"),
Some("rt_sigtimedwait_time64"),
Some("futex_time64"),
Some("sched_rr_get_interval_time64"),
Some("pidfd_send_signal"),
Some("io_uring_setup"),
Some("io_uring_enter"),
Some("io_uring_register"),
Some("open_tree"),
Some("move_mount"),
Some("fsopen"),
Some("fsconfig"),
Some("fsmount"),
Some("fspick"),
Some("pidfd_open"),
Some("clone3"),
Some("close_range"),
Some("openat2"),
Some("pidfd_getfd"),
Some("faccessat2"),
Some("process_madvise"),
Some("epoll_pwait2"),
Some("mount_setattr"),
Some("quotactl_fd"),
Some("landlock_create_ruleset"),
Some("landlock_add_rule"),
Some("landlock_restrict_self"),
Some("memfd_secret"),
Some("process_mrelease"),
Some("futex_waitv"),
Some("set_mempolicy_home_node"),
Some("cachestat"),
Some("fchmodat2"),
Some("map_shadow_stack"),
Some("futex_wake"),
Some("futex_wait"),
Some("futex_requeue"),
Some("statmount"),
Some("listmount"),
Some("lsm_get_self_attr"),
Some("lsm_set_self_attr"),
Some("lsm_list_modules"),
Some("mseal"),
Some("setxattrat"),
Some("getxattrat"),
Some("listxattrat"),
Some("removexattrat"),
Some("open_tree_attr"),
Some("file_getattr"),
Some("file_setattr"),
Some("listns"),
];