crosvm: Allow JailConfig to not define path to policy dir

This allow us to use undefined policy dir path to enable loading
policies embedded at build time inside the binary.

BUG=b:235858187

Change-Id: I312f32ec7db9d625621707ae6330bd556dc55e93
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/3759335
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Dennis Kempin <denniskempin@google.com>
Commit-Queue: Zihan Chen <zihanchen@google.com>
diff --git a/src/crosvm/cmdline.rs b/src/crosvm/cmdline.rs
index a49fa0d..412d5cb 100644
--- a/src/crosvm/cmdline.rs
+++ b/src/crosvm/cmdline.rs
@@ -1534,7 +1534,7 @@
             if let Some(d) = cmd.seccomp_policy_dir {
                 cfg.jail_config
                     .get_or_insert_with(Default::default)
-                    .seccomp_policy_dir = d;
+                    .seccomp_policy_dir = Some(d);
             }
 
             if cmd.seccomp_log_failures {
diff --git a/src/crosvm/config.rs b/src/crosvm/config.rs
index 8c88c1a..95c208a 100644
--- a/src/crosvm/config.rs
+++ b/src/crosvm/config.rs
@@ -565,7 +565,7 @@
 pub struct JailConfig {
     pub pivot_root: PathBuf,
     #[cfg(unix)]
-    pub seccomp_policy_dir: PathBuf,
+    pub seccomp_policy_dir: Option<PathBuf>,
     pub seccomp_log_failures: bool,
 }
 
@@ -574,7 +574,7 @@
         JailConfig {
             pivot_root: PathBuf::from(option_env!("DEFAULT_PIVOT_ROOT").unwrap_or("/var/empty")),
             #[cfg(unix)]
-            seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR),
+            seccomp_policy_dir: Some(PathBuf::from(SECCOMP_POLICY_DIR)),
             seccomp_log_failures: false,
         }
     }
diff --git a/src/crosvm/plugin/mod.rs b/src/crosvm/plugin/mod.rs
index 0e39b36..5bc3b24 100644
--- a/src/crosvm/plugin/mod.rs
+++ b/src/crosvm/plugin/mod.rs
@@ -144,7 +144,11 @@
     }
 }
 
