From c050cdf3b0942bbf1b88414165919aa267e2b49b Mon Sep 17 00:00:00 2001 From: Claude Date: Mon, 13 Apr 2026 03:44:26 +0000 Subject: [PATCH] refactor(fspy): gate ipc channel module on non-musl targets The shared-memory IPC channel is only used to transport path accesses from the preload library to the supervisor. On musl targets, the preload library is not built (seccomp-only tracking is used), so the channel has no senders and produces no data. Gate the entire `fspy_shared::ipc::channel` module and its downstream users behind `#[cfg(not(target_env = "musl"))]` so musl builds no longer allocate the 4 GiB shared-memory region, create the lock file, or wait for the receiver lock. - `fspy_shared::ipc::channel` module is now non-musl only - `fspy::ipc` (which re-exports `OwnedReceiverLockGuard` and `SHM_CAPACITY`) is non-musl only - `fspy::unix::SpyImpl::spawn` no longer creates a channel on musl; `PathAccessIterable` drops its `ipc_receiver_lock_guard` field on musl and `iter()` only yields arena-collected accesses - Update `Payload::seccomp_payload`'s `struct_field_names` expect so it only applies on non-musl, where `Payload` still has multiple fields (on musl it's the only field and the lint no longer fires) https://claude.ai/code/session_01VqiMHiGeViu1pGhWwJ67Qc --- crates/fspy/src/lib.rs | 1 + crates/fspy/src/unix/mod.rs | 34 ++++++++++++++++---------- crates/fspy_shared/src/ipc/mod.rs | 1 + crates/fspy_shared_unix/src/payload.rs | 5 +++- 4 files changed, 27 insertions(+), 14 deletions(-) diff --git a/crates/fspy/src/lib.rs b/crates/fspy/src/lib.rs index 70756003e..7acabe793 100644 --- a/crates/fspy/src/lib.rs +++ b/crates/fspy/src/lib.rs @@ -8,6 +8,7 @@ mod artifact; pub mod error; +#[cfg(not(target_env = "musl"))] mod ipc; #[cfg(unix)] diff --git a/crates/fspy/src/unix/mod.rs b/crates/fspy/src/unix/mod.rs index 98077a6d8..ba0516301 100644 --- a/crates/fspy/src/unix/mod.rs +++ b/crates/fspy/src/unix/mod.rs @@ -8,9 +8,9 @@ use std::{io, path::Path}; #[cfg(target_os = "linux")] use fspy_seccomp_unotify::supervisor::supervise; +use fspy_shared::ipc::PathAccess; #[cfg(not(target_env = "musl"))] -use fspy_shared::ipc::NativeStr; -use fspy_shared::ipc::{PathAccess, channel::channel}; +use fspy_shared::ipc::{NativeStr, channel::channel}; #[cfg(target_os = "macos")] use fspy_shared_unix::payload::Artifacts; use fspy_shared_unix::{ @@ -24,12 +24,9 @@ use syscall_handler::SyscallHandler; use tokio::task::spawn_blocking; use tokio_util::sync::CancellationToken; -use crate::{ - ChildTermination, Command, TrackedChild, - arena::PathAccessArena, - error::SpawnError, - ipc::{OwnedReceiverLockGuard, SHM_CAPACITY}, -}; +#[cfg(not(target_env = "musl"))] +use crate::ipc::{OwnedReceiverLockGuard, SHM_CAPACITY}; +use crate::{ChildTermination, Command, TrackedChild, arena::PathAccessArena, error::SpawnError}; #[derive(Debug)] pub struct SpyImpl { @@ -92,8 +89,6 @@ impl SpyImpl { #[cfg(not(target_env = "musl"))] let (ipc_channel_conf, ipc_receiver) = channel(SHM_CAPACITY).map_err(SpawnError::ChannelCreation)?; - #[cfg(target_env = "musl")] - let (_, ipc_receiver) = channel(SHM_CAPACITY).map_err(SpawnError::ChannelCreation)?; let payload = Payload { #[cfg(not(target_env = "musl"))] @@ -174,9 +169,14 @@ impl SpyImpl { // Lock the ipc channel after the child has exited. // We are not interested in path accesses from descendants after the main child has exited. + #[cfg(not(target_env = "musl"))] let ipc_receiver_lock_guard = OwnedReceiverLockGuard::lock_async(ipc_receiver).await?; - let path_accesses = PathAccessIterable { arenas, ipc_receiver_lock_guard }; + let path_accesses = PathAccessIterable { + arenas, + #[cfg(not(target_env = "musl"))] + ipc_receiver_lock_guard, + }; io::Result::Ok(ChildTermination { status, path_accesses }) }) @@ -188,6 +188,7 @@ impl SpyImpl { pub struct PathAccessIterable { arenas: Vec, + #[cfg(not(target_env = "musl"))] ipc_receiver_lock_guard: OwnedReceiverLockGuard, } @@ -196,7 +197,14 @@ impl PathAccessIterable { let accesses_in_arena = self.arenas.iter().flat_map(|arena| arena.borrow_accesses().iter()).copied(); - let accesses_in_shm = self.ipc_receiver_lock_guard.iter_path_accesses(); - accesses_in_shm.chain(accesses_in_arena) + #[cfg(not(target_env = "musl"))] + { + let accesses_in_shm = self.ipc_receiver_lock_guard.iter_path_accesses(); + accesses_in_shm.chain(accesses_in_arena) + } + #[cfg(target_env = "musl")] + { + accesses_in_arena + } } } diff --git a/crates/fspy_shared/src/ipc/mod.rs b/crates/fspy_shared/src/ipc/mod.rs index 755627d3b..17df1c2d3 100644 --- a/crates/fspy_shared/src/ipc/mod.rs +++ b/crates/fspy_shared/src/ipc/mod.rs @@ -1,3 +1,4 @@ +#[cfg(not(target_env = "musl"))] pub mod channel; mod native_path; pub(crate) mod native_str; diff --git a/crates/fspy_shared_unix/src/payload.rs b/crates/fspy_shared_unix/src/payload.rs index d606ca475..11c3e1bb8 100644 --- a/crates/fspy_shared_unix/src/payload.rs +++ b/crates/fspy_shared_unix/src/payload.rs @@ -20,7 +20,10 @@ pub struct Payload { pub artifacts: Artifacts, #[cfg(target_os = "linux")] - #[expect(clippy::struct_field_names, reason = "descriptive field name for clarity")] + #[cfg_attr( + not(target_env = "musl"), + expect(clippy::struct_field_names, reason = "descriptive field name for clarity") + )] pub seccomp_payload: fspy_seccomp_unotify::payload::SeccompPayload, }