diff --git a/src/cgroup.rs b/src/cgroup.rs index de219f8..8c940e9 100644 --- a/src/cgroup.rs +++ b/src/cgroup.rs @@ -7,8 +7,8 @@ use std::mem::ManuallyDrop; use std::path::{Path, PathBuf}; // The numerical representation below needs to match BPF_DEVCG constants. -#[allow(unused)] #[repr(u32)] +#[derive(Debug, Clone, Copy, PartialEq, Eq)] pub enum DeviceType { Block = 1, Character = 2, diff --git a/src/dev/device.rs b/src/dev/device.rs index 256d533..d8350fa 100644 --- a/src/dev/device.rs +++ b/src/dev/device.rs @@ -1,9 +1,12 @@ use std::fmt::{self, Display, Formatter}; use std::path::{Path, PathBuf}; +use crate::cgroup::DeviceType; + #[derive(Debug, Clone)] pub struct DevNode { pub path: PathBuf, + pub ty: DeviceType, pub devnum: (u32, u32), } @@ -16,17 +19,22 @@ pub struct Device { impl Device { pub fn from_udev(device: udev::Device) -> Self { - let devnode = device - .devnum() - .zip(device.devnode()) - .map(|(devnum, devnode)| { - let major = rustix::fs::major(devnum); - let minor = rustix::fs::minor(devnum); - DevNode { - path: devnode.to_owned(), - devnum: (major, minor), - } - }); + let devnode = device.devnode().and_then(|devnode| { + let devnum = device.devnum()?; + let major = rustix::fs::major(devnum); + let minor = rustix::fs::minor(devnum); + // Only block subsystem produce block device, everything else are character device. + let ty = if device.subsystem()? == "block" { + DeviceType::Block + } else { + DeviceType::Character + }; + Some(DevNode { + path: devnode.to_owned(), + ty, + devnum: (major, minor), + }) + }); Self { device, devnode } } diff --git a/src/hotplug/mod.rs b/src/hotplug/mod.rs index 3c03ac3..048f94e 100644 --- a/src/hotplug/mod.rs +++ b/src/hotplug/mod.rs @@ -70,8 +70,12 @@ impl HotPlug { .filter_map(|dev| dev.matches(&device)) .collect(); - self.container.device(devnode.devnum, Access::all()).await?; - self.container.mknod(&devnode.path, devnode.devnum).await?; + self.container + .device(devnode.ty, devnode.devnum, Access::all()) + .await?; + self.container + .mknod(&devnode.path, devnode.ty, devnode.devnum) + .await?; for symlink in &symlinks { self.container.symlink(&devnode.path, symlink).await?; } @@ -89,7 +93,7 @@ impl HotPlug { let devnode = device.devnode().unwrap(); self.container - .device(devnode.devnum, Access::empty()) + .device(devnode.ty, devnode.devnum, Access::empty()) .await?; self.container.rm(&devnode.path).await?; for symlink in &device.symlinks { diff --git a/src/runc/container.rs b/src/runc/container.rs index 8626e40..4a0e486 100644 --- a/src/runc/container.rs +++ b/src/runc/container.rs @@ -215,7 +215,12 @@ impl Container { Ok(()) } - pub async fn mknod(&self, node: &Path, (major, minor): (u32, u32)) -> Result<()> { + pub async fn mknod( + &self, + node: &Path, + ty: DeviceType, + (major, minor): (u32, u32), + ) -> Result<()> { let ns = crate::util::namespace::MntNamespace::of_pid(self.pid)?; ns.enter(|| { if let Some(parent) = node.parent() { @@ -225,7 +230,11 @@ impl Container { rustix::fs::mknodat( rustix::fs::CWD, node, - FileType::CharacterDevice, + if ty == DeviceType::Character { + FileType::CharacterDevice + } else { + FileType::BlockDevice + }, Mode::from(0o644), rustix::fs::makedev(major, minor), )?; @@ -252,13 +261,16 @@ impl Container { }) } - pub async fn device(&self, (major, minor): (u32, u32), access: Access) -> Result<()> { - self.cgroup_device_filter.lock().await.set_permission( - DeviceType::Character, - major, - minor, - access, - )?; + pub async fn device( + &self, + ty: DeviceType, + (major, minor): (u32, u32), + access: Access, + ) -> Result<()> { + self.cgroup_device_filter + .lock() + .await + .set_permission(ty, major, minor, access)?; Ok(()) } }