sirenia: Add Sandbox trait

This change converts Sandbox to a trait from an impl. This trait will be
implemented by different type of apps running in sandboxes in ManaTEE.

BUG=b:196186396
TEST=Unit tests.

Change-Id: I97db4828afcf50f061bd91977635c577a949bcb9
Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform2/+/3163768
Reviewed-by: Abhishek Bhardwaj <abhishekbh@chromium.org>
Reviewed-by: Allen Webb <allenwebb@google.com>
Tested-by: Abhishek Bhardwaj <abhishekbh@chromium.org>
Auto-Submit: Abhishek Bhardwaj <abhishekbh@chromium.org>
Commit-Queue: Abhishek Bhardwaj <abhishekbh@chromium.org>
diff --git a/sirenia/libsirenia/src/sandbox/mod.rs b/sirenia/libsirenia/src/sandbox/mod.rs
index 289b9a9..7de61ea 100644
--- a/sirenia/libsirenia/src/sandbox/mod.rs
+++ b/sirenia/libsirenia/src/sandbox/mod.rs
@@ -33,10 +33,22 @@
 
 const NEW_ROOT: &str = "/mnt/empty";
 
-/// An abstraction for the TEE application sandbox.
-pub struct Sandbox(minijail::Minijail);
+pub trait Sandbox {
+    /// Execute `cmd` with the specified arguments `args`. The specified file
+    /// descriptors are connected to stdio for the child process.
+    fn run(&mut self, cmd: &Path, args: &[&str], keep_fds: &[(RawFd, RawFd)]) -> Result<pid_t>;
 
-impl Sandbox {
+    fn run_raw(&mut self, cmd: RawFd, args: &[&str], keep_fds: &[(RawFd, RawFd)]) -> Result<pid_t>;
+
+    /// Wait until the child process completes. Non-zero return codes are
+    /// returned as an error.
+    fn wait_for_completion(&mut self) -> Result<()>;
+}
+
+/// An abstraction for the TEE application sandbox.
+pub struct MinijailSandbox(minijail::Minijail);
+
+impl MinijailSandbox {
     /// Setup default sandbox / namespaces
     pub fn new(seccomp_bpf_file: Option<&Path>) -> Result<Self> {
         // All child jails run in a new user namespace without any users mapped,
@@ -73,19 +85,19 @@
         j.set_rlimit(libc::RLIMIT_NOFILE as i32, limit, limit)
             .map_err(Error::SettingMaxOpenFiles)?;
 
-        Ok(Sandbox(j))
+        Ok(MinijailSandbox(j))
     }
 
     /// A version of the sandbox for use with tests because it doesn't require
     /// elevated privilege. It is also used for developer tools.
     pub fn passthrough() -> Result<Self> {
         let j = Minijail::new().map_err(Error::Jail)?;
-        Ok(Sandbox(j))
+        Ok(MinijailSandbox(j))
     }
+}
 
-    /// Execute `cmd` with the specified arguments `args`. The specified file
-    /// descriptors are connected to stdio for the child process.
-    pub fn run(&mut self, cmd: &Path, args: &[&str], keep_fds: &[(RawFd, RawFd)]) -> Result<pid_t> {
+impl Sandbox for MinijailSandbox {
+    fn run(&mut self, cmd: &Path, args: &[&str], keep_fds: &[(RawFd, RawFd)]) -> Result<pid_t> {
         let pid = match self
             .0
             .run_remap(cmd, keep_fds, args)
@@ -100,12 +112,7 @@
         Ok(pid)
     }
 
-    pub fn run_raw(
-        &mut self,
-        cmd: RawFd,
-        args: &[&str],
-        keep_fds: &[(RawFd, RawFd)],
-    ) -> Result<pid_t> {
+    fn run_raw(&mut self, cmd: RawFd, args: &[&str], keep_fds: &[(RawFd, RawFd)]) -> Result<pid_t> {
         let pid = match self
             .0
             .run_fd_remap(&cmd, keep_fds, args)
@@ -120,9 +127,7 @@
         Ok(pid)
     }
 
-    /// Wait until the child process completes. Non-zero return codes are
-    /// returned as an error.
-    pub fn wait_for_completion(&mut self) -> Result<()> {
+    fn wait_for_completion(&mut self) -> Result<()> {
         self.0.wait().map_err(Error::Wait)
     }
 }
@@ -138,7 +143,7 @@
 
     use crate::transport::{CROS_CONNECTION_ERR_FD, CROS_CONNECTION_R_FD, CROS_CONNECTION_W_FD};
 
-    fn do_test(mut s: Sandbox) {
+    fn do_test(s: &mut dyn Sandbox) {
         const STDOUT_TEST: &str = "stdout test";
         const STDERR_TEST: &str = "stderr test";
 
@@ -197,13 +202,13 @@
     #[test]
     #[ignore] // privileged operation.
     fn sandbox() {
-        let s = Sandbox::new(None).unwrap();
-        do_test(s);
+        let mut s = MinijailSandbox::new(None).unwrap();
+        do_test(&mut s);
     }
 
     #[test]
     fn sandbox_unpriviledged() {
-        let s = Sandbox::passthrough().unwrap();
-        do_test(s);
+        let mut s = MinijailSandbox::passthrough().unwrap();
+        do_test(&mut s);
     }
 }
diff --git a/sirenia/src/trichechus.rs b/sirenia/src/trichechus.rs
index a255719..1c60a7c 100644
--- a/sirenia/src/trichechus.rs
+++ b/sirenia/src/trichechus.rs
@@ -33,7 +33,7 @@
         syslog::{Syslog, SyslogReceiverMut, SYSLOG_PATH},
     },
     rpc::{self, ConnectionHandler, RpcDispatcher, TransportServer},
-    sandbox::{self, Sandbox},
+    sandbox::{self, MinijailSandbox, Sandbox},
     to_sys_util,
     transport::{
         self, create_transport_from_pipes, Transport, TransportType, CROS_CID,
@@ -92,7 +92,7 @@
 
 /* Holds the trichechus-relevant information for a TEEApp. */
 struct TeeApp {
-    sandbox: Sandbox,
+    sandbox: Box<dyn Sandbox>,
     app_info: AppManifestEntry,
 }
 
@@ -431,14 +431,20 @@
 ) -> StdResult<(), trichechus::Error> {
     let app_info = lookup_app_info(state, app_id)?.to_owned();
 
-    let sandbox = match &app_info.sandbox_type {
-        SandboxType::DeveloperEnvironment => Sandbox::passthrough(),
-        SandboxType::Container => Sandbox::new(None),
-        SandboxType::VirtualMachine => {
-            return Err(trichechus::Error::SandboxTypeNotImplemented);
-        }
-    }
-    .map_err(|err| trichechus::Error::from(format!("Failed create sandbox: {:?}", err)))?;
+    let sandbox =
+        match &app_info.sandbox_type {
+            SandboxType::DeveloperEnvironment => {
+                Box::new(MinijailSandbox::passthrough().map_err(|err| {
+                    trichechus::Error::from(format!("Failed create sandbox: {:?}", err))
+                })?)
+            }
+            SandboxType::Container => Box::new(MinijailSandbox::new(None).map_err(|err| {
+                trichechus::Error::from(format!("Failed create sandbox: {:?}", err))
+            })?),
+            SandboxType::VirtualMachine => {
+                return Err(trichechus::Error::SandboxTypeNotImplemented);
+            }
+        };
 
     // Do some additional checks to fail early and return the reason to the caller.
     match &app_info.exec_info {