summary refs log tree commit diff
path: root/ripple/minitrace
diff options
context:
space:
mode:
authoredef <edef@unfathomable.blue>2022-07-29 22:20:08 +0000
committeredef <edef@unfathomable.blue>2022-07-29 22:20:08 +0000
commit51e0657d496651fbbc73b34d85f949206491197a (patch)
tree9570ac2810fb7289cbf6eaba69cc82645ac9dad4 /ripple/minitrace
parent95440d3f5355791632adb389e2c4016b63c8d6c0 (diff)
downloadunf-legacy-51e0657d496651fbbc73b34d85f949206491197a.tar.zst
ripple/minitrace: strictly verify fd arguments
Change-Id: I9210105171314d036dc12a1b36ce01aaeeb2466d
Diffstat (limited to 'ripple/minitrace')
-rw-r--r--ripple/minitrace/src/main.rs90
1 files changed, 70 insertions, 20 deletions
diff --git a/ripple/minitrace/src/main.rs b/ripple/minitrace/src/main.rs
index 6d5dbc5..4735603 100644
--- a/ripple/minitrace/src/main.rs
+++ b/ripple/minitrace/src/main.rs
@@ -19,6 +19,7 @@ use {
 		convert::TryInto,
 		env,
 		ffi::CString,
+		fmt::{self, Debug},
 		fs::File,
 		io::{self, BufRead, Seek, SeekFrom},
 		os::unix::process::CommandExt,
@@ -26,9 +27,6 @@ use {
 	},
 };
 
-#[cfg(test)]
-use std::fmt::{self, Debug};
-
 // TODO(edef): consider implementing this in terms of TID?
 // tgids are a strict subset of tids
 #[derive(Debug, Copy, Clone, PartialEq, Eq, PartialOrd, Ord, Hash)]
@@ -316,8 +314,6 @@ impl SyscallArg for *mut u8 {
 	}
 }
 
-type FileDesc = i32;
-
 type SigAction = ();
 type SysInfo = ();
 type Tms = ();
