Skip to content

Commit c78b2b4

Browse files
committed
update README.md, add references.rs, and change segfault to rely on dereferencing a null reference
1 parent b3825d3 commit c78b2b4

File tree

4 files changed

+31
-26
lines changed

4 files changed

+31
-26
lines changed

README.md

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,9 @@
11
<p align="center">
22
<h1 align="center">cve-rs</h1>
33
<h6 align="center">
4-
<img src="https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master" align="top">
4+
<a href="https://github.com/Speykious/cve-rs/actions/workflows/ci.yaml">
5+
<img src="https://img.shields.io/github/actions/workflow/status/serde-rs/serde/ci.yml?branch=master" align="top">
6+
</a>
57
</h6>
68

79
<div align="center">
@@ -19,13 +21,16 @@ We are very committed to making sure **cve-rs** is memory-safe. We know that uns
1921

2022
> *\* There is, unfortunately, one exception: In our tests, we compare the results of our safe `transmute` function against the regular `std::mem::transmute` function. Perhaps somewhat shortsightedly, the standard library implementation is unsafe. Regardless, this is only in our tests - the core library has no unsafe code.*
2123
22-
**cve-rs** has safe implementations of the following bugs:
24+
**cve-rs** implements the following bugs in safe Rust:
2325

2426
- Use after free
2527
- Buffer overflow
2628
- Segmentation fault
2729

28-
**cve-rs** also contains a safe reimplementation of `core::mem::transmute`.
30+
**cve-rs** also contains safe reimplementations of:
31+
32+
- `std::mem::transmute`
33+
- `std::ptr::null()`/`null_mut()` but for references
2934

3035
Here is an example of usage with the `segfault` subcommand:
3136

src/lib.rs

Lines changed: 3 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ pub mod lifetime_expansion;
99

1010
// The bugs we created with the exploit
1111
pub mod buffer_overflow;
12+
pub mod references;
1213
pub mod segfault;
1314
pub mod transmute;
1415
pub mod use_after_free;
@@ -20,6 +21,8 @@ pub use segfault::segfault;
2021
pub use transmute::transmute;
2122
pub use use_after_free::use_after_free;
2223

24+
pub use references::{null, null_mut};
25+
2326
/// Construct a [`String`] from a pointer, capacity and length, in a completely safe manner.
2427
///
2528
/// [`String`] is a `Vec<u8>` which is a `(RawVec, usize)` which is a `((Unique, usize), usize)`.
@@ -49,21 +52,6 @@ pub fn construct_fake_string(ptr: *mut u8, cap: usize, len: usize) -> String {
4952
crate::transmute::<_, String>(actual_buf)
5053
}
5154

52-
use std::hint::black_box;
53-
54-
/// Returns a static reference to a dropped `Box<Box<T>>`.
55-
#[inline(never)]
56-
#[allow(clippy::borrowed_box, clippy::redundant_allocation)]
57-
fn get_dropped_box<T: Default>() -> &'static mut Box<Box<T>> {
58-
let mut boxx = black_box(Box::<Box<T>>::default());
59-
lifetime_expansion::expand_mut(&mut boxx)
60-
}
61-
62-
/// Not allocate an object. The returned reference is always invalid.
63-
pub fn not_alloc<'a, T: Default + 'static>() -> &'a mut T {
64-
get_dropped_box::<T>().as_mut().as_mut()
65-
}
66-
6755
/// Good for job security.
6856
#[cfg(feature = "give-up")]
6957
pub fn give_up<T: 'static>() -> Box<T> {

src/references.rs

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
//! Reimplementations of [`std::ptr::null()`] and [`std::ptr::null_mut()`], with safe code only.
2+
//! Relies on [`crate::transmute`] under the hood.
3+
4+
/// Equivalent to [`std::ptr::null()`], but returns an null reference instead.
5+
pub fn null<'a, T: 'static>() -> &'a T {
6+
crate::transmute(0usize)
7+
}
8+
/// Equivalent to [`std::ptr::null_mut()`], but returns an mutable null reference instead.
9+
pub fn null_mut<'a, T: 'static>() -> &'a mut T {
10+
crate::transmute(0usize)
11+
}
12+
13+
/// Not allocate an object. The returned reference is always invalid.
14+
/// This is equivalent to [`crate::null_mut()`].
15+
pub fn not_alloc<'a, T: 'static>() -> &'a mut T {
16+
null_mut()
17+
}

src/segfault.rs

Lines changed: 3 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
//! A 100% memory-safe segmentation fault.
22
//!
3-
//! We use this hole to create a `'static` reference to a dropped (yes, dropped) `Box<Box<u8>>`.
3+
//! We use the soundness hole to create a mutable null reference to a `u8`.
44
//!
55
//! The smart pointer exists on the stack, but was dropped, so the reference
66
//! is borrowing arbitrary data on the stack. We can then fill the stack with zeros, which
@@ -13,15 +13,10 @@
1313
//! > memory instead of segfaulting on a null pointer. We think this is due to compiler
1414
//! > optimisations.
1515
16-
use std::hint::black_box;
17-
18-
use crate::not_alloc;
19-
2016
/// Segfaults the program.
2117
pub fn segfault() -> ! {
22-
let not_my_ref = not_alloc::<u8>();
23-
black_box([0; 1024]);
24-
println!("{not_my_ref:?}");
18+
let null = crate::null_mut::<u8>();
19+
*null = 42;
2520

2621
// WASM. u_u
2722
unreachable!("Sorry, your platform is too strong.")

0 commit comments

Comments
 (0)