Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
15 changes: 15 additions & 0 deletions crates/openshell-driver-podman/src/container.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1494,6 +1494,13 @@ pub fn build_isolation_specs(
openshell_core::sandbox_env::ADMITTED_ISOLATION_BACKEND.into(),
openshell_sandbox_backend::BACKEND_NAME.into(),
);
// The supervisor runs as the resolved non-root workload identity. Keep
// generated interception CA material under its writable /run tmpfs rather
// than the root-owned default at /etc/openshell-tls.
supervisor.env.insert(
openshell_core::sandbox_env::PROXY_TLS_DIR.into(),
"/run/openshell/proxy-tls".into(),
);
supervisor.user = user;
supervisor.groups = input
.identity
Expand Down Expand Up @@ -1801,6 +1808,14 @@ mod tests {
.contains(&"nocopy".into())
);
assert_eq!(specs.supervisor.entrypoint, vec!["/openshell-supervisor"]);
assert_eq!(
specs
.supervisor
.env
.get(openshell_core::sandbox_env::PROXY_TLS_DIR)
.map(String::as_str),
Some("/run/openshell/proxy-tls")
);
}

fn json_struct(value: Value) -> prost_types::Struct {
Expand Down
24 changes: 23 additions & 1 deletion crates/openshell-sandbox/src/network_broker.rs
Original file line number Diff line number Diff line change
Expand Up @@ -41,6 +41,10 @@ const DNS_RELAY_ADDRESS: SocketAddr = SocketAddr::V4(std::net::SocketAddrV4::new
const RELAY_CONNECT_TIMEOUT: Duration = Duration::from_secs(5);
const NETWORK_DECISION_TIMEOUT: Duration = Duration::from_secs(30);

fn retry_notification_receive(error: &io::Error) -> bool {
error.kind() == io::ErrorKind::Interrupted || error.raw_os_error() == Some(libc::ENOENT)
}

#[derive(Debug)]
struct PendingOpenSlot(Arc<AtomicUsize>);

Expand Down Expand Up @@ -271,7 +275,12 @@ impl NetworkBroker {
while broker_healthy.load(Ordering::Acquire) {
let notification = match listener.receive() {
Ok(notification) => notification,
Err(error) if error.kind() == io::ErrorKind::Interrupted => continue,
// ENOENT is a documented seccomp user-notification
// race: the target thread exited or its blocked
// syscall was interrupted while the kernel was
// preparing the notification. It does not mean the
// listener itself is unhealthy.
Err(error) if retry_notification_receive(&error) => continue,
Err(error) => {
tracing::error!(%error, "sandbox network broker listener failed");
broker_healthy.store(false, Ordering::Release);
Expand Down Expand Up @@ -1754,6 +1763,19 @@ mod tests {
use std::io::{Read as _, Write as _};
use std::os::unix::net::{UnixListener, UnixStream};

#[test]
fn notification_receive_retries_interrupted_and_disappeared_targets() {
assert!(retry_notification_receive(&io::Error::from(
io::ErrorKind::Interrupted
)));
assert!(retry_notification_receive(&io::Error::from_raw_os_error(
libc::ENOENT
)));
assert!(!retry_notification_receive(&io::Error::from_raw_os_error(
libc::EBADF
)));
}

#[test]
fn relay_rejects_descriptor_replaced_after_policy_decision() {
let metadata = SocketMetadata {
Expand Down
Loading