devices: proxy: set TZ in sandboxed device process

The `chrono` crate attempts to read the local timezone from the TZ
environment variable, and if it's missing, it will try to read
`/etc/localtime`, which uses system calls that are not allowed in the
common device sandbox policy.

Preserve the TZ environment variable from the parent process across the
minijail fork so the /etc/localtime fallback is avoided and no
additional system calls are required in the seccomp policy.

BUG=b:257987535
TEST=Boot ARCVM

Change-Id: Ieaf5e59d0c839ad4c017cc283b81b9eb1430ff67
Reviewed-on: https://chromium-review.googlesource.com/c/crosvm/crosvm/+/4009580
Reviewed-by: Allen Webb <allenwebb@google.com>
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Commit-Queue: Daniel Verkamp <dverkamp@chromium.org>
This commit is contained in:
Daniel Verkamp 2022-11-07 10:56:36 -08:00 committed by crosvm LUCI
parent 02bc918e74
commit df7164273e
3 changed files with 18 additions and 0 deletions

View file

@ -188,6 +188,8 @@ impl ProxyDevice {
keep_rds.sort_unstable();
keep_rds.dedup();
let tz = std::env::var("TZ").unwrap_or_default();
// Forking here is safe as long as the program is still single threaded.
// We own the jail object and nobody else will try to reuse it.
let pid = match unsafe { jail.fork(Some(&keep_rds)) }.map_err(Error::ForkingJail)? {
@ -199,6 +201,10 @@ impl ProxyDevice {
// thread_name is a valid pointer and setting name of this thread should be safe.
let _ =
unsafe { libc::pthread_setname_np(libc::pthread_self(), thread_name.as_ptr()) };
// Preserve TZ for `chrono::Local` (b/257987535).
std::env::set_var("TZ", tz);
device.on_sandboxed();
child_proc(child_tube, &mut device);

View file

@ -65,6 +65,8 @@ fn jail_and_fork(
// Make sure there are no duplicates in keep_rds
keep_rds.dedup();
let tz = std::env::var("TZ").unwrap_or_default();
// fork on the jail here
let pid = unsafe { j.fork(Some(&keep_rds))? };
@ -72,6 +74,11 @@ fn jail_and_fork(
unsafe { libc::prctl(libc::PR_SET_PDEATHSIG, libc::SIGTERM) };
}
if pid == 0 {
// Preserve TZ for `chrono::Local` (b/257987535).
std::env::set_var("TZ", tz);
}
if pid < 0 {
bail!("Fork error! {}", std::io::Error::last_os_error());
}

View file

@ -2919,6 +2919,8 @@ fn jail_and_start_vu_device<T: VirtioDeviceBuilder>(
.or_else(|_| Minijail::new())
.with_context(|| format!("failed to create empty jail for {}", name))?;
let tz = std::env::var("TZ").unwrap_or_default();
// Safe because we are keeping all the descriptors needed for the child to function.
match unsafe { jail.fork(Some(&keep_rds)).context("error while forking")? } {
0 => {
@ -2941,6 +2943,9 @@ fn jail_and_start_vu_device<T: VirtioDeviceBuilder>(
// an error if we don't anyway).
let _ = unsafe { libc::pthread_setname_np(libc::pthread_self(), thread_name.as_ptr()) };
// Preserve TZ for `chrono::Local` (b/257987535).
std::env::set_var("TZ", tz);
// Run the device loop and terminate the child process once it exits.
let res = match listener.run_device(device) {
Ok(()) => 0,