Skip to content

Commit 0be7aed

Browse files
committed
add code for CVE, fix issue, ensure CVE doesn't compile anymore
1 parent 8745b65 commit 0be7aed

File tree

4 files changed

+148
-13
lines changed

4 files changed

+148
-13
lines changed

examples/cve_2020_36470_example1.rs

Lines changed: 43 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,43 @@
1+
// #![forbid(unsafe_code)]
2+
3+
// use disrustor::internal::RingBuffer;
4+
5+
// use std::marker::PhantomData;
6+
// use std::thread;
7+
8+
// struct NonSend {
9+
// created_thread: thread::ThreadId,
10+
// // Mark this struct as `NonSend`
11+
// _marker: PhantomData<*mut ()>,
12+
// }
13+
14+
// impl Default for NonSend {
15+
// fn default() -> Self {
16+
// NonSend {
17+
// created_thread: thread::current().id(),
18+
// _marker: PhantomData,
19+
// }
20+
// }
21+
// }
22+
23+
// impl Drop for NonSend {
24+
// fn drop(&mut self) {
25+
// if thread::current().id() != self.created_thread {
26+
// panic!("NonSend destructor is running on a wrong thread!");
27+
// }
28+
// }
29+
// }
30+
31+
// fn main() {
32+
// let buffer = RingBuffer::<NonSend>::new(1);
33+
34+
// let handle = thread::spawn(move || {
35+
// drop(buffer);
36+
// });
37+
38+
// handle.join().unwrap();
39+
// }
40+
41+
fn main() {
42+
println!("CVE-2020-36470 no longer compiles")
43+
}

examples/cve_2020_36470_example2.rs

Lines changed: 68 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,68 @@
1+
// #![forbid(unsafe_code)]
2+
3+
// use std::cell::Cell;
4+
// use std::sync::Arc;
5+
// use std::thread;
6+
7+
// use disrustor::internal::RingBuffer;
8+
// use disrustor::DisrustorBuilder;
9+
// use disrustor::EventProducer;
10+
11+
// // A simple tagged union used to demonstrate problems with data races in Cell.
12+
// #[derive(Clone, Copy)]
13+
// enum RefOrInt {
14+
// Ref(&'static u64),
15+
// Int(u64),
16+
// }
17+
18+
// static STATIC_INT: u64 = 123;
19+
20+
// impl Default for RefOrInt {
21+
// fn default() -> Self {
22+
// RefOrInt::Ref(&STATIC_INT)
23+
// }
24+
// }
25+
26+
// fn main() {
27+
// let provider = Arc::new(RingBuffer::<Cell<RefOrInt>>::new(1));
28+
// let provider_cloned = provider.clone();
29+
30+
// thread::spawn(move || {
31+
// let (_executor, producer) = DisrustorBuilder::new(provider_cloned)
32+
// .with_spin_wait()
33+
// .with_single_producer()
34+
// .with_barrier(|_| {})
35+
// .build();
36+
37+
// producer.write(std::iter::once(()), |slot, _seq, _item| loop {
38+
// // Repeatedly write Ref(&addr) and Int(0xdeadbeef) into the cell.
39+
// *slot.get_mut() = RefOrInt::Ref(&STATIC_INT);
40+
// *slot.get_mut() = RefOrInt::Int(0xdeadbeef);
41+
// });
42+
// });
43+
44+
// let (_executor, producer) = DisrustorBuilder::new(provider.clone())
45+
// .with_spin_wait()
46+
// .with_single_producer()
47+
// .with_barrier(|_| {})
48+
// .build();
49+
50+
// producer.write(std::iter::once(()), |slot, _seq, _item| {
51+
// loop {
52+
// if let RefOrInt::Ref(addr) = slot.get() {
53+
// // Hope that between the time we pattern match the object as a
54+
// // `Ref`, it gets written to by the other thread.
55+
// if addr as *const u64 == &STATIC_INT as *const u64 {
56+
// continue;
57+
// }
58+
59+
// println!("Pointer is now: {:p}", addr);
60+
// println!("Dereferencing addr will now segfault: {}", *addr);
61+
// }
62+
// }
63+
// });
64+
// }
65+
66+
fn main() {
67+
println!("CVE-2020-36470 no longer compiles")
68+
}

src/dsl.rs

Lines changed: 34 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -4,17 +4,26 @@ use std::{marker::PhantomData, sync::Arc};
44
#[derive(Debug)]
55
pub struct DisrustorBuilder {}
66

