mirror of
https://github.com/kata-containers/kata-containers.git
synced 2025-04-29 20:24:31 +00:00
jail/validator: introduce helpers to reduce duplicated code
Fixes: #1214 Signed-off-by: Liu Jiang <gerry@linux.alibaba.com>
This commit is contained in:
parent
76ad32136f
commit
d38a5d3fcf
@ -10,6 +10,14 @@ use oci::{LinuxIDMapping, LinuxNamespace, Spec};
|
||||
use std::collections::HashMap;
|
||||
use std::path::{Component, PathBuf};
|
||||
|
||||
fn einval() {
|
||||
anyhow!(nix::Error::from_errno(Errno::EINVAL))
|
||||
}
|
||||
|
||||
fn get_linux(oci: &Spec) -> Result<&Linux> {
|
||||
oci.linux.as_ref().ok_or_else(einval)
|
||||
}
|
||||
|
||||
fn contain_namespace(nses: &[LinuxNamespace], key: &str) -> bool {
|
||||
for ns in nses {
|
||||
if ns.r#type.as_str() == key {
|
||||
@ -27,14 +35,14 @@ fn get_namespace_path(nses: &[LinuxNamespace], key: &str) -> Result<String> {
|
||||
}
|
||||
}
|
||||
|
||||
Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)))
|
||||
Err(einval())
|
||||
}
|
||||
|
||||
fn rootfs(root: &str) -> Result<()> {
|
||||
let path = PathBuf::from(root);
|
||||
// not absolute path or not exists
|
||||
if !path.exists() || !path.is_absolute() {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
// symbolic link? ..?
|
||||
@ -52,7 +60,7 @@ fn rootfs(root: &str) -> Result<()> {
|
||||
if let Some(v) = c.as_os_str().to_str() {
|
||||
stack.push(v.to_string());
|
||||
} else {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
}
|
||||
|
||||
@ -64,7 +72,7 @@ fn rootfs(root: &str) -> Result<()> {
|
||||
let canon = path.canonicalize().context("canonicalize")?;
|
||||
if cleaned != canon {
|
||||
// There is symbolic in path
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -79,28 +87,23 @@ fn hostname(oci: &Spec) -> Result<()> {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
let linux = oci
|
||||
.linux
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let linux = get_linux(oci)?;
|
||||
if !contain_namespace(&linux.namespaces, "uts") {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn security(oci: &Spec) -> Result<()> {
|
||||
let linux = oci
|
||||
.linux
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let linux = get_linux(oci)?;
|
||||
|
||||
if linux.masked_paths.is_empty() && linux.readonly_paths.is_empty() {
|
||||
return Ok(());
|
||||
}
|
||||
|
||||
if !contain_namespace(&linux.namespaces, "mount") {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
// don't care about selinux at present
|
||||
@ -115,14 +118,12 @@ fn idmapping(maps: &[LinuxIDMapping]) -> Result<()> {
|
||||
}
|
||||
}
|
||||
|
||||
Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)))
|
||||
Err(einval())
|
||||
}
|
||||
|
||||
fn usernamespace(oci: &Spec) -> Result<()> {
|
||||
let linux = oci
|
||||
.linux
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let linux = get_linux(oci)?;
|
||||
|
||||
if contain_namespace(&linux.namespaces, "user") {
|
||||
let user_ns = PathBuf::from("/proc/self/ns/user");
|
||||
if !user_ns.exists() {
|
||||
@ -135,7 +136,7 @@ fn usernamespace(oci: &Spec) -> Result<()> {
|
||||
} else {
|
||||
// no user namespace but idmap
|
||||
if !linux.uid_mappings.is_empty() || !linux.gid_mappings.is_empty() {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
}
|
||||
|
||||
@ -143,10 +144,8 @@ fn usernamespace(oci: &Spec) -> Result<()> {
|
||||
}
|
||||
|
||||
fn cgroupnamespace(oci: &Spec) -> Result<()> {
|
||||
let linux = oci
|
||||
.linux
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let linux = get_linux(oci)?;
|
||||
|
||||
if contain_namespace(&linux.namespaces, "cgroup") {
|
||||
let path = PathBuf::from("/proc/self/ns/cgroup");
|
||||
if !path.exists() {
|
||||
@ -190,23 +189,21 @@ fn check_host_ns(path: &str) -> Result<()> {
|
||||
.read_link()
|
||||
.context(format!("read link {:?}", cpath))?;
|
||||
if real_cpath == real_hpath {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn sysctl(oci: &Spec) -> Result<()> {
|
||||
let linux = oci
|
||||
.linux
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let linux = get_linux(oci)?;
|
||||
|
||||
for (key, _) in linux.sysctl.iter() {
|
||||
if SYSCTLS.contains_key(key.as_str()) || key.starts_with("fs.mqueue.") {
|
||||
if contain_namespace(&linux.namespaces, "ipc") {
|
||||
continue;
|
||||
} else {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
}
|
||||
|
||||
@ -216,27 +213,25 @@ fn sysctl(oci: &Spec) -> Result<()> {
|
||||
}
|
||||
|
||||
if key == "kernel.hostname" {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
}
|
||||
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
|
||||
fn rootless_euid_mapping(oci: &Spec) -> Result<()> {
|
||||
let linux = oci
|
||||
.linux
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let linux = get_linux(oci)?;
|
||||
|
||||
if !contain_namespace(&linux.namespaces, "user") {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
if linux.uid_mappings.is_empty() || linux.gid_mappings.is_empty() {
|
||||
// rootless containers requires at least one UID/GID mapping
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
Ok(())
|
||||
@ -252,10 +247,7 @@ fn has_idmapping(maps: &[LinuxIDMapping], id: u32) -> bool {
|
||||
}
|
||||
|
||||
fn rootless_euid_mount(oci: &Spec) -> Result<()> {
|
||||
let linux = oci
|
||||
.linux
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let linux = get_linux(oci)?;
|
||||
|
||||
for mnt in oci.mounts.iter() {
|
||||
for opt in mnt.options.iter() {
|
||||
@ -263,7 +255,7 @@ fn rootless_euid_mount(oci: &Spec) -> Result<()> {
|
||||
let fields: Vec<&str> = opt.split('=').collect();
|
||||
|
||||
if fields.len() != 2 {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
let id = fields[1]
|
||||
@ -272,11 +264,11 @@ fn rootless_euid_mount(oci: &Spec) -> Result<()> {
|
||||
.context(format!("parse field {}", &fields[1]))?;
|
||||
|
||||
if opt.starts_with("uid=") && !has_idmapping(&linux.uid_mappings, id) {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
if opt.starts_with("gid=") && !has_idmapping(&linux.gid_mappings, id) {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -292,18 +284,15 @@ fn rootless_euid(oci: &Spec) -> Result<()> {
|
||||
|
||||
pub fn validate(conf: &Config) -> Result<()> {
|
||||
lazy_static::initialize(&SYSCTLS);
|
||||
let oci = conf
|
||||
.spec
|
||||
.as_ref()
|
||||
.ok_or(anyhow!(nix::Error::from_errno(Errno::EINVAL)))?;
|
||||
let oci = conf.spec.as_ref().ok_or_else(einval)?;
|
||||
|
||||
if oci.linux.is_none() {
|
||||
return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL)));
|
||||
return Err(einval());
|
||||
}
|
||||
|
||||
let root = match oci.root.as_ref() {
|
||||
Some(v) => v.path.as_str(),
|
||||
None => return Err(anyhow!(nix::Error::from_errno(Errno::EINVAL))),
|
||||
None => return Err(einval()),
|
||||
};
|
||||
|
||||
rootfs(root).context("rootfs")?;
|
||||
|
Loading…
Reference in New Issue
Block a user