diff --git a/Cargo.toml b/Cargo.toml index e94b7c5..6a35a4a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -1,6 +1,6 @@ [package] name = "intentrace" -version = "0.3.3" +version = "0.4.0" description = "intentrace is strace with intent, it goes all the way for you instead of half the way." edition = "2021" license = "MIT" diff --git a/src/main.rs b/src/main.rs index 7e31e89..be43e43 100644 --- a/src/main.rs +++ b/src/main.rs @@ -53,8 +53,10 @@ use utilities::{ }; mod syscall_object; -mod syscalls_map; +mod syscall_object_annotations; +mod syscall_annotations_map; mod types; +mod syscall_skeleton_map; use syscall_object::{SyscallObject, SyscallState}; mod one_line_formatter; mod utilities; @@ -236,7 +238,7 @@ fn ptrace_ptracer(mut ptracer: Ptracer, child: Pid) { } let syscall_pid = Pid::from_raw(tracee.pid.as_raw()); match tracee.stop { - Stop::SyscallEnter => 'label_for_early_break: { + Stop::SyscallEnter => 'for_exiting: { match nix::sys::ptrace::getregs(syscall_pid) { Ok(registers) => { if syscall_pid != last_pid { @@ -258,7 +260,7 @@ fn ptrace_ptracer(mut ptracer: Ptracer, child: Pid) { } syscall_will_run(&mut syscall); if syscall.is_exiting() { - break 'label_for_early_break; + break 'for_exiting; } last_sysno = syscall.sysno; syscall.state = SyscallState::Exiting; @@ -301,13 +303,13 @@ fn syscall_will_run(syscall: &mut SyscallObject) { // handle program break point if syscall.is_mem_alloc_dealloc() { - set_memory_break(syscall.child); + set_memory_break(syscall.process_pid); } if FOLLOW_FORKS.load(Ordering::SeqCst) || syscall.is_exiting() { syscall.format(); if syscall.is_exiting() { let exited = " EXITED ".on_bright_red(); - let pid = format!(" {} ", syscall.child).on_black(); + let pid = format!(" {} ", syscall.process_pid).on_black(); print!("\n\n {pid}{exited}\n",); } } diff --git a/src/one_line_formatter.rs b/src/one_line_formatter.rs index bc35c01..48ad97d 100644 --- a/src/one_line_formatter.rs +++ b/src/one_line_formatter.rs @@ -62,6 +62,13 @@ use rustix::{ use syscalls::Sysno; impl SyscallObject { + + pub(crate) fn one_line_error(&mut self) { + // TODO! Deprecate this logic for more granularity + self.one_line.push(" |=> ".white()); + self.one_line.push(format!("{}", errno_to_string(self.errno.unwrap())).red()); + } + pub(crate) fn get_syscall_return(&mut self) -> Result { let eph_return = self.parse_return_value_one_line(); if self.paused { @@ -75,6 +82,7 @@ impl SyscallObject { } eph_return } + pub(crate) fn one_line_formatter(&mut self) -> Result<(), ()> { use crate::syscall_object::SyscallState::*; @@ -82,7 +90,7 @@ impl SyscallObject { if FOLLOW_FORKS.load(Ordering::SeqCst) { self.one_line.extend(vec![ "\n".white(), - self.child.to_string().bright_blue(), + self.process_pid.to_string().bright_blue(), " ".dimmed(), SyscallObject::colorize_syscall_name(&self.sysno, &self.category), " - ".dimmed(), @@ -91,7 +99,7 @@ impl SyscallObject { if self.get_syscall_return().is_ok() { self.one_line.extend(vec![ "\n".white(), - self.child.to_string().blue(), + self.process_pid.to_string().blue(), // self.child.to_string().on_black(), " ".dimmed(), SyscallObject::colorize_syscall_name(&self.sysno, &self.category), @@ -100,7 +108,7 @@ impl SyscallObject { } else { self.one_line.extend(vec![ "\n".white(), - self.child.to_string().red(), + self.process_pid.to_string().red(), // self.child.to_string().on_red(), " ".dimmed(), SyscallObject::colorize_syscall_name(&self.sysno, &self.category), @@ -189,7 +197,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -208,7 +216,7 @@ impl SyscallObject { self.one_line.push("file closed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -230,7 +238,7 @@ impl SyscallObject { self.one_line.push("successfully opened file".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -329,7 +337,7 @@ impl SyscallObject { self.one_line.push("successfully opened file".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -348,7 +356,7 @@ impl SyscallObject { self.one_line.push("stats retrieved successfully".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -367,7 +375,7 @@ impl SyscallObject { self.one_line.push("stats retrieved successfully".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -388,7 +396,7 @@ impl SyscallObject { self.one_line.push("stats retrieved successfully".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -408,7 +416,7 @@ impl SyscallObject { self.one_line.push("stats retrieved successfully".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -428,7 +436,7 @@ impl SyscallObject { self.one_line.push("stats retrieved successfully".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -486,7 +494,7 @@ impl SyscallObject { self.one_line.push("stats retrieved successfully".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -545,7 +553,7 @@ impl SyscallObject { self.one_line.push("stats retrieved successfully".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -594,7 +602,7 @@ impl SyscallObject { self.one_line.push("ownership changed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -644,7 +652,7 @@ impl SyscallObject { self.one_line.push("ownership changed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -693,7 +701,7 @@ impl SyscallObject { self.one_line.push("ownership changed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -744,7 +752,7 @@ impl SyscallObject { self.one_line.push("ownership changed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -929,7 +937,7 @@ impl SyscallObject { self.one_line.push("memory advice registered".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1185,7 +1193,7 @@ impl SyscallObject { // } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1207,7 +1215,7 @@ impl SyscallObject { self.one_line.push("successfully unmapped region".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1249,7 +1257,7 @@ impl SyscallObject { self.one_line.push("successfully flushed data".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1327,7 +1335,7 @@ impl SyscallObject { self.one_line.push("memory protection modified".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1440,7 +1448,7 @@ impl SyscallObject { self.one_line.push(eph_return.unwrap().green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1464,7 +1472,7 @@ impl SyscallObject { .push("memory range is now unswappable".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1498,7 +1506,7 @@ impl SyscallObject { .push("memory range is now unswappable".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1522,7 +1530,7 @@ impl SyscallObject { self.one_line.push("memory range is now swappable".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1542,7 +1550,7 @@ impl SyscallObject { self.one_line.push("memory range is now swappable".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1608,7 +1616,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1639,7 +1647,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1691,7 +1699,7 @@ impl SyscallObject { .push("memory range is now unswappable".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1728,7 +1736,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1764,7 +1772,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1803,7 +1811,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1843,7 +1851,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1873,7 +1881,7 @@ impl SyscallObject { self.one_line.push(bytes_string.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1904,7 +1912,7 @@ impl SyscallObject { self.one_line.push(bytes_string.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1937,7 +1945,7 @@ impl SyscallObject { self.one_line.push(bytes_string.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1971,7 +1979,7 @@ impl SyscallObject { self.one_line.push(bytes_string.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -1990,7 +1998,7 @@ impl SyscallObject { self.one_line.push("all writes flushed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2015,7 +2023,7 @@ impl SyscallObject { self.one_line.push("file moved".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2042,7 +2050,7 @@ impl SyscallObject { self.one_line.push("file moved".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2081,7 +2089,7 @@ impl SyscallObject { self.one_line.push("file moved".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2111,7 +2119,7 @@ impl SyscallObject { self.one_line.push("directory created".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2141,7 +2149,7 @@ impl SyscallObject { self.one_line.push("directory created".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2160,7 +2168,7 @@ impl SyscallObject { self.one_line.push(eph_return.unwrap().yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2183,7 +2191,7 @@ impl SyscallObject { self.one_line.push("symlink created".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2207,7 +2215,7 @@ impl SyscallObject { self.one_line.push("symlink created".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } // the file does not exist at this point } @@ -2227,7 +2235,7 @@ impl SyscallObject { self.one_line.push("unlinking successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } // caution: the file is deleted at this point } @@ -2255,7 +2263,7 @@ impl SyscallObject { self.one_line.push("unlinking successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2298,7 +2306,7 @@ impl SyscallObject { self.one_line.push("check is positive".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2370,7 +2378,7 @@ impl SyscallObject { self.one_line.push("check is positive".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2443,7 +2451,7 @@ impl SyscallObject { self.one_line.push("check is positive".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2465,7 +2473,7 @@ impl SyscallObject { self.one_line.push(target.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2487,7 +2495,7 @@ impl SyscallObject { self.one_line.push(target.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2508,7 +2516,7 @@ impl SyscallObject { self.one_line.push("mode changed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2529,7 +2537,7 @@ impl SyscallObject { self.one_line.push("mode changed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2562,7 +2570,7 @@ impl SyscallObject { self.one_line.push("mode changed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2581,7 +2589,7 @@ impl SyscallObject { self.one_line.push("successfully flushed data".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2601,7 +2609,7 @@ impl SyscallObject { self.one_line.push(file_descriptors.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2623,7 +2631,7 @@ impl SyscallObject { self.one_line.push(file_descriptors.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2645,7 +2653,7 @@ impl SyscallObject { self.one_line.push(eph_return.unwrap().yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2668,7 +2676,7 @@ impl SyscallObject { self.one_line.push("Successfully duplicated".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2696,7 +2704,7 @@ impl SyscallObject { self.one_line.push("Successfully duplicated".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2717,7 +2725,7 @@ impl SyscallObject { self.one_line.push("all writes flushed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2736,7 +2744,7 @@ impl SyscallObject { self.one_line.push("all writes flushed".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2758,7 +2766,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2780,7 +2788,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2822,7 +2830,7 @@ impl SyscallObject { if timeout > 0 { let timeval = SyscallObject::read_bytes_as_struct::<16, timeval>( self.args[4] as usize, - self.child as _, + self.process_pid as _, ) .unwrap(); self.one_line.push(", and timeout ".white()); @@ -2846,7 +2854,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2894,7 +2902,7 @@ impl SyscallObject { if timeout > 0 { let timespec = SyscallObject::read_bytes_as_struct::<16, timespec>( self.args[4] as usize, - self.child as _, + self.process_pid as _, ) .unwrap(); self.one_line.push(", and timeout ".white()); @@ -2918,7 +2926,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2949,7 +2957,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -2974,7 +2982,7 @@ impl SyscallObject { if timeout > 0 { let timespec = SyscallObject::read_bytes_as_struct::<16, timespec>( self.args[2] as usize, - self.child as _, + self.process_pid as _, ) .unwrap(); self.one_line.push(", and timeout ".white()); @@ -2998,7 +3006,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3019,7 +3027,7 @@ impl SyscallObject { self.one_line.push("Successfull".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3044,7 +3052,7 @@ impl SyscallObject { self.one_line.push("Successfull".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3077,7 +3085,7 @@ impl SyscallObject { self.one_line.push("Successfull".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3117,7 +3125,7 @@ impl SyscallObject { self.one_line.push("Successfull".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3143,7 +3151,7 @@ impl SyscallObject { if time > 0 { let timespec = SyscallObject::read_bytes_as_struct::<16, timespec>( self.args[3] as usize, - self.child as _, + self.process_pid as _, ) .unwrap(); self.one_line.push(", and timeout ".white()); @@ -3161,7 +3169,7 @@ impl SyscallObject { self.one_line.push("Successfull".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3198,7 +3206,7 @@ impl SyscallObject { self.one_line.push("Successfull".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3220,7 +3228,7 @@ impl SyscallObject { self.one_line.push("operation successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3242,7 +3250,7 @@ impl SyscallObject { self.one_line.push("operation successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3336,7 +3344,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3356,7 +3364,7 @@ impl SyscallObject { self.one_line.push("successfully yielded CPU".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3473,7 +3481,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3537,7 +3545,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3555,7 +3563,7 @@ impl SyscallObject { .push("list of blocked signals modified".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3609,7 +3617,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3627,7 +3635,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3647,7 +3655,7 @@ impl SyscallObject { self.one_line.push("pending signals returned".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3666,7 +3674,7 @@ impl SyscallObject { self.one_line.push("Successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3698,7 +3706,7 @@ impl SyscallObject { self.one_line.push("data and signal sent".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3733,7 +3741,7 @@ impl SyscallObject { self.one_line.push("data and signal sent".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3770,7 +3778,7 @@ impl SyscallObject { self.one_line.push("signal sent".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3799,7 +3807,7 @@ impl SyscallObject { self.one_line.push("Successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3839,7 +3847,7 @@ impl SyscallObject { self.one_line.push("file descriptor created".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3859,7 +3867,7 @@ impl SyscallObject { self.one_line.push(thread.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3879,7 +3887,7 @@ impl SyscallObject { self.one_line.push(process_id.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3899,7 +3907,7 @@ impl SyscallObject { self.one_line.push(process_id.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3922,7 +3930,7 @@ impl SyscallObject { if eph_return.is_ok() { let address = self.pavfol(1); let length_of_list = - SyscallObject::read_word(self.args[2] as usize, self.child) + SyscallObject::read_word(self.args[2] as usize, self.process_pid) .unwrap(); self.one_line.push(" |=> ".white()); self.one_line @@ -3932,7 +3940,7 @@ impl SyscallObject { self.one_line.push(length_of_list.to_string().blue()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3956,7 +3964,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -3991,7 +3999,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4019,7 +4027,7 @@ impl SyscallObject { self.one_line.push(pgid.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4039,7 +4047,7 @@ impl SyscallObject { self.one_line.push(pgid.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4097,7 +4105,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4118,7 +4126,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4139,7 +4147,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4188,7 +4196,7 @@ impl SyscallObject { self.one_line.push(" |=> ".white()); let rlims = SyscallObject::read_bytes_as_struct::<16, rlimit>( self.args[3] as usize, - self.child as _, + self.process_pid as _, ) .unwrap(); match resource { @@ -4370,7 +4378,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4403,7 +4411,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4423,7 +4431,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4443,7 +4451,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4452,7 +4460,7 @@ impl SyscallObject { let thread_id = self.args[0]; let cpus = - SyscallObject::read_affinity_from_child(self.args[2] as usize, self.child) + SyscallObject::read_affinity_from_child(self.args[2] as usize, self.process_pid) .unwrap(); match self.state { Entering => { @@ -4485,7 +4493,7 @@ impl SyscallObject { self.one_line.push("thread successfully locked".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4497,7 +4505,7 @@ impl SyscallObject { let mut set: cpu_set_t = unsafe { mem::zeroed() }; let cpus = - SyscallObject::read_affinity_from_child(self.args[2] as usize, self.child) + SyscallObject::read_affinity_from_child(self.args[2] as usize, self.process_pid) .unwrap(); match self.state { Entering => { @@ -4529,7 +4537,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4601,7 +4609,7 @@ impl SyscallObject { self.one_line.push("signal sent".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4633,7 +4641,7 @@ impl SyscallObject { self.one_line.push("signal sent".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4666,7 +4674,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4685,7 +4693,7 @@ impl SyscallObject { self.one_line.push("information retrieved".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4705,7 +4713,7 @@ impl SyscallObject { self.one_line.push(user_id.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4725,7 +4733,7 @@ impl SyscallObject { self.one_line.push(user_id.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4745,7 +4753,7 @@ impl SyscallObject { self.one_line.push(group_id.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4765,7 +4773,7 @@ impl SyscallObject { self.one_line.push(group_id.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4807,7 +4815,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4953,14 +4961,14 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } } Sysno::set_tid_address => { let thread_id = - SyscallObject::read_word(self.args[0] as usize, self.child).unwrap(); + SyscallObject::read_word(self.args[0] as usize, self.process_pid).unwrap(); match self.state { Entering => { self.one_line @@ -4976,7 +4984,7 @@ impl SyscallObject { self.one_line.push(eph_return.unwrap().yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -4998,7 +5006,7 @@ impl SyscallObject { self.one_line.push(new_process()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5019,7 +5027,7 @@ impl SyscallObject { self.one_line.push(new_process()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5039,7 +5047,7 @@ impl SyscallObject { self.one_line.push(file_descriptor.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5084,7 +5092,7 @@ impl SyscallObject { self.one_line.push(file_descriptor.yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5165,7 +5173,7 @@ impl SyscallObject { self.one_line.push("Successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5379,7 +5387,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5388,7 +5396,7 @@ impl SyscallObject { let size_of_cl_args = self.args[1]; let cl_args = SyscallObject::read_bytes_as_struct::<88, clone3::CloneArgs>( self.args[0] as usize, - self.child as _, + self.process_pid as _, ) .unwrap(); let clone_flags: clone3::Flags = unsafe { std::mem::transmute(cl_args.flags) }; @@ -5562,7 +5570,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5737,7 +5745,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5760,7 +5768,7 @@ impl SyscallObject { self.one_line.push("successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5768,7 +5776,7 @@ impl SyscallObject { Sysno::nanosleep => { let timespec = SyscallObject::read_bytes_as_struct::<16, timespec>( self.args[0] as usize, - self.child as _, + self.process_pid as _, ) .unwrap(); match self.state { @@ -5789,7 +5797,7 @@ impl SyscallObject { // TODO! granularity // remaining time due to interruption is stored inside // the second syscall argument *rem (which is a timespec struct) - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5829,7 +5837,7 @@ impl SyscallObject { } } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5855,7 +5863,7 @@ impl SyscallObject { self.one_line.push("rule added".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -5878,7 +5886,7 @@ impl SyscallObject { self.one_line.push("ruleset is now enforced".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -6014,7 +6022,7 @@ impl SyscallObject { self.one_line.push("operation successful".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -6064,7 +6072,7 @@ impl SyscallObject { self.one_line.push(eph_return.unwrap().yellow()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -6121,7 +6129,7 @@ impl SyscallObject { .push("successfully set the scheduling priority".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -6141,7 +6149,7 @@ impl SyscallObject { self.one_line.push("successfully retrieved".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -6161,7 +6169,7 @@ impl SyscallObject { self.one_line.push("successfully retrieved".green()); } else { // TODO! granular - one_line_error(eph_return, &mut self.one_line, &self.errno); + self.one_line_error(); } } } @@ -6175,15 +6183,6 @@ impl SyscallObject { } } -pub fn one_line_error( - eph_return: Result, - one_line: &mut Vec, - self_errno: &Option, -) { - // TODO! Deprecate this logic for more granularity - one_line.push(" |=> ".white()); - one_line.push(format!("{}", errno_to_string(self_errno.unwrap())).red()); -} pub fn mode_matcher(mode: rustix::fs::Mode, one_line: &mut Vec) { // USER diff --git a/src/syscalls_map.rs b/src/syscall_annotations_map.rs similarity index 55% rename from src/syscalls_map.rs rename to src/syscall_annotations_map.rs index 480639c..032cb50 100644 --- a/src/syscalls_map.rs +++ b/src/syscall_annotations_map.rs @@ -1,7 +1,7 @@ use std::collections::HashMap; use syscalls::Sysno; use std::mem::MaybeUninit; -use crate::types::{SysArg, Category, Flag, SysDetails, SysReturn}; +use crate::types::{SysArg, Category, Flag, SysAnnotations, SysReturn}; // TODO! differentiate between bitflags (orables) and enums // TODO! add granularity for value-return type of syscall arguments @@ -11,12 +11,12 @@ use crate::types::{SysArg, Category, Flag, SysDetails, SysReturn}; // switch to MaybeUninit // TODO! switch to phf later -pub fn initialize_syscall_map() -> HashMap { +pub fn initialize_syscall_annotations_map() -> HashMap { use SysArg::*; use Category::*; use Flag::*; use SysReturn::*; - let array: Vec<(Sysno, SysDetails)> = vec![ + let array: Vec<(Sysno, SysAnnotations)> = vec![ // read from a file descriptor ( Sysno::read, @@ -24,11 +24,11 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "read", &[ - (["fd", "file descriptor to be read from"], File_Descriptor("")), - (["buf", "buffer to be read into"], Pointer_To_Text("")), - (["count", "count of bytes to be read"], Length_Of_Bytes_Specific), + ["fd", "file descriptor to be read from"], + ["buf", "buffer to be read into"], + ["count", "count of bytes to be read"], ], - (["return value", "positive number of bytes read, 0 means end of file, -1 means error, and errno modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "positive number of bytes read, 0 means end of file, -1 means error, and errno modified"], ), ), // write to a file descriptor @@ -38,11 +38,11 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "write", &[ - (["fd", "file descriptor"], File_Descriptor("")), - (["buf", "buffer holding the data to be written"], Pointer_To_Text("")), - (["count", "amount of bytes to write from the buffer"], Length_Of_Bytes_Specific), + ["fd", "file descriptor"], + ["buf", "buffer holding the data to be written"], + ["count", "amount of bytes to write from the buffer"], ], - (["return value", "positive number of bytes written, 0 means end of file, -1 means error, and errno modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "positive number of bytes written, 0 means end of file, -1 means error, and errno modified"], ) ), // read from a file descriptor at a given offset @@ -63,12 +63,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "parallel read, use your own offset to avoid file pointer data race", &[ - (["fd", "file descriptor of the file to be read from"], File_Descriptor("")), - (["buf", "pointer to a buffer where read data will be stored"], Pointer_To_Text("")), - (["count", "amount of bytes to be read from the file to the buffer"], Length_Of_Bytes_Specific), - (["offset", "bytes of offset of where reading must start"], Length_Of_Bytes_Specific), + ["fd", "file descriptor of the file to be read from"], + ["buf", "pointer to a buffer where read data will be stored"], + ["count", "amount of bytes to be read from the file to the buffer"], + ["offset", "bytes of offset of where reading must start"], ], - (["return value", "zero means done eof (done reading), on success returns number of bytes read, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "zero means done eof (done reading), on success returns number of bytes read, -1 On error and errno is modified"], ) ), // write to a file descriptor at a given offset @@ -82,12 +82,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "parallel write, use your own offset to avoid file pointer data race", &[ - (["fd", "file descriptor of the file to be written into"], File_Descriptor("")), - (["buf", "pointer to data which will be written to the file"], Pointer_To_Text("")), - (["count", "amount of bytes to be written into the file from the buffer"], Length_Of_Bytes_Specific), - (["offset", "bytes of offset of where writing must start"], Length_Of_Bytes_Specific), + ["fd", "file descriptor of the file to be written into"], + ["buf", "pointer to data which will be written to the file"], + ["count", "amount of bytes to be written into the file from the buffer"], + ["offset", "bytes of offset of where writing must start"], ], - (["return value", "zero means nothing was written (done writing), on success returns number of bytes written, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "zero means nothing was written (done writing), on success returns number of bytes written, -1 On error and errno is modified"], ) ), ( @@ -103,11 +103,11 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "scatter read, read vectored, read from several non contiguous regions", &[ - (["fd", "file descriptor of the file to be read from"], File_Descriptor("")), - (["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], Array_Of_Struct), - (["count", "number of iovec structs in the iovec array"], Unsigned_Numeric), + ["fd", "file descriptor of the file to be read from"], + ["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], + ["count", "number of iovec structs in the iovec array"], ], - (["return value", "on success returns number of bytes read, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "on success returns number of bytes read, -1 On error and errno is modified"], ) ), @@ -118,12 +118,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "gather write, write vectored, write from several non contiguous regions", &[ - (["fd", "file descriptor of the file to be written into"], File_Descriptor("")), - (["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], Array_Of_Struct), - (["count", "number of iovec structs in the iovec array"], Unsigned_Numeric), + ["fd", "file descriptor of the file to be written into"], + ["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], + ["count", "number of iovec structs in the iovec array"], ], // zero means what in here? man pages dont say anything - (["return value", "on success returns number of bytes written, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "on success returns number of bytes written, -1 On error and errno is modified"], ) ), ( @@ -133,12 +133,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "scatter read, read vectored, read from several non contiguous regions using your own offset to avoid file pointer data race", &[ - (["fd", "file descriptor of the file to be read from"], File_Descriptor("")), - (["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], Array_Of_Struct), - (["count", "number of iovec structs in the iovec array"], Unsigned_Numeric), - (["offset", "amount of bytes of offset from the beginning of the file"], Length_Of_Bytes_Specific), + ["fd", "file descriptor of the file to be read from"], + ["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], + ["count", "number of iovec structs in the iovec array"], + ["offset", "amount of bytes of offset from the beginning of the file"], ], - (["return value", "on success returns number of bytes written, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "on success returns number of bytes written, -1 On error and errno is modified"], ) ), ( @@ -148,12 +148,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "gather write, write vectored from several non contiguous regions using your own offset to avoid file pointer data race", &[ - (["fd", "file descriptor of the file to be written into"], File_Descriptor("")), - (["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], Array_Of_Struct), - (["count", "number of iovec structs in the iovec array"], Unsigned_Numeric), - (["offset", "amount of bytes of offset from the beginning of the file"], Length_Of_Bytes_Specific), + ["fd", "file descriptor of the file to be written into"], + ["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], + ["count", "number of iovec structs in the iovec array"], + ["offset", "amount of bytes of offset from the beginning of the file"], ], - (["return value", "on success returns number of bytes written, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "on success returns number of bytes written, -1 On error and errno is modified"], ) ), @@ -163,13 +163,13 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "scatter read, read vectored, read from several non contiguous regions using your own offset to avoid file pointer data race in addition to customized flags", &[ - (["fd", "file descriptor of the file to be read from"], File_Descriptor("")), - (["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], Array_Of_Struct), - (["count", "number of iovec structs in the iovec array"], Unsigned_Numeric), - (["offset", "amount of bytes of offset from the beginning of the file"], Length_Of_Bytes_Specific), - (["flags", "custom falgs for specific write behaviour"], General_Flag(P_RW_V2_Flags)), + ["fd", "file descriptor of the file to be read from"], + ["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], + ["count", "number of iovec structs in the iovec array"], + ["offset", "amount of bytes of offset from the beginning of the file"], + ["flags", "custom falgs for specific write behaviour"], ], - (["return value", "on success returns number of bytes written, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "on success returns number of bytes written, -1 On error and errno is modified"], ) ), @@ -179,13 +179,13 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "gather write, write vectored from several non contiguous regions using your own offset to avoid file pointer data race in addition to customized flags", &[ - (["fd", "file descriptor of the file to be written into"], File_Descriptor("")), - (["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], Array_Of_Struct), - (["count", "number of iovec structs in the iovec array"], Unsigned_Numeric), - (["offset", "amount of bytes of offset from the beginning of the file"], Length_Of_Bytes_Specific), - (["flags", "custom falgs for specific write behaviour"], General_Flag(P_RW_V2_Flags)), + ["fd", "file descriptor of the file to be written into"], + ["iovec", "array of iovec structs containing pointer-length pairs of scattered regions to be written"], + ["count", "number of iovec structs in the iovec array"], + ["offset", "amount of bytes of offset from the beginning of the file"], + ["flags", "custom falgs for specific write behaviour"], ], - (["return value", "on success returns number of bytes written, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "on success returns number of bytes written, -1 On error and errno is modified"], ) ), @@ -195,9 +195,9 @@ pub fn initialize_syscall_map() -> HashMap { Process, "create a unidirectional pipe for process communication", &[ - (["pipefd", "pointer to array containing the read and write file descriptors"], Pointer_To_File_Descriptor_Array(["", ""])), + ["pipefd", "pointer to array containing the read and write file descriptors"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -206,11 +206,11 @@ pub fn initialize_syscall_map() -> HashMap { Process, "create a unidirectional pipe for process communication, in additiona to flags for file opening behaviour", &[ - (["pipefd", "pointer to array containing the read and write file descriptors"], Pointer_To_File_Descriptor_Array(["", ""])), + ["pipefd", "pointer to array containing the read and write file descriptors"], // If flags is 0, then pipe2() is the same as pipe() - (["flags", "file opening flags for the pipe file descriptors"], General_Flag(Open)) + ["flags", "file opening flags for the pipe file descriptors"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // duplicate a file descriptor @@ -221,9 +221,9 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "duplicate file descriptor", &[ - (["oldfd", "file descriptor to be copied"], File_Descriptor("")), + ["oldfd", "file descriptor to be copied"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), // same as dup, but uses newfd for the fd @@ -235,10 +235,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "duplicate file descriptor with another file descriptor", &[ - (["oldfd", "file descriptor to be copied"], File_Descriptor("")), - (["newfd,", "new file descriptor"], File_Descriptor("")) + ["oldfd", "file descriptor to be copied"], + ["newfd,", "new file descriptor"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), // same as dup2 but the caller can force the close-on-exec flag to be set for the new file descriptor by specifying O_CLOEXEC in flags. @@ -248,11 +248,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "duplicate file descriptor with another file descriptor with some useful flags", &[ - (["oldfd", "file descriptor to be copied"], File_Descriptor("")), - (["newfd,", "new file descriptor"], File_Descriptor("")), - (["flags", "flag for -as of now- O_CLOEXEC only"], General_Flag(Dup3Flags)) + ["oldfd", "file descriptor to be copied"], + ["newfd,", "new file descriptor"], + ["flags", "flag for -as of now- O_CLOEXEC only"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), ( @@ -261,10 +261,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "check permissions on a file", &[ - (["pathname", "path of the file to be checked"], Pointer_To_Text("")), - (["mode", "specific accessibilities to be checked"], General_Flag(Access)) + ["pathname", "path of the file to be checked"], + ["mode", "specific accessibilities to be checked"], ], - (["numeric return", "0 on success (all permissions were granted), -1 on error (at least one permission was not granted), errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success (all permissions were granted), -1 on error (at least one permission was not granted), errno modified"], ) ), ( @@ -273,12 +273,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "check permissions on a file, with an optional anchor directory, and path resolution flags", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the file to be checked"], Pointer_To_Text("")), - (["mode", "specific accessibilities to be checked"], General_Flag(Access)), - (["flags", "path resolution flags"], General_Flag(FileAtFlags)), + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the file to be checked"], + ["mode", "specific accessibilities to be checked"], + ["flags", "path resolution flags"], ], - (["numeric return", "0 on success (all permissions were granted), -1 on error (at least one permission was not granted), errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success (all permissions were granted), -1 on error (at least one permission was not granted), errno modified"], ) ), ( @@ -287,12 +287,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "check permissions on a file, with an optional anchor directory, and path resolution flags", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the file to be checked"], Pointer_To_Text("")), - (["mode", "specific accessibilities to be checked"], General_Flag(Access)), - (["flags", "path resolution flags"], General_Flag(FileAtFlags)), + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the file to be checked"], + ["mode", "specific accessibilities to be checked"], + ["flags", "path resolution flags"], ], - (["numeric return", "0 on success (all permissions were granted), -1 on error (at least one permission was not granted), errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success (all permissions were granted), -1 on error (at least one permission was not granted), errno modified"], ) ), @@ -305,13 +305,13 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "open and possibly create a file", &[ - (["filename", "path of the file to be opened"], Pointer_To_Text("")), + ["filename", "path of the file to be opened"], // flags: one of the following modes: O_RDONLY, O_WRONLY, or O_RDWR. // and an optional or of others - (["flags", "file opening flags"], General_Flag(Open)), - (["mode", "file permission modes (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), + ["flags", "file opening flags"], + ["mode", "file permission modes (rwx rwx rwx, set-uid, set-guid, sticky bits)"], ], - (["return value", "-1 for error, and errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 for error, and errno modified"], ) ), // openat handles a relative path by considering it relative to the directory of dirfd @@ -323,12 +323,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "open and possibly create a file, use dirfd as anchor", &[ - (["dirfd", "file descriptor of the anchor directory"], File_Descriptor_openat("")), - (["pathname", "path of the file to be opened"], Pointer_To_Text("")), - (["flags", "file opening flags"], General_Flag(Open)), - (["mode", "file permission modes (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), + ["dirfd", "file descriptor of the anchor directory"], + ["pathname", "path of the file to be opened"], + ["flags", "file opening flags"], + ["mode", "file permission modes (rwx rwx rwx, set-uid, set-guid, sticky bits)"], ], - (["return value", "-1 for error, and errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 for error, and errno modified"], ) ), // an extension of openat(2) and provides a superset of its functionality. @@ -339,12 +339,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "open and possibly create a file, use dirfd as anchor, and open_how for further customization", &[ - (["dirfd", "file descriptor of the anchor directory"], File_Descriptor("")), - (["pathname", "path of the file to be opened"], Pointer_To_Text("")), - (["open_how", "how struct which contains the logic for opening"], Pointer_To_Struct), - (["size", "size of the how struct in bytes"], Length_Of_Bytes) + ["dirfd", "file descriptor of the anchor directory"], + ["pathname", "path of the file to be opened"], + ["open_how", "how struct which contains the logic for opening"], + ["size", "size of the how struct in bytes"], ], - (["return value", "-1 for error, and errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 for error, and errno modified"], ) ), // calling creat() is equivalent to calling open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC @@ -354,10 +354,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a file", &[ - (["pathname", "path of the file to be opened"], Pointer_To_Text("")), - (["mode", "file permission modes (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), + ["pathname", "path of the file to be opened"], + ["mode", "file permission modes (rwx rwx rwx, set-uid, set-guid, sticky bits)"], ], - (["return value", "-1 for error, and errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 for error, and errno modified"], ) ), ( @@ -366,10 +366,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "get current working directory", &[ - (["buf", "buffer to fill with the absolute path of the current working directory"], Pointer_To_Text("")), - (["size", "size of the absolute path buffer"], Length_Of_Bytes_Specific) + ["buf", "buffer to fill with the absolute path of the current working directory"], + ["size", "size of the absolute path buffer"], ], - (["return value", "pointer to path of the current working directory, null on error, and errno modified"], Address_Or_Errno_getcwd("")) + ["return value", "pointer to path of the current working directory, null on error, and errno modified"], ) ), ( @@ -378,9 +378,9 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change to a new directory using a specific path", &[ - (["pathname", "the new path we're switching to"], Pointer_To_Text("")), + ["pathname", "the new path we're switching to"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -389,9 +389,9 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change to a new directory using a file desciptor", &[ - (["fd", "file descriptor of the path we're switching to"], File_Descriptor("")), + ["fd", "file descriptor of the path we're switching to"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -400,10 +400,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "rename a file and possibly move it", &[ - (["oldpath", "old path of the file"], Pointer_To_Text("")), - (["newpath", "new path of the file"], Pointer_To_Text("")), + ["oldpath", "old path of the file"], + ["newpath", "new path of the file"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -412,13 +412,13 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "rename a file and possibly move it, with an optional anchor directory", &[ - (["olddirfd", "file descriptor of a path to use as anchor if oldpath is relative"], File_Descriptor("")), - (["oldpath", "old path of the file"], Pointer_To_Text("")), + ["olddirfd", "file descriptor of a path to use as anchor if oldpath is relative"], + ["oldpath", "old path of the file"], - (["newdirfd", "file descriptor of a path to use as anchor if newpath is relative"], File_Descriptor("")), - (["newpath", "new path of the file"], Pointer_To_Text("")), + ["newdirfd", "file descriptor of a path to use as anchor if newpath is relative"], + ["newpath", "new path of the file"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -427,15 +427,15 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "rename a file and possibly move it, with an optional anchor directory and flags for custom behaviour", &[ - (["olddirfd", "file descriptor of a path to use as anchor if oldpath is relative"], File_Descriptor("")), - (["oldpath", "old path of the file"], Pointer_To_Text("")), + ["olddirfd", "file descriptor of a path to use as anchor if oldpath is relative"], + ["oldpath", "old path of the file"], - (["newdirfd", "file descriptor of a path to use as anchor if newpath is relative"], File_Descriptor("")), - (["newpath", "new path of the file"], Pointer_To_Text("")), + ["newdirfd", "file descriptor of a path to use as anchor if newpath is relative"], + ["newpath", "new path of the file"], - (["flags", "renaming and replacement behaviour falgs"], General_Flag(FileRenameFlags)), + ["flags", "renaming and replacement behaviour falgs"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -444,10 +444,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a new directory using a path", &[ - (["pathname", "path of the new directory to create"], Pointer_To_Text("")), - (["mode", "directory permission (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), + ["pathname", "path of the new directory to create"], + ["mode", "directory permission (rwx rwx rwx, set-uid, set-guid, sticky bits)"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -456,11 +456,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a new directory using a path and an optional anchor directory", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the new directory to create"], Pointer_To_Text("")), - (["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the new directory to create"], + ["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -476,11 +476,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a hard link for a file", &[ - (["oldpath", "existing file we will link to"], Pointer_To_Text("")), + ["oldpath", "existing file we will link to"], // if existing, will not be overwritten - (["newpath", "path for the new file which will be linked"], Pointer_To_Text("")), + ["newpath", "path for the new file which will be linked"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -489,14 +489,14 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a hard link for a file, with an optional anchor directory, and path resolution flags", &[ - (["olddirfd", "file descriptor of a path to use as anchor if oldpath is relative"], File_Descriptor("")), - (["oldpath", "existing file we will link to"], Pointer_To_Text("")), - (["newdirfd", "file descriptor of a path to use as anchor if newpath is relative"], File_Descriptor("")), + ["olddirfd", "file descriptor of a path to use as anchor if oldpath is relative"], + ["oldpath", "existing file we will link to"], + ["newdirfd", "file descriptor of a path to use as anchor if newpath is relative"], // if existing, will not be overwritten - (["newpath", "path for the new file which will be linked"], Pointer_To_Text("")), - (["flags", "path resolution flags"], General_Flag(FileAtFlags)), + ["newpath", "path for the new file which will be linked"], + ["flags", "path resolution flags"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -507,9 +507,9 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "either deletes a file or directory, or in the case that other references still exist, simply reduces the reference count of the inode", &[ - (["pathname", "path of the file or directory to be removed"], Pointer_To_Text("")), + ["pathname", "path of the file or directory to be removed"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -518,11 +518,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "either deletes a file or directory, or in the case that other references still exist, simply reduces the reference count of the inode, in addtion to an optional anchor directory, and a behaviour customization flag", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the file or directory to be removed"], Pointer_To_Text("")), - (["flags", "flag specifying similar behaviour to rmdir or not"], General_Flag(FileAtFlags)), + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the file or directory to be removed"], + ["flags", "flag specifying similar behaviour to rmdir or not"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -531,9 +531,9 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "delete a specific directory", &[ - (["pathname", "path of the directory to remove"], Pointer_To_Text("")), + ["pathname", "path of the directory to remove"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -544,11 +544,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a symbolic link with the given name linked to the given target", &[ - (["target", "path of the target file to be linked"], Pointer_To_Text("")), + ["target", "path of the target file to be linked"], // If linkpath exists, it will not be overwritten. - (["linkpath", "path of the symlink to be created"], Pointer_To_Text("")), + ["linkpath", "path of the symlink to be created"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -557,12 +557,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a symbolic link with the given name linked to the given target", &[ - (["target", "path of the target file to be linked"], Pointer_To_Text("")), - (["dirfd", "file descriptor of a path to use as anchor if linkpath is relative"], File_Descriptor("")), + ["target", "path of the target file to be linked"], + ["dirfd", "file descriptor of a path to use as anchor if linkpath is relative"], // If linkpath exists, it will not be overwritten. - (["linkpath", "path of the symlink to be created"], Pointer_To_Text("")), + ["linkpath", "path of the symlink to be created"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -572,11 +572,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "read the contents of a symbolic link (its target path) to a buffer", &[ - (["pathname", "path of the symlink to be read"], Pointer_To_Text("")), - (["buf", "buffer where the the symlink contents will be stored"], Pointer_To_Text("")), - (["bufsiz", "size of the buffer"], Length_Of_Bytes_Specific) + ["pathname", "path of the symlink to be read"], + ["buf", "buffer where the the symlink contents will be stored"], + ["bufsiz", "size of the buffer"], ], - (["return value", "the number of bytes read to the buffer (can truncate if filled), -1 is returned On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "the number of bytes read to the buffer (can truncate if filled), -1 is returned On error and errno is modified"], ) ), ( @@ -585,12 +585,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "read the contents of a symbolic link (its target path) to a buffer", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the symlink to be read"], Pointer_To_Text("")), - (["buf", "buffer where the the symlink contents will be stored"], Pointer_To_Text("")), - (["bufsiz", "size of the buffer"], Length_Of_Bytes_Specific) + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the symlink to be read"], + ["buf", "buffer where the the symlink contents will be stored"], + ["bufsiz", "size of the buffer"], ], - (["return value", "the number of bytes read to the buffer (can truncate if filled), -1 is returned On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "the number of bytes read to the buffer (can truncate if filled), -1 is returned On error and errno is modified"], ) ), ( @@ -599,10 +599,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change the mode (rwx rwx rwx, set-uid, set-guid, sticky bits) of the file given through a file path", &[ - (["pathname", "path of the file to be altered"], Pointer_To_Text("")), - (["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), + ["pathname", "path of the file to be altered"], + ["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -611,12 +611,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change the mode (rwx rwx rwx, set-uid, set-guid, sticky bits) of the file given through a file descriptor", &[ - (["fd", "file descriptor of the file to be altered"], File_Descriptor("")), + ["fd", "file descriptor of the file to be altered"], // the RWX combination variants are infact a combination of the 3 R W X flags // its not its own variant - (["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), + ["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -625,12 +625,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change the mode (rwx rwx rwx, set-uid, set-guid, sticky bits) of the file given through a file path, in addition to path traversal flags", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the file to be altered"], Pointer_To_Text("")), - (["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], General_Flag(FileMode)), - (["flags", "path traversal flags"], General_Flag(FileChmodAtFlags)), + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the file to be altered"], + ["mode", "directory permissions (rwx rwx rwx, set-uid, set-guid, sticky bits)"], + ["flags", "path traversal flags"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // ( @@ -642,11 +642,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change the owner and group of a given file by its path", &[ - (["pathname", "path of the file to be altered"], Pointer_To_Text("")), - (["owner", "new owner to be set for the file"], Unsigned_Numeric), - (["group", "new group to be set for the file"], Unsigned_Numeric), + ["pathname", "path of the file to be altered"], + ["owner", "new owner to be set for the file"], + ["group", "new group to be set for the file"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -655,11 +655,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change the owner and group of a given file by its file descriptor", &[ - (["fd", "file descriptor of the file to be altered"], File_Descriptor("")), - (["owner", "new owner to be set for the file"], Unsigned_Numeric), - (["group", "new group to be set for the file"], Unsigned_Numeric), + ["fd", "file descriptor of the file to be altered"], + ["owner", "new owner to be set for the file"], + ["group", "new group to be set for the file"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // same as chown but does not recursively follow a symbolic link @@ -670,11 +670,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change the owner and group of a given file by its path without recursing symbolic links", &[ - (["pathname", "path of the file to be altered"], Pointer_To_Text("")), - (["owner", "new owner to be set for the file"], Unsigned_Numeric), - (["group", "new group to be set for the file"], Unsigned_Numeric), + ["pathname", "path of the file to be altered"], + ["owner", "new owner to be set for the file"], + ["group", "new group to be set for the file"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -683,13 +683,13 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "change the owner and group of a given file by its path, with an optional anchor directory, in addition to path traversal flags", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the file to be altered"], Pointer_To_Text("")), - (["owner", "new owner to be set for the file"], Numeric), - (["group", "new group to be set for the file"], Numeric), - (["flags", "path traversal flags"], General_Flag(FileAtFlags)), + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the file to be altered"], + ["owner", "new owner to be set for the file"], + ["group", "new group to be set for the file"], + ["flags", "path traversal flags"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -699,7 +699,7 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "flush all current pending filesystem data and metadata writes", &[], - (["does not return anything", "does not return anything"], Does_Not_Return_Anything) + ["does not return anything", "does not return anything"], ) ), ( @@ -709,9 +709,9 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "flush all current pending filesystem data and metadata writes via a file descriptor within that filesystem", &[ - (["fd", "file descriptor of a file inside the filesystem to be flushed"], File_Descriptor("")), + ["fd", "file descriptor of a file inside the filesystem to be flushed"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -721,9 +721,9 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "flush all current pending data and metadata writes for a specific file", &[ - (["fd", "file descriptor of the file whose pending writes are to be flushed"], File_Descriptor("")), + ["fd", "file descriptor of the file whose pending writes are to be flushed"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // The aim of fdatasync() is to reduce disk activity for applications @@ -735,9 +735,9 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "flush all current pending data writes and ignore non-critical metadata writes for a specific file", &[ - (["fd", "file descriptor of the file whose pending writes are to be flushed"], File_Descriptor("")), + ["fd", "file descriptor of the file whose pending writes are to be flushed"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // ( @@ -765,11 +765,11 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "extend or truncate a file to a precise size", &[ - (["path", "path of the file to be truncated or expanded"], Pointer_To_Text("")), - (["length", "new length of the file"], Length_Of_Bytes_Specific) + ["path", "path of the file to be truncated or expanded"], + ["length", "new length of the file"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -779,10 +779,10 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "extend or truncate a file to a precise size", &[ - (["fd", "file descriptor of the file to be truncated or expanded"], File_Descriptor("")), - (["length", "new length of the file"], Length_Of_Bytes_Specific) + ["fd", "file descriptor of the file to be truncated or expanded"], + ["length", "new length of the file"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // ( @@ -802,9 +802,9 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "close a file descriptor, will no longer refer to any file", &[ - (["fd", "file descriptor of the file to be closed"], File_Descriptor("")) + ["fd", "file descriptor of the file to be closed"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // return information about a file using a path @@ -814,10 +814,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "find information about a file using its path", &[ - (["pathname", "path of the file, CWD is used as anchor if relative"], Pointer_To_Text("")), - (["statbuf", "pointer to a buffer which will contain the information about the file upon success"], Pointer_To_Struct) + ["pathname", "path of the file, CWD is used as anchor if relative"], + ["statbuf", "pointer to a buffer which will contain the information about the file upon success"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // return information about a file using a file descriptor @@ -827,10 +827,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "find information about a file using a file descriptor", &[ - (["fd", "file descriptor of the file"], File_Descriptor("")), - (["statbuf", "pointer to a buffer which will contain the information about the file upon success"], Pointer_To_Struct) + ["fd", "file descriptor of the file"], + ["statbuf", "pointer to a buffer which will contain the information about the file upon success"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // return information about a file but does not recursively follow a symbolic link @@ -841,10 +841,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "find information about a file using a path without recursing symbolic links", &[ - (["pathname", "path of the file, CWD is used as anchor if relative"], Pointer_To_Text("")), - (["statbuf", "pointer to a buffer which will contain the information about the file upon success"], Pointer_To_Struct) + ["pathname", "path of the file, CWD is used as anchor if relative"], + ["statbuf", "pointer to a buffer which will contain the information about the file upon success"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -853,12 +853,12 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "find information about a file using its path, while specifying an anchor, and path resolution flags", &[ - (["dirfd", "file descriptor used either as anchor for pathname, or as a target file"], File_Descriptor("")), - (["pathname", "path of the file"], Pointer_To_Text("")), - (["statbuf", "pointer to a struct where the retrieved information will be stored"], Pointer_To_Struct), - (["flags", "path resolution behaviour"], General_Flag(FileAtFlags)), + ["dirfd", "file descriptor used either as anchor for pathname, or as a target file"], + ["pathname", "path of the file"], + ["statbuf", "pointer to a struct where the retrieved information will be stored"], + ["flags", "path resolution behaviour"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -867,13 +867,13 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "find information about a file using its path, while specifying an anchor, path resolution flags, and specific fields to retrieve", &[ - (["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], File_Descriptor("")), - (["pathname", "path of the file"], Pointer_To_Text("")), - (["flags", "path resolution behaviour"], General_Flag(FileAtFlags)), - (["mask", "mask specifying the fields of interest to be retrieved"], General_Flag(FileStatxFlags)), - (["statxbuf", "pointer to a struct where the retrieved information will be stored"], Pointer_To_Struct), + ["dirfd", "file descriptor of a path to use as anchor if pathname is relative"], + ["pathname", "path of the file"], + ["flags", "path resolution behaviour"], + ["mask", "mask specifying the fields of interest to be retrieved"], + ["statxbuf", "pointer to a struct where the retrieved information will be stored"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -882,10 +882,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "get information about a specific filesystem using a path", &[ - (["path", "path of the mounted file system"], Pointer_To_Text("")), - (["buf", "pointer to a struct where the retrieved information will be stored"], Pointer_To_Struct), + ["path", "path of the mounted file system"], + ["buf", "pointer to a struct where the retrieved information will be stored"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -894,10 +894,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "get information about a specific filesystem using a file descriptor", &[ - (["fd", "file descriptor of the mounted file system"], File_Descriptor("")), - (["buf", "pointer to a struct where the retrieved information will be stored"], Pointer_To_Struct), + ["fd", "file descriptor of the mounted file system"], + ["buf", "pointer to a struct where the retrieved information will be stored"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -907,10 +907,10 @@ pub fn initialize_syscall_map() -> HashMap { Device, "", &[ - (["dev", "number of the device where a filesystem is mounted"], Unsigned_Numeric), - (["ubuf", "pointer to a struct where the retrieved information will be stored"], Pointer_To_Struct), + ["dev", "number of the device where a filesystem is mounted"], + ["ubuf", "pointer to a struct where the retrieved information will be stored"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -919,15 +919,15 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "get information about the page cache of a file", &[ - (["fd", "file descriptor of the target file"], File_Descriptor("")), + ["fd", "file descriptor of the target file"], // pages ceil - (["cachestat_range", "pointer to a struct identifying the offset and range of bytes to find information about, pages ceil"], Pointer_To_Struct), - (["cachestat", "pointer to a struct where the page caches information will be stored"], Pointer_To_Struct), + ["cachestat_range", "pointer to a struct identifying the offset and range of bytes to find information about, pages ceil"], + ["cachestat", "pointer to a struct where the page caches information will be stored"], // Some unknown flag argument - (["flags", "some flag semantics"], General_Flag(ReservedForFutureUse)), + ["flags", "some flag semantics"], ], // unknown for now error value - (["return value", "some error semantics"], Numeric_Or_Errno) + ["return value", "some error semantics"], ) ), @@ -942,11 +942,11 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "reposition read/write file offset", &[ - (["fd", "file descriptor"], File_Descriptor("")), - (["offset", "new offset count"], Length_Of_Bytes_Specific), - (["whence", "determine usage of the offset (offset as new position vs offset as addititon to current position vs ... etc)"], General_Flag(LSeekWhence)) + ["fd", "file descriptor"], + ["offset", "new offset count"], + ["whence", "determine usage of the offset (offset as new position vs offset as addititon to current position vs ... etc)"], ], - (["return value", "on success returns resulting offset location as measured in bytes from the beginning of the file. (off_t) -1 is returned On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "on success returns resulting offset location as measured in bytes from the beginning of the file. (off_t) -1 is returned On error and errno is modified"], ) ), ( @@ -956,15 +956,15 @@ pub fn initialize_syscall_map() -> HashMap { "create a memory mapping potentially backed by a file", &[ // Nullable - (["addr", "hint for the starting address of the memory map"], Address), - (["len", "amount of bytes to be mapped"], Length_Of_Bytes_Page_Aligned_Ceil), + ["addr", "hint for the starting address of the memory map"], + ["len", "amount of bytes to be mapped"], // must not conflict with the open mode of the file - (["prot", "memory protection flags"], General_Flag(Prot)), - (["flags", "memory mapping flags"], General_Flag(Map)), - (["fd", "file descriptor of the file to be mapped"], File_Descriptor("")), - (["off", "offset of where the mapping must start"], Length_Of_Bytes_Specific), + ["prot", "memory protection flags"], + ["flags", "memory mapping flags"], + ["fd", "file descriptor of the file to be mapped"], + ["off", "offset of where the mapping must start"], ], - (["return value", "on success: pointer to the mapped area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is modified"],Address_Or_MAP_FAILED_Errno("")), + ["return value", "on success: pointer to the mapped area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is modified"], ) ), // set protection on a region of memory @@ -974,11 +974,11 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "set protection on a region of memory", &[ - (["start", "starting address of the range to be protected"], Address), - (["len", "amount of bytes to be protected, memory pages ceil"], Length_Of_Bytes_Page_Aligned_Ceil), - (["prot", "protection/access flags"], General_Flag(Prot)), + ["start", "starting address of the range to be protected"], + ["len", "amount of bytes to be protected, memory pages ceil"], + ["prot", "protection/access flags"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), // deletes the mappings for the specified address range @@ -988,10 +988,10 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "unmap previously mmapped region of memory", &[ - (["addr", "address where memory unmapping will begin"], Address), - (["len", "amount of bytes to be unmapped from memory"], Length_Of_Bytes_Page_Aligned_Ceil) + ["addr", "address where memory unmapping will begin"], + ["len", "amount of bytes to be unmapped from memory"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1000,12 +1000,12 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "change the location of the program break", &[ - (["address", "new program break address"], Address), + ["address", "new program break address"], ], // However, the actual Linux system call returns the new program break on success. // On failure, the system call returns the current break. // to know if an error occured you have to store the previous program break point somewhere to compare - (["return value", "new program break pointer on success, -1 on error and errno ENOMEM only"],Address_Or_Errno("")) + ["return value", "new program break pointer on success, -1 on error and errno ENOMEM only"], ) ), ( @@ -1014,11 +1014,11 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "lock a range of memory in RAM, to prevent swapping", &[ - (["addr", "starting address of the memory to be locked"], Address), + ["addr", "starting address of the memory to be locked"], // Pages Ceil - (["len", "amount of bytes of memory to lock beginning from the addr, pages ceil"], Length_Of_Bytes_Page_Aligned_Ceil), + ["len", "amount of bytes of memory to lock beginning from the addr, pages ceil"], ], - (["return value", "0 success. -1 for error and errno modified and no changes made"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified and no changes made"], ) ), // mlock2 is linux specific @@ -1028,18 +1028,18 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "lock a range of memory in RAM to prevent swapping, in addition to a flag that specifies how to handle non-resident pages", &[ - (["addr", "starting address of the memory to be locked"], Address), + ["addr", "starting address of the memory to be locked"], // Pages Ceil - (["len", "amount of bytes of memory to lock beginning from the addr, pages ceil"], Length_Of_Bytes_Page_Aligned_Ceil), + ["len", "amount of bytes of memory to lock beginning from the addr, pages ceil"], // if flag is 0 mlock2 is identical to mlock // MLOCK_ONFAULT // Lock the pages that are currently resident // and mark the entire range including non-resident pages // so that when they are later populated by a page fault // they get locked - (["flags", "flag that addresses handling non-resident pages"], General_Flag(MLock)), + ["flags", "flag that addresses handling non-resident pages"], ], - (["return value", "0 success. -1 for error and errno modified and no changes made"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified and no changes made"], ) ), @@ -1050,11 +1050,11 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "unlock a memory range and allow it to be swappable", &[ - (["addr", "starting address of the memory to be unlocked"], Address), + ["addr", "starting address of the memory to be unlocked"], // Pages Ceil - (["len", "amount of bytes of memory to unlock beginning from the addr, pages ceil"], Length_Of_Bytes_Page_Aligned_Ceil), + ["len", "amount of bytes of memory to unlock beginning from the addr, pages ceil"], ], - (["return value", "0 success. -1 for error and errno modified and no changes made"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified and no changes made"], ) ), ( @@ -1065,9 +1065,9 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "lock the entire memory of a process to prevent swapping, in addition to flags for handling non-resident and future pages", &[ - (["flags", "flags that addresses handling non-resident and future pages"], General_Flag(MLockAll)), + ["flags", "flags that addresses handling non-resident and future pages"], ], - (["return value", "0 success. -1 for error and errno modified and no changes made"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified and no changes made"], ) ), ( @@ -1077,7 +1077,7 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "unlock the entire memory of a process, allowing it to be swappable", &[], - (["return value", "0 success. -1 for error and errno modified and no changes made"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified and no changes made"], ) ), // expands (or shrinks) an existing memory mapping, potentially moving it at the same time @@ -1088,13 +1088,13 @@ pub fn initialize_syscall_map() -> HashMap { "shrink or expand or move memory region", &[ // must be page aligned - (["old_address", "old address of the memory region to be shrinked, expanded, or moved"], Address), - (["old_len", "old amount of bytes"], Length_Of_Bytes_Page_Aligned_Ceil), - (["new_len", "new amount of bytes"], Length_Of_Bytes_Page_Aligned_Ceil), - (["flags", "remapping flags"], General_Flag(ReMap)), - (["new_address", "new address in the case where the mapping is moved"], Address), + ["old_address", "old address of the memory region to be shrinked, expanded, or moved"], + ["old_len", "old amount of bytes"], + ["new_len", "new amount of bytes"], + ["flags", "remapping flags"], + ["new_address", "new address in the case where the mapping is moved"], ], - (["return value", "on success: pointer to the mapped area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is modified"],Address_Or_MAP_FAILED_Errno("")), + ["return value", "on success: pointer to the mapped area. On error, the value MAP_FAILED (that is, (void *) -1) is returned, and errno is modified"], ) ), // flushes changes made to the file copy mapped in memory back to the filesystem. @@ -1103,11 +1103,11 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "flush changes made in an mmapped memory range back to the filesystem", &[ - (["address", "address in the file mapping where flushing starts"], Address), - (["length", "amount of bytes from the beginning address to be flushed"], Length_Of_Bytes_Page_Aligned_Ceil), - (["flags", "flushing flags"], General_Flag(MSync)) + ["address", "address in the file mapping where flushing starts"], + ["length", "amount of bytes from the beginning address to be flushed"], + ["flags", "flushing flags"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), // returns a vector that represent whether pages of the calling process's virtual memory @@ -1119,11 +1119,11 @@ pub fn initialize_syscall_map() -> HashMap { Memory, "indicate in a vector which parts of a memory range are resident and which will cause a page fault if accessed", &[ - (["addr", "address in the file mapping where calculation starts"], Address), - (["length", "amount of bytes from beginning address where the calculation of resident pages will consider"], Length_Of_Bytes_Page_Aligned_Ceil), - (["vec", "pointer to array of bytes each represents a memory page, every byte indicates if the respective page is resident"], Byte_Stream) + ["addr", "address in the file mapping where calculation starts"], + ["length", "amount of bytes from beginning address where the calculation of resident pages will consider"], + ["vec", "pointer to array of bytes each represents a memory page, every byte indicates if the respective page is resident"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), // give advice about use of memory @@ -1135,11 +1135,11 @@ pub fn initialize_syscall_map() -> HashMap { &[ // only operates on whole pages // so must be page aligned - (["addr", "beginning of the memory range where the advice is applied"], Address), - (["length", "amount of bytes from beginning address indicating the range where the advice should be taken in consideration"], Length_Of_Bytes_Page_Aligned_Ceil), - (["advice", "memory advice flags"], General_Flag(Madvise)) + ["addr", "beginning of the memory range where the advice is applied"], + ["length", "amount of bytes from beginning address indicating the range where the advice should be taken in consideration"], + ["advice", "memory advice flags"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), @@ -1149,19 +1149,19 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "block while watching file descriptor sets for readiness to read, write, in addition to exceptional conditions", &[ - (["nfds", "the number of the highest file descriptor in the three sets + 1, used by the kernel to loop each set"], Numeric), + ["nfds", "the number of the highest file descriptor in the three sets + 1, used by the kernel to loop each set"], // you can set any of these sets to NULL if you don’t care about waiting for it - (["readfds", "pointer to struct containing an array of file descriptors watched to see if they are ready for reading"], Pointer_To_Struct), - (["writefds,", "pointer to struct containing an array of file descriptors watched to see if they are ready for writing"], Pointer_To_Struct), - (["exceptfds,", "pointer to struct containing an array of file descriptors in this set are watched for \"exceptional conditions\""], Pointer_To_Struct), + ["readfds", "pointer to struct containing an array of file descriptors watched to see if they are ready for reading"], + ["writefds,", "pointer to struct containing an array of file descriptors watched to see if they are ready for writing"], + ["exceptfds,", "pointer to struct containing an array of file descriptors in this set are watched for \"exceptional conditions\""], // Some Unices update the timeout here to show how much time is left, not all of them // If you set the fields in your struct timeval to 0, // select() will timeout immediately, effectively polling all the file descriptors in your sets. // If you set the parameter timeout to NULL, // it will wait forever until the first file descriptor is ready. - (["timeout", "pointer to struct describing the amount of time select will block in microseconds"], Pointer_To_Struct), + ["timeout", "pointer to struct describing the amount of time select will block in microseconds"], ], - (["retrun value", "total number of file descriptors in all sets, 0 if timeout expired before any file descriptors became ready, On error -1, and errno modified, file descriptor sets are left unmodified, and timeout becomes undefined"], Numeric_Or_Errno), + ["retrun value", "total number of file descriptors in all sets, 0 if timeout expired before any file descriptors became ready, On error -1, and errno modified, file descriptor sets are left unmodified, and timeout becomes undefined"], ) ), ( @@ -1170,25 +1170,25 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "block while watching file descriptor sets for readiness to read, write, in addition to exceptional conditions, and watch for new signals", &[ - (["nfds", "the number of the highest file descriptor in the three sets + 1, used by the kernel to loop each set"], Numeric), + ["nfds", "the number of the highest file descriptor in the three sets + 1, used by the kernel to loop each set"], // you can set any of these sets to NULL if you don’t care about waiting for it - (["readfds", "pointer to struct containing an array of file descriptors watched to see if they are ready for reading"], Pointer_To_Struct), - (["writefds,", "pointer to struct containing an array of file descriptors watched to see if they are ready for writing"], Pointer_To_Struct), - (["exceptfds,", "pointer to struct containing an array of file descriptors in this set are watched for \"exceptional conditions\""], Pointer_To_Struct), + ["readfds", "pointer to struct containing an array of file descriptors watched to see if they are ready for reading"], + ["writefds,", "pointer to struct containing an array of file descriptors watched to see if they are ready for writing"], + ["exceptfds,", "pointer to struct containing an array of file descriptors in this set are watched for \"exceptional conditions\""], // pselect never updates timeout to indicate how much time is left (normal select does that in some unices) // If you set the fields in your struct timeval to 0, // select() will timeout immediately, effectively polling all the file descriptors in your sets. // If you set the parameter timeout to NULL, // it will wait forever until the first file descriptor is ready. - (["timeout", "pointer to struct describing the amount of time select will block in nanoseconds"], Pointer_To_Struct), + ["timeout", "pointer to struct describing the amount of time select will block in nanoseconds"], // The final argument of the pselect6() system call is not a sigset_t * pointer, but is instead a structure of the form: // struct { // const kernel_sigset_t *ss; /* Pointer to signal set */ // size_t ss_len; /* Size (in bytes) of object pointed to by 'ss' */ // }; - (["sig", "pointer to struct containing both the signal mask to watch for and its size"], Pointer_To_Struct), + ["sig", "pointer to struct containing both the signal mask to watch for and its size"], ], - (["retrun value", "total number of file descriptors in all sets, 0 if timeout expired before any file descriptors became ready, On error -1, and errno modified, file descriptor sets are left unmodified, and timeout becomes undefined"], Numeric_Or_Errno), + ["retrun value", "total number of file descriptors in all sets, 0 if timeout expired before any file descriptors became ready, On error -1, and errno modified, file descriptor sets are left unmodified, and timeout becomes undefined"], ) ), ( @@ -1197,12 +1197,12 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "block until specific events occur on the provided file descriptors", &[ - (["fds", "array of file descriptor-event pairs for poll to monitor"], Array_Of_Struct), - (["nfds", "number of elements in pollfd"], Unsigned_Numeric), - (["timeout_msecs", "amount of time for poll to block in milliseconds"], Numeric), + ["fds", "array of file descriptor-event pairs for poll to monitor"], + ["nfds", "number of elements in pollfd"], + ["timeout_msecs", "amount of time for poll to block in milliseconds"], ], // It doesn’t tell you which elements (you still have to scan for that), it only tell you how many, - (["return value", "number of elements in nfds for which events have occurred, -1 on error, errno modified"], Numeric_Or_Errno), + ["return value", "number of elements in nfds for which events have occurred, -1 on error, errno modified"], ) ), ( @@ -1211,16 +1211,16 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "block until specific events occur on the provided file descriptors or until some signals are caught", &[ - (["fds", "array of file descriptor-event pairs for poll to monitor"], Array_Of_Struct), - (["nfds", "number of elements in pollfd"], Unsigned_Numeric), - (["tmo_p", "pointer to struct containing amount of time to block in nanoseconds"], Pointer_To_Struct), + ["fds", "array of file descriptor-event pairs for poll to monitor"], + ["nfds", "number of elements in pollfd"], + ["tmo_p", "pointer to struct containing amount of time to block in nanoseconds"], // if null then no mask manipulation is performed - (["sigmask", "signal mask containing the signals to watch for"], Pointer_To_Struct), - (["sigsetsize", "the size in bytes of the signal mask"], Length_Of_Bytes_Specific) + ["sigmask", "signal mask containing the signals to watch for"], + ["sigsetsize", "the size in bytes of the signal mask"], ], // It doesn’t tell you which elements (you still have to scan for that), // it only tell you how many, - (["return value", "number of elements in nfds for which events have occurred, -1 on error, errno modified"], Numeric_Or_Errno), + ["return value", "number of elements in nfds for which events have occurred, -1 on error, errno modified"], ) ), ( @@ -1235,9 +1235,9 @@ pub fn initialize_syscall_map() -> HashMap { // the kerenl now however does not need that information and instead dynamically allocates space // it is kept for backward compatibility // and must be greater than zero - (["size", "number of fds expected to be added later, this argument is no longer needed, but must not be 0"], Unsigned_Numeric) + ["size", "number of fds expected to be added later, this argument is no longer needed, but must not be 0"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), ( @@ -1250,9 +1250,9 @@ pub fn initialize_syscall_map() -> HashMap { "creates a new epoll instance and return a file descriptor for it, in addition to customizing behaviour with a flag", &[ // if this argument is zero, this syscall is identical to epoll_create - (["flags", "flags for different epoll behaviours"], General_Flag(EPollCreate1Flags)), + ["flags", "flags for different epoll behaviours"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), ( @@ -1265,16 +1265,16 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "block and wait for events on an epoll instance, equivalent to fetching from the ready list", &[ - (["epfd", "file descriptor of the epoll instance to be waited on"], File_Descriptor("")), - (["epoll_event", "buffer where information about ready file descriptors will be stored"], Pointer_To_Struct), - (["maxevents", "maximum number of events to be returned from the epoll instance"], Unsigned_Numeric), + ["epfd", "file descriptor of the epoll instance to be waited on"], + ["epoll_event", "buffer where information about ready file descriptors will be stored"], + ["maxevents", "maximum number of events to be returned from the epoll instance"], // Time is measured against the CLOCK_MONOTONIC clock // timeout interval will be rounded up to the system clock granularity // -1 means block indefinitely // 0 means return immediately - (["timeout", "amount of time for epoll to block in milliseconds"], Numeric), + ["timeout", "amount of time for epoll to block in milliseconds"], ], - (["return value", "number of file descriptors ready for the requested I/O,"], Numeric_Or_Errno) + ["return value", "number of file descriptors ready for the requested I/O,"], ) ), ( @@ -1284,19 +1284,19 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "block and wait until either an event on the epoll instance or a signal, equivalent to fetching from the ready list or waiting for a signal", &[ - (["epfd", "file descriptor of the epoll instance to be waited on"], File_Descriptor("")), - (["events", "buffer where information about ready file descriptors will be stored"], Pointer_To_Struct), - (["maxevents", "maximum number of events to be returned from the epoll instance"], Unsigned_Numeric), + ["epfd", "file descriptor of the epoll instance to be waited on"], + ["events", "buffer where information about ready file descriptors will be stored"], + ["maxevents", "maximum number of events to be returned from the epoll instance"], // Time is measured against the CLOCK_MONOTONIC clock // timeout interval will be rounded up to the system clock granularity // -1 means block indefinitely // 0 means return immediately - (["timeout", "amount of time for epoll to block in milliseconds"], Numeric), + ["timeout", "amount of time for epoll to block in milliseconds"], // if null this syscall is equivalent to epoll_pwait - (["sigmask", "signal mask containing the signals to watch for"], Pointer_To_Struct), - (["sigsetsize", "the size in bytes of the signal mask"], Length_Of_Bytes_Specific) + ["sigmask", "signal mask containing the signals to watch for"], + ["sigsetsize", "the size in bytes of the signal mask"], ], - (["return value", "number of file descriptors ready for the requested I/O,"], Numeric_Or_Errno) + ["return value", "number of file descriptors ready for the requested I/O,"], ) ), ( @@ -1306,19 +1306,19 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "block and wait until either an event on the epoll instance or a signal, equivalent to fetching from the ready list or waiting for a signal", &[ - (["epfd", "file descriptor of the epoll instance to be waited on"], File_Descriptor("")), - (["events", "buffer where information about ready file descriptors will be stored"], Pointer_To_Struct), - (["maxevents", "maximum number of events to be returned from the epoll instance"], Unsigned_Numeric), + ["epfd", "file descriptor of the epoll instance to be waited on"], + ["events", "buffer where information about ready file descriptors will be stored"], + ["maxevents", "maximum number of events to be returned from the epoll instance"], // Time is measured against the CLOCK_MONOTONIC clock // timeout interval will be rounded up to the system clock granularity // -1 means block indefinitely // 0 means return immediately - (["timeout", "pointer to struct containing amount of time to block in nanoseconds"], Pointer_To_Struct), + ["timeout", "pointer to struct containing amount of time to block in nanoseconds"], // if null this syscall is equivalent to epoll_pwait - (["sigmask", "signal mask containing the signals to watch for"], Pointer_To_Struct), - (["sigsetsize", "the size in bytes of the signal mask"], Length_Of_Bytes_Specific) + ["sigmask", "signal mask containing the signals to watch for"], + ["sigsetsize", "the size in bytes of the signal mask"], ], - (["return value", "number of file descriptors ready for the requested I/O,"], Numeric_Or_Errno) + ["return value", "number of file descriptors ready for the requested I/O,"], ) ), ( @@ -1327,12 +1327,12 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "add, modify, or remove entries in the interest list of the epoll instance", &[ - (["epfd", "file descriptor of the epoll instance"], File_Descriptor("")), - (["op", "operation to be performed on the epoll instance, add/remove/change"], General_Flag(EPollCTLOperationFlags)), - (["fd", "the file descriptor that the operation refers to"], File_Descriptor("")), - (["event", "struct containing information about the event associated with the operation"], Pointer_To_Struct), + ["epfd", "file descriptor of the epoll instance"], + ["op", "operation to be performed on the epoll instance, add/remove/change"], + ["fd", "the file descriptor that the operation refers to"], + ["event", "struct containing information about the event associated with the operation"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1341,11 +1341,11 @@ pub fn initialize_syscall_map() -> HashMap { Network, "create a socket file descriptor", &[ - (["family", "communication domain (Internet/IPV4, IPV6, Bluetooth, Amateur radio, XDP ..etc)"], General_Flag(SocketFamily)), - (["type", "communication type (Streaming, Datagram, etc..)"], General_Flag(SocketType)), - (["protocol", "specific protocol (TCP, UDP, RAW)"], General_Flag(SocketProtocol)) + ["family", "communication domain (Internet/IPV4, IPV6, Bluetooth, Amateur radio, XDP ..etc)"], + ["type", "communication type (Streaming, Datagram, etc..)"], + ["protocol", "specific protocol (TCP, UDP, RAW)"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), ( @@ -1354,11 +1354,11 @@ pub fn initialize_syscall_map() -> HashMap { Network, "assign an address to a socket file descriptor", &[ - (["sockfd", "file descriptor of the socket to be assigned"], File_Descriptor("")), - (["addr", "struct containing the address which the socket will get assigned"], Pointer_To_Struct), - (["addrlen", "size of the socket address struct in bytes"], Length_Of_Bytes_Specific) + ["sockfd", "file descriptor of the socket to be assigned"], + ["addr", "struct containing the address which the socket will get assigned"], + ["addrlen", "size of the socket address struct in bytes"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1367,16 +1367,16 @@ pub fn initialize_syscall_map() -> HashMap { Network, "get the address a specific socket is bound to", &[ - (["sockfd", "file descriptor of the socket we're getting the address of"], File_Descriptor("")), + ["sockfd", "file descriptor of the socket we're getting the address of"], // The returned information is truncated if the buffer provided is too small (addrlen small) - (["addr", "buffer where retrieved address information will get stored"], Pointer_To_Struct), + ["addr", "buffer where retrieved address information will get stored"], // upon return this pointer gets updated with the length of bytes written in the buffer // but in this case of truncation // it will return a value greater // than was supplied to the call. - (["addrlen", "pointer to integer specifying the length in bytes of the address buffer"], Pointer_To_Length_Of_Bytes_Specific), + ["addrlen", "pointer to integer specifying the length in bytes of the address buffer"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1385,17 +1385,17 @@ pub fn initialize_syscall_map() -> HashMap { Network, "get the address of the peer connected to a specific socket", &[ - (["sockfd", "file descriptor of the socket we're getting peer information of"], File_Descriptor("")), + ["sockfd", "file descriptor of the socket we're getting peer information of"], // The returned information is truncated // if the buffer provided is too small (addrlen small); - (["addr", "buffer where retrieved peer address information will get stored"], Pointer_To_Struct), + ["addr", "buffer where retrieved peer address information will get stored"], // upon return this pointer gets updated with the length of bytes written in the buffer // but in this case of truncation // it will return a value greater // than was supplied to the call. - (["addrlen", "pointer to integer specifying the length in bytes of the address buffer"], Pointer_To_Length_Of_Bytes_Specific), + ["addrlen", "pointer to integer specifying the length in bytes of the address buffer"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1404,14 +1404,14 @@ pub fn initialize_syscall_map() -> HashMap { Network, "create a pair of connected sockets", &[ - (["family", "communication domain (Internet/IPV4, IPV6, Bluetooth, Amateur radio, XDP ..etc)"], General_Flag(SocketFamily)), - (["type", "communication type (Streaming, Datagram, etc..)"], General_Flag(SocketType)), - (["protocol", "specific protocol (TCP, UDP, RAW)"], General_Flag(SocketProtocol)), - // (["sv", "array in which the two created socket descriptors will be stored"],ValueReturn(Pointer_To_File_Descriptor_Array(["", ""]),Pointer_To_File_Descriptor_Array(["", ""])) - (["sv", "array in which the two created socket descriptors will be stored"], Pointer_To_File_Descriptor_Array(["", ""])) + ["family", "communication domain (Internet/IPV4, IPV6, Bluetooth, Amateur radio, XDP ..etc)"], + ["type", "communication type (Streaming, Datagram, etc..)"], + ["protocol", "specific protocol (TCP, UDP, RAW)"], + // (["sv", "array in which the two created socket descriptors will be stored"], + ["sv", "array in which the two created socket descriptors will be stored"], ], // on error sv is left unchanged - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1420,18 +1420,18 @@ pub fn initialize_syscall_map() -> HashMap { Network, "set the options of a socket descriptor", &[ - (["sockfd", "socket descriptor whose options will be manipulated"], File_Descriptor("")), - (["level", "the protocol level in which the option resides"], General_Flag(SocketLevel)), - (["optname", "name of the option"], General_Flag(SocketOption)), + ["sockfd", "socket descriptor whose options will be manipulated"], + ["level", "the protocol level in which the option resides"], + ["optname", "name of the option"], // the argument should be // nonzero to enable a boolean option, // or zero if the option is to be disabled. - (["optval", "buffer containing the new option value to be set"], Pointer_To_Struct), + ["optval", "buffer containing the new option value to be set"], - (["optlen", "pointer to integer specifying the size in bytes of the option value buffer"], Pointer_To_Length_Of_Bytes_Specific), + ["optlen", "pointer to integer specifying the size in bytes of the option value buffer"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1440,18 +1440,18 @@ pub fn initialize_syscall_map() -> HashMap { Network, "retrieve the options of a socket descriptor", &[ - (["sockfd", "socket descriptor whose options will be manipulated"], File_Descriptor("")), - (["level", "the protocol level in which the option resides"], General_Flag(SocketLevel)), - (["optname", "name of the option"], General_Flag(SocketOption)), + ["sockfd", "socket descriptor whose options will be manipulated"], + ["level", "the protocol level in which the option resides"], + ["optname", "name of the option"], - (["optval", "buffer in which the retrieved option value will be stored"], Pointer_To_Struct), + ["optval", "buffer in which the retrieved option value will be stored"], // optlen is a value-result argument // initially containing the size of optval buffer // and on return modified to the actual size of the value returned // can be NULL If no option value is to be supplied or returned, - (["optlen", "pointer to integer specifying the length in bytes of the option value buffer"], Pointer_To_Length_Of_Bytes_Specific), + ["optlen", "pointer to integer specifying the length in bytes of the option value buffer"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), @@ -1461,10 +1461,10 @@ pub fn initialize_syscall_map() -> HashMap { Network, "create a backlog queue, and mark the socket descriptor as passive (ready to accept connections)", &[ - (["sockfd", "file descriptor of the socket to mark"], File_Descriptor("")), - (["backlog", "maximum number of connections the queue must hold"], Numeric) + ["sockfd", "file descriptor of the socket to mark"], + ["backlog", "maximum number of connections the queue must hold"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1473,17 +1473,17 @@ pub fn initialize_syscall_map() -> HashMap { Network, "extract the first connection from the backlog queue", &[ - (["sockfd", "file descriptor of the socket listening for connections"], File_Descriptor("")), + ["sockfd", "file descriptor of the socket listening for connections"], // nullable, and when nullable it is not filled - (["addr", "buffer where information about the peer connection will be stored"], Pointer_To_Struct), + ["addr", "buffer where information about the peer connection will be stored"], // addrlen is a value-result argument // initially containing the size of optval buffer // and on return modified to the actual size of the value returned // can be NULL If no option value is to be supplied or returned, - (["addrlen", "pointer to struct speciiying the size of the addr buffer"], Pointer_To_Struct), + ["addrlen", "pointer to struct speciiying the size of the addr buffer"], ], // -1 on error, errno modified - (["return value", "file descriptor of the new connection that was extracted, -1 for error and errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "file descriptor of the new connection that was extracted, -1 for error and errno modified"], ) ), ( @@ -1495,19 +1495,19 @@ pub fn initialize_syscall_map() -> HashMap { Network, "extract the first connection from the connection queue in addition to specifying behaviour flag such as non-block and close-on-exec", &[ - (["sockfd", "file descriptor of the socket listening for connections"], File_Descriptor("")), + ["sockfd", "file descriptor of the socket listening for connections"], // nullable, and when nullable it is not filled - (["addr", "buffer where information about the peer connection will be stored"], Pointer_To_Struct), + ["addr", "buffer where information about the peer connection will be stored"], // addrlen is a value-result argument // initially containing the size of optval buffer // and on return modified to the actual size of the value returned // can be NULL If no option value is to be supplied or returned, - (["addrlen", "pointer to struct speciiying the size of the addr buffer"], Pointer_To_Struct), + ["addrlen", "pointer to struct speciiying the size of the addr buffer"], // if this flag is 0 then accept4 is identical to accept - (["flags", "?"], General_Flag(SocketFlag)), + ["flags", "?"], ], // -1 on error, errno modified - (["return value", "file descriptor of the new connection that was extracted, -1 for error and errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "file descriptor of the new connection that was extracted, -1 for error and errno modified"], ) ), ( @@ -1516,11 +1516,11 @@ pub fn initialize_syscall_map() -> HashMap { Network, "connect a socket file descriptor to an address", &[ - (["sockfd", "file descriptor of the socket to be connected"], File_Descriptor("")), - (["addr", "struct containing the address to which the socket will connect"], Pointer_To_Struct), - (["addrlen", "size of the socket address struct in bytes"], Length_Of_Bytes_Specific) + ["sockfd", "file descriptor of the socket to be connected"], + ["addr", "struct containing the address to which the socket will connect"], + ["addrlen", "size of the socket address struct in bytes"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -1529,17 +1529,17 @@ pub fn initialize_syscall_map() -> HashMap { Network, "send a message to another socket", &[ - (["sockfd", "file descriptor of the sending socket"], File_Descriptor("")), - (["buf", "pointer to a buffer containing the message to be sent and the length of the message"], Pointer_To_Text("")), - (["len", "size of the message buffer in bytes"], Length_Of_Bytes_Specific), - (["flags", "flags to customize syscall behaviour"], General_Flag(SocketMessageFlag)), + ["sockfd", "file descriptor of the sending socket"], + ["buf", "pointer to a buffer containing the message to be sent and the length of the message"], + ["len", "size of the message buffer in bytes"], + ["flags", "flags to customize syscall behaviour"], // WILL BE USED if connection-less (like UDP) // WILL BE IGNORED if connection-mode (like TCP, or SEQ) and must be null or 0 - (["dest_addr", "address of the target socket"], Pointer_To_Struct), + ["dest_addr", "address of the target socket"], // IGNORED if connection-mode (like TCP, or SEQ) (UDP IS CONNECTIONLESS) and must be null or 0 - (["addr_len", "size of the destination address struct in bytes"], Length_Of_Bytes_Specific), + ["addr_len", "size of the destination address struct in bytes"], ], - (["return value", "number of bytes written, 0 means end of file, -1 means error, and errno modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "number of bytes written, 0 means end of file, -1 means error, and errno modified"], ) ), ( @@ -1548,11 +1548,11 @@ pub fn initialize_syscall_map() -> HashMap { Network, "send a message to another socket", &[ - (["sockfd", "file descriptor of the sending socket"], File_Descriptor("")), - (["msg", "pointer to struct containing the target socket address, the size of the struct, and an array containing the message to be sent"], Pointer_To_Struct), - (["flags", "flags to customize syscall behaviour"], General_Flag(SocketMessageFlag)) + ["sockfd", "file descriptor of the sending socket"], + ["msg", "pointer to struct containing the target socket address, the size of the struct, and an array containing the message to be sent"], + ["flags", "flags to customize syscall behaviour"], ], - (["return value", "number of bytes written, 0 means end of file, -1 means error, and errno modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "number of bytes written, 0 means end of file, -1 means error, and errno modified"], ) ), ( @@ -1561,21 +1561,21 @@ pub fn initialize_syscall_map() -> HashMap { Network, "receive a message from a socket", &[ - (["sockfd", "file descriptor of the socket to receive data from"], File_Descriptor("")), + ["sockfd", "file descriptor of the socket to receive data from"], // If a message is too long to fit in the supplied buffer, // excess bytes may be discarded depending // on the type of socket the message is received from. - (["buf", "buffer in which the received data will be stored"], Pointer_To_Text("")), - (["len", "size in bytes of the buffer"], Length_Of_Bytes_Specific), - (["flags", "?"], General_Flag(SocketMessageReceiveFlag)), + ["buf", "buffer in which the received data will be stored"], + ["len", "size in bytes of the buffer"], + ["flags", "?"], // if src_addr and addrlen are NULL // it means we do not care or want src_addr details // otherwise addrlen is value-result argument - (["src_addr", "buffer which will contain the source address of the socket we received the data from"], Pointer_To_Struct), + ["src_addr", "buffer which will contain the source address of the socket we received the data from"], // value-result argument, will become the length of the buffer, and truncation rules apply - (["addrlen", "size of the source address buffer"], Pointer_To_Struct), + ["addrlen", "size of the source address buffer"], ], - (["return value", "number of bytes written, 0 means zero-length datagrams which are permitted, -1 means error, and errno modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "number of bytes written, 0 means zero-length datagrams which are permitted, -1 means error, and errno modified"], ) ), ( @@ -1584,14 +1584,14 @@ pub fn initialize_syscall_map() -> HashMap { Network, "receive a message from a socket", &[ - (["sockfd", "file descriptor of the socket to receive data from"], File_Descriptor("")), + ["sockfd", "file descriptor of the socket to receive data from"], // If a message is too long to fit in the supplied buffer, // excess bytes may be discarded depending // on the type of socket the message is received from. - (["msg", "pointer to a struct containing the details of data received including scatter-gather buffer and length information"], Pointer_To_Struct), - (["flags", "?"], General_Flag(SocketMessageFlag)) + ["msg", "pointer to a struct containing the details of data received including scatter-gather buffer and length information"], + ["flags", "?"], ], - (["return value", "number of bytes written, 0 means zero-length datagrams which are permitted, -1 means error, and errno modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "number of bytes written, 0 means zero-length datagrams which are permitted, -1 means error, and errno modified"], ) ), ( @@ -1600,10 +1600,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "shut down a socket connection full or partially", &[ - (["sockfd", "file descriptor of the affected socket"], File_Descriptor("")), - (["how", "flag specificying shutdown domain"], General_Flag(SocketShutdownFlag)) + ["sockfd", "file descriptor of the affected socket"], + ["how", "flag specificying shutdown domain"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno), + ["return value", "0 success. -1 for error and errno modified"], ) ), // ( @@ -1615,11 +1615,11 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "perform a file operation on a file", &[ - (["fd", "the file descriptor to be operated on"], File_Descriptor("")), - (["op", "specific operation to be performed"], General_Flag(FcntlFlags)), - (["arg", "optional argument varying depending on the operation"], Pointer_To_Struct), + ["fd", "the file descriptor to be operated on"], + ["op", "specific operation to be performed"], + ["arg", "optional argument varying depending on the operation"], ], - (["return value", "0 on success (sometimes this is a output value), -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "0 on success (sometimes this is a output value), -1 on error, errno modified"], ) ), ( @@ -1628,15 +1628,15 @@ pub fn initialize_syscall_map() -> HashMap { Device, "carry out a specific operation/request on a device", &[ - (["fd", "file descriptor of the device"], File_Descriptor("")), - (["request", "code of the specific request to be carried out"], Unsigned_Numeric), + ["fd", "file descriptor of the device"], + ["request", "code of the specific request to be carried out"], // The arg parameter to the ioctl is opaque at the generic vfs level (an opaque data type is a data type whose concrete data structure is not defined in an interface) // How to interpret it is up to the driver or filesystem that actually handles it // So it may be a pointer to userspace memory, or it could be an index, a flag, whatever // It might even be unused and conventionally passed in a 0 - (["argp", "typeless extra argument, the driver defineds it, and can vary based on what the driver wants"], Pointer_To_Struct), + ["argp", "typeless extra argument, the driver defineds it, and can vary based on what the driver wants"], ], - (["return value", "0 on success (sometimes this is a output value), -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "0 on success (sometimes this is a output value), -1 on error, errno modified"], ) ), @@ -1649,12 +1649,12 @@ pub fn initialize_syscall_map() -> HashMap { Process, "set architecture-specific process/thread state", &[ - (["op", "specific operation to perform"], General_Flag(ArchPrctlFlags)), + ["op", "specific operation to perform"], // TODO! this argument is a number for set operations and a pointer to a number for get operations // Pointer_To_Numeric_Or_Numeric is a special case for arch_prctl, because it depends on the op union - (["addr", "can be either an unsigned long for set operations, or a pointer to unsigned long for get operations"], Pointer_To_Numeric_Or_Numeric(None)), + ["addr", "can be either an unsigned long for set operations, or a pointer to unsigned long for get operations"], ], - (["return value", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "0 on success, -1 on error, errno modified"], ) ), // causes the calling thread to relinquish the CPU. @@ -1665,7 +1665,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "relinquish the CPU, and move to the end of the queue", &[], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1675,13 +1675,13 @@ pub fn initialize_syscall_map() -> HashMap { "change action for a specific signal", &[ // can be any valid signal except SIGKILL and SIGSTOP. - (["signum", "specific signal for which the action should be changed"], General_Flag(Signal)), - (["act", "sigaction struct where new action to take is specified"], Pointer_To_Struct), + ["signum", "specific signal for which the action should be changed"], + ["act", "sigaction struct where new action to take is specified"], // nullable meaning we dont want it - (["oldact", "pointe to struct where the old sigaction struct will be saved"], Pointer_To_Struct), - (["sigsetsize", "size of the signal sets in the action mask and the old action mask"], Length_Of_Bytes_Specific), + ["oldact", "pointe to struct where the old sigaction struct will be saved"], + ["sigsetsize", "size of the signal sets in the action mask and the old action mask"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1690,14 +1690,14 @@ pub fn initialize_syscall_map() -> HashMap { Signals, "modify or get the signal mask (signals blocked from delivery) of the calling thread", &[ - (["how", "specific signal for which the action should be changed"], General_Flag(SignalHow)), + ["how", "specific signal for which the action should be changed"], // If NULL, then the signal mask is unchanged. - (["set", "sigaction struct where new action to take is specified"], Pointer_To_Struct), + ["set", "sigaction struct where new action to take is specified"], // If non-NULL, the previous value of the mask is stored here. - (["oldset", "sigaction struct where new action to take is specified"], Pointer_To_Struct), - (["sigsetsize", "size of the signal sets in the new set and the old set"], Length_Of_Bytes_Specific), + ["oldset", "sigaction struct where new action to take is specified"], + ["sigsetsize", "size of the signal sets in the new set and the old set"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1711,11 +1711,11 @@ pub fn initialize_syscall_map() -> HashMap { "temporarily alter the signal mask of the process, and suspend execution until the delivery of a signal that has a handler or one that terminates the thread", &[ // SIGKILL or SIGSTOP can not be blocked - (["mask", "new temporary mask to be set"], Pointer_To_Struct), - (["sigsetsize", "size of the mask struct in bytes"], Length_Of_Bytes_Specific) + ["mask", "new temporary mask to be set"], + ["sigsetsize", "size of the mask struct in bytes"], ], // always returns -1, with errno set to indicate the error (normally, EINTR) - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1729,11 +1729,11 @@ pub fn initialize_syscall_map() -> HashMap { "define an alternative signal stack or retrieve the state of the current one", &[ // can be null if dont want this part of the operation - (["ss", "pointer to a struct containing information about the new signal stack to use"], Pointer_To_Struct), + ["ss", "pointer to a struct containing information about the new signal stack to use"], // NULLABLE meaning we dont want it - (["old_ss", "pointer to an empty signal stack struct to store the old signal stack information"], Pointer_To_Struct), + ["old_ss", "pointer to an empty signal stack struct to store the old signal stack information"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1743,7 +1743,7 @@ pub fn initialize_syscall_map() -> HashMap { Signals, "return from signal handler and cleanup stack frame", &[], - (["", ""], Never_Returns) + ["", ""], ) ), ( @@ -1752,10 +1752,10 @@ pub fn initialize_syscall_map() -> HashMap { Signals, "return the set of signals pending for delivery for the calling thread", &[ - (["set", "pointer to struct set where the signals will be stored"], Pointer_To_Struct), - (["sigsetsize", "size of the set struct in bytes"], Length_Of_Bytes_Specific) + ["set", "pointer to struct set where the signals will be stored"], + ["sigsetsize", "size of the set struct in bytes"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1764,13 +1764,13 @@ pub fn initialize_syscall_map() -> HashMap { Signals, "suspends execution of the process until one of the signals provided is pending, or a given timeout is exceeded", &[ - (["set", "pointer to struct containing the set of signals to check for"], Pointer_To_Struct), + ["set", "pointer to struct containing the set of signals to check for"], // NULLABLE - (["info", "pointer to struct where information about the signals found will be stored"], Pointer_To_Struct), - (["timeout", "pointer to struct containing amount of time to block in nanoseconds"], Pointer_To_Struct), - (["sigsetsize", "size of the set struct in bytes"], Length_Of_Bytes_Specific) + ["info", "pointer to struct where information about the signals found will be stored"], + ["timeout", "pointer to struct containing amount of time to block in nanoseconds"], + ["sigsetsize", "size of the set struct in bytes"], ], - (["signal", "signal number on success, -1 on error, errno modified"],Signal_Or_Errno("")) + ["signal", "signal number on success, -1 on error, errno modified"], ) ), ( @@ -1781,11 +1781,11 @@ pub fn initialize_syscall_map() -> HashMap { Signals, "send a signal plus data to a process/thread group", &[ - (["tgid", "id of the thread group where the signal will be sent"], PID), - (["sig", "the signal to be sent"], General_Flag(Signal)), - (["info", "address of the struct containing the data to be sent"], Pointer_To_Struct), + ["tgid", "id of the thread group where the signal will be sent"], + ["sig", "the signal to be sent"], + ["info", "address of the struct containing the data to be sent"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1796,12 +1796,12 @@ pub fn initialize_syscall_map() -> HashMap { Signals, "send a signal plus data to a specific thread within a process/thread group", &[ - (["tgid", "id of the thread group where the signal will be sent"], PID), - (["pid", "id of the specific thread in the thread group"], PID), - (["sig", "the signal to be sent"], General_Flag(Signal)), - (["info", "address of the struct containing the data to be sent"], Pointer_To_Struct), + ["tgid", "id of the thread group where the signal will be sent"], + ["pid", "id of the specific thread in the thread group"], + ["sig", "the signal to be sent"], + ["info", "address of the struct containing the data to be sent"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1811,12 +1811,12 @@ pub fn initialize_syscall_map() -> HashMap { "create a new file for accepting signals", &[ // fd of a file, or -1, let the kernel create a new file descriptor - (["fd", "file descriptor of the file to be used to receive signals"], File_Descriptor("")), + ["fd", "file descriptor of the file to be used to receive signals"], // It is not possible to receive SIGKILL or SIGSTOP // SIGKILL or SIGSTOP can not be blocked - (["mask", "the set of signals to be accept via the file descriptor"], Pointer_To_Struct), + ["mask", "the set of signals to be accept via the file descriptor"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), ( @@ -1826,13 +1826,13 @@ pub fn initialize_syscall_map() -> HashMap { "create a file descriptor for accepting signals, in addition to file customization flags", &[ // fd of a file, or -1, let the kernel create a new file descriptor - (["fd", "file descriptor of the file to be used to receive signals"], File_Descriptor("")), + ["fd", "file descriptor of the file to be used to receive signals"], // It is not possible to receive SIGKILL or SIGSTOP // SIGKILL or SIGSTOP can not be blocked - (["mask", "the set of signals to be accept via the file descriptor"], Pointer_To_Struct), - (["flags", "flags to customize the file descriptor"], General_Flag(SignalFDFlags)) + ["mask", "the set of signals to be accept via the file descriptor"], + ["flags", "flags to customize the file descriptor"], ], - (["return value", "-1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "-1 on error, errno modified"], ) ), // The pidfd_open syscall allows users to obtain a file descriptor referring to the PID of the specified process. @@ -1845,15 +1845,15 @@ pub fn initialize_syscall_map() -> HashMap { Signals, "send a signal to a process specified by a file descriptor", &[ - (["pidfd", "file descriptor of the process of where the siganl is to be sent"], File_Descriptor("")), - (["sig", "signal to be sent"], General_Flag(Signal)), + ["pidfd", "file descriptor of the process of where the siganl is to be sent"], + ["sig", "signal to be sent"], // if null, its equivalent to the struct version which is provided a signal is sent using kill // otherwise the buffer is equivalent to the info buffer specified by the rt_sigqueueinfo syscall - (["info", "struct containing information about the signal"], Pointer_To_Struct), + ["info", "struct containing information about the signal"], // reserved for future use, currently should be 0 - (["flags", "flag for customization, currently does not provide any functionality"], General_Flag(ReservedForFutureUse)), + ["flags", "flag for customization, currently does not provide any functionality"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1863,7 +1863,7 @@ pub fn initialize_syscall_map() -> HashMap { Thread, "get the thread id of the calling thread", &[], - (["return value", "thread id of the calling thread"],Always_Successful_Numeric) + ["return value", "thread id of the calling thread"], ) ), // This is often used by routines that generate unique temporary filenames. @@ -1874,7 +1874,7 @@ pub fn initialize_syscall_map() -> HashMap { Thread, "get the process id of the calling process", &[], - (["return value", "process id of the calling process"],Always_Successful_Numeric) + ["return value", "process id of the calling process"], ) ), ( @@ -1884,7 +1884,7 @@ pub fn initialize_syscall_map() -> HashMap { Thread, "get the process id of the parent process", &[], - (["return value", "process id of the parent of the calling process"],Always_Successful_Numeric) + ["return value", "process id of the parent of the calling process"], ) ), // These bytes can be used to seed user-space random number generators or for cryptographic purposes. @@ -1894,11 +1894,11 @@ pub fn initialize_syscall_map() -> HashMap { Device, "fill a specified buffer with random bytes", &[ - (["buf", "pointer to a buffer where the random bytes will be stored"], Pointer_To_Struct), - (["buflen", "amount of bytes to fill in the buffer"], Length_Of_Bytes_Specific), - (["flags", "flags to select the random source, and whether the call should block"], General_Flag(GetRandomFlags)), + ["buf", "pointer to a buffer where the random bytes will be stored"], + ["buflen", "amount of bytes to fill in the buffer"], + ["flags", "flags to select the random source, and whether the call should block"], ], - (["return value", "number of random bytes retrieved, -1 On error and errno is modified"],Length_Of_Bytes_Specific_Or_Errno) + ["return value", "number of random bytes retrieved, -1 On error and errno is modified"], ) ), ( @@ -1907,10 +1907,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "set the soft and hard resource limits of a process", &[ - (["resource", "specific resource type to limit"], General_Flag(ResourceFlags)), - (["rlim", "pointer to a struct containing the soft and hard limits"], Pointer_To_Struct), + ["resource", "specific resource type to limit"], + ["rlim", "pointer to a struct containing the soft and hard limits"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1919,10 +1919,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get the soft and hard resource limits of a process", &[ - (["resource", "specific resource type to retrieve"], General_Flag(ResourceFlags)), - (["rlim", "pointer to a struct where the soft and hard limits of the resource will get stored"], Pointer_To_Struct), + ["resource", "specific resource type to retrieve"], + ["rlim", "pointer to a struct where the soft and hard limits of the resource will get stored"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1934,14 +1934,14 @@ pub fn initialize_syscall_map() -> HashMap { "get or set the soft and hard limits of a specific resource for a process", &[ // if zero then operate on the calling process - (["pid", "process id of the process to operate on"], PID), - (["resource", "specific resource type to operate on"], General_Flag(ResourceFlags)), + ["pid", "process id of the process to operate on"], + ["resource", "specific resource type to operate on"], // NULLABLE - (["new_limit", "pointer to a struct containing the soft and hard limits to use as new limits"], Pointer_To_Struct), + ["new_limit", "pointer to a struct containing the soft and hard limits to use as new limits"], // NULLABLE - (["old_limit", "pointer to a struct where the soft and hard limits of the resource will get stored"], Pointer_To_Struct), + ["old_limit", "pointer to a struct where the soft and hard limits of the resource will get stored"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1966,10 +1966,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get resource usage metrics for a specific process domain", &[ - (["who", "which domain of the process to measure"], General_Flag(RusageWhoFlags)), - (["usage", "pointer to a struct where the the resource usage metrics will get stored"], Pointer_To_Struct), + ["who", "which domain of the process to measure"], + ["usage", "pointer to a struct where the the resource usage metrics will get stored"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1978,9 +1978,9 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get memory and swap usage metrics", &[ - (["info", "pointer to a struct where the the system info will get stored"], Pointer_To_Struct), + ["info", "pointer to a struct where the the system info will get stored"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -1989,9 +1989,9 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get time metrics for the calling process and its children", &[ - (["buf", "pointer to a struct where various timing metrics for the process will get stored"], Pointer_To_Struct), + ["buf", "pointer to a struct where various timing metrics for the process will get stored"], ], - (["numeric return", "number of clock ticks for the process since an arbitrary point, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "number of clock ticks for the process since an arbitrary point, -1 on error, errno modified"], ) ), ( @@ -2001,11 +2001,11 @@ pub fn initialize_syscall_map() -> HashMap { "set specific CPUs for this thread to run on", &[ // if zero then the calling thread is the thread referred to - (["pid", "thread id of the thread to operate on"], PID), - (["cpusetsize", "size of the CPU mask struct"], Length_Of_Bytes_Specific), - (["mask", "pointer to struct containing the bitmask of CPUs"], Pointer_To_Struct), + ["pid", "thread id of the thread to operate on"], + ["cpusetsize", "size of the CPU mask struct"], + ["mask", "pointer to struct containing the bitmask of CPUs"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2015,11 +2015,11 @@ pub fn initialize_syscall_map() -> HashMap { "find which CPUs this thread is allowed to run on", &[ // if zero then the calling thread is the thread referred to - (["pid", "thread id of the thread to operate on"], PID), - (["cpusetsize", "size of the CPU mask struct"], Length_Of_Bytes_Specific), - (["mask", "pointer to struct where the current thread's CPU bitmask will be stored"], Pointer_To_Struct), + ["pid", "thread id of the thread to operate on"], + ["cpusetsize", "size of the CPU mask struct"], + ["mask", "pointer to struct where the current thread's CPU bitmask will be stored"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2032,9 +2032,9 @@ pub fn initialize_syscall_map() -> HashMap { Process, "exit the calling process", &[ - (["status", "status of the process on exit"], Numeric), + ["status", "status of the process on exit"], ], - (["", ""], Never_Returns) + ["", ""], ) ), ( @@ -2043,9 +2043,9 @@ pub fn initialize_syscall_map() -> HashMap { Process, "exit all threads in this process's thread group", &[ - (["status", "status of the process on exit"], Numeric), + ["status", "status of the process on exit"], ], - (["", ""], Never_Returns) + ["", ""], ) ), ( @@ -2058,11 +2058,11 @@ pub fn initialize_syscall_map() -> HashMap { "send a signal to a specific thread in a specific thread", &[ // If tgid is specified as -1, tgkill() is equivalent to tkill(). - (["tgid", "id of the thread group where the signal will be sent"], PID), - (["tid", "id of the specific thread in the thread group"], PID), - (["sig", "the signal to be sent"], General_Flag(Signal)), + ["tgid", "id of the thread group where the signal will be sent"], + ["tid", "id of the specific thread in the thread group"], + ["sig", "the signal to be sent"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2072,10 +2072,10 @@ pub fn initialize_syscall_map() -> HashMap { Thread, "send a signal to a specific thread in a specific thread", &[ - (["tid", "id of the specific thread to which the signal will be sent"], PID), - (["sig", "the signal to be sent"], General_Flag(Signal)), + ["tid", "id of the specific thread to which the signal will be sent"], + ["sig", "the signal to be sent"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2085,18 +2085,18 @@ pub fn initialize_syscall_map() -> HashMap { "register a per-thread data structure shared between kernel and user-space", &[ // Only one rseq can be registered per thread, - (["rseq", "pointer to the thread-local rseq struct to be shared between kernel and user-space"], Pointer_To_Struct), - (["rseq len", "size of the struct rseq"], Length_Of_Bytes_Specific), + ["rseq", "pointer to the thread-local rseq struct to be shared between kernel and user-space"], + ["rseq len", "size of the struct rseq"], // 0 for registration, and RSEQ FLAG UNREGISTER for unregistration - (["flags", "the signal to be sent"], General_Flag(RSeqFlag)), + ["flags", "the signal to be sent"], // Each supported architecture provides a RSEQ_SIG macro in sys/rseq.h // which contains a signature. That signature is expected to be present in the code // before each restartable sequences abort handler. // Failure to provide the expected signature may terminate the process // with a segmentation fault. - (["sig", "32-bit signature to be expected before the abort handler code"], Unsigned_Numeric), + ["sig", "32-bit signature to be expected before the abort handler code"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2105,9 +2105,9 @@ pub fn initialize_syscall_map() -> HashMap { System, "get system information", &[ - (["mask", "pointer to struct where the system information will be stored"], Pointer_To_Struct), + ["mask", "pointer to struct where the system information will be stored"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2117,7 +2117,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get the real user ID of the calling process", &[], - (["return value", "the real user ID of the calling process"],Always_Successful_User_Group) + ["return value", "the real user ID of the calling process"], ) ), ( @@ -2127,7 +2127,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get the effective user ID of the calling process", &[], - (["return value", "the effective user ID of the calling process"],Always_Successful_User_Group) + ["return value", "the effective user ID of the calling process"], ) ), ( @@ -2137,7 +2137,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get the real group ID of the calling process", &[], - (["return value", "the real group ID of the calling process"],Always_Successful_User_Group) + ["return value", "the real group ID of the calling process"], ) ), ( @@ -2147,7 +2147,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get the effective group ID of the calling process", &[], - (["return value", "the effective group ID of the calling process"],Always_Successful_User_Group) + ["return value", "the effective group ID of the calling process"], ) ), ( @@ -2158,12 +2158,12 @@ pub fn initialize_syscall_map() -> HashMap { Process, "set the effective user ID of the calling process", &[ - (["uid", "id of the thread group where the signal will be sent"], User_Group), + ["uid", "id of the thread group where the signal will be sent"], ], // The user ID specified in uid is not valid in this user namespace. // The user is not privileged (does not have the CAP_SETUID capability) // and uid does not match the real UID or saved set-user-ID of the calling process. - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2172,11 +2172,11 @@ pub fn initialize_syscall_map() -> HashMap { Process, "set the effective user ID of the calling process", &[ - (["gid", "id of the thread group where the signal will be sent"], User_Group), + ["gid", "id of the thread group where the signal will be sent"], ], // The calling process is not privileged (does not have the CAP_SETGID), // and gid does not match the real group ID or saved set-group-ID of the calling process. - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2187,14 +2187,14 @@ pub fn initialize_syscall_map() -> HashMap { AsyncIO, "set the effective user ID of the calling process", &[ - (["uaddr", "pointer to the futex-word"], Pointer_To_Unsigned_Numeric), - (["futex_op", "specific futex operation to carry"], General_Flag(FutexOpFlags)), - (["val", "value specific to each operation"], Unsigned_Numeric), - (["timeout", "either a pointer to a timeout struct for blocking operations or a normal numeric value specific to some operations"], Pointer_To_Struct), - (["uaddr2", "pointer to a second futex-word"], Pointer_To_Unsigned_Numeric), - (["val3", "value specific to each operation"], Unsigned_Numeric), + ["uaddr", "pointer to the futex-word"], + ["futex_op", "specific futex operation to carry"], + ["val", "value specific to each operation"], + ["timeout", "either a pointer to a timeout struct for blocking operations or a normal numeric value specific to some operations"], + ["uaddr2", "pointer to a second futex-word"], + ["val3", "value specific to each operation"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2212,9 +2212,9 @@ pub fn initialize_syscall_map() -> HashMap { Thread, "set the `clear_child_tid` value for the calling thread to the id provided", &[ - (["tidptr", "pointer to the thread id to use for `clear_child_tid`"], Pointer_To_Numeric(None)), + ["tidptr", "pointer to the thread id to use for `clear_child_tid`"], ], - (["return value", "thread id of the calling thread"], Numeric_Or_Errno) + ["return value", "thread id of the calling thread"], ) ), ( @@ -2223,9 +2223,9 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a file to use for event notifications/waiting", &[ - (["initval", "value specific to each operation"], Unsigned_Numeric), + ["initval", "value specific to each operation"], ], - (["return value", "event file descriptor on success, -1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "event file descriptor on success, -1 on error, errno modified"], ) ), ( @@ -2234,10 +2234,10 @@ pub fn initialize_syscall_map() -> HashMap { FileOp, "create a file to use for event notifications/waiting with custom file behaviour", &[ - (["initval", "value specific to each operation"], Unsigned_Numeric), - (["flags", "event file behaviour flag"], General_Flag(EventfdFlag)), + ["initval", "value specific to each operation"], + ["flags", "event file behaviour flag"], ], - (["return value", "event file descriptor on success, -1 on error, errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "event file descriptor on success, -1 on error, errno modified"], ) ), ( @@ -2250,17 +2250,17 @@ pub fn initialize_syscall_map() -> HashMap { // -1 wait for any child process. // 0 wait for any child process whose process group ID is equal to that of the calling process at the time of the call to waitpid(). // > 0 wait for the child whose process ID is equal to the value of pid. - (["pid", "number representing which process to wait on"], User_Group), + ["pid", "number representing which process to wait on"], // If wstatus is not NULL, wait4() stores status information in the int to which it points. // This integer can be inspected with the following macros // (which take the integer itself as an argument, not a pointer to it (as is done in syscall)) - (["wstatus", "pointer to int representing the status of the process"], Pointer_To_Numeric(None)), - (["options", "specific state changes to wait for"], General_Flag(WaitEventFlags)), + ["wstatus", "pointer to int representing the status of the process"], + ["options", "specific state changes to wait for"], // NULLABLE means do not want // resource usage information about the child - (["rusage", "pointer usage to a struct where the the resource usage metrics will get stored"], Pointer_To_Struct), + ["rusage", "pointer usage to a struct where the the resource usage metrics will get stored"], ], - (["numeric return", "pid of the child whose state has changed, or 0 on no state change for WNOHANG, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "pid of the child whose state has changed, or 0 on no state change for WNOHANG, -1 on error, errno modified"], ) ), ( @@ -2270,17 +2270,17 @@ pub fn initialize_syscall_map() -> HashMap { "wait until a specific event occurs for a specific child process", &[ - (["idtype", "categoty of process identifier to use for specifying the process"], General_Flag(WaitIdTypeFlags)), - (["id", "the specific id in the category defined by idtype"], User_Group), - (["infop", "pointer to a struct that will store the information about the child"], Pointer_To_Struct), - (["options", "specific state changes to wait for"], General_Flag(WaitEventFlags)), + ["idtype", "categoty of process identifier to use for specifying the process"], + ["id", "the specific id in the category defined by idtype"], + ["infop", "pointer to a struct that will store the information about the child"], + ["options", "specific state changes to wait for"], // NULLABLE means do not want // resource usage information about the // child, in the same manner as wait4(2). - (["rusage", "pointer usage to a struct where the the resource usage metrics will get stored"], Pointer_To_Struct), + ["rusage", "pointer usage to a struct where the the resource usage metrics will get stored"], ], // returns 0 on success or if WNOHANG was specified and no child(ren) specified by id has yet changed state - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), // @@ -2301,10 +2301,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "modify the robust futexes list of the calling thread", &[ - (["head_ptr", "location of the head of the robust futex list"], Address), - (["len_ptr", "size of the robust futex list"], Numeric), + ["head_ptr", "location of the head of the robust futex list"], + ["len_ptr", "size of the robust futex list"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2320,11 +2320,11 @@ pub fn initialize_syscall_map() -> HashMap { Process, "retrieve the list of robust futexes for a specific thread", &[ - (["pid", "id of the process to be modified"], User_Group), - (["head_ptr", "address of the head of the robust futex list"], Address), - (["len_ptr", "size of the robust futex list"], Pointer_To_Numeric(None)), + ["pid", "id of the process to be modified"], + ["head_ptr", "address of the head of the robust futex list"], + ["len_ptr", "size of the robust futex list"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2333,10 +2333,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "set the process group ID of a specific process", &[ - (["pid", "id of the process to be modified"], User_Group), - (["pgid", "the new process group id to set for the process"], User_Group), + ["pid", "id of the process to be modified"], + ["pgid", "the new process group id to set for the process"], ], - (["numeric return", "0 on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["numeric return", "0 on success, -1 on error, errno modified"], ) ), ( @@ -2345,9 +2345,9 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get the process group ID of a specific process", &[ - (["pid", "id of the process to operate on"], User_Group), + ["pid", "id of the process to operate on"], ], - (["return value", "process group id on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "process group id on success, -1 on error, errno modified"], ) ), ( @@ -2356,7 +2356,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get the process group ID of the calling process", &[], - (["return value", "process group id on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "process group id on success, -1 on error, errno modified"], ) ), ( @@ -2424,7 +2424,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "creates a new child process by duplicating the calling process", &[], - (["return value", "0 returned to the child process, and the new process id of the child returned to the calling process, -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "0 returned to the child process, and the new process id of the child returned to the calling process, -1 on error, errno modified"], ) ), ( @@ -2443,7 +2443,7 @@ pub fn initialize_syscall_map() -> HashMap { Process, "creates a new child process, and suspend the calling process until child termination", &[], - (["return value", "0 returned to the child process, and the new process id of the child returned to the calling process, -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "0 returned to the child process, and the new process id of the child returned to the calling process, -1 on error, errno modified"], ) ), ( @@ -2452,10 +2452,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "Create a new child thread", &[ - (["cl_args", "pointer to a struct containing the parameters for the new thread"], Pointer_To_Struct), - (["size", "size of the cl_args struct"], Unsigned_Numeric), + ["cl_args", "pointer to a struct containing the parameters for the new thread"], + ["size", "size of the cl_args struct"], ], - (["return value", "thread id of the new child thread"], Numeric_Or_Errno) + ["return value", "thread id of the new child thread"], ) ), ( @@ -2464,13 +2464,13 @@ pub fn initialize_syscall_map() -> HashMap { Process, "Create a new child thread", &[ - (["flags", "cloning customization flags"], General_Flag(CloneFlags)), - (["stack", "pointer to a struct containing the parameters for the new thread"], Address), - (["parent_tid", "location where child thread id is stored in parent's memory"], Pointer_To_Numeric(None)), - (["child_tid", "location where child thread id is stored in child's memory"], Pointer_To_Numeric(None)), - (["tls", "thread local storage descriptor"], Unsigned_Numeric), + ["flags", "cloning customization flags"], + ["stack", "pointer to a struct containing the parameters for the new thread"], + ["parent_tid", "location where child thread id is stored in parent's memory"], + ["child_tid", "location where child thread id is stored in child's memory"], + ["tls", "thread local storage descriptor"], ], - (["return value", "thread id of the new child thread"], Numeric_Or_Errno) + ["return value", "thread id of the new child thread"], ) ), @@ -2519,15 +2519,15 @@ pub fn initialize_syscall_map() -> HashMap { Process, "execute a program using a pathname and replace the current program", &[ - (["pathname", "path of the file of the program to be executed"], Pointer_To_Text("")), + ["pathname", "path of the file of the program to be executed"], // the first of these strings should be the filename of the file being executed // terminated by a null pointer - (["argv","array of pointers to strings containing the command-line arguments for the program"],Array_Of_Strings(&[])), + ["argv","array of pointers to strings containing the command-line arguments for the program"], // terminated by a null pointer - (["envp","array of pointers to `key=value` strings containing the environment of the new program"],Array_Of_Strings(&[])), + ["envp","array of pointers to `key=value` strings containing the environment of the new program"], ], // does not return on success - (["return value", "does not return on success, -1 on error, errno modified"], Numeric_Or_Errno) + ["return value", "does not return on success, -1 on error, errno modified"], ) ), ( @@ -2537,11 +2537,11 @@ pub fn initialize_syscall_map() -> HashMap { "suspend execution of the calling thread until the specified timeout, or ocurrence of siganl handling", &[ // The value of the nanoseconds field must be in the range [0, 999999999]. - (["duration", "pointer to struct containing amount of time to block in nanoseconds"], Pointer_To_Struct), + ["duration", "pointer to struct containing amount of time to block in nanoseconds"], // NULLABLE means do not want - (["rem", "pointer to a struct where the remaining time is to be stored in case of an interruption"],Pointer_To_Struct), + ["rem", "pointer to a struct where the remaining time is to be stored in case of an interruption"], ], - (["return value", "0 on success, -1 on interruption or error, errno modified"], Numeric_Or_Errno) + ["return value", "0 on success, -1 on interruption or error, errno modified"], ) ), // ( @@ -2671,14 +2671,14 @@ pub fn initialize_syscall_map() -> HashMap { &[ // these actions will by default be forbidden if no future rules explicitly allows them // Nullable - (["attr", "pointer to struct containing a bitmask of actions to be handled by this ruleset"], Pointer_To_Struct), - (["size", "size of the landlock ruleset struct"], Length_Of_Bytes_Specific), + ["attr", "pointer to struct containing a bitmask of actions to be handled by this ruleset"], + ["size", "size of the landlock ruleset struct"], // flags must be 0 if attr is used. // for now only: LANDLOCK_CREATE_RULESET_VERSION flag available // If attr is NULL and size is 0, then the returned value is the highest supported Landlock ABI version - (["flags", "flags "], General_Flag(LandlockCreateFlag)), + ["flags", "flags "], ], - (["return value", "landlock ruleset file descriptor, or a Landlock ABI version, -1 for error, and errno modified"],File_Descriptor_Or_Errno("")) + ["return value", "landlock ruleset file descriptor, or a Landlock ABI version, -1 for error, and errno modified"], ) ), ( @@ -2687,14 +2687,14 @@ pub fn initialize_syscall_map() -> HashMap { Security, "add a new Landlock rule to an existing landlock ruleset", &[ - (["ruleset_fd", "file descriptor of the landlock ruleset where the rule will be added"], File_Descriptor("")), + ["ruleset_fd", "file descriptor of the landlock ruleset where the rule will be added"], // currently only LANDLOCK_RULE_PATH_BENEATH : bla is file hierarchy. - (["rule_type", "flag identifying the type of rule in rule_attr"], General_Flag(LandlockRuleTypeFlag)), - (["rule_attr", "pointer to struct containing the new rule details"], Pointer_To_Struct), + ["rule_type", "flag identifying the type of rule in rule_attr"], + ["rule_attr", "pointer to struct containing the new rule details"], // must be 0 - (["flags", "curently no flags supported"], General_Flag(LandlockAddRuleFlag)), + ["flags", "curently no flags supported"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -2703,11 +2703,11 @@ pub fn initialize_syscall_map() -> HashMap { Security, "enforce the ruleset in the provided file descriptor on the calling thread", &[ - (["ruleset_fd", "file descriptor of the landlock ruleset"], File_Descriptor("")), + ["ruleset_fd", "file descriptor of the landlock ruleset"], // must be 0 - (["flags", "curently no flags supported"], General_Flag(LandlockRestrictFlag)), + ["flags", "curently no flags supported"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -2725,12 +2725,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "modify the allocated disk space for a specific file", &[ - (["fd", "file descriptor of the file to be modified"], File_Descriptor("")), - (["mode", "disk space modification flags"], General_Flag(FallocFlags)), - (["offset", "offset where the operation starts"], Length_Of_Bytes_Specific), - (["len", "amount of bytes from the offset to operate on"], Length_Of_Bytes), + ["fd", "file descriptor of the file to be modified"], + ["mode", "disk space modification flags"], + ["offset", "offset where the operation starts"], + ["len", "amount of bytes from the offset to operate on"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -2740,10 +2740,10 @@ pub fn initialize_syscall_map() -> HashMap { Process, "get a processes' or user's scheduling priority", &[ - (["which", "type of the target (process/process group/user)"], General_Flag(PriorityWhich)), - (["who", "specific id of the target"], Numeric), + ["which", "type of the target (process/process group/user)"], + ["who", "specific id of the target"], ], - (["return value", "priority of the process/process group/user. -1 for error and errno modified"], Priority_Or_Errno(MaybeUninit::::zeroed())), + ["return value", "priority of the process/process group/user. -1 for error and errno modified"], ) ), ( @@ -2753,11 +2753,11 @@ pub fn initialize_syscall_map() -> HashMap { Process, "increase or decrease processes' or user's scheduling priority", &[ - (["which", "type of the target (process/process group/user)"], General_Flag(PriorityWhich)), - (["who", "specific id of the target"], Numeric), - (["prio", "new scheduling priority value"], Unsigned_Numeric), + ["which", "type of the target (process/process group/user)"], + ["who", "specific id of the target"], + ["prio", "new scheduling priority value"], ], - (["return value", "0 success. -1 for error and errno modified"], Numeric_Or_Errno) + ["return value", "0 success. -1 for error and errno modified"], ) ), ( @@ -2766,12 +2766,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "get the directory entries for a specific directory", &[ - (["fd", "file descriptor of the directory"], File_Descriptor("")), - (["dirp", "pointer to a buffer where the retrieved directory entries will be stored"], Pointer_To_Struct), - (["count", "size of the dirp buffer"], Unsigned_Numeric), + ["fd", "file descriptor of the directory"], + ["dirp", "pointer to a buffer where the retrieved directory entries will be stored"], + ["count", "size of the dirp buffer"], ], // On end of directory, 0 is returned. - (["return value", "number of bytes read on success. -1 for error and errno modified"], Length_Of_Bytes_Specific_Or_Errno) + ["return value", "number of bytes read on success. -1 for error and errno modified"], ) ), ( @@ -2781,12 +2781,12 @@ pub fn initialize_syscall_map() -> HashMap { DiskIO, "get the directory entries for a specific directory", &[ - (["fd", "file descriptor of the directory"], File_Descriptor("")), - (["dirp", "pointer to a buffer where the retrieved directory entries will be stored"], Pointer_To_Struct), - (["count", "size of the dirp buffer"], Unsigned_Numeric), + ["fd", "file descriptor of the directory"], + ["dirp", "pointer to a buffer where the retrieved directory entries will be stored"], + ["count", "size of the dirp buffer"], ], // On end of directory, 0 is returned. - (["return value", "number of bytes read on success. -1 for error and errno modified"], Length_Of_Bytes_Specific_Or_Errno) + ["return value", "number of bytes read on success. -1 for error and errno modified"], ) ), // ( diff --git a/src/syscall_object.rs b/src/syscall_object.rs index 98bcd2b..df3233c 100644 --- a/src/syscall_object.rs +++ b/src/syscall_object.rs @@ -1,11 +1,12 @@ #![allow(unused_variables)] use crate::{ one_line_formatter::handle_path_file, + syscall_object_annotations::SyscallObject_Annotations, types::{ - mlock2, Annotation, Bytes, BytesPagesRelevant, Category, Flag, - LandlockCreateFlags, LandlockRuleTypeFlags, SysArg, SysReturn, + mlock2, Annotation, Bytes, BytesPagesRelevant, Category, Flag, LandlockCreateFlags, + LandlockRuleTypeFlags, SysArg, SysReturn, Syscall_Shape, }, - utilities::{FOLLOW_FORKS, INTENT, SYSCALL_MAP, UNSUPPORTED, lose_relativity_on_path}, + utilities::{lose_relativity_on_path, FOLLOW_FORKS, SYSANNOT_MAP, SYSKELETON_MAP, UNSUPPORTED}, }; use colored::{ColoredString, Colorize}; @@ -14,7 +15,8 @@ use nix::{ errno::Errno, fcntl::{self, AtFlags, FallocateFlags, OFlag, RenameFlags}, libc::{ - cpu_set_t, iovec, msghdr, sockaddr, 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, @@ -28,16 +30,22 @@ use nix::{ uio::{process_vm_readv, RemoteIoVec}, wait::WaitPidFlag, }, - unistd::{AccessFlags, Pid, Whence}, NixPath, + unistd::{AccessFlags, Pid, Whence}, + NixPath, }; - use rustix::{ fs::StatxFlags, io::ReadWriteFlags, path::Arg, rand::GetRandomFlags, thread::FutexFlags, }; use std::{ - fmt::Display, io::IoSliceMut, mem::{self, transmute, zeroed}, os::{fd::RawFd, raw::c_void}, path::PathBuf, ptr::null, sync::atomic::Ordering + fmt::Display, + io::IoSliceMut, + mem::{self, transmute, zeroed}, + os::{fd::RawFd, raw::c_void}, + path::PathBuf, + ptr::null, + sync::atomic::Ordering, }; #[derive(Clone, Debug, PartialEq)] @@ -47,20 +55,17 @@ pub enum SyscallState { } use syscalls::Sysno; -#[derive(Clone, Debug)] +#[derive(Debug)] pub struct SyscallObject { pub sysno: Sysno, - description: &'static str, pub category: Category, pub args: Vec, - rich_args: Vec<(Annotation, SysArg)>, - count: usize, - pub result: (Option, (Annotation, SysReturn)), - pub child: Pid, + pub skeleton: Vec, + pub result: (Option, SysReturn), + pub process_pid: Pid, pub errno: Option, pub state: SyscallState, pub paused: bool, - pub successful: bool, pub one_line: Vec, } @@ -68,17 +73,14 @@ impl Default for SyscallObject { fn default() -> Self { SyscallObject { sysno: unsafe { mem::zeroed() }, - description: "", category: unsafe { mem::zeroed() }, args: vec![], - rich_args: vec![], - count: unsafe { mem::zeroed() }, + skeleton: vec![], result: unsafe { mem::zeroed() }, - child: unsafe { mem::zeroed() }, + process_pid: unsafe { mem::zeroed() }, errno: unsafe { mem::zeroed() }, state: SyscallState::Entering, paused: false, - successful: false, one_line: vec![], } } @@ -86,539 +88,252 @@ impl Default for SyscallObject { impl SyscallObject { pub fn format(&mut self) { - if INTENT.get() { - if let Ok(_) = self.one_line_formatter() { - let mut string = String::new(); - for i in &mut self.one_line { - string.push_str(&format!("{}", i)); - } - print!("{}", string) - } else { - if self.state == SyscallState::Entering { - return; - } - // multiline arguments - let mut output = vec![]; - output.push("\n".dimmed()); - let eph_return = self.parse_return_value(1); - if FOLLOW_FORKS.load(Ordering::SeqCst) { - output.push(self.child.to_string().bright_blue()); - } else { - if eph_return.is_ok() { - output.push(self.child.to_string().blue()); - } else { - output.push(self.child.to_string().red()); - } - } - output.extend(vec![ - " ".dimmed(), - SyscallObject::colorize_syscall_name(&self.sysno, &self.category), - " - ".dimmed(), - ]); - output.push(self.description.dimmed()); - output.push("\n".bright_white()); - output.push("\t(\n".bright_white()); - let len = self.args.len(); - for index in 0..len { - // self.args[index], self.rich_args[index] - output.push("\t\t".dimmed()); - let parse_output = self.parse_arg_value(index, 1); - output.extend(parse_output); - output.push(",\n".dimmed()); - } - // println!("{}",self.count); - output.pop(); - output.push(",\n\t".dimmed()); - output.push(") = ".bright_white()); - match eph_return { - Ok(good) => { - output.extend(good); - } - Err(errno) => { - output.push(errno); - } - } - let string = String::from_iter(output.into_iter().map(|x| x.to_string())); - println!("{}", string) - // write!(f, "{}\n", string)? + let sysno = self.sysno; + if let Ok(_) = self.one_line_formatter() { + let mut string = String::new(); + for string_portion in &mut self.one_line { + string.push_str(&format!("{}", string_portion)); } + print!("{}", string) } else { - // - // - // - // - // - // multiline arguments - let mut output = vec![]; - let eph_return = self.parse_return_value(1); - if eph_return.is_ok() { - output.push(self.child.to_string().green()); - } else { - output.push(self.child.to_string().red()); - } - output.extend(vec![ - " - ".dimmed(), - SyscallObject::colorize_syscall_name(&self.sysno, &self.category), - " - ".dimmed(), - ]); - output.push(self.description.dimmed()); - output.push("\n".bright_white()); - output.push("\t(\n".bright_white()); - let len = self.args.len(); - for index in 0..len { - // self.args[index], self.rich_args[index] - output.push("\t\t".dimmed()); - let parse_output = self.parse_arg_value(index, 1); - output.extend(parse_output); - output.push(",\n".dimmed()); - } - // println!("{}",self.count); - output.pop(); - output.push(",\n\t".dimmed()); - output.push(") = ".bright_white()); - match eph_return { - Ok(good) => { - output.extend(good); - } - Err(errno) => { - output.push(errno); - } - } - let string = String::from_iter(output.into_iter().map(|x| x.to_string())); - println!("{}", string) - // - // - // - // - // + // disabled for now + // switch to syscallobject_annotation formatting + // let mut annot_variant = SyscallObject_Annotations::from(self); + // annot_variant.format() } - // - // - // - // - // - // normal old one line - // let mut output = vec![]; - // output.push(self.sysno.name().bright_green()); - // output.push(" - ".dimmed()); - // output.push(self.alt_name.dimmed()); - // output.push(" (".bright_white()); - // let len = self.args.len(); - // for index in 0..len { - // let parse_output = self.parse_arg_value(index, 0); - // output.extend(parse_output); - // output.push(", ".dimmed()); - // } - // output.pop(); - // output.push(") = ".bright_white()); - // let (might_register, (annotation, sys_return)) = self.result; - // let parse_return_output = match might_register { - // Some(register) => self.parse_return_value(0), - // None => { - // vec![] - // } - // }; - // output.extend(parse_return_output); - // let string = String::from_iter(output.into_iter().map(|x| x.to_string())); - // write!(f, "{}", string) - // - // - // - // - // } -} + fn replace_content(&mut self, index: usize, sys_arg: SysArg) { + self.skeleton[index] = sys_arg + } +} impl SyscallObject { - // annotation, arg_container, register_value - pub(crate) fn parse_arg_value(&self, index: usize, which: usize) -> Vec { - let annotation = self.rich_args[index].0; - let sysarg = self.rich_args[index].1; + pub(crate) fn get_sysno(orig_rax: i32) -> Sysno { + // println!("{:?}", registers.orig_rax as i32); + Sysno::from(orig_rax) + } + pub(crate) fn build(registers: &user_regs_struct, child: Pid) -> Self { + let sysno = Sysno::from(registers.orig_rax as i32); + let syscall = match SYSKELETON_MAP.get(&sysno) { + Some(&Syscall_Shape { + category, + types, + syscall_return, + }) => match types.len() { + 0 => SyscallObject { + sysno, + category: category, + args: vec![], + skeleton: types.into_iter().cloned().collect(), + result: (None, syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 1 => SyscallObject { + sysno, + category: category, + args: vec![registers.rdi], + skeleton: types.into_iter().cloned().collect(), + result: (None, syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 2 => SyscallObject { + sysno, + category: category, + args: vec![registers.rdi, registers.rsi], + skeleton: types.into_iter().cloned().collect(), + result: (None, syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 3 => SyscallObject { + sysno, + category: category, + args: vec![registers.rdi, registers.rsi, registers.rdx], + skeleton: types.into_iter().cloned().collect(), + result: (None, syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 4 => SyscallObject { + sysno, + category: category, + args: vec![registers.rdi, registers.rsi, registers.rdx, registers.r10], + skeleton: types.into_iter().cloned().collect(), + result: (None, syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 5 => SyscallObject { + sysno, + category: category, + args: vec![ + registers.rdi, + registers.rsi, + registers.rdx, + registers.r10, + registers.r8, + ], + skeleton: types.into_iter().cloned().collect(), + result: (None, syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + _ => SyscallObject { + sysno, + category: category, + args: vec![ + registers.rdi, + registers.rsi, + registers.rdx, + registers.r10, + registers.r8, + registers.r9, + ], + skeleton: types.into_iter().cloned().collect(), + result: (None, syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + }, + None => { + // unsafe { + // if !UNSUPPORTED.contains(&sysno.name()) { + // UNSUPPORTED.push(sysno.name()); + // } + // } + SyscallObject { + sysno, + category: Category::Process, + args: vec![], + result: (None, SysReturn::File_Descriptor_Or_Errno("")), + process_pid: child, + errno: None, + ..Default::default() + } + } + }; + syscall + } + // previously `parse_arg_value_for_one_line` + pub(crate) fn pavfol(&self, index: usize) -> String { let register_value = self.args[index]; - - let mut output: Vec = Vec::new(); use SysArg::*; - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - let value: ColoredString = match sysarg { + match self.skeleton[index] { // NUMERICS - Numeric => format!("{}", register_value as isize).yellow(), - PID => format!("{}", register_value as isize).yellow(), - User_Group => format!("{}", register_value as isize).yellow(), - Unsigned_Numeric => format!("{register_value}").yellow(), - File_Descriptor(fd) => format!("{fd}").yellow(), - File_Descriptor_openat(fd) => format!("{fd}").yellow(), + Numeric => format!("{}", register_value as isize), + PID => format!("{}", register_value as isize), + User_Group => format!("{}", register_value as isize), + Unsigned_Numeric => format!("{register_value}"), + File_Descriptor(fd) => format!("{fd}"), + File_Descriptor_openat(fd) => format!("{fd}"), Pointer_To_File_Descriptor_Array([fd1, fd2]) => { - format!("read end: {fd1}, write end: {fd2}").yellow() + format!("read end: {fd1}, write end: {fd2}") } - // FLAG - General_Flag(flag) => SyscallObject::handle_flag(register_value, flag).yellow(), + General_Flag(flag) => SyscallObject::handle_flag(register_value, flag), // BYTES - Length_Of_Bytes => SyscallObject::style_bytes(register_value).yellow(), + Length_Of_Bytes => SyscallObject::style_bytes(register_value), + Length_Of_Bytes_Specific => { + format!("{register_value} Bytes") + } Length_Of_Bytes_Page_Aligned_Ceil => { - SyscallObject::style_bytes_page_aligned_ceil(register_value).yellow() + SyscallObject::style_bytes_page_aligned_ceil(register_value) } Length_Of_Bytes_Page_Aligned_Floor => { - SyscallObject::style_bytes_page_aligned_floor(register_value).yellow() + SyscallObject::style_bytes_page_aligned_floor(register_value) } // Signed_Length_Of_Bytes_Specific => { - // SyscallObject::style_bytes_signed(register_value).yellow() + // SyscallObject::style_bytes_signed(register_value) // } - Length_Of_Bytes_Specific => format!("{register_value} Bytes").yellow(), // can be mined for granular insights - Pointer_To_Struct => "0x.. -> {..}".yellow(), - Array_Of_Struct => "[{..}, {..}]".yellow(), + Pointer_To_Struct => "0x.. -> {..}".to_owned(), + Array_Of_Struct => "[ {..}, {..} , {..} ]".to_owned(), Array_Of_Strings(array) => { let mut string = String::new(); for text in array { string.push_str(&text); string.push(' '); } - string.yellow() + string } - - Byte_Stream => format!("whatever").yellow(), // } + Byte_Stream => format!("whatever"), Single_Word => { let pointer = register_value as *const (); - format!("{:p}", pointer).blue() + format!("{:p}", pointer) } Pointer_To_Numeric(pid) => { let pointer = register_value as *const (); if pointer.is_null() { - format!("0xNull").magenta() + format!("0xNull") } else { let pid = pid.unwrap(); - format!("{pid}").blue() + format!("{pid}") + // format!("{pointer:p} -> {pid}") } + // let pointer = register_value as *const i64; + // let reference: &i64 = unsafe { transmute(pointer) }; } Pointer_To_Numeric_Or_Numeric(numeric) => { if numeric.is_none() { - format!("").blue() + format!("") } else { let num = numeric.unwrap(); - format!("{num}").blue() + format!("{num}") } } Pointer_To_Unsigned_Numeric => { let pointer = register_value as *const (); if pointer.is_null() { - format!("0xNull").magenta() + format!("0xNull") } else { - format!("{:p}", pointer).blue() + format!("{:p}", pointer) } + // let pointer = register_value as *const u64; + // let reference: &u64 = unsafe { transmute(pointer) }; } - Pointer_To_Text(text) => { - if text.len() > 20 { - let portion = &text[..20]; - format!("{:?}", format!("{}...", portion)).purple() - } else if text.len() == 0 { - format!("\"\"").bright_yellow() - } else { - format!("{:?}", format!("{}", text)).purple() - } + format!("{}", text) } Pointer_To_Path(text) => { - if text.len() > 20 { - let portion = &text[..]; - - format!("{:?}", format!("{}...", portion)).purple() - } else if text.len() == 0 { - format!("\"\"").bright_yellow() - } else { - format!("{:?}", format!("{}", text)).purple() - } + format!("{}", text) } Address => { let pointer = register_value as *const (); if pointer == std::ptr::null() { - format!("0xNull").bright_red() + format!("0xNull") } else { - format!("{:p}", pointer).yellow() + format!("{:p}", pointer) } } - Pointer_To_Length_Of_Bytes_Specific => { - ColoredString::from("did not handle this yet".yellow()) - } - // should remove + Pointer_To_Length_Of_Bytes_Specific => String::from("did not handle this yet"), Multiple_Flags([flag1, flag2]) => { - SyscallObject::handle_flag(register_value, flag1).yellow() + SyscallObject::handle_flag(register_value, flag1) + // SyscallObject::handle_multi_flags(register_value, flag1, flag2) } - }; - output.push(value); - output - } - - pub(crate) fn parse_return_value( - &self, - which: usize, - ) -> Result, ColoredString> { - if self.is_exiting(){ - return Ok(vec![]); - } - - let annotation = self.result.1 .0; - let sys_return = self.result.1 .1; - let register_value = self.result.0.unwrap(); - let mut output: Vec = Vec::new(); - - use SysReturn::*; - let err: syscalls::Errno = unsafe { std::mem::transmute(self.errno) }; - // println!("{:?}", err); - let value: ColoredString = match sys_return { - Numeric_Or_Errno => { - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - let numeric_return = register_value as isize; - if numeric_return == -1 { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - format!("{numeric_return}").yellow() - } - } - Always_Successful_Numeric => format!("{}", register_value as isize).yellow(), - Signal_Or_Errno(signal) => { - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - let signal_num = register_value as isize; - if signal_num == -1 { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - format!("{signal}").yellow() - } - } - // because -1 is a valid priority, we have to check - Priority_Or_Errno(errored) => { - let priority = register_value as isize; - if unsafe { errored.assume_init() } { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - priority.to_string().yellow() - } - } - - File_Descriptor_Or_Errno(fd) => { - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - let fd_num = register_value as isize; - if fd_num == -1 { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - format!("{fd}").yellow() - } - } - - Length_Of_Bytes_Specific_Or_Errno => { - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - let bytes = register_value as isize; - if bytes == -1 { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - format!("{bytes} Bytes").yellow() - } - } - Address_Or_Errno(address) => { - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - - let pointer = register_value as isize; - if pointer == -1 { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - format!("{:p}", pointer as *const ()).yellow() - } - } - Address_Or_MAP_FAILED_Errno(address) => { - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - let pointer = register_value as *mut c_void; - if pointer == MAP_FAILED { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - format!("{:p}", pointer as *const ()).yellow() - } - } - Address_Or_Errno_getcwd(current_working_dir) => { - output.push(annotation[which].dimmed()); - output.push(": ".dimmed()); - let pointer = register_value as *const (); - if pointer.is_null() { - return Err(self - .errno - .unwrap_or_else(|| Errno::UnknownErrno) - .to_string() - .red()); - } else { - format!("{current_working_dir}").yellow() - } - } - Always_Successful_User_Group => { - let result = register_value as isize; - format!("{result}").yellow() - } - Never_Returns => format!("never returns").yellow(), - Always_Succeeds => { - unimplemented!() - } - Does_Not_Return_Anything => { - // println!("Does_Not_Return_Anything"); - format!("").yellow() - } - }; - output.push(value); - Ok(output) - } - - // previously `parse_arg_value_for_one_line` - pub(crate) fn pavfol(&self, index: usize) -> String { - let register_value = self.args[index]; - let sysarg = self.rich_args[index].1; - use SysArg::*; - match sysarg { - // NUMERICS - Numeric => format!("{}", register_value as isize), - PID => format!("{}", register_value as isize), - User_Group => format!("{}", register_value as isize), - Unsigned_Numeric => format!("{register_value}"), - File_Descriptor(fd) => format!("{fd}"), - File_Descriptor_openat(fd) => format!("{fd}"), - Pointer_To_File_Descriptor_Array([fd1, fd2]) => { - format!("read end: {fd1}, write end: {fd2}") - } - // FLAG - General_Flag(flag) => SyscallObject::handle_flag(register_value, flag), - - // BYTES - Length_Of_Bytes => SyscallObject::style_bytes(register_value), - Length_Of_Bytes_Specific => { - format!("{register_value} Bytes") - } - Length_Of_Bytes_Page_Aligned_Ceil => { - SyscallObject::style_bytes_page_aligned_ceil(register_value) - } - Length_Of_Bytes_Page_Aligned_Floor => { - SyscallObject::style_bytes_page_aligned_floor(register_value) - } - // Signed_Length_Of_Bytes_Specific => { - // SyscallObject::style_bytes_signed(register_value) - // } - - // can be mined for granular insights - Pointer_To_Struct => "0x.. -> {..}".to_owned(), - Array_Of_Struct => "[ {..}, {..} , {..} ]".to_owned(), - Array_Of_Strings(array) => { - let mut string = String::new(); - for text in array { - string.push_str(&text); - string.push(' '); - } - string - } - Byte_Stream => format!("whatever"), - - Single_Word => { - let pointer = register_value as *const (); - format!("{:p}", pointer) - } - - Pointer_To_Numeric(pid) => { - let pointer = register_value as *const (); - if pointer.is_null() { - format!("0xNull") - } else { - let pid = pid.unwrap(); - format!("{pid}") - // format!("{pointer:p} -> {pid}") - } - // let pointer = register_value as *const i64; - // let reference: &i64 = unsafe { transmute(pointer) }; - } - Pointer_To_Numeric_Or_Numeric(numeric) => { - if numeric.is_none() { - format!("") - } else { - let num = numeric.unwrap(); - format!("{num}") - } - } - - Pointer_To_Unsigned_Numeric => { - let pointer = register_value as *const (); - if pointer.is_null() { - format!("0xNull") - } else { - format!("{:p}", pointer) - } - // let pointer = register_value as *const u64; - // let reference: &u64 = unsafe { transmute(pointer) }; - } - Pointer_To_Text(text) => { - format!("{}", text) - } - - Pointer_To_Path(text) => { - format!("{}", text) - } - - Address => { - let pointer = register_value as *const (); - if pointer == std::ptr::null() { - format!("0xNull") - } else { - format!("{:p}", pointer) - } - } - - Pointer_To_Length_Of_Bytes_Specific => String::from("did not handle this yet"), - Multiple_Flags([flag1, flag2]) => { - SyscallObject::handle_flag(register_value, flag1) - // SyscallObject::handle_multi_flags(register_value, flag1, flag2) - } } } pub(crate) fn parse_return_value_one_line(&self) -> Result { if self.is_exiting() { return Ok("".to_owned()); } - let sys_return = self.result.1 .1; + let sys_return = self.result.1; let register_value = self.result.0.unwrap(); use SysReturn::*; @@ -631,9 +346,7 @@ impl SyscallObject { Ok(format!("{numeric_return}")) } } - Always_Successful_Numeric => { - Ok(format!("{}", register_value as isize)) - } + Always_Successful_Numeric => Ok(format!("{}", register_value as isize)), Signal_Or_Errno(signal) => { let signal_num = register_value as isize; if signal_num + 1 == -1 { @@ -695,9 +408,7 @@ impl SyscallObject { if pointer.is_null() { Err(()) } else { - Ok(format!( - "{current_working_dir}", - )) + Ok(format!("{current_working_dir}",)) } } Always_Successful_User_Group => { @@ -714,36 +425,113 @@ impl SyscallObject { } } } + // basically fill up all the parentheses data + pub(crate) fn get_precall_data(&mut self) { + // POPULATING ARGUMENTS + // + // + // + for index in 0..self.skeleton.len() { + use SysArg::*; + match self.skeleton[index] { + File_Descriptor(ref mut file_descriptor) => { + let fd = self.args[index] as i32; + + let styled_fd = + SyscallObject::style_file_descriptor(self.args[index], self.process_pid) + .unwrap_or(format!("ignored")); + *file_descriptor = styled_fd.leak(); + } + File_Descriptor_openat(ref mut file_descriptor) => { + let mut styled_fd = String::new(); + let fd = self.args[index] as i32; + styled_fd = if fd == AT_FDCWD { + format!("{}", "AT_FDCWD -> Current Working Directory".bright_blue()) + } else { + SyscallObject::style_file_descriptor(self.args[index], self.process_pid) + .unwrap_or(format!("ignored")) + }; + *file_descriptor = styled_fd.leak(); + } + Pointer_To_Text(ref mut text) => { + // TODO! fix this + let mut styled_fd = String::new(); + if self.sysno == Sysno::execve { + continue; + } + if self.sysno == Sysno::write || self.sysno == Sysno::pwrite64 { + if self.args[2] < 20 { + match SyscallObject::read_string_specific_length( + self.args[1] as usize, + self.process_pid, + self.args[2] as usize, + ) { + Some(styled_fd) => { + *text = styled_fd.leak(); + } + None => (), + } + continue; + } + } + let styled_fd = + SyscallObject::string_from_pointer(self.args[index], self.process_pid); + *text = styled_fd.leak(); + } + Array_Of_Strings(ref mut text) => { + // TODO! fix this + if self.sysno == Sysno::execve { + continue; + } + let array_of_texts = SyscallObject::string_from_array_of_strings( + self.args[index], + self.process_pid, + ); + let mut svec: Vec<&'static str> = vec![]; + for text in array_of_texts { + svec.push(text.leak()); + } + *text = Box::leak(svec.into_boxed_slice()); + } + _ => {} + } + } + // POPULATING RETURN (for now only priority) + // + // + // + let (register, ref mut sys_return) = self.result; + use SysReturn::*; + match sys_return { + Priority_Or_Errno(_errored) => { + errno::set_errno(errno::Errno(0)); + } + _ => {} + }; + // returns are not populted because this is before the syscall runs + } pub(crate) fn get_postcall_data(&mut self) { // POPULATING ARGUMENTS // // // - let len = self.rich_args.len(); + let len = self.skeleton.len(); for index in 0..len { - let mut annotation = self.rich_args[index].0; - let mut sysarg = self.rich_args[index].1; use SysArg::*; - match sysarg { + match self.skeleton[index] { Pointer_To_File_Descriptor_Array( [ref mut file_descriptor1, ref mut file_descriptor2], ) => { - match SyscallObject::read_two_word( - self.args[index] as usize, - self.child, - ) { + match SyscallObject::read_two_word(self.args[index] as usize, self.process_pid) + { Some([ref mut fd1, ref mut fd2]) => { - let styled_fd1 = SyscallObject::style_file_descriptor( - *fd1 as u64, - self.child, - ) - .unwrap_or(format!("ignored")); - let styled_fd2 = SyscallObject::style_file_descriptor( - *fd2 as u64, - self.child, - ) - .unwrap_or(format!("ignored")); + let styled_fd1 = + SyscallObject::style_file_descriptor(*fd1 as u64, self.process_pid) + .unwrap_or(format!("ignored")); + let styled_fd2 = + SyscallObject::style_file_descriptor(*fd2 as u64, self.process_pid) + .unwrap_or(format!("ignored")); *file_descriptor1 = styled_fd1.leak(); *file_descriptor2 = styled_fd2.leak(); } @@ -754,10 +542,11 @@ impl SyscallObject { } } Pointer_To_Numeric(ref mut pid) => { - match SyscallObject::read_word(self.args[index] as usize, self.child) { + match SyscallObject::read_word(self.args[index] as usize, self.process_pid) { Some(pid_at_word) => { if self.sysno == Sysno::wait4 { - self.rich_args[1].1 = Pointer_To_Numeric(Some(pid_at_word)); + self.skeleton[1] = Pointer_To_Numeric(Some(pid_at_word)) + // self.skeleton[1] = Pointer_To_Numeric(Some(pid_at_word)); } } None => { @@ -784,13 +573,12 @@ impl SyscallObject { || (operation & ARCH_GET_FS) == ARCH_GET_FS || (operation & ARCH_GET_GS) == ARCH_GET_GS { - match SyscallObject::read_word( - self.args[index] as usize, - self.child, - ) { + match SyscallObject::read_word(self.args[index] as usize, self.process_pid) + { Some(pid_at_word) => { if self.sysno == Sysno::wait4 { - self.rich_args[1].1 = Pointer_To_Numeric_Or_Numeric(Some(pid_at_word)); + self.skeleton[1] = + Pointer_To_Numeric_Or_Numeric(Some(pid_at_word)); } } None => { @@ -815,26 +603,23 @@ impl SyscallObject { if self.sysno == Sysno::readlink && index == 1 { match SyscallObject::read_string_specific_length( self.args[index] as usize, - self.child, + self.process_pid, size as usize, ) { - Some(styled_fd) => { - self.rich_args[1].1 = Pointer_To_Text(styled_fd.leak()); - } + Some(styled_fd) => self + .replace_content(1, Pointer_To_Text(styled_fd.leak())), None => (), } } else if self.sysno == Sysno::readlinkat && index == 2 { match SyscallObject::read_string_specific_length( self.args[index] as usize, - self.child, + self.process_pid, size as usize, ) { - Some(styled_fd) => { - self.rich_args[1].1 = Pointer_To_Text(styled_fd.leak()); - } + Some(styled_fd) => self + .replace_content(1, Pointer_To_Text(styled_fd.leak())), None => (), } - } } } @@ -847,18 +632,19 @@ impl SyscallObject { // // // - let (register, (ref mut annotation, ref mut sys_return)) = self.result; + let (register, ref mut sys_return) = self.result; use SysReturn::*; match sys_return { File_Descriptor_Or_Errno(data) => { let fd = register.unwrap(); - let styled_fd = SyscallObject::style_file_descriptor(fd, self.child) + let styled_fd = SyscallObject::style_file_descriptor(fd, self.process_pid) .unwrap_or(format!("{:?}", self.errno)); *data = styled_fd.leak(); } Address_Or_Errno_getcwd(data) => { - let styled_string = SyscallObject::string_from_pointer(self.args[0], self.child); + let styled_string = + SyscallObject::string_from_pointer(self.args[0], self.process_pid); *data = styled_string.leak(); } Priority_Or_Errno(errored) => { @@ -880,247 +666,6 @@ impl SyscallObject { _ => {} }; } - // basically fill up all the parentheses data - pub(crate) fn get_precall_data(&mut self) { - // POPULATING ARGUMENTS - // - // - // - for (index, (annotation, sysarg)) in self.rich_args.iter_mut().enumerate() { - use SysArg::*; - match sysarg { - File_Descriptor(file_descriptor) => { - let fd = self.args[index] as i32; - - let styled_fd = - SyscallObject::style_file_descriptor(self.args[index], self.child) - .unwrap_or(format!("ignored")); - *file_descriptor = styled_fd.leak(); - } - File_Descriptor_openat(file_descriptor) => { - let mut styled_fd = String::new(); - let fd = self.args[index] as i32; - styled_fd = if fd == AT_FDCWD { - format!("{}", "AT_FDCWD -> Current Working Directory".bright_blue()) - } else { - SyscallObject::style_file_descriptor(self.args[index], self.child) - .unwrap_or(format!("ignored")) - }; - *file_descriptor = styled_fd.leak(); - } - Pointer_To_Text(ref mut text) => { - // TODO! fix this - let mut styled_fd = String::new(); - if self.sysno == Sysno::execve { - continue; - } - if self.sysno == Sysno::write || self.sysno == Sysno::pwrite64 { - if self.args[2] < 20 { - match SyscallObject::read_string_specific_length( - self.args[1] as usize, - self.child, - self.args[2] as usize, - ) { - Some(styled_fd) => { - *text = styled_fd.leak(); - } - None => (), - } - continue; - } - } - let styled_fd = - SyscallObject::string_from_pointer(self.args[index], self.child); - *text = styled_fd.leak(); - } - Array_Of_Strings(text) => { - // TODO! fix this - if self.sysno == Sysno::execve { - continue; - } - let array_of_texts = SyscallObject::string_from_array_of_strings( - self.args[index], - self.child, - ); - let mut svec: Vec<&'static str> = vec![]; - for text in array_of_texts { - svec.push(text.leak()); - } - *text = Box::leak(svec.into_boxed_slice()); - } - _ => {} - } - } - // POPULATING RETURN (for now only priority) - // - // - // - let (register, (ref mut annotation, ref mut sys_return)) = self.result; - use SysReturn::*; - match sys_return { - Priority_Or_Errno(_errored) => { - errno::set_errno(errno::Errno(0)); - } - _ => {} - }; - // returns are not populted because this is before the syscall runs - } - - pub(crate) fn get_sysno(orig_rax: i32) -> Sysno { - // println!("{:?}", registers.orig_rax as i32); - Sysno::from(orig_rax) - } - pub(crate) fn build(registers: &user_regs_struct, child: Pid) -> Self { - let sysno = Sysno::from(registers.orig_rax as i32); - let syscall = match SYSCALL_MAP.get(&sysno) { - Some(( - category, - syscall_description, - annotations_arg_containers, - (return_annotation, sys_return), - )) => match annotations_arg_containers.len() { - 0 => SyscallObject { - sysno, - description: syscall_description, - category: *category, - args: vec![], - rich_args: vec![], - count: 0, - result: (None, (*return_annotation, *sys_return)), - child, - errno: None, - ..Default::default() - }, - 1 => SyscallObject { - sysno, - description: syscall_description, - category: *category, - args: vec![registers.rdi], - rich_args: vec![annotations_arg_containers[0]], - count: 0, - result: (None, (*return_annotation, *sys_return)), - child, - errno: None, - ..Default::default() - }, - 2 => SyscallObject { - sysno, - description: syscall_description, - category: *category, - args: vec![registers.rdi, registers.rsi], - rich_args: vec![annotations_arg_containers[0], annotations_arg_containers[1]], - count: 0, - result: (None, (*return_annotation, *sys_return)), - child, - errno: None, - ..Default::default() - }, - 3 => SyscallObject { - sysno, - description: syscall_description, - category: *category, - args: vec![registers.rdi, registers.rsi, registers.rdx], - rich_args: vec![ - annotations_arg_containers[0], - annotations_arg_containers[1], - annotations_arg_containers[2], - ], - count: 0, - result: (None, (*return_annotation, *sys_return)), - child, - errno: None, - ..Default::default() - }, - 4 => SyscallObject { - sysno, - description: syscall_description, - category: *category, - args: vec![registers.rdi, registers.rsi, registers.rdx, registers.r10], - rich_args: vec![ - annotations_arg_containers[0], - annotations_arg_containers[1], - annotations_arg_containers[2], - annotations_arg_containers[3], - ], - count: 0, - result: (None, (*return_annotation, *sys_return)), - child, - errno: None, - ..Default::default() - }, - 5 => SyscallObject { - sysno, - description: syscall_description, - category: *category, - args: vec![ - registers.rdi, - registers.rsi, - registers.rdx, - registers.r10, - registers.r8, - ], - rich_args: vec![ - annotations_arg_containers[0], - annotations_arg_containers[1], - annotations_arg_containers[2], - annotations_arg_containers[3], - annotations_arg_containers[4], - ], - count: 0, - result: (None, (*return_annotation, *sys_return)), - child, - errno: None, - ..Default::default() - }, - _ => SyscallObject { - sysno, - description: syscall_description, - category: *category, - args: vec![ - registers.rdi, - registers.rsi, - registers.rdx, - registers.r10, - registers.r8, - registers.r9, - ], - rich_args: vec![ - annotations_arg_containers[0], - annotations_arg_containers[1], - annotations_arg_containers[2], - annotations_arg_containers[3], - annotations_arg_containers[4], - annotations_arg_containers[5], - ], - count: 0, - result: (None, (*return_annotation, *sys_return)), - child, - errno: None, - ..Default::default() - }, - }, - None => { - // unsafe { - // if !UNSUPPORTED.contains(&sysno.name()) { - // UNSUPPORTED.push(sysno.name()); - // } - // } - SyscallObject { - sysno, - description: "syscall not covered currently", - category: Category::Process, - args: vec![], - rich_args: vec![], - count: 0, - result: (None, (["", ""], SysReturn::File_Descriptor_Or_Errno(""))), - child, - errno: None, - ..Default::default() - } - } - }; - syscall - } fn style_file_descriptor(register_value: u64, child: Pid) -> Option { let fd = register_value as RawFd; let mut string = Vec::new(); @@ -1264,34 +809,44 @@ impl SyscallObject { bytes.to_string() } - pub(crate) fn possible_dirfd_file(&mut self, dirfd: i32, filename: String){ + pub(crate) fn possible_dirfd_file(&mut self, dirfd: i32, filename: String) { let file_path_buf = PathBuf::from(filename); if file_path_buf.is_relative() { if dirfd == AT_FDCWD { - let cwd = procfs::process::Process::new(self.child.into()).unwrap().cwd().unwrap(); + let cwd = procfs::process::Process::new(self.process_pid.into()) + .unwrap() + .cwd() + .unwrap(); self.one_line.push(cwd.as_path().to_string_lossy().yellow()); self.one_line.push("/".yellow()); - let path_without_leading_relativeness = lose_relativity_on_path(file_path_buf.as_path().to_string_lossy().to_owned()); + let path_without_leading_relativeness = + lose_relativity_on_path(file_path_buf.as_path().to_string_lossy().to_owned()); self.one_line.push(path_without_leading_relativeness.blue()); } else { - let file_info = procfs::process::FDInfo::from_raw_fd(self.child.into(), dirfd).unwrap(); + let file_info = + procfs::process::FDInfo::from_raw_fd(self.process_pid.into(), dirfd).unwrap(); match file_info.target { procfs::process::FDTarget::Path(path) => { - self.one_line.push(path.as_path().to_string_lossy().yellow()); + self.one_line + .push(path.as_path().to_string_lossy().yellow()); if !path.is_absolute() || path.len() != 1 { self.one_line.push("/".yellow()); - } - let path_without_leading_relativeness = lose_relativity_on_path(file_path_buf.as_path().to_string_lossy().to_owned()); + } + let path_without_leading_relativeness = lose_relativity_on_path( + file_path_buf.as_path().to_string_lossy().to_owned(), + ); self.one_line.push(path_without_leading_relativeness.blue()); } - _ => unreachable!() + _ => unreachable!(), } } } else { - handle_path_file(file_path_buf.as_path().to_string_lossy().into_owned(), &mut self.one_line); + handle_path_file( + file_path_buf.as_path().to_string_lossy().into_owned(), + &mut self.one_line, + ); } - } - + } pub(crate) fn possible_dirfd_file_output(&mut self, dirfd: i32, filename: String) -> String { let mut string = String::new(); @@ -1301,34 +856,39 @@ impl SyscallObject { let cwd = procfs::process::Process::new(10).unwrap().cwd().unwrap(); string.push_str(&cwd.as_path().to_string_lossy()); string.push_str("/"); - let path_without_leading_relativeness = lose_relativity_on_path(file_path_buf.as_path().to_string_lossy().to_owned()); + let path_without_leading_relativeness = + lose_relativity_on_path(file_path_buf.as_path().to_string_lossy().to_owned()); string.push_str(&path_without_leading_relativeness); } else { - let file_info = procfs::process::FDInfo::from_raw_fd(self.child.into(), dirfd).unwrap(); + let file_info = + procfs::process::FDInfo::from_raw_fd(self.process_pid.into(), dirfd).unwrap(); match file_info.target { procfs::process::FDTarget::Path(path) => { - self.one_line.push(path.as_path().to_string_lossy().yellow()); + self.one_line + .push(path.as_path().to_string_lossy().yellow()); if !path.is_absolute() || path.len() != 1 { self.one_line.push("/".yellow()); - } - let path_without_leading_relativeness = lose_relativity_on_path(file_path_buf.as_path().to_string_lossy().to_owned()); + } + let path_without_leading_relativeness = lose_relativity_on_path( + file_path_buf.as_path().to_string_lossy().to_owned(), + ); self.one_line.push(path_without_leading_relativeness.blue()); } - _ => unreachable!() + _ => unreachable!(), } } } else { string.push_str(&file_path_buf.as_path().to_string_lossy().to_owned()); } string - } + } // Use process_vm_readv(2) fn string_from_pointer(address: u64, child: Pid) -> String { // TODO! execve multi-threaded fails here for some reason match SyscallObject::read_bytes_until_null(address as usize, child) { Some(data) => String::from_utf8_lossy(&data).into_owned(), - None => "".to_owned() + None => "".to_owned(), } } fn string_from_array_of_strings(address: u64, child: Pid) -> Vec { @@ -1515,8 +1075,8 @@ impl SyscallObject { } pub(crate) fn read_affinity_from_child(addr: usize, child: Pid) -> Option> { - const CPU_SET_USIZE: usize = (CPU_SETSIZE / 8) as usize; - + const CPU_SET_USIZE: usize = (CPU_SETSIZE / 8) as usize; + let cpu_mask = SyscallObject::read_bytes_specific_length(addr, child, CPU_SET_USIZE)?; let a: [u8; CPU_SET_USIZE] = cpu_mask.try_into().ok()?; @@ -1599,7 +1159,6 @@ impl SyscallObject { // for i in a { // let bitmap: nix::sys::signal::Signal = unsafe { std::mem::transmute(i) }; // println!("{:?}", bitmap); - // println!("fycjubg good"); // } } SignalHow => { @@ -1885,17 +1444,3 @@ impl SyscallObject { range } } - - -impl Iterator for SyscallObject { - type Item = (u64, ([&'static str; 2], SysArg)); - fn next(&mut self) -> Option { - if self.count != self.args.len() { - let out = (self.args[self.count], self.rich_args[self.count]); - self.count += 1; - return Some(out); - } else { - None - } - } -} diff --git a/src/syscall_object_annotations.rs b/src/syscall_object_annotations.rs new file mode 100644 index 0000000..45bc91b --- /dev/null +++ b/src/syscall_object_annotations.rs @@ -0,0 +1,1102 @@ +#![allow(unused_variables)] +use crate::{ + one_line_formatter::handle_path_file, + syscall_object::SyscallObject, + types::{ + mlock2, Annotation, Bytes, BytesPagesRelevant, Category, Flag, LandlockCreateFlags, + LandlockRuleTypeFlags, SysArg, SysReturn, Syscall_Shape, + }, + utilities::{lose_relativity_on_path, FOLLOW_FORKS, SYSANNOT_MAP, SYSKELETON_MAP}, +}; + +use colored::{ColoredString, Colorize}; +use core::slice; +use nix::{ + errno::Errno, + fcntl::{self, AtFlags, FallocateFlags, OFlag, RenameFlags}, + libc::{ + 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, + mman::{MRemapFlags, MapFlags, MmapAdvise, MsFlags, ProtFlags}, + ptrace, + resource::{Resource, UsageWho}, + signal::Signal, + signalfd::SfdFlags, + socket::{self, SockFlag}, + stat::{FchmodatFlags, Mode}, + uio::{process_vm_readv, RemoteIoVec}, + wait::WaitPidFlag, + }, + unistd::{AccessFlags, Pid, Whence}, + NixPath, +}; +use syscalls::Sysno; + +use rustix::{ + fs::StatxFlags, io::ReadWriteFlags, path::Arg, rand::GetRandomFlags, thread::FutexFlags, +}; + +use std::{ + fmt::Display, + io::IoSliceMut, + mem::{self, transmute, zeroed}, + os::{fd::RawFd, raw::c_void}, + path::PathBuf, + ptr::null, + sync::atomic::Ordering, +}; + +#[derive(Clone, Debug, PartialEq)] +pub enum SyscallState { + Entering, + Exiting, +} + +#[derive(Clone, Debug)] +pub struct SyscallObject_Annotations { + pub sysno: Sysno, + description: &'static str, + pub category: Category, + pub args: Vec, + pub args_types: Vec, + rich_args: Vec, + pub result: (Option, Annotation, SysReturn), + pub process_pid: Pid, + pub errno: Option, +} +impl Default for SyscallObject_Annotations { + fn default() -> Self { + SyscallObject_Annotations { + sysno: unsafe { mem::zeroed() }, + description: "", + category: unsafe { mem::zeroed() }, + args: vec![], + rich_args: vec![], + args_types: vec![], + result: unsafe { mem::zeroed() }, + process_pid: unsafe { mem::zeroed() }, + errno: unsafe { mem::zeroed() }, + } + } +} + +impl From<&mut SyscallObject> for SyscallObject_Annotations { + fn from( + SyscallObject { + sysno, + category, + args, + skeleton, + result, + process_pid, + errno, + state, + paused, + one_line, + }: &mut SyscallObject, + ) -> Self { + if let Some(&(category, description, annotations_arg_containers, return_annotation)) = + SYSANNOT_MAP.get(&sysno) + { + SyscallObject_Annotations { + sysno: *sysno, + description, + category, + args: args.clone(), + args_types: skeleton.clone(), + rich_args: annotations_arg_containers.into_iter().cloned().collect(), + result: (result.0, return_annotation, result.1), + process_pid: *process_pid, + errno: *errno, + } + } else { + SyscallObject_Annotations { + sysno: *sysno, + description: "syscall not covered currently", + category: Category::Process, + rich_args: vec![], + result: (Some(0), ["", ""], SysReturn::Always_Succeeds), + process_pid: *process_pid, + errno: None, + args: args.clone(), + args_types: skeleton.clone(), + } + } + } +} +impl SyscallObject_Annotations { + pub fn format(&mut self) { + // multiline arguments + let mut output = vec![]; + output.push("\n".dimmed()); + let eph_return = self.parse_return_value(1); + if FOLLOW_FORKS.load(Ordering::SeqCst) { + output.push(self.process_pid.to_string().bright_blue()); + } else { + if eph_return.is_ok() { + output.push(self.process_pid.to_string().blue()); + } else { + output.push(self.process_pid.to_string().red()); + } + } + output.extend(vec![ + " ".dimmed(), + SyscallObject_Annotations::colorize_syscall_name(&self.sysno, &self.category), + " - ".dimmed(), + ]); + output.push(self.description.dimmed()); + output.push("\n".bright_white()); + output.push("\t(\n".bright_white()); + let len = self.args.len(); + for index in 0..len { + // self.args.get(index), self.rich_args[index] + output.push("\t\t".dimmed()); + let parse_output = self.parse_arg_value(index, 1); + output.extend(parse_output); + output.push(",\n".dimmed()); + } + // println!("{}",self.count); + output.pop(); + output.push(",\n\t".dimmed()); + output.push(") = ".bright_white()); + match eph_return { + Ok(good) => { + output.extend(good); + } + Err(errno) => { + output.push(errno); + } + } + let string = String::from_iter(output.into_iter().map(|x| x.to_string())); + println!("{}", string) + // write!(f, "{}\n", string)? + + // + // + // + // + // + // normal old one line + // let mut output = vec![]; + // output.push(self.sysno.name().bright_green()); + // output.push(" - ".dimmed()); + // output.push(self.alt_name.dimmed()); + // output.push(" (".bright_white()); + // let len = self.args.len(); + // for index in 0..len { + // let parse_output = self.parse_arg_value(index, 0); + // output.extend(parse_output); + // output.push(", ".dimmed()); + // } + // output.pop(); + // output.push(") = ".bright_white()); + // let (might_register, (annotation, sys_return)) = self.result; + // let parse_return_output = match might_register { + // Some(register) => self.parse_return_value(0), + // None => { + // vec![] + // } + // }; + // output.extend(parse_return_output); + // let string = String::from_iter(output.into_iter().map(|x| x.to_string())); + // write!(f, "{}", string) + // + // + // + // + // + } +} + +impl SyscallObject_Annotations { + // annotation, arg_container, register_value + pub(crate) fn build_annotations(registers: &user_regs_struct, child: Pid) -> Self { + let sysno = Sysno::from(registers.orig_rax as i32); + match SYSANNOT_MAP.get(&sysno) { + Some(( + category, + syscall_description, + annotations_arg_containers, + return_annotation, + )) => { + let Syscall_Shape { + category, + types, + syscall_return, + } = SYSKELETON_MAP.get(&sysno).unwrap(); + match annotations_arg_containers.len() { + 0 => SyscallObject_Annotations { + sysno, + description: syscall_description, + category: *category, + rich_args: vec![], + result: (None, *return_annotation, *syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 1 => SyscallObject_Annotations { + sysno, + description: syscall_description, + category: *category, + rich_args: vec![annotations_arg_containers[0]], + result: (None, *return_annotation, *syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 2 => SyscallObject_Annotations { + sysno, + description: syscall_description, + category: *category, + rich_args: vec![ + annotations_arg_containers[0], + annotations_arg_containers[1], + ], + result: (None, *return_annotation, *syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 3 => SyscallObject_Annotations { + sysno, + description: syscall_description, + category: *category, + rich_args: vec![ + annotations_arg_containers[0], + annotations_arg_containers[1], + annotations_arg_containers[2], + ], + result: (None, *return_annotation, *syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 4 => SyscallObject_Annotations { + sysno, + description: syscall_description, + category: *category, + rich_args: vec![ + annotations_arg_containers[0], + annotations_arg_containers[1], + annotations_arg_containers[2], + annotations_arg_containers[3], + ], + result: (None, *return_annotation, *syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + 5 => SyscallObject_Annotations { + sysno, + description: syscall_description, + category: *category, + rich_args: vec![ + annotations_arg_containers[0], + annotations_arg_containers[1], + annotations_arg_containers[2], + annotations_arg_containers[3], + annotations_arg_containers[4], + ], + result: (None, *return_annotation, *syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + _ => SyscallObject_Annotations { + sysno, + description: syscall_description, + category: *category, + rich_args: vec![ + annotations_arg_containers[0], + annotations_arg_containers[1], + annotations_arg_containers[2], + annotations_arg_containers[3], + annotations_arg_containers[4], + annotations_arg_containers[5], + ], + result: (None, *return_annotation, *syscall_return), + process_pid: child, + errno: None, + ..Default::default() + }, + } + } + None => { + // unsafe { + // if !UNSUPPORTED.contains(&sysno.name()) { + // UNSUPPORTED.push(sysno.name()); + // } + // } + SyscallObject_Annotations { + sysno, + description: "syscall not covered currently", + category: Category::Process, + rich_args: vec![], + result: (None, ["", ""], SysReturn::Always_Succeeds), + process_pid: child, + errno: None, + ..Default::default() + } + } + } + } + pub(crate) fn parse_arg_value(&self, index: usize, which: usize) -> Vec { + let annotation = self.rich_args[index]; + let register_value = self.args[index]; + + let mut output: Vec = Vec::new(); + use SysArg::*; + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + output.push(match self.args_types[index] { + // NUMERICS + Numeric => format!("{}", register_value as isize).yellow(), + PID => format!("{}", register_value as isize).yellow(), + User_Group => format!("{}", register_value as isize).yellow(), + Unsigned_Numeric => format!("{register_value}").yellow(), + File_Descriptor(fd) => format!("{fd}").yellow(), + File_Descriptor_openat(fd) => format!("{fd}").yellow(), + Pointer_To_File_Descriptor_Array([fd1, fd2]) => { + format!("read end: {fd1}, write end: {fd2}").yellow() + } + + // FLAG + General_Flag(flag) => { + SyscallObject_Annotations::handle_flag(register_value, flag).yellow() + } + + // BYTES + Length_Of_Bytes => SyscallObject_Annotations::style_bytes(register_value).yellow(), + Length_Of_Bytes_Page_Aligned_Ceil => { + SyscallObject_Annotations::style_bytes_page_aligned_ceil(register_value).yellow() + } + Length_Of_Bytes_Page_Aligned_Floor => { + SyscallObject_Annotations::style_bytes_page_aligned_floor(register_value).yellow() + } + // Signed_Length_Of_Bytes_Specific => { + // SyscallObject_Annotations::style_bytes_signed(register_value).yellow() + // } + Length_Of_Bytes_Specific => format!("{register_value} Bytes").yellow(), + + // can be mined for granular insights + Pointer_To_Struct => "0x.. -> {..}".yellow(), + Array_Of_Struct => "[{..}, {..}]".yellow(), + Array_Of_Strings(array) => { + let mut string = String::new(); + for text in array { + string.push_str(&text); + string.push(' '); + } + string.yellow() + } + + Byte_Stream => format!("whatever").yellow(), // } + + Single_Word => { + let pointer = register_value as *const (); + format!("{:p}", pointer).blue() + } + + Pointer_To_Numeric(pid) => { + let pointer = register_value as *const (); + if pointer.is_null() { + format!("0xNull").magenta() + } else { + let pid = pid.unwrap(); + format!("{pid}").blue() + } + } + Pointer_To_Numeric_Or_Numeric(numeric) => { + if numeric.is_none() { + format!("").blue() + } else { + let num = numeric.unwrap(); + format!("{num}").blue() + } + } + + Pointer_To_Unsigned_Numeric => { + let pointer = register_value as *const (); + if pointer.is_null() { + format!("0xNull").magenta() + } else { + format!("{:p}", pointer).blue() + } + } + + Pointer_To_Text(text) => { + if text.len() > 20 { + let portion = &text[..20]; + format!("{:?}", format!("{}...", portion)).purple() + } else if text.len() == 0 { + format!("\"\"").bright_yellow() + } else { + format!("{:?}", format!("{}", text)).purple() + } + } + + Pointer_To_Path(text) => { + if text.len() > 20 { + let portion = &text[..]; + + format!("{:?}", format!("{}...", portion)).purple() + } else if text.len() == 0 { + format!("\"\"").bright_yellow() + } else { + format!("{:?}", format!("{}", text)).purple() + } + } + + Address => { + let pointer = register_value as *const (); + if pointer == std::ptr::null() { + format!("0xNull").bright_red() + } else { + format!("{:p}", pointer).yellow() + } + } + + Pointer_To_Length_Of_Bytes_Specific => { + ColoredString::from("did not handle this yet".yellow()) + } + // should remove + Multiple_Flags([flag1, flag2]) => { + SyscallObject_Annotations::handle_flag(register_value, flag1).yellow() + } + }); + output + } + + pub(crate) fn parse_return_value( + &self, + which: usize, + ) -> Result, ColoredString> { + if self.is_exiting() { + return Ok(vec![]); + } + let register_value = self.result.0.unwrap(); + let annotation = self.result.1; + let sys_return = self.result.2; + let mut output: Vec = Vec::new(); + + use SysReturn::*; + let err: syscalls::Errno = unsafe { std::mem::transmute(self.errno) }; + // println!("{:?}", err); + let value: ColoredString = match sys_return { + Numeric_Or_Errno => { + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + let numeric_return = register_value as isize; + if numeric_return == -1 { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + format!("{numeric_return}").yellow() + } + } + Always_Successful_Numeric => format!("{}", register_value as isize).yellow(), + Signal_Or_Errno(signal) => { + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + let signal_num = register_value as isize; + if signal_num == -1 { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + format!("{signal}").yellow() + } + } + // because -1 is a valid priority, we have to check + Priority_Or_Errno(errored) => { + let priority = register_value as isize; + if unsafe { errored.assume_init() } { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + priority.to_string().yellow() + } + } + + File_Descriptor_Or_Errno(fd) => { + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + let fd_num = register_value as isize; + if fd_num == -1 { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + format!("{fd}").yellow() + } + } + + Length_Of_Bytes_Specific_Or_Errno => { + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + let bytes = register_value as isize; + if bytes == -1 { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + format!("{bytes} Bytes").yellow() + } + } + Address_Or_Errno(address) => { + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + + let pointer = register_value as isize; + if pointer == -1 { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + format!("{:p}", pointer as *const ()).yellow() + } + } + Address_Or_MAP_FAILED_Errno(address) => { + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + let pointer = register_value as *mut c_void; + if pointer == MAP_FAILED { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + format!("{:p}", pointer as *const ()).yellow() + } + } + Address_Or_Errno_getcwd(current_working_dir) => { + output.push(annotation[which].dimmed()); + output.push(": ".dimmed()); + let pointer = register_value as *const (); + if pointer.is_null() { + return Err(self + .errno + .unwrap_or_else(|| Errno::UnknownErrno) + .to_string() + .red()); + } else { + format!("{current_working_dir}").yellow() + } + } + Always_Successful_User_Group => { + let result = register_value as isize; + format!("{result}").yellow() + } + Never_Returns => format!("never returns").yellow(), + Always_Succeeds => format!("").yellow(), + Does_Not_Return_Anything => { + // println!("Does_Not_Return_Anything"); + format!("").yellow() + } + }; + output.push(value); + Ok(output) + } + pub(crate) fn is_exiting(&self) -> bool { + self.sysno == Sysno::exit || self.sysno == Sysno::exit_group + } + + fn style_file_descriptor(register_value: u64, child: Pid) -> Option { + let fd = register_value as RawFd; + let mut string = Vec::new(); + if fd < 0 { + return None; + } else if fd == 0 { + string.push("0 -> StdIn".bright_blue()); + } else if fd == 1 { + string.push("1 -> StdOut".bright_blue()); + } else if fd == 2 { + string.push("2 -> StdErr".bright_blue()); + } else { + let file_info = procfs::process::FDInfo::from_raw_fd(child.into(), fd); + match file_info { + Ok(file) => match file.target { + procfs::process::FDTarget::Path(path) => { + string.push(format!("{} -> ", file.fd).bright_blue()); + let mut formatted_path = vec![]; + handle_path_file(path.to_string_lossy().into_owned(), &mut formatted_path); + for path_part in formatted_path { + string.push(path_part); + } + } + procfs::process::FDTarget::Socket(socket_number) => { + use procfs; + let mut tcp = procfs::net::tcp().unwrap(); + tcp.extend(procfs::net::tcp6().unwrap()); + let mut udp = procfs::net::udp().unwrap(); + udp.extend(procfs::net::udp6().unwrap()); + let unix = procfs::net::unix().unwrap(); + 'lookup: { + for entry in &tcp { + if entry.inode == socket_number { + if entry.remote_address.ip().is_loopback() { + string.push( + format!( + "{} -> localhost:{}", + file.fd, + entry.remote_address.port() + ) + .bright_blue(), + ); + } else { + string.push( + format!( + "{} -> {:?}:{}", + file.fd, + entry.remote_address.ip(), + entry.remote_address.port() + ) + .bright_blue(), + ); + } + break 'lookup; + } + } + for entry in &udp { + if entry.inode == socket_number { + // println!("UDP {:?}", entry); + break 'lookup; + } + } + for entry in &unix { + if entry.inode == socket_number { + string.push( + format!("{} -> Unix Domain Socket", file.fd).bright_blue(), + ); + break 'lookup; + } + } + } + } + procfs::process::FDTarget::Net(net) => { + // println!("net: {}", net); + string.push(format!("NET").bright_magenta()) + } + procfs::process::FDTarget::Pipe(pipe) => { + string.push(format!("{} -> Unix Pipe", file.fd).bright_blue()); + } + procfs::process::FDTarget::AnonInode(anon_inode) => { + // anon_inode is basically a file that has no corresponding inode + // anon_inode could've been something that was a file but is no longer on the disk + // For file descriptors that have no corresponding inode + // (e.g., file descriptors produced by + // epoll_create(2), eventfd(2), inotify_init(2), signalfd(2), and timerfd(2)), + // the entry will be a symbolic link with contents "anon_inode:" + // An anon_inode shows that there's a file descriptor which has no referencing inode + + // At least in some contexts, an anonymous inode is + // an inode without an attached directory entry. + // The easiest way to create such an inode is as such: + // int fd = open( "/tmp/file", O_CREAT | O_RDWR, 0666 ); + // unlink( "/tmp/file" ); + // Note that the descriptor fd now points to an inode that has no filesystem entry; you + // can still write to it, fstat() it, etc. but you can't find it in the filesystem. + string.push(format!("{} -> Anonymous Inode", file.fd).bright_blue()); + } + procfs::process::FDTarget::MemFD(mem_fd) => { + string.push(format!("{} -> MemFD", file.fd).bright_blue()); + } + procfs::process::FDTarget::Other(first, second) => { + string.push(format!("{} -> Other", file.fd).bright_blue()); + } + }, + Err(_) => {} + } + } + Some(String::from_iter(string.into_iter().map(|x| x.to_string()))) + } + pub(crate) fn style_bytes_page_aligned_ceil(register_value: u64) -> String { + let bytes = BytesPagesRelevant::from_ceil(register_value as usize); + bytes.to_string() + } + fn style_bytes_page_aligned_floor(register_value: u64) -> String { + let bytes = BytesPagesRelevant::from_floor(register_value as usize); + bytes.to_string() + } + + fn style_bytes(register_value: u64) -> String { + let bytes_amount = register_value as usize; + let mut bytes = Bytes::norm(bytes_amount); + if bytes_amount as f64 / 1_000_000_000.0 > 1.0 { + bytes = Bytes::giga(bytes_amount as f64 / 1_000_000_000.0) + } else if bytes_amount as f64 / 1_000_000.0 > 1.0 { + bytes = Bytes::mega(bytes_amount as f64 / 1_000_000.0) + } else if bytes_amount as f64 / 1_000.0 > 1.0 { + bytes = Bytes::kilo(bytes_amount as f64 / 1_000.0) + } + bytes.to_string() + } + pub(crate) fn style_bytes_length_specific(register_value: u64) -> String { + let bytes_amount = register_value as usize; + let mut bytes = Bytes::norm(bytes_amount); + if bytes_amount / 1_000_000_000 > 1 { + bytes = Bytes::giga(bytes_amount as f64 / 1_000_000_000.0) + } else if bytes_amount / 1_000_000 > 1 { + bytes = Bytes::mega(bytes_amount as f64 / 1_000_000.0) + } else if bytes_amount / 1_000 > 1 { + bytes = Bytes::kilo(bytes_amount as f64 / 1_000.0) + } + bytes.to_string() + } + + fn handle_flag(register_value: u64, flag: Flag) -> String { + use Flag::*; + match flag { + Map => { + let bitmap: MapFlags = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[9..string.len() - 1]) + } + Prot => { + let bitmap: ProtFlags = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[10..string.len() - 1]) + } + Open => { + let bitmap: OFlag = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[6..string.len() - 1]) + } + FileMode => { + let bitmap: Mode = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[5..string.len() - 1]) + } + ReMap => { + let bitmap: MRemapFlags = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[12..string.len() - 1]) + } + MSync => { + let bitmap: MsFlags = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[8..string.len() - 1]) + } + Madvise => { + let bitmap: MmapAdvise = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", string) + } + Access => { + let bitmap: AccessFlags = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[12..string.len() - 1]) + } + P_RW_V2_Flags => { + let bitmap: ReadWriteFlags = unsafe { std::mem::transmute(register_value as u32) }; + let string = format!("{:?}", bitmap); + format!("{}", &string[15..string.len() - 1]) + } + LSeekWhence => { + let bitmap: Whence = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + Signal => { + let a = [ + 2, 3, 4, 5, 6, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, + 23, 24, 25, 26, 27, 28, 29, 30, 31, 31, + ]; + if !a.contains(&(register_value as i32)) { + format!("unsupported signal") + } else { + let bitmap: nix::sys::signal::Signal = + unsafe { std::mem::transmute(register_value as i32) }; + format!("{:?}", bitmap) + } + // for i in a { + // let bitmap: nix::sys::signal::Signal = unsafe { std::mem::transmute(i) }; + // println!("{:?}", bitmap); + // println!("fycjubg good"); + // } + } + SignalHow => { + let bitmap: nix::sys::signal::SigmaskHow = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + SignalFDFlags => { + let bitmap: SfdFlags = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + EPollCreate1Flags => { + #[derive(Debug)] + #[repr(C)] + enum epollcreateflags { + EPOLL_CLOEXEC, + } + let bitmap: epollcreateflags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + EPollCTLOperationFlags => { + #[derive(Debug)] + #[repr(C)] + enum epollctlflags { + EPOLL_CTL_ADD, + EPOLL_CTL_MOD, + EPOLL_CTL_DEL, + } + let bitmap: epollctlflags = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + + SocketFamily => { + let bitmap: nix::sys::socket::AddressFamily = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + SocketType => { + // Since Linux 2.6.27, the type argument serves a second purpose: + // in addition to specifying a socket type, + // it may include the bitwise OR of any of the following values, + // to modify the behavior of socket(): + + // SOCK_NONBLOCK Set the O_NONBLOCK file status flag on the open file description (see open(2)) referred to by the new file descriptor. Using this flag saves extra calls + // to fcntl(2) to achieve the same result. + // SOCK_CLOEXEC Set the close-on-exec (FD_CLOEXEC) flag on the new file descriptor. See the description of the O_CLOEXEC flag in open(2) for reasons why this may be use‐ + // ful. + + // two flags 1 register is crazy + // so we separate + let all_flags: u32 = unsafe { std::mem::transmute(SockFlag::all()) }; + let register_sockflag = register_value as u32 & all_flags; + + let register_socktype = register_value as u32 ^ register_sockflag; + + let bitmap_sockflag: nix::sys::socket::SockFlag = + unsafe { std::mem::transmute(register_sockflag) }; + + let bitmap_socktype: nix::sys::socket::SockType = + unsafe { std::mem::transmute(register_socktype) }; + + let string_sockflag = format!("{:?}", bitmap_sockflag); + let string_socktype = format!("{:?}", bitmap_socktype); + + format!( + "{}, {}", + string_socktype, + &string_sockflag[9..string_sockflag.len() - 1], + // string_sockflag, + // &string_socktype[9..string_socktype.len() - 1] + ) + } + SocketFlag => { + // this is the smaller flag taken in consideration + // in the above match + let bitmap: nix::sys::socket::SockFlag = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + SocketOption => { + // let bitmap: nix::sys::socket::Op = + // unsafe { std::mem::transmute(register_value as u32) }; + // format!("{:?}", bitmap) + format!("") + } + SocketLevel => { + // let bitmap: nix::sys::socket:: = + // unsafe { std::mem::transmute(register_value as u32) }; + // format!("{:?}", bitmap) + format!("") + } + SocketProtocol => { + let bitmap: nix::sys::socket::SockProtocol = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + ReservedForFutureUse => { + format!("Flag currently ignored, butreserved for future use") + } + SocketMessageFlag => { + // let bitmap: RecvFlags= + // unsafe { std::mem::transmute(register_value as u32) }; + // format!("{:?}", bitmap) + format!("") + } + SocketMessageReceiveFlag => { + // let bitmap: nix::sys::socket::SockProtocol = + // unsafe { std::mem::transmute(register_value as u32) }; + // format!("{:?}", bitmap) + format!("") + } + MLock => { + let bitmap: mlock2 = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + MLockAll => { + let bitmap: nix::sys::mman::MlockAllFlags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + FileAtFlags => { + let bitmap: AtFlags = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + FileStatxFlags => { + let bitmap: StatxFlags = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + FileRenameFlags => { + let bitmap: RenameFlags = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + GetRandomFlags => { + let bitmap: rustix::rand::GetRandomFlags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + RusageWhoFlags => { + let bitmap: UsageWho = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + ResourceFlags => { + let bitmap: Resource = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + FileChmodAtFlags => { + let bitmap: FchmodatFlags = unsafe { std::mem::transmute(register_value as u8) }; + format!("{:?}", bitmap) + } + RSeqFlag => { + // TODO! figure this out + // let bitmap: ?? = unsafe { std::mem::transmute(register_value as u8) }; + format!("{:?}", "unknown flags for rseq") + } + FutexOpFlags => { + let bitmap: FutexFlags = unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + SocketShutdownFlag => { + let bitmap: rustix::net::Shutdown = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + EventfdFlag => { + let bitmap: eventfd::EfdFlags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + FcntlFlags => { + // TODO! + // let bitmap: FcntlArg = unsafe { std::mem::transmute(register_value as u32) }; + format!("todo!") + } + ArchPrctlFlags => { + // TODO! + // let bitmap: FcntlArg = unsafe { std::mem::transmute(register_value as u32) }; + format!("todo!") + } + Dup3Flags => { + let bitmap: rustix::io::DupFlags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + LandlockCreateFlag => { + let bitmap: LandlockCreateFlags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + LandlockRuleTypeFlag => { + let bitmap: LandlockRuleTypeFlags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + LandlockAddRuleFlag => { + // TODO! + // let bitmap: FcntlArg = unsafe { std::mem::transmute(register_value as u32) }; + format!("todo!") + } + LandlockRestrictFlag => { + // TODO! + // let bitmap: FcntlArg = unsafe { std::mem::transmute(register_value as u32) }; + format!("todo!") + } + FallocFlags => { + let bitmap: nix::fcntl::FallocateFlags = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + PriorityWhich => { + // TODO! was this flag nullable? check later + // + let which = register_value as u32; + if (which & PRIO_PROCESS) == PRIO_PROCESS { + format!("PRIO_PROCESS") + } else if (which & PRIO_PGRP) == PRIO_PGRP { + format!("PRIO_PGRP") + + // } else if (which & PRIO_USER) == PRIO_USER { + } else { + format!("PRIO_USER") + } + } + WaitIdTypeFlags => { + let bitmap: nix::sys::wait::Id = unsafe { std::mem::transmute(register_value) }; + format!("{:?}", bitmap) + } + WaitEventFlags => { + let bitmap: nix::sys::wait::WaitPidFlag = + unsafe { std::mem::transmute(register_value as u32) }; + format!("{:?}", bitmap) + } + CloneFlags => { + let bitmap: clone3::Flags = unsafe { std::mem::transmute(register_value) }; + format!("{:?}", bitmap) + } + } + } + pub(crate) fn is_mem_alloc_dealloc(&self) -> bool { + self.sysno == Sysno::brk || self.sysno == Sysno::mmap + } + // TODO! check how strace does this, maybe its better + pub(crate) fn colorize_syscall_name(sysno: &Sysno, category: &Category) -> ColoredString { + match category { + // green + Category::Process => sysno.name().bold().green(), + Category::Thread => sysno.name().bold().green(), + Category::CPU => sysno.name().bold().green(), + + Category::Network => sysno.name().bold().green(), + + // ram + Category::Memory => sysno.name().bold().bright_red(), + + // bluish + Category::FileOp => sysno.name().bold().blue(), + Category::DiskIO => sysno.name().bold().bright_blue(), + Category::Security => sysno.name().bold().bright_cyan(), + + // black + Category::System => sysno.name().bold().cyan(), + + // exotic + Category::Signals => sysno.name().bold().magenta(), + Category::Device => sysno.name().bold().bright_yellow(), + Category::AsyncIO => sysno.name().bold().purple(), + } + } +} diff --git a/src/syscall_skeleton_map.rs b/src/syscall_skeleton_map.rs new file mode 100644 index 0000000..e521c23 --- /dev/null +++ b/src/syscall_skeleton_map.rs @@ -0,0 +1,2987 @@ +use crate::types::{Category, Flag, SysArg, SysReturn, Syscall_Shape} +; +use std::collections::HashMap; +use std::mem::MaybeUninit; +use syscalls::Sysno; + +// TODO! differentiate between bitflags (orables) and enums +// TODO! add granularity for value-return type of syscall arguments +// these are semantics for syscall arguments that get modified after syscall return +// see if some arguments are better combined, like the very common buffer and buffer lengths (this makes processing cleaner but might result in complexity in non-conforming cases) +// clarify whether a buffer is provided by the user or to be filled by the kernel in the name of the argument (GIVE vs FILL) +// switch to MaybeUninit + +// TODO! switch to phf later +pub fn initialize_syscall_skeleton_map() -> HashMap { + use Category::*; + use Flag::*; + use SysArg::*; + use SysReturn::*; + let array: Vec<(Sysno, Syscall_Shape)> = vec![ + // read from a file descriptor + ( + Sysno::read, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + // write to a file descriptor + ( + Sysno::write, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + // read from a file descriptor at a given offset + ( + // Pread() basically works just like read() + // but comes with its own offset + // and doesnt modify the file pointer. + + // If you read() twice, you get different results + // If you pread() twice, you get the same result + + // the system call was renamed in from pread() to pread64(). The syscall numbers remain the same. + // The glibc pread() and pwrite() wrapper functions transparently deal with the change. + // parallel read + // also: stateless read + Sysno::pread64, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + // write to a file descriptor at a given offset + ( + // the system call was renamed in from pwrite() to pwrite64(). The syscall numbers remain the same. + // The glibc pread() and pwrite() wrapper functions transparently deal with the change. + // parallel write + // also: stateless write + Sysno::pwrite64, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + // The readv() function behave the same as read( ), except that multiple buffers are read to. + // this is used when memory to read from is scattered around (not contiguous) + // this avoids multiple read syscalls that would otherwise be needed + // + // readv: read vectored + // you use it when you know that you have multiple fixed size blocks of data + // to read into non-contiguous memory locations + Sysno::readv, + Syscall_Shape { + category: DiskIO, + types: &[File_Descriptor(""), Array_Of_Struct, Unsigned_Numeric], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + // same as readv + Sysno::writev, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Array_Of_Struct, + Unsigned_Numeric, + ], + syscall_return: // zero means what in here? man pages dont say anything + Length_Of_Bytes_Specific_Or_Errno + }, + ), + ( + // parallel read vectored + Sysno::preadv, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Array_Of_Struct, + Unsigned_Numeric, + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + // parallel write vectored + Sysno::pwritev, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Array_Of_Struct, + Unsigned_Numeric, + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::preadv2, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Array_Of_Struct, + Unsigned_Numeric, + Length_Of_Bytes_Specific, + General_Flag(P_RW_V2_Flags), + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::pwritev2, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Array_Of_Struct, + Unsigned_Numeric, + Length_Of_Bytes_Specific, + General_Flag(P_RW_V2_Flags), + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::pipe, + Syscall_Shape { + category: Process, + types: &[Pointer_To_File_Descriptor_Array(["", ""])], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::pipe2, + Syscall_Shape { + category: Process, + types: &[ + Pointer_To_File_Descriptor_Array(["", ""]), + General_Flag(Open), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // duplicate a file descriptor + // creates a copy of the file descriptor oldfd, using the lowest-numbered unused file descriptor for the new descriptor. + ( + Sysno::dup, + Syscall_Shape { + category: FileOp, + types: &[File_Descriptor("")], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + // same as dup, but uses newfd for the fd + // it overrwrites the newfd if its used + // If newfd was previously open, it is closed before being reused + ( + Sysno::dup2, + Syscall_Shape { + category: FileOp, + types: &[File_Descriptor(""), File_Descriptor("")], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + // same as dup2 but the caller can force the close-on-exec flag to be set for the new file descriptor by specifying O_CLOEXEC in flags. + ( + Sysno::dup3, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + File_Descriptor(""), + General_Flag(Dup3Flags), + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::access, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), General_Flag(Access)], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::faccessat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + General_Flag(Access), + General_Flag(FileAtFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::faccessat2, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + General_Flag(Access), + General_Flag(FileAtFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // open and possibly create a file + // open handles a relative path by considering it relative to the current process working directory + // files must be opened first before being read from or written to + ( + Sysno::open, + Syscall_Shape { + category: FileOp, + types: &[ + Pointer_To_Text(""), + // flags: one of the following modes: O_RDONLY, O_WRONLY, or O_RDWR. + // and an optional or of others + General_Flag(Open), + General_Flag(FileMode), + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + // openat handles a relative path by considering it relative to the directory of dirfd + // if AT_FDCWD is used in dirfd, then it is identical to open + // if the path is absolute then dirfd is ignored + ( + Sysno::openat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor_openat(""), + Pointer_To_Text(""), + General_Flag(Open), + General_Flag(FileMode), + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + // an extension of openat(2) and provides a superset of its functionality. + // operaes with the same logic as openat() + ( + Sysno::openat2, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Pointer_To_Struct, + Length_Of_Bytes, + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + // calling creat() is equivalent to calling open() with flags equal to O_CREAT|O_WRONLY|O_TRUNC + ( + Sysno::creat, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), General_Flag(FileMode)], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::getcwd, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), Length_Of_Bytes_Specific], + syscall_return: Address_Or_Errno_getcwd(""), + }, + ), + ( + Sysno::chdir, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text("")], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::fchdir, + Syscall_Shape { + category: FileOp, + types: &[File_Descriptor("")], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::rename, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), Pointer_To_Text("")], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::renameat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + File_Descriptor(""), + Pointer_To_Text(""), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::renameat2, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + File_Descriptor(""), + Pointer_To_Text(""), + General_Flag(FileRenameFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::mkdir, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), General_Flag(FileMode)], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::mkdirat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + General_Flag(FileMode), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::link, + Syscall_Shape { + // after hard linking it is impossible to tell which file was the original + category: FileOp, + // because they both point to the same inode now + // + // The link() system call can be used to detect and trace malicious or suspicious file modification. + // For example, if a malicious user is trying to modify or delete files in a system, + // creating/deleting a hard link to the file is one way to do this. + // Tracking the link() system call will notify if any files are modified in this way. + types: &[ + Pointer_To_Text(""), + // if existing, will not be overwritten + Pointer_To_Text(""), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::linkat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + File_Descriptor(""), + // if existing, will not be overwritten + Pointer_To_Text(""), + General_Flag(FileAtFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::unlink, + Syscall_Shape { + // Each inode on your FileOp has a reference count - it knows how many places refer to it. A directory entry is a reference. Multiple references to the same inode can exist. unlink removes a reference. When the reference count is zero, then the inode is no longer in use and may be deleted. This is how many things work, such as hard linking and snap shots. + category: FileOp, + // In particular - an open file handle is a reference. So you can open a file, unlink it, and continue to use it - it'll only be actually removed after the file handle is closed (provided the reference count drops to zero, and it's not open/hard linked anywhere else). + types: &[Pointer_To_Text("")], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::unlinkat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + General_Flag(FileAtFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::rmdir, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text("")], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // A symbolic link (also known as a soft link) may becomoe dangling + // (point to a nonexistent file); + Sysno::symlink, + Syscall_Shape { + category: FileOp, + types: &[ + Pointer_To_Text(""), + // If linkpath exists, it will not be overwritten. + Pointer_To_Text(""), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::symlinkat, + Syscall_Shape { + category: FileOp, + types: &[ + Pointer_To_Text(""), + File_Descriptor(""), + // If linkpath exists, it will not be overwritten. + Pointer_To_Text(""), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // contents of the symbolic link pathname in the buffer buf, + Sysno::readlink, + Syscall_Shape { + category: FileOp, + types: &[ + Pointer_To_Text(""), + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::readlinkat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::chmod, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), General_Flag(FileMode)], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::fchmod, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + // the RWX combination variants are infact a combination of the 3 R W X flags + // its not its own variant + General_Flag(FileMode), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::fchmodat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + General_Flag(FileMode), + General_Flag(FileChmodAtFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // ( + // Sysno::fchmodat2, + // ), + ( + Sysno::chown, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), Unsigned_Numeric, Unsigned_Numeric], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::fchown, + Syscall_Shape { + category: FileOp, + types: &[File_Descriptor(""), Unsigned_Numeric, Unsigned_Numeric], + syscall_return: Numeric_Or_Errno, + }, + ), + // same as chown but does not recursively follow a symbolic link + // it will simply change ownership of the link itself + ( + Sysno::lchown, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), Unsigned_Numeric, Unsigned_Numeric], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::fchownat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Numeric, + Numeric, + General_Flag(FileAtFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // file-system level sync + Sysno::sync, + Syscall_Shape { + category: DiskIO, + types: &[], + syscall_return: Does_Not_Return_Anything, + }, + ), + ( + // file-system level sync + Sysno::syncfs, + Syscall_Shape { + category: DiskIO, + types: &[File_Descriptor("")], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // file level sync + Sysno::fsync, + Syscall_Shape { + category: DiskIO, + types: &[File_Descriptor("")], + syscall_return: Numeric_Or_Errno, + }, + ), + // The aim of fdatasync() is to reduce disk activity for applications + // that do not require all metadata to be synchronized with the disk. + ( + // file level sync + Sysno::fdatasync, + Syscall_Shape { + category: DiskIO, + types: &[File_Descriptor("")], + syscall_return: Numeric_Or_Errno, + }, + ), + // ( + // Sysno::mount, + // ), + // ( + // Sysno::umount2, + // ), + // ( + // Sysno::swapon, + // ), + // ( + // Sysno::swapoff, + // ), + // ( + // Sysno::pivot_root, + // ), + // ( + // Sysno::chroot, + // ), + ( + // file must be writable. + Sysno::truncate, + Syscall_Shape { + category: DiskIO, + types: &[Pointer_To_Text(""), Length_Of_Bytes_Specific], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // file must be open for writing + Sysno::ftruncate, + Syscall_Shape { + category: DiskIO, + types: &[File_Descriptor(""), Length_Of_Bytes_Specific], + syscall_return: Numeric_Or_Errno, + }, + ), + // ( + // ), + // ( + // ), + // ( + // ), + // ( + // ), + // ( + // ), + + // closes a file descriptor, so that it no longer refers to any file and may be reused + ( + Sysno::close, + Syscall_Shape { + category: FileOp, + types: &[File_Descriptor("")], + syscall_return: Numeric_Or_Errno, + }, + ), + // return information about a file using a path + ( + Sysno::stat, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + // return information about a file using a file descriptor + ( + Sysno::fstat, + Syscall_Shape { + category: FileOp, + types: &[File_Descriptor(""), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + // return information about a file but does not recursively follow a symbolic link + // it will simply return information about the link itself + ( + Sysno::lstat, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::newfstatat, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Pointer_To_Struct, + General_Flag(FileAtFlags), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::statx, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + General_Flag(FileAtFlags), + General_Flag(FileStatxFlags), + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::statfs, + Syscall_Shape { + category: FileOp, + types: &[Pointer_To_Text(""), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::fstatfs, + Syscall_Shape { + category: FileOp, + types: &[File_Descriptor(""), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // deprecated syscall + Sysno::ustat, + Syscall_Shape { + category: Device, + types: &[Unsigned_Numeric, Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::cachestat, + Syscall_Shape { + category: Memory, + types: &[ + File_Descriptor(""), + // pages ceil + Pointer_To_Struct, + Pointer_To_Struct, + // Some unknown flag argument + General_Flag(ReservedForFutureUse), + ], + // unknown for now error value + syscall_return: Numeric_Or_Errno, + }, + ), + // ( + // Sysno::statmount, + // ), + + // reposition read/write file offset + ( + Sysno::lseek, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + Length_Of_Bytes_Specific, + General_Flag(LSeekWhence), + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::mmap, + Syscall_Shape { + category: Memory, + types: &[ + // Nullable + Address, + Length_Of_Bytes_Page_Aligned_Ceil, + // must not conflict with the open mode of the file + General_Flag(Prot), + General_Flag(Map), + File_Descriptor(""), + Length_Of_Bytes_Specific, + ], + syscall_return: Address_Or_MAP_FAILED_Errno(""), + }, + ), + // set protection on a region of memory + ( + Sysno::mprotect, + Syscall_Shape { + category: Memory, + types: &[ + Address, + Length_Of_Bytes_Page_Aligned_Ceil, + General_Flag(Prot), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // deletes the mappings for the specified address range + ( + Sysno::munmap, + Syscall_Shape { + category: Memory, + types: &[Address, Length_Of_Bytes_Page_Aligned_Ceil], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::brk, + Syscall_Shape { + category: Memory, + types: &[Address], + // However, the actual Linux system call returns the new program break on success. + syscall_return: Address_Or_Errno(""), + }, // On failure, the system call returns the current break. + // to know if an error occured you have to store the previous program break point somewhere to compare + ), + ( + Sysno::mlock, + Syscall_Shape { + category: Memory, + types: &[ + Address, + // Pages Ceil + Length_Of_Bytes_Page_Aligned_Ceil, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // mlock2 is linux specific + ( + Sysno::mlock2, + Syscall_Shape { + category: Memory, + types: &[ + Address, + // Pages Ceil + Length_Of_Bytes_Page_Aligned_Ceil, + // if flag is 0 mlock2 is identical to mlock + // MLOCK_ONFAULT + // Lock the pages that are currently resident + // and mark the entire range including non-resident pages + // so that when they are later populated by a page fault + // they get locked + General_Flag(MLock), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // Memory locking and unlocking are performed in units of whole pages. + Sysno::munlock, + Syscall_Shape { + category: Memory, + types: &[ + Address, + // Pages Ceil + Length_Of_Bytes_Page_Aligned_Ceil, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // Memory locking and unlocking are performed in units of whole pages. + // this is equivalent to MAP_POPULATE (unless the flag is specified for custom behaviour for non-resident and future pages) + Sysno::mlockall, + Syscall_Shape { + category: Memory, + types: &[General_Flag(MLockAll)], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // Memory locking and unlocking are performed in units of whole pages. + Sysno::munlockall, + Syscall_Shape { + category: Memory, + types: &[], + syscall_return: Numeric_Or_Errno, + }, + ), + // expands (or shrinks) an existing memory mapping, potentially moving it at the same time + ( + Sysno::mremap, + Syscall_Shape { + category: Memory, + types: &[ + // must be page aligned + Address, + Length_Of_Bytes_Page_Aligned_Ceil, + Length_Of_Bytes_Page_Aligned_Ceil, + General_Flag(ReMap), + Address, + ], + syscall_return: Address_Or_MAP_FAILED_Errno(""), + }, + ), + // flushes changes made to the file copy mapped in memory back to the filesystem. + ( + Sysno::msync, + Syscall_Shape { + category: Memory, + types: &[ + Address, + Length_Of_Bytes_Page_Aligned_Ceil, + General_Flag(MSync), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // returns a vector that represent whether pages of the calling process's virtual memory + // are resident in core (RAM), and so will not cause a disk access (page fault) if referenced + ( + // memory in core + Sysno::mincore, + Syscall_Shape { + category: Memory, + types: &[Address, Length_Of_Bytes_Page_Aligned_Ceil, Byte_Stream], + syscall_return: Numeric_Or_Errno, + }, + ), + // give advice about use of memory + ( + Sysno::madvise, + Syscall_Shape { + category: Memory, + types: &[ + // only operates on whole pages + // so must be page aligned + Address, + Length_Of_Bytes_Page_Aligned_Ceil, + General_Flag(Madvise), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::select, + Syscall_Shape { + category: AsyncIO, + types: &[ + Numeric, + // you can set any of these sets to NULL if you don’t care about waiting for it + Pointer_To_Struct, + Pointer_To_Struct, + Pointer_To_Struct, + // Some Unices update the timeout here to show how much time is left, not all of them + // If you set the fields in your struct timeval to 0, + // select() will timeout immediately, effectively polling all the file descriptors in your sets. + // If you set the parameter timeout to NULL, + // it will wait forever until the first file descriptor is ready. + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::pselect6, + Syscall_Shape { + category: AsyncIO, + types: &[ + Numeric, + // you can set any of these sets to NULL if you don’t care about waiting for it + Pointer_To_Struct, + Pointer_To_Struct, + Pointer_To_Struct, + // pselect never updates timeout to indicate how much time is left (normal select does that in some unices) + // If you set the fields in your struct timeval to 0, + // select() will timeout immediately, effectively polling all the file descriptors in your sets. + // If you set the parameter timeout to NULL, + // it will wait forever until the first file descriptor is ready. + Pointer_To_Struct, + // The final argument of the pselect6() system call is not a sigset_t * pointer, but is instead a structure of the form: + // struct { + // const kernel_sigset_t *ss; /* Pointer to signal set */ + // size_t ss_len; /* Size (in bytes) of object pointed to by 'ss' */ + // }; + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::poll, + Syscall_Shape { + category: AsyncIO, + types: &[Array_Of_Struct, Unsigned_Numeric, Numeric], + // It doesn’t tell you which elements (you still have to scan for that), it only tell you how many, + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::ppoll, + Syscall_Shape { + category: AsyncIO, + types: &[ + Array_Of_Struct, + Unsigned_Numeric, + Pointer_To_Struct, + // if null then no mask manipulation is performed + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + // It doesn’t tell you which elements (you still have to scan for that), + syscall_return: Numeric_Or_Errno, + }, // it only tell you how many, + ), + ( + // This file descriptor is used for all the subsequent calls to the epoll interface. + // the file descriptor returned by epoll_create() should be closed by using close(2) + Sysno::epoll_create, + Syscall_Shape { + category: AsyncIO, + types: &[ + // in the past this size parameter told the kernel how many fds the caller expects to add + // the kerenl now however does not need that information and instead dynamically allocates space + // it is kept for backward compatibility + // and must be greater than zero + Unsigned_Numeric, + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + // This file descriptor is used for all the subsequent calls to the epoll interface. + // the file descriptor returned by epoll_create1() should be closed by using close(2) + // epoll_create but with a bahviour customizing flag + Sysno::epoll_create1, + Syscall_Shape { + category: AsyncIO, + types: &[ + // if this argument is zero, this syscall is identical to epoll_create + General_Flag(EPollCreate1Flags), + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + // A call to epoll_wait() will block until either: + // • a file descriptor delivers an event; + // • the call is interrupted by a signal handler (different from epoll_pwait) + // • the timeout expires. + Sysno::epoll_wait, + Syscall_Shape { + category: AsyncIO, + types: &[ + File_Descriptor(""), + Pointer_To_Struct, + Unsigned_Numeric, + // Time is measured against the CLOCK_MONOTONIC clock + // timeout interval will be rounded up to the system clock granularity + // -1 means block indefinitely + // 0 means return immediately + Numeric, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // similar to epoll_wait but in addition to waiting on specific signals + Sysno::epoll_pwait, + Syscall_Shape { + category: AsyncIO, + types: &[ + File_Descriptor(""), + Pointer_To_Struct, + Unsigned_Numeric, + // Time is measured against the CLOCK_MONOTONIC clock + // timeout interval will be rounded up to the system clock granularity + // -1 means block indefinitely + // 0 means return immediately + Numeric, + // if null this syscall is equivalent to epoll_pwait + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // similar to epoll_pwait but has nanosend resolution + Sysno::epoll_pwait2, + Syscall_Shape { + category: AsyncIO, + types: &[ + File_Descriptor(""), + Pointer_To_Struct, + Unsigned_Numeric, + // Time is measured against the CLOCK_MONOTONIC clock + // timeout interval will be rounded up to the system clock granularity + // -1 means block indefinitely + // 0 means return immediately + Pointer_To_Struct, + // if null this syscall is equivalent to epoll_pwait + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::epoll_ctl, + Syscall_Shape { + category: AsyncIO, + types: &[ + File_Descriptor(""), + General_Flag(EPollCTLOperationFlags), + File_Descriptor(""), + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::socket, + Syscall_Shape { + category: Network, + types: &[ + General_Flag(SocketFamily), + General_Flag(SocketType), + General_Flag(SocketProtocol), + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::bind, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::getsockname, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + // The returned information is truncated if the buffer provided is too small (addrlen small) + Pointer_To_Struct, + // upon return this pointer gets updated with the length of bytes written in the buffer + // but in this case of truncation + // it will return a value greater + // than was supplied to the call. + Pointer_To_Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::getpeername, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + // The returned information is truncated + // if the buffer provided is too small (addrlen small); + Pointer_To_Struct, + // upon return this pointer gets updated with the length of bytes written in the buffer + // but in this case of truncation + // it will return a value greater + // than was supplied to the call. + Pointer_To_Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::socketpair, + Syscall_Shape { + category: Network, + types: &[ + General_Flag(SocketFamily), + General_Flag(SocketType), + General_Flag(SocketProtocol), + // (ValueReturn(Pointer_To_File_Descriptor_Array(["", ""],syscall_return: Pointer_To_File_Descriptor_Array(["", ""])) + Pointer_To_File_Descriptor_Array(["", ""],) + ], + // on error sv is left unchanged + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::setsockopt, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + General_Flag(SocketLevel), + General_Flag(SocketOption), + // the argument should be + // nonzero to enable a boolean option, + // or zero if the option is to be disabled. + Pointer_To_Struct, + Pointer_To_Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::getsockopt, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + General_Flag(SocketLevel), + General_Flag(SocketOption), + Pointer_To_Struct, + // optlen is a value-result argument + // initially containing the size of optval buffer + // and on return modified to the actual size of the value returned + // can be NULL If no option value is to be supplied or returned, + Pointer_To_Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::listen, + Syscall_Shape { + category: Network, + types: &[File_Descriptor(""), Numeric], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::accept, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + // nullable, and when nullable it is not filled + Pointer_To_Struct, + // addrlen is a value-result argument + // initially containing the size of optval buffer + // and on return modified to the actual size of the value returned + // can be NULL If no option value is to be supplied or returned, + Pointer_To_Struct, + ], + // -1 on error, errno modified + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + // identical to accept + // except that it has flag arguments which save from doing extra calls to fcntl(2) + // the flags are to: 1- set socket as non-blocking, 2- set socket as close-on-exec + Sysno::accept4, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + // nullable, and when nullable it is not filled + Pointer_To_Struct, + // addrlen is a value-result argument + // initially containing the size of optval buffer + // and on return modified to the actual size of the value returned + // can be NULL If no option value is to be supplied or returned, + Pointer_To_Struct, + // if this flag is 0 then accept4 is identical to accept + General_Flag(SocketFlag), + ], + // -1 on error, errno modified + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::connect, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::sendto, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + 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 + Pointer_To_Struct, + // IGNORED if connection-mode (like TCP, or SEQ) (UDP IS CONNECTIONLESS) and must be null or 0 + Length_Of_Bytes_Specific, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::sendmsg, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + Pointer_To_Struct, + General_Flag(SocketMessageFlag), + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::recvfrom, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + // If a message is too long to fit in the supplied buffer, + // excess bytes may be discarded depending + // on the type of socket the message is received from. + Pointer_To_Text(""), + Length_Of_Bytes_Specific, + General_Flag(SocketMessageReceiveFlag), + // if src_addr and addrlen are NULL + // it means we do not care or want src_addr details + // otherwise addrlen is value-result argument + Pointer_To_Struct, + // value-result argument, will become the length of the buffer, and truncation rules apply + Pointer_To_Struct, + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::recvmsg, + Syscall_Shape { + category: Network, + types: &[ + File_Descriptor(""), + // If a message is too long to fit in the supplied buffer, + // excess bytes may be discarded depending + // on the type of socket the message is received from. + Pointer_To_Struct, + General_Flag(SocketMessageFlag), + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::shutdown, + Syscall_Shape { + category: Process, + types: &[File_Descriptor(""), General_Flag(SocketShutdownFlag)], + syscall_return: Numeric_Or_Errno, + }, + ), + // ( + // Sysno::sendfile, + // ), + ( + Sysno::fcntl, + Syscall_Shape { + category: FileOp, + types: &[ + File_Descriptor(""), + General_Flag(FcntlFlags), + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::ioctl, + Syscall_Shape { + category: Device, + types: &[ + File_Descriptor(""), + Unsigned_Numeric, + // The arg parameter to the ioctl is opaque at the generic vfs level (an opaque data type is a data type whose concrete data structure is not defined in an interface) + // How to interpret it is up to the driver or filesystem that actually handles it + // So it may be a pointer to userspace memory, or it could be an index, a flag, whatever + // It might even be unused and conventionally passed in a 0 + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // ( + // Sysno::prctl, + // ), + ( + Sysno::arch_prctl, + Syscall_Shape { + category: Process, + types: &[ + General_Flag(ArchPrctlFlags), + // TODO! this argument is a number for set operations and a pointer to a number for get operations + // Pointer_To_Numeric_Or_Numeric is a special case for arch_prctl, because it depends on the op union + Pointer_To_Numeric_Or_Numeric(None), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // causes the calling thread to relinquish the CPU. + // The thread is moved to the end of the queue for its static priority and a new thread gets to run. + ( + Sysno::sched_yield, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::rt_sigaction, + Syscall_Shape { + category: Signals, + types: &[ + // can be any valid signal except SIGKILL and SIGSTOP. + General_Flag(Signal), + Pointer_To_Struct, + // nullable meaning we dont want it + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::rt_sigprocmask, + Syscall_Shape { + category: Signals, + types: &[ + General_Flag(SignalHow), + // If NULL, then the signal mask is unchanged. + Pointer_To_Struct, + // If non-NULL, the previous value of the mask is stored here. + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // basically + // 1- change the signal mask + // 2- immediately BLOCK the process waiting for a signal on that new mask to trigger + // (its like what ptrace TRACE_ME does) + Sysno::rt_sigsuspend, + Syscall_Shape { + category: Signals, + types: &[ + // SIGKILL or SIGSTOP can not be blocked + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + // always returns -1, with errno set to indicate the error (normally, EINTR) + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // used during signal handling + // A signal stack is a special area of memory + // to be used as the execution stack during signal handlers + // It should be fairly large, to avoid any danger that it will overflow + Sysno::sigaltstack, + Syscall_Shape { + category: Signals, + types: &[ + // can be null if dont want this part of the operation + Pointer_To_Struct, + // NULLABLE meaning we dont want it + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // created to immediately run after signal handlers, to clean up and correct stack pointer/program counter + Sysno::rt_sigreturn, + Syscall_Shape { + category: Signals, + types: &[], + syscall_return: Never_Returns, + }, + ), + ( + Sysno::rt_sigpending, + Syscall_Shape { + category: Signals, + types: &[Pointer_To_Struct, Length_Of_Bytes_Specific], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::rt_sigtimedwait, + Syscall_Shape { + category: Signals, + types: &[ + Pointer_To_Struct, + // NULLABLE + Pointer_To_Struct, + Pointer_To_Struct, + Length_Of_Bytes_Specific, + ], + syscall_return: Signal_Or_Errno(""), + }, + ), + ( + // require registering a handler first via sigaction + // sends the data to an arbitrary thread with the thread group + Sysno::rt_sigqueueinfo, + Syscall_Shape { + category: Signals, + types: &[PID, General_Flag(Signal), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // require registering a handler first via sigaction + // sends the data to a specific thread withing the thread group + Sysno::rt_tgsigqueueinfo, + Syscall_Shape { + category: Signals, + types: &[PID, PID, General_Flag(Signal), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::signalfd, + Syscall_Shape { + category: Signals, + types: &[ + // fd of a file, or -1, let the kernel create a new file descriptor + File_Descriptor(""), + // It is not possible to receive SIGKILL or SIGSTOP + // SIGKILL or SIGSTOP can not be blocked + Pointer_To_Struct, + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::signalfd4, + Syscall_Shape { + category: Signals, + types: &[ + // fd of a file, or -1, let the kernel create a new file descriptor + File_Descriptor(""), + // It is not possible to receive SIGKILL or SIGSTOP + // SIGKILL or SIGSTOP can not be blocked + Pointer_To_Struct, + General_Flag(SignalFDFlags), + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + // The pidfd_open syscall allows users to obtain a file descriptor referring to the PID of the specified process. + // This syscall is useful in situations where one process needs access to the PID of another process in order to send signals, + // retrieve information about the process, or similar operations. + // It can also be used to monitor the lifetime of the process, since the file descriptor is closed when the process terminates. + ( + Sysno::pidfd_send_signal, + Syscall_Shape { + category: Signals, + types: &[ + File_Descriptor(""), + General_Flag(Signal), + // if null, its equivalent to the struct version which is provided a signal is sent using kill + // otherwise the buffer is equivalent to the info buffer specified by the rt_sigqueueinfo syscall + Pointer_To_Struct, + // reserved for future use, currently should be 0 + General_Flag(ReservedForFutureUse), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // always successful + Sysno::gettid, + Syscall_Shape { + category: Thread, + types: &[], + syscall_return: Always_Successful_Numeric, + }, + ), + // This is often used by routines that generate unique temporary filenames. + ( + // always successful + Sysno::getpid, + Syscall_Shape { + category: Thread, + types: &[], + syscall_return: Always_Successful_Numeric, + }, + ), + ( + // always successful + Sysno::getppid, + Syscall_Shape { + category: Thread, + types: &[], + syscall_return: Always_Successful_Numeric, + }, + ), + // These bytes can be used to seed user-space random number generators or for cryptographic purposes. + ( + Sysno::getrandom, + Syscall_Shape { + category: Device, + types: &[ + Pointer_To_Struct, + Length_Of_Bytes_Specific, + General_Flag(GetRandomFlags), + ], + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + Sysno::setrlimit, + Syscall_Shape { + category: Process, + types: &[General_Flag(ResourceFlags), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::getrlimit, + Syscall_Shape { + category: Process, + types: &[General_Flag(ResourceFlags), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // basically both, setrlimit and getrlimit in one syscall + // NULL when you dont want either + Sysno::prlimit64, + Syscall_Shape { + category: Process, + types: &[ + // if zero then operate on the calling process + PID, + General_Flag(ResourceFlags), + // NULLABLE + Pointer_To_Struct, + // NULLABLE + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + /* user CPU time used */ + /* system CPU time used */ + /* maximum resident set size */ + /* integral shared memory size */ + /* integral unshared data size */ + /* integral unshared stack size */ + /* page reclaims (soft page faults) */ + /* page faults (hard page faults) */ + /* swaps */ + /* block input operations */ + /* block output operations */ + /* IPC messages sent */ + /* IPC messages received */ + /* signals received */ + /* voluntary context switches */ + /* involuntary context switches */ + Sysno::getrusage, + Syscall_Shape { + category: Process, + types: &[General_Flag(RusageWhoFlags), Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::sysinfo, + Syscall_Shape { + category: Process, + types: &[Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::times, + Syscall_Shape { + category: Process, + types: &[Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::sched_setaffinity, + Syscall_Shape { + category: CPU, + types: &[ + // if zero then the calling thread is the thread referred to + PID, + Length_Of_Bytes_Specific, + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::sched_getaffinity, + Syscall_Shape { + category: CPU, + types: &[ + // if zero then the calling thread is the thread referred to + PID, + Length_Of_Bytes_Specific, + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // Any open file descriptors belonging to the process are closed. + // Any children of the process are inherited by init(1) + // (or by the nearest "subreaper" process as defined prctl(2) PR_SET_CHILD_SUBREAPER operation). + // The process's parent is sent a SIGCHLD signal. + Sysno::exit, + Syscall_Shape { + category: Process, + types: &[Numeric], + syscall_return: Never_Returns, + }, + ), + ( + Sysno::exit_group, + Syscall_Shape { + category: Process, + types: &[Numeric], + syscall_return: Never_Returns, + }, + ), + ( + // can be used to send a signal only to a process (i.e., thread group) as a whole, + // and the signal will be delivered to an arbitrary thread within that process. + // similar to rt_tgsigqueueinfo + Sysno::tgkill, + Syscall_Shape { + category: Thread, + types: &[ + // If tgid is specified as -1, tgkill() is equivalent to tkill(). + PID, + PID, + General_Flag(Signal), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // similar to rt_sigqueueinfo + Sysno::tkill, + Syscall_Shape { + category: Thread, + types: &[PID, General_Flag(Signal)], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::rseq, + Syscall_Shape { + category: Thread, + types: &[ + // Only one rseq can be registered per thread, + Pointer_To_Struct, + Length_Of_Bytes_Specific, + // 0 for registration, and RSEQ FLAG UNREGISTER for unregistration + General_Flag(RSeqFlag), + // Each supported architecture provides a RSEQ_SIG macro in sys/rseq.h + // which contains a signature. That signature is expected to be present in the code + // before each restartable sequences abort handler. + // Failure to provide the expected signature may terminate the process + // with a segmentation fault. + Unsigned_Numeric, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::uname, + Syscall_Shape { + category: System, + types: &[Pointer_To_Struct], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // always successful + Sysno::getuid, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Always_Successful_User_Group, + }, + ), + ( + // always successful + Sysno::geteuid, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Always_Successful_User_Group, + }, + ), + ( + // always successful + Sysno::getgid, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Always_Successful_User_Group, + }, + ), + ( + // always successful + Sysno::getegid, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Always_Successful_User_Group, + }, + ), + ( + // If the calling process is privileged (the process has the CAP_SETUID capability), + // then the real UID and saved set-user-ID are also set. + Sysno::setuid, + Syscall_Shape { + category: Process, + types: &[User_Group], + // The user ID specified in uid is not valid in this user namespace. + syscall_return: Numeric_Or_Errno, + }, // The user is not privileged (does not have the CAP_SETUID capability) + // and uid does not match the real UID or saved set-user-ID of the calling process. + ), + ( + Sysno::setgid, + Syscall_Shape { + category: Process, + types: &[User_Group], + // The calling process is not privileged (does not have the CAP_SETGID), + syscall_return: Numeric_Or_Errno, + }, // and gid does not match the real group ID or saved set-group-ID of the calling process. + ), + ( + // Before the introduction of futexes, system calls were required for locking and unlocking shared resources + // (for example semop). + Sysno::futex, + Syscall_Shape { + category: AsyncIO, + types: &[ + Pointer_To_Unsigned_Numeric, + General_Flag(FutexOpFlags), + Unsigned_Numeric, + Pointer_To_Struct, + Pointer_To_Unsigned_Numeric, + Unsigned_Numeric, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // always successful + // When set_child_tid is set, the very first thing the new thread does is to write its thread ID at this address. + + // When a thread whose clear_child_tid is not NULL terminates, then, + // if the thread is sharing memory with other threads, then 0 is written at the address specified in + // clear_child_tid and the kernel performs the following operation: + // futex(clear_child_tid, FUTEX_WAKE, 1, NULL, NULL, 0); + // The effect of this operation is to wake a single thread that is performing a futex wait on the memory location. + // Errors from the futex wake operation are ignored. + Sysno::set_tid_address, + Syscall_Shape { + category: Thread, + types: &[Pointer_To_Numeric(None)], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::eventfd, + Syscall_Shape { + category: FileOp, + types: &[Unsigned_Numeric], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::eventfd2, + Syscall_Shape { + category: FileOp, + types: &[Unsigned_Numeric, General_Flag(EventfdFlag)], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::wait4, + Syscall_Shape { + category: Process, + types: &[ + // < -1 wait for any child process whose process group ID is equal to the absolute value of pid. + // -1 wait for any child process. + // 0 wait for any child process whose process group ID is equal to that of the calling process at the time of the call to waitpid(). + // > 0 wait for the child whose process ID is equal to the value of pid. + User_Group, + // If wstatus is not NULL, wait4() stores status information in the int to which it points. + // This integer can be inspected with the following macros + // (which take the integer itself as an argument, not a pointer to it (as is done in syscall)) + Pointer_To_Numeric(None), + General_Flag(WaitEventFlags), + // NULLABLE means do not want + // resource usage information about the child + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::waitid, + Syscall_Shape { + category: Process, + types: &[ + General_Flag(WaitIdTypeFlags), + User_Group, + Pointer_To_Struct, + General_Flag(WaitEventFlags), + // NULLABLE means do not want + // resource usage information about the + // child, in the same manner as wait4(2). + Pointer_To_Struct, + ], + // returns 0 on success or if WNOHANG was specified and no child(ren) specified by id has yet changed state + syscall_return: Numeric_Or_Errno, + }, + ), + // + // ( + // Sysno::eventfd2, + // ), + // + ( + // in linux every thread can have a list of "robust futexes" + // threads in programs use this list as a contingency plan in the case that they die unexpectedly + // given that they are in user-space, the kernel can't do anything in case a thread dies while holding the lock, + // in that case the only way for waiting threads to be stopped is by rebooting! + // to fix this, in linux, whever a thread exits (any thread) the kernel checks if it has a robust futex list + // if it does, then the kernel walks the list of futexes + // and for every futex it cleans up and wakes any other waiter + Sysno::set_robust_list, + Syscall_Shape { + category: Process, + types: &[Address, Numeric], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // in linux every thread can have a list of "robust futexes" + // threads in programs use this list as a contingency plan in the case that they die unexpectedly + // given that they are in user-space, the kernel can't do anything in case a thread dies while holding the lock, + // in that case the only way for waiting threads to be stopped is by rebooting! + // to fix this, in linux, whever a thread exits (any thread) the kernel checks if it has a robust futex list + // if it does, then the kernel walks the list of futexes + // and for every futex it cleans up and wakes any other waiter + Sysno::get_robust_list, + Syscall_Shape { + category: Process, + types: &[User_Group, Address, Pointer_To_Numeric(None)], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::setpgid, + Syscall_Shape { + category: Process, + types: &[User_Group, User_Group], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::getpgid, + Syscall_Shape { + category: Process, + types: &[User_Group], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::getpgrp, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // run in separate memory spaces. + // At the time of fork() both memory spaces have the same content. + // Memory writes, file mappings, unmappings, performed by one of the processes do not affect the other. + + // The child process is an exact duplicate of the parent process except for the following points: + + // • The child has its own unique process ID, + + // • The child's and parent have the same parent process ID + + // • The child does not inherit memory locks (mlock(2), mlockall(2)). + + // • Process resource utilizations (getrusage(2)) and CPU time counters (times(2)) are reset to zero in the child. + + // • The child's set of pending signals is initially empty (sigpending(2)). + + // • The child does not inherit semaphore adjustments from its parent (semop(2)). + + // • The child does not inherit process-associated record locks from its parent (fcntl(2)). (On the other hand, it does inherit fcntl(2) open file description locks and + // flock(2) locks from its parent.) + + // • The child does not inherit timers from its parent (setitimer(2), alarm(2), timer_create(2)). + + // • The child does not inherit outstanding (unresolved) asynchronous I/O operations from its parent (aio_read(3), aio_write(3), nor does it inherit any asynchronous I/O contexts from + // its parent (see io_setup(2)). + + // The process attributes in the preceding list are all specified in POSIX.1. The parent and child also differ with respect to the following Linux-specific process attributes: + + // • The child does not inherit directory change notifications (dnotify) from its parent + + // • The prctl(2) PR_SET_PDEATHSIG setting is reset so that the child does not receive a signal when its parent terminates. + + // • The default timer slack value is set to the parent's current timer slack value. + + // • madvise(2) MADV_DONTFORK marked Memory mappings flag are not inherited + + // • madvise(2) MADV_WIPEONFORK marked Memory mappings are wiped + + // • The termination signal of the child is always SIGCHLD (see cl&2)). + + // • The port access permission bits set by ioperm(2) are not inherited by the child; the child must turn on any bits that it requires using ioperm(2). + + // Note the following further points: + + // • The child process is created with a single thread—the one that called fork(). The entire virtual address space of the parent is replicated in the child, including the + // states of mutexes, condition variables, and other pthreads objects; the use of pthread_atfork(3) may be helpful for dealing with problems that this can cause. + + // • After a fork() in a multithreaded program, the child can safely call only async-signal-safe functions (see signal-safety(7)) until such time as it calls execve(2). + + // • The child inherits copies of the parent's set of open file descriptors. Each file descriptor in the child refers to the same open file description (see open(2)) as the + // corresponding file descriptor in the parent. This means that the two file descriptors share open file status flags, file offset, and signal-driven I/O attributes (see + // the description of F_SETOWN and F_SETSIG in fcntl(2)). + + // • The child inherits copies of the parent's set of open message queue descriptors (see mq_overview(7)). Each file descriptor in the child refers to the same open message + // queue description as the corresponding file descriptor in the parent. This means that the two file descriptors share the same flags (mq_flags). + + // • The child inherits copies of the parent's set of open directory streams (see opendir(3)). POSIX.1 says that the corresponding directory streams in the parent and child + // may share the directory stream positioning; on Linux/glibc they do not. + Sysno::fork, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // 1- simpler version of the fork() system call. + // This is because executing the fork() system call, + // (before the copy-on-write mechanism was created) + // involved copying everything from the parent process, including address space, + // which was very inefficient. + // + // 2- the calling thread is suspended until the child terminates or makes a call to execve + // This is because both processes use the same address space, + // which contains the stack, stack pointer, and instruction pointer. + Sysno::vfork, + Syscall_Shape { + category: Process, + types: &[], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::clone3, + Syscall_Shape { + category: Process, + types: &[Pointer_To_Struct, Unsigned_Numeric], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::clone, + Syscall_Shape { + category: Process, + types: &[ + General_Flag(CloneFlags), + Address, + Pointer_To_Numeric(None), + Pointer_To_Numeric(None), + Unsigned_Numeric, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + // ( + // Sysno::setsid, + // ), + // ( + // Sysno::setreuid, + // ), + // ( + // Sysno::setregid, + // ), + // ( + // Sysno::getgroups, + // ), + // ( + // Sysno::setgroups, + // ), + // ( + // Sysno::setresuid, + // ), + // ( + // Sysno::getresuid, + // ), + // ( + // Sysno::setresgid, + // ), + // ( + // Sysno::getresgid, + // ), + // ( + // Sysno::setfsuid, + // ), + // ( + // Sysno::setfsgid, + // ), + // ( + // Sysno::getsid, + // ), + // ( + // Sysno::unshare, + // ), + ( + Sysno::nanosleep, + Syscall_Shape { + category: Process, + types: &[ + // The value of the nanoseconds field must be in the range [0, 999999999]. + Pointer_To_Struct, + // NULLABLE means do not want + Pointer_To_Struct, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::execve, + Syscall_Shape { + category: Process, + types: &[ + Pointer_To_Text(""), + // the first of these strings should be the filename of the file being executed + // terminated by a null pointer + Array_Of_Strings(&[]), + // terminated by a null pointer + Array_Of_Strings(&[]) + ], + // does not return on success + syscall_return: Numeric_Or_Errno, + }, + ), + + // ( + // Sysno::execveat, + // ), + // ( + // Sysno::kill, + // ), + // ( + // Sysno::shmget, + // ), + // ( + // Sysno::shmat, + // ), + // ( + // Sysno::shmctl, + // ), + // ( + // Sysno::pause, + // ), + // ( + // Sysno::getitimer, + // ), + // ( + // Sysno::alarm, + // ), + // ( + // Sysno::setitimer, + // ), + // ( + // Sysno::remap_file_pages, + // ), + // ( + // Sysno::mq_timedsend, + // ), + // ( + // Sysno::sendmmsg, + // ), + // ( + // Sysno::recvmmsg, + // ), + // ( + // Sysno::reboot, + // ), + // ( + // Sysno::sethostname, + // ), + // ( + // Sysno::setdomainname, + // ), + // ( + // Sysno::iopl, + // ) + + // ( + // Sysno::seccomp, + // ) + + // ( + // Sysno::bpf, + // ) + + // ( + // Sysno::semget, + // ) + + // ( + // Sysno::semop, + // ) + + // ( + // Sysno::semctl, + // ) + + // ( + // Sysno::shmdt, + // ) + + // ( + // Sysno::msgget, + // ) + + // ( + // Sysno::msgsnd, + // ) + + // ( + // Sysno::msgrcv, + // ) + + // ( + // Sysno::msgctl, + // ) + + // ( + // Sysno::flock, + // ) + + // ( + // Sysno::gettimeofday, + // ) + + // ( + // Sysno::ptrace, + // ) + + // ( + // Sysno::syslog, + // ) + ( + // landlocking is mostly a situation where a piece of software + // is protecting the user from the software itself, in the case that it is exploited + // think kubernetes/docker protecting you in case they were compromised + // for now its only file system related + // + // landlock is an access control system available to non-priviliged processes + // using these 3 linux syscalls + // it enables built-in sandboxing + // + // landlock is security sandboxing + // namespaces/containers are not considered security sandboxes + // they are resources "virtualization" tools + Sysno::landlock_create_ruleset, + Syscall_Shape { + category: Security, + types: &[ + // these actions will by default be forbidden if no future rules explicitly allows them + // Nullable + Pointer_To_Struct, + Length_Of_Bytes_Specific, + // flags must be 0 if attr is used. + // for now only: LANDLOCK_CREATE_RULESET_VERSION flag available + // If attr is NULL and size is 0, then the returned value is the highest supported Landlock ABI version + General_Flag(LandlockCreateFlag), + ], + syscall_return: File_Descriptor_Or_Errno(""), + }, + ), + ( + Sysno::landlock_add_rule, + Syscall_Shape { + category: Security, + types: &[ + File_Descriptor(""), + // currently only LANDLOCK_RULE_PATH_BENEATH : bla is file hierarchy. + General_Flag(LandlockRuleTypeFlag), + Pointer_To_Struct, + // must be 0 + General_Flag(LandlockAddRuleFlag), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::landlock_restrict_self, + Syscall_Shape { + category: Security, + types: &[ + File_Descriptor(""), + // must be 0 + General_Flag(LandlockRestrictFlag), + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // A sparse file is a file that is mostly empty, + // i.e. it contains large blocks of bytes whose value is 0 (zero). + // On the disk, the content of a file is stored in blocks of fixed size (usually 4 KiB or more). + // + // When all the bytes contained in such a block are 0, + // a file system that supports sparse files will not store the block on disk, + // instead it keeps the information somewhere in the file meta-data. + // + // offset and len must be a multiple of the filesystem logical block size, + Sysno::fallocate, + Syscall_Shape { + category: DiskIO, + types: &[ + File_Descriptor(""), + General_Flag(FallocFlags), + Length_Of_Bytes_Specific, + Length_Of_Bytes, + ], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + // this is what runs behind the nice command + Sysno::getpriority, + Syscall_Shape { + category: Process, + types: &[General_Flag(PriorityWhich), Numeric], + syscall_return: Priority_Or_Errno(MaybeUninit::::zeroed()), + }, + ), + ( + // this is what runs behind the nice command + Sysno::setpriority, + Syscall_Shape { + category: Process, + types: &[General_Flag(PriorityWhich), Numeric, Unsigned_Numeric], + syscall_return: Numeric_Or_Errno, + }, + ), + ( + Sysno::getdents, + Syscall_Shape { + category: DiskIO, + types: &[File_Descriptor(""), Pointer_To_Struct, Unsigned_Numeric], + // On end of directory, 0 is returned. + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + ( + // handle large filesystems and large file offsets. + Sysno::getdents64, + Syscall_Shape { + category: DiskIO, + types: &[File_Descriptor(""), Pointer_To_Struct, Unsigned_Numeric], + // On end of directory, 0 is returned. + syscall_return: Length_Of_Bytes_Specific_Or_Errno, + }, + ), + // ( + // Sysno::umask, + // ) + + // ( + // Sysno::mknod, + // ) + + // ( + // Sysno::mknodat, + // ) + + // ( + // Sysno::getdents, + // ) + + // ( + // Sysno::getdents64, + // ) + + // ( + // Sysno::capget, + // ) + + // ( + // Sysno::capset, + // ) + + // ( + // Sysno::utime, + // ) + + // ( + // Sysno::personality, + // ) + + // ( + // Sysno::sysfs, + // ) + + // ( + // Sysno::sched_setparam, + // ) + + // ( + // Sysno::sched_getparam, + // ) + + // ( + // Sysno::sched_setscheduler, + // ) + + // ( + // Sysno::sched_get_priority_max, + // ) + + // ( + // Sysno::sched_get_priority_min, + // ) + + // ( + // Sysno::sched_rr_get_interval, + // ) + + // ( + // Sysno::modify_ldt, + // ) + + // ( + // Sysno::adjtimex, + // ) + + // ( + // Sysno::settimeofday, + // ) + + // ( + // Sysno::ioperm, + // ) + + // ( + // Sysno::init_module, + // ) + + // ( + // Sysno::delete_module, + // ) + + // ( + // Sysno::quotactl, + // ) + + // ( + // Sysno::readahead, + // ) + + // ( + // Sysno::setxattr, + // ) + + // ( + // Sysno::lsetxattr, + // ) + + // ( + // Sysno::fsetxattr, + // ) + + // ( + // Sysno::getxattr, + // ) + + // ( + // Sysno::lgetxattr, + // ) + + // ( + // Sysno::fgetxattr, + // ) + + // ( + // Sysno::listxattr, + // ) + + // ( + // Sysno::llistxattr, + // ) + + // ( + // Sysno::flistxattr, + // ) + + // ( + // Sysno::removexattr, + // ) + + // ( + // Sysno::lremovexattr, + // ) + + // ( + // Sysno::fremovexattr, + // ) + + // ( + // Sysno::time, + // ) + + // ( + // Sysno::sched_setaffinity, + // ) + + // ( + // Sysno::sched_getaffinity, + // ) + + // ( + // Sysno::io_setup, + // ) + + // ( + // Sysno::io_getevents, + // ) + + // ( + // Sysno::io_submit, + // ) + + // ( + // Sysno::copy_file_range, + // ) + + // ( + // Sysno::io_cancel, + // ) + + // ( + // Sysno::splice, + // ) + + // ( + // Sysno::vmsplice, + // ) + + // ( + // Sysno::semtimedop, + // ) + + // ( + // Sysno::fadvise64, + // ) + + // ( + // Sysno::timer_create, + // ) + + // ( + // Sysno::timer_settime, + // ) + + // ( + // Sysno::timer_gettime, + // ) + + // ( + // Sysno::timer_getoverrun, + // ) + + // ( + // Sysno::timer_delete, + // ) + + // ( + // Sysno::clock_settime, + // ) + + // ( + // Sysno::clock_gettime, + // ) + + // ( + // Sysno::clock_getres, + // ) + + // ( + // Sysno::clock_nanosleep, + // ) + + // ( + // Sysno::utimes, + // ) + + // ( + // Sysno::mbind, + // ) + + // ( + // Sysno::set_mempolicy, + // ) + + // ( + // Sysno::get_mempolicy, + // ) + + // ( + // Sysno::mq_open, + // ) + + // ( + // Sysno::mq_timedreceive, + // ) + + // ( + // Sysno::mq_notify, + // ) + + // ( + // Sysno::mq_getsetattr, + // ) + + // ( + // Sysno::kexec_load, + // ) + + // ( + // Sysno::add_key, + // ) + + // ( + // Sysno::request_key, + // ) + + // ( + // Sysno::keyctl, + // ) + + // ( + // Sysno::ioprio_set, + // ) + + // ( + // Sysno::ioprio_get, + // ) + + // ( + // Sysno::inotify_add_watch, + // ) + + // ( + // Sysno::inotify_rm_watch, + // ) + + // ( + // Sysno::migrate_pages, + // ) + + // ( + // Sysno::futimesat, + // ) + + // ( + // Sysno::tee, + // ) + + // ( + // Sysno::sync_file_range, + // ) + + // ( + // Sysno::move_pages, + // ) + + // ( + // Sysno::utimensat, + // ) + + // ( + // Sysno::timerfd_create, + // ) + + // ( + // Sysno::timerfd_settime, + // ) + + // ( + // Sysno::timerfd_gettime, + // ) + + // ( + // Sysno::perf_event_open, + // ) + + // ( + // Sysno::fanotify_init, + // ) + + // ( + // Sysno::fanotify_mark, + // ) + + // ( + // Sysno::name_to_handle_at, + // ) + + // ( + // Sysno::open_by_handle_at, + // ) + + // ( + // Sysno::clock_adjtime, + // ) + + // ( + // Sysno::getcpu, + // ) + + // ( + // Sysno::process_vm_readv, + // ) + + // ( + // Sysno::process_vm_writev, + // ) + + // ( + // Sysno::kcmp, + // ) + + // ( + // Sysno::finit_module, + // ) + + // ( + // Sysno::sched_setattr, + // ) + + // ( + // Sysno::sched_getattr, + // ) + + // ( + // Sysno::memfd_create, + // ) + + // ( + // Sysno::kexec_file_load, + // ) + + // ( + // Sysno::membarrier, + // ) + + // ( + // Sysno::pkey_mprotect, + // ) + + // ( + // Sysno::faccessat2, + // ) + + // ( + // Sysno::pkey_alloc, + // ) + + // ( + // Sysno::io_pgetevents, + // ) + + // ( + // Sysno::io_uring_setup, + // ) + + // ( + // Sysno::io_uring_enter, + // ) + + // ( + // Sysno::io_uring_register, + // ) + + // ( + // Sysno::open_tree, + // ) + + // ( + // Sysno::move_mount, + // ) + + // ( + // Sysno::fsopen, + // ) + + // ( + // Sysno::fsconfig, + // ) + + // ( + // Sysno::fsmount, + // ) + + // ( + // Sysno::fspick, + // ) + + // ( + // Sysno::pidfd_open, + // ) + + // ( + // Sysno::close_range, + // ) + + // ( + // Sysno::pidfd_getfd, + // ) + + // ( + // Sysno::process_madvise, + // ) + + // ( + // Sysno::mount_setattr, + // ) + + // ( + // Sysno::quotactl_fd, + // ) + + // ( + // Sysno::memfd_secret, + // ) + + // ( + // Sysno::process_mrelease, + // ) + + // ( + // Sysno::futex_waitv, + // ) + + // ( + // Sysno::set_mempolicy_home_node, + // ) + + // ( + // Sysno::map_shadow_stack, + // ) + + // ( + // Sysno::futex_wake, + // ) + + // ( + // Sysno::futex_wait, + // ) + + // ( + // Sysno::futex_requeue, + // ) + + // ( + // Sysno::listmount, + // ) + + // ( + // Sysno::lsm_get_self_attr, + // ) + + // ( + // Sysno::lsm_set_self_attr, + // ) + + // ( + // Sysno::lsm_list_modules, + // ) + // ( + // Sysno::sched_getscheduler + // ) + + // ( + // Sysno::vhangup + // ) + + // ( + // Sysno::acct + // ) + + // ( + // Sysno::io_destroy + // ) + + // ( + // Sysno::restart_syscall + // ) + + // ( + // Sysno::mq_unlink + // ) + + // ( + // Sysno::inotify_init + // ) + + // ( + // Sysno::inotify_init1 + // ) + + // ( + // Sysno::setns + // ) + + // ( + // Sysno::userfaultfd + // ) + + // ( + // Sysno::pkey_free + // ) + ]; + + array.into_iter().collect() +} diff --git a/src/types.rs b/src/types.rs index 4ef6e76..e2f7c41 100644 --- a/src/types.rs +++ b/src/types.rs @@ -1,15 +1,17 @@ -use std::{fmt::Display, mem::MaybeUninit}; -use colored::Colorize; use crate::utilities::PAGE_SIZE; +use colored::Colorize; +use std::{convert::Infallible, fmt::Display, marker::PhantomData, mem::MaybeUninit}; pub type Annotation = [&'static str; 2]; -pub type SysDetails = ( - Category, - &'static str, - &'static [(Annotation, SysArg)], - (Annotation, SysReturn), -); +pub type SysAnnotations = (Category, &'static str, &'static [Annotation], Annotation); + +#[derive(Clone)] +pub struct Syscall_Shape { + pub category: Category, + pub types: &'static [SysArg], + pub syscall_return: SysReturn, +} #[derive(Clone, Copy, Debug)] pub enum Flag { @@ -75,8 +77,7 @@ type ADDRESS = &'static str; type SIGNAL = &'static str; type TEXT = &'static str; - -#[derive(Clone, Copy, Debug)] +#[derive(Clone, Debug)] pub enum SysArg { Numeric, Unsigned_Numeric, @@ -105,10 +106,6 @@ pub enum SysArg { File_Descriptor_openat(FD), } -enum types { - Pointer_To(T) -} - #[derive(Clone, Copy, Debug)] pub enum SysReturn { Numeric_Or_Errno, @@ -186,7 +183,7 @@ impl Display for Category { } // TODO! -// consider humansize crate +// consider humansize crate pub enum Bytes { norm(usize), @@ -314,7 +311,6 @@ impl Display for BytesPagesRelevant { } } - #[repr(C)] #[derive(Debug)] pub enum mlock2 { diff --git a/src/utilities.rs b/src/utilities.rs index c50defa..dc08d50 100644 --- a/src/utilities.rs +++ b/src/utilities.rs @@ -1,4 +1,4 @@ -use crate::{syscalls_map::initialize_syscall_map, types::SysDetails}; +use crate::{syscall_annotations_map::initialize_syscall_annotations_map, syscall_skeleton_map::initialize_syscall_skeleton_map, types::{SysAnnotations, Syscall_Shape}}; use lazy_static::lazy_static; use nix::{errno::Errno, libc::__errno_location, unistd::Pid}; use procfs::process::{MMapPath, MemoryMap}; @@ -7,33 +7,14 @@ use std::{ }; use syscalls::Sysno; -macro_rules! p { - ($a:expr) => { - println!("{:?}", $a) - }; -} - -macro_rules! pp { - ($a:expr,$b:expr) => { - println!("{:?}, {:?}", $a, $b) - }; -} - -macro_rules! ppp { - ($a:expr,$b:expr,$c:expr) => { - println!("{:?}, {:?}, {:?}", $a, $b, $c) - }; -} - pub static mut UNSUPPORTED: Vec<&'static str> = Vec::new(); - thread_local! { pub static PRE_CALL_PROGRAM_BREAK_POINT: Cell = Cell::new(0); - pub static INTENT: Cell = Cell::new(true); pub static STRING_LIMIT: Cell = Cell::new(36); - pub static QUIET: Cell = Cell::new(false); pub static FAILED_ONLY: Cell = Cell::new(false); + pub static QUIET: Cell = Cell::new(false); + pub static ANNOT: Cell = Cell::new(false); pub static ATTACH: Cell> = Cell::new(None); // TODO! Time blocks feature // pub static TIME_BLOCKS: Cell = Cell::new(false); @@ -45,7 +26,8 @@ lazy_static! { pub static ref SUMMARY: AtomicBool = AtomicBool::new(false); pub static ref OUTPUT: Mutex> = Mutex::new(HashMap::new()); pub static ref OUTPUT_FOLLOW_FORKS: Mutex> = Mutex::new(HashMap::new()); - pub static ref SYSCALL_MAP: HashMap = initialize_syscall_map(); + pub static ref SYSANNOT_MAP: HashMap = initialize_syscall_annotations_map(); + pub static ref SYSKELETON_MAP: HashMap = initialize_syscall_skeleton_map(); pub static ref PAGE_SIZE: usize = page_size::get(); } @@ -73,6 +55,7 @@ Options: -f, --follow-forks trace child processes when traced programs create them -z, --failed-only only print failed syscalls -q, --mute-stdout mute the traced program's std output + -a, --annotations print the classic strace feed with argument annotations -h, --help print help -v, --version print version "); @@ -157,6 +140,16 @@ Options: let _ = args.next().unwrap(); QUIET.set(true); } + "-a" | "--annotations" => { + let _ = args.next().unwrap(); + if FOLLOW_FORKS.load(Ordering::SeqCst) { + eprintln!( + "Usage: printing annotations and fork following are mutually exclusive\n" + ); + std::process::exit(100); + } + ANNOT.set(true); + } _ => break, } }