mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-22 20:45:21 +00:00
vmm: Follow the "exe" symlink from the PID directory in /proc
It is necessary to do this at the start of the VMM execution rather than later as it must be done in the main thread in order to satisfy the checks required by PTRACE_MODE_READ_FSCREDS (see proc(5) and ptrace(2)) The alternative is to run as CAP_SYS_PTRACE but that has its disadvantages. Signed-off-by: Rob Bradford <robert.bradford@intel.com>
This commit is contained in:
parent
503887843f
commit
b04eb4770b
@ -35,6 +35,7 @@ use std::collections::HashMap;
|
||||
use std::fs::{File, OpenOptions};
|
||||
use std::io::{self, sink, stdout};
|
||||
use std::os::unix::fs::OpenOptionsExt;
|
||||
use std::path::PathBuf;
|
||||
use std::result;
|
||||
#[cfg(feature = "pci_support")]
|
||||
use std::sync::Weak;
|
||||
@ -399,6 +400,9 @@ pub struct DeviceManager {
|
||||
|
||||
// The virtio devices on the system
|
||||
virtio_devices: Vec<(VirtioDeviceArc, bool)>,
|
||||
|
||||
// The path to the VMM for self spawning
|
||||
_vmm_path: PathBuf,
|
||||
}
|
||||
|
||||
impl DeviceManager {
|
||||
@ -409,6 +413,7 @@ impl DeviceManager {
|
||||
memory_manager: Arc<Mutex<MemoryManager>>,
|
||||
_exit_evt: &EventFd,
|
||||
reset_evt: &EventFd,
|
||||
_vmm_path: PathBuf,
|
||||
) -> DeviceManagerResult<Self> {
|
||||
let io_bus = devices::Bus::new();
|
||||
let mmio_bus = devices::Bus::new();
|
||||
@ -482,6 +487,7 @@ impl DeviceManager {
|
||||
migratable_devices,
|
||||
memory_manager,
|
||||
virtio_devices: Vec::new(),
|
||||
_vmm_path,
|
||||
};
|
||||
|
||||
device_manager
|
||||
|
@ -20,6 +20,7 @@ use crate::vm::{Error as VmError, Vm, VmState};
|
||||
use libc::EFD_NONBLOCK;
|
||||
use std::io;
|
||||
use std::os::unix::io::{AsRawFd, RawFd};
|
||||
use std::path::PathBuf;
|
||||
use std::sync::mpsc::{Receiver, RecvError, SendError, Sender};
|
||||
use std::sync::{Arc, Mutex};
|
||||
use std::{result, thread};
|
||||
@ -79,6 +80,9 @@ pub enum Error {
|
||||
|
||||
/// Cannot shut the VMM down
|
||||
VmmShutdown(VmError),
|
||||
|
||||
// Error following "exe" link
|
||||
ExePathReadLink(io::Error),
|
||||
}
|
||||
pub type Result<T> = result::Result<T, Error>;
|
||||
|
||||
@ -159,10 +163,16 @@ pub fn start_vmm_thread(
|
||||
) -> Result<thread::JoinHandle<Result<()>>> {
|
||||
let http_api_event = api_event.try_clone().map_err(Error::EventFdClone)?;
|
||||
|
||||
// Find the path that the "/proc/<pid>/exe" symlink points to. Must be done before spawning
|
||||
// a thread as Rust does not put the child threads in the same thread group which prevents the
|
||||
// link from being followed as per PTRACE_MODE_READ_FSCREDS (see proc(5) and ptrace(2)). The
|
||||
// alternative is to run always with CAP_SYS_PTRACE but that is not a good idea.
|
||||
let self_path = format!("/proc/{}/exe", std::process::id());
|
||||
let vmm_path = std::fs::read_link(PathBuf::from(self_path)).map_err(Error::ExePathReadLink)?;
|
||||
let thread = thread::Builder::new()
|
||||
.name("vmm".to_string())
|
||||
.spawn(move || {
|
||||
let mut vmm = Vmm::new(vmm_version.to_string(), api_event)?;
|
||||
let mut vmm = Vmm::new(vmm_version.to_string(), api_event, vmm_path)?;
|
||||
|
||||
vmm.control_loop(Arc::new(api_receiver))
|
||||
})
|
||||
@ -182,10 +192,11 @@ pub struct Vmm {
|
||||
version: String,
|
||||
vm: Option<Vm>,
|
||||
vm_config: Option<Arc<Mutex<VmConfig>>>,
|
||||
vmm_path: PathBuf,
|
||||
}
|
||||
|
||||
impl Vmm {
|
||||
fn new(vmm_version: String, api_evt: EventFd) -> Result<Self> {
|
||||
fn new(vmm_version: String, api_evt: EventFd, vmm_path: PathBuf) -> Result<Self> {
|
||||
let mut epoll = EpollContext::new().map_err(Error::Epoll)?;
|
||||
let exit_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
let reset_evt = EventFd::new(EFD_NONBLOCK).map_err(Error::EventFdCreate)?;
|
||||
@ -214,6 +225,7 @@ impl Vmm {
|
||||
version: vmm_version,
|
||||
vm: None,
|
||||
vm_config: None,
|
||||
vmm_path,
|
||||
})
|
||||
}
|
||||
|
||||
@ -224,7 +236,12 @@ impl Vmm {
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
|
||||
if let Some(ref vm_config) = self.vm_config {
|
||||
let vm = Vm::new(Arc::clone(vm_config), exit_evt, reset_evt)?;
|
||||
let vm = Vm::new(
|
||||
Arc::clone(vm_config),
|
||||
exit_evt,
|
||||
reset_evt,
|
||||
self.vmm_path.clone(),
|
||||
)?;
|
||||
self.vm = Some(vm);
|
||||
}
|
||||
}
|
||||
@ -278,7 +295,7 @@ impl Vmm {
|
||||
let exit_evt = self.exit_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
let reset_evt = self.reset_evt.try_clone().map_err(VmError::EventFdClone)?;
|
||||
|
||||
self.vm = Some(Vm::new(config, exit_evt, reset_evt)?);
|
||||
self.vm = Some(Vm::new(config, exit_evt, reset_evt, self.vmm_path.clone())?);
|
||||
}
|
||||
|
||||
// Then we start the new VM.
|
||||
|
@ -39,6 +39,7 @@ use signal_hook::{iterator::Signals, SIGINT, SIGTERM, SIGWINCH};
|
||||
use std::ffi::CString;
|
||||
use std::fs::File;
|
||||
use std::io;
|
||||
use std::path::PathBuf;
|
||||
use std::sync::{Arc, Mutex, RwLock};
|
||||
use std::{result, str, thread};
|
||||
use vm_allocator::{GsiApic, SystemAllocator};
|
||||
@ -223,6 +224,7 @@ impl Vm {
|
||||
config: Arc<Mutex<VmConfig>>,
|
||||
exit_evt: EventFd,
|
||||
reset_evt: EventFd,
|
||||
vmm_path: PathBuf,
|
||||
) -> Result<Self> {
|
||||
let kvm = Kvm::new().map_err(Error::KvmNew)?;
|
||||
|
||||
@ -343,6 +345,7 @@ impl Vm {
|
||||
memory_manager.clone(),
|
||||
&exit_evt,
|
||||
&reset_evt,
|
||||
vmm_path,
|
||||
)
|
||||
.map_err(Error::DeviceManager)?;
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user