Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 6 additions & 6 deletions crates/fspy_preload_unix/src/client/convert.rs
Original file line number Diff line number Diff line change
Expand Up @@ -107,15 +107,15 @@ impl ToAbsolutePath for Fd {
}
}

pub struct PathAt(pub c_int, pub *const c_char);
pub struct PathAt<'a, R>(pub c_int, pub sigsafe::CStr<'a, R>);

impl ToAbsolutePath for PathAt {
impl<Repr> ToAbsolutePath for PathAt<'_, Repr> {
unsafe fn to_absolute_path<R, F: FnOnce(Option<&BStr>) -> nix::Result<R>>(
self,
f: F,
) -> nix::Result<R> {
// SAFETY: self.1 is a non-null pointer to a valid null-terminated C string, as guaranteed by the libc calling convention
let pathname = unsafe { CStr::from_ptr(self.1) }.to_bytes().as_bstr();
// SAFETY: self.1 is a valid NUL-terminated string.
let pathname = unsafe { CStr::from_ptr(self.1.as_ptr()) }.to_bytes().as_bstr();

if pathname.first().copied() == Some(b'/') {
f(pathname.into())
Expand Down Expand Up @@ -148,12 +148,12 @@ impl ToAbsolutePath for PathAt {
}
}

impl ToAbsolutePath for *const c_char {
impl<Repr> ToAbsolutePath for sigsafe::CStr<'_, Repr> {
unsafe fn to_absolute_path<R, F: FnOnce(Option<&BStr>) -> nix::Result<R>>(
self,
f: F,
) -> nix::Result<R> {
// SAFETY: delegates to PathAt::to_absolute_path with AT_FDCWD and the caller-provided C string pointer
// SAFETY: delegates the same caller-provided C string to PathAt.
unsafe { PathAt(libc::AT_FDCWD, self).to_absolute_path(f) }
}
}
Expand Down
4 changes: 2 additions & 2 deletions crates/fspy_preload_unix/src/interceptions/access.rs
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ intercept!(access(64): unsafe extern "C" fn(pathname: *const c_char, mode: c_int
unsafe extern "C" fn access(pathname: *const c_char, mode: c_int) -> c_int {
// SAFETY: pathname is a valid C string pointer provided by the caller of the interposed function
unsafe {
handle_open(pathname, AccessMode::READ);
handle_open(sigsafe::CStr::from_ptr(pathname), AccessMode::READ);
}
// SAFETY: calling the original libc access() with the same arguments forwarded from the interposed function
unsafe { access::original()(pathname, mode) }
Expand All @@ -25,7 +25,7 @@ unsafe extern "C" fn faccessat(
) -> c_int {
// SAFETY: dirfd and pathname are valid arguments provided by the caller of the interposed function
unsafe {
handle_open(PathAt(dirfd, pathname), AccessMode::READ);
handle_open(PathAt(dirfd, sigsafe::CStr::from_ptr(pathname)), AccessMode::READ);
}
// SAFETY: calling the original libc faccessat() with the same arguments forwarded from the interposed function
unsafe { faccessat::original()(dirfd, pathname, mode, flags) }
Expand Down
6 changes: 3 additions & 3 deletions crates/fspy_preload_unix/src/interceptions/dirent.rs
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ unsafe extern "C" fn scandir(
compar: *const c_void,
) -> c_int {
// SAFETY: dirname is a valid C string pointer provided by the caller of the interposed function
unsafe { handle_open(dirname, AccessMode::READ_DIR) }
unsafe { handle_open(sigsafe::CStr::from_ptr(dirname), AccessMode::READ_DIR) }
// SAFETY: calling the original libc scandir() with the same arguments forwarded from the interposed function
unsafe { scandir::original()(dirname, namelist, select, compar) }
}
Expand All @@ -41,7 +41,7 @@ mod macos_only {
compar: *const c_void,
) -> c_int {
// SAFETY: dirname is a valid C string pointer provided by the caller of the interposed function
unsafe { handle_open(dirname, AccessMode::READ_DIR) };
unsafe { handle_open(sigsafe::CStr::from_ptr(dirname), AccessMode::READ_DIR) };
// SAFETY: calling the original libc scandir_b() with the same arguments forwarded from the interposed function
unsafe { scandir_b::original()(dirname, namelist, select, compar) }
}
Expand Down Expand Up @@ -84,7 +84,7 @@ unsafe extern "C" fn fdopendir(fd: c_int) -> *mut DIR {
intercept!(opendir(64): unsafe extern "C" fn (*const c_char) -> *mut DIR);
unsafe extern "C" fn opendir(dir_name: *const c_char) -> *mut DIR {
// SAFETY: dir_name is a valid C string pointer provided by the caller of the interposed function
unsafe { handle_open(dir_name, AccessMode::READ_DIR) };
unsafe { handle_open(sigsafe::CStr::from_ptr(dir_name), AccessMode::READ_DIR) };
// SAFETY: calling the original libc opendir() with the same arguments forwarded from the interposed function
unsafe { opendir::original()(dir_name) }
}
4 changes: 3 additions & 1 deletion crates/fspy_preload_unix/src/interceptions/linux_syscall.rs
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,9 @@ unsafe extern "C" fn syscall(syscall_no: c_long, mut args: ...) -> c_long {
}
} else {
// SAFETY: pathname is a non-null C string pointer provided by the statx syscall caller.
unsafe { handle_open(PathAt(dirfd, pathname), AccessMode::READ) };
unsafe {
handle_open(PathAt(dirfd, sigsafe::CStr::from_ptr(pathname)), AccessMode::READ);
}
}
}
// SAFETY: forwarding the syscall to the original libc syscall function with the extracted arguments
Expand Down
12 changes: 6 additions & 6 deletions crates/fspy_preload_unix/src/interceptions/open.rs
Original file line number Diff line number Diff line change
Expand Up @@ -28,7 +28,7 @@ type Mode = c_int;
intercept!(open(64): unsafe extern "C" fn(*const c_char, c_int, args: ...) -> c_int);
unsafe extern "C" fn open(path: *const c_char, flags: c_int, mut args: ...) -> c_int {
// SAFETY: path is a valid C string pointer provided by the caller of the interposed function
unsafe { handle_open(path, OpenFlags(flags)) };
unsafe { handle_open(sigsafe::CStr::from_ptr(path), OpenFlags(flags)) };
if has_mode_arg(flags) {
// SAFETY: when O_CREAT or O_TMPFILE is set, a mode_t argument is required by the open() contract
let mode: Mode = unsafe { args.next_arg() };
Expand All @@ -48,7 +48,7 @@ unsafe extern "C" fn openat(
mut args: ...
) -> c_int {
// SAFETY: dirfd and path are valid arguments provided by the caller of the interposed function
unsafe { handle_open(PathAt(dirfd, path), OpenFlags(flags)) };
unsafe { handle_open(PathAt(dirfd, sigsafe::CStr::from_ptr(path)), OpenFlags(flags)) };

if has_mode_arg(flags) {
// https://github.com/tailhook/openat/issues/21#issuecomment-535914957
Expand All @@ -67,7 +67,7 @@ intercept!(open_nocancel: unsafe extern "C" fn(*const c_char, c_int, ...) -> c_i
#[cfg(target_os = "macos")]
unsafe extern "C" fn open_nocancel(path: *const c_char, flags: c_int, mut args: ...) -> c_int {
// SAFETY: path is a valid C string pointer provided by the caller of open$NOCANCEL
unsafe { handle_open(path, OpenFlags(flags)) };
unsafe { handle_open(sigsafe::CStr::from_ptr(path), OpenFlags(flags)) };
if has_mode_arg(flags) {
// SAFETY: O_CREAT requires a mode argument, matching the open$NOCANCEL contract
let mode: Mode = unsafe { args.next_arg() };
Expand All @@ -89,7 +89,7 @@ unsafe extern "C" fn openat_nocancel(
mut args: ...
) -> c_int {
// SAFETY: dirfd and path are valid arguments provided by the caller of openat$NOCANCEL
unsafe { handle_open(PathAt(dirfd, path), OpenFlags(flags)) };
unsafe { handle_open(PathAt(dirfd, sigsafe::CStr::from_ptr(path)), OpenFlags(flags)) };
if has_mode_arg(flags) {
// SAFETY: O_CREAT requires a mode argument, matching the openat$NOCANCEL contract
let mode: Mode = unsafe { args.next_arg() };
Expand All @@ -104,7 +104,7 @@ unsafe extern "C" fn openat_nocancel(
intercept!(fopen(64): unsafe extern "C" fn(path: *const c_char, mode: *const c_char) -> *mut FILE);
unsafe extern "C" fn fopen(path: *const c_char, mode: *const c_char) -> *mut libc::FILE {
// SAFETY: path and mode are valid C string pointers provided by the caller of the interposed function
unsafe { handle_open(path, ModeStr(mode)) };
unsafe { handle_open(sigsafe::CStr::from_ptr(path), ModeStr(mode)) };
// SAFETY: calling the original libc fopen() with the same arguments forwarded from the interposed function
unsafe { fopen::original()(path, mode) }
}
Expand All @@ -116,7 +116,7 @@ unsafe extern "C" fn freopen(
stream: *mut FILE,
) -> *mut FILE {
// SAFETY: path and mode are valid C string pointers provided by the caller of the interposed function
unsafe { handle_open(path, ModeStr(mode)) };
unsafe { handle_open(sigsafe::CStr::from_ptr(path), ModeStr(mode)) };
// SAFETY: calling the original libc freopen() with the same arguments forwarded from the interposed function
unsafe { freopen::original()(path, mode, stream) }
}
Original file line number Diff line number Diff line change
Expand Up @@ -197,7 +197,7 @@ mod linux_only {
let _unused = execveat::original;
// SAFETY: PathAt wraps a valid dirfd and pathname pointer from the interposed execveat call
let abs_path_result = unsafe {
PathAt(dirfd, pathname).to_absolute_path(|path| {
PathAt(dirfd, sigsafe::CStr::from_ptr(pathname)).to_absolute_path(|path| {
let Some(path) = path else {
return Ok(None);
};
Expand Down
8 changes: 4 additions & 4 deletions crates/fspy_preload_unix/src/interceptions/stat.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ intercept!(stat(64): unsafe extern "C" fn(path: *const c_char, buf: *mut stat_st
unsafe extern "C" fn stat(path: *const c_char, buf: *mut stat_struct) -> c_int {
// SAFETY: path is a valid C string pointer provided by the caller of the interposed function
unsafe {
handle_open(path, AccessMode::READ);
handle_open(sigsafe::CStr::from_ptr(path), AccessMode::READ);
}
// SAFETY: calling the original libc stat() with the same arguments forwarded from the interposed function
unsafe { stat::original()(path, buf) }
Expand All @@ -23,7 +23,7 @@ unsafe extern "C" fn lstat(path: *const c_char, buf: *mut stat_struct) -> c_int
// TODO: add accessmode ReadNoFollow
// SAFETY: path is a valid C string pointer provided by the caller of the interposed function
unsafe {
handle_open(path, AccessMode::READ);
handle_open(sigsafe::CStr::from_ptr(path), AccessMode::READ);
}
// SAFETY: calling the original libc lstat() with the same arguments forwarded from the interposed function
unsafe { lstat::original()(path, buf) }
Expand All @@ -38,7 +38,7 @@ unsafe extern "C" fn fstatat(
) -> c_int {
// SAFETY: dirfd and pathname are valid arguments provided by the caller of the interposed function
unsafe {
handle_open(PathAt(dirfd, pathname), AccessMode::READ);
handle_open(PathAt(dirfd, sigsafe::CStr::from_ptr(pathname)), AccessMode::READ);
}
// SAFETY: calling the original libc fstatat() with the same arguments forwarded from the interposed function
unsafe { fstatat::original()(dirfd, pathname, buf, flags) }
Expand Down Expand Up @@ -75,7 +75,7 @@ unsafe extern "C" fn statx(
}
} else {
// SAFETY: pathname is a non-null C string pointer provided by the statx caller.
unsafe { handle_open(PathAt(dirfd, pathname), AccessMode::READ) };
unsafe { handle_open(PathAt(dirfd, sigsafe::CStr::from_ptr(pathname)), AccessMode::READ) };
}
// SAFETY: calling the original libc statx() with the same arguments forwarded from the interposed function
unsafe { original(dirfd, pathname, flags, mask, statxbuf) }
Expand Down
Loading