diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/argument.rs | 10 | ||||
-rw-r--r-- | src/crosvm.rs | 6 | ||||
-rw-r--r-- | src/linux.rs | 64 | ||||
-rw-r--r-- | src/main.rs | 145 | ||||
-rw-r--r-- | src/plugin/mod.rs | 6 | ||||
-rw-r--r-- | src/plugin/process.rs | 19 | ||||
-rw-r--r-- | src/plugin/vcpu.rs | 1 |
7 files changed, 175 insertions, 76 deletions
diff --git a/src/argument.rs b/src/argument.rs index 0d0e142..26950a9 100644 --- a/src/argument.rs +++ b/src/argument.rs @@ -292,14 +292,12 @@ where State::Positional } State::Value { name } => { - if arg.starts_with("-") { + if arg.starts_with('-') { arg_consumed = false; f(&name, None)?; - } else { - if let Err(e) = f(&name, Some(&arg)) { - arg_consumed = false; - f(&name, None).map_err(|_| e)?; - } + } else if let Err(e) = f(&name, Some(&arg)) { + arg_consumed = false; + f(&name, None).map_err(|_| e)?; } State::Top } diff --git a/src/crosvm.rs b/src/crosvm.rs index a55d2e4..49a08c0 100644 --- a/src/crosvm.rs +++ b/src/crosvm.rs @@ -16,11 +16,11 @@ use std::os::unix::io::RawFd; use std::path::{Path, PathBuf}; use std::str::FromStr; -use arch::Pstore; +use arch::{Pstore, SerialHardware, SerialParameters}; use devices::virtio::fs::passthrough; #[cfg(feature = "gpu")] use devices::virtio::gpu::GpuParameters; -use devices::{Ac97Parameters, SerialParameters}; +use devices::Ac97Parameters; use libc::{getegid, geteuid}; static SECCOMP_POLICY_DIR: &str = "/usr/share/policy/crosvm"; @@ -193,7 +193,7 @@ pub struct Config { pub display_window_keyboard: bool, pub display_window_mouse: bool, pub ac97_parameters: Vec<Ac97Parameters>, - pub serial_parameters: BTreeMap<u8, SerialParameters>, + pub serial_parameters: BTreeMap<(SerialHardware, u8), SerialParameters>, pub syslog_tag: Option<String>, pub virtio_single_touch: Option<TouchDeviceOption>, pub virtio_trackpad: Option<TouchDeviceOption>, diff --git a/src/linux.rs b/src/linux.rs index 9dbdb5c..e480a4c 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -2,7 +2,6 @@ // Use of this source code is governed by a BSD-style license that can be // found in the LICENSE file. -use std; use std::cmp::max; use std::convert::TryFrom; use std::error::Error as StdError; @@ -29,7 +28,7 @@ use libc::{self, c_int, gid_t, uid_t}; #[cfg(feature = "gpu")] use devices::virtio::EventDevice; -use devices::virtio::{self, VirtioDevice}; +use devices::virtio::{self, Console, VirtioDevice}; use devices::{ self, Ac97Backend, Ac97Dev, HostBackendDeviceProvider, PciDevice, VfioContainer, VfioDevice, VfioPciDevice, VirtioPciDevice, XhciController, @@ -50,7 +49,6 @@ use sys_util::{ Killable, MemoryMappingArena, PollContext, PollToken, Protection, ScopedEvent, SignalFd, Terminal, TimerFd, WatchingEvents, SIGRTMIN, }; -use vhost; use vm_control::{ BalloonControlCommand, BalloonControlRequestSocket, BalloonControlResponseSocket, BalloonControlResult, DiskControlCommand, DiskControlRequestSocket, DiskControlResponseSocket, @@ -61,7 +59,10 @@ use vm_control::{ }; use crate::{Config, DiskOption, Executable, SharedDir, SharedDirKind, TouchDeviceOption}; -use arch::{self, LinuxArch, RunnableLinuxVm, VirtioDeviceStub, VmComponents, VmImage}; +use arch::{ + self, LinuxArch, RunnableLinuxVm, SerialHardware, SerialParameters, VirtioDeviceStub, + VmComponents, VmImage, +}; #[cfg(any(target_arch = "arm", target_arch = "aarch64"))] use aarch64::AArch64 as Arch; @@ -82,6 +83,7 @@ pub enum Error { ChownTpmStorage(sys_util::Error), CloneEventFd(sys_util::Error), CreateAc97(devices::PciDeviceError), + CreateConsole(arch::serial::Error), CreateDiskError(disk::Error), CreateEventFd(sys_util::Error), CreatePollContext(sys_util::Error), @@ -166,6 +168,7 @@ impl Display for Error { ChownTpmStorage(e) => write!(f, "failed to chown tpm storage: {}", e), CloneEventFd(e) => write!(f, "failed to clone eventfd: {}", e), CreateAc97(e) => write!(f, "failed to create ac97 device: {}", e), + CreateConsole(e) => write!(f, "failed to create console device: {}", e), CreateDiskError(e) => write!(f, "failed to create virtual disk: {}", e), CreateEventFd(e) => write!(f, "failed to create eventfd: {}", e), CreatePollContext(e) => write!(f, "failed to create poll context: {}", e), @@ -816,7 +819,12 @@ fn create_fs_device( log_failures: cfg.seccomp_log_failures, seccomp_policy: &seccomp_policy, }; - create_base_minijail(src, Some(max_open_files), Some(&config))? + let mut jail = create_base_minijail(src, Some(max_open_files), Some(&config))?; + // We want bind mounts from the parent namespaces to propagate into the fs device's + // namespace. + jail.set_remount_mode(libc::MS_SLAVE); + + jail } else { create_base_minijail(src, Some(max_open_files), None)? }; @@ -885,7 +893,7 @@ fn create_pmem_device( .open(&disk.path) .map_err(|e| Error::Disk(disk.path.to_path_buf(), e))?; - let (disk_size, arena_size) = { + let arena_size = { let metadata = std::fs::metadata(&disk.path).map_err(|e| Error::Disk(disk.path.to_path_buf(), e))?; let disk_len = metadata.len(); @@ -900,12 +908,9 @@ fn create_pmem_device( } else { 0 }; - ( - disk_len, - disk_len - .checked_add(align_adjust) - .ok_or(Error::PmemDeviceImageTooBig)?, - ) + disk_len + .checked_add(align_adjust) + .ok_or(Error::PmemDeviceImageTooBig)? }; let protection = { @@ -919,11 +924,10 @@ fn create_pmem_device( let arena = { // Conversion from u64 to usize may fail on 32bit system. let arena_size = usize::try_from(arena_size).map_err(|_| Error::PmemDeviceImageTooBig)?; - let disk_size = usize::try_from(disk_size).map_err(|_| Error::PmemDeviceImageTooBig)?; let mut arena = MemoryMappingArena::new(arena_size).map_err(Error::ReservePmemMemory)?; arena - .add_fd_offset_protection(0, disk_size, &fd, 0, protection) + .add_fd_offset_protection(0, arena_size, &fd, 0, protection) .map_err(Error::ReservePmemMemory)?; arena }; @@ -963,6 +967,19 @@ fn create_pmem_device( }) } +fn create_console_device(cfg: &Config, param: &SerialParameters) -> DeviceResult { + let mut keep_fds = Vec::new(); + let evt = EventFd::new().map_err(Error::CreateEventFd)?; + let dev = param + .create_serial_device::<Console>(&evt, &mut keep_fds) + .map_err(Error::CreateConsole)?; + + Ok(VirtioDeviceStub { + dev: Box::new(dev), + jail: simple_jail(&cfg, "serial")?, // TODO(dverkamp): use a separate policy for console? + }) +} + // gpu_device_socket is not used when GPU support is disabled. #[cfg_attr(not(feature = "gpu"), allow(unused_variables))] fn create_virtio_devices( @@ -979,6 +996,15 @@ fn create_virtio_devices( ) -> DeviceResult<Vec<VirtioDeviceStub>> { let mut devs = Vec::new(); + for (_, param) in cfg + .serial_parameters + .iter() + .filter(|(_k, v)| v.hardware == SerialHardware::VirtioConsole) + { + let dev = create_console_device(cfg, param)?; + devs.push(dev); + } + for disk in &cfg.disks { let disk_device_socket = disk_device_sockets.remove(0); devs.push(create_block_device(cfg, disk, disk_device_socket)?); @@ -1398,7 +1424,7 @@ fn run_vcpu( // implementation accomplishes that. let _scoped_exit_evt = ScopedEvent::from(exit_evt); - if vcpu_affinity.len() != 0 { + if !vcpu_affinity.is_empty() { if let Err(e) = set_cpu_affinity(vcpu_affinity) { error!("Failed to set CPU affinity: {}", e); } @@ -1740,7 +1766,7 @@ fn run_control( } // Balance available memory between guest and host every second. - let mut balancemem_timer = TimerFd::new().map_err(Error::CreateTimerFd)?; + let balancemem_timer = TimerFd::new().map_err(Error::CreateTimerFd)?; if Path::new(LOWMEM_AVAILABLE).exists() { // Create timer request balloon stats every 1s. poll_ctx @@ -2024,7 +2050,7 @@ fn run_control( } } Err(e) => { - if let MsgError::BadRecvSize { actual: 0, .. } = e { + if let MsgError::RecvZero = e { vm_control_indices_to_remove.push(index); } else { error!("failed to recv VmRequest: {}", e); @@ -2040,7 +2066,7 @@ fn run_control( } } Err(e) => { - if let MsgError::BadRecvSize { actual: 0, .. } = e { + if let MsgError::RecvZero = e { vm_control_indices_to_remove.push(index); } else { error!("failed to recv VmMemoryControlRequest: {}", e); @@ -2056,7 +2082,7 @@ fn run_control( } } Err(e) => { - if let MsgError::BadRecvSize { actual: 0, .. } = e { + if let MsgError::RecvZero = e { vm_control_indices_to_remove.push(index); } else { error!("failed to recv VmIrqRequest: {}", e); diff --git a/src/main.rs b/src/main.rs index e33be66..7fd3eca 100644 --- a/src/main.rs +++ b/src/main.rs @@ -17,7 +17,7 @@ use std::string::String; use std::thread::sleep; use std::time::Duration; -use arch::Pstore; +use arch::{set_default_serial_parameters, Pstore, SerialHardware, SerialParameters, SerialType}; use audio_streams::StreamEffect; use crosvm::{ argument::{self, print_help, set_arguments, Argument}, @@ -25,7 +25,7 @@ use crosvm::{ }; #[cfg(feature = "gpu")] use devices::virtio::gpu::{GpuMode, GpuParameters}; -use devices::{Ac97Backend, Ac97Parameters, SerialParameters, SerialType}; +use devices::{Ac97Backend, Ac97Parameters}; use disk::QcowFile; use msg_socket::{MsgReceiver, MsgSender, MsgSocket}; use sys_util::{ @@ -74,7 +74,7 @@ fn parse_cpu_set(s: &str) -> argument::Result<Vec<usize>> { let mut cpuset = Vec::new(); for part in s.split(',') { let range: Vec<&str> = part.split('-').collect(); - if range.len() == 0 || range.len() > 2 { + if range.is_empty() || range.len() > 2 { return Err(argument::Error::InvalidValue { value: part.to_owned(), expected: String::from("invalid list syntax"), @@ -117,8 +117,8 @@ fn parse_gpu_options(s: Option<&str>) -> argument::Result<GpuParameters> { if let Some(s) = s { let opts = s - .split(",") - .map(|frag| frag.split("=")) + .split(',') + .map(|frag| frag.split('=')) .map(|mut kv| (kv.next().unwrap_or(""), kv.next().unwrap_or(""))); for (k, v) in opts { @@ -252,8 +252,8 @@ fn parse_ac97_options(s: &str) -> argument::Result<Ac97Parameters> { let mut ac97_params: Ac97Parameters = Default::default(); let opts = s - .split(",") - .map(|frag| frag.split("=")) + .split(',') + .map(|frag| frag.split('=')) .map(|mut kv| (kv.next().unwrap_or(""), kv.next().unwrap_or(""))); for (k, v) in opts { @@ -273,7 +273,7 @@ fn parse_ac97_options(s: &str) -> argument::Result<Ac97Parameters> { } "capture_effects" => { ac97_params.capture_effects = v - .split("|") + .split('|') .map(|val| { val.parse::<StreamEffect>() .map_err(|e| argument::Error::InvalidValue { @@ -298,19 +298,27 @@ fn parse_ac97_options(s: &str) -> argument::Result<Ac97Parameters> { fn parse_serial_options(s: &str) -> argument::Result<SerialParameters> { let mut serial_setting = SerialParameters { type_: SerialType::Sink, + hardware: SerialHardware::Serial, path: None, + input: None, num: 1, console: false, + earlycon: false, stdin: false, }; let opts = s - .split(",") - .map(|frag| frag.split("=")) + .split(',') + .map(|frag| frag.split('=')) .map(|mut kv| (kv.next().unwrap_or(""), kv.next().unwrap_or(""))); for (k, v) in opts { match k { + "hardware" => { + serial_setting.hardware = v + .parse::<SerialHardware>() + .map_err(|e| argument::Error::UnknownArgument(format!("{}", e)))? + } "type" => { serial_setting.type_ = v .parse::<SerialType>() @@ -336,12 +344,33 @@ fn parse_serial_options(s: &str) -> argument::Result<SerialParameters> { )) })? } + "earlycon" => { + serial_setting.earlycon = v.parse::<bool>().map_err(|e| { + argument::Error::Syntax(format!( + "serial device earlycon is not parseable: {}", + e, + )) + })? + } "stdin" => { serial_setting.stdin = v.parse::<bool>().map_err(|e| { argument::Error::Syntax(format!("serial device stdin is not parseable: {}", e)) - })? + })?; + if serial_setting.stdin && serial_setting.input.is_some() { + return Err(argument::Error::TooManyArguments( + "Cannot specify both stdin and input options".to_string(), + )); + } } "path" => serial_setting.path = Some(PathBuf::from(v)), + "input" => { + if serial_setting.stdin { + return Err(argument::Error::TooManyArguments( + "Cannot specify both stdin and input options".to_string(), + )); + } + serial_setting.input = Some(PathBuf::from(v)); + } _ => { return Err(argument::Error::UnknownArgument(format!( "serial parameter {}", @@ -355,7 +384,7 @@ fn parse_serial_options(s: &str) -> argument::Result<SerialParameters> { } fn parse_plugin_mount_option(value: &str) -> argument::Result<BindMount> { - let components: Vec<&str> = value.split(":").collect(); + let components: Vec<&str> = value.split(':').collect(); if components.is_empty() || components.len() > 3 || components[0].is_empty() { return Err(argument::Error::InvalidValue { value: value.to_owned(), @@ -402,7 +431,7 @@ fn parse_plugin_mount_option(value: &str) -> argument::Result<BindMount> { } fn parse_plugin_gid_map_option(value: &str) -> argument::Result<GidMap> { - let components: Vec<&str> = value.split(":").collect(); + let components: Vec<&str> = value.split(':').collect(); if components.is_empty() || components.len() > 3 || components[0].is_empty() { return Err(argument::Error::InvalidValue { value: value.to_owned(), @@ -501,7 +530,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: ) } "cpu-affinity" => { - if cfg.vcpu_affinity.len() != 0 { + if !cfg.vcpu_affinity.is_empty() { return Err(argument::Error::TooManyArguments( "`cpu-affinity` already given".to_owned(), )); @@ -532,10 +561,11 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: "serial" => { let serial_params = parse_serial_options(value.unwrap())?; let num = serial_params.num; - if cfg.serial_parameters.contains_key(&num) { + let key = (serial_params.hardware, num); + if cfg.serial_parameters.contains_key(&key) { return Err(argument::Error::TooManyArguments(format!( - "serial num {}", - num + "serial hardware {} num {}", + serial_params.hardware, num, ))); } @@ -543,8 +573,29 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: for params in cfg.serial_parameters.values() { if params.console { return Err(argument::Error::TooManyArguments(format!( - "serial device {} already set as console", - params.num + "{} device {} already set as console", + params.hardware, params.num, + ))); + } + } + } + + if serial_params.earlycon { + // Only SerialHardware::Serial supports earlycon= currently. + match serial_params.hardware { + SerialHardware::Serial => {} + _ => { + return Err(argument::Error::InvalidValue { + value: serial_params.hardware.to_string().to_owned(), + expected: String::from("earlycon not supported for hardware"), + }); + } + } + for params in cfg.serial_parameters.values() { + if params.earlycon { + return Err(argument::Error::TooManyArguments(format!( + "{} device {} already set as earlycon", + params.hardware, params.num, ))); } } @@ -553,13 +604,13 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: if serial_params.stdin { if let Some(previous_stdin) = cfg.serial_parameters.values().find(|sp| sp.stdin) { return Err(argument::Error::TooManyArguments(format!( - "serial device {} already connected to standard input", - previous_stdin.num + "{} device {} already connected to standard input", + previous_stdin.hardware, previous_stdin.num, ))); } } - cfg.serial_parameters.insert(num, serial_params); + cfg.serial_parameters.insert(key, serial_params); } "syslog-tag" => { if cfg.syslog_tag.is_some() { @@ -1030,7 +1081,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: let reader = BufReader::new(file); for l in reader.lines() { let line = l.unwrap(); - let trimmed_line = line.splitn(2, '#').nth(0).unwrap().trim(); + let trimmed_line = line.splitn(2, '#').next().unwrap().trim(); if !trimmed_line.is_empty() { let mount = parse_plugin_mount_option(trimmed_line)?; cfg.plugin_mounts.push(mount); @@ -1049,7 +1100,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: let reader = BufReader::new(file); for l in reader.lines() { let line = l.unwrap(); - let trimmed_line = line.splitn(2, '#').nth(0).unwrap().trim(); + let trimmed_line = line.splitn(2, '#').next().unwrap().trim(); if !trimmed_line.is_empty() { let map = parse_plugin_gid_map_option(trimmed_line)?; cfg.plugin_gid_maps.push(map); @@ -1084,7 +1135,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: "`single-touch` already given".to_owned(), )); } - let mut it = value.unwrap().split(":"); + let mut it = value.unwrap().split(':'); let mut single_touch_spec = TouchDeviceOption::new(PathBuf::from(it.next().unwrap().to_owned())); @@ -1102,7 +1153,7 @@ fn set_argument(cfg: &mut Config, name: &str, value: Option<&str>) -> argument:: "`trackpad` already given".to_owned(), )); } - let mut it = value.unwrap().split(":"); + let mut it = value.unwrap().split(':'); let mut trackpad_spec = TouchDeviceOption::new(PathBuf::from(it.next().unwrap().to_owned())); @@ -1214,6 +1265,7 @@ fn validate_arguments(cfg: &mut Config) -> std::result::Result<(), argument::Err } } } + set_default_serial_parameters(&mut cfg.serial_parameters); Ok(()) } @@ -1326,10 +1378,9 @@ Possible key values: effect value now is EchoCancellation or aec. "#, ), - Argument::value( "serial", - "type=TYPE,[num=NUM,path=PATH,console,stdin]", + "type=TYPE,[hardware=HW,num=NUM,path=PATH,input=PATH,console,earlycon,stdin]", "\ Comma separated key=value pairs for setting up serial devices. Can be given more than once. @@ -1339,16 +1390,26 @@ Possible key values: type=(stdout,syslog,sink,file) Where to route the serial device. + hardware=(serial,virtio-console) + Which type of serial hardware to emulate. Defaults to 8250 UART + (serial). + num=(1,2,3,4) Serial Device Number. If not provided, num will default to 1. path=PATH The path to the file to write to when type=file. + input=PATH + The path to the file to read from when not stdin. + console Use this serial device as the guest console. Can only be given once. Will default to first serial port if not provided. + earlycon + Use this serial device as the early console. Can only be given once. + stdin Direct standard input to this serial device. Can only be given once. Will default to first serial port if not provided. @@ -1738,7 +1799,7 @@ fn balloon_vms(mut args: std::env::Args) -> std::result::Result<(), ()> { println!("Set the balloon size of the crosvm instance to `SIZE` bytes."); return Err(()); } - let num_bytes = match args.nth(0).unwrap().parse::<u64>() { + let num_bytes = match args.next().unwrap().parse::<u64>() { Ok(n) => n, Err(_) => { error!("Failed to parse number of bytes"); @@ -1750,6 +1811,19 @@ fn balloon_vms(mut args: std::env::Args) -> std::result::Result<(), ()> { vms_request(&VmRequest::BalloonCommand(command), args) } +fn balloon_stats(args: std::env::Args) -> std::result::Result<(), ()> { + if args.len() != 1 { + print_help("crosvm balloon_stats", "VM_SOCKET", &[]); + println!("Prints virtio balloon statistics for a `VM_SOCKET`."); + return Err(()); + } + let command = BalloonControlCommand::Stats {}; + let request = &VmRequest::BalloonCommand(command); + let response = handle_request(request, args)?; + println!("{}", response); + Ok(()) +} + fn create_qcow2(args: std::env::Args) -> std::result::Result<(), ()> { let arguments = [ Argument::positional("PATH", "where to create the qcow2 image"), @@ -1796,7 +1870,7 @@ fn create_qcow2(args: std::env::Args) -> std::result::Result<(), ()> { .map_err(|e| { error!("Unable to parse command line arguments: {}", e); })?; - if file_path.len() == 0 || !(size.is_some() ^ backing_file.is_some()) { + if file_path.is_empty() || !(size.is_some() ^ backing_file.is_some()) { print_help("crosvm create_qcow2", "PATH [SIZE]", &arguments); println!( "Create a new QCOW2 image at `PATH` of either the specified `SIZE` in bytes or @@ -1837,11 +1911,11 @@ fn disk_cmd(mut args: std::env::Args) -> std::result::Result<(), ()> { println!(" resize DISK_INDEX NEW_SIZE VM_SOCKET"); return Err(()); } - let subcommand: &str = &args.nth(0).unwrap(); + let subcommand: &str = &args.next().unwrap(); let request = match subcommand { "resize" => { - let disk_index = match args.nth(0).unwrap().parse::<usize>() { + let disk_index = match args.next().unwrap().parse::<usize>() { Ok(n) => n, Err(_) => { error!("Failed to parse disk index"); @@ -1849,7 +1923,7 @@ fn disk_cmd(mut args: std::env::Args) -> std::result::Result<(), ()> { } }; - let new_size = match args.nth(0).unwrap().parse::<u64>() { + let new_size = match args.next().unwrap().parse::<u64>() { Ok(n) => n, Err(_) => { error!("Failed to parse disk size"); @@ -1911,7 +1985,7 @@ type ModifyUsbResult<T> = std::result::Result<T, ModifyUsbError>; fn parse_bus_id_addr(v: &str) -> ModifyUsbResult<(u8, u8, u16, u16)> { debug!("parse_bus_id_addr: {}", v); - let mut ids = v.split(":"); + let mut ids = v.split(':'); match (ids.next(), ids.next(), ids.next(), ids.next()) { (Some(bus_id), Some(addr), Some(vid), Some(pid)) => { let bus_id = bus_id @@ -2069,7 +2143,7 @@ fn pkg_version() -> std::result::Result<(), ()> { print!("crosvm {}", VERSION.unwrap_or("UNKNOWN")); match PKG_VERSION { Some(v) => println!("-{}", v), - None => println!(""), + None => println!(), } Ok(()) } @@ -2099,6 +2173,7 @@ fn crosvm_main() -> std::result::Result<(), ()> { Some("resume") => resume_vms(args), Some("run") => run_vm(args), Some("balloon") => balloon_vms(args), + Some("balloon_stats") => balloon_stats(args), Some("create_qcow2") => create_qcow2(args), Some("disk") => disk_cmd(args), Some("usb") => modify_usb(args), diff --git a/src/plugin/mod.rs b/src/plugin/mod.rs index ae7e19c..470d5f0 100644 --- a/src/plugin/mod.rs +++ b/src/plugin/mod.rs @@ -8,7 +8,7 @@ mod vcpu; use std::fmt::{self, Display}; use std::fs::File; use std::io; -use std::os::unix::io::{AsRawFd, FromRawFd, IntoRawFd}; +use std::os::unix::io::{AsRawFd, FromRawFd}; use std::os::unix::net::UnixDatagram; use std::path::Path; use std::result; @@ -181,10 +181,6 @@ impl Display for Error { type Result<T> = result::Result<T, Error>; -fn downcast_file<F: IntoRawFd>(f: F) -> File { - unsafe { File::from_raw_fd(f.into_raw_fd()) } -} - fn new_seqpacket_pair() -> SysResult<(UnixDatagram, UnixDatagram)> { let mut fds = [0, 0]; unsafe { diff --git a/src/plugin/process.rs b/src/plugin/process.rs index 51fc892..783239a 100644 --- a/src/plugin/process.rs +++ b/src/plugin/process.rs @@ -7,19 +7,17 @@ use std::env::set_var; use std::fs::File; use std::io::Write; use std::mem::transmute; -use std::os::unix::io::{AsRawFd, RawFd}; +use std::os::unix::io::{IntoRawFd, RawFd}; use std::os::unix::net::UnixDatagram; use std::path::Path; use std::process::Command; use std::sync::{Arc, RwLock}; use std::thread::JoinHandle; -use net_util; use net_util::Error as NetError; use libc::{pid_t, waitpid, EINVAL, ENODATA, ENOTTY, WEXITSTATUS, WIFEXITED, WNOHANG, WTERMSIG}; -use protobuf; use protobuf::Message; use io_jail::Minijail; @@ -348,7 +346,7 @@ impl Process { read_only: bool, dirty_log: bool, ) -> SysResult<()> { - let shm = SharedMemory::from_raw_fd(memfd)?; + let shm = SharedMemory::from_file(memfd)?; // Checking the seals ensures the plugin process won't shrink the mmapped file, causing us // to SIGBUS in the future. let seals = shm.get_seals()?; @@ -517,7 +515,14 @@ impl Process { let request = protobuf::parse_from_bytes::<MainRequest>(&self.request_buffer[..msg_size]) .map_err(Error::DecodeRequest)?; - let mut response_files = Vec::new(); + /// Use this to make it easier to stuff various kinds of File-like objects into the + /// `boxed_fds` list. + fn box_owned_fd<F: IntoRawFd + 'static>(f: F) -> Box<dyn IntoRawFd> { + Box::new(f) + } + + // This vec is used to extend ownership of certain FDs until the end of this function. + let mut boxed_fds = Vec::new(); let mut response_fds = Vec::new(); let mut response = MainResponse::new(); let res = if request.has_create() { @@ -559,7 +564,7 @@ impl Process { Ok(()) => { response_fds.push(evt.as_raw_fd()); response_fds.push(resample_evt.as_raw_fd()); - response_files.push(downcast_file(resample_evt)); + boxed_fds.push(box_owned_fd(resample_evt)); entry.insert(PluginObject::IrqEvent { irq_id: irq_event.irq_id, evt, @@ -588,7 +593,7 @@ impl Process { Ok((request_socket, child_socket)) => { self.request_sockets.push(request_socket); response_fds.push(child_socket.as_raw_fd()); - response_files.push(downcast_file(child_socket)); + boxed_fds.push(box_owned_fd(child_socket)); Ok(()) } Err(e) => Err(e), diff --git a/src/plugin/vcpu.rs b/src/plugin/vcpu.rs index a5bf73c..4bd3ea8 100644 --- a/src/plugin/vcpu.rs +++ b/src/plugin/vcpu.rs @@ -13,7 +13,6 @@ use std::sync::{Arc, RwLock}; use libc::{EINVAL, ENOENT, ENOTTY, EPERM, EPIPE, EPROTO}; -use protobuf; use protobuf::Message; use assertions::const_assert; |