-
Notifications
You must be signed in to change notification settings - Fork 1
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
Unsoundness from panic on lock failure. #1
Comments
MitigationGenerally, I think panicking should be replaced with either
The current thread must continue living, but it can't continue any kind of execution at all, or the whole process should collapse. If supporting all of the // Safety: `lock_exclusive` is prevented from unwinding. See [issue #1](https://github.com/yvt/cryo/issues/1)
let unwind_safe_lock = std::panic::AssertUnwindSafe(lock);
match std::panic::catch_unwind(|| unsafe {
// I would have preferred to use a method returning a `Result`.
// However, the regular lock blocks on `lock_exclusive` but returns an error
// on `try_lock_exclusive`, so this doesn't work.
unwind_safe_lock.lock_exclusive()
}) {
Ok(_) => (),
Err(_) => std::process::abort(),
} or alternatively, loop until it succeeds. The |
The problem
When the
with_cryo
function completes, it must guarantee that any outstandingCryoRef
is gone. If any are left, it can't safely continue execution under any circumstances. In some cases (LocalLock
andAtomicLock
for example), this is done by panicking (specifically, unwinding). However, panics don't actually guarantee that execution will freeze, and this is unsound. There are a few ways to exploit this:When a panic is thrown in a thread and it isn't caught, it deallocated the
Cryo
and stops the execution of the thread. However, the rest of the threads keep running, which is unsafe because they might still hold theCryoRef
. This isExploit through multithreading
.Altertnatively, execution can continue using the
catch_unwind
, which is a safe, std function. It is guarded byUnwindSafe
, but it's merely a heuristic helper, not a safety guard (see UnwindSafe). This leads to unsoundness even in single threaded contexts. This isexploit through catch_unwind
.In addition, we can use the destructors called by the panic to use the leaked
CryoRef
. This isExploit through destructors
.Examples
Exploit through multithreading
Exploit through catch_unwind
Exploit through destructors
Other locks
This is most obvious in
LocalLock
andAtomicLock
, which panic on purpose. However, any edgecase that triggers a panic during lock acquisition will lead to the same unsoundness.In addition, this also applies to user-defined locks from outside this library, implemented through the
Cryo::Lock
trait. It is anunsafe
trait, but its interface doesn't restrict panicking in any way (and in fact, panicking is the expected behavior of thelock_exclusive
function). And, with thelock_api
feature, all the locks implementingRawRwLock
are also available, which can also panic freely.The text was updated successfully, but these errors were encountered: