diff --git a/Cargo.toml b/Cargo.toml index 4dcc8a1..2510f9c 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -17,7 +17,7 @@ default = [] all = [ # "aarch64", "arm", "mips", "mips64", "powerpc", "powerpc64", "s390x", # "sparc", "sparc64", "x86", - "x86_64" + "x86_64", "riscv64" ] # Enable syscall tables for individual architectures. @@ -32,6 +32,7 @@ all = [ #sparc64 = [] #x86 = [] x86_64 = [] +riscv64 = [] [dependencies] anyhow = "1" diff --git a/src/arch/mod.rs b/src/arch/mod.rs index c380451..0e5c275 100644 --- a/src/arch/mod.rs +++ b/src/arch/mod.rs @@ -19,6 +19,8 @@ use syscalls::Sysno; // pub mod powerpc; // #[cfg(any(target_arch = "powerpc64", feature = "powerpc64"))] // pub mod powerpc64; +#[cfg(any(target_arch = "riscv64", feature = "riscv64"))] +pub mod riscv64; // #[cfg(any(target_arch = "s390x", feature = "s390x"))] // pub mod s390x; // #[cfg(any(target_arch = "sparc", feature = "sparc"))] @@ -42,6 +44,8 @@ pub mod x86_64; // pub use powerpc::*; // #[cfg(target_arch = "powerpc64")] // pub use powerpc64::*; +#[cfg(target_arch = "riscv64")] +pub use riscv64::*; // #[cfg(target_arch = "s390x")] // pub use s390x::*; // #[cfg(target_arch = "sparc")] @@ -139,7 +143,10 @@ fn map_arg(pid: Pid, registers: user_regs_struct, idx: usize, arg: SyscallArgTyp let value = get_arg_value(registers, idx); // The return value of a system call for functions like read or write represents the number of bytes that were successfully processed. // which will stores in rax + #[cfg(target_arch = "x86_64")] let length = registers.rax as usize; + #[cfg(target_arch = "riscv64")] + let length = registers.a7 as usize; match arg { SyscallArgType::Int => SyscallArg::Int(value as i64), SyscallArgType::Bytes => SyscallArg::Bytes(read_bytes(pid, value, length)), diff --git a/src/arch/riscv64.rs b/src/arch/riscv64.rs new file mode 100644 index 0000000..37085a5 --- /dev/null +++ b/src/arch/riscv64.rs @@ -0,0 +1,772 @@ +use crate::arch::SyscallArgType; +use libc::{c_ulonglong, user_regs_struct}; +use std::ops::Index; +use syscalls::riscv64::Sysno; +use syscalls::SysnoSet; + +#[allow(clippy::enum_glob_use)] +use syscalls::riscv64::Sysno::*; + +pub static TRACE_DESC: SysnoSet = SysnoSet::new(&[ + // strace/src/linux/64/syscallent.h + fsetxattr, + fgetxattr, + flistxattr, + fremovexattr, + eventfd2, + epoll_create1, + epoll_ctl, + epoll_pwait, + dup, + dup3, + fcntl, + inotify_init1, + inotify_add_watch, + inotify_rm_watch, + ioctl, + flock, + mknodat, + mkdirat, + unlinkat, + symlinkat, + linkat, + renameat, + fstatfs, + ftruncate, + fallocate, + faccessat, + fchdir, + fchmod, + fchmodat, + fchownat, + fchown, + openat, + close, + pipe2, + getdents64, + lseek, + read, + write, + readv, + writev, + pread64, + pwrite64, + preadv, + pwritev, + sendfile, + pselect6, + ppoll, + signalfd4, + vmsplice, + splice, + tee, + readlinkat, + fstatat, + fstat, + fsync, + fdatasync, + sync_file_range2, + timerfd_create, + timerfd_settime, + timerfd_gettime, + utimensat, + mq_open, + mq_timedsend, + mq_timedreceive, + mq_notify, + mq_getsetattr, + readahead, + mmap, + fadvise64, + perf_event_open, + fanotify_init, + fanotify_mark, + name_to_handle_at, + open_by_handle_at, + syncfs, + setns, + finit_module, + renameat2, + memfd_create, + bpf, + execveat, + userfaultfd, + copy_file_range, + preadv2, + pwritev2, + statx, + kexec_file_load, + // strace/src/linux/generic/syscallent-common.h + pidfd_send_signal, + io_uring_setup, + io_uring_enter, + io_uring_register, + open_tree, + move_mount, + fsopen, + fsconfig, + fsmount, + fspick, + pidfd_open, + openat2, + pidfd_getfd, + faccessat2, + process_madvise, + epoll_pwait2, + mount_setattr, + quotactl_fd, + landlock_create_ruleset, + landlock_add_rule, + landlock_restrict_self, + memfd_secret, + process_mrelease, +]); + +pub static TRACE_FILE: SysnoSet = SysnoSet::new(&[ + // strace/src/linux/64/syscallent.h + setxattr, + lsetxattr, + getxattr, + lgetxattr, + listxattr, + llistxattr, + removexattr, + lremovexattr, + getcwd, + inotify_add_watch, + mknodat, + mkdirat, + unlinkat, + symlinkat, + linkat, + renameat, + umount2, + mount, + pivot_root, + statfs, + fstatfs, + truncate, + faccessat, + chdir, + chroot, + fchmodat, + fchownat, + openat, + quotactl, + readlinkat, + fstatat, + fstat, + utimensat, + acct, + execve, + swapon, + swapoff, + fanotify_mark, + name_to_handle_at, + renameat2, + execveat, + statx, + // strace/src/linux/generic/syscallent-common.h + open_tree, + move_mount, + fsconfig, + fspick, + openat2, + faccessat2, + mount_setattr, +]); + +pub static TRACE_IPC: SysnoSet = SysnoSet::new(&[ + msgget, msgctl, msgrcv, msgsnd, semget, semctl, semtimedop, semop, shmget, shmctl, shmat, shmdt, +]); + +pub static TRACE_NETWORK: SysnoSet = SysnoSet::new(&[ + sendfile, + socket, + socketpair, + bind, + listen, + accept, + connect, + getsockname, + getpeername, + sendto, + recvfrom, + setsockopt, + getsockopt, + shutdown, + sendmsg, + recvmsg, + accept4, + recvmmsg, + sendmmsg, +]); + +pub static TRACE_PROCESS: SysnoSet = SysnoSet::new(&[ + // strace/src/linux/64/syscallent.h + exit, + exit_group, + waitid, + kill, + tkill, + tgkill, + rt_sigqueueinfo, + clone, + execve, + rt_tgsigqueueinfo, + wait4, + execveat, + // strace/src/linux/generic/syscallent-common.h + pidfd_send_signal, + clone3, +]); + +pub static TRACE_SIGNAL: SysnoSet = SysnoSet::new(&[ + // strace/src/linux/64/syscallent.h + statfs, + fstatfs, + signalfd4, + fstatat, + fstat, + kill, + tkill, + tgkill, + sigaltstack, + rt_sigsuspend, + rt_sigaction, + rt_sigprocmask, + rt_sigpending, + rt_sigtimedwait, + rt_sigqueueinfo, + rt_sigreturn, + execve, + rt_tgsigqueueinfo, + execveat, + statx, + // strace/src/linux/generic/syscallent-common.h + pidfd_send_signal, + io_uring_enter, +]); + +pub static TRACE_MEMORY: SysnoSet = SysnoSet::new(&[ + // strace/src/linux/64/syscallent.h + io_setup, + io_destroy, + shmat, + shmdt, + brk, + munmap, + mremap, + mmap, + mprotect, + msync, + mlock, + munlock, + mlockall, + munlockall, + mincore, + madvise, + remap_file_pages, + mbind, + get_mempolicy, + set_mempolicy, + migrate_pages, + move_pages, + mlock2, + pkey_mprotect, + // strace/src/linux/generic/syscallent-common.h + io_uring_register, + set_mempolicy_home_node, + // strace/src/linux/riscv64/syscallent.h + // riscv_flush_icache, +]); + +pub static TRACE_STAT: SysnoSet = SysnoSet::new(&[fstatat, fstat, statx]); +pub static TRACE_LSTAT: SysnoSet = SysnoSet::new(&[]); +pub static TRACE_FSTAT: SysnoSet = SysnoSet::new(&[fstatat, fstat, statx]); +pub static TRACE_STAT_LIKE: SysnoSet = SysnoSet::new(&[fstatat, fstat, statx]); +pub static TRACE_STATFS: SysnoSet = SysnoSet::new(&[statfs, fstatfs]); +pub static TRACE_FSTATFS: SysnoSet = SysnoSet::new(&[fstatfs]); +pub static TRACE_STATFS_LIKE: SysnoSet = SysnoSet::new(&[statfs, fstatfs]); + +pub static TRACE_PURE: SysnoSet = + SysnoSet::new(&[getpid, getppid, getuid, geteuid, getgid, getegid, gettid]); + +pub static TRACE_CREDS: SysnoSet = SysnoSet::new(&[ + capget, + capset, + clock_settime, + clock_gettime, + clock_getres, + setregid, + setgid, + setreuid, + setuid, + setresuid, + getresuid, + setresgid, + getresgid, + setfsuid, + setfsgid, + getgroups, + setgroups, + prctl, + gettimeofday, + settimeofday, + adjtimex, + getuid, + geteuid, + getgid, + getegid, + clock_adjtime, +]); + +pub static TRACE_CLOCK: SysnoSet = SysnoSet::new(&[ + clock_settime, + clock_gettime, + clock_getres, + gettimeofday, + settimeofday, + adjtimex, + clock_adjtime, +]); + +macro_rules! syscall { + ($name:ident $(,)?) => { + Some((Sysno::$name, [None, None, None, None, None, None])) + }; + ($name:ident, $arg0:ident $(,)?) => { + Some((Sysno::$name, [$arg0, None, None, None, None, None])) + }; + ($name:ident, $arg0:ident, $arg1:ident $(,)?) => { + Some((Sysno::$name, [$arg0, $arg1, None, None, None, None])) + }; + ($name:ident, $arg0:ident, $arg1:ident, $arg2:ident $(,)?) => { + Some((Sysno::$name, [$arg0, $arg1, $arg2, None, None, None])) + }; + ($name:ident, $arg0:ident, $arg1:ident, $arg2:ident, $arg3:ident $(,)?) => { + Some((Sysno::$name, [$arg0, $arg1, $arg2, $arg3, None, None])) + }; + ($name:ident, $arg0:ident, $arg1:ident, $arg2:ident, $arg3:ident, $arg4:ident $(,)?) => { + Some((Sysno::$name, [$arg0, $arg1, $arg2, $arg3, $arg4, None])) + }; + ($name:ident, $arg0:ident, $arg1:ident, $arg2:ident, $arg3:ident, $arg4:ident, $arg5:ident $(,)?) => { + Some((Sysno::$name, [$arg0, $arg1, $arg2, $arg3, $arg4, $arg5])) + }; +} + +const ADDR: Option = Some(SyscallArgType::Addr); +const INT: Option = Some(SyscallArgType::Int); +const STR: Option = Some(SyscallArgType::Bytes); + +pub struct Riscv64Syscalls { + _0: [Option<(Sysno, [Option; 6])>; 244], + _258: [Option<(Sysno, [Option; 6])>; 37], + _403: [Option<(Sysno, [Option; 6])>; 12], + _416: [Option<(Sysno, [Option; 6])>; 36], +} + +impl Riscv64Syscalls { + pub fn get(&self, index: usize) -> Option<&Option<(Sysno, [Option; 6])>> { + let result = match index { + 0..=243 => &self._0[index], + 260..=294 => &self._258[index - 258], + 403..=414 => &self._403[index - 403], + 416..=451 => &self._416[index - 416], + _ => return None, + }; + Some(result) + } +} + +impl Index for Riscv64Syscalls { + type Output = Option<(Sysno, [Option; 6])>; + + fn index(&self, index: usize) -> &Self::Output { + self.get(index).expect("unimplemented syscall") + } +} + +pub static SYSCALLS: Riscv64Syscalls = Riscv64Syscalls { + _0: [ + syscall!(io_setup, INT, ADDR), + syscall!(io_destroy, INT), + syscall!(io_submit, INT, INT, ADDR), + syscall!(io_cancel, INT, ADDR, ADDR), + syscall!(io_getevents, INT, INT, INT, ADDR, ADDR), + syscall!(setxattr, STR, STR, ADDR, INT, INT), + syscall!(lsetxattr, STR, STR, ADDR, INT, INT), + syscall!(fsetxattr, INT, STR, ADDR, INT, INT), + syscall!(getxattr, STR, STR, ADDR, INT), + syscall!(lgetxattr, STR, STR, ADDR, INT), + syscall!(fgetxattr, INT, STR, ADDR, INT), + syscall!(listxattr, STR, STR, INT), + syscall!(llistxattr, STR, STR, INT), + syscall!(flistxattr, INT, STR, INT), + syscall!(removexattr, STR, STR), + syscall!(lremovexattr, STR, STR), + syscall!(fremovexattr, INT, STR), + syscall!(getcwd, STR, INT), + syscall!(lookup_dcookie, INT, STR, INT), + syscall!(eventfd2, INT, INT), + syscall!(epoll_create1, INT), + syscall!(epoll_ctl, INT, INT, INT, ADDR), + syscall!(epoll_pwait, INT, ADDR, INT, INT, ADDR, INT), + syscall!(dup, INT), + syscall!(dup3, INT, INT, INT), + syscall!(fcntl, INT, INT, INT), + syscall!(inotify_init1, INT), + syscall!(inotify_add_watch, INT, STR, INT), + syscall!(inotify_rm_watch, INT, INT), + syscall!(ioctl, INT, INT, INT), + syscall!(ioprio_set, INT, INT, INT), + syscall!(ioprio_get, INT, INT), + syscall!(flock, INT, INT), + syscall!(mknodat, INT, STR, INT, INT), + syscall!(mkdirat, INT, STR, INT), + syscall!(unlinkat, INT, STR, INT), + syscall!(symlinkat, STR, INT, STR), + syscall!(linkat, INT, STR, INT, STR, INT), + syscall!(renameat, INT, STR, INT, STR), + syscall!(umount2, STR, INT), + syscall!(mount, STR, STR, STR, INT, ADDR), + syscall!(pivot_root, STR, STR), + syscall!(nfsservctl, INT, ADDR, ADDR), + syscall!(statfs, STR, ADDR), + syscall!(fstatfs, INT, ADDR), + syscall!(truncate, STR, INT), + syscall!(ftruncate, INT, INT), + syscall!(fallocate, INT, INT, INT, INT), + syscall!(faccessat, INT, STR, INT), + syscall!(chdir, STR), + syscall!(fchdir, INT), + syscall!(chroot, STR), + syscall!(fchmod, INT, INT), + syscall!(fchmodat, INT, STR, INT), + syscall!(fchownat, INT, STR, INT, INT, INT), + syscall!(fchown, INT, INT, INT), + syscall!(openat, INT, STR, INT, INT), + syscall!(close, INT), + syscall!(vhangup), + syscall!(pipe2, ADDR, INT), + syscall!(quotactl, INT, STR, INT, ADDR), + syscall!(getdents64, INT, ADDR, INT), + syscall!(lseek, INT, INT, INT), + syscall!(read, INT, STR, INT), + syscall!(write, INT, STR, INT), + syscall!(readv, INT, ADDR, INT), + syscall!(writev, INT, ADDR, INT), + syscall!(pread64, INT, STR, INT, INT), + syscall!(pwrite64, INT, STR, INT, INT), + syscall!(preadv, INT, ADDR, INT, INT, INT), + syscall!(pwritev, INT, ADDR, INT, INT, INT), + syscall!(sendfile, INT, INT, ADDR, INT), + syscall!(pselect6, INT, ADDR, ADDR, ADDR, ADDR, ADDR), + syscall!(ppoll, ADDR, INT, ADDR, ADDR, INT), + syscall!(signalfd4, INT, ADDR, INT, INT), + syscall!(vmsplice, INT, ADDR, INT, INT), + syscall!(splice, INT, ADDR, INT, ADDR, INT, INT), + syscall!(tee, INT, INT, INT, INT), + syscall!(readlinkat, INT, STR, STR, INT), + syscall!(fstatat, INT, STR, ADDR, INT), + syscall!(fstat, INT, ADDR), + syscall!(sync), + syscall!(fsync, INT), + syscall!(fdatasync, INT), + syscall!(sync_file_range2, INT, INT, INT, INT), + syscall!(timerfd_create, INT, INT), + syscall!(timerfd_settime, INT, INT, ADDR, ADDR), + syscall!(timerfd_gettime, INT, ADDR), + syscall!(utimensat, INT, STR, ADDR, INT), + syscall!(acct, STR), + syscall!(capget, ADDR, ADDR), + syscall!(capset, ADDR, ADDR), + syscall!(personality, INT), + syscall!(exit, INT), + syscall!(exit_group, INT), + syscall!(waitid, INT, INT, ADDR, INT, ADDR), + syscall!(set_tid_address, ADDR), + syscall!(unshare, INT), + syscall!(futex, ADDR, INT, INT, ADDR, ADDR, INT), + syscall!(set_robust_list, ADDR, INT), + syscall!(get_robust_list, INT, ADDR, ADDR), + syscall!(nanosleep, ADDR, ADDR), + syscall!(getitimer, INT, ADDR), + syscall!(setitimer, INT, ADDR, ADDR), + syscall!(kexec_load, INT, INT, ADDR, INT), + syscall!(init_module, ADDR, INT, STR), + syscall!(delete_module, STR, INT), + syscall!(timer_create, INT, ADDR, ADDR), + syscall!(timer_gettime, INT, ADDR), + syscall!(timer_getoverrun, INT), + syscall!(timer_settime, INT, INT, ADDR, ADDR), + syscall!(timer_delete, INT), + syscall!(clock_settime, INT, ADDR), + syscall!(clock_gettime, INT, ADDR), + syscall!(clock_getres, INT, ADDR), + syscall!(clock_nanosleep, INT, INT, ADDR, ADDR), + syscall!(syslog, INT, STR, INT), + syscall!(ptrace, INT, INT, INT, INT), + syscall!(sched_setparam, INT, ADDR), + syscall!(sched_setscheduler, INT, INT, ADDR), + syscall!(sched_getscheduler, INT), + syscall!(sched_getparam, INT, ADDR), + syscall!(sched_setaffinity, INT, INT, ADDR), + syscall!(sched_getaffinity, INT, INT, ADDR), + syscall!(sched_yield), + syscall!(sched_get_priority_max, INT), + syscall!(sched_get_priority_min, INT), + syscall!(sched_rr_get_interval, INT, ADDR), + syscall!(restart_syscall), + syscall!(kill, INT, INT), + syscall!(tkill, INT, INT), + syscall!(tgkill, INT, INT, INT), + syscall!(sigaltstack, ADDR, ADDR), + syscall!(rt_sigsuspend, ADDR, INT), + syscall!(rt_sigaction, INT, ADDR, ADDR, INT), + syscall!(rt_sigprocmask, INT, ADDR, ADDR, INT), + syscall!(rt_sigpending, ADDR, INT), + syscall!(rt_sigtimedwait, ADDR, ADDR, ADDR, INT), + syscall!(rt_sigqueueinfo, INT, INT, ADDR), + syscall!(rt_sigreturn), + syscall!(setpriority, INT, INT, INT), + syscall!(getpriority, INT, INT), + syscall!(reboot, INT, INT, INT, ADDR), + syscall!(setregid, INT, INT), + syscall!(setgid, INT), + syscall!(setreuid, INT, INT), + syscall!(setuid, INT), + syscall!(setresuid, INT, INT, INT), + syscall!(getresuid, ADDR, ADDR, ADDR), + syscall!(setresgid, INT, INT, INT), + syscall!(getresgid, ADDR, ADDR, ADDR), + syscall!(setfsuid, INT), + syscall!(setfsgid, INT), + syscall!(times, ADDR), + syscall!(setpgid, INT, INT), + syscall!(getpgid, INT), + syscall!(getsid, INT), + syscall!(setsid), + syscall!(getgroups, INT, ADDR), + syscall!(setgroups, INT, ADDR), + syscall!(uname, ADDR), + syscall!(sethostname, STR, INT), + syscall!(setdomainname, STR, INT), + syscall!(getrlimit, INT, ADDR), + syscall!(setrlimit, INT, ADDR), + syscall!(getrusage, INT, ADDR), + syscall!(umask, INT), + syscall!(prctl, INT, INT, INT, INT, INT), + syscall!(getcpu, ADDR, ADDR, ADDR), + syscall!(gettimeofday, ADDR, ADDR), + syscall!(settimeofday, ADDR, ADDR), + syscall!(adjtimex, ADDR), + syscall!(getpid), + syscall!(getppid), + syscall!(getuid), + syscall!(geteuid), + syscall!(getgid), + syscall!(getegid), + syscall!(gettid), + syscall!(sysinfo, ADDR), + syscall!(mq_open, STR, INT, INT, ADDR), + syscall!(mq_unlink, STR), + syscall!(mq_timedsend, INT, STR, INT, INT, ADDR), + syscall!(mq_timedreceive, INT, STR, INT, ADDR, ADDR), + syscall!(mq_notify, INT, ADDR), + syscall!(mq_getsetattr, INT, ADDR, ADDR), + syscall!(msgget, INT, INT), + syscall!(msgctl, INT, INT, ADDR), + syscall!(msgrcv, INT, ADDR, INT, INT, INT), + syscall!(msgsnd, INT, ADDR, INT, INT), + syscall!(semget, INT, INT, INT), + syscall!(semctl, INT, INT, INT, INT), + syscall!(semtimedop, INT, ADDR, INT, ADDR), + syscall!(semop, INT, ADDR, INT), + syscall!(shmget, INT, INT, INT), + syscall!(shmctl, INT, INT, ADDR), + syscall!(shmat, INT, STR, INT), + syscall!(shmdt, STR), + syscall!(socket, INT, INT, INT), + syscall!(socketpair, INT, INT, INT, ADDR), + syscall!(bind, INT, ADDR, INT), + syscall!(listen, INT, INT), + syscall!(accept, INT, ADDR, ADDR), + syscall!(connect, INT, ADDR, INT), + syscall!(getsockname, INT, ADDR, ADDR), + syscall!(getpeername, INT, ADDR, ADDR), + syscall!(sendto, INT, ADDR, INT, INT, ADDR, INT), + syscall!(recvfrom, INT, ADDR, INT, INT, ADDR, ADDR), + syscall!(setsockopt, INT, INT, INT, STR, INT), + syscall!(getsockopt, INT, INT, INT, STR, ADDR), + syscall!(shutdown, INT, INT), + syscall!(sendmsg, INT, ADDR, INT), + syscall!(recvmsg, INT, ADDR, INT), + syscall!(readahead, INT, INT, INT), + syscall!(brk, INT), + syscall!(munmap, INT, INT), + syscall!(mremap, INT, INT, INT, INT, INT), + syscall!(add_key, STR, STR, ADDR, INT, INT), + syscall!(request_key, STR, STR, STR, INT), + syscall!(keyctl, INT, INT, INT, INT, INT), + syscall!(clone, INT, INT, ADDR, INT, ADDR), + syscall!(execve, STR, STR, STR), + syscall!(mmap, ADDR, INT, INT, INT, INT, INT), + syscall!(fadvise64, INT, INT, INT, INT), + syscall!(swapon, STR, INT), + syscall!(swapoff, STR), + syscall!(mprotect, INT, INT, INT), + syscall!(msync, INT, INT, INT), + syscall!(mlock, INT, INT), + syscall!(munlock, INT, INT), + syscall!(mlockall, INT), + syscall!(munlockall), + syscall!(mincore, INT, INT, ADDR), + syscall!(madvise, INT, INT, INT), + syscall!(remap_file_pages, INT, INT, INT, INT, INT), + syscall!(mbind, INT, INT, INT, ADDR, INT, INT), + syscall!(get_mempolicy, ADDR, ADDR, INT, INT, INT), + syscall!(set_mempolicy, INT, ADDR, INT), + syscall!(migrate_pages, INT, INT, ADDR, ADDR), + syscall!(move_pages, INT, INT, ADDR, ADDR, ADDR, INT), + syscall!(rt_tgsigqueueinfo, INT, INT, INT, ADDR), + syscall!(perf_event_open, ADDR, INT, INT, INT, INT), + syscall!(accept4, INT, ADDR, ADDR, INT), + syscall!(recvmmsg, INT, ADDR, INT, INT, ADDR), + ], + _258: [ + syscall!(riscv_hwprobe, ADDR, INT, INT, ADDR, INT), + syscall!(riscv_flush_icache, ADDR, ADDR, INT), + syscall!(wait4, INT, ADDR, INT, ADDR), + syscall!(prlimit64, INT, INT, ADDR, ADDR), + syscall!(fanotify_init, INT, INT), + syscall!(fanotify_mark, INT, INT, INT, INT, STR), + syscall!(name_to_handle_at, INT, STR, ADDR, INT, INT), + syscall!(open_by_handle_at, INT, ADDR, INT), + syscall!(clock_adjtime, INT, ADDR), + syscall!(syncfs, INT), + syscall!(setns, INT, INT), + syscall!(sendmmsg, INT, ADDR, INT, INT), + syscall!(process_vm_readv, INT, ADDR, INT, ADDR, INT, INT), + syscall!(process_vm_writev, INT, ADDR, INT, ADDR, INT, INT), + syscall!(kcmp, INT, INT, INT, INT, INT), + syscall!(finit_module, INT, STR, INT), + syscall!(sched_setattr, INT, ADDR, INT), + syscall!(sched_getattr, INT, ADDR, INT, INT), + syscall!(renameat2, INT, STR, INT, STR, INT), + syscall!(seccomp, INT, INT, ADDR), + syscall!(getrandom, STR, INT, INT), + syscall!(memfd_create, STR, INT), + syscall!(bpf, INT, ADDR, INT), + syscall!(execveat, INT, STR, STR, STR, INT), + syscall!(userfaultfd, INT), + syscall!(membarrier, INT, INT, INT), + syscall!(mlock2, INT, INT, INT), + syscall!(copy_file_range, INT, ADDR, INT, ADDR, INT, INT), + syscall!(preadv2, INT, ADDR, INT, INT, INT, INT), + syscall!(pwritev2, INT, ADDR, INT, INT, INT, INT), + syscall!(pkey_mprotect, INT, INT, INT, INT), + syscall!(pkey_alloc, INT, INT), + syscall!(pkey_free, INT), + syscall!(statx, INT, STR, INT, INT, ADDR), + syscall!(io_pgetevents, INT, INT, INT, ADDR, ADDR, ADDR), + syscall!(rseq, ADDR, INT, INT, INT), + syscall!(kexec_file_load, INT, INT, INT, STR, INT), + ], + _403: [ + // These time64 syscalls are the same as the original variant on 64-bit systems. + syscall!(clock_gettime64, INT, ADDR), + syscall!(clock_settime64, INT, ADDR), + syscall!(clock_adjtime64, INT, ADDR), + syscall!(clock_getres_time64, INT, ADDR), + syscall!(clock_nanosleep_time64, INT, INT, ADDR, ADDR), + syscall!(timer_gettime64, INT, ADDR), + syscall!(timer_settime64, INT, INT, ADDR, ADDR), + syscall!(timerfd_gettime64, INT, ADDR), + syscall!(timerfd_settime64, INT, INT, ADDR, ADDR), + syscall!(utimensat_time64, INT, STR, ADDR, INT), + syscall!(pselect6_time64, INT, ADDR, ADDR, ADDR, ADDR, ADDR), + syscall!(ppoll_time64, ADDR, INT, ADDR, ADDR, INT), + ], + _416: [ + // These time64 syscalls are the same as the original variant on 64-bit systems. + syscall!(io_pgetevents_time64, INT, INT, INT, ADDR, ADDR, ADDR), + syscall!(recvmmsg_time64, INT, ADDR, INT, INT, ADDR), + syscall!(mq_timedsend_time64, INT, STR, INT, INT, ADDR), + syscall!(mq_timedreceive_time64, INT, STR, INT, ADDR, ADDR), + syscall!(semtimedop_time64, INT, ADDR, INT, ADDR), + syscall!(rt_sigtimedwait_time64, ADDR, ADDR, ADDR, INT), + syscall!(futex_time64, ADDR, INT, INT, ADDR, ADDR, INT), + syscall!(sched_rr_get_interval_time64, INT, ADDR), + syscall!(pidfd_send_signal, INT, INT, ADDR, INT), + syscall!(io_uring_setup, INT, ADDR), + syscall!(io_uring_enter, INT, INT, INT, INT, ADDR, INT), + syscall!(io_uring_register, INT, INT, ADDR, INT), + syscall!(open_tree, INT, STR, INT), + syscall!(move_mount, INT, STR, INT, STR, INT), + syscall!(fsopen, STR, INT), + syscall!(fsconfig, INT, INT, STR, ADDR, INT), + syscall!(fsmount, INT, INT, INT), + syscall!(fspick, INT, STR, INT), + syscall!(pidfd_open, INT, INT), + syscall!(clone3, ADDR, INT), + syscall!(close_range, INT, INT, INT), + syscall!(openat2, INT, STR, ADDR, INT), + syscall!(pidfd_getfd, INT, INT, INT), + syscall!(faccessat2, INT, STR, INT, INT), + syscall!(process_madvise, INT, ADDR, INT, INT, INT), + syscall!(epoll_pwait2, INT, ADDR, INT, ADDR, ADDR, INT), + syscall!(mount_setattr, INT, STR, INT, ADDR, INT), + syscall!(quotactl_fd, INT, INT, INT, ADDR), + syscall!(landlock_create_ruleset, ADDR, INT, INT), + syscall!(landlock_add_rule, INT, ADDR, ADDR, INT), + syscall!(landlock_restrict_self, INT, INT), + syscall!(memfd_secret, INT), + syscall!(process_mrelease, INT, INT), + syscall!(futex_waitv, ADDR, INT, INT, ADDR, INT), + syscall!(set_mempolicy_home_node, INT, INT, INT, INT), + syscall!(cachestat, INT, INT, INT, INT), + ], +}; + +pub fn get_arg_value(registers: user_regs_struct, i: usize) -> c_ulonglong { + match i { + 0 => registers.a0, + 1 => registers.a1, + 2 => registers.a2, + 3 => registers.a3, + 4 => registers.a4, + 5 => registers.a5, + v => panic!("Invalid system call index {v}!"), + } +} + +// test that all syscalls match their syscall number +#[cfg(test)] +mod tests { + use super::*; + + #[test] + fn test_syscall_numbers() { + for (i, sysno, ..) in SYSCALLS._0.iter().enumerate() { + if let Some((sysno, _)) = sysno { + assert_eq!(i, sysno.id() as usize); + } + } + for (i, sysno, ..) in SYSCALLS._258.iter().enumerate() { + if let Some((sysno, _)) = sysno { + assert_eq!(i + 258, sysno.id() as usize); + } + } + for (i, sysno, ..) in SYSCALLS._403.iter().enumerate() { + if let Some((sysno, _)) = sysno { + assert_eq!(i + 403, sysno.id() as usize); + } + } + for (i, sysno, ..) in SYSCALLS._416.iter().enumerate() { + if let Some((sysno, _)) = sysno { + assert_eq!(i + 416, sysno.id() as usize); + } + } + } +} diff --git a/src/lib.rs b/src/lib.rs index 6e343a2..8a429a7 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -375,7 +375,10 @@ impl Tracer { let ret_code = match syscall_number { Sysno::exit | Sysno::exit_group => RetCode::from_raw(0), _ => { + #[cfg(target_arch = "x86_64")] let code = RetCode::from_raw(registers.rax); + #[cfg(target_arch = "riscv64")] + let code = RetCode::from_raw(registers.a7); match code { RetCode::Err(_) => self.syscalls_fail[syscall_number] += 1, _ => self.syscalls_pass[syscall_number] += 1, @@ -430,9 +433,12 @@ impl Tracer { } fn get_syscall(&self, registers: user_regs_struct) -> Result { - (registers.orig_rax as u32) - .try_into() - .map_err(|_| anyhow!("Invalid syscall number {}", registers.orig_rax)) + #[cfg(target_arch = "x86_64")] + let reg = registers.orig_rax; + #[cfg(target_arch = "riscv64")] + let reg = registers.a7; + (reg as u32).try_into() + .map_err(|_| anyhow!("Invalid syscall number {}", reg)) } // Issues a ptrace(PTRACE_GETREGS, ...) request and gets the corresponding syscall number (Sysno). @@ -445,8 +451,11 @@ impl Tracer { fn is_exit_syscall(&self, pid: Pid) -> Result { self.get_registers(pid).map(|registers| { - registers.orig_rax == Sysno::exit as u64 - || registers.orig_rax == Sysno::exit_group as u64 + #[cfg(target_arch = "x86_64")] + let reg = registers.orig_rax; + #[cfg(target_arch = "riscv64")] + let reg = registers.a7; + reg == Sysno::exit as u64 || reg == Sysno::exit_group as u64 }) } }