rustjail: get all capabilities dynamically

The runtime determines the kernel capability set at runtime.

Fixes: #1370

Signed-off-by: Manabu Sugimoto <Manabu.Sugimoto@sony.com>
This commit is contained in:
Manabu Sugimoto 2021-02-07 13:43:44 +09:00
parent d4391d784d
commit a252d861e3
4 changed files with 30 additions and 99 deletions

21
src/agent/Cargo.lock generated
View File

@ -141,13 +141,13 @@ checksum = "0e4cec68f03f32e44924783795810fa50a7035d8c8ebe78580ad7e6c703fba38"
[[package]] [[package]]
name = "caps" name = "caps"
version = "0.3.4" version = "0.5.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "bf6a638a1f7f409f1e545ff0036b8aa5541692c775dd36b48b75bbde50d83d1c" checksum = "26b13b33799e01119c4a7cd15c8f07e5f6b901bd97e85b321cf5a460f430f7cc"
dependencies = [ dependencies = [
"errno", "errno",
"error-chain",
"libc", "libc",
"thiserror",
] ]
[[package]] [[package]]
@ -299,15 +299,6 @@ dependencies = [
"libc", "libc",
] ]
[[package]]
name = "error-chain"
version = "0.12.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "2d2f06b9cac1506ece98fe3231e3cc9c4410ec3d5b1f24ae1c8946f0742cdefc"
dependencies = [
"version_check",
]
[[package]] [[package]]
name = "failure" name = "failure"
version = "0.1.8" version = "0.1.8"
@ -1828,12 +1819,6 @@ version = "0.2.1"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564" checksum = "f7fe0bb3479651439c9112f72b6c505038574c9fbb575ed1bf3b797fa39dd564"
[[package]]
name = "version_check"
version = "0.9.2"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "b5a972e5669d67ba988ce3dc826706fb0a8b01471c088cb0b6110b805cc36aed"
[[package]] [[package]]
name = "void" name = "void"
version = "1.0.2" version = "1.0.2"

View File

@ -10,7 +10,7 @@ serde_json = "1.0.39"
serde_derive = "1.0.91" serde_derive = "1.0.91"
oci = { path = "../oci" } oci = { path = "../oci" }
protocols = { path ="../protocols" } protocols = { path ="../protocols" }
caps = "0.3.0" caps = "0.5.0"
nix = "0.17.0" nix = "0.17.0"
scopeguard = "1.0.0" scopeguard = "1.0.0"
prctl = "1.0.0" prctl = "1.0.0"

View File

