Skip to content

Commit 23f2a0a

Browse files
authored
Merge branch 'main' into dimad/mbe-736-add-support-for-argo-workflow-targets
2 parents fab6221 + ab018da commit 23f2a0a

26 files changed

+349
-60
lines changed

.github/workflows/ci.yaml

+8
Original file line numberDiff line numberDiff line change
@@ -366,6 +366,9 @@ jobs:
366366
- run: |
367367
cd mirrord/layer/tests/apps/issue2438
368368
cargo build
369+
- run: |
370+
cd mirrord/layer/tests/apps/issue3248
371+
cargo build
369372
- run: |
370373
cd mirrord/layer/tests/apps/rebind0
371374
cargo build
@@ -414,6 +417,8 @@ jobs:
414417
uses: metalbear-co/setup-protoc@3ea1d70ac22caff0b66ed6cb37d5b7aadebd4623
415418
with:
416419
repo-token: ${{ secrets.GITHUB_TOKEN }}
420+
- name: verify SIP status
421+
run: csrutil status
417422
# this is required for clippy lint because the layer path variable is checked at compile time
418423
- name: create fake layer file
419424
run: touch /tmp/file.dylib
@@ -494,6 +499,9 @@ jobs:
494499
- run: |
495500
cd mirrord/layer/tests/apps/issue2438
496501
cargo build
502+
- run: |
503+
cd mirrord/layer/tests/apps/issue3248
504+
cargo build
497505
- run: |
498506
cd mirrord/layer/tests/apps/rebind0
499507
cargo build

Cargo.lock