@@ -342,7 +338,7 @@ define_syscalls! {
 		fn read(fd: FileDesc, buf: *mut u8, count: usize) -> i64 = 0;
 		fn write(fd: FileDesc, buf: *const u8, count: usize) -> i64 = 1;
 		fn close(fd: FileDesc) -> i64 = 3;
-		fn mmap(addr: u64, len: u64, prot: ProtFlags, flags: MapFlags, fd: FileDesc, off: u64) -> i64 = 9;
+		fn mmap(addr: u64, len: u64, prot: ProtFlags, flags: MapFlags, fd: Option<FileDesc>, off: u64) -> i64 = 9;
 		fn mprotect(addr: u64, len: usize, prot: ProtFlags) -> i64 = 10;
 		fn brk(brk: u64) -> i64 = 12;
 		fn rt_sigaction(sig: Signal, act: *const SigAction, oact: *mut SigAction, sigsetsize: usize) -> i64 = 13;
@@ -356,8 +352,8 @@ define_syscalls! {
 		fn arch_prctl(option: ArchOption, arg2: u64) -> i64 = 158;
 		fn set_tid_address(tidptr: *mut i32) -> i64 = 218;
 		fn exit_group(error_code: i32) -> i64 = 231;
-		fn openat(dfd: FileDesc, filename: CString, flags: OpenFlags, mode: FileMode) -> i64 = 257;
-		fn newfstatat(dfd: FileDesc, filename: CString, statbuf: *mut Stat, flags: AtFlags) -> i64 = 262;
+		fn openat(dfd: DirFd, filename: CString, flags: OpenFlags, mode: FileMode) -> i64 = 257;
+		fn newfstatat(dfd: DirFd, filename: CString, statbuf: *mut Stat, flags: AtFlags) -> i64 = 262;
 		fn set_robust_list(head: *mut RobustListHead, len: usize) -> i64 = 273;
 		fn prlimit64(pid: i32, resource: ResourceLimit, new_rlim: *const RLimit64, old_rlim: *mut RLimit64) -> i64 = 302;
 		fn getrandom(ubuf: *mut u8, len: usize, flags: GrndFlags) -> i64 = 318;
@@ -468,11 +464,15 @@ fn check_syscall(entry: &SyscallEntry) -> bool {
 			if addr % 4096 != 0 {
 				return false;
 			}
-			if fd == !0 {
-				return flags.contains(MapFlags::ANONYMOUS);
-			} else {
-				return flags.intersection(MapFlags::PRIVATE | MapFlags::ANONYMOUS)
-					== MapFlags::PRIVATE;
+
+			match fd {
+				None => {
+					return flags.contains(MapFlags::ANONYMOUS);
+				}
+				Some(_) => {
+					return flags.intersection(MapFlags::PRIVATE | MapFlags::ANONYMOUS)
+						== MapFlags::PRIVATE;
+				}
 			}
 		}
 		SyscallEntry::mprotect { addr, len, prot: _ } => {
@@ -509,11 +509,11 @@ fn check_syscall(entry: &SyscallEntry) -> bool {
 			flags,
 			mode: _,
 		} => {
-			if dfd != AT_FDCWD {
+			if dfd != DirFd::Cwd {
 				return false;
 			}
 
-			println!("openat(AT_FDCWD, {filename:?}, {flags:?}, ..)");
+			println!("openat({dfd:?}, {filename:?}, {flags:?}, ..)");
 		}
 		SyscallEntry::newfstatat {
 			dfd,
@@ -526,11 +526,8 @@ fn check_syscall(entry: &SyscallEntry) -> bool {
 					// empty path without AT_EMPTY_PATH
 					return false;
 				}
-				(AT_FDCWD, _) => {
-					println!("newfstatat(AT_FDCWD, {filename:?}, .., {flags:?})");
-				}
-				(_, b"") if dfd >= 0 => {
-					println!("newfstatat({dfd}, {filename:?}, .., {flags:?})");
+				(DirFd::Cwd, _) | (_, b"") => {
+					println!("newfstatat({dfd:?}, {filename:?}, .., {flags:?})");
 				}
 				_ => {
 					return false;
@@ -642,3 +639,56 @@ syscall_enums! {
 		SEGV = 11 => SIGSEGV,
 	}
 }
+
+#[derive(Clone, Copy, Eq, PartialEq)]
+struct FileDesc(i32);
+
+impl Debug for FileDesc {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		write!(f, "{}", self.0)
+	}
+}
+
+impl SyscallArg for FileDesc {
+	fn try_from_reg(reg: u64) -> Option<Self> {
+		Some(match i32::try_from_reg(reg)? {
+			fd @ 0..=i32::MAX => FileDesc(fd),
+			_ => return None,
+		})
+	}
+}
+
+impl SyscallArg for Option<FileDesc> {
+	fn try_from_reg(reg: u64) -> Option<Self> {
+		Some(match i32::try_from_reg(reg)? {
+			-1 => None,
+			fd @ 0..=i32::MAX => Some(FileDesc(fd)),
+			_ => return None,
+		})
+	}
+}
+
+#[derive(Clone, Copy, Eq, PartialEq)]
+enum DirFd {
+	Cwd,
+	Fd(FileDesc),
+}
+
+impl Debug for DirFd {
+	fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+		match *self {
+			DirFd::Cwd => write!(f, "AT_FDCWD"),
+			DirFd::Fd(FileDesc(fd)) => write!(f, "{fd}"),
+		}
+	}
+}
+
+impl SyscallArg for DirFd {
+	fn try_from_reg(reg: u64) -> Option<Self> {
+		Some(match i32::try_from_reg(reg)? {
+			AT_FDCWD => Self::Cwd,
+			fd @ 0..=i32::MAX => DirFd::Fd(FileDesc(fd)),
+			_ => return None,
+		})
+	}
+}