summary refs log tree commit diff
path: root/devices/src/proxy.rs
diff options
context:
space:
mode:
authorDylan Reid <dgreid@chromium.org>2017-10-13 13:18:00 -0700
committerchrome-bot <chrome-bot@chromium.org>2017-10-25 05:52:43 -0700
commitb3bfbde1db2fb19ccb79a9da738108286d91f556 (patch)
tree827db5a5b76bc7d1eb7d513ba9c665b2f2e065a3 /devices/src/proxy.rs
parentd37aa9fab5dfa79e2859d86debd02ed11da932c9 (diff)
downloadcrosvm-b3bfbde1db2fb19ccb79a9da738108286d91f556.tar
crosvm-b3bfbde1db2fb19ccb79a9da738108286d91f556.tar.gz
crosvm-b3bfbde1db2fb19ccb79a9da738108286d91f556.tar.bz2
crosvm-b3bfbde1db2fb19ccb79a9da738108286d91f556.tar.lz
crosvm-b3bfbde1db2fb19ccb79a9da738108286d91f556.tar.xz
crosvm-b3bfbde1db2fb19ccb79a9da738108286d91f556.tar.zst
crosvm-b3bfbde1db2fb19ccb79a9da738108286d91f556.zip
Use minijail_fork
Using minijail_fork removes the need to manage user and pid namespace
explicitly in crosvm and removes some parent/child synchonization
requirements too.

Change-Id: I47f9d39527d0a3ccf625600e9bfc2cccc3cb27ca
Signed-off-by: Dylan Reid <dgreid@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/719443
Reviewed-by: Stephen Barber <smbarber@chromium.org>
Diffstat (limited to 'devices/src/proxy.rs')
-rw-r--r--devices/src/proxy.rs63
1 files changed, 45 insertions, 18 deletions
diff --git a/devices/src/proxy.rs b/devices/src/proxy.rs
index c55f5a3..ce5bea1 100644
--- a/devices/src/proxy.rs
+++ b/devices/src/proxy.rs
@@ -6,14 +6,33 @@
 
 use libc::pid_t;
 
-use std::io::{Error, ErrorKind, Result};
+use std::{self, fmt, io};
+use std::os::unix::io::{AsRawFd, RawFd};
 use std::os::unix::net::UnixDatagram;
+use std::process;
 use std::time::Duration;
 
 use byteorder::{NativeEndian, ByteOrder};
 
 use BusDevice;
-use sys_util::{clone_process, CloneNamespace};
+use io_jail::{self, Minijail};
+
+/// Errors for proxy devices.
+#[derive(Debug)]
+pub enum Error {
+    ForkingJail(io_jail::Error),
+    Io(io::Error),
+}
+pub type Result<T> = std::result::Result<T, Error>;
+
+impl fmt::Display for Error {
+    fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
+        match self {
+            &Error::ForkingJail(_) => write!(f, "Failed to fork jail process"),
+            &Error::Io(ref e) => write!(f, "IO error configuring proxy device {}.", e),
+        }
+    }
+}
 
 const SOCKET_TIMEOUT_MS: u64 = 2000;
 const MSG_SIZE: usize = 24;
@@ -85,23 +104,31 @@ impl ProxyDevice {
     ///
     /// # Arguments
     /// * `device` - The device to isolate to another process.
-    /// * `post_clone_cb` - Called after forking the child process, passed the child end of the pipe
-    /// that must be kept open.
-    pub fn new<D: BusDevice, F>(mut device: D, post_clone_cb: F) -> Result<ProxyDevice>
-        where F: FnOnce(&UnixDatagram)
+    /// * `keep_fds` - File descriptors that will be kept open in the child
+    pub fn new<D: BusDevice>(mut device: D, jail: &Minijail, mut keep_fds: Vec<RawFd>)
+            -> Result<ProxyDevice>
     {
-        let (child_sock, parent_sock) = UnixDatagram::pair()?;
-
-        let pid = clone_process(CloneNamespace::NewUserPid, move || {
-            post_clone_cb(&child_sock);
-            child_proc(child_sock, &mut device);
-        })
-                .map_err(|e| Error::new(ErrorKind::Other, format!("{:?}", e)))?;
+        let (child_sock, parent_sock) = UnixDatagram::pair().map_err(Error::Io)?;
+
+        keep_fds.push(child_sock.as_raw_fd());
+        // Forking here is safe as long as the program is still single threaded.
+        let pid = unsafe {
+            match jail.fork(Some(&keep_fds)).map_err(Error::ForkingJail)? {
+                0 => {
+                    child_proc(child_sock, &mut device);
+                    // ! Never returns
+                    process::exit(0);
+                },
+                p => p,
+            }
+        };
 
         parent_sock
-            .set_write_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))?;
+            .set_write_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
+            .map_err(Error::Io)?;
         parent_sock
-            .set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))?;
+            .set_read_timeout(Some(Duration::from_millis(SOCKET_TIMEOUT_MS)))
+            .map_err(Error::Io)?;
         Ok(ProxyDevice {
                sock: parent_sock,
                pid: pid,
@@ -118,12 +145,12 @@ impl ProxyDevice {
         NativeEndian::write_u32(&mut buf[4..], len);
         NativeEndian::write_u64(&mut buf[8..], offset);
         buf[16..16 + data.len()].clone_from_slice(data);
-        handle_eintr!(self.sock.send(&buf)).map(|_| ())
+        handle_eintr!(self.sock.send(&buf)).map(|_| ()).map_err(Error::Io)
     }
 
     fn recv_resp(&self, data: &mut [u8]) -> Result<()> {
         let mut buf = [0; MSG_SIZE];
-        handle_eintr!(self.sock.recv(&mut buf))?;
+        handle_eintr!(self.sock.recv(&mut buf)).map_err(Error::Io)?;
         let len = data.len();
         data.clone_from_slice(&buf[16..16 + len]);
         Ok(())
@@ -131,7 +158,7 @@ impl ProxyDevice {
 
     fn wait(&self) -> Result<()> {
         let mut buf = [0; MSG_SIZE];
-        handle_eintr!(self.sock.recv(&mut buf)).map(|_| ())
+        handle_eintr!(self.sock.recv(&mut buf)).map(|_| ()).map_err(Error::Io)
     }
 }