1
0
Fork 0
mirror of https://github.com/containers/youki synced 2024-05-10 17:46:15 +02:00
youki/src/cgroups/devices.rs

158 lines
4.0 KiB
Rust

use std::io::Write;
use std::{
fs::{create_dir_all, OpenOptions},
path::Path,
};
use anyhow::Result;
use nix::unistd::Pid;
use crate::{
cgroups::Controller,
rootfs::default_devices,
spec::{LinuxDeviceCgroup, LinuxDeviceType, LinuxResources},
};
impl ToString for LinuxDeviceCgroup {
fn to_string(&self) -> String {
let major = self
.major
.map(|mj| mj.to_string())
.unwrap_or_else(|| "*".to_string());
let minor = self
.minor
.map(|mi| mi.to_string())
.unwrap_or_else(|| "*".to_string());
format!(
"{} {}:{} {}",
self.typ.as_str(),
&major,
&minor,
&self.access
)
}
}
pub struct Devices {}
impl Controller for Devices {
fn apply(linux_resources: &LinuxResources, cgroup_root: &Path, pid: Pid) -> Result<()> {
log::debug!("Apply Devices cgroup config");
create_dir_all(&cgroup_root)?;
for d in &linux_resources.devices {
Self::apply_device(d, cgroup_root)?;
}
for d in [
default_devices().iter().map(|d| d.into()).collect(),
Self::default_allow_devices(),
]
.concat()
{
Self::apply_device(&d, &cgroup_root)?;
}
OpenOptions::new()
.create(false)
.write(true)
.truncate(false)
.open(cgroup_root.join("cgroup.procs"))?
.write_all(pid.to_string().as_bytes())?;
Ok(())
}
}
impl Devices {
fn apply_device(device: &LinuxDeviceCgroup, cgroup_root: &Path) -> Result<()> {
let path = if device.allow {
cgroup_root.join("devices.allow")
} else {
cgroup_root.join("devices.deny")
};
OpenOptions::new()
.create(false)
.write(true)
.truncate(false)
.open(path)?
.write_all(device.to_string().as_bytes())?;
Ok(())
}
fn default_allow_devices() -> Vec<LinuxDeviceCgroup> {
vec![
LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::C,
major: None,
minor: None,
access: "m".to_string(),
},
LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::B,
major: None,
minor: None,
access: "m".to_string(),
},
// /dev/console
LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::C,
major: Some(5),
minor: Some(1),
access: "rwm".to_string(),
},
// /dev/pts
LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::C,
major: Some(136),
minor: None,
access: "rwm".to_string(),
},
LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::C,
major: Some(5),
minor: Some(2),
access: "rwm".to_string(),
},
// tun/tap
LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::C,
major: Some(10),
minor: Some(200),
access: "rwm".to_string(),
},
]
}
}
#[cfg(test)]
mod tests {
use super::*;
#[test]
fn test_linux_device_cgroup_to_string() {
let ldc = LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::A,
major: None,
minor: None,
access: "rwm".into(),
};
assert_eq!(ldc.to_string(), "a *:* rwm");
let ldc = LinuxDeviceCgroup {
allow: true,
typ: LinuxDeviceType::A,
major: Some(1),
minor: Some(9),
access: "rwm".into(),
};
assert_eq!(ldc.to_string(), "a 1:9 rwm");
}
}