hypervisor: ensure the thread of vcpu has not been changed

This commit is contained in:
equation314 2020-07-17 14:34:54 +08:00
parent 4fea25a76e
commit 82ca3d891a
3 changed files with 51 additions and 8 deletions

View File

@ -3,6 +3,7 @@ use {
hypervisor::{Guest, VcpuIo, VcpuState},
object::*,
signal::*,
task::{Thread, ThreadFlag},
},
alloc::sync::Arc,
core::convert::TryInto,
@ -13,6 +14,7 @@ use {
pub struct Vcpu {
base: KObjectBase,
_counter: CountHelper,
thread: Arc<Thread>,
inner: Mutex<VcpuInner>,
}
@ -20,15 +22,24 @@ impl_kobject!(Vcpu);
define_count_helper!(Vcpu);
impl Vcpu {
pub fn new(guest: Arc<Guest>, entry: u64) -> ZxResult<Arc<Self>> {
// TODO: check thread
pub fn new(guest: Arc<Guest>, entry: u64, thread: Arc<Thread>) -> ZxResult<Arc<Self>> {
if thread.get_flags().contains(ThreadFlag::VCPU) {
return Err(ZxError::BAD_STATE);
}
let inner = Mutex::new(VcpuInner::new(entry, guest.rvm_geust())?);
thread.update_flags(|flags| flags.insert(ThreadFlag::VCPU));
Ok(Arc::new(Vcpu {
base: KObjectBase::new(),
_counter: CountHelper::new(),
inner: Mutex::new(VcpuInner::new(entry, guest.rvm_geust())?),
thread,
inner,
}))
}
pub fn same_thread(&self, current_thread: &Arc<Thread>) -> bool {
Arc::ptr_eq(&self.thread, current_thread)
}
pub fn virtual_interrupt(&self, vector: u32) -> ZxResult {
self.inner
.lock()
@ -37,26 +48,29 @@ impl Vcpu {
}
pub fn resume(&self) -> ZxResult<PortPacket> {
// TODO: check thread
self.inner.lock().resume()?.try_into()
}
pub fn read_state(&self) -> ZxResult<VcpuState> {
// TODO: check thread
self.inner.lock().read_state().map_err(From::from)
}
pub fn write_state(&self, state: &VcpuState) -> ZxResult {
// TODO: check thread
self.inner.lock().write_state(state).map_err(From::from)
}
pub fn write_io_state(&self, state: &VcpuIo) -> ZxResult {
// TODO: check thread
self.inner.lock().write_io_state(state).map_err(From::from)
}
}
impl Drop for Vcpu {
fn drop(&mut self) {
self.thread
.update_flags(|flags| flags.remove(ThreadFlag::VCPU));
}
}
impl From<rvm::BellPacket> for PacketGuestBell {
fn from(bell: rvm::BellPacket) -> Self {
Self {

View File

@ -4,6 +4,7 @@ use {
super::*,
crate::object::*,
alloc::{boxed::Box, sync::Arc},
bitflags::bitflags,
core::{
any::Any,
future::Future,
@ -120,6 +121,7 @@ struct ThreadInner {
state: ThreadState,
/// The time this thread has run on cpu
time: u128,
flags: ThreadFlag,
}
impl ThreadInner {
@ -132,6 +134,13 @@ impl ThreadInner {
}
}
bitflags! {
#[derive(Default)]
pub struct ThreadFlag: usize {
const VCPU = 1 << 3;
}
}
impl Thread {
/// Create a new thread.
pub fn create(proc: &Arc<Process>, name: &str, _options: u32) -> ZxResult<Arc<Self>> {
@ -389,6 +398,17 @@ impl Thread {
}
ExceptionFuture
}
pub fn get_flags(&self) -> ThreadFlag {
self.inner.lock().flags
}
pub fn update_flags<F>(&self, f: F)
where
F: FnOnce(&mut ThreadFlag),
{
f(&mut self.inner.lock().flags)
}
}
impl Task for Thread {

View File

@ -91,7 +91,7 @@ impl Syscall<'_> {
}
let proc = self.thread.proc();
let guest = proc.get_object_with_rights::<Guest>(guest_handle, Rights::MANAGE_PROCESS)?;
let vcpu = Vcpu::new(guest, entry)?;
let vcpu = Vcpu::new(guest, entry, self.thread.clone())?;
let handle_value = proc.add_handle(Handle::new(vcpu, Rights::DEFAULT_VCPU));
out.write(handle_value)?;
Ok(())
@ -105,6 +105,9 @@ impl Syscall<'_> {
info!("hypervisor.vcpu_resume: handle={:#x?}", handle);
let proc = self.thread.proc();
let vcpu = proc.get_object_with_rights::<Vcpu>(handle, Rights::EXECUTE)?;
if !vcpu.same_thread(&self.thread) {
return Err(ZxError::BAD_STATE);
}
let packet = vcpu.resume()?;
user_packet.write(packet)?;
Ok(())
@ -137,6 +140,9 @@ impl Syscall<'_> {
}
let proc = self.thread.proc();
let vcpu = proc.get_object_with_rights::<Vcpu>(handle, Rights::READ)?;
if !vcpu.same_thread(&self.thread) {
return Err(ZxError::BAD_STATE);
}
let state = vcpu.read_state()?;
user_buffer.write(state)?;
Ok(())
@ -155,6 +161,9 @@ impl Syscall<'_> {
);
let proc = self.thread.proc();
let vcpu = proc.get_object_with_rights::<Vcpu>(handle, Rights::WRITE)?;
if !vcpu.same_thread(&self.thread) {
return Err(ZxError::BAD_STATE);
}
match VcpuReadWriteKind::try_from(kind) {
Ok(VcpuReadWriteKind::VcpuState) => {