rpc: Fixed alignment problem.

Fixes issue #42.

Previously there was no fix for the variable alignment.
We calculate the position of the variable based on the size
of the previous variable, so we could break the alignment requirement
for variables. For example, having a `i64` after `bool` could break
the alignment required for `i64` and trigger DataAbort or data
corruption.

However, this requires the same data layout and LLVM type for the
variables. If this cannot be maintained, this would break the alignment
on the other side of the RPC, either from host to kernel or kernel to
host.
This commit is contained in:
pca006132 2020-07-16 14:06:39 +08:00
parent 2e10922715
commit 4457af7277
1 changed files with 15 additions and 2 deletions

View File

@ -13,6 +13,18 @@ use crate::proto_core_io::ProtoWrite;
use crate::proto_async;
use self::tag::{Tag, TagIterator, split_tag};
unsafe fn align_ptr<T>(ptr: *const ()) -> *const T {
let alignment = core::mem::align_of::<T>() as isize;
let fix = (alignment - (ptr as isize) % alignment) % alignment;
((ptr as isize) + fix) as *const T
}
unsafe fn align_ptr_mut<T>(ptr: *mut ()) -> *mut T {
let alignment = core::mem::align_of::<T>() as isize;
let fix = (alignment - (ptr as isize) % alignment) % alignment;
((ptr as isize) + fix) as *mut T
}
#[async_recursion(?Send)]
async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, data: &mut *mut (),
alloc: &(impl Fn(usize) -> F + 'async_recursion))
@ -21,7 +33,7 @@ async unsafe fn recv_value<F>(stream: &TcpStream, tag: Tag<'async_recursion>, da
{
macro_rules! consume_value {
($ty:ty, |$ptr:ident| $map:expr) => ({
let $ptr = (*data) as *mut $ty;
let $ptr = align_ptr_mut::<$ty>(*data);
*data = $ptr.offset(1) as *mut ();
$map
})
@ -108,7 +120,7 @@ unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
{
macro_rules! consume_value {
($ty:ty, |$ptr:ident| $map:expr) => ({
let $ptr = (*data) as *const $ty;
let $ptr = align_ptr::<$ty>(*data);
*data = $ptr.offset(1) as *const ();
$map
})
@ -142,6 +154,7 @@ unsafe fn send_value<W>(writer: &mut W, tag: Tag, data: &mut *const ())
Ok(())
}
Tag::List(it) | Tag::Array(it) => {
#[repr(C)]
struct List { elements: *const (), length: u32 };
consume_value!(List, |ptr| {
writer.write_u32((*ptr).length)?;