summary refs log tree commit diff
path: root/src/plugin
diff options
context:
space:
mode:
authorDavid Tolnay <dtolnay@chromium.org>2019-04-12 16:57:48 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-04-18 19:51:29 -0700
commit4b292afafcd44ca3fc34f483a8edb455a3212cb5 (patch)
tree868bdb3122e088e33836cd48608d23518ee5a1d0 /src/plugin
parentdc4effa72b214bc3bd14ca2f7772ab1b728aef5b (diff)
downloadcrosvm-4b292afafcd44ca3fc34f483a8edb455a3212cb5.tar
crosvm-4b292afafcd44ca3fc34f483a8edb455a3212cb5.tar.gz
crosvm-4b292afafcd44ca3fc34f483a8edb455a3212cb5.tar.bz2
crosvm-4b292afafcd44ca3fc34f483a8edb455a3212cb5.tar.lz
crosvm-4b292afafcd44ca3fc34f483a8edb455a3212cb5.tar.xz
crosvm-4b292afafcd44ca3fc34f483a8edb455a3212cb5.tar.zst
crosvm-4b292afafcd44ca3fc34f483a8edb455a3212cb5.zip
clippy: Resolve cast_ptr_alignment
This CL fixes four cases of what I believe are undefined behavior:

  - In vhost where the original code allocates a Vec<u8> with 1-byte
    alignment and casts the Vec's data pointer to a &mut vhost_memory
    which is required to be 8-byte aligned. Underaligned references of
    type &T or &mut T are always undefined behavior in Rust.

  - Same pattern in x86_64.

  - Same pattern in plugin::vcpu.

  - Code in crosvm_plugin that dereferences a potentially underaligned
    pointer. This is always undefined behavior in Rust.

TEST=bin/clippy
TEST=cargo test sys_util

Change-Id: I926f17b1fe022a798f69d738f9990d548f40c59b
Reviewed-on: https://chromium-review.googlesource.com/1566736
Commit-Ready: David Tolnay <dtolnay@chromium.org>
Tested-by: David Tolnay <dtolnay@chromium.org>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: David Tolnay <dtolnay@chromium.org>
Diffstat (limited to 'src/plugin')
-rw-r--r--src/plugin/vcpu.rs29
1 files changed, 19 insertions, 10 deletions
diff --git a/src/plugin/vcpu.rs b/src/plugin/vcpu.rs
index eb7128c..d19a5f8 100644
--- a/src/plugin/vcpu.rs
+++ b/src/plugin/vcpu.rs
@@ -2,11 +2,12 @@
 // Use of this source code is governed by a BSD-style license that can be
 // found in the LICENSE file.
 
+use std::alloc::Layout;
 use std::cell::{Cell, RefCell};
 use std::cmp::min;
 use std::cmp::{self, Ord, PartialEq, PartialOrd};
 use std::collections::btree_set::BTreeSet;
-use std::mem::size_of;
+use std::mem;
 use std::os::unix::net::UnixDatagram;
 use std::sync::{Arc, RwLock};
 
@@ -15,6 +16,7 @@ use libc::{EINVAL, ENOENT, ENOTTY, EPERM, EPIPE, EPROTO};
 use protobuf;
 use protobuf::Message;
 
+use assertions::const_assert;
 use data_model::DataInit;
 use kvm::{CpuId, Vcpu};
 use kvm_sys::{
@@ -23,7 +25,7 @@ use kvm_sys::{
 };
 use protos::plugin::*;
 use sync::Mutex;
-use sys_util::error;
+use sys_util::{error, LayoutAllocation};
 
 use super::*;
 
@@ -451,16 +453,23 @@ impl PluginVcpu {
                 Err(e) => Err(e),
             }
         } else if request.has_set_msrs() {
+            const SIZE_OF_MSRS: usize = mem::size_of::<kvm_msrs>();
+            const SIZE_OF_ENTRY: usize = mem::size_of::<kvm_msr_entry>();
+            const ALIGN_OF_MSRS: usize = mem::align_of::<kvm_msrs>();
+            const ALIGN_OF_ENTRY: usize = mem::align_of::<kvm_msr_entry>();
+            const_assert!(ALIGN_OF_MSRS >= ALIGN_OF_ENTRY);
+
             response.mut_set_msrs();
             let request_entries = &request.get_set_msrs().entries;
-            let vec_size_bytes =
-                size_of::<kvm_msrs>() + (request_entries.len() * size_of::<kvm_msr_entry>());
-            let vec: Vec<u8> = vec![0; vec_size_bytes];
-            let kvm_msrs: &mut kvm_msrs = unsafe {
-                // Converting the vector's memory to a struct is unsafe.  Carefully using the read-
-                // only vector to size and set the members ensures no out-of-bounds erros below.
-                &mut *(vec.as_ptr() as *mut kvm_msrs)
-            };
+            let size = SIZE_OF_MSRS + request_entries.len() * SIZE_OF_ENTRY;
+            let layout = Layout::from_size_align(size, ALIGN_OF_MSRS).expect("impossible layout");
+            let mut allocation = LayoutAllocation::zeroed(layout);
+
+            // Safe to obtain an exclusive reference because there are no other
+            // references to the allocation yet and all-zero is a valid bit
+            // pattern.
+            let kvm_msrs = unsafe { allocation.as_mut::<kvm_msrs>() };
+
             unsafe {
                 // Mapping the unsized array to a slice is unsafe becase the length isn't known.
                 // Providing the length used to create the struct guarantees the entire slice is