-
Notifications
You must be signed in to change notification settings - Fork 92
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
Wrong atomic ordering in Drop
impl for RwLockWriteGuard
and buggy lock acquisition failure in RwLock::try_read
#65
Comments
Drop
impl for RwLockWriteGuard
and issues in RwLock::try_read
Drop
impl for RwLockWriteGuard
and incorrect lock acquisition failure in RwLock::try_read
Drop
impl for RwLockWriteGuard
and incorrect lock acquisition failure in RwLock::try_read
Drop
impl for RwLockWriteGuard
and buggy lock acquisition failure in RwLock::try_read
Your first bug makes sense; blame that was my error years ago. Thanks for catching. I am confused by your second bug; if readers is incremented than the compare won't match and just another loop will happen: seems sub-optimal but not unsound? Feel free to take a stab at a rewrite. |
The problem is that there is an implicit expectation that Working on a fix - would you be okay with an implementation which includes upgradeable locks? I'll try and do a benchmark and show that performance doesn't suffer as a result. |
|
Oh right! There is no loop. Yeah I think I just took the code from the original to make the try version, not realizing about that difference in expectations. Upgradable is fine. I think std might even do that now? |
The vulnerability: ``` $ ./build-support/bin/ci.py --cargo-audit ... error: Vulnerable crates found! ID: RUSTSEC-2019-0013 Crate: spin Version: 0.5.1 Date: 2019-08-27 URL: mvdnes/spin-rs#65 Title: Wrong memory orderings in RwLock potentially violates mutual exclusion Solution: upgrade to: >= 0.5.2 error: 1 vulnerability found! Cargo audit failure ``` Although we don't directly depend on `spin`, we depend on `lazy_static` (amongst others) which does: ``` $ (cd src/rust/engine && ../../../build-support/bin/native/cargo tree -p spin -i) spin v0.5.2 ├── lazy_static v1.3.0 ... ``` So this change was generated with a targeted upgrade: ``` $ ./build-support/bin/native/cargo update --manifest-path src/rust/engine/Cargo.toml -p spin --aggressive ```
The vulnerability: ``` $ ./build-support/bin/ci.py --cargo-audit ... error: Vulnerable crates found! ID: RUSTSEC-2019-0013 Crate: spin Version: 0.5.1 Date: 2019-08-27 URL: mvdnes/spin-rs#65 Title: Wrong memory orderings in RwLock potentially violates mutual exclusion Solution: upgrade to: >= 0.5.2 error: 1 vulnerability found! Cargo audit failure ``` Although we don't directly depend on `spin`, we depend on `lazy_static` (amongst others) which does: ``` $ (cd src/rust/engine && ../../../build-support/bin/native/cargo tree -p spin -i) spin v0.5.2 ├── lazy_static v1.3.0 ... ``` So this change was generated with a targeted upgrade: ``` $ ./build-support/bin/native/cargo update --manifest-path src/rust/engine/Cargo.toml -p spin --aggressive ```
Multiple issues in the
RwLock
implementation.The first (and the worst) one is here:
Use of
Ordering::Relaxed
is incorrect. The compiler is free to reorder a write behind this, which could lead to two mutable refs being used at the same time (UB). It should beOrdering::Release
instead (maybe this was just a typo?). Other parts of this code use the needlessly strictSeqCst
ordering, but that's not a soundness issue.The second that I've found is a bug in the
try_read
function:The problem is that a different thread could increment the readers count on the indicated line, making the value that the CAS checks for incorrect - it might fail even if there are no writers at all. For example:
This code panics for me, even though it there are no writers so
try_read
should always succeed.To be frank, I think it would be better to simply rewrite this whole implementation. The original blog that this was implemented from uses the writers bit to allow for recursive write locking (which this crate doesn't) - I see no reason not to just use some sentinel value like -1 to indicate a writer is holding the lock.
The text was updated successfully, but these errors were encountered: