Skip to content

Commit dd95709

Browse files
authored
Merge branch 'main' into fix/default-untracked-env-patterns
2 parents 06fbe32 + ef64d0f commit dd95709

95 files changed

Lines changed: 1889 additions & 815 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

.cargo/config.toml

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,8 @@ rustflags = ["--cfg", "tokio_unstable", "-D", "warnings"]
44
[unstable]
55
bindeps = true
66

7-
# Linker wrappers for cross-compiling bindep targets (fspy_test_bin) via cargo-zigbuild.
8-
# On native Linux the system linker can handle musl targets; these are needed on non-Linux hosts.
7+
# Linker wrappers for musl targets. On Linux hosts these use the system cc directly;
8+
# on non-Linux hosts (macOS, Windows) they cross-compile via cargo-zigbuild.
99
[target.x86_64-unknown-linux-musl]
1010
rustflags = ["-C", "linker=.cargo/zigcc-x86_64-unknown-linux-musl"]
1111

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
#!/bin/sh
2+
# Linker wrapper for aarch64-unknown-linux-musl targets.
3+
# On Linux, use the system cc directly. On other hosts, cross-compile via cargo-zigbuild.
4+
if [ "$(uname -s)" = "Linux" ]; then
5+
exec cc "$@"
6+
fi
27
exec cargo-zigbuild zig cc -- -fno-sanitize=all -target aarch64-linux-musl "$@"
Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,7 @@
11
#!/bin/sh
2+
# Linker wrapper for x86_64-unknown-linux-musl targets.
3+
# On Linux, use the system cc directly. On other hosts, cross-compile via cargo-zigbuild.
4+
if [ "$(uname -s)" = "Linux" ]; then
5+
exec cc "$@"
6+
fi
27
exec cargo-zigbuild zig cc -- -fno-sanitize=all -target x86_64-linux-musl "$@"

.github/workflows/ci.yml

Lines changed: 45 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -133,6 +133,50 @@ jobs:
133133
- run: cargo-zigbuild test --target x86_64-unknown-linux-gnu.2.17
134134
if: ${{ matrix.os == 'ubuntu-latest' }}
135135

136+
test-musl:
137+
needs: detect-changes
138+
if: needs.detect-changes.outputs.code-changed == 'true'
139+
name: Test (musl)
140+
runs-on: ubuntu-latest
141+
container:
142+
image: node:22-alpine3.21
143+
options: --shm-size=256m # shm_io tests need bigger shared memory
144+
env:
145+
# Override all rustflags to skip the zig cross-linker from .cargo/config.toml.
146+
# Alpine's cc is already musl-native, so no custom linker is needed.
147+
# Must mirror [build].rustflags and target rustflags from .cargo/config.toml
148+
# (RUSTFLAGS env var overrides both levels).
149+
# -crt-static: vite-task is shipped as a NAPI module in vite+, and musl Node
150+
# with native modules links to musl libc dynamically, so we must do the same.
151+
RUSTFLAGS: --cfg tokio_unstable -D warnings -C target-feature=-crt-static
152+
# On musl, concurrent PTY operations can trigger SIGSEGV in musl internals.
153+
# Run test threads sequentially to avoid the race.
154+
RUST_TEST_THREADS: 1
155+
steps:
156+
- name: Install Alpine dependencies
157+
shell: sh {0}
158+
run: apk add --no-cache bash curl git musl-dev gcc g++ python3
159+
160+
- uses: actions/checkout@11bd71901bbe5b1630ceea73d27597364c9af683 # v4.2.2
161+
with:
162+
persist-credentials: false
163+
submodules: true
164+
165+
- name: Install rustup
166+
run: |
167+
curl --proto '=https' --tlsv1.2 -sSf https://sh.rustup.rs | sh -s -- -y --default-toolchain none
168+
echo "$HOME/.cargo/bin" >> "$GITHUB_PATH"
169+
170+
- name: Install Rust toolchain
171+
run: rustup show
172+
173+
- name: Install pnpm and Node tools
174+
run: |
175+
corepack enable
176+
pnpm install
177+
178+
- run: cargo test
179+
136180
fmt:
137181
name: Format and Check Deps
138182
runs-on: ubuntu-latest
@@ -168,6 +212,7 @@ jobs:
168212
needs:
169213
- clippy
170214
- test
215+
- test-musl
171216
- fmt
172217
steps:
173218
- run: exit 1

Cargo.lock

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

Cargo.toml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,7 +85,7 @@ jsonc-parser = { version = "0.29.0", features = ["serde"] }
8585
libc = "0.2.172"
8686
memmap2 = "0.9.7"
8787
monostate = "1.0.2"
88-
nix = { version = "0.30.1", features = ["dir"] }
88+
nix = { version = "0.30.1", features = ["dir", "signal"] }
8989
ntapi = "0.4.1"
9090
nucleo-matcher = "0.3.1"
9191
once_cell = "1.19"

crates/fspy/Cargo.toml

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -28,8 +28,10 @@ fspy_seccomp_unotify = { workspace = true, features = ["supervisor"] }
2828
nix = { workspace = true, features = ["uio"] }
2929
tokio = { workspace = true, features = ["bytes"] }
3030

