Skip to content

Commit

Permalink
Fixed fork and gethostname
Browse files Browse the repository at this point in the history
  • Loading branch information
Razz4780 committed Nov 3, 2023
1 parent 4d877a2 commit d4d8058
Show file tree
Hide file tree
Showing 5 changed files with 52 additions and 32 deletions.
1 change: 1 addition & 0 deletions changelog.d/+layer-trace-only.fixed.md
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Fixed layer bugs when `MIRRORD_LAYER_TRACE_ONLY` is set.
4 changes: 4 additions & 0 deletions mirrord/layer/src/detour.rs
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,10 @@ pub(crate) enum Bypass {

/// Incoming traffic is disabled, bypass.
DisabledIncoming,

/// Hostname should be resolved locally.
/// Currently this is the case only when the layer operates in the `trace only` mode.
LocalHostname,
}

/// [`ControlFlow`](std::ops::ControlFlow)-like enum to be used by hooks.
Expand Down
52 changes: 23 additions & 29 deletions mirrord/layer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -77,10 +77,7 @@ use libc::{c_int, pid_t};
use load::ExecutableName;
#[cfg(target_os = "macos")]
use mirrord_config::feature::fs::FsConfig;
use mirrord_config::{
feature::{fs::FsModeConfig, network::incoming::IncomingMode},
LayerConfig,
};
use mirrord_config::{feature::fs::FsModeConfig, LayerConfig};
use mirrord_intproxy::protocol::NewSessionRequest;
use mirrord_layer_macro::{hook_fn, hook_guard_fn};
use proxy_connection::ProxyConnection;
Expand Down Expand Up @@ -266,23 +263,14 @@ fn layer_start(mut config: LayerConfig) {
.parse()
.unwrap_or(false);

// Disable all features that require the agent
if trace_only {
config.feature.fs.mode = FsModeConfig::Local;
config.feature.network.dns = false;
config.feature.network.incoming.mode = IncomingMode::Off;
config.feature.network.outgoing.tcp = false;
config.feature.network.outgoing.udp = false;
}

// does not need to be atomic because on the first call there are never other threads.
// Will be false when manually called from fork hook.
if SETUP.get().is_none() {
// If we're here it's not a fork, we're in the ctor.
init_tracing();

let debugger_ports = DebuggerPorts::from_env();
let state = LayerSetup::new(config, debugger_ports);
let state = LayerSetup::new(config, debugger_ports, trace_only);
SETUP.set(state).unwrap();

let state = setup();
Expand Down Expand Up @@ -466,28 +454,34 @@ pub(crate) unsafe extern "C" fn close_detour(fd: c_int) -> c_int {
pub(crate) unsafe extern "C" fn fork_detour() -> pid_t {
tracing::debug!("Process {} forking!.", std::process::id());

let parent_connection = PROXY_CONNECTION.get().expect("PROXY_CONNECTION not set");

// After fork, this new connection lives both in the parent and in the child.
// The child will have access to cloned file descriptor of the underlying socket.
// The parent will close its descriptor at the end of this scope.
let new_connection = ProxyConnection::new(
parent_connection.proxy_addr(),
NewSessionRequest::Forked(parent_connection.layer_id()),
Duration::from_secs(5),
)
.expect("failed to establish proxy connection for child");
let new_connection = if setup().trace_only() {
None
} else {
let parent_connection = PROXY_CONNECTION.get().expect("PROXY_CONNECTION not set");
// After fork, this new connection lives both in the parent and in the child.
// The child will have access to cloned file descriptor of the underlying socket.
// The parent will close its descriptor at the end of this scope.
ProxyConnection::new(
parent_connection.proxy_addr(),
NewSessionRequest::Forked(parent_connection.layer_id()),
Duration::from_secs(5),
)
.expect("failed to establish proxy connection for child")
.into()
};

let res = FN_FORK();

match res.cmp(&0) {
Ordering::Equal => {
tracing::debug!("Child process initializing layer.");

PROXY_CONNECTION.take();
PROXY_CONNECTION
.set(new_connection)
.expect("setting PROXY_CONNECTION");
if let Some(new_connection) = new_connection {
PROXY_CONNECTION.take();
PROXY_CONNECTION
.set(new_connection)
.expect("setting PROXY_CONNECTION");
}

mirrord_layer_entry_point()
}
Expand Down
23 changes: 20 additions & 3 deletions mirrord/layer/src/setup.rs
Original file line number Diff line number Diff line change
Expand Up @@ -2,8 +2,11 @@ use std::{collections::HashSet, net::SocketAddr};

use mirrord_config::{
feature::{
fs::FsConfig,
network::{incoming::IncomingConfig, outgoing::OutgoingConfig},
fs::{FsConfig, FsModeConfig},
network::{
incoming::{self, IncomingConfig},
outgoing::OutgoingConfig,
},
},
util::VecOrSingle,
LayerConfig,
Expand All @@ -29,10 +32,19 @@ pub struct LayerSetup {
outgoing_selector: OutgoingSelector,
proxy_address: SocketAddr,
incoming_mode: IncomingMode,
trace_only: bool,
}

impl LayerSetup {
pub fn new(config: LayerConfig, debugger_ports: DebuggerPorts) -> Self {
pub fn new(mut config: LayerConfig, debugger_ports: DebuggerPorts, trace_only: bool) -> Self {
if trace_only {
config.feature.network.dns = false;
config.feature.network.outgoing.tcp = false;
config.feature.network.outgoing.udp = false;
config.feature.network.incoming.mode = incoming::IncomingMode::Off;
config.feature.fs.mode = FsModeConfig::Local;
}

let file_filter = FileFilter::new(config.feature.fs.clone());

let remote_unix_streams = config
Expand Down Expand Up @@ -67,6 +79,7 @@ impl LayerSetup {
outgoing_selector,
proxy_address,
incoming_mode,
trace_only,
}
}

Expand Down Expand Up @@ -121,6 +134,10 @@ impl LayerSetup {
pub fn incoming_mode(&self) -> &IncomingMode {
&self.incoming_mode
}

pub fn trace_only(&self) -> bool {
self.trace_only
}
}

/// HTTP filter used by the layer with the `steal` feature.
Expand Down
4 changes: 4 additions & 0 deletions mirrord/layer/src/socket/ops.rs
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,10 @@ pub(super) fn getaddrinfo(

/// Retrieves the `hostname` from the agent's `/etc/hostname` to be used by [`gethostname`]
fn remote_hostname_string() -> Detour<CString> {
if crate::setup().trace_only() {
return Detour::Bypass(Bypass::LocalHostname);
}

let hostname_path = PathBuf::from("/etc/hostname");

let OpenFileResponse { fd } = file::ops::RemoteFile::remote_open(
Expand Down

0 comments on commit d4d8058

Please sign in to comment.