diff --git a/Cargo.lock b/Cargo.lock index 1e9753be..d668bde3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -533,7 +533,7 @@ dependencies = [ "flate2", "libcgroups", "libcontainer", - "nix 0.27.1", + "nix 0.28.0", "num_cpus", "oci-spec", "once_cell", @@ -1938,7 +1938,7 @@ dependencies = [ "libbpf-sys", "libc", "mockall", - "nix 0.27.1", + "nix 0.28.0", "oci-spec", "procfs", "quickcheck", @@ -1965,7 +1965,7 @@ dependencies = [ "libcgroups", "libseccomp", "nc", - "nix 0.27.1", + "nix 0.28.0", "oci-spec", "once_cell", "prctl", @@ -2257,7 +2257,6 @@ dependencies = [ "bitflags 2.5.0", "cfg-if", "libc", - "memoffset 0.9.1", ] [[package]] @@ -2270,6 +2269,7 @@ dependencies = [ "cfg-if", "cfg_aliases", "libc", + "memoffset 0.9.1", ] [[package]] @@ -3153,7 +3153,7 @@ dependencies = [ "anyhow", "libc", "nc", - "nix 0.27.1", + "nix 0.28.0", "oci-spec", ] @@ -5712,7 +5712,7 @@ dependencies = [ "libcgroups", "libcontainer", "liboci-cli", - "nix 0.27.1", + "nix 0.28.0", "once_cell", "pentacle", "procfs", diff --git a/crates/libcgroups/Cargo.toml b/crates/libcgroups/Cargo.toml index a01c6bb1..868eaf47 100644 --- a/crates/libcgroups/Cargo.toml +++ b/crates/libcgroups/Cargo.toml @@ -20,7 +20,7 @@ systemd = ["v2", "nix/socket", "nix/uio"] cgroupsv2_devices = ["rbpf", "libbpf-sys", "errno", "libc", "nix/dir"] [dependencies] -nix = { version = "0.27.1", features = ["signal", "user", "fs"] } +nix = { version = "0.28.0", features = ["signal", "user", "fs"] } procfs = "0.16.0" oci-spec = { version = "~0.6.4", features = ["runtime"] } fixedbitset = "0.5.7" diff --git a/crates/libcgroups/src/v1/memory.rs b/crates/libcgroups/src/v1/memory.rs index 2d6d644f..a55e3fe8 100644 --- a/crates/libcgroups/src/v1/memory.rs +++ b/crates/libcgroups/src/v1/memory.rs @@ -331,7 +331,7 @@ impl Memory { Err(e) => { // we need to look into the raw OS error for an EBUSY status match e.inner().raw_os_error() { - Some(code) => match Errno::from_i32(code) { + Some(code) => match Errno::from_raw(code) { Errno::EBUSY => { let usage = Self::get_memory_usage(cgroup_root)?; let max_usage = Self::get_memory_max_usage(cgroup_root)?; diff --git a/crates/libcontainer/Cargo.toml b/crates/libcontainer/Cargo.toml index 364a9b05..a2ea5f1c 100644 --- a/crates/libcontainer/Cargo.toml +++ b/crates/libcontainer/Cargo.toml @@ -29,7 +29,7 @@ chrono = { version = "0.4", default-features = false, features = [ fastrand = "^2.1.0" futures = { version = "0.3", features = ["thread-pool"] } libc = "0.2.155" -nix = { version = "0.27.1", features = [ +nix = { version = "0.28.0", features = [ "socket", "sched", "mount", diff --git a/crates/libcontainer/src/container/builder_impl.rs b/crates/libcontainer/src/container/builder_impl.rs index 7eeb58d4..4de50391 100644 --- a/crates/libcontainer/src/container/builder_impl.rs +++ b/crates/libcontainer/src/container/builder_impl.rs @@ -133,7 +133,7 @@ impl ContainerBuilderImpl { prctl::set_dumpable(false).map_err(|e| { LibcontainerError::Other(format!( "error in setting dumpable to false : {}", - nix::errno::from_i32(e) + nix::errno::Errno::from_raw(e) )) })?; } diff --git a/crates/libcontainer/src/container/tenant_builder.rs b/crates/libcontainer/src/container/tenant_builder.rs index 11cc59e1..979eaf56 100644 --- a/crates/libcontainer/src/container/tenant_builder.rs +++ b/crates/libcontainer/src/container/tenant_builder.rs @@ -3,6 +3,7 @@ use std::convert::TryFrom; use std::ffi::{OsStr, OsString}; use std::fs; use std::io::BufReader; +use std::os::fd::AsRawFd; use std::os::unix::prelude::RawFd; use std::path::{Path, PathBuf}; use std::rc::Rc; @@ -10,7 +11,7 @@ use std::str::FromStr; use caps::Capability; use nix::fcntl::OFlag; -use nix::unistd::{close, pipe2, read, Pid}; +use nix::unistd::{pipe2, read, Pid}; use oci_spec::runtime::{ Capabilities as SpecCapabilities, Capability as SpecCapability, LinuxBuilder, LinuxCapabilities, LinuxCapabilitiesBuilder, LinuxNamespace, LinuxNamespaceBuilder, @@ -126,7 +127,7 @@ impl TenantContainerBuilder { let mut builder_impl = ContainerBuilderImpl { container_type: ContainerType::TenantContainer { - exec_notify_fd: write_end, + exec_notify_fd: write_end.as_raw_fd(), }, syscall: self.base.syscall, container_id: self.base.container_id, @@ -148,13 +149,19 @@ impl TenantContainerBuilder { let mut notify_socket = NotifySocket::new(notify_path); notify_socket.notify_container_start()?; - close(write_end).map_err(LibcontainerError::OtherSyscall)?; + // Explicitly close the write end of the pipe here to notify the + // `read_end` that the init process is able to move forward. Closing one + // end of the pipe will immediately signal the other end of the pipe, + // which we use in the init thread as a form of barrier. `drop` is used + // here becuase `OwnedFd` supports it, so we don't have to use `close` + // here with `RawFd`. + drop(write_end); let mut err_str_buf = Vec::new(); loop { let mut buf = [0; 3]; - match read(read_end, &mut buf).map_err(LibcontainerError::OtherSyscall)? { + match read(read_end.as_raw_fd(), &mut buf).map_err(LibcontainerError::OtherSyscall)? { 0 => { if err_str_buf.is_empty() { return Ok(pid); diff --git a/crates/libcontainer/src/process/container_intermediate_process.rs b/crates/libcontainer/src/process/container_intermediate_process.rs index 306fd76b..fad2103d 100644 --- a/crates/libcontainer/src/process/container_intermediate_process.rs +++ b/crates/libcontainer/src/process/container_intermediate_process.rs @@ -1,3 +1,5 @@ +use std::os::fd::FromRawFd; + use libcgroups::common::CgroupManager; use nix::unistd::{close, write, Gid, Pid, Uid}; use oci_spec::runtime::{LinuxNamespace, LinuxNamespaceType, LinuxResources}; @@ -130,12 +132,15 @@ pub fn container_intermediate_process( } if let ContainerType::TenantContainer { exec_notify_fd } = args.container_type { let buf = format!("{e}"); - if let Err(err) = write(exec_notify_fd, buf.as_bytes()) { + let exec_notify_fd = + unsafe { std::os::fd::OwnedFd::from_raw_fd(exec_notify_fd) }; + if let Err(err) = write(&exec_notify_fd, buf.as_bytes()) { tracing::error!(?err, "failed to write to exec notify fd"); } - if let Err(err) = close(exec_notify_fd) { - tracing::error!(?err, "failed to close exec notify fd"); - } + + // After sending the error through the exec_notify_fd, + // we need to explicitly close the pipe. + drop(exec_notify_fd); } -1 } @@ -206,7 +211,7 @@ fn setup_userns( prctl::set_dumpable(true).map_err(|e| { IntermediateProcessError::Other(format!( "error in setting dumpable to true : {}", - nix::errno::from_i32(e) + nix::errno::Errno::from_raw(e) )) })?; sender.identifier_mapping_request().map_err(|err| { @@ -220,7 +225,7 @@ fn setup_userns( prctl::set_dumpable(false).map_err(|e| { IntermediateProcessError::Other(format!( "error in setting dumplable to false : {}", - nix::errno::from_i32(e) + nix::errno::Errno::from_raw(e) )) })?; Ok(()) diff --git a/crates/libcontainer/src/process/fork.rs b/crates/libcontainer/src/process/fork.rs index 5f06e3f5..64143883 100644 --- a/crates/libcontainer/src/process/fork.rs +++ b/crates/libcontainer/src/process/fork.rs @@ -1,5 +1,4 @@ use std::ffi::c_int; -use std::fs::File; use std::num::NonZeroUsize; use libc::SIGCHLD; @@ -164,15 +163,11 @@ fn clone(cb: CloneCb, flags: u64, exit_signal: Option) -> Result` doesn't have any meaning because we won't use it. - mman::mmap::( + mman::mmap_anonymous( None, NonZeroUsize::new(default_stack_size).ok_or(CloneError::ZeroStackSize)?, mman::ProtFlags::PROT_READ | mman::ProtFlags::PROT_WRITE, - mman::MapFlags::MAP_PRIVATE | mman::MapFlags::MAP_ANONYMOUS | mman::MapFlags::MAP_STACK, - None, - 0, + mman::MapFlags::MAP_PRIVATE | mman::MapFlags::MAP_STACK, ) .map_err(CloneError::StackAllocation)? }; @@ -187,7 +182,7 @@ fn clone(cb: CloneCb, flags: u64, exit_signal: Option) -> Result Result<()> { prctl::set_keep_capabilities(true).map_err(|errno| { tracing::error!(?errno, "failed to set keep capabilities to true"); - nix::errno::from_i32(errno) + nix::errno::Errno::from_raw(errno) })?; // args : real *id, effective *id, saved set *id respectively @@ -350,7 +350,7 @@ impl Syscall for LinuxSyscall { } prctl::set_keep_capabilities(false).map_err(|errno| { tracing::error!(?errno, "failed to set keep capabilities to false"); - nix::errno::from_i32(errno) + nix::errno::Errno::from_raw(errno) })?; Ok(()) } diff --git a/crates/youki/Cargo.toml b/crates/youki/Cargo.toml index c245f109..00590e65 100644 --- a/crates/youki/Cargo.toml +++ b/crates/youki/Cargo.toml @@ -32,7 +32,7 @@ chrono = { version = "0.4", default-features = false, features = ["clock", "serd libcgroups = { path = "../libcgroups", default-features = false, version = "0.3.3" } # MARK: Version libcontainer = { path = "../libcontainer", default-features = false, version = "0.3.3" } # MARK: Version liboci-cli = { path = "../liboci-cli", version = "0.3.3" } # MARK: Version -nix = "0.27.1" +nix = "0.28.0" once_cell = "1.19.0" pentacle = "1.0.0" procfs = "0.16.0" diff --git a/tests/contest/contest/Cargo.toml b/tests/contest/contest/Cargo.toml index 252fef00..81d90cca 100644 --- a/tests/contest/contest/Cargo.toml +++ b/tests/contest/contest/Cargo.toml @@ -9,7 +9,7 @@ chrono = { version = "0.4", default-features = false, features = ["clock"] } flate2 = "1.0" libcgroups = { path = "../../../crates/libcgroups" } libcontainer = { path = "../../../crates/libcontainer" } -nix = "0.27.1" +nix = "0.28.0" num_cpus = "1.16" oci-spec = { version = "0.6.4", features = ["runtime"] } once_cell = "1.19.0" diff --git a/tests/contest/contest/src/tests/seccomp_notify/seccomp_agent.rs b/tests/contest/contest/src/tests/seccomp_notify/seccomp_agent.rs index 5a2030c5..e70a77b8 100644 --- a/tests/contest/contest/src/tests/seccomp_notify/seccomp_agent.rs +++ b/tests/contest/contest/src/tests/seccomp_notify/seccomp_agent.rs @@ -5,7 +5,7 @@ use std::path::Path; use anyhow::{bail, Context, Result}; use libcontainer::container::ContainerProcessState; -use nix::sys::socket::{self, UnixAddr}; +use nix::sys::socket::{self, Backlog, UnixAddr}; use nix::unistd; const DEFAULT_BUFFER_SIZE: usize = 4096; @@ -30,7 +30,8 @@ pub fn recv_seccomp_listener(seccomp_listener: &Path) -> SeccompAgentResult { socket::bind(socket.as_raw_fd(), &addr).context("failed to bind to seccomp listener socket")?; // Force the backlog to be 1 so in the case of an error, only one connection // from clients will be waiting. - socket::listen(&socket.as_fd(), 1).context("failed to listen on seccomp listener")?; + socket::listen(&socket.as_fd(), Backlog::new(1)?) + .context("failed to listen on seccomp listener")?; let conn = match socket::accept(socket.as_raw_fd()) { Ok(conn) => conn, Err(e) => { diff --git a/tests/contest/runtimetest/Cargo.toml b/tests/contest/runtimetest/Cargo.toml index 311a2dc4..44c9b984 100644 --- a/tests/contest/runtimetest/Cargo.toml +++ b/tests/contest/runtimetest/Cargo.toml @@ -5,7 +5,7 @@ edition = "2021" [dependencies] oci-spec = { version = "0.6.4", features = ["runtime"] } -nix = "0.27.1" +nix = "0.28.0" anyhow = "1.0" libc = "0.2.155" # TODO (YJDoc2) upgrade to latest nc = "0.8.20" diff --git a/tests/contest/runtimetest/src/tests.rs b/tests/contest/runtimetest/src/tests.rs index 2861df1a..f2b9aa61 100644 --- a/tests/contest/runtimetest/src/tests.rs +++ b/tests/contest/runtimetest/src/tests.rs @@ -38,7 +38,7 @@ pub fn validate_readonly_paths(spec: &Spec) { // change manual matching of i32 to e.kind() and match statement for path in ro_paths { if let std::io::Result::Err(e) = test_read_access(path) { - let errno = Errno::from_i32(e.raw_os_error().unwrap()); + let errno = Errno::from_raw(e.raw_os_error().unwrap()); // In the integration tests we test for both existing and non-existing readonly paths // to be specified in the spec, so we allow ENOENT here if errno == Errno::ENOENT { @@ -54,7 +54,7 @@ pub fn validate_readonly_paths(spec: &Spec) { } if let std::io::Result::Err(e) = test_write_access(path) { - let errno = Errno::from_i32(e.raw_os_error().unwrap()); + let errno = Errno::from_raw(e.raw_os_error().unwrap()); // In the integration tests we test for both existing and non-existing readonly paths // being specified in the spec, so we allow ENOENT, and we expect EROFS as the paths // should be read-only