diff options
author | Zach Reizner <zachr@google.com> | 2019-08-13 11:20:14 -0700 |
---|---|---|
committer | Commit Bot <commit-bot@chromium.org> | 2019-10-10 02:09:13 +0000 |
commit | a8adff0ff14f66570a3aa86f6106b55081526be1 (patch) | |
tree | 515ed01d01828a8622bac5203d508da708db5d41 /devices/src/proxy.rs | |
parent | 0b6f02fea7716ec5752555ea44aafed214b58faa (diff) | |
download | crosvm-a8adff0ff14f66570a3aa86f6106b55081526be1.tar crosvm-a8adff0ff14f66570a3aa86f6106b55081526be1.tar.gz crosvm-a8adff0ff14f66570a3aa86f6106b55081526be1.tar.bz2 crosvm-a8adff0ff14f66570a3aa86f6106b55081526be1.tar.lz crosvm-a8adff0ff14f66570a3aa86f6106b55081526be1.tar.xz crosvm-a8adff0ff14f66570a3aa86f6106b55081526be1.tar.zst crosvm-a8adff0ff14f66570a3aa86f6106b55081526be1.zip |
devices: jail serial device
This change plumbs the jail throughout the arch specific device creation process. It also adds a custom callback support for the ProxyDevice so that the main process can interrupt the child serial process when it has incoming bytes. TEST=crosvm run BUG=None Change-Id: I6af7d2cb0acbba9bf42eaeeb294cee2bce4a1f36 Reviewed-on: https://chromium-review.googlesource.com/c/chromiumos/platform/crosvm/+/1752589 Reviewed-by: Dylan Reid <dgreid@chromium.org> Reviewed-by: Daniel Verkamp <dverkamp@chromium.org> Tested-by: kokoro <noreply+kokoro@google.com> Tested-by: Zach Reizner <zachr@chromium.org> Commit-Queue: Zach Reizner <zachr@chromium.org>
Diffstat (limited to 'devices/src/proxy.rs')
-rw-r--r-- | devices/src/proxy.rs | 43 |
1 files changed, 40 insertions, 3 deletions
diff --git a/devices/src/proxy.rs b/devices/src/proxy.rs index b97ccca..3770779 100644 --- a/devices/src/proxy.rs +++ b/devices/src/proxy.rs @@ -56,6 +56,7 @@ enum Command { data: [u8; 4], }, Shutdown, + RunUserCommand, } #[derive(MsgOnSocket)] @@ -65,7 +66,11 @@ enum CommandResult { ReadConfigResult(u32), } -fn child_proc(sock: UnixSeqpacket, device: &mut dyn BusDevice) { +fn child_proc<D: BusDevice, F: FnMut(&mut D)>( + sock: UnixSeqpacket, + device: &mut D, + mut user_command: F, +) { let mut running = true; let sock = MsgSocket::<CommandResult, Command>::new(sock); @@ -107,6 +112,10 @@ fn child_proc(sock: UnixSeqpacket, device: &mut dyn BusDevice) { running = false; sock.send(&CommandResult::Ok) } + Command::RunUserCommand => { + user_command(device); + sock.send(&CommandResult::Ok) + } }; if let Err(e) = res { error!("child device process failed send: {}", e); @@ -132,11 +141,34 @@ impl ProxyDevice { /// /// # Arguments /// * `device` - The device to isolate to another process. - /// * `keep_fds` - File descriptors that will be kept open in the child + /// * `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>( + device: D, + jail: &Minijail, + keep_fds: Vec<RawFd>, + ) -> Result<ProxyDevice> { + Self::new_with_user_command(device, jail, keep_fds, |_| {}) + } + + /// Similar to `ProxyDevice::new`, but adds an additional custom command to be run in the forked + /// process when `run_user_command` is called. + /// + /// Note that the custom command closure is run in the main thread of the child process, which + /// also services `BusDevice` requests. Therefore, do not run blocking calls in the closure + /// without a timeout, or you will block any VCPU which touches this device, and every other + /// thread which needs to lock this device's mutex. + /// + /// # 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. + /// * `user_command` - Closure to be run in the forked process. + pub fn new_with_user_command<D: BusDevice, F: FnMut(&mut D)>( mut device: D, jail: &Minijail, mut keep_fds: Vec<RawFd>, + user_command: F, ) -> Result<ProxyDevice> { let debug_label = device.debug_label(); let (child_sock, parent_sock) = UnixSeqpacket::pair().map_err(Error::Io)?; @@ -147,7 +179,7 @@ impl ProxyDevice { match jail.fork(Some(&keep_fds)).map_err(Error::ForkingJail)? { 0 => { device.on_sandboxed(); - child_proc(child_sock, &mut device); + child_proc(child_sock, &mut device, user_command); // 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 @@ -180,6 +212,11 @@ impl ProxyDevice { self.pid } + /// Runs the callback given in `new_with_custom_command` in the child device process. + pub fn run_user_command(&self) { + self.sync_send(Command::RunUserCommand); + } + fn sync_send(&self, cmd: Command) -> Option<CommandResult> { let res = self.sock.send(&cmd); if let Err(e) = res { |