summary refs log tree commit diff
path: root/devices
diff options
context:
space:
mode:
authorAlyssa Ross <hi@alyssa.is>2020-02-01 16:09:37 +0000
committerAlyssa Ross <hi@alyssa.is>2020-06-15 09:36:00 +0000
commit1a522613c469cbab90f7fa615cf359c7b55676ca (patch)
tree7470c2017e4ce3697ab475c19e40852dff4a1292 /devices
parent3e6aa18b5564fd0190bb4618b14a5de5653b0731 (diff)
downloadcrosvm-1a522613c469cbab90f7fa615cf359c7b55676ca.tar
crosvm-1a522613c469cbab90f7fa615cf359c7b55676ca.tar.gz
crosvm-1a522613c469cbab90f7fa615cf359c7b55676ca.tar.bz2
crosvm-1a522613c469cbab90f7fa615cf359c7b55676ca.tar.lz
crosvm-1a522613c469cbab90f7fa615cf359c7b55676ca.tar.xz
crosvm-1a522613c469cbab90f7fa615cf359c7b55676ca.tar.zst
crosvm-1a522613c469cbab90f7fa615cf359c7b55676ca.zip
devices: move jailing out of JailedDevice::new
Doing this in its own function, jail_device, which returns a simple record
struct (JailInfo), means that callers can do other things with the
jailed device than just configure a ProxyDevice.

This will make it possible to have a program that acts only as a jail
supervisor, and which forwards its socket to a CrosVM to be put into a
ProxyDevice in that process.
Diffstat (limited to 'devices')
-rw-r--r--devices/src/jailed.rs128
1 files changed, 78 insertions, 50 deletions
diff --git a/devices/src/jailed.rs b/devices/src/jailed.rs
index 69eb1fe..d3fa2cf 100644
--- a/devices/src/jailed.rs
+++ b/devices/src/jailed.rs
@@ -89,64 +89,92 @@ fn child_proc<D: BusDevice>(sock: UnixSeqpacket, device: &mut D) {
     }
 }
 
+pub struct JailInfo {
+    pid: pid_t,
+    sock: MsgSocket<Command, CommandResult>,
+    debug_label: String,
+}
+
+impl JailInfo {
+    pub fn pid(&self) -> pid_t {
+        self.pid
+    }
+
+    pub fn sock(&self) -> &MsgSocket<Command, CommandResult> {
+        &self.sock
+    }
+
+    pub fn debug_label(&self) -> &str {
+        self.debug_label.as_ref()
+    }
+}
+
+/// Takes the given device and isolates it into another process via fork before returning.
+///
+/// # Arguments
+/// * `device` - The device to isolate to another process.
+/// * `jail` - The jail to use for isolating the given device.
+/// * `keep_fds` - File descriptors that will be kept open in the child.
+pub fn jail_device<D: BusDevice>(
+    mut device: D,
+    jail: &Minijail,
+    mut keep_fds: Vec<RawFd>,
+) -> Result<JailInfo> {
+    let debug_label = device.debug_label();
+    let (child_sock, parent_sock) = UnixSeqpacket::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 => {
+                device.on_sandboxed();
+                child_proc(child_sock, &mut device);
+
+                // We're explicitly not using std::process::exit here to avoid the cleanup of
+                // stdout/stderr globals. This can cause cascading panics and SIGILL if a worker
+                // thread attempts to log to stderr after at_exit handlers have been run.
+                // TODO(crbug.com/992494): Remove this once device shutdown ordering is clearly
+                // defined.
+                //
+                // exit() is trivially safe.
+                // ! Never returns
+                libc::exit(0);
+            }
+            p => p,
+        }
+    };
+
+    parent_sock
+        .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)))
+        .map_err(Error::Io)?;
+    Ok(JailInfo {
+        sock: MsgSocket::<Command, CommandResult>::new(parent_sock),
+        pid,
+        debug_label,
+    })
+}
+
 pub struct JailedDevice {
     proxy: ProxyDevice,
     pid: pid_t,
 }
 
 impl JailedDevice {
-    /// Takes the given device and isolates it into another process via fork before returning.
-    ///
+    pub fn jail<D: BusDevice>(device: D, jail: &Minijail, keep_fds: Vec<RawFd>) -> Result<Self> {
+        jail_device(device, jail, keep_fds).map(Self::new)
+    }
+
     /// The forked process will automatically be terminated when this is dropped, so be sure to keep
     /// a reference.
-    ///
-    /// # Arguments
-    /// * `device` - The device to isolate to another process.
-    /// * `jail` - The jail to use for isolating the given device.
-    /// * `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<JailedDevice> {
-        let debug_label = device.debug_label();
-        let (child_sock, parent_sock) = UnixSeqpacket::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 => {
-                    device.on_sandboxed();
-                    child_proc(child_sock, &mut device);
-
-                    // We're explicitly not using std::process::exit here to avoid the cleanup of
-                    // stdout/stderr globals. This can cause cascading panics and SIGILL if a worker
-                    // thread attempts to log to stderr after at_exit handlers have been run.
-                    // TODO(crbug.com/992494): Remove this once device shutdown ordering is clearly
-                    // defined.
-                    //
-                    // exit() is trivially safe.
-                    // ! Never returns
-                    libc::exit(0);
-                }
-                p => p,
-            }
-        };
-
-        parent_sock
-            .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)))
-            .map_err(Error::Io)?;
-        Ok(JailedDevice {
-            proxy: ProxyDevice::new(
-                MsgSocket::<Command, CommandResult>::new(parent_sock),
-                debug_label,
-            ),
-            pid,
-        })
+    pub fn new(j: JailInfo) -> JailedDevice {
+        Self {
+            proxy: ProxyDevice::new(j.sock, j.debug_label),
+            pid: j.pid,
+        }
     }
 
     pub fn pid(&self) -> pid_t {