+5
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@ members = [
1414
"mirrord/layer/tests/apps/issue1899",
1515
"mirrord/layer/tests/apps/issue2001",
1616
"mirrord/layer/tests/apps/issue2438",
17+
"mirrord/layer/tests/apps/issue3248",
1718
"mirrord/layer/tests/apps/rebind0",
1819
"sample/rust",
1920
"medschool",
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fixed logic for detecting whether the operator supports Kafka splitting without copying the target.

changelog.d/+skip-sip.added.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Added the option to skip sip patching.

changelog.d/3245.fixed.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Tie SIP patch files to the version of mirrord so that fixes to patching will create new files.

changelog.d/3271.fixed.md

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
Fix docs on how to specify multiple binaries.

mirrord-schema.json

+14-2
Original file line numberDiff line numberDiff line change
@@ -112,7 +112,7 @@
112112
},
113113
"sip_binaries": {
114114
"title": "sip_binaries {#root-sip_binaries}",
115-
"description": "Binaries to patch (macOS SIP).\n\nUse this when mirrord isn't loaded to protected binaries that weren't automatically patched.\n\nRuns `endswith` on the binary path (so `bash` would apply to any binary ending with `bash` while `/usr/bin/bash` would apply only for that binary).\n\n```json { \"sip_binaries\": \"bash;python\" } ```",
115+
"description": "Binaries to patch (macOS SIP).\n\nUse this when mirrord isn't loaded to protected binaries that weren't automatically patched.\n\nRuns `endswith` on the binary path (so `bash` would apply to any binary ending with `bash` while `/usr/bin/bash` would apply only for that binary).\n\n```json { \"sip_binaries\": [\"bash\", \"python\"] } ```",
116116
"anyOf": [
117117
{
118118
"$ref": "#/definitions/VecOrSingle_for_String"
@@ -132,7 +132,19 @@
132132
},
133133
"skip_processes": {
134134
"title": "skip_processes {#root-skip_processes}",
135-
"description": "Allows mirrord to skip unwanted processes.\n\nUseful when process A spawns process B, and the user wants mirrord to operate only on process B. Accepts a single value, or multiple values separated by `;`.\n\n```json { \"skip_processes\": \"bash;node\" } ```",
135+
"description": "Allows mirrord to skip unwanted processes.\n\nUseful when process A spawns process B, and the user wants mirrord to operate only on process B. Accepts a single value, or an array of values.\n\n```json { \"skip_processes\": [\"bash\", \"node\"] } ```",
136+
"anyOf": [
137+
{
138+
"$ref": "#/definitions/VecOrSingle_for_String"
139+
},
140+
{
141+
"type": "null"
142+
}
143+
]
144+
},
145+
"skip_sip": {
146+
"title": "skip_sip {#root-skip_sip}",
147+
"description": "Allows mirrord to skip patching (macOS SIP) unwanted processes.\n\nWhen patching is skipped, mirrord will no longer be able to load into the process and its child processes.",
136148
"anyOf": [
137149
{
138150
"$ref": "#/definitions/VecOrSingle_for_String"

mirrord/cli/src/execution.rs

+13-6
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ use mirrord_protocol::{
1717
LogLevel,
1818
};
1919
#[cfg(target_os = "macos")]
20-
use mirrord_sip::sip_patch;
20+
use mirrord_sip::{sip_patch, SipPatchOptions};
2121
use mirrord_tls_util::SecureChannelSetup;
2222
use semver::Version;
2323
use serde::Serialize;
@@ -308,11 +308,18 @@ impl MirrordExecution {
308308
.and_then(|exe| {
309309
sip_patch(
310310
exe,
311-
&config
312-
.sip_binaries
313-
.clone()
314-
.map(|x| x.to_vec())
315-
.unwrap_or_default(),
311+
SipPatchOptions {
312+
patch: &config
313+
.sip_binaries
314+
.clone()
315+
.map(|x| x.to_vec())
316+
.unwrap_or_default(),
317+
skip: &config
318+
.skip_sip
319+
.clone()
320+
.map(|x| x.to_vec())
321+
.unwrap_or_default(),
322+
},
316323
)
317324
.transpose() // We transpose twice to propagate a possible error out of this
318325
// closure.

mirrord/cli/src/main.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
//! the [`LayerConfig`], and checks it with [`LayerConfig::verify`] (which is similar to what's done
3333
//! in the `mirrord verify-config` command).
3434
//!
35-
//! - Tip: [`Progress`] logging might be incovenient sometimes when you want to see normal Rust
35+
//! - Tip: [`Progress`] logging might be inconvenient sometimes when you want to see normal Rust
3636
//! logs, you can disable it with the `MIRRORD_PROGRESS_MODE=off` env var.
3737
//!
3838
//! Next, we start the target resolution, and how the target is resolved depends if the

mirrord/config/configuration.md

+2-2
Original file line numberDiff line numberDiff line change
@@ -1683,7 +1683,7 @@ while `/usr/bin/bash` would apply only for that binary).
16831683

16841684
```json
16851685
{
1686-
"sip_binaries": "bash;python"
1686+
"sip_binaries": ["bash", "python"]
16871687
}
16881688
```
16891689

@@ -1708,7 +1708,7 @@ Accepts a single value, or multiple values separated by `;`.
17081708

17091709
```json
17101710
{
1711-
"skip_processes": "bash;node"
1711+
"skip_processes": ["bash", "node"]
17121712
}
17131713
```
17141714

mirrord/config/src/lib.rs

+13-3
Original file line numberDiff line numberDiff line change
@@ -205,11 +205,11 @@ pub struct LayerConfig {
205205
///
206206
/// Useful when process A spawns process B, and the user wants mirrord to operate only on
207207
/// process B.
208-
/// Accepts a single value, or multiple values separated by `;`.
208+
/// Accepts a single value, or an array of values.
209209
///
210210
///```json
211211
/// {
212-
/// "skip_processes": "bash;node"
212+
/// "skip_processes": ["bash", "node"]
213213
/// }
214214
/// ```
215215
#[config(env = "MIRRORD_SKIP_PROCESSES")]
@@ -266,7 +266,7 @@ pub struct LayerConfig {
266266
///
267267
/// ```json
268268
/// {
269-
/// "sip_binaries": "bash;python"
269+
/// "sip_binaries": ["bash", "python"]
270270
/// }
271271
/// ```
272272
pub sip_binaries: Option<VecOrSingle<String>>,
@@ -329,6 +329,15 @@ pub struct LayerConfig {
329329
/// ## experimental {#root-experimental}
330330
#[config(nested)]
331331
pub experimental: ExperimentalConfig,
332+
333+
/// ## skip_sip {#root-skip_sip}
334+
///
335+
/// Allows mirrord to skip patching (macOS SIP) unwanted processes.
336+
///
337+
/// When patching is skipped, mirrord will no longer be able to load into
338+
/// the process and its child processes.
339+
#[config(env = "MIRRORD_SKIP_SIP")]
340+
pub skip_sip: Option<VecOrSingle<String>>,
332341
}
333342

334343
impl LayerConfig {
@@ -1002,6 +1011,7 @@ mod tests {
10021011
internal_proxy: None,
10031012
use_proxy: None,
10041013
experimental: None,
1014+
skip_sip: None,
10051015
};
10061016

10071017
assert_eq!(config, expect);

mirrord/layer/Cargo.toml

+3
Original file line numberDiff line numberDiff line change
@@ -65,5 +65,8 @@ tests = { path = "../../tests" }
6565
test-cdylib = "1"
6666
tokio = { workspace = true, features = ["rt", "net", "macros", "fs"] }
6767

68+
[target.'cfg(target_os = "macos")'.dev-dependencies]
69+
apple-codesign = { version = "0.29", default-features = false }
70+
6871
[lib]
6972
crate-type = ["cdylib"]

mirrord/layer/src/exec_utils.rs

+17-2
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,7 @@ use std::{
77

88
use libc::{c_char, c_int, pid_t};
99
use mirrord_layer_macro::{hook_fn, hook_guard_fn};
10-
use mirrord_sip::{sip_patch, SipError, MIRRORD_PATCH_DIR};
10+
use mirrord_sip::{sip_patch, SipError, SipPatchOptions, MIRRORD_PATCH_DIR};
1111
use null_terminated::Nul;
1212
use tracing::{trace, warn};
1313

@@ -33,13 +33,19 @@ const MAX_ARGC: usize = 256;
3333

3434
pub(crate) static PATCH_BINARIES: OnceLock<Vec<String>> = OnceLock::new();
3535

36+
pub(crate) static SKIP_PATCH_BINARIES: OnceLock<Vec<String>> = OnceLock::new();
37+
3638
pub(crate) unsafe fn enable_macos_hooks(
3739
hook_manager: &mut HookManager,
3840
patch_binaries: Vec<String>,
41+
skip_binaries: Vec<String>,
3942
) {
4043
PATCH_BINARIES
4144
.set(patch_binaries)
4245
.expect("couldn't set patch_binaries");
46+
SKIP_PATCH_BINARIES
47+
.set(skip_binaries)
48+
.expect("couldn't set skip_binaries");
4349
replace!(
4450
hook_manager,
4551
"posix_spawn",
@@ -61,7 +67,16 @@ pub(crate) unsafe fn enable_macos_hooks(
6167
#[mirrord_layer_macro::instrument(level = "trace")]
6268
pub(super) fn patch_if_sip(path: &str) -> Detour<String> {
6369
let patch_binaries = PATCH_BINARIES.get().expect("patch binaries not set");
64-
match sip_patch(path, patch_binaries) {
70+
let skip_patch_binaries = SKIP_PATCH_BINARIES
71+
.get()
72+
.expect("skip patch binaries not set");
73+
match sip_patch(
74+
path,
75+
SipPatchOptions {
76+
patch: patch_binaries,
77+
skip: skip_patch_binaries,
78+
},
79+
) {
6580
Ok(None) => Bypass(NoSipDetected(path.to_string())),
6681
Ok(Some(new_path)) => Success(new_path),
6782
Err(SipError::FileNotFound(non_existing_bin)) => {

mirrord/layer/src/lib.rs

+27-5
Original file line numberDiff line numberDiff line change
@@ -107,6 +107,8 @@ use crate::{
107107
#[cfg(test)]
108108
mod integration_tests_deps {
109109
use actix_codec as _;
110+
#[cfg(target_os = "macos")]
111+
use apple_codesign as _;
110112
use futures as _;
111113
use mirrord_intproxy as _;
112114
use serde_json as _;
@@ -197,14 +199,27 @@ fn layer_pre_initialization() -> Result<(), LayerError> {
197199
.map(|x| x.to_vec())
198200
.unwrap_or_default();
199201

202+
#[cfg(target_os = "macos")]
203+
let skip_patch_binaries = config
204+
.skip_sip
205+
.clone()
206+
.map(|x| x.to_vec())
207+
.unwrap_or_default();
208+
200209
// SIP Patch the process' binary then re-execute it. Needed
201210
// for https://github.com/metalbear-co/mirrord/issues/1529
202211
#[cfg(target_os = "macos")]
203212
if given_process.ends_with("dotnet") {
204213
let path = EXECUTABLE_PATH
205214
.get()
206215
.expect("EXECUTABLE_PATH needs to be set!");
207-
if let Ok(Some(binary)) = mirrord_sip::sip_patch(path, &patch_binaries) {
216+
if let Ok(Some(binary)) = mirrord_sip::sip_patch(
217+
path,
218+
mirrord_sip::SipPatchOptions {
219+
patch: &patch_binaries,
220+
skip: &skip_patch_binaries,
221+
},
222+
) {
208223
let err = exec::execvp(
209224
binary,
210225
EXECUTABLE_ARGS
@@ -221,7 +236,7 @@ fn layer_pre_initialization() -> Result<(), LayerError> {
221236
match given_process.load_type(&config) {
222237
LoadType::Full => layer_start(config),
223238
#[cfg(target_os = "macos")]
224-
LoadType::SIPOnly => sip_only_layer_start(config, patch_binaries),
239+
LoadType::SIPOnly => sip_only_layer_start(config, patch_binaries, skip_patch_binaries),
225240
LoadType::Skip => load_only_layer_start(&config),
226241
}
227242

@@ -488,14 +503,20 @@ fn fetch_env_vars() -> HashMap<String, String> {
488503
/// We need to hook execve syscall to allow mirrord-layer to be loaded with sip patch when loading
489504
/// mirrord-layer on a process where specified to skip with MIRRORD_SKIP_PROCESSES
490505
#[cfg(target_os = "macos")]
491-
fn sip_only_layer_start(mut config: LayerConfig, patch_binaries: Vec<String>) {
506+
fn sip_only_layer_start(
507+
mut config: LayerConfig,
508+
patch_binaries: Vec<String>,
509+
skip_patch_binaries: Vec<String>,
510+
) {
492511
use mirrord_config::feature::fs::READONLY_FILE_BUFFER_DEFAULT;
493512

494513
load_only_layer_start(&config);
495514

496515
let mut hook_manager = HookManager::default();
497516

498-
unsafe { exec_utils::enable_macos_hooks(&mut hook_manager, patch_binaries) };
517+
unsafe {
518+
exec_utils::enable_macos_hooks(&mut hook_manager, patch_binaries, skip_patch_binaries)
519+
};
499520
unsafe { exec_hooks::hooks::enable_exec_hooks(&mut hook_manager) };
500521
// we need to hook file access to patch path to our temp bin.
501522
config.feature.fs = FsConfig {
@@ -591,7 +612,8 @@ fn enable_hooks(state: &LayerSetup) {
591612
use crate::exec_utils::enable_macos_hooks;
592613

593614
let patch_binaries = state.sip_binaries();
594-
unsafe { enable_macos_hooks(&mut hook_manager, patch_binaries) };
615+
let skip_patch_binaries = state.skip_patch_binaries();
616+
unsafe { enable_macos_hooks(&mut hook_manager, patch_binaries, skip_patch_binaries) };
595617

596618
if state.experimental().trust_any_certificate {
597619
unsafe { tls::enable_tls_hooks(&mut hook_manager) };

mirrord/layer/src/setup.rs

+9
Original file line numberDiff line numberDiff line change
@@ -151,6 +151,15 @@ impl LayerSetup {
151151
.unwrap_or_default()
152152
}
153153

154+
#[cfg(target_os = "macos")]
155+
pub fn skip_patch_binaries(&self) -> Vec<String> {
156+
self.config
157+
.skip_sip
158+
.as_deref()
159+
.map(<[_]>::to_vec)
160+
.unwrap_or_default()
161+
}
162+
154163
pub fn is_debugger_port(&self, addr: &SocketAddr) -> bool {
155164
self.debugger_ports.contains(addr)
156165
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
[package]
2+
name = "issue3248"
3+
version = "0.1.0"
4+
edition = "2021"
5+
license.workspace = true
6+
7+
[dependencies]
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,7 @@
1+
fn main() {
2+
let script_path = std::env::var("TEST_SCRIPT_PATH").unwrap();
3+
let binary_path = std::env::var("TEST_BINARY_PATH").unwrap();
4+
let _output = std::process::Command::new(script_path).output().unwrap();
5+
6+
let _output = std::process::Command::new(binary_path).output().unwrap();
7+
}

mirrord/layer/tests/bash.rs

+4-2
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ use mirrord_protocol::{
99
ClientMessage, DaemonMessage, FileRequest, FileResponse,
1010
};
1111
#[cfg(target_os = "macos")]
12-
use mirrord_sip::sip_patch;
12+
use mirrord_sip::{sip_patch, SipPatchOptions};
1313
use rstest::rstest;
1414
use tokio::net::TcpListener;
1515

@@ -37,7 +37,9 @@ async fn bash_script(dylib_path: &Path, config_dir: &Path) {
3737
println!("Listening for messages from the layer on {addr}");
3838
let env = get_env(dylib_path, addr, vec![], Some(&config_path));
3939
#[cfg(target_os = "macos")]
40-
let executable = sip_patch(&executable, &Vec::new()).unwrap().unwrap();
40+
let executable = sip_patch(&executable, SipPatchOptions::default())
41+
.unwrap()
42+
.unwrap();
4143
let test_process = TestProcess::start_process(executable, application.get_args(), env).await;
4244

4345
let mut intproxy = TestIntProxy::new(listener).await;

0 commit comments

Comments
 (0)