diff options
author | Alyssa Ross <hi@alyssa.is> | 2020-02-01 16:09:37 +0000 |
---|---|---|
committer | Alyssa Ross <hi@alyssa.is> | 2020-06-15 09:36:00 +0000 |
commit | 1a522613c469cbab90f7fa615cf359c7b55676ca (patch) | |
tree | 7470c2017e4ce3697ab475c19e40852dff4a1292 /devices | |
parent | 3e6aa18b5564fd0190bb4618b14a5de5653b0731 (diff) | |
download | crosvm-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.rs | 128 |
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 { |