Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Implement thiserror for libcontainer - Part 1 #1876

Merged
merged 7 commits into from
May 4, 2023
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
1 change: 1 addition & 0 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 1 addition & 0 deletions crates/libcontainer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -44,6 +44,7 @@ syscalls = "0.6.10"
rust-criu = "0.4.0"
clone3 = "0.2.3"
regex = "1.7.3"
thiserror = "1.0.24"

[dev-dependencies]
oci-spec = { version = "^0.6.0", features = ["proptests", "runtime"] }
Expand Down
10 changes: 6 additions & 4 deletions crates/libcontainer/src/capabilities.rs
Original file line number Diff line number Diff line change
@@ -1,9 +1,8 @@
//! Handles Management of Capabilities
use crate::syscall::Syscall;
use crate::syscall::{Syscall, SyscallError};
use caps::Capability as CapsCapability;
use caps::*;

use anyhow::Result;
use oci_spec::runtime::{Capabilities, Capability as SpecCapability, LinuxCapabilities};

/// Converts a list of capability types to capabilities has set
Expand Down Expand Up @@ -124,14 +123,17 @@ impl CapabilityExt for SpecCapability {
/// reset capabilities of process calling this to effective capabilities
/// effective capability set is set of capabilities used by kernel to perform checks
/// see <https://man7.org/linux/man-pages/man7/capabilities.7.html> for more information
pub fn reset_effective<S: Syscall + ?Sized>(syscall: &S) -> Result<()> {
pub fn reset_effective<S: Syscall + ?Sized>(syscall: &S) -> Result<(), SyscallError> {
log::debug!("reset all caps");
syscall.set_capability(CapSet::Effective, &caps::all())?;
Ok(())
}

/// Drop any extra granted capabilities, and reset to defaults which are in oci specification
pub fn drop_privileges<S: Syscall + ?Sized>(cs: &LinuxCapabilities, syscall: &S) -> Result<()> {
pub fn drop_privileges<S: Syscall + ?Sized>(
cs: &LinuxCapabilities,
syscall: &S,
) -> Result<(), SyscallError> {
log::debug!("dropping bounding capabilities to {:?}", cs.bounding());
if let Some(bounding) = cs.bounding() {
syscall.set_capability(CapSet::Bounding, &to_set(bounding))?;
Expand Down
5 changes: 2 additions & 3 deletions crates/libcontainer/src/lib.rs
Original file line number Diff line number Diff line change
Expand Up @@ -8,11 +8,10 @@ pub mod notify_socket;
pub mod process;
pub mod rootfs;
pub mod rootless;
#[cfg(feature = "libseccomp")]
pub mod seccomp;
pub mod signal;
pub mod syscall;
pub mod tty;
pub mod utils;
pub mod workload;

#[cfg(feature = "libseccomp")]
pub mod seccomp;
65 changes: 50 additions & 15 deletions crates/libcontainer/src/namespaces.rs
Original file line number Diff line number Diff line change
Expand Up @@ -7,12 +7,29 @@
//! UTS (hostname and domain information, processes will think they're running on servers with different names),
//! Cgroup (Resource limits, execution priority etc.)

use crate::syscall::{syscall::create_syscall, Syscall};
use anyhow::{Context, Result};
use crate::syscall::{syscall::create_syscall, Syscall, SyscallError};
use nix::{fcntl, sched::CloneFlags, sys::stat, unistd};
use oci_spec::runtime::{LinuxNamespace, LinuxNamespaceType};
use std::collections;

type Result<T> = std::result::Result<T, NamespaceError>;

#[derive(Debug, thiserror::Error)]
pub enum NamespaceError {
#[error("failed to set namespace")]
ApplyNamespaceSyscallFailed {
namespace: Box<LinuxNamespace>,
#[source]
err: SyscallError,
},
#[error("failed to set namespace")]
ApplyNamespaceUnixSyscallFailed {
namespace: Box<LinuxNamespace>,
#[source]
err: nix::Error,
},
}

static ORDERED_NAMESPACES: &[CloneFlags] = &[
CloneFlags::CLONE_NEWUSER,
CloneFlags::CLONE_NEWPID,
Expand Down Expand Up @@ -65,25 +82,43 @@ impl Namespaces {
.filter_map(|c| self.namespace_map.get_key_value(c))
.collect();

for (ns_type, ns) in to_enter {
self.unshare_or_setns(ns)
.with_context(|| format!("failed to enter {ns_type:?} namespace: {ns:?}"))?;
for (_, ns) in to_enter {
self.unshare_or_setns(ns)?;
}
Ok(())
}

pub fn unshare_or_setns(&self, namespace: &LinuxNamespace) -> Result<()> {
log::debug!("unshare or setns: {:?}", namespace);
if namespace.path().is_none() {
self.command.unshare(get_clone_flag(namespace.typ()))?;
} else {
let ns_path = namespace.path().as_ref().unwrap();
let fd = fcntl::open(ns_path, fcntl::OFlag::empty(), stat::Mode::empty())
.with_context(|| format!("failed to open namespace fd: {ns_path:?}"))?;
self.command
.set_ns(fd, get_clone_flag(namespace.typ()))
.with_context(|| "failed to set namespace")?;
unistd::close(fd).with_context(|| "failed to close namespace fd")?;
match namespace.path() {
Some(path) => {
let fd = fcntl::open(path, fcntl::OFlag::empty(), stat::Mode::empty()).map_err(
|err| NamespaceError::ApplyNamespaceUnixSyscallFailed {
namespace: Box::new(namespace.to_owned()),
err,
},
)?;
self.command
.set_ns(fd, get_clone_flag(namespace.typ()))
.map_err(|err| NamespaceError::ApplyNamespaceSyscallFailed {
namespace: Box::new(namespace.to_owned()),
err,
})?;
unistd::close(fd).map_err(|err| {
NamespaceError::ApplyNamespaceUnixSyscallFailed {
namespace: Box::new(namespace.to_owned()),
err,
}
})?;
}
None => {
self.command
.unshare(get_clone_flag(namespace.typ()))
.map_err(|err| NamespaceError::ApplyNamespaceSyscallFailed {
namespace: Box::new(namespace.to_owned()),
err,
})?;
}
}

Ok(())
Expand Down
Loading