Skip to content

Commit

Permalink
add id mount
Browse files Browse the repository at this point in the history
Signed-off-by: lengrongfu <lenronfu@gmail.com>
  • Loading branch information
lengrongfu committed Jun 27, 2024
1 parent a757258 commit f157bb5
Show file tree
Hide file tree
Showing 15 changed files with 430 additions and 89 deletions.
3 changes: 1 addition & 2 deletions Cargo.lock

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

6 changes: 4 additions & 2 deletions crates/libcgroups/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,8 @@ cgroupsv2_devices = ["rbpf", "libbpf-sys", "errno", "libc", "nix/dir"]
[dependencies]
nix = { version = "0.28.0", features = ["signal", "user", "fs"] }
procfs = "0.16.0"
oci-spec = { version = "~0.6.4", features = ["runtime"] }
#oci-spec = { version = "~0.6.4", features = ["runtime"] }
oci-spec={git="https://github.com/lengrongfu/oci-spec-rs",branch = "feat/add_idmapped_mount",features = ["runtime"] }
fixedbitset = "0.5.7"
serde = { version = "1.0", features = ["derive"] }
rbpf = { version = "0.2.0", optional = true }
Expand All @@ -34,7 +35,8 @@ tracing = { version = "0.1.40", features = ["attributes"] }

[dev-dependencies]
anyhow = "1.0"
oci-spec = { version = "~0.6.4", features = ["proptests", "runtime"] }
#oci-spec = { version = "~0.6.4", features = ["proptests", "runtime"] }
oci-spec={git="https://github.com/lengrongfu/oci-spec-rs",branch = "feat/add_idmapped_mount",features = ["proptests", "runtime"]}
quickcheck = "1"
mockall = { version = "0.12.1", features = [] }
clap = "4.1.6"
Expand Down
6 changes: 4 additions & 2 deletions crates/libcontainer/Cargo.toml
Original file line number Diff line number Diff line change
Expand Up @@ -39,7 +39,8 @@ nix = { version = "0.28.0", features = [
"term",
"hostname",
] }
oci-spec = { version = "~0.6.4", features = ["runtime"] }
#oci-spec = { version = "~0.6.4", features = ["runtime"] }
oci-spec={git="https://github.com/lengrongfu/oci-spec-rs",branch = "feat/add_idmapped_mount",features = ["runtime"] }
once_cell = "1.19.0"
procfs = "0.16.0"
prctl = "1.0.0"
Expand All @@ -56,7 +57,8 @@ safe-path = "0.1.0"
nc = "0.8.20"

[dev-dependencies]
oci-spec = { version = "~0.6.4", features = ["proptests", "runtime"] }
#oci-spec = { version = "~0.6.4", features = ["proptests", "runtime"] }
oci-spec={git="https://github.com/lengrongfu/oci-spec-rs",branch = "feat/add_idmapped_mount",features = ["proptests", "runtime"]}
quickcheck = "1"
serial_test = "3.1.1"
tempfile = "3"
Expand Down
47 changes: 47 additions & 0 deletions crates/libcontainer/src/process/channel.rs
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,7 @@ use nix::unistd::Pid;

use crate::channel::{channel, Receiver, Sender};
use crate::process::message::Message;
use crate::rootfs::mount::{IdMountParam, IdMountSource};

