diff --git a/Cargo.lock b/Cargo.lock index c0f34b73..ab715169 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -1167,7 +1167,6 @@ dependencies = [ "derive_more", "flate2", "fspy_detours_sys", - "fspy_preload_unix", "fspy_preload_windows", "fspy_seccomp_unotify", "fspy_shared", @@ -1273,6 +1272,8 @@ dependencies = [ "bstr", "bytemuck", "ctor", + "memfd", + "memmap2", "os_str_bytes", "rustc-hash", "shared_memory", @@ -1861,11 +1862,20 @@ version = "2.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "f8ca58f447f06ed17d5fc4043ce1b10dd205e060fb3ce5b979b8ed8e59ff3f79" +[[package]] +name = "memfd" +version = "0.6.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ad38eb12aea514a0466ea40a80fd8cc83637065948eb4a426e4aa46261175227" +dependencies = [ + "rustix", +] + [[package]] name = "memmap2" -version = "0.9.9" +version = "0.9.10" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "744133e4a0e0a658e1374cf3bf8e415c4052a15a111acd372764c55b4177d490" +checksum = "714098028fe011992e1c3962653c96b2d578c4b4bce9036e15ff220319b1e0e3" dependencies = [ "libc", ] diff --git a/crates/fspy/Cargo.toml b/crates/fspy/Cargo.toml index 7269f0f9..bb4a5ce9 100644 --- a/crates/fspy/Cargo.toml +++ b/crates/fspy/Cargo.toml @@ -29,7 +29,7 @@ fspy_seccomp_unotify = { workspace = true, features = ["supervisor"] } nix = { workspace = true, features = ["uio"] } tokio = { workspace = true, features = ["bytes"] } -[target.'cfg(all(unix, not(target_env = "musl")))'.dependencies] +[target.'cfg(all(unix, all(not(target_env = "musl"), not(target_os = "android"))))'.dependencies] fspy_preload_unix = { workspace = true } [target.'cfg(unix)'.dependencies] diff --git a/crates/fspy/src/artifact.rs b/crates/fspy/src/artifact.rs index 0c3fcba0..4b03362a 100644 --- a/crates/fspy/src/artifact.rs +++ b/crates/fspy/src/artifact.rs @@ -28,7 +28,7 @@ macro_rules! artifact { pub use artifact; impl Artifact { - #[cfg(not(target_os = "linux"))] + #[cfg(all(not(target_os = "android"), not(target_os = "linux")))] pub const fn new(name: &'static str, content: &'static [u8], hash: &'static str) -> Self { Self { name, content, hash } } diff --git a/crates/fspy/src/lib.rs b/crates/fspy/src/lib.rs index 70756003..4946cffe 100644 --- a/crates/fspy/src/lib.rs +++ b/crates/fspy/src/lib.rs @@ -1,9 +1,9 @@ #![cfg_attr(target_os = "windows", feature(windows_process_extensions_main_thread_handle))] -#![feature(once_cell_try)] +#![cfg_attr(not(target_os = "android"), feature(once_cell_try))] // Persist the injected DLL/shared library somewhere in the filesystem. // Not needed on musl (seccomp-only tracking). -#[cfg(not(target_env = "musl"))] +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] mod artifact; pub mod error; diff --git a/crates/fspy/src/unix/mod.rs b/crates/fspy/src/unix/mod.rs index 7f946005..e7bb7782 100644 --- a/crates/fspy/src/unix/mod.rs +++ b/crates/fspy/src/unix/mod.rs @@ -8,7 +8,7 @@ use std::{io, path::Path}; #[cfg(target_os = "linux")] use fspy_seccomp_unotify::supervisor::supervise; -#[cfg(not(target_env = "musl"))] +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] use fspy_shared::ipc::NativeStr; use fspy_shared::ipc::{PathAccess, channel::channel}; #[cfg(target_os = "macos")] @@ -36,11 +36,11 @@ pub struct SpyImpl { #[cfg(target_os = "macos")] artifacts: Artifacts, - #[cfg(not(target_env = "musl"))] + #[cfg(all(not(target_os = "android"), not(target_env = "musl")))] preload_path: Box, } -#[cfg(not(target_env = "musl"))] +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] const PRELOAD_CDYLIB_BINARY: &[u8] = include_bytes!(env!("CARGO_CDYLIB_FILE_FSPY_PRELOAD_UNIX")); impl SpyImpl { @@ -48,8 +48,10 @@ impl SpyImpl { /// /// On musl targets, we don't build a preload library — /// only seccomp-based tracking is used. - pub fn init_in(#[cfg_attr(target_env = "musl", allow(unused))] dir: &Path) -> io::Result { - #[cfg(not(target_env = "musl"))] + pub fn init_in( + #[cfg_attr(any(target_os = "android", target_env = "musl"), allow(unused))] dir: &Path, + ) -> io::Result { + #[cfg(all(not(target_os = "android"), not(target_env = "musl")))] let preload_path = { use const_format::formatcp; use xxhash_rust::const_xxh3::xxh3_128; @@ -67,7 +69,7 @@ impl SpyImpl { }; Ok(Self { - #[cfg(not(target_env = "musl"))] + #[cfg(all(not(target_os = "android"), not(target_env = "musl")))] preload_path, #[cfg(target_os = "macos")] artifacts: { @@ -98,7 +100,7 @@ impl SpyImpl { #[cfg(target_os = "macos")] artifacts: self.artifacts.clone(), - #[cfg(not(target_env = "musl"))] + #[cfg(all(not(target_os = "android"), not(target_env = "musl")))] preload_path: self.preload_path.clone(), #[cfg(target_os = "linux")] diff --git a/crates/fspy_preload_unix/src/lib.rs b/crates/fspy_preload_unix/src/lib.rs index 9728cd98..5a8aab8e 100644 --- a/crates/fspy_preload_unix/src/lib.rs +++ b/crates/fspy_preload_unix/src/lib.rs @@ -1,12 +1,15 @@ // On musl targets, fspy_preload_unix is not needed since we can track accesses via seccomp-only. // Compile as an empty crate to avoid build failures from missing libc symbols. -#![cfg_attr(not(target_env = "musl"), feature(c_variadic))] +#![cfg_attr(not(target_os = "android"), not(target_env = "musl"), feature(c_variadic))] -#[cfg(all(unix, not(target_env = "musl")))] +#[cfg(all(target_os = "linux", not(target_env = "musl")))] mod client; -#[cfg(all(unix, not(target_env = "musl")))] + +#[cfg(all(target_os = "linux", not(target_env = "musl")))] mod interceptions; -#[cfg(all(unix, not(target_env = "musl")))] + +#[cfg(all(target_os = "linux", not(target_env = "musl")))] mod libc; -#[cfg(all(unix, not(target_env = "musl")))] + +#[cfg(all(target_os = "linux", not(target_env = "musl")))] mod macros; diff --git a/crates/fspy_seccomp_unotify/Cargo.toml b/crates/fspy_seccomp_unotify/Cargo.toml index 9a4a2a08..c0733c68 100644 --- a/crates/fspy_seccomp_unotify/Cargo.toml +++ b/crates/fspy_seccomp_unotify/Cargo.toml @@ -4,7 +4,7 @@ version = "0.1.0" edition = "2024" publish = false -[target.'cfg(target_os = "linux")'.dependencies] +[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies] bincode = { workspace = true } libc = { workspace = true } nix = { workspace = true, features = ["process", "fs", "poll", "socket", "uio"] } diff --git a/crates/fspy_seccomp_unotify/src/lib.rs b/crates/fspy_seccomp_unotify/src/lib.rs index a70b0a81..b530f3ba 100644 --- a/crates/fspy_seccomp_unotify/src/lib.rs +++ b/crates/fspy_seccomp_unotify/src/lib.rs @@ -1,4 +1,4 @@ -#![cfg(target_os = "linux")] +#![cfg(any(target_os = "android", target_os = "linux"))] #[cfg(any(feature = "supervisor", feature = "target"))] mod bindings; diff --git a/crates/fspy_seccomp_unotify/src/target.rs b/crates/fspy_seccomp_unotify/src/target.rs index 5406f796..8e424451 100644 --- a/crates/fspy_seccomp_unotify/src/target.rs +++ b/crates/fspy_seccomp_unotify/src/target.rs @@ -7,6 +7,9 @@ use std::{ }; use libc::sock_filter; +#[cfg(target_os = "android")] +use libc::{PR_SET_NO_NEW_PRIVS, prctl}; +#[cfg(not(target_os = "android"))] use nix::sys::prctl::set_no_new_privs; use passfd::FdPassingExt; @@ -19,7 +22,17 @@ use crate::{bindings::install_unotify_filter, payload::SeccompPayload}; /// Returns an error if setting no-new-privs fails, the filter cannot be installed, /// or the IPC socket communication fails. pub fn install_target(payload: &SeccompPayload) -> nix::Result<()> { + #[cfg(not(target_os = "android"))] set_no_new_privs()?; + + #[cfg(target_os = "android")] + { + let ret = unsafe { prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) }; + if ret != 0 { + return Err(nix::Error::last()); + } + } + let sock_filters = payload.filter.0.iter().copied().map(sock_filter::from).collect::>(); let notify_fd = install_unotify_filter(&sock_filters)?; diff --git a/crates/fspy_shared/Cargo.toml b/crates/fspy_shared/Cargo.toml index 756e4512..af4ea41d 100644 --- a/crates/fspy_shared/Cargo.toml +++ b/crates/fspy_shared/Cargo.toml @@ -10,11 +10,17 @@ bincode = { workspace = true } bitflags = { workspace = true } bstr = { workspace = true } bytemuck = { workspace = true, features = ["must_cast", "derive"] } -shared_memory = { workspace = true, features = ["logging"] } thiserror = { workspace = true } tracing = { workspace = true } uuid = { workspace = true, features = ["v4"] } +[target.'cfg(not(target_os = "android"))'.dependencies] +shared_memory = { workspace = true, features = ["logging"] } + +[target.'cfg(target_os = "android")'.dependencies] +memmap2 = "0.9.10" +memfd = "0.6" + [target.'cfg(target_os = "windows")'.dependencies] bytemuck = { workspace = true } os_str_bytes = { workspace = true } diff --git a/crates/fspy_shared/src/ipc/channel/backend/memfd.rs b/crates/fspy_shared/src/ipc/channel/backend/memfd.rs new file mode 100644 index 00000000..e29ec974 --- /dev/null +++ b/crates/fspy_shared/src/ipc/channel/backend/memfd.rs @@ -0,0 +1,29 @@ +use std::{fs::File, io, os::unix::io::AsRawFd, sync::Arc}; + +use memfd::MemfdOptions; +use memmap2::{MmapMut, MmapOptions}; + +pub struct Shm { + pub mmap: MmapMut, + pub fd_path: Arc, +} + +pub fn create(size: usize) -> io::Result { + let memfd = MemfdOptions::default().create("ipc").map_err(io::Error::other)?; + memfd.as_file().set_len(size as u64)?; + + let fd = memfd.as_file().as_raw_fd(); + let fd_path = format!("/proc/self/fd/{fd}"); + + let mmap = unsafe { MmapOptions::new().len(size).map_mut(memfd.as_file())? }; + + Ok(Shm { mmap, fd_path: fd_path.into() }) +} + +pub fn open(shm_id: &str, size: usize) -> io::Result { + let file = File::open(shm_id)?; + + let mmap = unsafe { memmap2::MmapOptions::new().len(size).map_mut(&file)? }; + + Ok(mmap) +} diff --git a/crates/fspy_shared/src/ipc/channel/backend/mod.rs b/crates/fspy_shared/src/ipc/channel/backend/mod.rs new file mode 100644 index 00000000..40fadd6a --- /dev/null +++ b/crates/fspy_shared/src/ipc/channel/backend/mod.rs @@ -0,0 +1,10 @@ +#[cfg(target_os = "android")] +mod memfd; + +#[cfg(not(target_os = "android"))] +mod shmem; + +#[cfg(target_os = "android")] +pub use memfd::*; +#[cfg(not(target_os = "android"))] +pub use shmem::*; diff --git a/crates/fspy_shared/src/ipc/channel/backend/shmem.rs b/crates/fspy_shared/src/ipc/channel/backend/shmem.rs new file mode 100644 index 00000000..c7b6afff --- /dev/null +++ b/crates/fspy_shared/src/ipc/channel/backend/shmem.rs @@ -0,0 +1,16 @@ +use std::io; + +use shared_memory::{Shmem, ShmemConf}; + +pub struct Shm { + pub shm: Shmem, + pub os_id: String, +} + +pub fn create(size: usize) -> io::Result { + let shm = ShmemConf::new().size(size).create().map_err(io::Error::other)?; + + let os_id = shm.get_os_id().to_string(); + + Ok(Shm { shm, os_id }) +} diff --git a/crates/fspy_shared/src/ipc/channel/mod.rs b/crates/fspy_shared/src/ipc/channel/mod.rs index 3e67cea8..3bfdeeb2 100644 --- a/crates/fspy_shared/src/ipc/channel/mod.rs +++ b/crates/fspy_shared/src/ipc/channel/mod.rs @@ -1,19 +1,19 @@ //! Fast mpsc IPC channel implementation based on shared memory. -mod shm_io; - use std::{env::temp_dir, fs::File, io, ops::Deref, path::PathBuf, sync::Arc}; use bincode::{Decode, Encode}; -use shared_memory::{Shmem, ShmemConf}; -pub use shm_io::FrameMut; +#[cfg(not(target_os = "android"))] +use shared_memory::ShmemConf; use shm_io::{ShmReader, ShmWriter}; use tracing::debug; use uuid::Uuid; use super::NativeStr; -/// Serializable configuration to create channel senders. +mod backend; +mod shm_io; + #[derive(Encode, Decode, Clone, Debug)] pub struct ChannelConf { lock_file_path: Box, @@ -21,31 +21,24 @@ pub struct ChannelConf { shm_size: usize, } -/// Creates a mpsc IPC channel with one receiver and a `ChannelConf` that can be passed around processes and used to create multiple senders -#[expect( - clippy::missing_errors_doc, - reason = "non-vite crate: cannot use vite_str/vite_path types" -)] pub fn channel(capacity: usize) -> io::Result<(ChannelConf, Receiver)> { - // Initialize the lock file with a unique name. let lock_file_path = temp_dir().join(format!("fspy_ipc_{}.lock", Uuid::new_v4())); - #[cfg_attr( - not(windows), - expect(unused_mut, reason = "mut required on Windows, unused on Unix") - )] - let mut conf = ShmemConf::new().size(capacity); - // On Windows, allow opening raw shared memory (without backing file) for DLL injection scenarios - #[cfg(target_os = "windows")] - { - conf = conf.allow_raw(true); - } + let shm = backend::create(capacity)?; + + #[cfg(target_os = "android")] + let conf = ChannelConf { + lock_file_path: lock_file_path.as_os_str().into(), - let shm = conf.create().map_err(io::Error::other)?; + shm_id: shm.fd_path.clone(), + shm_size: capacity, + }; + #[cfg(not(target_os = "android"))] let conf = ChannelConf { lock_file_path: lock_file_path.as_os_str().into(), - shm_id: shm.get_os_id().into(), + + shm_id: shm.os_id.clone().into(), shm_size: capacity, }; @@ -65,26 +58,38 @@ impl ChannelConf { let lock_file = File::open(self.lock_file_path.to_cow_os_str())?; lock_file.try_lock_shared()?; - #[cfg_attr( - not(windows), - expect(unused_mut, reason = "mut required on Windows, unused on Unix") - )] - let mut conf = ShmemConf::new().size(self.shm_size).os_id(&self.shm_id); - // On Windows, allow opening raw shared memory (without backing file) for DLL injection scenarios - #[cfg(target_os = "windows")] - { - conf = conf.allow_raw(true); - } - let shm = conf.open().map_err(io::Error::other)?; - // SAFETY: `shm` is a freshly opened shared memory region with valid pointer and size. - // Exclusive write access is ensured by the shared file lock held by this sender. - let writer = unsafe { ShmWriter::new(shm) }; + #[cfg(target_os = "android")] + let writer = { + let mmap = backend::open(&self.shm_id, self.shm_size)?; + + WriterHandle::MemFd(unsafe { ShmWriter::new(mmap) }) + }; + + #[cfg(not(target_os = "android"))] + let writer = { + #[cfg_attr( + not(windows), + expect(unused_mut, reason = "mut required on Windows, unused on Unix") + )] + let mut conf = ShmemConf::new().size(self.shm_size).os_id(&self.shm_id); + + #[cfg(target_os = "windows")] + { + conf = conf.allow_raw(true); + } + + let shm = conf.open().map_err(io::Error::other)?; + + // SAFETY: shm valide + lock garantit exclusivité + WriterHandle::Shmem(unsafe { ShmWriter::new(shm) }) + }; + Ok(Sender { writer, lock_file, lock_file_path: self.lock_file_path.clone() }) } } pub struct Sender { - writer: ShmWriter, + writer: WriterHandle, lock_file_path: Box, lock_file: File, } @@ -98,7 +103,7 @@ impl Drop for Sender { } impl Deref for Sender { - type Target = ShmWriter; + type Target = WriterHandle; fn deref(&self) -> &Self::Target { &self.writer @@ -115,22 +120,27 @@ unsafe impl Send for Sender {} /// SAFETY: `Sender` holds a shared file lock that ensures there's no reader, so `shm` can be safely written to. unsafe impl Sync for Sender {} -/// The unique receiver side of an IPC channel. -/// Owns the lock file and removes it on drop. +enum ShmHandle { + #[cfg(target_os = "android")] + MemFd(memmap2::MmapMut), + #[cfg(not(target_os = "android"))] + Shmem(shared_memory::Shmem), +} + +pub enum WriterHandle { + #[cfg(target_os = "android")] + MemFd(ShmWriter), + #[cfg(not(target_os = "android"))] + Shmem(ShmWriter), +} + pub struct Receiver { lock_file_path: PathBuf, lock_file: File, - shm: Shmem, + shm: ShmHandle, } -#[expect( - clippy::non_send_fields_in_send_ty, - reason = "Receiver doesn't read or write `shm`. It only pass it to `ReceiverLockGuard` under the lock" -)] -/// SAFETY: `Receiver` doesn't read or write `shm`. It only passes it to `ReceiverLockGuard` under the lock. unsafe impl Send for Receiver {} - -/// SAFETY: `Receiver` doesn't read or write `shm`. It only passes it to `ReceiverLockGuard` under the lock. unsafe impl Sync for Receiver {} impl Drop for Receiver { @@ -142,8 +152,15 @@ impl Drop for Receiver { } impl Receiver { - fn new(lock_file_path: PathBuf, shm: Shmem) -> io::Result { + fn new(lock_file_path: PathBuf, shm: backend::Shm) -> io::Result { let lock_file = File::create(&lock_file_path)?; + + #[cfg(target_os = "android")] + let shm = ShmHandle::MemFd(shm.mmap); + + #[cfg(not(target_os = "android"))] + let shm = ShmHandle::Shmem(shm.shm); + Ok(Self { lock_file_path, lock_file, shm }) } @@ -156,9 +173,19 @@ impl Receiver { )] pub fn lock(&self) -> io::Result> { self.lock_file.lock()?; - // SAFETY: The exclusive file lock is held, so no writers can access the shared memory. - // The lock ensures all prior writes are visible to this thread. - let reader = ShmReader::new(unsafe { self.shm.as_slice() }); + + let slice: &[u8] = match &self.shm { + #[cfg(target_os = "android")] + ShmHandle::MemFd(mmap) => unsafe { + std::slice::from_raw_parts(mmap.as_ptr(), mmap.len()) + }, + + #[cfg(not(target_os = "android"))] + ShmHandle::Shmem(shm) => unsafe { shm.as_slice() }, + }; + + let reader = ShmReader::new(slice); + Ok(ReceiverLockGuard { reader, lock_file: &self.lock_file }) } } diff --git a/crates/fspy_shared/src/ipc/channel/shm_io.rs b/crates/fspy_shared/src/ipc/channel/shm_io.rs index 39a490d1..95aa6704 100644 --- a/crates/fspy_shared/src/ipc/channel/shm_io.rs +++ b/crates/fspy_shared/src/ipc/channel/shm_io.rs @@ -12,6 +12,9 @@ use bincode::{ Encode, config::Config, enc::write::SizeWriter, encode_into_slice, encode_into_writer, }; use bytemuck::must_cast; +#[cfg(target_os = "android")] +use memmap2::MmapMut; +#[cfg(not(target_os = "android"))] use shared_memory::Shmem; // `ShmWriter` writes headers using atomic operations to prevent partial writes due to crashes, @@ -30,11 +33,18 @@ pub trait AsRawSlice { fn as_raw_slice(&self) -> *mut [u8]; } +#[cfg(not(target_os = "android"))] impl AsRawSlice for Shmem { fn as_raw_slice(&self) -> *mut [u8] { slice_from_raw_parts_mut(self.as_ptr(), self.len()) } } +#[cfg(target_os = "android")] +impl AsRawSlice for MmapMut { + fn as_raw_slice(&self) -> *mut [u8] { + slice_from_raw_parts_mut(self.as_ptr() as *mut u8, self.len()) + } +} /// A concurrent shared memory writer. /// diff --git a/crates/fspy_shared/src/ipc/mod.rs b/crates/fspy_shared/src/ipc/mod.rs index 755627d3..f137a844 100644 --- a/crates/fspy_shared/src/ipc/mod.rs +++ b/crates/fspy_shared/src/ipc/mod.rs @@ -1,3 +1,4 @@ +#[cfg(not(target_os = "android"))] pub mod channel; mod native_path; pub(crate) mod native_str; diff --git a/crates/fspy_shared_unix/Cargo.toml b/crates/fspy_shared_unix/Cargo.toml index 4afedf81..c5266c39 100644 --- a/crates/fspy_shared_unix/Cargo.toml +++ b/crates/fspy_shared_unix/Cargo.toml @@ -15,7 +15,7 @@ stackalloc = { workspace = true } [dev-dependencies] -[target.'cfg(target_os = "linux")'.dependencies] +[target.'cfg(any(target_os = "android",target_os = "linux"))'.dependencies] elf = { workspace = true } fspy_seccomp_unotify = { workspace = true, features = ["target"] } memmap2 = { workspace = true } diff --git a/crates/fspy_shared_unix/src/lib.rs b/crates/fspy_shared_unix/src/lib.rs index 5437a3ef..d39490f9 100644 --- a/crates/fspy_shared_unix/src/lib.rs +++ b/crates/fspy_shared_unix/src/lib.rs @@ -5,8 +5,9 @@ pub(crate) mod open_exec; pub mod payload; pub mod spawn; -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "android", target_os = "linux"))] mod elf; -#[cfg(target_os = "linux")] // exposed for verifying static executables in fspy tests +#[cfg(any(target_os = "android", target_os = "linux"))] +// exposed for verifying static executables in fspy tests pub use elf::is_dynamically_linked_to_libc; diff --git a/crates/fspy_shared_unix/src/payload.rs b/crates/fspy_shared_unix/src/payload.rs index e23f7ce0..252f8c01 100644 --- a/crates/fspy_shared_unix/src/payload.rs +++ b/crates/fspy_shared_unix/src/payload.rs @@ -3,7 +3,7 @@ use std::os::unix::ffi::OsStringExt; use base64::{Engine as _, prelude::BASE64_STANDARD_NO_PAD}; use bincode::{Decode, Encode, config::standard}; use bstr::BString; -#[cfg(not(target_env = "musl"))] +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] use fspy_shared::ipc::NativeStr; use fspy_shared::ipc::channel::ChannelConf; @@ -11,7 +11,7 @@ use fspy_shared::ipc::channel::ChannelConf; pub struct Payload { pub ipc_channel_conf: ChannelConf, - #[cfg(not(target_env = "musl"))] + #[cfg(all(not(target_os = "android"), not(target_env = "musl")))] pub preload_path: Box, #[cfg(target_os = "macos")] diff --git a/crates/fspy_shared_unix/src/spawn/linux/mod.rs b/crates/fspy_shared_unix/src/spawn/linux/mod.rs index 0632999d..9ff6be49 100644 --- a/crates/fspy_shared_unix/src/spawn/linux/mod.rs +++ b/crates/fspy_shared_unix/src/spawn/linux/mod.rs @@ -1,11 +1,11 @@ -#[cfg(not(target_env = "musl"))] +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] use std::{ffi::OsStr, os::unix::ffi::OsStrExt as _, path::Path}; use fspy_seccomp_unotify::{payload::SeccompPayload, target::install_target}; -#[cfg(not(target_env = "musl"))] +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] use memmap2::Mmap; -#[cfg(not(target_env = "musl"))] +#[cfg(all(not(target_os = "android"), not(target_env = "musl")))] use crate::{elf, exec::ensure_env, open_exec::open_executable}; use crate::{ exec::Exec, @@ -28,11 +28,11 @@ impl PreExec { pub fn handle_exec( command: &mut Exec, - encoded_payload: &EncodedPayload, + _encoded_payload: &EncodedPayload, ) -> nix::Result> { // On musl targets, LD_PRELOAD is not available (cdylib not supported). // Always use seccomp-based tracking instead. - #[cfg(not(target_env = "musl"))] + #[cfg(all(not(target_os = "android"), not(target_env = "musl")))] { let executable_fd = open_executable(Path::new(OsStr::from_bytes(&command.program)))?; // SAFETY: The file descriptor is valid and we only read from the mapping. @@ -51,5 +51,6 @@ pub fn handle_exec( } command.envs.retain(|(name, _)| name != LD_PRELOAD && name != PAYLOAD_ENV_NAME); - Ok(Some(PreExec(encoded_payload.payload.seccomp_payload.clone()))) + Ok(None) + // Ok(Some(PreExec(encoded_payload.payload.seccomp_payload.clone()))) } diff --git a/crates/fspy_shared_unix/src/spawn/mod.rs b/crates/fspy_shared_unix/src/spawn/mod.rs index e4812577..7273030b 100644 --- a/crates/fspy_shared_unix/src/spawn/mod.rs +++ b/crates/fspy_shared_unix/src/spawn/mod.rs @@ -1,4 +1,4 @@ -#[cfg(target_os = "linux")] +#[cfg(any(target_os = "android", target_os = "linux"))] #[path = "./linux/mod.rs"] mod os_specific;