@ -9,97 +9,44 @@
use crate::log_child; use crate::log_child;
use crate::sync::write_count; use crate::sync::write_count;
use anyhow::{anyhow, Result}; use anyhow::{anyhow, Result};
use caps::{self, CapSet, Capability, CapsHashSet}; use caps::{self, runtime, CapSet, Capability, CapsHashSet};
use oci::LinuxCapabilities; use oci::LinuxCapabilities;
use std::collections::HashMap;
use std::os::unix::io::RawFd; use std::os::unix::io::RawFd;
use std::str::FromStr;
lazy_static! {
pub static ref CAPSMAP: HashMap<String, Capability> = {
let mut m = HashMap::new();
m.insert("CAP_CHOWN".to_string(), Capability::CAP_CHOWN);
m.insert("CAP_DAC_OVERRIDE".to_string(), Capability::CAP_DAC_OVERRIDE);
m.insert(
"CAP_DAC_READ_SEARCH".to_string(),
Capability::CAP_DAC_READ_SEARCH,
);
m.insert("CAP_FOWNER".to_string(), Capability::CAP_FOWNER);
m.insert("CAP_FSETID".to_string(), Capability::CAP_FSETID);
m.insert("CAP_KILL".to_string(), Capability::CAP_KILL);
m.insert("CAP_SETGID".to_string(), Capability::CAP_SETGID);
m.insert("CAP_SETUID".to_string(), Capability::CAP_SETUID);
m.insert("CAP_SETPCAP".to_string(), Capability::CAP_SETPCAP);
m.insert(
"CAP_LINUX_IMMUTABLE".to_string(),
Capability::CAP_LINUX_IMMUTABLE,
);
m.insert(
"CAP_NET_BIND_SERVICE".to_string(),
Capability::CAP_NET_BIND_SERVICE,
);
m.insert(
"CAP_NET_BROADCAST".to_string(),
Capability::CAP_NET_BROADCAST,
);
m.insert("CAP_NET_ADMIN".to_string(), Capability::CAP_NET_ADMIN);
m.insert("CAP_NET_RAW".to_string(), Capability::CAP_NET_RAW);
m.insert("CAP_IPC_LOCK".to_string(), Capability::CAP_IPC_LOCK);
m.insert("CAP_IPC_OWNER".to_string(), Capability::CAP_IPC_OWNER);
m.insert("CAP_SYS_MODULE".to_string(), Capability::CAP_SYS_MODULE);
m.insert("CAP_SYS_RAWIO".to_string(), Capability::CAP_SYS_RAWIO);
m.insert("CAP_SYS_CHROOT".to_string(), Capability::CAP_SYS_CHROOT);
m.insert("CAP_SYS_PTRACE".to_string(), Capability::CAP_SYS_PTRACE);
m.insert("CAP_SYS_PACCT".to_string(), Capability::CAP_SYS_PACCT);
m.insert("CAP_SYS_ADMIN".to_string(), Capability::CAP_SYS_ADMIN);
m.insert("CAP_SYS_BOOT".to_string(), Capability::CAP_SYS_BOOT);
m.insert("CAP_SYS_NICE".to_string(), Capability::CAP_SYS_NICE);
m.insert("CAP_SYS_RESOURCE".to_string(), Capability::CAP_SYS_RESOURCE);
m.insert("CAP_SYS_TIME".to_string(), Capability::CAP_SYS_TIME);
m.insert(
"CAP_SYS_TTY_CONFIG".to_string(),
Capability::CAP_SYS_TTY_CONFIG,
);
m.insert("CAP_MKNOD".to_string(), Capability::CAP_MKNOD);
m.insert("CAP_LEASE".to_string(), Capability::CAP_LEASE);
m.insert("CAP_AUDIT_WRITE".to_string(), Capability::CAP_AUDIT_WRITE);
m.insert("CAP_AUDIT_CONTROL".to_string(), Capability::CAP_AUDIT_WRITE);
m.insert("CAP_SETFCAP".to_string(), Capability::CAP_SETFCAP);
m.insert("CAP_MAC_OVERRIDE".to_string(), Capability::CAP_MAC_OVERRIDE);
m.insert("CAP_SYSLOG".to_string(), Capability::CAP_SYSLOG);
m.insert("CAP_WAKE_ALARM".to_string(), Capability::CAP_WAKE_ALARM);
m.insert(
"CAP_BLOCK_SUSPEND".to_string(),
Capability::CAP_BLOCK_SUSPEND,
);
m.insert("CAP_AUDIT_READ".to_string(), Capability::CAP_AUDIT_READ);
m
};
}
fn to_capshashset(cfd_log: RawFd, caps: &[String]) -> CapsHashSet { fn to_capshashset(cfd_log: RawFd, caps: &[String]) -> CapsHashSet {
let mut r = CapsHashSet::new(); let mut r = CapsHashSet::new();
for cap in caps.iter() { for cap in caps.iter() {
let c = CAPSMAP.get(cap); match Capability::from_str(cap) {
Err(_) => {
if c.is_none() { log_child!(cfd_log, "{} is not a cap", cap);
log_child!(cfd_log, "{} is not a cap", cap); continue;
continue; }
} Ok(c) => r.insert(c),
};
r.insert(*c.unwrap());
} }
r r
} }
pub fn get_all_caps() -> CapsHashSet {
let mut caps_set =
runtime::procfs_all_supported(None).unwrap_or_else(|_| runtime::thread_all_supported());
if caps_set.is_empty() {
caps_set = caps::all();
}
caps_set
}
pub fn reset_effective() -> Result<()> { pub fn reset_effective() -> Result<()> {
caps::set(None, CapSet::Effective, caps::all()).map_err(|e| anyhow!(e.to_string()))?; let all = get_all_caps();
caps::set(None, CapSet::Effective, &all).map_err(|e| anyhow!(e.to_string()))?;
Ok(()) Ok(())
} }
pub fn drop_privileges(cfd_log: RawFd, caps: &LinuxCapabilities) -> Result<()> { pub fn drop_privileges(cfd_log: RawFd, caps: &LinuxCapabilities) -> Result<()> {
let all = caps::all(); let all = get_all_caps();
for c in all.difference(&to_capshashset(cfd_log, caps.bounding.as_ref())) { for c in all.difference(&to_capshashset(cfd_log, caps.bounding.as_ref())) {
caps::drop(None, CapSet::Bounding, *c).map_err(|e| anyhow!(e.to_string()))?; caps::drop(None, CapSet::Bounding, *c).map_err(|e| anyhow!(e.to_string()))?;
@ -108,26 +55,26 @@ pub fn drop_privileges(cfd_log: RawFd, caps: &LinuxCapabilities) -> Result<()> {
caps::set( caps::set(
None, None,
CapSet::Effective, CapSet::Effective,
to_capshashset(cfd_log, caps.effective.as_ref()), &to_capshashset(cfd_log, caps.effective.as_ref()),
) )
.map_err(|e| anyhow!(e.to_string()))?; .map_err(|e| anyhow!(e.to_string()))?;
caps::set( caps::set(
None, None,
CapSet::Permitted, CapSet::Permitted,
to_capshashset(cfd_log, caps.permitted.as_ref()), &to_capshashset(cfd_log, caps.permitted.as_ref()),
) )
.map_err(|e| anyhow!(e.to_string()))?; .map_err(|e| anyhow!(e.to_string()))?;
caps::set( caps::set(
None, None,
CapSet::Inheritable, CapSet::Inheritable,
to_capshashset(cfd_log, caps.inheritable.as_ref()), &to_capshashset(cfd_log, caps.inheritable.as_ref()),
) )
.map_err(|e| anyhow!(e.to_string()))?; .map_err(|e| anyhow!(e.to_string()))?;
let _ = caps::set( let _ = caps::set(
None, None,
CapSet::Ambient, CapSet::Ambient,
to_capshashset(cfd_log, caps.ambient.as_ref()), &to_capshashset(cfd_log, caps.ambient.as_ref()),
) )
.map_err(|_| log_child!(cfd_log, "failed to set ambient capability")); .map_err(|_| log_child!(cfd_log, "failed to set ambient capability"));

View File

@ -18,7 +18,7 @@ use std::time::SystemTime;
use cgroups::freezer::FreezerState; use cgroups::freezer::FreezerState;
use crate::capabilities::{self, CAPSMAP}; use crate::capabilities;
#[cfg(not(test))] #[cfg(not(test))]
use crate::cgroups::fs::Manager as FsManager; use crate::cgroups::fs::Manager as FsManager;
#[cfg(test)] #[cfg(test)]
@ -339,7 +339,6 @@ fn do_init_child(cwfd: RawFd) -> Result<()> {
lazy_static::initialize(&NAMESPACES); lazy_static::initialize(&NAMESPACES);
lazy_static::initialize(&DEFAULT_DEVICES); lazy_static::initialize(&DEFAULT_DEVICES);
lazy_static::initialize(&RLIMITMAPS); lazy_static::initialize(&RLIMITMAPS);
lazy_static::initialize(&CAPSMAP);
let init = std::env::var(INIT)?.eq(format!("{}", true).as_str()); let init = std::env::var(INIT)?.eq(format!("{}", true).as_str());