You signed in with another tab or window. Reload to refresh your session.You signed out in another tab or window. Reload to refresh your session.You switched accounts on another tab or window. Reload to refresh your session.Dismiss alert
Currently AtomicOption implements Sync for any type. However, this should really be bounded by T: Sync, otherwise it allows for types that were never meant to be used across threads to be smuggled across boundaries through the use of an &AtomicOption. (Issue found by @Qwaz).
See this example of using AtomicOption to use a Cell across thread boundaries, leading to an arbitrary pointer dereference:
#![forbid(unsafe_code)]use atomic_option::AtomicOption;use crossbeam_utils::thread;use std::{cell::Cell, sync::atomic::Ordering};staticSOME_INT:u64 = 123;fnmain(){#[derive(Debug,Clone,Copy)]enumRefOrInt<'a>{Ref(&'a u64),Int(u64),}let cell = Cell::new(RefOrInt::Ref(&SOME_INT));let atomic_opt = AtomicOption::new(Box::new(&cell));let ref_to_atomic_opt = &atomic_opt;
thread::scope(|s| {
s.spawn(move |_| {let cell_in_thread = *(ref_to_atomic_opt.take(Ordering::Relaxed).unwrap());println!("Thread - {:p} - {:?}", cell_in_thread, cell_in_thread);loop{// Repeatedly write Ref(&addr) and Int(0xdeadbeef) into the cell.
cell_in_thread.set(RefOrInt::Ref(&SOME_INT));
cell_in_thread.set(RefOrInt::Int(0xdeadbeef));}});println!("Main - {:p} - {:?}", &cell, cell);loop{ifletRefOrInt::Ref(addr) = cell.get(){// Hope that between the time we pattern match the object as a// `Ref`, it gets written to by the other thread.if addr as*constu64 == &SOME_INTas*constu64{continue;}// Due to the data race, obtaining Ref(0xdeadbeef) is possibleprintln!("Pointer is now: {:p}", addr);println!("Dereferencing addr will now segfault: {}", *addr);}}});}
It seems to me that AtomicOption<T> not only needs T: Sync but also T: Send,
in order to prevent smuggling non-Send types like std::sync::MutexGuard<T> to other threads.
I don't think T: Sync is necessary because AtomicOption<T> doesn't let you borrow T while T is in AtomicOption - it just lets you move T between places. On the other hand, T: Send is undoubtedly necessary. (Actually, T: Send is enough for the example in the issue description to be rejected because in this case T is &Cell<_>, not Cell<_>.)
Currently
AtomicOption
implementsSync
for any type. However, this should really be bounded byT: Sync
, otherwise it allows for types that were never meant to be used across threads to be smuggled across boundaries through the use of an&AtomicOption
. (Issue found by @Qwaz).See this example of using
AtomicOption
to use aCell
across thread boundaries, leading to an arbitrary pointer dereference:Output:
Return Code: -11 (SIGSEGV)
The text was updated successfully, but these errors were encountered: