Skip to content

Commit 5886c91

Browse files
saku3cypharutam0k
authored
Merge commit from fork
* apparmor: use safe procfs API for labels Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * remove ensure_procfs Signed-off-by: Yusuke <yusuke.sakurai@3-shake.com> * sysctl: use safe procfs API from libpathrs Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> * convert Process::myself to ProcfsHandle Signed-off-by: Yusuke <yusuke.sakurai@3-shake.com> * use ProcfsHandle for /proc/self/setgroups Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * use libpathrs for mount_into_container Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * rootfs: switch fd-based handling of mountpoint targets Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * update libpathrs version Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * adjust test for fd-base mount Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * Harden masked paths Signed-off-by: utam0k <k0ma@utam0k.jp> * fixup! Harden masked paths Signed-off-by: utam0k <k0ma@utam0k.jp> * mount_setattr: fd base Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * rootfs: switch fd-based handling of mountpoint targets to using move_mount Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * fd-based handling for src and dest Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * use BorrowedFd and as_fd Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * the mount flags are set via mount_setattr (not fsmount) Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> * use resolve replace subpath Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> --------- Signed-off-by: Yusuke Sakurai <yusuke.sakurai@3-shake.com> Signed-off-by: Yusuke <yusuke.sakurai@3-shake.com> Signed-off-by: Aleksa Sarai <cyphar@cyphar.com> Signed-off-by: utam0k <k0ma@utam0k.jp> Co-authored-by: Aleksa Sarai <cyphar@cyphar.com> Co-authored-by: utam0k <k0ma@utam0k.jp>
1 parent 06b7621 commit 5886c91

File tree

18 files changed

+1038
-388
lines changed

18 files changed

+1038
-388
lines changed

Cargo.lock

Lines changed: 43 additions & 8 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

crates/libcgroups/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@ cgroupsv2_devices = ["rbpf", "libbpf-sys", "errno", "libc", "nix/dir"]
2222
[dependencies]
2323
nix = { version = "0.29.0", features = ["signal", "user", "fs"] }
2424
procfs = "0.17.0"
25+
pathrs = "0.2.1"
2526
oci-spec = { version = "~0.8.3", features = ["runtime"] }
2627
fixedbitset = "0.5.7"
2728
serde = { version = "1.0", features = ["derive"] }

crates/libcgroups/src/v1/manager.rs

Lines changed: 13 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ use std::path::{Path, PathBuf};
44
use std::time::Duration;
55

66
use nix::unistd::Pid;
7-
use procfs::ProcError;
8-
use procfs::process::Process;
7+
use pathrs::flags::OpenFlags;
8+
use pathrs::procfs::{ProcfsBase, ProcfsHandle};
9+
use procfs::{FromRead, ProcError, ProcessCGroups};
910

