diff options
-rw-r--r-- | Cargo.toml | 7 | ||||
-rw-r--r-- | src/argument.rs | 25 | ||||
-rw-r--r-- | src/crosvm.rs | 156 | ||||
-rw-r--r-- | src/main.rs | 165 | ||||
-rw-r--r-- | src/plugin/mod.rs | 4 |
5 files changed, 196 insertions, 161 deletions
diff --git a/Cargo.toml b/Cargo.toml index eda21cf..d899031 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,13 @@ version = "0.1.0" authors = ["The Chromium OS Authors"] edition = "2018" +[lib] +path = "src/crosvm.rs" + +[[bin]] +name = "crosvm" +path = "src/main.rs" + [profile.release] panic = 'abort' overflow-checks = true diff --git a/src/argument.rs b/src/argument.rs index 7cb56d6..7106f8b 100644 --- a/src/argument.rs +++ b/src/argument.rs @@ -7,7 +7,9 @@ //! # Example //! //! ``` -//! const ARGUMENTS: &'static [Argument] = &[ +//! # use crosvm::argument::{Argument, Error, print_help, set_arguments}; +//! # let args: std::slice::Iter<String> = [].iter(); +//! let arguments = &[ //! Argument::positional("FILES", "files to operate on"), //! Argument::short_value('p', "program", "PROGRAM", "Program to apply to each file"), //! Argument::short_value('c', "cpus", "N", "Number of CPUs to use. (default: 1)"), @@ -15,7 +17,7 @@ //! Argument::short_flag('h', "help", "Print help message."), //! ]; //! -//! let match_res = set_arguments(args, ARGUMENTS, |name, value| { +//! let match_res = set_arguments(args, arguments, |name, value| { //! match name { //! "" => println!("positional arg! {}", value.unwrap()), //! "program" => println!("gonna use program {}", value.unwrap()), @@ -31,11 +33,12 @@ //! "help" => return Err(Error::PrintHelp), //! _ => unreachable!(), //! } -//! } +//! unreachable!(); +//! }); //! //! match match_res { //! Ok(_) => println!("running with settings"), -//! Err(Error::PrintHelp) => print_help("best_program", "FILES", ARGUMENTS), +//! Err(Error::PrintHelp) => print_help("best_program", "FILES", arguments), //! Err(e) => println!("{}", e), //! } //! ``` @@ -93,28 +96,32 @@ pub type Result<T> = result::Result<T, Error>; /// To indicate a flag style argument: /// /// ``` -/// Argument::short_flag('f', "flag", "enable awesome mode") +/// # use crosvm::argument::Argument; +/// Argument::short_flag('f', "flag", "enable awesome mode"); /// ``` /// /// To indicate a parameter style argument that expects a value: /// /// ``` +/// # use crosvm::argument::Argument; /// // "VALUE" and "NETMASK" are placeholder values displayed in the help message for these /// // arguments. -/// Argument::short_value('v', "val", "VALUE", "how much do you value this usage information") -/// Argument::value("netmask", "NETMASK", "hides your netface") +/// Argument::short_value('v', "val", "VALUE", "how much do you value this usage information"); +/// Argument::value("netmask", "NETMASK", "hides your netface"); /// ``` /// /// To indicate an argument with no short version: /// /// ``` -/// Argument::flag("verbose", "this option is hard to type quickly") +/// # use crosvm::argument::Argument; +/// Argument::flag("verbose", "this option is hard to type quickly"); /// ``` /// /// To indicate a positional argument: /// /// ``` -/// Argument::positional("VALUES", "these are positional arguments") +/// # use crosvm::argument::Argument; +/// Argument::positional("VALUES", "these are positional arguments"); /// ``` #[derive(Default)] pub struct Argument { diff --git a/src/crosvm.rs b/src/crosvm.rs new file mode 100644 index 0000000..4e820c9 --- /dev/null +++ b/src/crosvm.rs @@ -0,0 +1,156 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//! The root level module that includes the config and aggregate of the submodules for running said +//! configs. + +pub mod argument; +pub mod linux; +#[cfg(feature = "plugin")] +pub mod plugin; + +use std::collections::BTreeMap; +use std::net; +use std::os::unix::io::RawFd; +use std::path::PathBuf; + +use devices::SerialParameters; + +static SECCOMP_POLICY_DIR: &'static str = "/usr/share/policy/crosvm"; + +/// Indicates the location and kind of executable kernel for a VM. +#[derive(Debug)] +pub enum Executable { + /// An executable intended to be run as a BIOS directly. + Bios(PathBuf), + /// A elf linux kernel, loaded and executed by crosvm. + Kernel(PathBuf), + /// Path to a plugin executable that is forked by crosvm. + Plugin(PathBuf), +} + +pub struct DiskOption { + pub path: PathBuf, + pub read_only: bool, +} + +/// A bind mount for directories in the plugin process. +pub struct BindMount { + pub src: PathBuf, + pub dst: PathBuf, + pub writable: bool, +} + +/// A mapping of linux group IDs for the plugin process. +pub struct GidMap { + pub inner: libc::gid_t, + pub outer: libc::gid_t, + pub count: u32, +} + +const DEFAULT_TOUCH_DEVICE_WIDTH: u32 = 800; +const DEFAULT_TOUCH_DEVICE_HEIGHT: u32 = 1280; + +pub struct TouchDeviceOption { + pub path: PathBuf, + pub width: u32, + pub height: u32, +} + +impl TouchDeviceOption { + pub fn new(path: PathBuf) -> TouchDeviceOption { + TouchDeviceOption { + path, + width: DEFAULT_TOUCH_DEVICE_WIDTH, + height: DEFAULT_TOUCH_DEVICE_HEIGHT, + } + } +} + +/// Aggregate of all configurable options for a running VM. +pub struct Config { + pub vcpu_count: Option<u32>, + pub vcpu_affinity: Vec<usize>, + pub memory: Option<usize>, + pub executable_path: Option<Executable>, + pub android_fstab: Option<PathBuf>, + pub initrd_path: Option<PathBuf>, + pub params: Vec<String>, + pub socket_path: Option<PathBuf>, + pub plugin_root: Option<PathBuf>, + pub plugin_mounts: Vec<BindMount>, + pub plugin_gid_maps: Vec<GidMap>, + pub disks: Vec<DiskOption>, + pub pmem_devices: Vec<DiskOption>, + pub host_ip: Option<net::Ipv4Addr>, + pub netmask: Option<net::Ipv4Addr>, + pub mac_address: Option<net_util::MacAddress>, + pub vhost_net: bool, + pub tap_fd: Vec<RawFd>, + pub cid: Option<u64>, + pub wayland_socket_path: Option<PathBuf>, + pub wayland_dmabuf: bool, + pub shared_dirs: Vec<(PathBuf, String)>, + pub sandbox: bool, + pub seccomp_policy_dir: PathBuf, + pub seccomp_log_failures: bool, + pub gpu: bool, + pub software_tpm: bool, + pub cras_audio: bool, + pub cras_capture: bool, + pub null_audio: bool, + pub serial_parameters: BTreeMap<u8, SerialParameters>, + pub syslog_tag: Option<String>, + pub virtio_single_touch: Option<TouchDeviceOption>, + pub virtio_trackpad: Option<TouchDeviceOption>, + pub virtio_mouse: Option<PathBuf>, + pub virtio_keyboard: Option<PathBuf>, + pub virtio_input_evdevs: Vec<PathBuf>, + pub split_irqchip: bool, +} + +impl Default for Config { + fn default() -> Config { + Config { + vcpu_count: None, + vcpu_affinity: Vec::new(), + memory: None, + executable_path: None, + android_fstab: None, + initrd_path: None, + params: Vec::new(), + socket_path: None, + plugin_root: None, + plugin_mounts: Vec::new(), + plugin_gid_maps: Vec::new(), + disks: Vec::new(), + pmem_devices: Vec::new(), + host_ip: None, + netmask: None, + mac_address: None, + vhost_net: false, + tap_fd: Vec::new(), + cid: None, + gpu: false, + software_tpm: false, + wayland_socket_path: None, + wayland_dmabuf: false, + shared_dirs: Vec::new(), + sandbox: !cfg!(feature = "default-no-sandbox"), + seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR), + seccomp_log_failures: false, + cras_audio: false, + cras_capture: false, + null_audio: false, + serial_parameters: BTreeMap::new(), + syslog_tag: None, + virtio_single_touch: None, + virtio_trackpad: None, + virtio_mouse: None, + virtio_keyboard: None, + virtio_input_evdevs: Vec::new(), + split_irqchip: false, + } + } +} diff --git a/src/main.rs b/src/main.rs index 78dfbf2..1d18c3b 100644 --- a/src/main.rs +++ b/src/main.rs @@ -4,16 +4,10 @@ //! Runs a virtual machine under KVM -pub mod argument; -pub mod linux; pub mod panic_hook; -#[cfg(feature = "plugin")] -pub mod plugin; -use std::collections::BTreeMap; use std::fmt; use std::fs::{File, OpenOptions}; -use std::net; use std::num::ParseIntError; use std::os::unix::io::{FromRawFd, RawFd}; use std::path::{Path, PathBuf}; @@ -21,6 +15,10 @@ use std::string::String; use std::thread::sleep; use std::time::Duration; +use crosvm::{ + argument::{self, print_help, set_arguments, Argument}, + linux, BindMount, Config, DiskOption, Executable, GidMap, TouchDeviceOption, +}; use devices::{SerialParameters, SerialType}; use msg_socket::{MsgReceiver, MsgSender, MsgSocket}; use qcow::QcowFile; @@ -33,55 +31,6 @@ use vm_control::{ VmControlRequestSocket, VmRequest, VmResponse, USB_CONTROL_MAX_PORTS, }; -use crate::argument::{print_help, set_arguments, Argument}; - -static SECCOMP_POLICY_DIR: &'static str = "/usr/share/policy/crosvm"; - -struct DiskOption { - path: PathBuf, - read_only: bool, -} - -#[allow(dead_code)] -struct BindMount { - src: PathBuf, - dst: PathBuf, - writable: bool, -} - -#[allow(dead_code)] -struct GidMap { - inner: libc::gid_t, - outer: libc::gid_t, - count: u32, -} - -const DEFAULT_TOUCH_DEVICE_WIDTH: u32 = 800; -const DEFAULT_TOUCH_DEVICE_HEIGHT: u32 = 1280; - -struct TouchDeviceOption { - path: PathBuf, - width: u32, - height: u32, -} - -impl TouchDeviceOption { - fn new(path: PathBuf) -> TouchDeviceOption { - TouchDeviceOption { - path, - width: DEFAULT_TOUCH_DEVICE_WIDTH, - height: DEFAULT_TOUCH_DEVICE_HEIGHT, - } - } -} - -#[derive(Debug)] -pub enum Executable { - Bios(PathBuf), - Kernel(PathBuf), - Plugin(PathBuf), -} - fn executable_is_plugin(executable: &Option<Executable>) -> bool { match executable { Some(Executable::Plugin(_)) => true, @@ -89,92 +38,6 @@ fn executable_is_plugin(executable: &Option<Executable>) -> bool { } } -pub struct Config { - vcpu_count: Option<u32>, - vcpu_affinity: Vec<usize>, - memory: Option<usize>, - executable_path: Option<Executable>, - android_fstab: Option<PathBuf>, - initrd_path: Option<PathBuf>, - params: Vec<String>, - socket_path: Option<PathBuf>, - plugin_root: Option<PathBuf>, - plugin_mounts: Vec<BindMount>, - plugin_gid_maps: Vec<GidMap>, - disks: Vec<DiskOption>, - pmem_devices: Vec<DiskOption>, - host_ip: Option<net::Ipv4Addr>, - netmask: Option<net::Ipv4Addr>, - mac_address: Option<net_util::MacAddress>, - vhost_net: bool, - tap_fd: Vec<RawFd>, - cid: Option<u64>, - wayland_socket_path: Option<PathBuf>, - wayland_dmabuf: bool, - shared_dirs: Vec<(PathBuf, String)>, - sandbox: bool, - seccomp_policy_dir: PathBuf, - seccomp_log_failures: bool, - gpu: bool, - software_tpm: bool, - cras_audio: bool, - cras_capture: bool, - null_audio: bool, - serial_parameters: BTreeMap<u8, SerialParameters>, - syslog_tag: Option<String>, - virtio_single_touch: Option<TouchDeviceOption>, - virtio_trackpad: Option<TouchDeviceOption>, - virtio_mouse: Option<PathBuf>, - virtio_keyboard: Option<PathBuf>, - virtio_input_evdevs: Vec<PathBuf>, - split_irqchip: bool, -} - -impl Default for Config { - fn default() -> Config { - Config { - vcpu_count: None, - vcpu_affinity: Vec::new(), - memory: None, - executable_path: None, - android_fstab: None, - initrd_path: None, - params: Vec::new(), - socket_path: None, - plugin_root: None, - plugin_mounts: Vec::new(), - plugin_gid_maps: Vec::new(), - disks: Vec::new(), - pmem_devices: Vec::new(), - host_ip: None, - netmask: None, - mac_address: None, - vhost_net: false, - tap_fd: Vec::new(), - cid: None, - gpu: false, - software_tpm: false, - wayland_socket_path: None, - wayland_dmabuf: false, - shared_dirs: Vec::new(), - sandbox: !cfg!(feature = "default-no-sandbox"), - seccomp_policy_dir: PathBuf::from(SECCOMP_POLICY_DIR), - seccomp_log_failures: false, - cras_audio: false, - cras_capture: false, - null_audio: false, - serial_parameters: BTreeMap::new(), - syslog_tag: None, - virtio_single_touch: None, - virtio_trackpad: None, - virtio_mouse: None, - virtio_keyboard: None, - virtio_input_evdevs: Vec::new(), - split_irqchip: false, - } - } -} - // Wait for all children to exit. Return true if they have all exited, false // otherwise. fn wait_all_children() -> bool { @@ -939,16 +802,18 @@ fn run_vm(args: std::env::Args) -> std::result::Result<(), ()> { match match_res { #[cfg(feature = "plugin")] - Ok(()) if executable_is_plugin(&cfg.executable_path) => match plugin::run_config(cfg) { - Ok(_) => { - info!("crosvm and plugin have exited normally"); - Ok(()) - } - Err(e) => { - error!("{}", e); - Err(()) + Ok(()) if executable_is_plugin(&cfg.executable_path) => { + match crosvm::plugin::run_config(cfg) { + Ok(_) => { + info!("crosvm and plugin have exited normally"); + Ok(()) + } + Err(e) => { + error!("{}", e); + Err(()) + } } - }, + } Ok(()) => match linux::run_config(cfg) { Ok(_) => { info!("crosvm has exited normally"); diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs index 3b6d82b..2680684 100644 --- a/src/plugin/mod.rs +++ b/src/plugin/mod.rs @@ -322,9 +322,9 @@ fn create_plugin_jail(root: &Path, log_failures: bool, seccomp_policy: &Path) -> /// These variant methods must be done by matching the variant to the expected type for that method. /// For example, getting the dirty log from a `Memory` object starting with an ID: /// -/// ``` +/// ```ignore /// match objects.get(&request_id) { -/// Some(&PluginObject::Memory { slot, length }) => vm.get_dirty_log(slot, &mut dirty_log[..]) +/// Some(&PluginObject::Memory { slot, length }) => vm.get_dirty_log(slot, &mut dirty_log[..]), /// _ => return Err(SysError::new(ENOENT)), /// } /// ``` |