Skip to content

Commit 27a19fe

Browse files
committed
feat(jailer): honor solitary --parent-cgroup option on cgroupsv2
If we specify `--parent-cgroup` without any `--cgroup` option, the jailer doesn't do anything, though a user specifying it could reasonably expect it to move the process under that cgroup. We could just error in that situation, and expect something else to launch the jailer process in a cgroup, but we risk breaking anybody that is already using it that way. Instead, we move the process to the `--parent-cgroup` since it's the most intuitive, although the specified `--parent-cgroup` is not a parent in that case. Link: #4287 Signed-off-by: Pablo Barbáchano <[email protected]>
1 parent 783f821 commit 27a19fe

File tree

5 files changed

+32
-4
lines changed

5 files changed

+32
-4
lines changed

CHANGELOG.md

+3
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,9 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4848

4949
### Changed
5050

51+
- [#4309](https://github.com/firecracker-microvm/firecracker/pull/4309): The
52+
jailer's option `--parent-cgroup` will move the process to that cgroup if no
53+
`cgroup` options are provided.
5154
- Simplified and clarified the removal policy of deprecated API elements
5255
to follow semantic versioning 2.0.0. For more information, please refer to
5356
[this GitHub discussion](https://github.com/firecracker-microvm/firecracker/discussions/4135).

docs/jailer.md

+2
Original file line numberDiff line numberDiff line change
@@ -46,6 +46,8 @@ jailer --id <id> \
4646
the jailer will write all cgroup parameters specified through `--cgroup` in
4747
`/sys/fs/cgroup/<controller_name>/all_uvms/external_uvms/<id>`. By default, the
4848
parent cgroup is `exec-file`.
49+
If there are no `--cgroup` parameters specified and `--group-version=2` was
50+
passed, then the jailer will move the process to the specified cgroup.
4951
- `cgroup-version` is used to select which type of cgroup hierarchy to use for
5052
the creation of cgroups. The default value is "1" which means that cgroups
5153
specified with the `cgroup` argument will be created within a v1 hierarchy.

src/jailer/src/cgroup.rs

+10
Original file line numberDiff line numberDiff line change
@@ -161,6 +161,16 @@ impl CgroupBuilder {
161161
}
162162
}
163163
}
164+
165+
// Returns the path to the root of the hierarchy
166+
pub fn get_v2_hierarchy_path(&mut self) -> Result<&PathBuf, JailerError> {
167+
match self.hierarchies.entry("unified".to_string()) {
168+
Occupied(entry) => Ok(entry.into_mut()),
169+
Vacant(_entry) => Err(JailerError::CgroupHierarchyMissing(
170+
"cgroupsv2 hierarchy missing".to_string(),
171+
)),
172+
}
173+
}
164174
}
165175

166176
#[derive(Debug)]

src/jailer/src/env.rs

+15-2
Original file line numberDiff line numberDiff line change
@@ -233,11 +233,24 @@ impl Env {
233233
.parse::<u8>()
234234
.map_err(|_| JailerError::CgroupInvalidVersion(cgroup_ver.to_string()))?;
235235

236-
let mut cgroup_builder = None;
236+
let cgroups_args: &[String] = arguments.multiple_values("cgroup").unwrap_or_default();
237+
238+
// If the --parent-cgroup exists, and we have no other cgroups,
239+
// then the intent is to move the process to that cgroup.
240+
// Only applies to cgroupsv2 since it's a unified hierarchy
241+
if cgroups_args.is_empty() && cgroup_ver == 2 {
242+
let mut builder = CgroupBuilder::new(cgroup_ver)?;
243+
let cg_parent = builder.get_v2_hierarchy_path()?.join(parent_cgroup);
244+
let cg_parent_procs = cg_parent.join("cgroup.procs");
245+
if cg_parent.exists() {
246+
fs::write(cg_parent_procs, std::process::id().to_string())
247+
.map_err(|_| JailerError::CgroupWrite(io::Error::last_os_error()))?;
248+
}
249+
}
237250

238251
// cgroup format: <cgroup_controller>.<cgroup_property>=<value>,...
239252
if let Some(cgroups_args) = arguments.multiple_values("cgroup") {
240-
let builder = cgroup_builder.get_or_insert(CgroupBuilder::new(cgroup_ver)?);
253+
let mut builder = CgroupBuilder::new(cgroup_ver)?;
241254
for cg in cgroups_args {
242255
let aux: Vec<&str> = cg.split('=').collect();
243256
if aux.len() != 2 || aux[1].is_empty() {

src/jailer/src/main.rs

+2-2
Original file line numberDiff line numberDiff line change
@@ -32,8 +32,6 @@ pub enum JailerError {
3232
CgroupLineNotFound(String, String),
3333
#[error("Cgroup invalid file: {0}")]
3434
CgroupInvalidFile(String),
35-
#[error("Expected value {0} for {2}. Current value: {1}")]
36-
CgroupWrite(String, String, String),
3735
#[error("Invalid format for cgroups: {0}")]
3836
CgroupFormat(String),
3937
#[error("Hierarchy not found: {0}")]
@@ -44,6 +42,8 @@ pub enum JailerError {
4442
CgroupInvalidVersion(String),
4543
#[error("Parent cgroup path is invalid. Path should not be absolute or contain '..' or '.'")]
4644
CgroupInvalidParentPath(),
45+
#[error("Failed to write to cgroups file: {0}")]
46+
CgroupWrite(io::Error),
4747
#[error("Failed to change owner for {0:?}: {1}")]
4848
ChangeFileOwner(PathBuf, io::Error),
4949
#[error("Failed to chdir into chroot directory: {0}")]

0 commit comments

Comments
 (0)