-
-
Notifications
You must be signed in to change notification settings - Fork 14.7k
Insufficient synchronization in Arc::get_mut #51780
Copy link
Copy link
Closed
Labels
C-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.
Metadata
Metadata
Assignees
Labels
C-bugCategory: This is a bug.Category: This is a bug.I-unsoundIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessIssue: A soundness hole (worst kind of bug), see: https://en.wikipedia.org/wiki/SoundnessT-libs-apiRelevant to the library API team, which will review and decide on the PR/issue.Relevant to the library API team, which will review and decide on the PR/issue.
Type
Fields
Give feedbackNo fields configured for issues without a type.
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_mutto 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::dropandArc::get_mutwould establish this happens-before relationship. However, even thoughArc::dropdoes use a release write,Arc::get_mutonly 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_uniquealready 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: