actix-web: InternalError can trigger memory unsafety (such as use-after-free or double-free)
There is an unsafe impl Send<T> for InternalError<T>
, making it so one can construct an InternalError
with any type, and accidentally send it to another thread. However, the implementation of InternalError
isn’t actually safe to implement Send
for any T
.
Consider this example:
let my_err = Rc::new("foobar".to_owned());
let int_err = InternalError::new(my_err.clone(), StatusCode::BAD_REQUEST);
thread::spawn(move || {
let _moved = int_err;
// clone 1 dropped
})
let my_err2 = my_err.clone();
// clone 2 dropped
// orig dropped
The drop of the InternalError
in the other thread can cause the ref count to race with the clone in the first thread. It’s now possible that the 2nd drop (out of 3) will free the allocation. Using the 3rd (the original) afterwards would cause use-after-free bugs. Finally dropping it would cause a double-free.
Seems related to #289
About this issue
- Original URL
- State: closed
- Created 6 years ago
- Reactions: 4
- Comments: 15 (10 by maintainers)
Commits related to this issue
- InternalError can trigger memory unsafety #301 — committed to actix/actix-web by fafhrd91 6 years ago
- InternalError can trigger memory unsafety #301 — committed to actix/actix-web by fafhrd91 6 years ago
- do not allow stream or actor responses for internal error #301 — committed to actix/actix-web by fafhrd91 6 years ago
- do not allow stream or actor responses for internal error #301 — committed to actix/actix-web by fafhrd91 6 years ago
I’m just reporting a memory unsafety bug I noticed that can be triggered in safe Rust (safe from a user’s perspective). I didn’t see an issue mentioning it, so I thought I’d bring it up in case it was missed!
@seanmonstar do you think I don’t understand
impl Send
? 😃If not another ticket, shouldn’t this issue be re-opened for now? It would be good to have an open record, especially if anyone else comes across it and has an idea for the fix.
@anderejd Please see #289
FWIW, the problem doesn’t exist because of
failure
. It’s theunsafe impl
ofSend
andSync
. If those impls were removed, then just the default ones would exist, which are safe.This is absolutely conscious decision.