Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion rust-vmm-ci
14 changes: 11 additions & 3 deletions src/devices/src/virtio/net/tap.rs
Original file line number Diff line number Diff line change
Expand Up @@ -85,6 +85,7 @@ impl IfReqBuilder {
}

pub fn if_name(mut self, if_name: &[u8; IFACE_NAME_MAX_LEN]) -> Self {
// SAFETY:
// Since we don't call as_mut on the same union field more than once, this block is safe.
let ifrn_name = unsafe { self.0.ifr_ifrn.ifrn_name.as_mut() };
ifrn_name.copy_from_slice(if_name.as_ref());
Expand All @@ -93,6 +94,7 @@ impl IfReqBuilder {
}

pub(crate) fn flags(mut self, flags: i16) -> Self {
// SAFETY:
// Since we don't call as_mut on the same union field more than once, this block is safe.
let ifru_flags = unsafe { self.0.ifr_ifru.ifru_flags.as_mut() };
*ifru_flags = flags;
Expand All @@ -101,6 +103,7 @@ impl IfReqBuilder {
}

pub(crate) fn execute<F: AsRawFd>(mut self, socket: &F, ioctl: u64) -> Result<ifreq> {
// SAFETY:
// ioctl is safe. Called with a valid socket fd, and we check the return.
let ret = unsafe { ioctl_with_mut_ref(socket, ioctl, &mut self.0) };
if ret < 0 {
Expand All @@ -119,9 +122,10 @@ impl Tap {
pub fn open_named(if_name: &str) -> Result<Tap> {
let terminated_if_name = build_terminated_if_name(if_name)?;

// SAFETY:
// Open calls are safe because we give a constant null-terminated
// string and verify the result.
let fd = unsafe {
// Open calls are safe because we give a constant null-terminated
// string and verify the result.
libc::open(
b"/dev/net/tun\0".as_ptr() as *const c_char,
libc::O_RDWR | libc::O_NONBLOCK | libc::O_CLOEXEC,
Expand All @@ -130,6 +134,7 @@ impl Tap {
if fd < 0 {
return Err(Error::OpenTun(IoError::last_os_error()));
}
// SAFETY:
// We just checked that the fd is valid.
let tuntap = unsafe { File::from_raw_fd(fd) };

Expand All @@ -138,9 +143,10 @@ impl Tap {
.flags((IFF_TAP | IFF_NO_PI | IFF_VNET_HDR) as i16)
.execute(&tuntap, TUNSETIFF())?;

// Safe since only the name is accessed, and it's cloned out.
Ok(Tap {
tap_file: tuntap,
// SAFETY:
// Safe since only the name is accessed, and it's cloned out.
if_name: unsafe { *ifreq.ifr_ifrn.ifrn_name.as_ref() },
})
}
Expand All @@ -156,6 +162,7 @@ impl Tap {

/// Set the offload flags for the tap interface.
pub fn set_offload(&self, flags: c_uint) -> Result<()> {
// SAFETY:
// ioctl is safe. Called with a valid tap fd, and we check the return.
let ret = unsafe { ioctl_with_val(&self.tap_file, TUNSETOFFLOAD(), c_ulong::from(flags)) };
if ret < 0 {
Expand All @@ -167,6 +174,7 @@ impl Tap {

/// Set the size of the vnet hdr.
pub fn set_vnet_hdr_size(&self, size: c_int) -> Result<()> {
// SAFETY:
// ioctl is safe. Called with a valid tap fd, and we check the return.
let ret = unsafe { ioctl_with_ref(&self.tap_file, TUNSETVNETHDRSZ(), &size) };
if ret < 0 {
Expand Down
1 change: 1 addition & 0 deletions src/vm-vcpu-ref/src/x86_64/gdt.rs
Original file line number Diff line number Diff line change
Expand Up @@ -51,6 +51,7 @@ pub type Result<T> = std::result::Result<T, Error>;
/// Descriptors" of the Intel Manual Volume 3a.
pub struct SegmentDescriptor(pub u64);

// SAFETY:
// Safe because SegmentDescriptor is just a wrapper over u64.
unsafe impl ByteValued for SegmentDescriptor {}

Expand Down
3 changes: 2 additions & 1 deletion src/vm-vcpu-ref/src/x86_64/mpspec.rs
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
non_camel_case_types,
non_upper_case_globals,
unused,
clippy::redundant_static_lifetimes
clippy::redundant_static_lifetimes,
clippy::undocumented_unsafe_blocks
)]
#![cfg_attr(test, allow(clippy::zero_ptr))]
#![cfg_attr(test, allow(deref_nullptr))]
Expand Down
24 changes: 22 additions & 2 deletions src/vm-vcpu-ref/src/x86_64/mptable.rs
Original file line number Diff line number Diff line change
Expand Up @@ -33,14 +33,33 @@ struct MpcLintsrc(mpspec::mpc_lintsrc);
#[derive(Copy, Clone, Default)]
struct MpfIntel(mpspec::mpf_intel);

// These `mpspec` wrapper types are POD (Plain Old Data), so reading them from
// data a slice of u8 (which is what ByteValued offers) is safe.
// SAFETY:
// This wrapper type is POD (Plain Old Data), so reading them from a slice of
// u8 (which is what ByteValued offers) is safe.
unsafe impl ByteValued for MpcBus {}
// SAFETY:
// This wrapper type is POD (Plain Old Data), so reading them from a slice of
// u8 (which is what ByteValued offers) is safe.
unsafe impl ByteValued for MpcCpu {}
// SAFETY:
// This wrapper type is POD (Plain Old Data), so reading them from a slice of
// u8 (which is what ByteValued offers) is safe.
unsafe impl ByteValued for MpcIntsrc {}
// SAFETY:
// This wrapper type is POD (Plain Old Data), so reading them from a slice of
// u8 (which is what ByteValued offers) is safe.
unsafe impl ByteValued for MpcIoapic {}
// SAFETY:
// This wrapper type is POD (Plain Old Data), so reading them from a slice of
// u8 (which is what ByteValued offers) is safe.
unsafe impl ByteValued for MpcTable {}
// SAFETY:
// This wrapper type is POD (Plain Old Data), so reading them from a slice of
// u8 (which is what ByteValued offers) is safe.
unsafe impl ByteValued for MpcLintsrc {}
// SAFETY:
// This wrapper type is POD (Plain Old Data), so reading them from a slice of
// u8 (which is what ByteValued offers) is safe.
unsafe impl ByteValued for MpfIntel {}

// MPTABLE, describing VCPUS.
Expand Down Expand Up @@ -105,6 +124,7 @@ const CPU_FEATURE_APIC: u32 = 0x200;
const CPU_FEATURE_FPU: u32 = 0x001;

fn compute_checksum<T: Copy>(v: &T) -> u8 {
// SAFETY:
// Safe because we are only reading the bytes within the size of the `T` reference `v`.
let v_slice = unsafe { slice::from_raw_parts(v as *const T as *const u8, mem::size_of::<T>()) };
let mut checksum: u8 = 0;
Expand Down
1 change: 1 addition & 0 deletions src/vm-vcpu/src/vcpu/mod.rs
Original file line number Diff line number Diff line change
Expand Up @@ -654,6 +654,7 @@ impl KvmVcpu {
fn set_local_immediate_exit(value: u8) {
Self::TLS_VCPU_PTR.with(|v| {
if let Some(vcpu) = *v.borrow() {
// SAFETY:
// The block below modifies a mmaped memory region (`kvm_run` struct) which is valid
// as long as the `VMM` is still in scope. This function is called in response to
// SIGRTMIN(), while the vCPU threads are still active. Their termination are
Expand Down
1 change: 1 addition & 0 deletions src/vm-vcpu/src/vcpu/regs.rs
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ macro_rules! arm64_core_reg {
macro_rules! offset__of {
($str:ty, $($field:ident)+) => ({
let tmp: std::mem::MaybeUninit<$str> = std::mem::MaybeUninit::uninit();
// SAFETY:
// Safe because we are not using the value of tmp.
let tmp = unsafe { tmp.assume_init() };
let base = &tmp as *const _ as usize;
Expand Down
1 change: 1 addition & 0 deletions src/vm-vcpu/src/vm.rs
Original file line number Diff line number Diff line change
Expand Up @@ -355,6 +355,7 @@ impl<EH: 'static + ExitHandler + Send> KvmVm<EH> {
flags: 0,
};

// SAFETY:
// Safe because:
// * userspace_addr is a valid address for a memory region, obtained by calling
// get_host_address() on a valid region's start address;
Expand Down