#[derive(Debug, thiserror::Error)]
pub enum ChannelError {
Expand Down Expand Up @@ -57,6 +58,13 @@ impl MainSender {
Ok(())
}

// process mount place
pub fn process_mount_place(&mut self, m: IdMountParam) -> Result<(), ChannelError> {
tracing::debug!("send process mapping place request");
self.sender.send(Message::SendConfigureMount(m))?;
Ok(())
}

pub fn seccomp_notify_request(&mut self, fd: RawFd) -> Result<(), ChannelError> {
self.sender
.send_fds(Message::SeccompNotify, &[fd.as_raw_fd()])?;
Expand Down Expand Up @@ -186,6 +194,23 @@ impl MainReceiver {
}
}

pub fn wait_process_mount_place(&mut self) -> Result<IdMountParam,ChannelError> {
let msg = self
.receiver
.recv()
.map_err(|err| ChannelError::ReceiveError {
msg: "waiting for process mount place".to_string(),
source: err,
})?;
match msg {
Message::SendConfigureMount(m) => Ok(m),
msg => Err(ChannelError::UnexpectedMessage {
expected: Message::SendConfigureMount(Default::default()),
received: msg,
})
}
}

pub fn close(&self) -> Result<(), ChannelError> {
self.receiver.close()?;

Expand Down Expand Up @@ -270,6 +295,12 @@ impl InitSender {
Ok(())
}

pub fn send_mount_source(&mut self, ms: &IdMountSource) -> Result<(),ChannelError> {
tracing::debug!("send mount source request");
self.sender.send(Message::ReceiveMountFd(ms.clone()))?;
Ok(())
}

pub fn close(&self) -> Result<(), ChannelError> {
self.sender.close()?;

Expand Down Expand Up @@ -301,6 +332,22 @@ impl InitReceiver {
}
}

pub fn wait_for_mount_source(&mut self) -> Result<IdMountSource,ChannelError> {
let msg = self.receiver.recv().map_err(|err| ChannelError::ReceiveError {
msg: "waiting for get mount source".to_string(),
source: err,
})?;
match msg {
Message::ReceiveMountFd(ms) => Ok(ms),
msg => Err(
ChannelError::UnexpectedMessage {
expected: Message::ReceiveMountFd(IdMountSource { file: 0 }),
received: msg,
}
)
}
}

pub fn close(&self) -> Result<(), ChannelError> {
self.receiver.close()?;

Expand Down
7 changes: 7 additions & 0 deletions crates/libcontainer/src/process/container_init_process.rs
Original file line number Diff line number Diff line change
Expand Up @@ -323,13 +323,20 @@ pub fn container_init_process(

let in_user_ns = utils::is_in_new_userns().map_err(InitProcessError::Io)?;
let bind_service = namespaces.get(LinuxNamespaceType::User)?.is_some() || in_user_ns;
let mut ns_path: Option<PathBuf> = None;
if let Some(user_namespace) = namespaces.get(LinuxNamespaceType::User)? {
ns_path = Some(user_namespace.path().clone().unwrap());
}
let rootfs = RootFS::new();
rootfs
.prepare_rootfs(
spec,
rootfs_path,
bind_service,
namespaces.get(LinuxNamespaceType::Cgroup)?.is_some(),
ns_path,
main_sender,
init_receiver,
)
.map_err(|err| {
tracing::error!(?err, "failed to prepare rootfs");
Expand Down
43 changes: 42 additions & 1 deletion crates/libcontainer/src/process/container_main_process.rs
Original file line number Diff line number Diff line change
@@ -1,11 +1,14 @@
use std::mem;
use std::fs::File;
use std::os::fd::{AsRawFd, RawFd};
use nix::sys::wait::{waitpid, WaitStatus};
use nix::unistd::Pid;

use crate::process::args::ContainerArgs;
use crate::process::fork::{self, CloneCb};
use crate::process::intel_rdt::setup_intel_rdt;
use crate::process::{channel, container_intermediate_process};
use crate::syscall::SyscallError;
use crate::syscall::{linux, SyscallError};
use crate::user_ns::UserNamespaceConfig;

#[derive(Debug, thiserror::Error)]
Expand Down Expand Up @@ -115,6 +118,44 @@ pub fn container_main_process(container_args: &ContainerArgs) -> Result<(Pid, bo
// The intermediate process will send the init pid once it forks the init
// process. The intermediate process should exit after this point.
let init_pid = main_receiver.wait_for_intermediate_ready()?;

loop {
let id_map = main_receiver.wait_process_mount_place().unwrap();
if id_map.end {
break;
}
let mut flags = libc::OPEN_TREE_CLONE | libc::OPEN_TREE_CLOEXEC;
let id_map_flags = id_map.flags;
if id_map_flags&libc::MS_REC == libc::MS_REC {
flags |= libc::AT_RECURSIVE as std::os::raw::c_uint;
}
let mount_file = unsafe {
libc::syscall(libc::SYS_open_tree,libc::AT_FDCWD,id_map.source,flags)
};
let mut userns_file: RawFd = -1;
if id_map.user_ns_path != "" {
let file = File::open(id_map.user_ns_path).unwrap();
userns_file = file.as_raw_fd();
} else {
// TODO we need use uid and git go get fd
}

let mat = &linux::MountAttr{
attr_set: linux::MOUNT_ATTR_IDMAP,
attr_clr: 0,
propagation: 0,
userns_fd: userns_file as u64,
};
let mut set_attr_flags = libc::AT_EMPTY_PATH;
if id_map.recursive {
set_attr_flags |= libc::AT_RECURSIVE;
}
syscall.mount_setattr(mount_file as i32, "".as_ref(), set_attr_flags as u32, mat,mem::size_of::<linux::MountAttr>(),).map_err(|err| {
tracing::error!(?err, "failed to mount_setattr");
ProcessError::SyscallOther(err)
}).unwrap();
}

let mut need_to_clean_up_intel_rdt_subdirectory = false;

if let Some(linux) = container_args.spec.linux() {
Expand Down
5 changes: 5 additions & 0 deletions crates/libcontainer/src/process/message.rs
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
use core::fmt;

use serde::{Deserialize, Serialize};
use crate::rootfs::mount::{IdMountParam, IdMountSource};

/// Used as a wrapper for messages to be sent between child and parent processes
#[derive(Debug, Serialize, Deserialize, Clone)]
Expand All @@ -12,6 +13,8 @@ pub enum Message {
SeccompNotify,
SeccompNotifyDone,
ExecFailed(String),
SendConfigureMount(IdMountParam),
ReceiveMountFd(IdMountSource),
}

impl fmt::Display for Message {
Expand All @@ -24,6 +27,8 @@ impl fmt::Display for Message {
Message::SeccompNotify => write!(f, "SeccompNotify"),
Message::SeccompNotifyDone => write!(f, "SeccompNotifyDone"),
Message::ExecFailed(s) => write!(f, "ExecFailed({})", s),
Message::SendConfigureMount(_) => write!(f,"SendConfigureMount"),
Message::ReceiveMountFd(_) => write!(f,"ReceiveMountFd"),
}
}
}
Loading

0 comments on commit f157bb5

Please sign in to comment.