7-
pub struct WithDataProvider<D: DataProvider<T>, T> {
7+
pub struct WithDataProvider<D: DataProvider<T>, T>
8+
where
9+
T: Send + Sync,
10+
{
811
data_provider: Arc<D>,
912
_element: PhantomData<T>,
1013
}
1114

12-
pub struct WithWaitStrategy<W: WaitStrategy, D: DataProvider<T>, T> {
15+
pub struct WithWaitStrategy<W: WaitStrategy, D: DataProvider<T>, T>
16+
where
17+
T: Send + Sync,
18+
{
1319
with_data_provider: WithDataProvider<D, T>,
1420
_wait_strategy: PhantomData<W>,
1521
}
1622

17-
pub struct WithSequencer<S: Sequencer, W: WaitStrategy, D: DataProvider<T>, T> {
23+
pub struct WithSequencer<S: Sequencer, W: WaitStrategy, D: DataProvider<T>, T>
24+
where
25+
T: Send + Sync,
26+
{
1827
with_wait_strategy: WithWaitStrategy<W, D, T>,
1928
sequencer: S,
2029
}
@@ -28,27 +37,39 @@ pub struct BarrierScope<'a, S: Sequencer, D: DataProvider<T>, T> {
2837
_element: PhantomData<T>,
2938
}
3039

31-
pub struct WithEventHandlers<'a, S: Sequencer, W: WaitStrategy, D: DataProvider<T>, T> {
40+
pub struct WithEventHandlers<'a, S: Sequencer, W: WaitStrategy, D: DataProvider<T>, T>
41+
where
42+
T: Send + Sync,
43+
{
3244
with_sequencer: WithSequencer<S, W, D, T>,
3345
event_handlers: Vec<Box<dyn Runnable + 'a>>,
3446
gating_sequences: Vec<Arc<AtomicSequence>>,
3547
}
3648

3749
impl DisrustorBuilder {
3850
#[allow(clippy::new_ret_no_self)]
39-
pub fn new<D: DataProvider<T>, T>(data_provider: Arc<D>) -> WithDataProvider<D, T> {
51+
pub fn new<D: DataProvider<T>, T>(data_provider: Arc<D>) -> WithDataProvider<D, T>
52+
where
53+
T: Send + Sync,
54+
{
4055
WithDataProvider {
4156
data_provider,
4257
_element: Default::default(),
4358
}
4459
}
4560

46-
pub fn with_ring_buffer<T: Default>(capacity: usize) -> WithDataProvider<RingBuffer<T>, T> {
61+
pub fn with_ring_buffer<T: Default>(capacity: usize) -> WithDataProvider<RingBuffer<T>, T>
62+
where
63+
T: Send + Sync,
64+
{
4765
Self::new(Arc::new(RingBuffer::new(capacity)))
4866
}
4967
}
5068

51-
impl<D: DataProvider<T>, T> WithDataProvider<D, T> {
69+
impl<D: DataProvider<T>, T> WithDataProvider<D, T>
70+
where
71+
T: Send + Sync,
72+
{
5273
pub fn with_wait_strategy<W: WaitStrategy>(self) -> WithWaitStrategy<W, D, T> {
5374
WithWaitStrategy {
5475
with_data_provider: self,
@@ -65,7 +86,10 @@ impl<D: DataProvider<T>, T> WithDataProvider<D, T> {
6586
}
6687
}
6788

68-
impl<W: WaitStrategy, D: DataProvider<T>, T> WithWaitStrategy<W, D, T> {
89+
impl<W: WaitStrategy, D: DataProvider<T>, T> WithWaitStrategy<W, D, T>
90+
where
91+
T: Send + Sync,
92+
{
6993
pub fn with_sequencer<S: Sequencer>(self, sequencer: S) -> WithSequencer<S, W, D, T> {
7094
WithSequencer {
7195
with_wait_strategy: self,
@@ -84,7 +108,7 @@ impl<W: WaitStrategy, D: DataProvider<T>, T> WithWaitStrategy<W, D, T> {
84108
}
85109
}
86110

87-
impl<'a, S: Sequencer + 'a, W: WaitStrategy, D: DataProvider<T> + 'a, T: Send + 'a>
111+
impl<'a, S: Sequencer + 'a, W: WaitStrategy, D: DataProvider<T> + 'a, T: Send + Sync + 'a>
88112
WithSequencer<S, W, D, T>
89113
{
90114
pub fn with_barrier(
@@ -154,7 +178,7 @@ impl<'a, S: Sequencer + 'a, D: DataProvider<T> + 'a, T: Send + 'a> BarrierScope<
154178
}
155179
}
156180

157-
impl<'a, S: Sequencer + 'a, W: WaitStrategy, D: DataProvider<T> + 'a, T: Send + 'a>
181+
impl<'a, S: Sequencer + 'a, W: WaitStrategy, D: DataProvider<T> + 'a, T: Send + Sync + 'a>
158182
WithEventHandlers<'a, S, W, D, T>
159183
{
160184
pub fn with_barrier(mut self, f: impl FnOnce(&mut BarrierScope<'a, S, D, T>)) -> Self {

src/ringbuffer.rs

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -27,7 +27,7 @@ impl<T: Default> RingBuffer<T> {
2727
}
2828
}
2929

30-
impl<T> DataProvider<T> for RingBuffer<T> {
30+
impl<T: Send + Sync> DataProvider<T> for RingBuffer<T> {
3131
unsafe fn get_mut(&self, sequence: Sequence) -> &mut T {
3232
let index = sequence as usize & self.mask;
3333
let cell = self.data.get_unchecked(index);
@@ -45,8 +45,8 @@ impl<T> DataProvider<T> for RingBuffer<T> {
4545
}
4646
}
4747

48-
unsafe impl<T> Send for RingBuffer<T> {}
49-
unsafe impl<T> Sync for RingBuffer<T> {}
48+
unsafe impl<T: Send> Send for RingBuffer<T> {}
49+
unsafe impl<T: Sync> Sync for RingBuffer<T> {}
5050

5151
#[cfg(test)]
5252
mod test {

0 commit comments

Comments
 (0)