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 /arch | |
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 'arch')
-rw-r--r-- | arch/src/lib.rs | 68 |
1 files changed, 52 insertions, 16 deletions
diff --git a/arch/src/lib.rs b/arch/src/lib.rs index 28f1168..45ed247 100644 --- a/arch/src/lib.rs +++ b/arch/src/lib.rs @@ -16,13 +16,13 @@ use std::sync::Arc; use devices::virtio::VirtioDevice; use devices::{ Bus, BusDevice, BusError, PciDevice, PciDeviceError, PciInterruptPin, PciRoot, ProxyDevice, - Serial, SerialParameters, DEFAULT_SERIAL_PARAMS, SERIAL_ADDR, + SerialInput, SerialParameters, DEFAULT_SERIAL_PARAMS, SERIAL_ADDR, }; use io_jail::Minijail; use kvm::{IoeventAddress, Kvm, Vcpu, Vm}; use resources::SystemAllocator; use sync::Mutex; -use sys_util::{syslog, EventFd, GuestAddress, GuestMemory, GuestMemoryError}; +use sys_util::{pipe, poll_in, syslog, warn, EventFd, GuestAddress, GuestMemory, GuestMemoryError}; pub enum VmImage { Kernel(File), @@ -47,7 +47,7 @@ pub struct RunnableLinuxVm { pub vm: Vm, pub kvm: Kvm, pub resources: SystemAllocator, - pub stdio_serial: Option<Arc<Mutex<Serial>>>, + pub stdio_serial: Option<SerialInput>, pub exit_evt: EventFd, pub vcpus: Vec<Vcpu>, pub vcpu_affinity: Vec<usize>, @@ -80,6 +80,7 @@ pub trait LinuxArch { components: VmComponents, split_irqchip: bool, serial_parameters: &BTreeMap<u8, SerialParameters>, + serial_jail: Option<Minijail>, create_devices: F, ) -> Result<RunnableLinuxVm, Self::Error> where @@ -103,7 +104,9 @@ pub enum DeviceRegistrationError { AllocateIrq, /// Could not create the mmio device to wrap a VirtioDevice. CreateMmioDevice(sys_util::Error), - // Unable to create serial device from serial parameters + // Unable to create a pipe. + CreatePipe(sys_util::Error), + // Unable to create serial device from serial parameters CreateSerialDevice(devices::SerialError), /// Could not create an event fd. EventFdCreate(sys_util::Error), @@ -134,6 +137,7 @@ impl Display for DeviceRegistrationError { AllocateDeviceAddrs(e) => write!(f, "Allocating device addresses: {}", e), AllocateIrq => write!(f, "Allocating IRQ number"), CreateMmioDevice(e) => write!(f, "failed to create mmio device: {}", e), + CreatePipe(e) => write!(f, "failed to create pipe: {}", e), CreateSerialDevice(e) => write!(f, "failed to create serial device: {}", e), Cmdline(e) => write!(f, "unable to add device to kernel command line: {}", e), EventFdCreate(e) => write!(f, "failed to create eventfd: {}", e), @@ -243,7 +247,8 @@ pub fn add_serial_devices( com_evt_1_3: &EventFd, com_evt_2_4: &EventFd, serial_parameters: &BTreeMap<u8, SerialParameters>, -) -> Result<(Option<u8>, Option<Arc<Mutex<Serial>>>), DeviceRegistrationError> { + serial_jail: Option<Minijail>, +) -> Result<(Option<u8>, Option<SerialInput>), DeviceRegistrationError> { let mut stdio_serial_num = None; let mut stdio_serial = None; @@ -260,21 +265,52 @@ pub fn add_serial_devices( .get(&(x + 1)) .unwrap_or(&DEFAULT_SERIAL_PARAMS[x as usize]); - let com = Arc::new(Mutex::new( - param - .create_serial_device(&com_evt) - .map_err(DeviceRegistrationError::CreateSerialDevice)?, - )); - io_bus - .insert(com.clone(), SERIAL_ADDR[x as usize], 0x8, false) - .unwrap(); - if param.console { stdio_serial_num = Some(x + 1); } - if param.stdin { - stdio_serial = Some(com.clone()); + let mut preserved_fds = Vec::new(); + let com = param + .create_serial_device(&com_evt, &mut preserved_fds) + .map_err(DeviceRegistrationError::CreateSerialDevice)?; + + match serial_jail.as_ref() { + Some(jail) => { + let (rx, tx) = pipe(true).map_err(DeviceRegistrationError::CreatePipe)?; + preserved_fds.push(rx.as_raw_fd()); + let com = Arc::new(Mutex::new( + ProxyDevice::new_with_user_command(com, &jail, preserved_fds, move |serial| { + let mut rx_buf = [0u8; 32]; + // This loop may end up stealing bytes from future user callbacks, so we + // check to make sure the pipe is readable so as not to block the proxy + // device's loop. + while poll_in(&rx) { + if let Ok(count) = (&rx).read(&mut rx_buf) { + if let Err(e) = serial.queue_input_bytes(&rx_buf[..count]) { + warn!("failed to queue bytes into serial device {}: {}", x, e); + } + } + } + }) + .map_err(DeviceRegistrationError::ProxyDeviceCreation)?, + )); + io_bus + .insert(com.clone(), SERIAL_ADDR[x as usize], 0x8, false) + .unwrap(); + if param.stdin { + stdio_serial = Some(SerialInput::new_remote(tx, com)); + } + } + None => { + let com = Arc::new(Mutex::new(com)); + io_bus + .insert(com.clone(), SERIAL_ADDR[x as usize], 0x8, false) + .unwrap(); + + if param.stdin { + stdio_serial = Some(SerialInput::new_local(com)); + } + } } } |