From 4457af72776943ca0a68c4a7824740e1b468360c Mon Sep 17 00:00:00 2001 From: pca006132 Date: Thu, 16 Jul 2020 14:06:39 +0800 Subject: [PATCH] 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. --- src/runtime/src/rpc.rs | 17 +++++++++++++++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/src/runtime/src/rpc.rs b/src/runtime/src/rpc.rs index 36fb791e..9d3e1185 100644 --- a/src/runtime/src/rpc.rs +++ b/src/runtime/src/rpc.rs @@ -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(ptr: *const ()) -> *const T { + let alignment = core::mem::align_of::() as isize; + let fix = (alignment - (ptr as isize) % alignment) % alignment; + ((ptr as isize) + fix) as *const T +} + +unsafe fn align_ptr_mut(ptr: *mut ()) -> *mut T { + let alignment = core::mem::align_of::() 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(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(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(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(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)?;