diff --git a/changelog.d/2889.changed.md b/changelog.d/2889.changed.md new file mode 100644 index 00000000000..ed48d4898f0 --- /dev/null +++ b/changelog.d/2889.changed.md @@ -0,0 +1 @@ +log better errors of local file creation and add option to use alternative way diff --git a/mirrord-schema.json b/mirrord-schema.json index bcfadb25472..356ba6d3bf2 100644 --- a/mirrord-schema.json +++ b/mirrord-schema.json @@ -811,6 +811,14 @@ "boolean", "null" ] + }, + "use_dev_null": { + "title": "_experimental_ use_dev_null {#experimental-use_dev_null}", + "description": "Uses /dev/null for creating local fake files (should be better than using /tmp)", + "type": [ + "boolean", + "null" + ] } }, "additionalProperties": false diff --git a/mirrord/config/src/experimental.rs b/mirrord/config/src/experimental.rs index a226af6793e..3a232514836 100644 --- a/mirrord/config/src/experimental.rs +++ b/mirrord/config/src/experimental.rs @@ -52,6 +52,12 @@ pub struct ExperimentalConfig { /// This option applies only on macOS. #[config(default = false)] pub disable_reuseaddr: bool, + + /// ### _experimental_ use_dev_null {#experimental-use_dev_null} + /// + /// Uses /dev/null for creating local fake files (should be better than using /tmp) + #[config(default = false)] + pub use_dev_null: bool, } impl CollectAnalytics for &ExperimentalConfig { diff --git a/mirrord/layer/src/error.rs b/mirrord/layer/src/error.rs index e38bc950fa3..497da010a05 100644 --- a/mirrord/layer/src/error.rs +++ b/mirrord/layer/src/error.rs @@ -68,8 +68,8 @@ pub(crate) enum HookError { #[error("mirrord-layer: Failed converting `to_str` with `{0}`!")] Utf8(#[from] std::str::Utf8Error), - #[error("mirrord-layer: Failed creating local file for `remote_fd` `{0}`!")] - LocalFileCreation(u64), + #[error("mirrord-layer: Failed creating local file for `remote_fd` `{0}`! with errno `{1}`")] + LocalFileCreation(u64, i32), #[cfg(target_os = "macos")] #[error("mirrord-layer: SIP patch failed with error `{0}`!")] @@ -289,7 +289,7 @@ impl From for i64 { HookError::DNSNoName => libc::EFAULT, HookError::Utf8(_) => libc::EINVAL, HookError::NullPointer => libc::EINVAL, - HookError::LocalFileCreation(_) => libc::EINVAL, + HookError::LocalFileCreation(_, err) => err, #[cfg(target_os = "macos")] HookError::FailedSipPatch(_) => libc::EACCES, HookError::SocketUnsuportedIpv6 => libc::EAFNOSUPPORT, diff --git a/mirrord/layer/src/file/ops.rs b/mirrord/layer/src/file/ops.rs index 61518f7cead..3d6a598606b 100644 --- a/mirrord/layer/src/file/ops.rs +++ b/mirrord/layer/src/file/ops.rs @@ -142,6 +142,9 @@ fn get_remote_fd(local_fd: RawFd) -> Detour { /// Create temporary local file to get a valid local fd. #[mirrord_layer_macro::instrument(level = "trace", ret)] fn create_local_fake_file(remote_fd: u64) -> Detour { + if crate::setup().experimental().use_dev_null { + return create_local_devnull_file(remote_fd); + } let random_string = Alphanumeric.sample_string(&mut rand::thread_rng(), 16); let file_name = format!("{remote_fd}-{random_string}"); let file_path = env::temp_dir().join(file_name); @@ -149,15 +152,32 @@ fn create_local_fake_file(remote_fd: u64) -> Detour { let file_path_ptr = file_c_string.as_ptr(); let local_file_fd: RawFd = unsafe { FN_OPEN(file_path_ptr, O_RDONLY | O_CREAT) }; if local_file_fd == -1 { + let error = errno::errno(); // Close the remote file if creating a tmp local file failed and we have an invalid local fd close_remote_file_on_failure(remote_fd)?; - Detour::Error(HookError::LocalFileCreation(remote_fd)) + Detour::Error(HookError::LocalFileCreation(remote_fd, error.0)) } else { unsafe { unlink(file_path_ptr) }; Detour::Success(local_file_fd) } } +/// Open /dev/null to get a valid file fd +#[mirrord_layer_macro::instrument(level = "trace", ret)] +fn create_local_devnull_file(remote_fd: u64) -> Detour { + let file_c_string = CString::new("/dev/null")?; + let file_path_ptr = file_c_string.as_ptr(); + let local_file_fd: RawFd = unsafe { FN_OPEN(file_path_ptr, O_RDONLY) }; + if local_file_fd == -1 { + let error = errno::errno(); + // Close the remote file if creating a tmp local file failed and we have an invalid local fd + close_remote_file_on_failure(remote_fd)?; + Detour::Error(HookError::LocalFileCreation(remote_fd, error.0)) + } else { + Detour::Success(local_file_fd) + } +} + /// Close the remote file if the call to [`libc::shm_open`] failed and we have an invalid local fd. #[mirrord_layer_macro::instrument(level = "trace", ret)] fn close_remote_file_on_failure(fd: u64) -> Result<()> {