-fn create_plugin_jail(root: &Path, log_failures: bool, seccomp_policy: &Path) -> Result<Minijail> {
+fn create_plugin_jail(
+    root: &Path,
+    log_failures: bool,
+    seccomp_policy: Option<&Path>,
+) -> Result<Minijail> {
     // All child jails run in a new user namespace without any users mapped,
     // they run as nobody unless otherwise configured.
     let mut j = Minijail::new().context("failed to create jail")?;
@@ -171,7 +175,7 @@
     // command-line parameter for an explanation about why the |log_failures|
     // flag forces the use of .policy files (and the build-time alternative to
     // this run-time flag).
-    let bpf_policy_file = seccomp_policy.with_extension("bpf");
+    let bpf_policy_file = seccomp_policy.unwrap().with_extension("bpf");
     if bpf_policy_file.exists() && !log_failures {
         j.parse_seccomp_program(&bpf_policy_file)
             .context("failed to parse jail seccomp BPF program")?;
@@ -183,7 +187,7 @@
         if log_failures {
             j.log_seccomp_filter_failures();
         }
-        j.parse_seccomp_filters(&seccomp_policy.with_extension("policy"))
+        j.parse_seccomp_filters(&seccomp_policy.unwrap().with_extension("policy"))
             .context("failed to parse jail seccomp filter")?;
     }
     j.use_seccomp_filter();
@@ -561,9 +565,15 @@
             bail!("specified root directory is not a directory");
         }
 
-        let policy_path = jail_config.seccomp_policy_dir.join("plugin");
-        let mut jail =
-            create_plugin_jail(root_path, jail_config.seccomp_log_failures, &policy_path)?;
+        let policy_path = jail_config
+            .seccomp_policy_dir
+            .as_ref()
+            .map(|dir| dir.join("plugin"));
+        let mut jail = create_plugin_jail(
+            root_path,
+            jail_config.seccomp_log_failures,
+            policy_path.as_deref(),
+        )?;
 
         // Update gid map of the jail if caller provided supplemental groups.
         if !cfg.plugin_gid_maps.is_empty() {
diff --git a/src/crosvm/sys/unix/device_helpers.rs b/src/crosvm/sys/unix/device_helpers.rs
index 061e229..fdc8fb7 100644
--- a/src/crosvm/sys/unix/device_helpers.rs
+++ b/src/crosvm/sys/unix/device_helpers.rs
@@ -995,13 +995,17 @@
     let max_open_files =
         base::get_max_open_files().context("failed to get max number of open files")?;
     let j = if let Some(jail_config) = jail_config {
-        let seccomp_policy = jail_config.seccomp_policy_dir.join("fs_device");
+        let policy_path = jail_config
+            .seccomp_policy_dir
+            .as_ref()
+            .map(|dir| dir.join("fs_device"));
         let config = SandboxConfig {
             limit_caps: false,
             uid_map: Some(uid_map),
             gid_map: Some(gid_map),
             log_failures: jail_config.seccomp_log_failures,
-            seccomp_policy: &seccomp_policy,
+            seccomp_policy_path: policy_path.as_deref(),
+            seccomp_policy_name: "fs_device",
             // We want bind mounts from the parent namespaces to propagate into the fs device's
             // namespace.
             remount_mode: Some(libc::MS_SLAVE),
@@ -1035,13 +1039,17 @@
     let max_open_files =
         base::get_max_open_files().context("failed to get max number of open files")?;
     let (jail, root) = if let Some(jail_config) = jail_config {
-        let seccomp_policy = jail_config.seccomp_policy_dir.join("9p_device");
+        let policy_path = jail_config
+            .seccomp_policy_dir
+            .as_ref()
+            .map(|dir| dir.join("9p_device"));
         let config = SandboxConfig {
             limit_caps: false,
             uid_map: Some(uid_map),
             gid_map: Some(gid_map),
             log_failures: jail_config.seccomp_log_failures,
-            seccomp_policy: &seccomp_policy,
+            seccomp_policy_path: policy_path.as_deref(),
+            seccomp_policy_name: "9p_device",
             // We want bind mounts from the parent namespaces to propagate into the 9p server's
             // namespace.
             remount_mode: Some(libc::MS_SLAVE),
diff --git a/src/crosvm/sys/unix/jail_helpers.rs b/src/crosvm/sys/unix/jail_helpers.rs
index 777f404..631c436 100644
--- a/src/crosvm/sys/unix/jail_helpers.rs
+++ b/src/crosvm/sys/unix/jail_helpers.rs
@@ -2,7 +2,7 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
-use std::path::{Path, PathBuf};
+use std::path::Path;
 use std::str;
 
 use libc::{self, c_ulong, gid_t, uid_t};
@@ -13,10 +13,12 @@
 
 use crate::crosvm::config::JailConfig;
 
+#[allow(dead_code)]
 pub(super) struct SandboxConfig<'a> {
     pub(super) limit_caps: bool,
     pub(super) log_failures: bool,
-    pub(super) seccomp_policy: &'a Path,
+    pub(super) seccomp_policy_path: Option<&'a Path>,
+    pub(super) seccomp_policy_name: &'a str,
     pub(super) uid_map: Option<&'a str>,
     pub(super) gid_map: Option<&'a str>,
     pub(super) remount_mode: Option<c_ulong>,
@@ -69,7 +71,7 @@
         // command-line parameter for an explanation about why the |log_failures|
         // flag forces the use of .policy files (and the build-time alternative to
         // this run-time flag).
-        let bpf_policy_file = config.seccomp_policy.with_extension("bpf");
+        let bpf_policy_file = config.seccomp_policy_path.unwrap().with_extension("bpf");
         if bpf_policy_file.exists() && !config.log_failures {
             j.parse_seccomp_program(&bpf_policy_file)
                 .context("failed to parse precompiled seccomp policy")?;
@@ -81,7 +83,7 @@
             if config.log_failures {
                 j.log_seccomp_filter_failures();
             }
-            j.parse_seccomp_filters(&config.seccomp_policy.with_extension("policy"))
+            j.parse_seccomp_filters(&config.seccomp_policy_path.unwrap().with_extension("policy"))
                 .context("failed to parse seccomp policy")?;
         }
         j.use_seccomp_filter();
@@ -121,11 +123,15 @@
                 jail_config.pivot_root
             );
         }
-        let policy_path: PathBuf = jail_config.seccomp_policy_dir.join(policy);
+        let policy_path = jail_config
+            .seccomp_policy_dir
+            .as_ref()
+            .map(|dir| dir.join(policy));
         let config = SandboxConfig {
             limit_caps: true,
             log_failures: jail_config.seccomp_log_failures,
-            seccomp_policy: &policy_path,
+            seccomp_policy_path: policy_path.as_deref(),
+            seccomp_policy_name: policy,
             uid_map: None,
             gid_map: None,
             remount_mode: None,