rustjail: replace protocol spec with oci spec

transform the rpc protocol spec to
oci spec.

Signed-off-by: fupan.lfp <fupan.lfp@antfin.com>
This commit is contained in:
fupan.lfp 2020-03-10 09:55:16 +08:00
parent 8280208443
commit 7df8edef1b
11 changed files with 369 additions and 381 deletions

View File

@ -10,7 +10,7 @@ use lazy_static;
use crate::errors::*;
use caps::{self, CapSet, Capability, CapsHashSet};
use protocols::oci::LinuxCapabilities;
use oci::LinuxCapabilities;
use slog::Logger;
use std::collections::HashMap;
@ -103,30 +103,30 @@ pub fn drop_priviledges(logger: &Logger, caps: &LinuxCapabilities) -> Result<()>
let all = caps::all();
for c in all.difference(&to_capshashset(&logger, caps.Bounding.as_ref())) {
for c in all.difference(&to_capshashset(&logger, caps.bounding.as_ref())) {
caps::drop(None, CapSet::Bounding, *c)?;
}
caps::set(
None,
CapSet::Effective,
to_capshashset(&logger, caps.Effective.as_ref()),
to_capshashset(&logger, caps.effective.as_ref()),
)?;
caps::set(
None,
CapSet::Permitted,
to_capshashset(&logger, caps.Permitted.as_ref()),
to_capshashset(&logger, caps.permitted.as_ref()),
)?;
caps::set(
None,
CapSet::Inheritable,
to_capshashset(&logger, caps.Inheritable.as_ref()),
to_capshashset(&logger, caps.inheritable.as_ref()),
)?;
if let Err(_) = caps::set(
None,
CapSet::Ambient,
to_capshashset(&logger, caps.Ambient.as_ref()),
to_capshashset(&logger, caps.ambient.as_ref()),
) {
warn!(logger, "failed to set ambient capability");
}

View File

@ -10,12 +10,12 @@ use crate::errors::*;
use lazy_static;
use libc::{self, pid_t};
use nix::errno::Errno;
use oci::{LinuxDeviceCgroup, LinuxResources, LinuxThrottleDevice, LinuxWeightDevice};
use protobuf::{CachedSize, RepeatedField, SingularPtrField, UnknownFields};
use protocols::agent::{
BlkioStats, BlkioStatsEntry, CgroupStats, CpuStats, CpuUsage, HugetlbStats, MemoryData,
MemoryStats, PidsStats, ThrottlingData,
};
use protocols::oci::{LinuxDeviceCgroup, LinuxResources, LinuxThrottleDevice, LinuxWeightDevice};
use regex::Regex;
use std::collections::HashMap;
use std::fs;
@ -57,63 +57,51 @@ lazy_static! {
pub static ref DEFAULT_ALLOWED_DEVICES: Vec<LinuxDeviceCgroup> = {
let mut v = Vec::new();
v.push(LinuxDeviceCgroup {
Allow: true,
Type: "c".to_string(),
Major: WILDCARD,
Minor: WILDCARD,
Access: "m".to_string(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
allow: true,
r#type: "c".to_string(),
major: Some(WILDCARD),
minor: Some(WILDCARD),
access: "m".to_string(),
});
v.push(LinuxDeviceCgroup {
Allow: true,
Type: "b".to_string(),
Major: WILDCARD,
Minor: WILDCARD,
Access: "m".to_string(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
allow: true,
r#type: "b".to_string(),
major: Some(WILDCARD),
minor: Some(WILDCARD),
access: "m".to_string(),
});
v.push(LinuxDeviceCgroup {
Allow: true,
Type: "c".to_string(),
Major: 5,
Minor: 1,
Access: "rwm".to_string(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
allow: true,
r#type: "c".to_string(),
major: Some(5),
minor: Some(1),
access: "rwm".to_string(),
});
v.push(LinuxDeviceCgroup {
Allow: true,
Type: "c".to_string(),
Major: 136,
Minor: WILDCARD,
Access: "rwm".to_string(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
allow: true,
r#type: "c".to_string(),
major: Some(136),
minor: Some(WILDCARD),
access: "rwm".to_string(),
});
v.push(LinuxDeviceCgroup {
Allow: true,
Type: "c".to_string(),
Major: 5,
Minor: 2,
Access: "rwm".to_string(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
allow: true,
r#type: "c".to_string(),
major: Some(5),
minor: Some(2),
access: "rwm".to_string(),
});
v.push(LinuxDeviceCgroup {
Allow: true,
Type: "c".to_string(),
Major: 10,
Minor: 200,
Access: "rwm".to_string(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
allow: true,
r#type: "c".to_string(),
major: Some(10),
minor: Some(200),
access: "rwm".to_string(),
});
v
@ -419,10 +407,10 @@ impl Subsystem for CpuSet {
let mut cpus: &str = "";
let mut mems: &str = "";
if r.CPU.is_some() {
let cpu = r.CPU.as_ref().unwrap();
cpus = cpu.Cpus.as_str();
mems = cpu.Mems.as_str();
if r.cpu.is_some() {
let cpu = r.cpu.as_ref().unwrap();
cpus = cpu.cpus.as_str();
mems = cpu.mems.as_str();
}
// For updatecontainer, just set the new value
@ -466,17 +454,25 @@ impl Subsystem for Cpu {
}
fn set(&self, dir: &str, r: &LinuxResources, _update: bool) -> Result<()> {
if r.CPU.is_none() {
if r.cpu.is_none() {
return Ok(());
}
let cpu = r.CPU.as_ref().unwrap();
let cpu = r.cpu.as_ref().unwrap();
try_write_nonzero(dir, CPU_RT_PERIOD_US, cpu.RealtimePeriod as i128)?;
try_write_nonzero(dir, CPU_RT_RUNTIME_US, cpu.RealtimeRuntime as i128)?;
write_nonzero(dir, CPU_SHARES, cpu.Shares as i128)?;
write_nonzero(dir, CPU_CFS_QUOTA_US, cpu.Quota as i128)?;
write_nonzero(dir, CPU_CFS_PERIOD_US, cpu.Period as i128)?;
try_write_nonzero(
dir,
CPU_RT_PERIOD_US,
cpu.realtime_period.unwrap_or(0) as i128,
)?;
try_write_nonzero(
dir,
CPU_RT_RUNTIME_US,
cpu.realtime_runtime.unwrap_or(0) as i128,
)?;
write_nonzero(dir, CPU_SHARES, cpu.shares.unwrap_or(0) as i128)?;
write_nonzero(dir, CPU_CFS_QUOTA_US, cpu.quota.unwrap_or(0) as i128)?;
write_nonzero(dir, CPU_CFS_PERIOD_US, cpu.period.unwrap_or(0) as i128)?;
Ok(())
}
@ -599,24 +595,24 @@ impl CpuAcct {
}
fn write_device(d: &LinuxDeviceCgroup, dir: &str) -> Result<()> {
let file = if d.Allow { DEVICES_ALLOW } else { DEVICES_DENY };
let file = if d.allow { DEVICES_ALLOW } else { DEVICES_DENY };
let major = if d.Major == WILDCARD {
let major = if d.major.unwrap_or(0) == WILDCARD {
"*".to_string()
} else {
d.Major.to_string()
d.major.unwrap_or(0).to_string()
};
let minor = if d.Minor == WILDCARD {
let minor = if d.minor.unwrap_or(0) == WILDCARD {
"*".to_string()
} else {
d.Minor.to_string()
d.minor.unwrap_or(0).to_string()
};
let t = if d.Type.is_empty() {
let t = if d.r#type.is_empty() {
"a"
} else {
d.Type.as_str()
d.r#type.as_str()
};
let v = format!(
@ -624,7 +620,7 @@ fn write_device(d: &LinuxDeviceCgroup, dir: &str) -> Result<()> {
t,
major.as_str(),
minor.as_str(),
d.Access.as_str()
d.access.as_str()
);
info!(sl!(), "{}", v.as_str());
@ -638,19 +634,17 @@ impl Subsystem for Devices {
}
fn set(&self, dir: &str, r: &LinuxResources, _update: bool) -> Result<()> {
for d in r.Devices.iter() {
for d in r.devices.iter() {
write_device(d, dir)?;
}
for d in DEFAULT_DEVICES.iter() {
let td = LinuxDeviceCgroup {
Allow: true,
Type: d.Type.clone(),
Major: d.Major,
Minor: d.Minor,
Access: "rwm".to_string(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
allow: true,
r#type: d.r#type.clone(),
major: Some(d.major),
minor: Some(d.minor),
access: "rwm".to_string(),
};
write_device(&td, dir)?;
@ -691,30 +685,34 @@ impl Subsystem for Memory {
}
fn set(&self, dir: &str, r: &LinuxResources, update: bool) -> Result<()> {
if r.Memory.is_none() {
if r.memory.is_none() {
return Ok(());
}
let memory = r.Memory.as_ref().unwrap();
let memory = r.memory.as_ref().unwrap();
// initialize kmem limits for accounting
if !update {
try_write(dir, KMEM_LIMIT, 1)?;
try_write(dir, KMEM_LIMIT, -1)?;
}
write_nonzero(dir, MEMORY_LIMIT, memory.Limit as i128)?;
write_nonzero(dir, MEMORY_SOFT_LIMIT, memory.Reservation as i128)?;
write_nonzero(dir, MEMORY_LIMIT, memory.limit.unwrap_or(0) as i128)?;
write_nonzero(
dir,
MEMORY_SOFT_LIMIT,
memory.reservation.unwrap_or(0) as i128,
)?;
try_write_nonzero(dir, MEMSW_LIMIT, memory.Swap as i128)?;
try_write_nonzero(dir, KMEM_LIMIT, memory.Kernel as i128)?;
try_write_nonzero(dir, MEMSW_LIMIT, memory.swap.unwrap_or(0) as i128)?;
try_write_nonzero(dir, KMEM_LIMIT, memory.kernel.unwrap_or(0) as i128)?;
write_nonzero(dir, KMEM_TCP_LIMIT, memory.KernelTCP as i128)?;
write_nonzero(dir, KMEM_TCP_LIMIT, memory.kernel_tcp.unwrap_or(0) as i128)?;
if memory.Swappiness <= 100 {
write_file(dir, SWAPPINESS, memory.Swappiness)?;
if memory.swapiness.unwrap_or(0) <= 100 {
write_file(dir, SWAPPINESS, memory.swapiness.unwrap_or(0))?;
}
if memory.DisableOOMKiller {
if memory.disable_oom_killer.unwrap_or(false) {
write_file(dir, OOM_CONTROL, 1)?;
}
@ -808,14 +806,14 @@ impl Subsystem for Pids {
}
fn set(&self, dir: &str, r: &LinuxResources, _update: bool) -> Result<()> {
if r.Pids.is_none() {
if r.pids.is_none() {
return Ok(());
}
let pids = r.Pids.as_ref().unwrap();
let pids = r.pids.as_ref().unwrap();
let v = if pids.Limit > 0 {
pids.Limit.to_string()
let v = if pids.limit > 0 {
pids.limit.to_string()
} else {
"max".to_string()
};
@ -857,14 +855,14 @@ impl Pids {
#[inline]
fn weight(d: &LinuxWeightDevice) -> (String, String) {
(
format!("{}:{} {}", d.Major, d.Minor, d.Weight),
format!("{}:{} {}", d.Major, d.Minor, d.LeafWeight),
format!("{:?} {:?}", d.blk, d.weight),
format!("{:?} {:?}", d.blk, d.leaf_weight),
)
}
#[inline]
fn rate(d: &LinuxThrottleDevice) -> String {
format!("{}:{} {}", d.Major, d.Minor, d.Rate)
format!("{:?} {}", d.blk, d.rate)
}
fn write_blkio_device<T: ToString>(dir: &str, file: &str, v: T) -> Result<()> {
@ -895,34 +893,38 @@ impl Subsystem for Blkio {
}
fn set(&self, dir: &str, r: &LinuxResources, _update: bool) -> Result<()> {
if r.BlockIO.is_none() {
if r.block_io.is_none() {
return Ok(());
}
let blkio = r.BlockIO.as_ref().unwrap();
let blkio = r.block_io.as_ref().unwrap();
write_nonzero(dir, BLKIO_WEIGHT, blkio.Weight as i128)?;
write_nonzero(dir, BLKIO_LEAF_WEIGHT, blkio.LeafWeight as i128)?;
write_nonzero(dir, BLKIO_WEIGHT, blkio.weight.unwrap_or(0) as i128)?;
write_nonzero(
dir,
BLKIO_LEAF_WEIGHT,
blkio.leaf_weight.unwrap_or(0) as i128,
)?;
for d in blkio.WeightDevice.iter() {
for d in blkio.weight_device.iter() {
let (w, lw) = weight(d);
write_blkio_device(dir, BLKIO_WEIGHT_DEVICE, w)?;
write_blkio_device(dir, BLKIO_LEAF_WEIGHT_DEVICE, lw)?;
}
for d in blkio.ThrottleReadBpsDevice.iter() {
for d in blkio.throttle_read_bps_device.iter() {
write_blkio_device(dir, BLKIO_READ_BPS_DEVICE, rate(d))?;
}
for d in blkio.ThrottleWriteBpsDevice.iter() {
for d in blkio.throttle_write_bps_device.iter() {
write_blkio_device(dir, BLKIO_WRITE_BPS_DEVICE, rate(d))?;
}
for d in blkio.ThrottleReadIOPSDevice.iter() {
for d in blkio.throttle_read_iops_device.iter() {
write_blkio_device(dir, BLKIO_READ_IOPS_DEVICE, rate(d))?;
}
for d in blkio.ThrottleWriteIOPSDevice.iter() {
for d in blkio.throttle_write_iops_device.iter() {
write_blkio_device(dir, BLKIO_WRITE_IOPS_DEVICE, rate(d))?;
}
@ -1010,9 +1012,9 @@ impl Subsystem for HugeTLB {
}
fn set(&self, dir: &str, r: &LinuxResources, _update: bool) -> Result<()> {
for l in r.HugepageLimits.iter() {
let file = format!("hugetlb.{}.limit_in_bytes", l.Pagesize);
write_file(dir, file.as_str(), l.Limit)?;
for l in r.hugepage_limits.iter() {
let file = format!("hugetlb.{}.limit_in_bytes", l.page_size);
write_file(dir, file.as_str(), l.limit)?;
}
Ok(())
}
@ -1052,13 +1054,13 @@ impl Subsystem for NetCls {
}
fn set(&self, dir: &str, r: &LinuxResources, _update: bool) -> Result<()> {
if r.Network.is_none() {
if r.network.is_none() {
return Ok(());
}
let network = r.Network.as_ref().unwrap();
let network = r.network.as_ref().unwrap();
write_nonzero(dir, NET_CLS_CLASSID, network.ClassID as i128)?;
write_nonzero(dir, NET_CLS_CLASSID, network.class_id.unwrap_or(0) as i128)?;
Ok(())
}
@ -1070,14 +1072,14 @@ impl Subsystem for NetPrio {
}
fn set(&self, dir: &str, r: &LinuxResources, _update: bool) -> Result<()> {
if r.Network.is_none() {
if r.network.is_none() {
return Ok(());
}
let network = r.Network.as_ref().unwrap();
let network = r.network.as_ref().unwrap();
for p in network.Priorities.iter() {
let prio = format!("{} {}", p.Name, p.Priority);
for p in network.priorities.iter() {
let prio = format!("{} {}", p.name, p.priority);
try_write_file(dir, NET_PRIO_IFPRIOMAP, prio)?;
}

View File

@ -5,8 +5,8 @@
use crate::errors::*;
// use crate::configs::{FreezerState, Config};
use oci::LinuxResources;
use protocols::agent::CgroupStats;
use protocols::oci::LinuxResources;
use std::collections::HashMap;
pub mod fs;

View File

@ -4,7 +4,7 @@
//
use lazy_static;
use protocols::oci::{Hook, Linux, LinuxNamespace, LinuxResources, POSIXRlimit, Spec};
use oci::{Hook, Linux, LinuxNamespace, LinuxResources, POSIXRlimit, Spec};
use serde_json;
use std::ffi::{CStr, CString};
use std::fs;
@ -14,7 +14,7 @@ use std::path::{Path, PathBuf};
use std::time::SystemTime;
// use crate::sync::Cond;
use libc::pid_t;
use protocols::oci::{LinuxDevice, LinuxIDMapping};
use oci::{LinuxDevice, LinuxIDMapping};
use std::clone::Clone;
use std::fmt::Display;
use std::process::Command;
@ -99,70 +99,58 @@ lazy_static! {
pub static ref DEFAULT_DEVICES: Vec<LinuxDevice> = {
let mut v = Vec::new();
v.push(LinuxDevice {
Path: "/dev/null".to_string(),
Type: "c".to_string(),
Major: 1,
Minor: 3,
FileMode: 0o066,
UID: 0xffffffff,
GID: 0xffffffff,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
path: "/dev/null".to_string(),
r#type: "c".to_string(),
major: 1,
minor: 3,
file_mode: Some(0o066),
uid: Some(0xffffffff),
gid: Some(0xffffffff),
});
v.push(LinuxDevice {
Path: "/dev/zero".to_string(),
Type: "c".to_string(),
Major: 1,
Minor: 5,
FileMode: 0o066,
UID: 0xffffffff,
GID: 0xffffffff,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
path: "/dev/zero".to_string(),
r#type: "c".to_string(),
major: 1,
minor: 5,
file_mode: Some(0o066),
uid: Some(0xffffffff),
gid: Some(0xffffffff),
});
v.push(LinuxDevice {
Path: "/dev/full".to_string(),
Type: String::from("c"),
Major: 1,
Minor: 7,
FileMode: 0o066,
UID: 0xffffffff,
GID: 0xffffffff,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
path: "/dev/full".to_string(),
r#type: String::from("c"),
major: 1,
minor: 7,
file_mode: Some(0o066),
uid: Some(0xffffffff),
gid: Some(0xffffffff),
});
v.push(LinuxDevice {
Path: "/dev/tty".to_string(),
Type: "c".to_string(),
Major: 5,
Minor: 0,
FileMode: 0o066,
UID: 0xffffffff,
GID: 0xffffffff,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
path: "/dev/tty".to_string(),
r#type: "c".to_string(),
major: 5,
minor: 0,
file_mode: Some(0o066),
uid: Some(0xffffffff),
gid: Some(0xffffffff),
});
v.push(LinuxDevice {
Path: "/dev/urandom".to_string(),
Type: "c".to_string(),
Major: 1,
Minor: 9,
FileMode: 0o066,
UID: 0xffffffff,
GID: 0xffffffff,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
path: "/dev/urandom".to_string(),
r#type: "c".to_string(),
major: 1,
minor: 9,
file_mode: Some(0o066),
uid: Some(0xffffffff),
gid: Some(0xffffffff),
});
v.push(LinuxDevice {
Path: "/dev/random".to_string(),
Type: "c".to_string(),
Major: 1,
Minor: 8,
FileMode: 0o066,
UID: 0xffffffff,
GID: 0xffffffff,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
path: "/dev/random".to_string(),
r#type: "c".to_string(),
major: 1,
minor: 8,
file_mode: Some(0o066),
uid: Some(0xffffffff),
gid: Some(0xffffffff),
});
v
};
@ -274,16 +262,16 @@ impl BaseContainer for LinuxContainer {
0
};
let root = oci.Root.as_ref().unwrap().Path.as_str();
let root = oci.root.as_ref().unwrap().path.as_str();
let path = fs::canonicalize(root)?;
let bundle = path.parent().unwrap().to_str().unwrap().to_string();
Ok(OCIState {
version: oci.Version.clone(),
version: oci.version.clone(),
id: self.id(),
status,
pid,
bundle,
annotations: oci.Annotations.clone(),
annotations: oci.annotations.clone(),
})
}
@ -326,10 +314,10 @@ impl BaseContainer for LinuxContainer {
.spec
.as_mut()
.unwrap()
.Linux
.linux
.as_mut()
.unwrap()
.Resources = SingularPtrField::some(r);
.resources = Some(r);
Ok(())
}
@ -363,11 +351,11 @@ impl BaseContainer for LinuxContainer {
}
let spec = self.config.spec.as_ref().unwrap();
if spec.Linux.is_none() {
if spec.linux.is_none() {
return Err(ErrorKind::ErrorCode("no linux config".to_string()).into());
}
let linux = spec.Linux.as_ref().unwrap();
let linux = spec.linux.as_ref().unwrap();
// get namespace vector to join/new
let nses = get_namespaces(&linux, p.init, self.init_process_pid)?;
info!(self.logger, "got namespaces {:?}!\n", nses);
@ -376,23 +364,23 @@ impl BaseContainer for LinuxContainer {
let mut pidns = false;
let mut userns = false;
for ns in &nses {
let s = NAMESPACES.get(&ns.Type.as_str());
let s = NAMESPACES.get(&ns.r#type.as_str());
if s.is_none() {
return Err(ErrorKind::ErrorCode("invalid ns type".to_string()).into());
}
let s = s.unwrap();
if ns.Path.is_empty() {
if ns.path.is_empty() {
to_new.set(*s, true);
} else {
let fd = match fcntl::open(ns.Path.as_str(), OFlag::empty(), Mode::empty()) {
let fd = match fcntl::open(ns.path.as_str(), OFlag::empty(), Mode::empty()) {
Ok(v) => v,
Err(e) => {
info!(
self.logger,
"cannot open type: {} path: {}",
ns.Type.clone(),
ns.Path.clone()
ns.r#type.clone(),
ns.path.clone()
);
info!(self.logger, "error is : {}", e.as_errno().unwrap().desc());
return Err(e.into());
@ -535,29 +523,27 @@ impl BaseContainer for LinuxContainer {
mount::finish_rootfs(spec)?;
}
if !p.oci.Cwd.is_empty() {
debug!(self.logger, "cwd: {}", p.oci.Cwd.as_str());
unistd::chdir(p.oci.Cwd.as_str())?;
if !p.oci.cwd.is_empty() {
debug!(self.logger, "cwd: {}", p.oci.cwd.as_str());
unistd::chdir(p.oci.cwd.as_str())?;
}
// setup uid/gid
info!(self.logger, "{:?}", p.oci.clone());
info!(self.logger, "{:?}", &p.oci);
if p.oci.User.is_some() {
let guser = p.oci.User.as_ref().unwrap();
let guser = &p.oci.user;
let uid = Uid::from_raw(guser.UID);
let gid = Gid::from_raw(guser.GID);
let uid = Uid::from_raw(guser.uid);
let gid = Gid::from_raw(guser.gid);
setid(uid, gid)?;
setid(uid, gid)?;
if !guser.AdditionalGids.is_empty() {
setgroups(guser.AdditionalGids.as_slice())?;
}
if guser.additional_gids.len() > 0 {
setgroups(guser.additional_gids.as_slice())?;
}
// NoNewPeiviledges, Drop capabilities
if p.oci.NoNewPrivileges {
if p.oci.no_new_privileges {
if let Err(_) = prctl::set_no_new_privileges(true) {
return Err(
ErrorKind::ErrorCode("cannot set no new privileges".to_string()).into(),
@ -565,8 +551,8 @@ impl BaseContainer for LinuxContainer {
}
}
if p.oci.Capabilities.is_some() {
let c = p.oci.Capabilities.as_ref().unwrap();
if p.oci.capabilities.is_some() {
let c = p.oci.capabilities.as_ref().unwrap();
info!(self.logger, "drop capabilities!");
capabilities::drop_priviledges(&self.logger, c)?;
}
@ -597,8 +583,8 @@ impl BaseContainer for LinuxContainer {
}
// exec process
let args = p.oci.Args.to_vec();
let env = p.oci.Env.to_vec();
let args = p.oci.args.to_vec();
let env = p.oci.env.to_vec();
do_exec(&self.logger, &args[0], &args, &env)?;
Err(ErrorKind::ErrorCode("fail to create container".to_string()).into())
@ -624,10 +610,10 @@ impl BaseContainer for LinuxContainer {
signal::kill(Pid::from_raw(*pid), Some(Signal::SIGKILL))?;
}
if spec.Hooks.is_some() {
if spec.hooks.is_some() {
info!(self.logger, "poststop");
let hooks = spec.Hooks.as_ref().unwrap();
for h in hooks.Poststop.iter() {
let hooks = spec.hooks.as_ref().unwrap();
for h in hooks.poststop.iter() {
execute_hook(&self.logger, h, &st)?;
}
}
@ -724,12 +710,10 @@ fn do_exec(logger: &Logger, path: &str, args: &[String], env: &[String]) -> Resu
fn get_namespaces(linux: &Linux, init: bool, init_pid: pid_t) -> Result<Vec<LinuxNamespace>> {
let mut ns: Vec<LinuxNamespace> = Vec::new();
if init {
for i in &linux.Namespaces {
for i in &linux.namespaces {
ns.push(LinuxNamespace {
Type: i.Type.clone(),
Path: i.Path.clone(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
r#type: i.r#type.clone(),
path: i.path.clone(),
});
}
} else {
@ -748,10 +732,8 @@ fn get_namespaces(linux: &Linux, init: bool, init_pid: pid_t) -> Result<Vec<Linu
// since it shouldn't be join.
if !ns_path_buf.eq(&init_ns_path_buf) {
ns.push(LinuxNamespace {
Type: i.to_string(),
Path: ns_path,
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
r#type: i.to_string(),
path: ns_path,
});
}
}
@ -829,8 +811,8 @@ fn join_namespaces(
let (pfd, cfd) = unistd::pipe2(OFlag::O_CLOEXEC).chain_err(|| "failed to create pipe")?;
let (crfd, pwfd) = unistd::pipe2(OFlag::O_CLOEXEC)?;
let linux = spec.Linux.as_ref().unwrap();
let res = linux.Resources.as_ref();
let linux = spec.linux.as_ref().unwrap();
let res = linux.resources.as_ref();
match unistd::fork()? {
ForkResult::Parent { child } => {
@ -846,12 +828,12 @@ fn join_namespaces(
write_mappings(
&logger,
&format!("/proc/{}/uid_map", child.as_raw()),
&linux.UIDMappings,
&linux.uid_mappings,
)?;
write_mappings(
&logger,
&format!("/proc/{}/gid_map", child.as_raw()),
&linux.GIDMappings,
&linux.gid_mappings,
)?;
}
@ -908,10 +890,10 @@ fn join_namespaces(
let _ = read_sync(pfd)?;
// run prestart hook
if spec.Hooks.is_some() {
if spec.hooks.is_some() {
info!(logger, "prestart");
let hooks = spec.Hooks.as_ref().unwrap();
for h in hooks.Prestart.iter() {
let hooks = spec.hooks.as_ref().unwrap();
for h in hooks.prestart.iter() {
execute_hook(&logger, h, st)?;
}
}
@ -922,10 +904,10 @@ fn join_namespaces(
// wait to run poststart hook
let _ = read_sync(pfd)?;
//run poststart hook
if spec.Hooks.is_some() {
if spec.hooks.is_some() {
info!(logger, "poststart");
let hooks = spec.Hooks.as_ref().unwrap();
for h in hooks.Poststart.iter() {
let hooks = spec.hooks.as_ref().unwrap();
for h in hooks.poststart.iter() {
execute_hook(&logger, h, st)?;
}
}
@ -941,21 +923,21 @@ fn join_namespaces(
unistd::close(pwfd)?;
// set oom_score_adj
let p = if spec.Process.is_some() {
spec.Process.as_ref().unwrap()
let p = if spec.process.is_some() {
spec.process.as_ref().unwrap()
} else {
return Err(nix::Error::Sys(Errno::EINVAL).into());
};
if p.OOMScoreAdj > 0 {
if p.oom_score_adj.is_some() {
fs::write(
"/proc/self/oom_score_adj",
p.OOMScoreAdj.to_string().as_bytes(),
p.oom_score_adj.unwrap().to_string().as_bytes(),
)?
}
// set rlimit
for rl in p.Rlimits.iter() {
for rl in p.rlimits.iter() {
setrlimit(rl)?;
}
@ -1061,10 +1043,10 @@ fn join_namespaces(
}
if to_new.contains(CloneFlags::CLONE_NEWUTS) {
unistd::sethostname(&spec.Hostname)?;
unistd::sethostname(&spec.hostname)?;
}
let rootfs = spec.Root.as_ref().unwrap().Path.as_str();
let rootfs = spec.root.as_ref().unwrap().path.as_str();
let root = fs::canonicalize(rootfs)?;
let rootfs = root.to_str().unwrap();
@ -1104,7 +1086,7 @@ fn join_namespaces(
}
// setup sysctl
set_sysctls(&linux.Sysctl)?;
set_sysctls(&linux.sysctl)?;
unistd::chdir("/")?;
if let Err(_) = stat::stat("marker") {
info!(logger, "not in expect root!!");
@ -1193,11 +1175,11 @@ fn setup_stdio(p: &Process) -> Result<()> {
fn write_mappings(logger: &Logger, path: &str, maps: &[LinuxIDMapping]) -> Result<()> {
let mut data = String::new();
for m in maps {
if m.Size == 0 {
if m.size == 0 {
continue;
}
let val = format!("{} {} {}\n", m.ContainerID, m.HostID, m.Size);
let val = format!("{} {} {}\n", m.container_id, m.host_id, m.size);
data = data + &val;
}
@ -1273,16 +1255,16 @@ impl LinuxContainer {
let spec = config.spec.as_ref().unwrap();
if spec.Linux.is_none() {
if spec.linux.is_none() {
return Err(nix::Error::Sys(Errno::EINVAL).into());
}
let linux = spec.Linux.as_ref().unwrap();
let linux = spec.linux.as_ref().unwrap();
let cpath = if linux.CgroupsPath.is_empty() {
let cpath = if linux.cgroups_path.is_empty() {
format!("/{}", id.as_str())
} else {
linux.CgroupsPath.clone()
linux.cgroups_path.clone()
};
let cgroup_manager = FsManager::new(cpath.as_str())?;
@ -1384,12 +1366,12 @@ lazy_static! {
fn setrlimit(limit: &POSIXRlimit) -> Result<()> {
let rl = libc::rlimit {
rlim_cur: limit.Soft,
rlim_max: limit.Hard,
rlim_cur: limit.soft,
rlim_max: limit.hard,
};
let res = if RLIMITMAPS.get(limit.Type.as_str()).is_some() {
*RLIMITMAPS.get(limit.Type.as_str()).unwrap()
let res = if RLIMITMAPS.get(limit.r#type.as_str()).is_some() {
*RLIMITMAPS.get(limit.r#type.as_str()).unwrap()
} else {
return Err(nix::Error::Sys(Errno::EINVAL).into());
};
@ -1445,14 +1427,14 @@ use std::time::Duration;
fn execute_hook(logger: &Logger, h: &Hook, st: &OCIState) -> Result<()> {
let logger = logger.new(o!("action" => "execute-hook"));
let binary = PathBuf::from(h.Path.as_str());
let binary = PathBuf::from(h.path.as_str());
let path = binary.canonicalize()?;
if !path.exists() {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
let args = h.Args.clone();
let envs = h.Env.clone();
let args = h.args.clone();
let envs = h.env.clone();
let state = serde_json::to_string(st)?;
// state.push_str("\n");
@ -1565,25 +1547,27 @@ fn execute_hook(logger: &Logger, h: &Hook, st: &OCIState) -> Result<()> {
let pid = rx.recv().unwrap();
info!(logger, "hook grand: {}", pid);
let status: i32 = if h.Timeout > 0 {
match rx.recv_timeout(Duration::from_secs(h.Timeout as u64)) {
Ok(s) => s,
Err(e) => {
let error = if e == RecvTimeoutError::Timeout {
-libc::ETIMEDOUT
} else {
-libc::EPIPE
};
let _ = signal::kill(Pid::from_raw(pid), Some(Signal::SIGKILL));
error
let status = {
if let Some(timeout) = h.timeout {
match rx.recv_timeout(Duration::from_secs(timeout as u64)) {
Ok(s) => s,
Err(e) => {
let error = if e == RecvTimeoutError::Timeout {
-libc::ETIMEDOUT
} else {
-libc::EPIPE
};
let _ = signal::kill(Pid::from_raw(pid), Some(Signal::SIGKILL));
error
}
}
}
} else {
if let Ok(s) = rx.recv() {
s
} else {
let _ = signal::kill(Pid::from_raw(pid), Some(Signal::SIGKILL));
-libc::EPIPE
if let Ok(s) = rx.recv() {
s
} else {
let _ = signal::kill(Pid::from_raw(pid), Some(Signal::SIGKILL));
-libc::EPIPE
}
}
};

View File

@ -68,7 +68,6 @@ pub mod validator;
use std::collections::HashMap;
use std::mem::MaybeUninit;
use oci::{
Box as ociBox, Hooks as ociHooks, Linux as ociLinux, LinuxCapabilities as ociLinuxCapabilities,
Mount as ociMount, POSIXRlimit as ociPOSIXRlimit, Process as ociProcess, Root as ociRoot,
@ -79,7 +78,7 @@ use protocols::oci::{
Root as grpcRoot, Spec as grpcSpec,
};
fn process_grpc_to_oci(p: &grpcProcess) -> ociProcess {
pub fn process_grpc_to_oci(p: &grpcProcess) -> ociProcess {
let console_size = if p.ConsoleSize.is_some() {
let c = p.ConsoleSize.as_ref().unwrap();
Some(ociBox {
@ -296,7 +295,7 @@ fn blockio_grpc_to_oci(blk: &grpcLinuxBlockIO) -> ociLinuxBlockIO {
}
}
fn resources_grpc_to_oci(res: &grpcLinuxResources) -> ociLinuxResources {
pub fn resources_grpc_to_oci(res: &grpcLinuxResources) -> ociLinuxResources {
let devices = {
let mut d = Vec::new();
for dev in res.Devices.iter() {

View File

@ -10,7 +10,7 @@ use nix::mount::{self, MntFlags, MsFlags};
use nix::sys::stat::{self, Mode, SFlag};
use nix::unistd::{self, Gid, Uid};
use nix::NixPath;
use protocols::oci::{LinuxDevice, Mount, Spec};
use oci::{LinuxDevice, Mount, Spec};
use std::collections::{HashMap, HashSet};
use std::fs::{self, OpenOptions};
use std::os::unix;
@ -108,14 +108,14 @@ pub fn init_rootfs(
lazy_static::initialize(&PROPAGATION);
lazy_static::initialize(&LINUXDEVICETYPE);
let linux = spec.Linux.as_ref().unwrap();
let linux = spec.linux.as_ref().unwrap();
let mut flags = MsFlags::MS_REC;
match PROPAGATION.get(&linux.RootfsPropagation.as_str()) {
match PROPAGATION.get(&linux.rootfs_propagation.as_str()) {
Some(fl) => flags |= *fl,
None => flags |= MsFlags::MS_SLAVE,
}
let rootfs = spec.Root.as_ref().unwrap().Path.as_str();
let rootfs = spec.root.as_ref().unwrap().path.as_str();
let root = fs::canonicalize(rootfs)?;
let rootfs = root.to_str().unwrap();
@ -128,13 +128,13 @@ pub fn init_rootfs(
None::<&str>,
)?;
for m in &spec.Mounts {
for m in &spec.mounts {
let (mut flags, data) = parse_mount(&m);
if !m.destination.starts_with("/") || m.destination.contains("..") {
return Err(ErrorKind::Nix(nix::Error::Sys(Errno::EINVAL)).into());
}
if m.field_type == "cgroup" {
mount_cgroups(logger, m, rootfs, flags, &data, cpath, mounts)?;
if m.r#type == "cgroup" {
mount_cgroups(logger, &m, rootfs, flags, &data, cpath, mounts)?;
} else {
if m.destination == "/dev" {
flags &= !MsFlags::MS_RDONLY;
@ -148,7 +148,7 @@ pub fn init_rootfs(
unistd::chdir(rootfs)?;
default_symlinks()?;
create_devices(&linux.Devices, bind_device)?;
create_devices(&linux.devices, bind_device)?;
ensure_ptmx()?;
unistd::chdir(&olddir)?;
@ -168,11 +168,9 @@ fn mount_cgroups(
// mount tmpfs
let ctm = Mount {
source: "tmpfs".to_string(),
field_type: "tmpfs".to_string(),
r#type: "tmpfs".to_string(),
destination: m.destination.clone(),
options: RepeatedField::default(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
options: Vec::new(),
};
let cflags = MsFlags::MS_NOEXEC | MsFlags::MS_NOSUID | MsFlags::MS_NODEV;
@ -217,11 +215,9 @@ fn mount_cgroups(
let bm = Mount {
source: source.to_string(),
field_type: "bind".to_string(),
r#type: "bind".to_string(),
destination: destination.clone(),
options: RepeatedField::default(),
unknown_fields: UnknownFields::default(),
cached_size: CachedSize::default(),
options: Vec::new(),
};
mount_from(
@ -430,7 +426,7 @@ fn mount_from(m: &Mount, rootfs: &str, flags: MsFlags, data: &str, _label: &str)
let d = String::from(data);
let dest = format!("{}{}", rootfs, &m.destination);
let src = if m.field_type.as_str() == "bind" {
let src = if m.r#type.as_str() == "bind" {
let src = fs::canonicalize(m.source.as_str())?;
let dir = if src.is_file() {
Path::new(&dest).parent().unwrap()
@ -484,7 +480,7 @@ fn mount_from(m: &Mount, rootfs: &str, flags: MsFlags, data: &str, _label: &str)
match mount::mount(
Some(src.to_str().unwrap()),
dest.as_str(),
Some(m.field_type.as_str()),
Some(m.r#type.as_str()),
flags,
Some(d.as_str()),
) {
@ -550,8 +546,8 @@ fn create_devices(devices: &[LinuxDevice], bind: bool) -> Result<()> {
op(dev)?;
}
for dev in devices {
if !dev.Path.starts_with("/dev") || dev.Path.contains("..") {
let msg = format!("{} is not a valid device path", dev.Path);
if !dev.path.starts_with("/dev") || dev.path.contains("..") {
let msg = format!("{} is not a valid device path", dev.path);
bail!(ErrorKind::ErrorCode(msg));
}
op(dev)?;
@ -581,22 +577,22 @@ lazy_static! {
}
fn mknod_dev(dev: &LinuxDevice) -> Result<()> {
let f = match LINUXDEVICETYPE.get(dev.Type.as_str()) {
let f = match LINUXDEVICETYPE.get(dev.r#type.as_str()) {
Some(v) => v,
None => return Err(ErrorKind::ErrorCode("invalid spec".to_string()).into()),
};
stat::mknod(
&dev.Path[1..],
&dev.path[1..],
*f,
Mode::from_bits_truncate(dev.FileMode),
makedev(dev.Major as u64, dev.Minor as u64),
Mode::from_bits_truncate(dev.file_mode.unwrap_or(0)),
makedev(dev.major as u64, dev.minor as u64),
)?;
unistd::chown(
&dev.Path[1..],
Some(Uid::from_raw(dev.UID as uid_t)),
Some(Gid::from_raw(dev.GID as uid_t)),
&dev.path[1..],
Some(Uid::from_raw(dev.uid.unwrap_or(0) as uid_t)),
Some(Gid::from_raw(dev.gid.unwrap_or(0) as uid_t)),
)?;
Ok(())
@ -604,7 +600,7 @@ fn mknod_dev(dev: &LinuxDevice) -> Result<()> {
fn bind_dev(dev: &LinuxDevice) -> Result<()> {
let fd = fcntl::open(
&dev.Path[1..],
&dev.path[1..],
OFlag::O_RDWR | OFlag::O_CREAT,
Mode::from_bits_truncate(0o644),
)?;
@ -612,8 +608,8 @@ fn bind_dev(dev: &LinuxDevice) -> Result<()> {
unistd::close(fd)?;
mount::mount(
Some(&*dev.Path),
&dev.Path[1..],
Some(&*dev.path),
&dev.path[1..],
None::<&str>,
MsFlags::MS_BIND,
None::<&str>,
@ -625,19 +621,19 @@ pub fn finish_rootfs(spec: &Spec) -> Result<()> {
let olddir = unistd::getcwd()?;
info!(sl!(), "{}", olddir.to_str().unwrap());
unistd::chdir("/")?;
if spec.Linux.is_some() {
let linux = spec.Linux.as_ref().unwrap();
if spec.linux.is_some() {
let linux = spec.linux.as_ref().unwrap();
for path in linux.MaskedPaths.iter() {
for path in linux.masked_paths.iter() {
mask_path(path)?;
}
for path in linux.ReadonlyPaths.iter() {
for path in linux.readonly_paths.iter() {
readonly_path(path)?;
}
}
for m in spec.Mounts.iter() {
for m in spec.mounts.iter() {
if m.destination == "/dev" {
let (flags, _) = parse_mount(m);
if flags.contains(MsFlags::MS_RDONLY) {
@ -652,7 +648,7 @@ pub fn finish_rootfs(spec: &Spec) -> Result<()> {
}
}
if spec.Root.as_ref().unwrap().Readonly {
if spec.root.as_ref().unwrap().readonly {
let flags = MsFlags::MS_BIND | MsFlags::MS_RDONLY | MsFlags::MS_NODEV | MsFlags::MS_REMOUNT;
mount::mount(Some("/"), "/", None::<&str>, flags, None::<&str>)?;

View File

@ -20,7 +20,7 @@ use nix::unistd::{self, Pid};
use nix::Result;
use nix::Error;
use protocols::oci::Process as OCIProcess;
use oci::Process as OCIProcess;
use slog::Logger;
#[derive(Debug)]
@ -104,7 +104,7 @@ impl Process {
info!(logger, "before create console socket!");
if ocip.Terminal {
if ocip.terminal {
let (psocket, csocket) = match socket::socketpair(
AddressFamily::Unix,
SockType::Stream,

View File

@ -3,7 +3,7 @@
// SPDX-License-Identifier: Apache-2.0
//
use protocols::oci::Spec;
use oci::Spec;
// use crate::configs::namespaces;
// use crate::configs::device::Device;

View File

@ -3,14 +3,14 @@ use crate::errors::*;
use lazy_static;
use nix::errno::Errno;
use nix::Error;
use oci::{LinuxIDMapping, LinuxNamespace, Spec};
use protobuf::RepeatedField;
use protocols::oci::{LinuxIDMapping, LinuxNamespace, Spec};
use std::collections::HashMap;
use std::path::{Component, PathBuf};
fn contain_namespace(nses: &RepeatedField<LinuxNamespace>, key: &str) -> bool {
fn contain_namespace(nses: &Vec<LinuxNamespace>, key: &str) -> bool {
for ns in nses {
if ns.Type.as_str() == key {
if ns.r#type.as_str() == key {
return true;
}
}
@ -18,10 +18,10 @@ fn contain_namespace(nses: &RepeatedField<LinuxNamespace>, key: &str) -> bool {
false
}
fn get_namespace_path(nses: &RepeatedField<LinuxNamespace>, key: &str) -> Result<String> {
fn get_namespace_path(nses: &Vec<LinuxNamespace>, key: &str) -> Result<String> {
for ns in nses {
if ns.Type.as_str() == key {
return Ok(ns.Path.clone());
if ns.r#type.as_str() == key {
return Ok(ns.path.clone());
}
}
@ -71,15 +71,15 @@ fn network(_oci: &Spec) -> Result<()> {
}
fn hostname(oci: &Spec) -> Result<()> {
if oci.Hostname.is_empty() || oci.Hostname == "".to_string() {
if oci.hostname.is_empty() || oci.hostname == "".to_string() {
return Ok(());
}
if oci.Linux.is_none() {
if oci.linux.is_none() {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
let linux = oci.Linux.as_ref().unwrap();
if !contain_namespace(&linux.Namespaces, "uts") {
let linux = oci.linux.as_ref().unwrap();
if !contain_namespace(&linux.namespaces, "uts") {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
@ -87,12 +87,12 @@ fn hostname(oci: &Spec) -> Result<()> {
}
fn security(oci: &Spec) -> Result<()> {
let linux = oci.Linux.as_ref().unwrap();
if linux.MaskedPaths.len() == 0 && linux.ReadonlyPaths.len() == 0 {
let linux = oci.linux.as_ref().unwrap();
if linux.masked_paths.len() == 0 && linux.readonly_paths.len() == 0 {
return Ok(());
}
if !contain_namespace(&linux.Namespaces, "mount") {
if !contain_namespace(&linux.namespaces, "mount") {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
@ -101,9 +101,9 @@ fn security(oci: &Spec) -> Result<()> {
Ok(())
}
fn idmapping(maps: &RepeatedField<LinuxIDMapping>) -> Result<()> {
fn idmapping(maps: &Vec<LinuxIDMapping>) -> Result<()> {
for map in maps {
if map.Size > 0 {
if map.size > 0 {
return Ok(());
}
}
@ -112,19 +112,19 @@ fn idmapping(maps: &RepeatedField<LinuxIDMapping>) -> Result<()> {
}
fn usernamespace(oci: &Spec) -> Result<()> {
let linux = oci.Linux.as_ref().unwrap();
if contain_namespace(&linux.Namespaces, "user") {
let linux = oci.linux.as_ref().unwrap();
if contain_namespace(&linux.namespaces, "user") {
let user_ns = PathBuf::from("/proc/self/ns/user");
if !user_ns.exists() {
return Err(ErrorKind::ErrorCode("user namespace not supported!".to_string()).into());
}
// check if idmappings is correct, at least I saw idmaps
// with zero size was passed to agent
idmapping(&linux.UIDMappings)?;
idmapping(&linux.GIDMappings)?;
idmapping(&linux.uid_mappings)?;
idmapping(&linux.gid_mappings)?;
} else {
// no user namespace but idmap
if linux.UIDMappings.len() != 0 || linux.GIDMappings.len() != 0 {
if linux.uid_mappings.len() != 0 || linux.gid_mappings.len() != 0 {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
}
@ -133,8 +133,8 @@ fn usernamespace(oci: &Spec) -> Result<()> {
}
fn cgroupnamespace(oci: &Spec) -> Result<()> {
let linux = oci.Linux.as_ref().unwrap();
if contain_namespace(&linux.Namespaces, "cgroup") {
let linux = oci.linux.as_ref().unwrap();
if contain_namespace(&linux.namespaces, "cgroup") {
let path = PathBuf::from("/proc/self/ns/cgroup");
if !path.exists() {
return Err(ErrorKind::ErrorCode("cgroup unsupported!".to_string()).into());
@ -178,10 +178,10 @@ fn check_host_ns(path: &str) -> Result<()> {
}
fn sysctl(oci: &Spec) -> Result<()> {
let linux = oci.Linux.as_ref().unwrap();
for (key, _) in linux.Sysctl.iter() {
let linux = oci.linux.as_ref().unwrap();
for (key, _) in linux.sysctl.iter() {
if SYSCTLS.contains_key(key.as_str()) || key.starts_with("fs.mqueue.") {
if contain_namespace(&linux.Namespaces, "ipc") {
if contain_namespace(&linux.namespaces, "ipc") {
continue;
} else {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
@ -189,11 +189,11 @@ fn sysctl(oci: &Spec) -> Result<()> {
}
if key.starts_with("net.") {
if !contain_namespace(&linux.Namespaces, "network") {
if !contain_namespace(&linux.namespaces, "network") {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
let net = get_namespace_path(&linux.Namespaces, "network")?;
let net = get_namespace_path(&linux.namespaces, "network")?;
if net.is_empty() || net == "".to_string() {
continue;
}
@ -201,7 +201,7 @@ fn sysctl(oci: &Spec) -> Result<()> {
check_host_ns(net.as_str())?;
}
if contain_namespace(&linux.Namespaces, "uts") {
if contain_namespace(&linux.namespaces, "uts") {
if key == "kernel.domainname" {
continue;
}
@ -217,21 +217,21 @@ fn sysctl(oci: &Spec) -> Result<()> {
}
fn rootless_euid_mapping(oci: &Spec) -> Result<()> {
let linux = oci.Linux.as_ref().unwrap();
if !contain_namespace(&linux.Namespaces, "user") {
let linux = oci.linux.as_ref().unwrap();
if !contain_namespace(&linux.namespaces, "user") {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
if linux.UIDMappings.len() == 0 || linux.GIDMappings.len() == 0 {
if linux.gid_mappings.len() == 0 || linux.gid_mappings.len() == 0 {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
Ok(())
}
fn has_idmapping(maps: &RepeatedField<LinuxIDMapping>, id: u32) -> bool {
fn has_idmapping(maps: &Vec<LinuxIDMapping>, id: u32) -> bool {
for map in maps {
if id >= map.ContainerID && id < map.ContainerID + map.Size {
if id >= map.container_id && id < map.container_id + map.size {
return true;
}
}
@ -239,9 +239,9 @@ fn has_idmapping(maps: &RepeatedField<LinuxIDMapping>, id: u32) -> bool {
}
fn rootless_euid_mount(oci: &Spec) -> Result<()> {
let linux = oci.Linux.as_ref().unwrap();
let linux = oci.linux.as_ref().unwrap();
for mnt in oci.Mounts.iter() {
for mnt in oci.mounts.iter() {
for opt in mnt.options.iter() {
if opt.starts_with("uid=") || opt.starts_with("gid=") {
let fields: Vec<&str> = opt.split('=').collect();
@ -253,13 +253,13 @@ fn rootless_euid_mount(oci: &Spec) -> Result<()> {
let id = fields[1].trim().parse::<u32>()?;
if opt.starts_with("uid=") {
if !has_idmapping(&linux.UIDMappings, id) {
if !has_idmapping(&linux.uid_mappings, id) {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
}
if opt.starts_with("gid=") {
if !has_idmapping(&linux.GIDMappings, id) {
if !has_idmapping(&linux.gid_mappings, id) {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
}
@ -279,14 +279,14 @@ pub fn validate(conf: &Config) -> Result<()> {
lazy_static::initialize(&SYSCTLS);
let oci = conf.spec.as_ref().unwrap();
if oci.Linux.is_none() {
if oci.linux.is_none() {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
if oci.Root.is_none() {
if oci.root.is_none() {
return Err(ErrorKind::Nix(Error::from_errno(Errno::EINVAL)).into());
}
let root = oci.Root.get_ref().Path.as_str();
let root = oci.root.as_ref().unwrap().path.as_str();
rootfs(root)?;
network(oci)?;

View File

@ -15,7 +15,7 @@ use crate::mount::{DRIVERBLKTYPE, DRIVERMMIOBLKTYPE, DRIVERNVDIMMTYPE, DRIVERSCS
use crate::sandbox::Sandbox;
use crate::{AGENT_CONFIG, GLOBAL_DEVICE_WATCHER};
use protocols::agent::Device;
use protocols::oci::Spec;
use oci::Spec;
use rustjail::errors::*;
// Convenience macro to obtain the scope logger
@ -207,7 +207,7 @@ fn update_spec_device_list(device: &Device, spec: &mut Spec) -> Result<()> {
.into());
}
let linux = match spec.Linux.as_mut() {
let linux = match spec.linux.as_mut() {
None => {
return Err(
ErrorKind::ErrorCode("Spec didn't container linux field".to_string()).into(),
@ -232,14 +232,14 @@ fn update_spec_device_list(device: &Device, spec: &mut Spec) -> Result<()> {
"got the device: dev_path: {}, major: {}, minor: {}\n", &device.vm_path, major_id, minor_id
);
let devices = linux.Devices.as_mut_slice();
let devices = linux.devices.as_mut_slice();
for dev in devices.iter_mut() {
if dev.Path == device.container_path {
let host_major = dev.Major;
let host_minor = dev.Minor;
if dev.path == device.container_path {
let host_major = dev.major;
let host_minor = dev.minor;
dev.Major = major_id as i64;
dev.Minor = minor_id as i64;
dev.major = major_id as i64;
dev.minor = minor_id as i64;
info!(
sl!(),
@ -252,12 +252,12 @@ fn update_spec_device_list(device: &Device, spec: &mut Spec) -> Result<()> {
// Resources must be updated since they are used to identify the
// device in the devices cgroup.
if let Some(res) = linux.Resources.as_mut() {
let ds = res.Devices.as_mut_slice();
if let Some(res) = linux.resources.as_mut() {
let ds = res.devices.as_mut_slice();
for d in ds.iter_mut() {
if d.Major == host_major && d.Minor == host_minor {
d.Major = major_id as i64;
d.Minor = minor_id as i64;
if d.major == Some(host_major) && d.minor == Some(host_minor) {
d.major = Some(major_id as i64);
d.minor = Some(minor_id as i64);
info!(
sl!(),

View File

@ -8,6 +8,7 @@ use grpcio::{EnvBuilder, Server, ServerBuilder};
use grpcio::{RpcStatus, RpcStatusCode};
use std::sync::{Arc, Mutex};
use oci::{LinuxNamespace, Spec};
use protobuf::{RepeatedField, SingularPtrField};
use protocols::agent::CopyFileRequest;
use protocols::agent::{
@ -16,7 +17,6 @@ use protocols::agent::{
};
use protocols::empty::Empty;
use protocols::health::{HealthCheckResponse, HealthCheckResponse_ServingStatus};
use protocols::oci::{LinuxNamespace, Spec};
use rustjail;
use rustjail::container::{BaseContainer, LinuxContainer};
use rustjail::errors::*;
@ -81,8 +81,8 @@ impl agentService {
let sandbox;
let mut s;
let oci = match oci_spec.as_mut() {
Some(spec) => spec,
let mut oci = match oci_spec.as_mut() {
Some(spec) => rustjail::grpc_to_oci(spec),
None => {
error!(sl!(), "no oci spec in the create container request!");
return Err(
@ -103,7 +103,7 @@ impl agentService {
// updates the devices listed in the OCI spec, so that they actually
// match real devices inside the VM. This step is necessary since we
// cannot predict everything from the caller.
add_devices(&req.devices.to_vec(), oci, &self.sandbox)?;
add_devices(&req.devices.to_vec(), &mut oci, &self.sandbox)?;
// Both rootfs and volumes (invoked with --volume for instance) will
// be processed the same way. The idea is to always mount any provided
@ -119,11 +119,11 @@ impl agentService {
s.container_mounts.insert(cid.clone(), m);
}
update_container_namespaces(&s, oci)?;
update_container_namespaces(&s, &mut oci)?;
// write spec to bundle path, hooks might
// read ocispec
let olddir = setup_bundle(oci)?;
let olddir = setup_bundle(&oci)?;
// restore the cwd for kata-agent process.
defer!(unistd::chdir(&olddir).unwrap());
@ -141,8 +141,14 @@ impl agentService {
LinuxContainer::new(cid.as_str(), CONTAINER_BASE, opts, &sl!())?;
let pipe_size = AGENT_CONFIG.read().unwrap().container_pipe_size;
let p = if oci.Process.is_some() {
let tp = Process::new(&sl!(), oci.get_Process(), eid.as_str(), true, pipe_size)?;
let p = if oci.process.is_some() {
let tp = Process::new(
&sl!(),
&oci.process.as_ref().unwrap(),
eid.as_str(),
true,
pipe_size,
)?;
tp
} else {
info!(sl!(), "no process configurations!");
@ -270,14 +276,15 @@ impl agentService {
let mut sandbox = s.lock().unwrap();
// ignore string_user, not sure what it is
let ocip = if req.process.is_some() {
let process = if req.process.is_some() {
req.process.as_ref().unwrap()
} else {
return Err(ErrorKind::Nix(nix::Error::from_errno(nix::errno::Errno::EINVAL)).into());
};
let pipe_size = AGENT_CONFIG.read().unwrap().container_pipe_size;
let p = Process::new(&sl!(), ocip, exec_id.as_str(), false, pipe_size)?;
let ocip = rustjail::process_grpc_to_oci(process);
let p = Process::new(&sl!(), &ocip, exec_id.as_str(), false, pipe_size)?;
let ctr = match sandbox.get_container(cid.as_str()) {
Some(v) => v,
@ -732,7 +739,7 @@ impl protocols::agent_grpc::AgentService for agentService {
sink: ::grpcio::UnarySink<protocols::empty::Empty>,
) {
let cid = req.container_id.clone();
let res = req.resources.clone();
let res = req.resources;
let s = Arc::clone(&self.sandbox);
let mut sandbox = s.lock().unwrap();
@ -742,7 +749,8 @@ impl protocols::agent_grpc::AgentService for agentService {
let resp = Empty::new();
if res.is_some() {
match ctr.set(res.unwrap()) {
let ociRes = rustjail::resources_grpc_to_oci(&res.unwrap());
match ctr.set(ociRes) {
Err(_e) => {
let f = sink
.fail(RpcStatus::new(
@ -1605,7 +1613,7 @@ pub fn start<S: Into<String>>(sandbox: Arc<Mutex<Sandbox>>, host: S, port: u16)
// sense to rely on the namespace path provided by the host since namespaces
// are different inside the guest.
fn update_container_namespaces(sandbox: &Sandbox, spec: &mut Spec) -> Result<()> {
let linux = match spec.Linux.as_mut() {
let linux = match spec.linux.as_mut() {
None => {
return Err(
ErrorKind::ErrorCode("Spec didn't container linux field".to_string()).into(),
@ -1616,26 +1624,26 @@ fn update_container_namespaces(sandbox: &Sandbox, spec: &mut Spec) -> Result<()>
let mut pidNs = false;
let namespaces = linux.Namespaces.as_mut_slice();
let namespaces = linux.namespaces.as_mut_slice();
for namespace in namespaces.iter_mut() {
if namespace.Type == NSTYPEPID {
if namespace.r#type == NSTYPEPID {
pidNs = true;
continue;
}
if namespace.Type == NSTYPEIPC {
namespace.Path = sandbox.shared_ipcns.path.clone();
if namespace.r#type == NSTYPEIPC {
namespace.path = sandbox.shared_ipcns.path.clone();
continue;
}
if namespace.Type == NSTYPEUTS {
namespace.Path = sandbox.shared_utsns.path.clone();
if namespace.r#type == NSTYPEUTS {
namespace.path = sandbox.shared_utsns.path.clone();
continue;
}
}
if !pidNs && !sandbox.sandbox_pid_ns {
let mut pid_ns = LinuxNamespace::new();
pid_ns.set_Type(NSTYPEPID.to_string());
linux.Namespaces.push(pid_ns);
let mut pid_ns = LinuxNamespace::default();
pid_ns.r#type = NSTYPEPID.to_string();
linux.namespaces.push(pid_ns);
}
Ok(())
@ -1764,24 +1772,23 @@ fn do_copy_file(req: &CopyFileRequest) -> Result<()> {
Ok(())
}
fn setup_bundle(gspec: &Spec) -> Result<PathBuf> {
if gspec.Root.is_none() {
fn setup_bundle(spec: &Spec) -> Result<PathBuf> {
if spec.root.is_none() {
return Err(nix::Error::Sys(Errno::EINVAL).into());
}
let root = gspec.Root.as_ref().unwrap().Path.as_str();
let root = spec.root.as_ref().unwrap().path.as_str();
let rootfs = fs::canonicalize(root)?;
let bundle_path = rootfs.parent().unwrap().to_str().unwrap();
let config = format!("{}/{}", bundle_path, "config.json");
let oci = rustjail::grpc_to_oci(gspec);
info!(
sl!(),
"{:?}",
oci.process.as_ref().unwrap().console_size.as_ref()
spec.process.as_ref().unwrap().console_size.as_ref()
);
let _ = oci.save(config.as_str());
let _ = spec.save(config.as_str());
let olddir = unistd::getcwd().chain_err(|| "cannot getcwd")?;
unistd::chdir(bundle_path)?;