`Demuxer` can carry non-Send types across thread boundaries
JOE1994 opened this issue Β· comments
Hello π¦ , we (Rust group @sslab-gatech) found an undefined-behavior issue in this crate while scanning Rust code on crates.io for potential vulnerabilities.
Issue
Send
is unconditionally implemented for Demuxer
, so that it is possible for a non-Send implementor of DemuxerEvents
trait to be sent across thread boundaries.
unsafe impl<T> Send for Demuxer<T> where T: DemuxerEvents {}
Proof of Concept
Here is a simple program where Demuxer
is used to move a MutexGuard
(!Send
object) to another thread.
It is also possible to create data races by inserting non-Send types like Rc
or Cell
into Demuxer
(which is not demonstrated in the example code below).
use va_ts::{Demuxer, DemuxerEvents, SubtableID, DemuxedPacket, DemuxedTable};
use std::sync::{Mutex, MutexGuard};
use std::thread::{self, ThreadId};
use std::ops::Drop;
struct X(MutexGuard<'static, u64>, ThreadId);
impl DemuxerEvents for X {
fn on_table(&mut self, _: SubtableID, _: &DemuxedTable) { }
fn on_packet(&mut self, _: &DemuxedPacket) { }
}
impl Drop for X {
fn drop(&mut self) {
// `MutexGuard` must not be dropped from a thread that didn't lock the `Mutex`.
//
// If a thread attempts to unlock a Mutex that it has not locked, it can result in undefined behavior.
// (https://github.com/rust-lang/rust/issues/23465#issuecomment-82730326)
assert_eq!(self.1, thread::current().id());
}
}
fn main() {
let static_mutex = Box::leak(Box::new(Mutex::new(0xbeefbeef_u64)));
// MutexGuard is `!Send`
let mutex_guard = static_mutex.lock().unwrap();
let tid = thread::current().id();
let demuxer = Demuxer::new(X(mutex_guard, tid));
std::thread::spawn(move || {
let demuxer = demuxer;
// demuxer is dropped here, along with `MutexGuard`.
}).join().unwrap();
}
Suggested Fix
Adding a trait bound T: Send
as below will allow the compiler to prevent Demuxer
from moving !Send
types across thread boundaries.
unsafe impl<T> Send for Demuxer<T> where T: DemuxerEvents + Send {}
Thank you for reviewing this issue π
Hello!
Thanks a lot!
Thank you for accepting the fix π
Would you also mind publishing a new release containing the fix to crates.io ?
No problem :) New release uploaded. Thanks!