1011
use super::blkio::{Blkio, V1BlkioStatsError};
1112
use super::controller::Controller;
@@ -47,6 +48,8 @@ pub enum V1ManagerError {
4748
CGroupRequired(CtrlType),
4849
#[error("subsystem does not exist")]
4950
SubsystemDoesNotExist,
51+
#[error(transparent)]
52+
Pathrs(#[from] pathrs::error::Error),
5053

5154
#[error(transparent)]
5255
BlkioController(WrappedIoError),
@@ -101,11 +104,14 @@ impl Manager {
101104
tracing::debug!("Get path for subsystem: {}", subsystem);
102105
let mount_point = util::get_subsystem_mount_point(subsystem)?;
103106

104-
let cgroup = Process::myself()?
105-
.cgroups()?
106-
.into_iter()
107-
.find(|c| c.controllers.contains(&subsystem.to_string()))
108-
.ok_or(V1ManagerError::SubsystemDoesNotExist)?;
107+
let cgroup = ProcessCGroups::from_read(ProcfsHandle::new()?.open(
108+
ProcfsBase::ProcSelf,
109+
"cgroup",
110+
OpenFlags::O_RDONLY | OpenFlags::O_CLOEXEC,
111+
)?)?
112+
.into_iter()
113+
.find(|c| c.controllers.contains(&subsystem.to_string()))
114+
.ok_or(V1ManagerError::SubsystemDoesNotExist)?;
109115

110116
let p = if cgroup_path.as_os_str().is_empty() {
111117
mount_point.join_safely(Path::new(&cgroup.pathname))?

crates/libcgroups/src/v1/util.rs

Lines changed: 61 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,33 +1,50 @@
11
use std::collections::HashMap;
2+
use std::io::{BufRead, BufReader};
23
use std::path::PathBuf;
34

5+
use pathrs::flags::OpenFlags;
6+
use pathrs::procfs::{ProcfsBase, ProcfsHandle};
47
use procfs::ProcError;
5-
use procfs::process::Process;
8+
use procfs::process::MountInfo;
69

710
use super::ControllerType;
811
use super::controller_type::CONTROLLERS;
912

1013
#[derive(thiserror::Error, Debug)]
1114
pub enum V1MountPointError {
12-
#[error("failed to read process info from /proc/self: {0}")]
13-
ReadSelf(ProcError),
15+
#[error("io error: {0}")]
16+
Io(#[from] std::io::Error),
1417
#[error("failed to get mountinfo: {0}")]
1518
MountInfo(ProcError),
1619
#[error("could not find mountpoint for {subsystem}")]
1720
NotFound { subsystem: ControllerType },
21+
#[error(transparent)]
22+
Pathrs(#[from] pathrs::error::Error),
1823
}
1924

2025
/// List all cgroup v1 subsystem mount points on the system. This can include unsupported
2126
/// subsystems, comounted controllers and named hierarchies.
2227
pub fn list_subsystem_mount_points() -> Result<Vec<PathBuf>, V1MountPointError> {
23-
Ok(Process::myself()
24-
.map_err(V1MountPointError::ReadSelf)?
25-
.mountinfo()
26-
.map_err(V1MountPointError::MountInfo)?
27-
.into_iter()
28-
.filter(|m| m.fs_type == "cgroup")
29-
.map(|m| m.mount_point)
30-
.collect())
28+
let reader = BufReader::new(ProcfsHandle::new()?.open(
29+
ProcfsBase::ProcSelf,
30+
"mountinfo",
31+
OpenFlags::O_RDONLY | OpenFlags::O_CLOEXEC,
32+
)?);
33+
34+
reader
35+
.lines()
36+
.map(|lr| {
37+
lr.map_err(V1MountPointError::Io)
38+
.and_then(|line| MountInfo::from_line(&line).map_err(V1MountPointError::MountInfo))
39+
})
40+
.try_fold(Vec::new(), |mut mount_points, r| {
41+
r.map(|m| {
42+
if m.fs_type == "cgroup" {
43+
mount_points.push(m.mount_point);
44+
}
45+
mount_points
46+
})
47+
})
3148
}
3249

3350
/// List the mount points of all currently supported cgroup subsystems.
@@ -46,38 +63,44 @@ pub fn list_supported_mount_points() -> Result<HashMap<ControllerType, PathBuf>,
4663

4764
pub fn get_subsystem_mount_point(subsystem: &ControllerType) -> Result<PathBuf, V1MountPointError> {
4865
let subsystem_name = subsystem.to_string();
49-
Process::myself()
50-
.map_err(V1MountPointError::ReadSelf)?
51-
.mountinfo()
52-
.map_err(V1MountPointError::MountInfo)?
53-
.into_iter()
54-
.find(|m| {
55-
if m.fs_type == "cgroup" {
66+
let reader = BufReader::new(ProcfsHandle::new()?.open(
67+
ProcfsBase::ProcSelf,
68+
"mountinfo",
69+
OpenFlags::O_RDONLY | OpenFlags::O_CLOEXEC,
70+
)?);
71+
72+
reader
73+
.lines()
74+
.map(|lr| {
75+
lr.map_err(V1MountPointError::Io)
76+
.and_then(|line| MountInfo::from_line(&line).map_err(V1MountPointError::MountInfo))
77+
})
78+
.find_map(|r| match r {
79+
Err(e) => Some(Err(e)),
80+
Ok(m) if m.fs_type == "cgroup" => {
5681
// Some systems mount net_prio and net_cls in the same directory
5782
// other systems mount them in their own directories. This
5883
// should handle both cases.
59-
if subsystem_name == "net_cls" {
60-
return m.mount_point.ends_with("net_cls,net_prio")
61-
|| m.mount_point.ends_with("net_prio,net_cls")
62-
|| m.mount_point.ends_with("net_cls");
63-
} else if subsystem_name == "net_prio" {
64-
return m.mount_point.ends_with("net_cls,net_prio")
65-
|| m.mount_point.ends_with("net_prio,net_cls")
66-
|| m.mount_point.ends_with("net_prio");
67-
}
68-
69-
if subsystem_name == "cpu" {
70-
return m.mount_point.ends_with("cpu,cpuacct")
71-
|| m.mount_point.ends_with("cpu");
72-
}
73-
if subsystem_name == "cpuacct" {
74-
return m.mount_point.ends_with("cpu,cpuacct")
75-
|| m.mount_point.ends_with("cpuacct");
76-
}
84+
let ok = match subsystem_name.as_str() {
85+
"net_cls" => ["net_cls,net_prio", "net_prio,net_cls", "net_cls"]
86+
.iter()
87+
.any(|s| m.mount_point.ends_with(s)),
88+
"net_prio" => ["net_cls,net_prio", "net_prio,net_cls", "net_prio"]
89+
.iter()
90+
.any(|s| m.mount_point.ends_with(s)),
91+
"cpu" => ["cpu,cpuacct", "cpu"]
92+
.iter()
93+
.any(|s| m.mount_point.ends_with(s)),
94+
"cpuacct" => ["cpu,cpuacct", "cpuacct"]
95+
.iter()
96+
.any(|s| m.mount_point.ends_with(s)),
97+
_ => m.mount_point.ends_with(&subsystem_name),
98+
};
99+
if ok { Some(Ok(m.mount_point)) } else { None }
77100
}
78-
m.mount_point.ends_with(&subsystem_name)
101+
Ok(_) => None,
79102
})
80-
.map(|m| m.mount_point)
103+
.transpose()?
81104
.ok_or(V1MountPointError::NotFound {
82105
subsystem: *subsystem,
83106
})

crates/libcgroups/src/v2/util.rs

Lines changed: 26 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,10 @@
1+
use std::io::{BufRead, BufReader};
12
use std::path::{Path, PathBuf};
23

4+
use pathrs::flags::OpenFlags;
5+
use pathrs::procfs::{ProcfsBase, ProcfsHandle};
36
use procfs::ProcError;
4-
use procfs::process::Process;
7+
use procfs::process::MountInfo;
58

69
use super::controller_type::ControllerType;
710
use crate::common::{self, WrappedIoError};
@@ -11,6 +14,8 @@ pub const CGROUP_SUBTREE_CONTROL: &str = "cgroup.subtree_control";
1114

1215
#[derive(thiserror::Error, Debug)]
1316
pub enum V2UtilError {
17+
#[error("io error: {0}")]
18+
Io(#[from] std::io::Error),
1419
#[error("io error: {0}")]
1520
WrappedIo(#[from] WrappedIoError),
1621
#[error("proc error: {0}")]
@@ -19,15 +24,30 @@ pub enum V2UtilError {
1924
CouldNotFind,
2025
#[error("cannot get available controllers. {0} does not exist")]
2126
DoesNotExist(PathBuf),
27+
#[error(transparent)]
28+
Pathrs(#[from] pathrs::error::Error),
2229
}
2330

2431
// Reads the `/proc/self/mountinfo` to get the mount point of this cgroup
2532
pub fn get_unified_mount_point() -> Result<PathBuf, V2UtilError> {
26-
Process::myself()?
27-
.mountinfo()?
28-
.into_iter()
29-
.find(|m| m.fs_type == "cgroup2")
30-
.map(|m| m.mount_point)
33+
let reader = BufReader::new(ProcfsHandle::new()?.open(
34+
ProcfsBase::ProcSelf,
35+
"mountinfo",
36+
OpenFlags::O_RDONLY | OpenFlags::O_CLOEXEC,
37+
)?);
38+
39+
reader
40+
.lines()
41+
.map(|lr| {
42+
lr.map_err(V2UtilError::Io)
43+
.and_then(|s| MountInfo::from_line(&s).map_err(V2UtilError::from))
44+
})
45+
.find_map(|r| match r {
46+
Ok(mi) if mi.fs_type == "cgroup2" => Some(Ok(mi.mount_point)),
47+
Ok(_) => None,
48+
Err(e) => Some(Err(e)),
49+
})
50+
.transpose()?
3151
.ok_or(V2UtilError::CouldNotFind)
3252
}
3353

crates/libcontainer/Cargo.toml

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -53,6 +53,7 @@ thiserror = "2.0.17"
5353
tracing = { version = "0.1.41", features = ["attributes"] }
5454
safe-path = "0.1.0"
5555
nc = "0.9.6"
56+
pathrs = "0.2.1"
5657

5758
[dev-dependencies]
5859
oci-spec = { version = "~0.8.3", features = ["proptests", "runtime"] }

0 commit comments

Comments
 (0)