use nix::libc::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.orig_rax;
let args = [regs.rdi, regs.rsi, regs.rdx, regs.r10, regs.r8, regs.r9];
(number, args)
}
pub fn extract_return_value(regs: &user_regs_struct) -> i64 {
regs.rax 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 {
0 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Addr(args[1]), DecodedArg::Size(args[2]),
],
1 => {
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]),
]
}
2 => vec![
read_path(pid, args[0]),
decode_open_flags(args[1]),
DecodedArg::Int(args[2] as i64),
],
3 => vec![DecodedArg::Fd(args[0] as i32)],
4 => vec![read_path(pid, args[0]), DecodedArg::Addr(args[1])],
5 => vec![DecodedArg::Fd(args[0] as i32), DecodedArg::Addr(args[1])],
6 => vec![read_path(pid, args[0]), DecodedArg::Addr(args[1])],
8 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Int(args[1] as i64),
decode_whence(args[2]),
],
9 => 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),
],
10 => vec![
DecodedArg::Addr(args[0]),
DecodedArg::Size(args[1]),
decode_mmap_prot(args[2]),
],
11 => vec![DecodedArg::Addr(args[0]), DecodedArg::Size(args[1])],
12 => vec![DecodedArg::Addr(args[0])],
13 => vec![
DecodedArg::Int(args[0] as i64),
DecodedArg::Addr(args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Size(args[3]),
],
14 => vec![
DecodedArg::Int(args[0] as i64),
DecodedArg::Addr(args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Size(args[3]),
],
16 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Raw(args[1]),
DecodedArg::Addr(args[2]),
],
17 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Addr(args[1]),
DecodedArg::Size(args[2]),
DecodedArg::Int(args[3] as i64),
],
21 => vec![read_path(pid, args[0]), decode_access_mode(args[1])],
32 => vec![DecodedArg::Fd(args[0] as i32)],
33 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Fd(args[1] as i32),
],
59 => vec![
read_path(pid, args[0]),
DecodedArg::Addr(args[1]),
DecodedArg::Addr(args[2]),
],
60 => vec![DecodedArg::Int(args[0] as i64)],
72 => vec![
DecodedArg::Fd(args[0] as i32),
DecodedArg::Int(args[1] as i64),
DecodedArg::Raw(args[2]),
],
79 => vec![DecodedArg::Addr(args[0]), DecodedArg::Size(args[1])],
80 => vec![read_path(pid, args[0])],
83 => vec![read_path(pid, args[0]), DecodedArg::Int(args[1] as i64)],
87 => vec![read_path(pid, args[0])],
89 => vec![
read_path(pid, args[0]),
DecodedArg::Addr(args[1]),
DecodedArg::Size(args[2]),
],
39 | 102 | 104 | 107 | 108 | 110 | 186 => vec![],
158 => vec![
decode_arch_prctl_code(args[0]),
DecodedArg::Addr(args[1]),
],
218 => vec![DecodedArg::Addr(args[0])],
231 => vec![DecodedArg::Int(args[0] as i64)],
257 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
decode_open_flags(args[2]),
DecodedArg::Int(args[3] as i64),
],
262 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Raw(args[3]),
],
267 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
DecodedArg::Addr(args[2]),
DecodedArg::Size(args[3]),
],
269 => vec![
DecodedArg::Fd(args[0] as i32),
read_path(pid, args[1]),
decode_access_mode(args[2]),
],
273 => vec![DecodedArg::Addr(args[0]), DecodedArg::Size(args[1])],
302 => vec![
DecodedArg::Int(args[0] as i64),
DecodedArg::Int(args[1] as i64),
DecodedArg::Addr(args[2]),
DecodedArg::Addr(args[3]),
],
318 => vec![
DecodedArg::Addr(args[0]),
DecodedArg::Size(args[1]),
DecodedArg::Raw(args[2]),
],
334 => 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 {
0 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_???",
}];
static FLAG_BITS: &[(u64, &str)] = &[
(0o0100, "O_CREAT"),
(0o0200, "O_EXCL"),
(0o0400, "O_NOCTTY"),
(0o01000, "O_TRUNC"),
(0o02000, "O_APPEND"),
(0o04000, "O_NONBLOCK"),
(0o010000, "O_DSYNC"),
(0o020000, "O_ASYNC"),
(0o040000, "O_DIRECT"),
(0o0100000, "O_LARGEFILE"),
(0o0200000, "O_DIRECTORY"),
(0o0400000, "O_NOFOLLOW"),
(0o01000000, "O_NOATIME"),
(0o02000000, "O_CLOEXEC"),
(0o04010000, "O_SYNC"),
(0o010000000, "O_PATH"),
(0o020000000, "O_TMPFILE"),
];
for &(bit, name) in FLAG_BITS {
if flags & bit == bit && bit != 0 {
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 & 0x1 != 0 { parts.push("PROT_READ"); }
if prot & 0x2 != 0 { parts.push("PROT_WRITE"); }
if prot & 0x4 != 0 { parts.push("PROT_EXEC"); }
DecodedArg::Flags(parts.join("|"))
}
fn decode_mmap_flags(flags: u64) -> DecodedArg {
let mut parts = Vec::new();
if flags & 0x01 != 0 { parts.push("MAP_SHARED"); }
if flags & 0x02 != 0 { parts.push("MAP_PRIVATE"); }
if flags & 0x10 != 0 { parts.push("MAP_FIXED"); }
if flags & 0x20 != 0 { parts.push("MAP_ANONYMOUS"); }
if flags & 0x100 != 0 { parts.push("MAP_GROWSDOWN"); }
if flags & 0x0800 != 0 { parts.push("MAP_DENYWRITE"); }
if flags & 0x40000 != 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 & 0x4 != 0 { parts.push("R_OK"); }
if mode & 0x2 != 0 { parts.push("W_OK"); }
if mode & 0x1 != 0 { parts.push("X_OK"); }
DecodedArg::Flags(parts.join("|"))
}
fn decode_whence(whence: u64) -> DecodedArg {
DecodedArg::Flags(match whence {
0 => "SEEK_SET".to_string(),
1 => "SEEK_CUR".to_string(),
2 => "SEEK_END".to_string(),
_ => format!("{}", whence),
})
}
fn decode_arch_prctl_code(code: u64) -> DecodedArg {
DecodedArg::Flags(match code {
0x1001 => "ARCH_SET_GS".to_string(),
0x1002 => "ARCH_SET_FS".to_string(),
0x1003 => "ARCH_GET_FS".to_string(),
0x1004 => "ARCH_GET_GS".to_string(),
_ => format!("{:#x}", code),
})
}
static SYSCALL_NAMES: &[Option<&str>] = &[
Some("read"),
Some("write"),
Some("open"),
Some("close"),
Some("stat"),
Some("fstat"),
Some("lstat"),
Some("poll"),
Some("lseek"),
Some("mmap"),
Some("mprotect"),
Some("munmap"),
Some("brk"),
Some("rt_sigaction"),
Some("rt_sigprocmask"),
Some("rt_sigreturn"),
Some("ioctl"),
Some("pread64"),
Some("pwrite64"),
Some("readv"),
Some("writev"),
Some("access"),
Some("pipe"),
Some("select"),
Some("sched_yield"),
Some("mremap"),
Some("msync"),
Some("mincore"),
Some("madvise"),
Some("shmget"),
Some("shmat"),
Some("shmctl"),
Some("dup"),
Some("dup2"),
Some("pause"),
Some("nanosleep"),
Some("getitimer"),
Some("alarm"),
Some("setitimer"),
Some("getpid"),
Some("sendfile"),
Some("socket"),
Some("connect"),
Some("accept"),
Some("sendto"),
Some("recvfrom"),
Some("sendmsg"),
Some("recvmsg"),
Some("shutdown"),
Some("bind"),
Some("listen"),
Some("getsockname"),
Some("getpeername"),
Some("socketpair"),
Some("setsockopt"),
Some("getsockopt"),
Some("clone"),
Some("fork"),
Some("vfork"),
Some("execve"),
Some("exit"),
Some("wait4"),
Some("kill"),
Some("uname"),
Some("semget"),
Some("semop"),
Some("semctl"),
Some("shmdt"),
Some("msgget"),
Some("msgsnd"),
Some("msgrcv"),
Some("msgctl"),
Some("fcntl"),
Some("flock"),
Some("fsync"),
Some("fdatasync"),
Some("truncate"),
Some("ftruncate"),
Some("getdents"),
Some("getcwd"),
Some("chdir"),
Some("fchdir"),
Some("rename"),
Some("mkdir"),
Some("rmdir"),
Some("creat"),
Some("link"),
Some("unlink"),
Some("symlink"),
Some("readlink"),
Some("chmod"),
Some("fchmod"),
Some("chown"),
Some("fchown"),
Some("lchown"),
Some("umask"),
Some("gettimeofday"),
Some("getrlimit"),
Some("getrusage"),
Some("sysinfo"),
Some("times"),
Some("ptrace"),
Some("getuid"),
Some("syslog"),
Some("getgid"),
Some("setuid"),
Some("setgid"),
Some("geteuid"),
Some("getegid"),
Some("setpgid"),
Some("getppid"),
Some("getpgrp"),
Some("setsid"),
Some("setreuid"),
Some("setregid"),
Some("getgroups"),
Some("setgroups"),
Some("setresuid"),
Some("getresuid"),
Some("setresgid"),
Some("getresgid"),
Some("getpgid"),
Some("setfsuid"),
Some("setfsgid"),
Some("getsid"),
Some("capget"),
Some("capset"),
Some("rt_sigpending"),
Some("rt_sigtimedwait"),
Some("rt_sigqueueinfo"),
Some("rt_sigsuspend"),
Some("sigaltstack"),
Some("utime"),
Some("mknod"),
Some("uselib"),
Some("personality"),
Some("ustat"),
Some("statfs"),
Some("fstatfs"),
Some("sysfs"),
Some("getpriority"),
Some("setpriority"),
Some("sched_setparam"),
Some("sched_getparam"),
Some("sched_setscheduler"),
Some("sched_getscheduler"),
Some("sched_get_priority_max"),
Some("sched_get_priority_min"),
Some("sched_rr_get_interval"),
Some("mlock"),
Some("munlock"),
Some("mlockall"),
Some("munlockall"),
Some("vhangup"),
Some("modify_ldt"),
Some("pivot_root"),
Some("_sysctl"),
Some("prctl"),
Some("arch_prctl"),
Some("adjtimex"),
Some("setrlimit"),
Some("chroot"),
Some("sync"),
Some("acct"),
Some("settimeofday"),
Some("mount"),
Some("umount2"),
Some("swapon"),
Some("swapoff"),
Some("reboot"),
Some("sethostname"),
Some("setdomainname"),
Some("iopl"),
Some("ioperm"),
Some("create_module"),
Some("init_module"),
Some("delete_module"),
Some("get_kernel_syms"),
Some("query_module"),
Some("quotactl"),
Some("nfsservctl"),
Some("getpmsg"),
Some("putpmsg"),
Some("afs_syscall"),
Some("tuxcall"),
Some("security"),
Some("gettid"),
Some("readahead"),
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("tkill"),
Some("time"),
Some("futex"),
Some("sched_setaffinity"),
Some("sched_getaffinity"),
Some("set_thread_area"),
Some("io_setup"),
Some("io_destroy"),
Some("io_getevents"),
Some("io_submit"),
Some("io_cancel"),
Some("get_thread_area"),
Some("lookup_dcookie"),
Some("epoll_create"),
Some("epoll_ctl_old"),
Some("epoll_wait_old"),
Some("remap_file_pages"),
Some("getdents64"),
Some("set_tid_address"),
Some("restart_syscall"),
Some("semtimedop"),
Some("fadvise64"),
Some("timer_create"),
Some("timer_settime"),
Some("timer_gettime"),
Some("timer_getoverrun"),
Some("timer_delete"),
Some("clock_settime"),
Some("clock_gettime"),
Some("clock_getres"),
Some("clock_nanosleep"),
Some("exit_group"),
Some("epoll_wait"),
Some("epoll_ctl"),
Some("tgkill"),
Some("utimes"),
Some("vserver"),
Some("mbind"),
Some("set_mempolicy"),
Some("get_mempolicy"),
Some("mq_open"),
Some("mq_unlink"),
Some("mq_timedsend"),
Some("mq_timedreceive"),
Some("mq_notify"),
Some("mq_getsetattr"),
Some("kexec_load"),
Some("waitid"),
Some("add_key"),
Some("request_key"),
Some("keyctl"),
Some("ioprio_set"),
Some("ioprio_get"),
Some("inotify_init"),
Some("inotify_add_watch"),
Some("inotify_rm_watch"),
Some("migrate_pages"),
Some("openat"),
Some("mkdirat"),
Some("mknodat"),
Some("fchownat"),
Some("futimesat"),
Some("newfstatat"),
Some("unlinkat"),
Some("renameat"),
Some("linkat"),
Some("symlinkat"),
Some("readlinkat"),
Some("fchmodat"),
Some("faccessat"),
Some("pselect6"),
Some("ppoll"),
Some("unshare"),
Some("set_robust_list"),
Some("get_robust_list"),
Some("splice"),
Some("tee"),
Some("sync_file_range"),
Some("vmsplice"),
Some("move_pages"),
Some("utimensat"),
Some("epoll_pwait"),
Some("signalfd"),
Some("timerfd_create"),
Some("eventfd"),
Some("fallocate"),
Some("timerfd_settime"),
Some("timerfd_gettime"),
Some("accept4"),
Some("signalfd4"),
Some("eventfd2"),
Some("epoll_create1"),
Some("dup3"),
Some("pipe2"),
Some("inotify_init1"),
Some("preadv"),
Some("pwritev"),
Some("rt_tgsigqueueinfo"),
Some("perf_event_open"),
Some("recvmmsg"),
Some("fanotify_init"),
Some("fanotify_mark"),
Some("prlimit64"),
Some("name_to_handle_at"),
Some("open_by_handle_at"),
Some("clock_adjtime"),
Some("syncfs"),
Some("sendmmsg"),
Some("setns"),
Some("getcpu"),
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("kexec_file_load"),
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"),
];