mirror of
https://chromium.googlesource.com/crosvm/crosvm
synced 2025-02-11 12:35:26 +00:00
linux.rs: unify jail creation
This change unifies two substantially similiar segments of code used to create a jail. BUG=none TEST=Ran 'build_test'. Local build, deployed to DUT, and verified that termina VM could still be used. Change-Id: Ib1f2f9bc5cfe1e6c9f3633af7e23f52e5eafe3c7 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/2057744 Tested-by: Matt Delco <delco@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Reviewed-by: Dylan Reid <dgreid@chromium.org> Commit-Queue: Matt Delco <delco@chromium.org>
This commit is contained in:
parent
de92ad05c7
commit
c24ad78624
1 changed files with 83 additions and 82 deletions
111
src/linux.rs
111
src/linux.rs
|
@ -304,27 +304,39 @@ fn get_max_open_files() -> Result<libc::rlim64_t> {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
struct SandboxConfig<'a> {
|
||||||
|
limit_caps: bool,
|
||||||
|
log_failures: bool,
|
||||||
|
seccomp_policy: &'a Path,
|
||||||
|
uid_map: Option<&'a str>,
|
||||||
|
gid_map: Option<&'a str>,
|
||||||
|
}
|
||||||
|
|
||||||
fn create_base_minijail(
|
fn create_base_minijail(
|
||||||
root: &Path,
|
root: &Path,
|
||||||
log_failures: bool,
|
r_limit: Option<u64>,
|
||||||
seccomp_policy: &Path,
|
config: Option<&SandboxConfig>,
|
||||||
) -> Result<Minijail> {
|
) -> Result<Minijail> {
|
||||||
// All child jails run in a new user namespace without any users mapped,
|
// All child jails run in a new user namespace without any users mapped,
|
||||||
// they run as nobody unless otherwise configured.
|
// they run as nobody unless otherwise configured.
|
||||||
let mut j = Minijail::new().map_err(Error::DeviceJail)?;
|
let mut j = Minijail::new().map_err(Error::DeviceJail)?;
|
||||||
|
|
||||||
|
if let Some(config) = config {
|
||||||
j.namespace_pids();
|
j.namespace_pids();
|
||||||
j.namespace_user();
|
j.namespace_user();
|
||||||
j.namespace_user_disable_setgroups();
|
j.namespace_user_disable_setgroups();
|
||||||
|
if config.limit_caps {
|
||||||
// Don't need any capabilities.
|
// Don't need any capabilities.
|
||||||
j.use_caps(0);
|
j.use_caps(0);
|
||||||
// Create a new mount namespace with an empty root FS.
|
}
|
||||||
j.namespace_vfs();
|
if let Some(uid_map) = config.uid_map {
|
||||||
j.enter_pivot_root(root).map_err(Error::DevicePivotRoot)?;
|
j.uidmap(uid_map).map_err(Error::SettingUidMap)?;
|
||||||
|
}
|
||||||
|
if let Some(gid_map) = config.gid_map {
|
||||||
|
j.gidmap(gid_map).map_err(Error::SettingGidMap)?;
|
||||||
|
}
|
||||||
// Run in an empty network namespace.
|
// Run in an empty network namespace.
|
||||||
j.namespace_net();
|
j.namespace_net();
|
||||||
// Most devices don't need to open many fds.
|
|
||||||
j.set_rlimit(libc::RLIMIT_NOFILE as i32, 1024, 1024)
|
|
||||||
.map_err(Error::SettingMaxOpenFiles)?;
|
|
||||||
// Apply the block device seccomp policy.
|
// Apply the block device seccomp policy.
|
||||||
j.no_new_privs();
|
j.no_new_privs();
|
||||||
|
|
||||||
|
@ -335,8 +347,8 @@ fn create_base_minijail(
|
||||||
// command-line parameter for an explanation about why the |log_failures|
|
// command-line parameter for an explanation about why the |log_failures|
|
||||||
// flag forces the use of .policy files (and the build-time alternative to
|
// flag forces the use of .policy files (and the build-time alternative to
|
||||||
// this run-time flag).
|
// this run-time flag).
|
||||||
let bpf_policy_file = seccomp_policy.with_extension("bpf");
|
let bpf_policy_file = config.seccomp_policy.with_extension("bpf");
|
||||||
if bpf_policy_file.exists() && !log_failures {
|
if bpf_policy_file.exists() && !config.log_failures {
|
||||||
j.parse_seccomp_program(&bpf_policy_file)
|
j.parse_seccomp_program(&bpf_policy_file)
|
||||||
.map_err(Error::DeviceJail)?;
|
.map_err(Error::DeviceJail)?;
|
||||||
} else {
|
} else {
|
||||||
|
@ -344,15 +356,26 @@ fn create_base_minijail(
|
||||||
// which will correctly kill the entire device process if a worker
|
// which will correctly kill the entire device process if a worker
|
||||||
// thread commits a seccomp violation.
|
// thread commits a seccomp violation.
|
||||||
j.set_seccomp_filter_tsync();
|
j.set_seccomp_filter_tsync();
|
||||||
if log_failures {
|
if config.log_failures {
|
||||||
j.log_seccomp_filter_failures();
|
j.log_seccomp_filter_failures();
|
||||||
}
|
}
|
||||||
j.parse_seccomp_filters(&seccomp_policy.with_extension("policy"))
|
j.parse_seccomp_filters(&config.seccomp_policy.with_extension("policy"))
|
||||||
.map_err(Error::DeviceJail)?;
|
.map_err(Error::DeviceJail)?;
|
||||||
}
|
}
|
||||||
j.use_seccomp_filter();
|
j.use_seccomp_filter();
|
||||||
// Don't do init setup.
|
// Don't do init setup.
|
||||||
j.run_as_init();
|
j.run_as_init();
|
||||||
|
}
|
||||||
|
|
||||||
|
// Create a new mount namespace with an empty root FS.
|
||||||
|
j.namespace_vfs();
|
||||||
|
j.enter_pivot_root(root).map_err(Error::DevicePivotRoot)?;
|
||||||
|
|
||||||
|
// Most devices don't need to open many fds.
|
||||||
|
let limit = if let Some(r) = r_limit { r } else { 1024u64 };
|
||||||
|
j.set_rlimit(libc::RLIMIT_NOFILE as i32, limit, limit)
|
||||||
|
.map_err(Error::SettingMaxOpenFiles)?;
|
||||||
|
|
||||||
Ok(j)
|
Ok(j)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -365,11 +388,14 @@ fn simple_jail(cfg: &Config, policy: &str) -> Result<Option<Minijail>> {
|
||||||
return Err(Error::PivotRootDoesntExist(pivot_root));
|
return Err(Error::PivotRootDoesntExist(pivot_root));
|
||||||
}
|
}
|
||||||
let policy_path: PathBuf = cfg.seccomp_policy_dir.join(policy);
|
let policy_path: PathBuf = cfg.seccomp_policy_dir.join(policy);
|
||||||
Ok(Some(create_base_minijail(
|
let config = SandboxConfig {
|
||||||
root_path,
|
limit_caps: true,
|
||||||
cfg.seccomp_log_failures,
|
log_failures: cfg.seccomp_log_failures,
|
||||||
&policy_path,
|
seccomp_policy: &policy_path,
|
||||||
)?))
|
uid_map: None,
|
||||||
|
gid_map: None,
|
||||||
|
};
|
||||||
|
Ok(Some(create_base_minijail(root_path, None, Some(&config))?))
|
||||||
} else {
|
} else {
|
||||||
Ok(None)
|
Ok(None)
|
||||||
}
|
}
|
||||||
|
@ -774,45 +800,20 @@ fn create_fs_device(
|
||||||
tag: &str,
|
tag: &str,
|
||||||
fs_cfg: virtio::fs::passthrough::Config,
|
fs_cfg: virtio::fs::passthrough::Config,
|
||||||
) -> DeviceResult {
|
) -> DeviceResult {
|
||||||
let mut j = Minijail::new().map_err(Error::DeviceJail)?;
|
|
||||||
|
|
||||||
if cfg.sandbox {
|
|
||||||
j.namespace_pids();
|
|
||||||
j.namespace_user();
|
|
||||||
j.namespace_user_disable_setgroups();
|
|
||||||
j.uidmap(uid_map).map_err(Error::SettingUidMap)?;
|
|
||||||
j.gidmap(gid_map).map_err(Error::SettingGidMap)?;
|
|
||||||
|
|
||||||
// Run in an empty network namespace.
|
|
||||||
j.namespace_net();
|
|
||||||
|
|
||||||
j.no_new_privs();
|
|
||||||
|
|
||||||
// Use TSYNC only for the side effect of it using SECCOMP_RET_TRAP, which will correctly kill
|
|
||||||
// the entire device process if a worker thread commits a seccomp violation.
|
|
||||||
let seccomp_policy = cfg.seccomp_policy_dir.join("fs_device");
|
|
||||||
j.set_seccomp_filter_tsync();
|
|
||||||
if cfg.seccomp_log_failures {
|
|
||||||
j.log_seccomp_filter_failures();
|
|
||||||
}
|
|
||||||
j.parse_seccomp_filters(&seccomp_policy)
|
|
||||||
.map_err(Error::DeviceJail)?;
|
|
||||||
j.use_seccomp_filter();
|
|
||||||
|
|
||||||
// Don't do init setup.
|
|
||||||
j.run_as_init();
|
|
||||||
}
|
|
||||||
|
|
||||||
// Create a new mount namespace with the source directory as the root. We need this even when
|
|
||||||
// sandboxing is disabled as the server relies on the host kernel to prevent path traversals
|
|
||||||
// from leaking out of the shared directory.
|
|
||||||
j.namespace_vfs();
|
|
||||||
j.enter_pivot_root(src).map_err(Error::DevicePivotRoot)?;
|
|
||||||
|
|
||||||
// The file server opens a lot of fds and needs a really high open file limit.
|
|
||||||
let max_open_files = get_max_open_files()?;
|
let max_open_files = get_max_open_files()?;
|
||||||
j.set_rlimit(libc::RLIMIT_NOFILE as i32, max_open_files, max_open_files)
|
let j = if cfg.sandbox {
|
||||||
.map_err(Error::SettingMaxOpenFiles)?;
|
let seccomp_policy = cfg.seccomp_policy_dir.join("fs_device");
|
||||||
|
let config = SandboxConfig {
|
||||||
|
limit_caps: false,
|
||||||
|
uid_map: Some(uid_map),
|
||||||
|
gid_map: Some(gid_map),
|
||||||
|
log_failures: cfg.seccomp_log_failures,
|
||||||
|
seccomp_policy: &seccomp_policy,
|
||||||
|
};
|
||||||
|
create_base_minijail(src, Some(max_open_files), Some(&config))?
|
||||||
|
} else {
|
||||||
|
create_base_minijail(src, Some(max_open_files), None)?
|
||||||
|
};
|
||||||
|
|
||||||
// TODO(chirantan): Use more than one worker once the kernel driver has been fixed to not panic
|
// TODO(chirantan): Use more than one worker once the kernel driver has been fixed to not panic
|
||||||
// when num_queues > 1.
|
// when num_queues > 1.
|
||||||
|
|
Loading…
Reference in a new issue