-
Notifications
You must be signed in to change notification settings - Fork 109
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Put shared buffer into UnsafeCell #185
Conversation
c5c8267
to
d8a7afd
Compare
core/src/shared_memory.rs
Outdated
driver_number: usize, | ||
allow_number: usize, | ||
buffer_to_share: &'a mut [u8], | ||
buffer_to_share: UnsafeCell<T>, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I think this is wrong! Instead of enforcing to pass an array reference which would pin the referenced array it is now possible to pass an entire array. This should result in UB once you move the SharedMemory
object around.
Why not change the signature to UnsafeCell<&'a mut [u8]>
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good point, I fixed this.
core/src/shared_memory.rs
Outdated
pub fn write_bytes<T: AsRef<[u8]>>(&mut self, source: T) { | ||
safe_copy(source.as_ref(), self.buffer_to_share); | ||
pub fn write_bytes<S: AsRef<[u8]>>(&mut self, source: S) { | ||
let buf = unsafe { (*self.buffer_to_share.get()).as_mut() }; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why not delegate this to operate_on_mut_ptr
?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good idea!
core/src/shared_memory.rs
Outdated
safe_copy(source.as_ref(), buf); | ||
} | ||
|
||
pub(crate) unsafe fn operate_on_mut_ptr<R: Sized, F: FnOnce(*mut u8) -> R>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
- Couldn't this be transformed to a safe function where
F: FnOnce(&mut u8) ->R
? - Shouldn't
R: Sized
be implicit?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Right!
@@ -45,6 +45,12 @@ pub struct AdcBuffer { | |||
buffer: [u8; BUFFER_SIZE], | |||
} | |||
|
|||
impl AsMut<[u8]> for AdcBuffer { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You no longer need this.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I would prefer if all AsRef
and AsMut
implementations were removed until we see the need for them.
EDIT: "derefenceable" in this post refers to LLVM's dereferenceable attribute: https://llvm.org/docs/LangRef.html#dereferenceable-metadata
|
@jrvanwhy I have issues understanding your comment.
But it is unsafe.
raw pointers are also dereferenceable but this is unsafe. I have issues understanding your code snippet. In my eyes AllowRegion::get should be unsafe as it dereferences arbitrary pointers. But the whole point of using an |
I should clarify: when I said "dereferenceable" in my previous comment, I was referring to LLVM's dereferenceable attribute: https://llvm.org/docs/LangRef.html#dereferenceable-metadata. In Rust, references (including references to UnsafeCell) are deferenceable but raw pointers are not. |
I don't understand how this exactly relates to the issue this PR is aiming to solve and from what I understand the problem you are trying to solve is beyond the aliasing rules of Rust in particular and probably also beyond the safety guarantuees of Rust in general. Your proposal (from the code snippet) is about implementing an alternative to My proposal is: Let us merge this PR once it improves the library safety-wise. Open an issue (or more...) describing the exact problem the implementation still has and let us develop a PR fixing this particular problem after this PR is merged. |
It is undefined behavior to have a
This PR has no effect on the library's memory safety properties. As-is, it does not remove any source of undefined behavior. |
Thank you for the reference to the issue (#33), I didn't know it and I am happy to learn about that from you.
This depends on the perspective, still. From the perspective of what is currently (i.e. merged to master) consensus (i.e. https://doc.rust-lang.org/stable/reference/behavior-considered-undefined.html) this PR removes a source of UB. However, I still would recommend to not do your suggested change in this PR, for two reasons:
I would at least consider https://github.com/rust-embedded/wg/pull/387/files#diff-deb4784915d448685e0ca924234ecc03R476, i.e. waiting until the issues with |
Ah, I didn't think about that document. I agree, this PR does remove a documented source of UB. |
@jrvanwhy So would it make sense to merge this PR in your eyes? |
I think so. That said, I expect to refactor the syscall/platform code soon. My current TODO list is as follows:
Note that license header tooling may become my top priority (based on past core WG meetings) somewhere in there, but I don't expect that to take too long. |
So as this PR has two approvals can someone do a "bors r+", please? |
Could you remove the |
syscalls::allow(DRIVER_NUMBER, allow_nr::BUFFER, &mut buffer.buffer).map_err(Into::into) | ||
} | ||
|
||
pub fn init_alt_buffer(&self, alt_buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory> { | ||
pub fn init_alt_buffer(&self, alt_buffer: &'a mut AdcBuffer) -> TockResult<SharedMemory<'a>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Could you revert this?
@@ -87,15 +123,15 @@ pub struct HmacDriver<'a> { | |||
} | |||
|
|||
impl<'a> HmacDriver<'a> { | |||
pub fn init_key_buffer(&self, buffer: &'a mut HmacKeyBuffer) -> TockResult<SharedMemory> { | |||
pub fn init_key_buffer(&self, buffer: &'a mut HmacKeyBuffer) -> TockResult<SharedMemory<'a>> { |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
And this.
} | ||
pub fn initialize<'a>( | ||
pub fn initialize<'a, 'b>( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Do we need a second lifetime here?
|
||
const EMPTY_SCAN_BUFFER: ScanBuffer = [0; BUFFER_SIZE_SCAN]; | ||
const EMPTY_SCAN_BUFFER: ScanBuffer = ScanBuffer([0; BUFFER_SIZE_SCAN]); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revert?
pub fn create_advertising_buffer() -> [u8; BUFFER_SIZE_ADVERTISE] { | ||
[0; BUFFER_SIZE_ADVERTISE] | ||
pub fn create_advertising_buffer() -> BleAdvertisingBuffer { | ||
BleAdvertisingBuffer([0; BUFFER_SIZE_ADVERTISE]) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Revert this?
The Tock 1.0 |
Summary
This PR attempts to solve #129: Currently shared memory contains a mutable reference to a buffer which can be mutated by the kernel. This violates the pointer aliasing rules and can lead to undefined behavior. To circumvent this we replace this buffer by an
UnsafeCell
solving this issue.Limitations
The following aspects are not touched by this PR:
mem::forget
the kernel without calling drop and reuse the memory still shared with the kernel (see Subscriptions and shared memory have a loophole which can lead to UB #143).Both issues could be solved by taking one of the approaches proposed in #143, however this is not the content of this PR (and an appropriate solution has not yet been chosen).