-
Notifications
You must be signed in to change notification settings - Fork 12.7k
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
Insufficient synchronization in Arc::get_mut
#51780
Comments
Actually, the race also exists if we were not using |
That bug was discovered while trying to formally prove soundness of |
Another bug found by formal verification :) |
I should emphasize that this new version of the bug does not use |
Arc::get_mut
Arc::get_mut
More detail on this: The bug was found while Hai (@hans89), Derek and me were trying to formally verify |
This may be confusing because I claimed previously that we (that was including @jhjourdan) already had verified |
@jhjourdan Can you update the original issue with the new version that doesn't use mem::forget? Leakpocalypse is what my mind immediately jumped to upon seeing that example. |
@bstrie here's the code: extern crate rayon;
use std::sync::Arc;
use rayon::join;
fn main() {
let a1 = Arc::new(0);
let mut a2 = a1.clone();
join(
|| {
let _ : u32 = *a1;
drop(a1);
},
|| {
loop {
match Arc::get_mut(&mut a2) {
None => {}
Some(m) => {
*m = 1u32;
return;
}
}
}
}
);
} The read and write access satisfy the condition of a race according to C11: Two accesses not ordered by happens-before, at least one a write, and at least one non-atomic. (It is debatable whether this should be a race because it seems no compiler optimization actually invalidates said code. But that's a different question.) |
Previously, `is_unique` would not synchronize at all with a `drop` that returned early because it was not the last reference, leading to a data race. Fixes rust-lang#51780
Strenghten synchronization in `Arc::is_unique` Previously, `is_unique` would not synchronize at all with a `drop` that returned early because it was not the last reference, leading to a data race. Fixes rust-lang#51780 Unfortunately I have no idea how to add a test for this. Cc @jhjourdan
Consider the following Rust code:
The first thread acquires the lock, modifies the variable, and then drop its Arc without unlocking (that's the point of the
mem::forget
).The second thread waits until the first thread decrements the count by dropping its Arc, and then uses
get_mut
to access the content without taking the lock (at that time, the mutex is still locked).My claim is that there is a race between the two accesses of the content of the mutex. The only reason the two accesses would be in a happens-before relationship would be that
Arc::drop
andArc::get_mut
would establish this happens-before relationship. However, even thoughArc::drop
does use a release write,Arc::get_mut
only uses a relaxed read of the strong counter (viais_unique
).The fix is to use an acquire read in
is_unique
. I do not expect significant performance penalty here, sinceis_unique
already contains several release-acquire accesses (of the weak count).CC @RalfJung
EDIT
As @RalfJung noted, we do not actually need leaking memory to exploit this bug (hence this is not another instance of Leakpocalypse). The following piece of code exhibit the same problem:
The text was updated successfully, but these errors were encountered: