Skip to content

Commit 6da9e9a

Browse files
committed
android support
1 parent c45e5e7 commit 6da9e9a

15 files changed

Lines changed: 74 additions & 51 deletions

File tree

Cargo.lock

Lines changed: 2 additions & 2 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/fspy/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ tokio = { workspace = true, features = ["net", "process", "io-util", "sync", "rt
2222
tokio-util = { workspace = true }
2323
which = { workspace = true, features = ["tracing"] }
2424

25-
[target.'cfg(target_os = "linux")'.dependencies]
25+
[target.'cfg(any(target_os = "linux", target_os = "android"))'.dependencies]
2626
fspy_seccomp_unotify = { workspace = true, features = ["supervisor"] }
2727
nix = { workspace = true, features = ["uio"] }
2828
tokio = { workspace = true, features = ["bytes"] }

crates/fspy/src/lib.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
#![cfg_attr(target_os = "windows", feature(windows_process_extensions_main_thread_handle))]
2-
#![feature(once_cell_try)]
2+
#![cfg_attr(not(target_os = "android"), feature(once_cell_try))]
33

44
pub mod error;
55

6-
#[cfg(not(target_env = "musl"))]
6+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
77
mod ipc;
88

99
#[cfg(unix)]

crates/fspy/src/unix/mod.rs

Lines changed: 22 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,15 @@
1-
#[cfg(target_os = "linux")]
1+
#[cfg(any(target_os = "linux", target_os = "android"))]
22
mod syscall_handler;
33

44
#[cfg(target_os = "macos")]
55
mod macos_artifacts;
66

77
use std::{io, path::Path};
88

9-
#[cfg(target_os = "linux")]
9+
#[cfg(any(target_os = "linux", target_os = "android"))]
1010
use fspy_seccomp_unotify::supervisor::supervise;
1111
use fspy_shared::ipc::PathAccess;
12-
#[cfg(not(target_env = "musl"))]
12+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
1313
use fspy_shared::ipc::{NativeStr, channel::channel};
1414
#[cfg(target_os = "macos")]
1515
use fspy_shared_unix::payload::Artifacts;
@@ -19,12 +19,12 @@ use fspy_shared_unix::{
1919
spawn::handle_exec,
2020
};
2121
use futures_util::FutureExt;
22-
#[cfg(target_os = "linux")]
22+
#[cfg(any(target_os = "linux", target_os = "android"))]
2323
use syscall_handler::SyscallHandler;
2424
use tokio::task::spawn_blocking;
2525
use tokio_util::sync::CancellationToken;
2626

27-
#[cfg(not(target_env = "musl"))]
27+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
2828
use crate::ipc::{OwnedReceiverLockGuard, SHM_CAPACITY};
2929
use crate::{ChildTermination, Command, TrackedChild, arena::PathAccessArena, error::SpawnError};
3030

@@ -33,7 +33,7 @@ pub struct SpyImpl {
3333
#[cfg(target_os = "macos")]
3434
artifacts: Artifacts,
3535

36-
#[cfg(not(target_env = "musl"))]
36+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
3737
preload_path: Box<NativeStr>,
3838
}
3939

@@ -42,8 +42,10 @@ impl SpyImpl {
4242
///
4343
/// On musl targets, we don't build a preload library —
4444
/// only seccomp-based tracking is used.
45-
pub fn init_in(#[cfg_attr(target_env = "musl", allow(unused))] dir: &Path) -> io::Result<Self> {
46-
#[cfg(not(target_env = "musl"))]
45+
pub fn init_in(
46+
#[cfg_attr(any(target_os = "android", target_env = "musl"), allow(unused))] dir: &Path,
47+
) -> io::Result<Self> {
48+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
4749
let preload_path = {
4850
use materialized_artifact::{Artifact, artifact};
4951

@@ -54,7 +56,7 @@ impl SpyImpl {
5456
};
5557

5658
Ok(Self {
57-
#[cfg(not(target_env = "musl"))]
59+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
5860
preload_path,
5961
#[cfg(target_os = "macos")]
6062
artifacts: {
@@ -74,24 +76,24 @@ impl SpyImpl {
7476
mut command: Command,
7577
cancellation_token: CancellationToken,
7678
) -> Result<TrackedChild, SpawnError> {
77-
#[cfg(target_os = "linux")]
79+
#[cfg(any(target_os = "linux", target_os = "android"))]
7880
let supervisor = supervise::<SyscallHandler>().map_err(SpawnError::Supervisor)?;
7981

80-
#[cfg(not(target_env = "musl"))]
82+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
8183
let (ipc_channel_conf, ipc_receiver) =
8284
channel(SHM_CAPACITY).map_err(SpawnError::ChannelCreation)?;
8385

8486
let payload = Payload {
85-
#[cfg(not(target_env = "musl"))]
87+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
8688
ipc_channel_conf,
8789

8890
#[cfg(target_os = "macos")]
8991
artifacts: self.artifacts.clone(),
9092

91-
#[cfg(not(target_env = "musl"))]
93+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
9294
preload_path: self.preload_path.clone(),
9395

94-
#[cfg(target_os = "linux")]
96+
#[cfg(any(target_os = "linux", target_os = "android"))]
9597
seccomp_payload: supervisor.payload().clone(),
9698
};
9799

@@ -148,7 +150,7 @@ impl SpyImpl {
148150

149151
let arenas = std::iter::once(exec_resolve_accesses);
150152
// Stop the supervisor and collect path accesses from it.
151-
#[cfg(target_os = "linux")]
153+
#[cfg(any(target_os = "linux", target_os = "android"))]
152154
let arenas = arenas.chain(
153155
supervisor
154156
.stop()
@@ -160,12 +162,12 @@ impl SpyImpl {
160162

161163
// Lock the ipc channel after the child has exited.
162164
// We are not interested in path accesses from descendants after the main child has exited.
163-
#[cfg(not(target_env = "musl"))]
165+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
164166
let ipc_receiver_lock_guard =
165167
OwnedReceiverLockGuard::lock_async(ipc_receiver).await?;
166168
let path_accesses = PathAccessIterable {
167169
arenas,
168-
#[cfg(not(target_env = "musl"))]
170+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
169171
ipc_receiver_lock_guard,
170172
};
171173

@@ -179,7 +181,7 @@ impl SpyImpl {
179181

180182
pub struct PathAccessIterable {
181183
arenas: Vec<PathAccessArena>,
182-
#[cfg(not(target_env = "musl"))]
184+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
183185
ipc_receiver_lock_guard: OwnedReceiverLockGuard,
184186
}
185187

@@ -188,12 +190,12 @@ impl PathAccessIterable {
188190
let accesses_in_arena =
189191
self.arenas.iter().flat_map(|arena| arena.borrow_accesses().iter()).copied();
190192

191-
#[cfg(not(target_env = "musl"))]
193+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
192194
{
193195
let accesses_in_shm = self.ipc_receiver_lock_guard.iter_path_accesses();
194196
accesses_in_shm.chain(accesses_in_arena)
195197
}
196-
#[cfg(target_env = "musl")]
198+
#[cfg(any(target_os = "android", target_env = "musl"))]
197199
{
198200
accesses_in_arena
199201
}
Lines changed: 11 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
1-
// Compile as an empty crate on non-unix targets and on musl (where seccomp
2-
// alone handles access tracking). Guarding the feature gate keeps rustc from
3-
// warning about unused features on those targets.
4-
#![cfg_attr(all(unix, not(target_env = "musl")), feature(c_variadic))]
1+
// Compile as an empty crate on non-unix targets, on android, and on musl
2+
// (where seccomp alone handles access tracking). Guarding the feature gate
3+
// keeps rustc from warning about unused features on those targets.
4+
#![cfg_attr(all(unix, not(target_os = "android"), not(target_env = "musl")), feature(c_variadic))]
55

6-
#[cfg(all(unix, not(target_env = "musl")))]
6+
#[cfg(all(unix, not(target_os = "android"), not(target_env = "musl")))]
77
mod client;
8-
#[cfg(all(unix, not(target_env = "musl")))]
8+
9+
#[cfg(all(unix, not(target_os = "android"), not(target_env = "musl")))]
910
mod interceptions;
10-
#[cfg(all(unix, not(target_env = "musl")))]
11+
12+
#[cfg(all(unix, not(target_os = "android"), not(target_env = "musl")))]
1113
mod libc;
12-
#[cfg(all(unix, not(target_env = "musl")))]
14+
15+
#[cfg(all(unix, not(target_os = "android"), not(target_env = "musl")))]
1316
mod macros;

crates/fspy_seccomp_unotify/Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,7 +4,7 @@ version = "0.1.0"
44
edition = "2024"
55
publish = false
66

7-
[target.'cfg(target_os = "linux")'.dependencies]
7+
[target.'cfg(any(target_os = "android", target_os = "linux"))'.dependencies]
88
wincode = { workspace = true, features = ["derive"] }
99
libc = { workspace = true }
1010
nix = { workspace = true, features = ["process", "fs", "poll", "socket", "uio"] }

crates/fspy_seccomp_unotify/src/lib.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#![cfg(target_os = "linux")]
1+
#![cfg(any(target_os = "android", target_os = "linux"))]
22

33
#[cfg(any(feature = "supervisor", feature = "target"))]
44
mod bindings;

crates/fspy_seccomp_unotify/src/target.rs

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,9 @@ use std::{
77
};
88

99
use libc::sock_filter;
10+
#[cfg(target_os = "android")]
11+
use libc::{PR_SET_NO_NEW_PRIVS, prctl};
12+
#[cfg(not(target_os = "android"))]
1013
use nix::sys::prctl::set_no_new_privs;
1114
use passfd::FdPassingExt;
1215

@@ -19,7 +22,17 @@ use crate::{bindings::install_unotify_filter, payload::SeccompPayload};
1922
/// Returns an error if setting no-new-privs fails, the filter cannot be installed,
2023
/// or the IPC socket communication fails.
2124
pub fn install_target(payload: &SeccompPayload) -> nix::Result<()> {
25+
#[cfg(not(target_os = "android"))]
2226
set_no_new_privs()?;
27+
28+
#[cfg(target_os = "android")]
29+
{
30+
let ret = unsafe { prctl(PR_SET_NO_NEW_PRIVS, 1, 0, 0, 0) };
31+
if ret != 0 {
32+
return Err(nix::Error::last());
33+
}
34+
}
35+
2336
let sock_filters =
2437
payload.filter.0.iter().copied().map(sock_filter::from).collect::<Vec<sock_filter>>();
2538
let notify_fd = install_unotify_filter(&sock_filters)?;

crates/fspy_shared/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,11 +11,13 @@ bitflags = { workspace = true }
1111
bstr = { workspace = true }
1212
bytemuck = { workspace = true, features = ["must_cast", "derive"] }
1313
native_str = { workspace = true }
14-
shared_memory = { workspace = true, features = ["logging"] }
1514
thiserror = { workspace = true }
1615
tracing = { workspace = true }
1716
uuid = { workspace = true, features = ["v4"] }
1817

18+
[target.'cfg(not(target_os = "android"))'.dependencies]
19+
shared_memory = { workspace = true, features = ["logging"] }
20+
1921
[target.'cfg(target_os = "windows")'.dependencies]
2022
bytemuck = { workspace = true }
2123
os_str_bytes = { workspace = true }

crates/fspy_shared/src/ipc/mod.rs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
#[cfg(not(target_env = "musl"))]
1+
#[cfg(all(not(target_os = "android"), not(target_env = "musl")))]
22
pub mod channel;
33
mod native_path;
44
use std::fmt::Debug;

0 commit comments

Comments
 (0)