31-
[target.'cfg(unix)'.dependencies]
31+
[target.'cfg(all(unix, not(target_env = "musl")))'.dependencies]
3232
fspy_preload_unix = { workspace = true }
33+
34+
[target.'cfg(unix)'.dependencies]
3335
fspy_shared_unix = { workspace = true }
3436
nix = { workspace = true, features = ["fs", "process", "socket", "feature"] }
3537

crates/fspy/README.md

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -2,7 +2,7 @@
22

33
Run a command and capture all the paths it tries to access.
44

5-
## macOS/Linux implementation
5+
## macOS/Linux (glibc) implementation
66

77
It uses `DYLD_INSERT_LIBRARIES` on macOS and `LD_PRELOAD` on Linux to inject a shared library that intercepts file system calls.
88
The injection process is almost identical on both platforms other than the environment variable name. The implementation is in `src/unix`.
@@ -11,6 +11,10 @@ The injection process is almost identical on both platforms other than the envir
1111

1212
For fully static binaries (such as `esbuild`), `LD_PRELOAD` does not work. In this case, `seccomp_unotify` is used to intercept direct system calls. The handler is implemented in `src/unix/syscall_handler`.
1313

14+
## Linux musl implementation
15+
16+
On musl targets, only `seccomp_unotify`-based tracking is used (no preload library).
17+
1418
## Windows implementation
1519

1620
It uses [Detours](https://github.com/microsoft/Detours) to intercept file system calls. The implementation is in `src/windows`.

crates/fspy/src/lib.rs

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,8 @@
22
#![feature(once_cell_try)]
33

44
// Persist the injected DLL/shared library somewhere in the filesystem.
5+
// Not needed on musl (seccomp-only tracking).
6+
#[cfg(not(target_env = "musl"))]
57
mod artifact;
68

79
pub mod error;

crates/fspy/src/unix/mod.rs

Lines changed: 28 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -8,7 +8,9 @@ use std::{io, path::Path};
88

99
#[cfg(target_os = "linux")]
1010
use fspy_seccomp_unotify::supervisor::supervise;
11-
use fspy_shared::ipc::{NativeStr, PathAccess, channel::channel};
11+
#[cfg(not(target_env = "musl"))]
12+
use fspy_shared::ipc::NativeStr;
13+
use fspy_shared::ipc::{PathAccess, channel::channel};
1214
#[cfg(target_os = "macos")]
1315
use fspy_shared_unix::payload::Artifacts;
1416
use fspy_shared_unix::{
@@ -33,28 +35,39 @@ pub struct SpyImpl {
3335
#[cfg(target_os = "macos")]
3436
artifacts: Artifacts,
3537

38+
#[cfg(not(target_env = "musl"))]
3639
preload_path: Box<NativeStr>,
3740
}
3841

42+
#[cfg(not(target_env = "musl"))]
3943
const PRELOAD_CDYLIB_BINARY: &[u8] = include_bytes!(env!("CARGO_CDYLIB_FILE_FSPY_PRELOAD_UNIX"));
4044

4145
impl SpyImpl {
42-
/// Initialize the fs access spy by writing the preload library on disk
43-
pub fn init_in(dir: &Path) -> io::Result<Self> {
44-
use const_format::formatcp;
45-
use xxhash_rust::const_xxh3::xxh3_128;
46-
47-
use crate::artifact::Artifact;
48-
49-
const PRELOAD_CDYLIB: Artifact = Artifact {
50-
name: "fspy_preload",
51-
content: PRELOAD_CDYLIB_BINARY,
52-
hash: formatcp!("{:x}", xxh3_128(PRELOAD_CDYLIB_BINARY)),
46+
/// Initialize the fs access spy by writing the preload library on disk.
47+
///
48+
/// On musl targets, we don't build a preload library —
49+
/// only seccomp-based tracking is used.
50+
pub fn init_in(#[cfg_attr(target_env = "musl", allow(unused))] dir: &Path) -> io::Result<Self> {
51+
#[cfg(not(target_env = "musl"))]
52+
let preload_path = {
53+
use const_format::formatcp;
54+
use xxhash_rust::const_xxh3::xxh3_128;
55+
56+
use crate::artifact::Artifact;
57+
58+
const PRELOAD_CDYLIB: Artifact = Artifact {
59+
name: "fspy_preload",
60+
content: PRELOAD_CDYLIB_BINARY,
61+
hash: formatcp!("{:x}", xxh3_128(PRELOAD_CDYLIB_BINARY)),
62+
};
63+
64+
let preload_cdylib_path = PRELOAD_CDYLIB.write_to(dir, ".dylib")?;
65+
preload_cdylib_path.as_path().into()
5366
};
5467

55-
let preload_cdylib_path = PRELOAD_CDYLIB.write_to(dir, ".dylib")?;
5668
Ok(Self {
57-
preload_path: preload_cdylib_path.as_path().into(),
69+
#[cfg(not(target_env = "musl"))]
70+
preload_path,
5871
#[cfg(target_os = "macos")]
5972
artifacts: {
6073
let coreutils_path = macos_artifacts::COREUTILS_BINARY.write_to(dir, "")?;
@@ -80,6 +93,7 @@ impl SpyImpl {
8093
#[cfg(target_os = "macos")]
8194
artifacts: self.artifacts.clone(),
8295

96+
#[cfg(not(target_env = "musl"))]
8397
preload_path: self.preload_path.clone(),
8498

8599
#[cfg(target_os = "linux")]

0 commit comments

Comments
 (0)