From 7da74cfec9bfb1fb99e262f3215651eb6c1fd55f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Martin=20Kr=C3=B6ning?= Date: Mon, 3 Jan 2022 23:58:19 +0100 Subject: [PATCH] Parse kernel arguments using clap --- src/bin/uhyve.rs | 5 +-- src/linux/uhyve.rs | 4 +++ src/linux/vcpu.rs | 8 +++++ src/macos/aarch64/uhyve.rs | 4 +++ src/macos/aarch64/vcpu.rs | 9 +++++- src/macos/x86_64/uhyve.rs | 4 +++ src/macos/x86_64/vcpu.rs | 8 +++++ src/params.rs | 5 +++ src/vm.rs | 63 +++++++++++++------------------------- 9 files changed, 66 insertions(+), 44 deletions(-) diff --git a/src/bin/uhyve.rs b/src/bin/uhyve.rs index d5d01ae0..93c59b19 100644 --- a/src/bin/uhyve.rs +++ b/src/bin/uhyve.rs @@ -73,7 +73,7 @@ struct Args { /// Arguments to forward to the kernel #[structopt(parse(from_os_str))] - _arguments: Vec, + args: Vec, } #[derive(Parser, Debug)] @@ -285,7 +285,7 @@ impl From for Params { _mac, }, kernel: _, - _arguments, + args, } = args; Self { verbose, @@ -305,6 +305,7 @@ impl From for Params { nic, #[cfg(target_os = "linux")] gdb_port, + args, } } } diff --git a/src/linux/uhyve.rs b/src/linux/uhyve.rs index 5b2d0ab5..bf53ea80 100755 --- a/src/linux/uhyve.rs +++ b/src/linux/uhyve.rs @@ -16,6 +16,7 @@ use kvm_ioctls::VmFd; use log::debug; use nix::sys::mman::*; use std::cmp; +use std::ffi::OsString; use std::fmt; use std::hint; use std::mem; @@ -133,6 +134,7 @@ pub struct Uhyve { mem: MmapMemory, num_cpus: u32, path: PathBuf, + args: Vec, boot_info: *const BootInfo, verbose: bool, ip: Option, @@ -271,6 +273,7 @@ impl Uhyve { mem, num_cpus: cpu_count, path: kernel_path, + args: params.args, boot_info: ptr::null(), verbose: params.verbose, ip: params.ip, @@ -339,6 +342,7 @@ impl Vm for Uhyve { Ok(UhyveCPU::new( id, self.path.clone(), + self.args.clone(), self.vm.create_vcpu(id.try_into().unwrap())?, vm_start, tx, diff --git a/src/linux/vcpu.rs b/src/linux/vcpu.rs index a65a7077..a36440ef 100755 --- a/src/linux/vcpu.rs +++ b/src/linux/vcpu.rs @@ -8,6 +8,7 @@ use crate::vm::VcpuStopReason; use crate::vm::VirtualCPU; use kvm_bindings::*; use kvm_ioctls::{VcpuExit, VcpuFd}; +use std::ffi::OsString; use std::path::Path; use std::path::PathBuf; use std::slice; @@ -27,6 +28,7 @@ pub struct UhyveCPU { vcpu: VcpuFd, vm_start: usize, kernel_path: PathBuf, + args: Vec, tx: Option>, virtio_device: Arc>, pci_addr: Option, @@ -42,6 +44,7 @@ impl UhyveCPU { pub fn new( id: u32, kernel_path: PathBuf, + args: Vec, vcpu: VcpuFd, vm_start: usize, tx: Option>, @@ -52,6 +55,7 @@ impl UhyveCPU { vcpu, vm_start, kernel_path, + args, tx, virtio_device, pci_addr: None, @@ -256,6 +260,10 @@ impl VirtualCPU for UhyveCPU { self.kernel_path.as_path() } + fn args(&self) -> &[OsString] { + self.args.as_slice() + } + fn host_address(&self, addr: usize) -> usize { addr + self.vm_start } diff --git a/src/macos/aarch64/uhyve.rs b/src/macos/aarch64/uhyve.rs index f7e04dd6..746d37d6 100644 --- a/src/macos/aarch64/uhyve.rs +++ b/src/macos/aarch64/uhyve.rs @@ -7,6 +7,7 @@ use crate::vm::Vm; use libc; use libc::c_void; use log::debug; +use std::ffi::OsString; use std::net::Ipv4Addr; use std::path::Path; use std::path::PathBuf; @@ -21,6 +22,7 @@ pub struct Uhyve { guest_mem: *mut c_void, num_cpus: u32, path: PathBuf, + args: Vec, boot_info: *const BootInfo, verbose: bool, } @@ -88,6 +90,7 @@ impl Uhyve { guest_mem: mem, num_cpus: params.cpu_count.get(), path: kernel_path, + args: params.args, boot_info: ptr::null(), verbose: params.verbose, }; @@ -135,6 +138,7 @@ impl Vm for Uhyve { Ok(UhyveCPU::new( id, self.path.clone(), + self.args.clone(), self.guest_mem as usize, )) } diff --git a/src/macos/aarch64/vcpu.rs b/src/macos/aarch64/vcpu.rs index 50102f6c..20884a41 100644 --- a/src/macos/aarch64/vcpu.rs +++ b/src/macos/aarch64/vcpu.rs @@ -6,6 +6,7 @@ use crate::vm::HypervisorResult; use crate::vm::VcpuStopReason; use crate::vm::VirtualCPU; use log::debug; +use std::ffi::OsString; use std::path::Path; use std::path::PathBuf; use xhypervisor; @@ -14,15 +15,17 @@ use xhypervisor::{Register, SystemRegister, VirtualCpuExitReason}; pub struct UhyveCPU { id: u32, kernel_path: PathBuf, + args: Vec, vcpu: xhypervisor::VirtualCpu, vm_start: usize, } impl UhyveCPU { - pub fn new(id: u32, kernel_path: PathBuf, vm_start: usize) -> UhyveCPU { + pub fn new(id: u32, kernel_path: PathBuf, args: Vec, vm_start: usize) -> UhyveCPU { Self { id, kernel_path, + args, vcpu: xhypervisor::VirtualCpu::new().unwrap(), vm_start, } @@ -50,6 +53,10 @@ impl VirtualCPU for UhyveCPU { self.kernel_path.as_path() } + fn args(&self) -> &[OsString] { + self.args.as_slice() + } + fn host_address(&self, addr: usize) -> usize { addr + self.vm_start } diff --git a/src/macos/x86_64/uhyve.rs b/src/macos/x86_64/uhyve.rs index 76ad8472..590329ed 100644 --- a/src/macos/x86_64/uhyve.rs +++ b/src/macos/x86_64/uhyve.rs @@ -9,6 +9,7 @@ use crate::x86_64::create_gdt_entry; use libc; use libc::c_void; use log::debug; +use std::ffi::OsString; use std::mem; use std::net::Ipv4Addr; use std::path::Path; @@ -27,6 +28,7 @@ pub struct Uhyve { guest_mem: *mut c_void, num_cpus: u32, path: PathBuf, + args: Vec, boot_info: *const BootInfo, ioapic: Arc>, verbose: bool, @@ -85,6 +87,7 @@ impl Uhyve { guest_mem: mem, num_cpus: params.cpu_count.get(), path: kernel_path, + args: params.args, boot_info: ptr::null(), ioapic: Arc::new(Mutex::new(IoApic::new())), verbose: params.verbose, @@ -133,6 +136,7 @@ impl Vm for Uhyve { Ok(UhyveCPU::new( id, self.path.clone(), + self.args.clone(), self.guest_mem as usize, self.ioapic.clone(), )) diff --git a/src/macos/x86_64/vcpu.rs b/src/macos/x86_64/vcpu.rs index 2ac1bcf1..8e4130e1 100644 --- a/src/macos/x86_64/vcpu.rs +++ b/src/macos/x86_64/vcpu.rs @@ -11,6 +11,7 @@ use burst::x86::{disassemble_64, InstructionOperation, OperandType}; use lazy_static::lazy_static; use log::{debug, trace}; use std::arch::x86_64::__cpuid_count; +use std::ffi::OsString; use std::path::Path; use std::path::PathBuf; use std::sync::{Arc, Mutex}; @@ -146,6 +147,7 @@ lazy_static! { pub struct UhyveCPU { id: u32, kernel_path: PathBuf, + args: Vec, vcpu: xhypervisor::VirtualCpu, vm_start: usize, apic_base: u64, @@ -156,12 +158,14 @@ impl UhyveCPU { pub fn new( id: u32, kernel_path: PathBuf, + args: Vec, vm_start: usize, ioapic: Arc>, ) -> UhyveCPU { UhyveCPU { id, kernel_path, + args, vcpu: xhypervisor::VirtualCpu::new().unwrap(), vm_start, apic_base: APIC_DEFAULT_BASE, @@ -626,6 +630,10 @@ impl VirtualCPU for UhyveCPU { self.kernel_path.as_path() } + fn args(&self) -> &[OsString] { + self.args.as_slice() + } + fn host_address(&self, addr: usize) -> usize { addr + self.vm_start } diff --git a/src/params.rs b/src/params.rs index 0054c9a9..16be24b6 100644 --- a/src/params.rs +++ b/src/params.rs @@ -1,6 +1,7 @@ #[cfg(target_os = "linux")] use std::net::Ipv4Addr; use std::{ + ffi::OsString, fmt, num::{NonZeroU32, ParseIntError, TryFromIntError}, str::FromStr, @@ -47,6 +48,9 @@ pub struct Params { /// Name of the network interface #[cfg(target_os = "linux")] pub nic: Option, + + /// Arguments to forward to the kernel + pub args: Vec, } #[allow(clippy::derivable_impls)] @@ -70,6 +74,7 @@ impl Default for Params { mask: Default::default(), #[cfg(target_os = "linux")] nic: Default::default(), + args: Default::default(), } } } diff --git a/src/vm.rs b/src/vm.rs index d6055cc6..61e165a3 100644 --- a/src/vm.rs +++ b/src/vm.rs @@ -3,6 +3,7 @@ use goblin::elf64::header::ET_DYN; use goblin::elf64::program_header::{PT_LOAD, PT_TLS}; use goblin::elf64::reloc::*; use log::{debug, error, warn}; +use std::ffi::OsString; use std::io::Write; use std::net::Ipv4Addr; use std::os::unix::ffi::OsStrExt; @@ -140,36 +141,25 @@ pub trait VirtualCPU { /// Returns the (host) path of the kernel binary. fn kernel_path(&self) -> &Path; + fn args(&self) -> &[OsString]; + fn cmdsize(&self, syssize: &mut SysCmdsize) { syssize.argc = 0; syssize.envc = 0; - let mut counter: i32 = 0; - let mut separator_pos: i32 = 0; let path = self.kernel_path(); - let mut found_separator = false; syssize.argsz[0] = path.as_os_str().len() as i32 + 1; - for argument in std::env::args_os() { - if !found_separator && argument == "--" { - separator_pos = counter + 1; - found_separator = true; - } - - if found_separator && counter >= separator_pos { - syssize.argsz[(counter - separator_pos + 1) as usize] = argument.len() as i32 + 1; - } + let mut counter = 0; + for argument in self.args() { + syssize.argsz[(counter + 1) as usize] = argument.len() as i32 + 1; counter += 1; } - if found_separator && counter >= separator_pos { - syssize.argc = counter - separator_pos + 1; - } else { - syssize.argc = 1; - } + syssize.argc = counter + 1; - counter = 0; + let mut counter = 0; for (key, value) in std::env::vars_os() { if counter < MAX_ENVC.try_into().unwrap() { syssize.envsz[counter as usize] = (key.len() + value.len()) as i32 + 2; @@ -185,10 +175,7 @@ pub trait VirtualCPU { /// Copies the arguments end environment of the application into the VM's memory. fn cmdval(&self, syscmdval: &SysCmdval) { - let mut counter: i32 = 0; let argv = self.host_address(syscmdval.argv as usize); - let mut found_separator = false; - let mut separator_pos: i32 = 0; // copy kernel path as first argument { @@ -204,32 +191,26 @@ pub trait VirtualCPU { } // Copy the application arguments into the vm memory - for argument in std::env::args_os() { - if !found_separator && argument == "--" { - separator_pos = counter + 1; - found_separator = true; - } - - if found_separator && counter >= separator_pos { - let argvptr = unsafe { - self.host_address( - *((argv + (counter - separator_pos + 1) as usize * mem::size_of::()) - as *mut *mut u8) as usize, - ) - }; - let len = argument.len(); - let slice = unsafe { slice::from_raw_parts_mut(argvptr as *mut u8, len + 1) }; + let mut counter = 0; + for argument in self.args() { + let argvptr = unsafe { + self.host_address( + *((argv + (counter + 1) as usize * mem::size_of::()) as *mut *mut u8) + as usize, + ) + }; + let len = argument.len(); + let slice = unsafe { slice::from_raw_parts_mut(argvptr as *mut u8, len + 1) }; - // Create string for environment variable - slice[0..len].copy_from_slice(argument.as_bytes()); - slice[len] = 0; - } + // Create string for environment variable + slice[0..len].copy_from_slice(argument.as_bytes()); + slice[len] = 0; counter += 1; } // Copy the environment variables into the vm memory - counter = 0; + let mut counter = 0; let envp = self.host_address(syscmdval.envp as usize); for (key, value) in std::env::vars_os() { if counter < MAX_ENVC.try_into().unwrap() {