1
0
Fork 0
mirror of https://github.com/containers/youki synced 2024-05-05 15:16:16 +02:00
youki/crates/libcgroups/src/v2/devices/emulator.rs
Emanuele Aina 3879619af7 style(spelling): Spellcheck the libcgroups crate
Signed-off-by: Emanuele Aina <emanuele.aina@collabora.com>
2022-01-03 22:06:03 +01:00

58 lines
1.9 KiB
Rust

use anyhow::Result;
use oci_spec::runtime::{LinuxDeviceCgroup, LinuxDeviceType};
// For cgroup v1 compatibility, runc implements a device emulator to caculate the final rules given
// a list of user-defined rules.
// https://github.com/opencontainers/runc/commit/2353ffec2bb670a200009dc7a54a56b93145f141
//
// I chose to implement a very simple algorithm, which will just work in most cases, but with
// diversion from cgroupv1 in some cases:
// 1. just add used-defined rules one by one
// 2. discard existing rules when encountering a rule with type='a', and change to deny/allow all
// list according the 'allow' of the rule
// 3. bpf program will check rule one by one in *reversed* order, return action of first rule
// which matches device access operation
//
// FIXME: should we use runc's implementation?
pub struct Emulator {
pub default_allow: bool,
pub rules: Vec<LinuxDeviceCgroup>,
}
impl Emulator {
pub fn with_default_allow(default_allow: bool) -> Self {
Emulator {
default_allow,
rules: Vec::new(),
}
}
pub fn add_rules(&mut self, rules: &[LinuxDeviceCgroup]) -> Result<()> {
for rule in rules {
self.add_rule(rule)?;
}
Ok(())
}
pub fn add_rule(&mut self, rule: &LinuxDeviceCgroup) -> Result<()> {
// special case, switch to blacklist or whitelist and clear all existing rules
// NOTE: we ignore other fields when type='a', this is same as cgroup v1 and runc
if rule.typ().unwrap_or_default() == LinuxDeviceType::A {
self.default_allow = rule.allow();
self.rules.clear();
return Ok(());
}
// empty access match nothing, just discard this rule
if rule.access().is_none() {
return Ok(());
}
self.rules.push(rule.clone());
Ok(())
}
}
// FIXME: add some tests