-
Notifications
You must be signed in to change notification settings - Fork 51
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
Is it safe to implement SharedMemCast for bool? #33
Comments
cc @nox |
Regular use of a bool that lives in the shared memory should be safe (ie: manipulated/initialized through the structs traits) In contrast for example, the regular use of Vec in the shmem is unsafe as some Vec traits manipulate the backing allocation (alloc/realloc/etc...) |
How? Anything that crosses the process boundary should be untrusted, there is no guarantee that the value is actually a bool as Rust means it on the other side. |
This is UB and does not use any unsafe code. Please reopen this issue. use ::shared_memory::*;
use std::ffi::{CStr, CString};
static GLOBAL_LOCK_ID: usize = 0;
fn main() -> Result<(), SharedMemError> {
let mut shmem = match SharedMem::create_linked("shared_mem.link", LockType::Mutex, 4096) {
// We created and own this mapping
Ok(v) => v,
// Link file already exists
Err(SharedMemError::LinkExists) => SharedMem::open_linked("shared_mem.link")?,
Err(e) => return Err(e),
};
{
let mut shared_state = shmem.wlock::<u8>(GLOBAL_LOCK_ID)?;
**shared_state = 2;
}
println!("{:?}", *shmem.rlock::<bool>(GLOBAL_LOCK_ID)?);
Ok(())
} |
You can also do |
Also note that for similar reasons, the implementations for |
+1 on reopening. |
I just realised that it also makes the impls for |
Not sure about that last comment, though it depends on what you think the contract for AtomicBool is. Why is AtomicUsize unsound? |
Ah, it's because you can use a read-write lock to access the same shared memory both at type |
That raises a related issue, which is whether the implementation of |
I see what you're saying now. I will re-open the issue. If I look at shared_memory's behavior with your point of view, then the whole crate is essentially unsafe. This is simply the inherent unsafety of sharing memory between two processes (regardless of languages)... Both processes have to agree exactly on what the memory represents or nothing will work, there is simply no way around this. This can be clearly highlighted when using
As highligted in this issue, some of these can be done with "safe" usage of this crate... This is also ignoring the fact that the rust ABI is not stable which could lead to even more subtle issues. Im open to suggestions on how to fix this but unfortunately, i believe the only way to get the message across to the users of the crate is to mark essentially 90% of the API unsafe, eg :
Unforunately, this would essentialy render the API a pain in the @$* to use... Thoughts ? |
Thanks for re-opening! One way of dealing this would be to be explicit about the attacker model: is the crate intended to be safe against all attackers, or just ones written in Rust? Defending against all attackers is the goal of I think a fair bit of the API for |
I feel like many parts of the crate could be safe and sound, and that maybe its scope should be reduced while we look for the perfect set of safe primitives, for example, what would you think of removing the casting infrastructure to make the crate only be about reading and writing bytes in shared memory?
I’ll file another issue for the usage on non-anonymous memory-mapped files, because that also leads to soundness issues.
Thanks for reopening btw!
|
I guess even |
Yeap good point, I could strip the whole Deref/Casting feature and simply return raw pointers to the shared memory and let the callers handle those the way they want. In addition, I would have to strip the lock/events out of the crate as they make a lot of assumptions about the shmem contents being valid but I was thinking of doing so anyways for #29 Essentialy, this would simplify the |
@elast0ny I can make a home for There's still the issue of truncation for anyone who ever wants to use one of the raw pointers, but that would then be my issue :) |
I was playing around with this crate a bit to make it work with procspawn / mitosis. I think what would be possible to make safe is a pattern like this: #[derive(SharedMemCast)]
pub struct SharedState {
did_something: bool,
}
fn main() {
procspawn::init();
let region = shared_memory::Region::new(SharedState {
did_something: false,
});
procspawn::spawn(region.clone(), |region| {
let state = region.wlock().unwrap();
state.did_something = true;
}).join().unwrap();
let state = region.rlock().unwrap();
assert_eq!(state.did_something, true);
} This way you can't unsafely have the wrong type on the subprocess. It's already easily possible to implement this type of thing on top of the systems that exist. |
What's |
This issue can finally be closed. I have decided to remove all shared memory casting and exposed an This now removes all the safety issues highlighted in this thread from the crate. |
One of the requirements for bool is that it only has the values
0x00
and0x01
, so there is a possible safety issue around havingbool
implementSharedMemCast
.The text was updated successfully, but these errors were encountered: