mirror of
https://github.com/cloud-hypervisor/cloud-hypervisor.git
synced 2025-01-03 03:15:20 +00:00
virtio-devices: modify or provide safety comments
Signed-off-by: Wei Liu <liuwe@microsoft.com>
This commit is contained in:
parent
f110029acf
commit
c45d24df16
@ -128,8 +128,8 @@ impl BalloonEpollHandler {
|
|||||||
let hva = memory
|
let hva = memory
|
||||||
.get_host_address(range_base)
|
.get_host_address(range_base)
|
||||||
.map_err(Error::GuestMemory)?;
|
.map_err(Error::GuestMemory)?;
|
||||||
// Need unsafe to do syscall madvise
|
|
||||||
let res =
|
let res =
|
||||||
|
// SAFETY: Need unsafe to do syscall madvise
|
||||||
unsafe { libc::madvise(hva as *mut libc::c_void, range_len as libc::size_t, advice) };
|
unsafe { libc::madvise(hva as *mut libc::c_void, range_len as libc::size_t, advice) };
|
||||||
if res != 0 {
|
if res != 0 {
|
||||||
return Err(Error::MadviseFail(io::Error::last_os_error()));
|
return Err(Error::MadviseFail(io::Error::last_os_error()));
|
||||||
@ -147,6 +147,7 @@ impl BalloonEpollHandler {
|
|||||||
))?;
|
))?;
|
||||||
if let Some(f_off) = region.file_offset() {
|
if let Some(f_off) = region.file_offset() {
|
||||||
let offset = range_base.0 - region.start_addr().0;
|
let offset = range_base.0 - region.start_addr().0;
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
libc::fallocate64(
|
libc::fallocate64(
|
||||||
f_off.file().as_raw_fd(),
|
f_off.file().as_raw_fd(),
|
||||||
|
@ -607,6 +607,7 @@ fn get_win_size(tty: &dyn AsRawFd) -> (u16, u16) {
|
|||||||
}
|
}
|
||||||
let ws: WindowSize = WindowSize::default();
|
let ws: WindowSize = WindowSize::default();
|
||||||
|
|
||||||
|
// SAFETY: FFI call with correct arguments
|
||||||
unsafe {
|
unsafe {
|
||||||
libc::ioctl(tty.as_raw_fd(), TIOCGWINSZ, &ws);
|
libc::ioctl(tty.as_raw_fd(), TIOCGWINSZ, &ws);
|
||||||
}
|
}
|
||||||
|
@ -87,6 +87,7 @@ impl EpollHelper {
|
|||||||
// Create the epoll file descriptor
|
// Create the epoll file descriptor
|
||||||
let epoll_fd = epoll::create(true).map_err(EpollHelperError::CreateFd)?;
|
let epoll_fd = epoll::create(true).map_err(EpollHelperError::CreateFd)?;
|
||||||
// Use 'File' to enforce closing on 'epoll_fd'
|
// Use 'File' to enforce closing on 'epoll_fd'
|
||||||
|
// SAFETY: epoll_fd is a valid fd
|
||||||
let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
|
let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
|
||||||
|
|
||||||
let mut helper = Self {
|
let mut helper = Self {
|
||||||
|
@ -267,19 +267,31 @@ struct VirtioIommuFault {
|
|||||||
address: u64,
|
address: u64,
|
||||||
}
|
}
|
||||||
|
|
||||||
// SAFETY: these data structures only contain integers and have no implicit padding
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuRange32 {}
|
unsafe impl ByteValued for VirtioIommuRange32 {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuRange64 {}
|
unsafe impl ByteValued for VirtioIommuRange64 {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuConfig {}
|
unsafe impl ByteValued for VirtioIommuConfig {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuReqHead {}
|
unsafe impl ByteValued for VirtioIommuReqHead {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuReqTail {}
|
unsafe impl ByteValued for VirtioIommuReqTail {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuReqAttach {}
|
unsafe impl ByteValued for VirtioIommuReqAttach {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuReqDetach {}
|
unsafe impl ByteValued for VirtioIommuReqDetach {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuReqMap {}
|
unsafe impl ByteValued for VirtioIommuReqMap {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuReqUnmap {}
|
unsafe impl ByteValued for VirtioIommuReqUnmap {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuReqProbe {}
|
unsafe impl ByteValued for VirtioIommuReqProbe {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuProbeProperty {}
|
unsafe impl ByteValued for VirtioIommuProbeProperty {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuProbeResvMem {}
|
unsafe impl ByteValued for VirtioIommuProbeResvMem {}
|
||||||
|
// SAFETY: data structure only contain integers and have no implicit padding
|
||||||
unsafe impl ByteValued for VirtioIommuFault {}
|
unsafe impl ByteValued for VirtioIommuFault {}
|
||||||
|
|
||||||
#[derive(Error, Debug)]
|
#[derive(Error, Debug)]
|
||||||
|
@ -417,6 +417,7 @@ impl MemEpollHandler {
|
|||||||
fn discard_memory_range(&self, offset: u64, size: u64) -> Result<(), Error> {
|
fn discard_memory_range(&self, offset: u64, size: u64) -> Result<(), Error> {
|
||||||
// Use fallocate if the memory region is backed by a file.
|
// Use fallocate if the memory region is backed by a file.
|
||||||
if let Some(fd) = self.host_fd {
|
if let Some(fd) = self.host_fd {
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
libc::fallocate64(
|
libc::fallocate64(
|
||||||
fd,
|
fd,
|
||||||
@ -435,6 +436,7 @@ impl MemEpollHandler {
|
|||||||
// Only use madvise if the memory region is not allocated with
|
// Only use madvise if the memory region is not allocated with
|
||||||
// hugepages.
|
// hugepages.
|
||||||
if !self.hugepages {
|
if !self.hugepages {
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
libc::madvise(
|
libc::madvise(
|
||||||
(self.host_addr + offset) as *mut libc::c_void,
|
(self.host_addr + offset) as *mut libc::c_void,
|
||||||
|
@ -666,8 +666,8 @@ impl VirtioPciDevice {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
// Safe since we know self.cap_pci_cfg_info.cap.cap.offset is 32bits long.
|
|
||||||
let bar_offset: u32 =
|
let bar_offset: u32 =
|
||||||
|
// SAFETY: we know self.cap_pci_cfg_info.cap.cap.offset is 32bits long.
|
||||||
unsafe { std::mem::transmute(self.cap_pci_cfg_info.cap.cap.offset) };
|
unsafe { std::mem::transmute(self.cap_pci_cfg_info.cap.cap.offset) };
|
||||||
self.read_bar(0, bar_offset as u64, data)
|
self.read_bar(0, bar_offset as u64, data)
|
||||||
}
|
}
|
||||||
@ -687,8 +687,8 @@ impl VirtioPciDevice {
|
|||||||
right[..data_len].copy_from_slice(data);
|
right[..data_len].copy_from_slice(data);
|
||||||
None
|
None
|
||||||
} else {
|
} else {
|
||||||
// Safe since we know self.cap_pci_cfg_info.cap.cap.offset is 32bits long.
|
|
||||||
let bar_offset: u32 =
|
let bar_offset: u32 =
|
||||||
|
// SAFETY: we know self.cap_pci_cfg_info.cap.cap.offset is 32bits long.
|
||||||
unsafe { std::mem::transmute(self.cap_pci_cfg_info.cap.cap.offset) };
|
unsafe { std::mem::transmute(self.cap_pci_cfg_info.cap.cap.offset) };
|
||||||
self.write_bar(0, bar_offset as u64, data)
|
self.write_bar(0, bar_offset as u64, data)
|
||||||
}
|
}
|
||||||
|
@ -95,6 +95,7 @@ impl VhostUserMasterReqHandler for SlaveReqHandler {
|
|||||||
|
|
||||||
let addr = self.mmap_cache_addr + offset;
|
let addr = self.mmap_cache_addr + offset;
|
||||||
let flags = fs.flags[i];
|
let flags = fs.flags[i];
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
libc::mmap(
|
libc::mmap(
|
||||||
addr as *mut libc::c_void,
|
addr as *mut libc::c_void,
|
||||||
@ -136,6 +137,7 @@ impl VhostUserMasterReqHandler for SlaveReqHandler {
|
|||||||
}
|
}
|
||||||
|
|
||||||
let addr = self.mmap_cache_addr + offset;
|
let addr = self.mmap_cache_addr + offset;
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
let ret = unsafe {
|
let ret = unsafe {
|
||||||
libc::mmap(
|
libc::mmap(
|
||||||
addr as *mut libc::c_void,
|
addr as *mut libc::c_void,
|
||||||
@ -172,6 +174,7 @@ impl VhostUserMasterReqHandler for SlaveReqHandler {
|
|||||||
|
|
||||||
let addr = self.mmap_cache_addr + offset;
|
let addr = self.mmap_cache_addr + offset;
|
||||||
let ret =
|
let ret =
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
unsafe { libc::msync(addr as *mut libc::c_void, len as usize, libc::MS_SYNC) };
|
unsafe { libc::msync(addr as *mut libc::c_void, len as usize, libc::MS_SYNC) };
|
||||||
if ret == -1 {
|
if ret == -1 {
|
||||||
return Err(io::Error::last_os_error());
|
return Err(io::Error::last_os_error());
|
||||||
@ -228,6 +231,7 @@ impl VhostUserMasterReqHandler for SlaveReqHandler {
|
|||||||
== VhostUserFSSlaveMsgFlags::MAP_W
|
== VhostUserFSSlaveMsgFlags::MAP_W
|
||||||
{
|
{
|
||||||
debug!("write: foffset={}, len={}", foffset, len);
|
debug!("write: foffset={}, len={}", foffset, len);
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
unsafe {
|
unsafe {
|
||||||
pwrite64(
|
pwrite64(
|
||||||
fd.as_raw_fd(),
|
fd.as_raw_fd(),
|
||||||
@ -238,6 +242,7 @@ impl VhostUserMasterReqHandler for SlaveReqHandler {
|
|||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
debug!("read: foffset={}, len={}", foffset, len);
|
debug!("read: foffset={}, len={}", foffset, len);
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
unsafe { pread64(fd.as_raw_fd(), ptr as *mut c_void, len, foffset as off64_t) }
|
unsafe { pread64(fd.as_raw_fd(), ptr as *mut c_void, len, foffset as off64_t) }
|
||||||
};
|
};
|
||||||
|
|
||||||
@ -279,6 +284,7 @@ impl Default for VirtioFsConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// SAFETY: only a series of integers
|
||||||
unsafe impl ByteValued for VirtioFsConfig {}
|
unsafe impl ByteValued for VirtioFsConfig {}
|
||||||
|
|
||||||
pub struct Fs {
|
pub struct Fs {
|
||||||
|
@ -375,6 +375,7 @@ impl VhostUserCommon {
|
|||||||
|
|
||||||
pub fn shutdown(&mut self) {
|
pub fn shutdown(&mut self) {
|
||||||
if let Some(vu) = &self.vu {
|
if let Some(vu) = &self.vu {
|
||||||
|
// SAFETY: trivially safe
|
||||||
let _ = unsafe { libc::close(vu.lock().unwrap().socket_handle().as_raw_fd()) };
|
let _ = unsafe { libc::close(vu.lock().unwrap().socket_handle().as_raw_fd()) };
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -451,7 +451,7 @@ impl VhostUserHandle {
|
|||||||
)
|
)
|
||||||
.map_err(Error::MemfdCreate)?;
|
.map_err(Error::MemfdCreate)?;
|
||||||
|
|
||||||
// Safe because we checked the file descriptor is valid
|
// SAFETY: we checked the file descriptor is valid
|
||||||
let file = unsafe { File::from_raw_fd(fd) };
|
let file = unsafe { File::from_raw_fd(fd) };
|
||||||
// The size of the memory mapping corresponds to the size of a bitmap
|
// The size of the memory mapping corresponds to the size of a bitmap
|
||||||
// covering all guest pages for addresses from 0 to the last physical
|
// covering all guest pages for addresses from 0 to the last physical
|
||||||
@ -465,6 +465,7 @@ impl VhostUserHandle {
|
|||||||
file.set_len(mmap_size).map_err(Error::SetFileSize)?;
|
file.set_len(mmap_size).map_err(Error::SetFileSize)?;
|
||||||
|
|
||||||
// Set the seals
|
// Set the seals
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
let res = unsafe {
|
let res = unsafe {
|
||||||
libc::fcntl(
|
libc::fcntl(
|
||||||
file.as_raw_fd(),
|
file.as_raw_fd(),
|
||||||
@ -569,6 +570,7 @@ impl VhostUserHandle {
|
|||||||
// Be careful with the size, as it was based on u8, meaning we must
|
// Be careful with the size, as it was based on u8, meaning we must
|
||||||
// divide it by 8.
|
// divide it by 8.
|
||||||
let len = region.size() / 8;
|
let len = region.size() / 8;
|
||||||
|
// SAFETY: region is of size len
|
||||||
let bitmap = unsafe {
|
let bitmap = unsafe {
|
||||||
// Cast the pointer to u64
|
// Cast the pointer to u64
|
||||||
let ptr = region.as_ptr() as *const u64;
|
let ptr = region.as_ptr() as *const u64;
|
||||||
@ -582,6 +584,7 @@ impl VhostUserHandle {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn memfd_create(name: &ffi::CStr, flags: u32) -> std::result::Result<RawFd, std::io::Error> {
|
fn memfd_create(name: &ffi::CStr, flags: u32) -> std::result::Result<RawFd, std::io::Error> {
|
||||||
|
// SAFETY: FFI call with valid arguments
|
||||||
let res = unsafe { libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags) };
|
let res = unsafe { libc::syscall(libc::SYS_memfd_create, name.as_ptr(), flags) };
|
||||||
|
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
|
@ -239,7 +239,7 @@ impl VsockPacket {
|
|||||||
/// Provides in-place, byte-slice, access to the vsock packet header.
|
/// Provides in-place, byte-slice, access to the vsock packet header.
|
||||||
///
|
///
|
||||||
pub fn hdr(&self) -> &[u8] {
|
pub fn hdr(&self) -> &[u8] {
|
||||||
// This is safe since bound checks have already been performed when creating the packet
|
// SAFETY: bound checks have already been performed when creating the packet
|
||||||
// from the virtq descriptor.
|
// from the virtq descriptor.
|
||||||
unsafe { std::slice::from_raw_parts(self.hdr as *const u8, VSOCK_PKT_HDR_SIZE) }
|
unsafe { std::slice::from_raw_parts(self.hdr as *const u8, VSOCK_PKT_HDR_SIZE) }
|
||||||
}
|
}
|
||||||
@ -247,7 +247,7 @@ impl VsockPacket {
|
|||||||
/// Provides in-place, byte-slice, mutable access to the vsock packet header.
|
/// Provides in-place, byte-slice, mutable access to the vsock packet header.
|
||||||
///
|
///
|
||||||
pub fn hdr_mut(&mut self) -> &mut [u8] {
|
pub fn hdr_mut(&mut self) -> &mut [u8] {
|
||||||
// This is safe since bound checks have already been performed when creating the packet
|
// SAFETY: bound checks have already been performed when creating the packet
|
||||||
// from the virtq descriptor.
|
// from the virtq descriptor.
|
||||||
unsafe { std::slice::from_raw_parts_mut(self.hdr, VSOCK_PKT_HDR_SIZE) }
|
unsafe { std::slice::from_raw_parts_mut(self.hdr, VSOCK_PKT_HDR_SIZE) }
|
||||||
}
|
}
|
||||||
@ -261,7 +261,7 @@ impl VsockPacket {
|
|||||||
/// is stored in the packet header, and accessible via `VsockPacket::len()`.
|
/// is stored in the packet header, and accessible via `VsockPacket::len()`.
|
||||||
pub fn buf(&self) -> Option<&[u8]> {
|
pub fn buf(&self) -> Option<&[u8]> {
|
||||||
self.buf.map(|ptr| {
|
self.buf.map(|ptr| {
|
||||||
// This is safe since bound checks have already been performed when creating the packet
|
// SAFETY: bound checks have already been performed when creating the packet
|
||||||
// from the virtq descriptor.
|
// from the virtq descriptor.
|
||||||
unsafe { std::slice::from_raw_parts(ptr as *const u8, self.buf_size) }
|
unsafe { std::slice::from_raw_parts(ptr as *const u8, self.buf_size) }
|
||||||
})
|
})
|
||||||
@ -276,7 +276,7 @@ impl VsockPacket {
|
|||||||
/// is stored in the packet header, and accessible via `VsockPacket::len()`.
|
/// is stored in the packet header, and accessible via `VsockPacket::len()`.
|
||||||
pub fn buf_mut(&mut self) -> Option<&mut [u8]> {
|
pub fn buf_mut(&mut self) -> Option<&mut [u8]> {
|
||||||
self.buf.map(|ptr| {
|
self.buf.map(|ptr| {
|
||||||
// This is safe since bound checks have already been performed when creating the packet
|
// SAFETY: bound checks have already been performed when creating the packet
|
||||||
// from the virtq descriptor.
|
// from the virtq descriptor.
|
||||||
unsafe { std::slice::from_raw_parts_mut(ptr, self.buf_size) }
|
unsafe { std::slice::from_raw_parts_mut(ptr, self.buf_size) }
|
||||||
})
|
})
|
||||||
@ -383,6 +383,7 @@ impl VsockPacket {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#[cfg(test)]
|
#[cfg(test)]
|
||||||
|
#[allow(clippy::undocumented_unsafe_blocks)]
|
||||||
mod tests {
|
mod tests {
|
||||||
use super::super::tests::TestContext;
|
use super::super::tests::TestContext;
|
||||||
use super::*;
|
use super::*;
|
||||||
|
@ -334,6 +334,7 @@ impl VsockMuxer {
|
|||||||
// device activation time.
|
// device activation time.
|
||||||
let epoll_fd = epoll::create(true).map_err(Error::EpollFdCreate)?;
|
let epoll_fd = epoll::create(true).map_err(Error::EpollFdCreate)?;
|
||||||
// Use 'File' to enforce closing on 'epoll_fd'
|
// Use 'File' to enforce closing on 'epoll_fd'
|
||||||
|
// SAFETY: epoll_fd is a valid fd
|
||||||
let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
|
let epoll_file = unsafe { File::from_raw_fd(epoll_fd) };
|
||||||
|
|
||||||
// Open/bind/listen on the host Unix socket, so we can accept host-initiated
|
// Open/bind/listen on the host Unix socket, so we can accept host-initiated
|
||||||
|
@ -235,6 +235,7 @@ impl Watchdog {
|
|||||||
error!("Failed to create timer fd {}", e);
|
error!("Failed to create timer fd {}", e);
|
||||||
e
|
e
|
||||||
})?;
|
})?;
|
||||||
|
// SAFETY: timer_fd is a valid fd
|
||||||
let timer = unsafe { File::from_raw_fd(timer_fd) };
|
let timer = unsafe { File::from_raw_fd(timer_fd) };
|
||||||
|
|
||||||
Ok(Watchdog {
|
Ok(Watchdog {
|
||||||
@ -280,6 +281,7 @@ impl Drop for Watchdog {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn timerfd_create() -> Result<RawFd, io::Error> {
|
fn timerfd_create() -> Result<RawFd, io::Error> {
|
||||||
|
// SAFETY: FFI call, trivially safe
|
||||||
let res = unsafe { libc::timerfd_create(libc::CLOCK_MONOTONIC, 0) };
|
let res = unsafe { libc::timerfd_create(libc::CLOCK_MONOTONIC, 0) };
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
Err(io::Error::last_os_error())
|
Err(io::Error::last_os_error())
|
||||||
@ -301,6 +303,7 @@ fn timerfd_setup(timer: &File, secs: i64) -> Result<(), io::Error> {
|
|||||||
};
|
};
|
||||||
|
|
||||||
let res =
|
let res =
|
||||||
|
// SAFETY: FFI call with correct arguments
|
||||||
unsafe { libc::timerfd_settime(timer.as_raw_fd(), 0, &periodic, std::ptr::null_mut()) };
|
unsafe { libc::timerfd_settime(timer.as_raw_fd(), 0, &periodic, std::ptr::null_mut()) };
|
||||||
|
|
||||||
if res < 0 {
|
if res < 0 {
|
||||||
|
Loading…
Reference in New Issue
Block a user