Skip to content

Commit a2ac04e

Browse files
authored
Merge branch 'main' into fix-physical-counters
2 parents 0bbf375 + 0975cd4 commit a2ac04e

File tree

2 files changed

+17
-31
lines changed

2 files changed

+17
-31
lines changed

CHANGELOG.md

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,11 @@ and this project adheres to
4949
balloon device is inflated post UFFD-backed snapshot restore, Firecracker now
5050
causes `remove` UFFD messages to be sent to the UFFD handler. Previously, no
5151
such message would be sent.
52+
- [#5034](https://github.com/firecracker-microvm/firecracker/pull/5034): Fix an
53+
integer underflow in the jailer when computing the value it passes to
54+
Firecracker's `--parent-cpu-time-us` values, which caused development builds
55+
of Firecracker to crash (but production builds were unaffected as underflows
56+
do not panic in release mode).
5257

5358
## [1.10.1]
5459

src/jailer/src/env.rs

Lines changed: 12 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -3,13 +3,13 @@
33

44
use std::ffi::{CString, OsString};
55
use std::fs::{self, canonicalize, read_to_string, File, OpenOptions, Permissions};
6+
use std::io;
67
use std::io::Write;
78
use std::os::unix::fs::PermissionsExt;
89
use std::os::unix::io::AsRawFd;
910
use std::os::unix::process::CommandExt;
1011
use std::path::{Component, Path, PathBuf};
1112
use std::process::{exit, id, Command, Stdio};
12-
use std::{fmt, io};
1313

1414
use utils::arg_parser::UtilsArgParserError::MissingValue;
1515
use utils::time::{get_time_us, ClockType};
@@ -114,6 +114,7 @@ enum UserfaultfdParseError {
114114
NotFound,
115115
}
116116

117+
#[derive(Debug)]
117118
pub struct Env {
118119
id: String,
119120
chroot_dir: PathBuf,
@@ -132,26 +133,6 @@ pub struct Env {
132133
uffd_dev_minor: Option<u32>,
133134
}
134135

135-
impl fmt::Debug for Env {
136-
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
137-
f.debug_struct("Env")
138-
.field("id", &self.id)
139-
.field("chroot_dir", &self.chroot_dir)
140-
.field("exec_file_path", &self.exec_file_path)
141-
.field("uid", &self.uid)
142-
.field("gid", &self.gid)
143-
.field("netns", &self.netns)
144-
.field("daemonize", &self.daemonize)
145-
.field("new_pid_ns", &self.new_pid_ns)
146-
.field("start_time_us", &self.start_time_us)
147-
.field("jailer_cpu_time_us", &self.jailer_cpu_time_us)
148-
.field("extra_args", &self.extra_args)
149-
.field("cgroups", &self.cgroup_conf)
150-
.field("resource_limits", &self.resource_limits)
151-
.finish()
152-
}
153-
}
154-
155136
impl Env {
156137
pub fn new(
157138
arguments: &arg_parser::Arguments,
@@ -495,7 +476,10 @@ impl Env {
495476
Command::new(chroot_exec_file)
496477
.args(["--id", &self.id])
497478
.args(["--start-time-us", &self.start_time_us.to_string()])
498-
.args(["--start-time-cpu-us", &self.start_time_cpu_us.to_string()])
479+
.args([
480+
"--start-time-cpu-us",
481+
&get_time_us(ClockType::ProcessCpu).to_string(),
482+
])
499483
.args(["--parent-cpu-time-us", &self.jailer_cpu_time_us.to_string()])
500484
.stdin(Stdio::inherit())
501485
.stdout(Stdio::inherit())
@@ -661,11 +645,10 @@ impl Env {
661645
self.mknod_and_own_dev(DEV_UFFD_PATH, DEV_UFFD_MAJOR, minor)?;
662646
}
663647

648+
self.jailer_cpu_time_us = get_time_us(ClockType::ProcessCpu) - self.start_time_cpu_us;
649+
664650
// Daemonize before exec, if so required (when the dev_null variable != None).
665651
if let Some(dev_null) = dev_null {
666-
// Meter CPU usage before fork()
667-
self.jailer_cpu_time_us = get_time_us(ClockType::ProcessCpu);
668-
669652
// We follow the double fork method to daemonize the jailer referring to
670653
// https://0xjet.github.io/3OHA/2022/04/11/post.html
671654
// setsid() will fail if the calling process is a process group leader.
@@ -688,7 +671,7 @@ impl Env {
688671
.into_empty_result()
689672
.map_err(JailerError::SetSid)?;
690673

691-
// Meter CPU usage before fork()
674+
// Meter CPU usage after first fork()
692675
self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu);
693676

694677
// Daemons should not have controlling terminals.
@@ -712,12 +695,10 @@ impl Env {
712695
dup2(dev_null.as_raw_fd(), STDIN_FILENO)?;
713696
dup2(dev_null.as_raw_fd(), STDOUT_FILENO)?;
714697
dup2(dev_null.as_raw_fd(), STDERR_FILENO)?;
715-
}
716698

717-
// Compute jailer's total CPU time up to the current time.
718-
self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu) - self.start_time_cpu_us;
719-
// Reset process start time.
720-
self.start_time_cpu_us = 0;
699+
// Meter CPU usage after second fork()
700+
self.jailer_cpu_time_us += get_time_us(ClockType::ProcessCpu);
701+
}
721702

722703
// If specified, exec the provided binary into a new PID namespace.
723704
if self.new_pid_ns {

0 commit comments

Comments
 (0)