Skip to content

Commit f622215

Browse files
authored
Add memory sanitizer support (#521)
Add new `getrandom_sanitize` flag which enables unpoisoning of buffer passed to `getrandom_uninit`.
1 parent 9aab00c commit f622215

File tree

4 files changed

+43
-1
lines changed

4 files changed

+43
-1
lines changed

.github/workflows/tests.yml

+14
Original file line numberDiff line numberDiff line change
@@ -159,6 +159,20 @@ jobs:
159159
- run: cargo test --target=x86_64-win7-windows-msvc -Z build-std --features=std
160160
- run: cargo test --target=i686-win7-windows-msvc -Z build-std --features=std
161161

162+
sanitizer-test:
163+
name: Sanitizer Test
164+
runs-on: ubuntu-22.04
165+
steps:
166+
- uses: actions/checkout@v4
167+
- uses: dtolnay/rust-toolchain@master
168+
with:
169+
toolchain: nightly-2024-10-08
170+
components: rust-src
171+
- env:
172+
RUSTFLAGS: -Dwarnings -Zsanitizer=memory --cfg getrandom_sanitize
173+
# `--all-targets` is used to skip doc tests which currently fail linking
174+
run: cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu --all-targets
175+
162176
cross-tests:
163177
name: Cross Test
164178
runs-on: ubuntu-22.04

CHANGELOG.md

+2
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
3030
- `Error::new_custom` method [#507]
3131
- `rndr` opt-in backend [#512]
3232
- `linux_rustix` opt-in backend [#520]
33+
- Memory sanitizer support gated behind `getrandom_sanitize` configuration flag [#521]
3334

3435
[#415]: https://github.com/rust-random/getrandom/pull/415
3536
[#440]: https://github.com/rust-random/getrandom/pull/440
@@ -42,6 +43,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
4243
[#507]: https://github.com/rust-random/getrandom/pull/507
4344
[#512]: https://github.com/rust-random/getrandom/pull/512
4445
[#520]: https://github.com/rust-random/getrandom/pull/520
46+
[#521]: https://github.com/rust-random/getrandom/pull/521
4547

4648
## [0.2.15] - 2024-05-06
4749
### Added

Cargo.toml

+1
Original file line numberDiff line numberDiff line change
@@ -80,6 +80,7 @@ rustc-dep-of-std = ["compiler_builtins", "core"]
8080
level = "warn"
8181
check-cfg = [
8282
'cfg(getrandom_backend, values("custom", "rdrand", "rndr", "linux_getrandom", "linux_rustix", "wasm_js", "esp_idf"))',
83+
'cfg(getrandom_sanitize)',
8384
'cfg(getrandom_browser_test)',
8485
'cfg(getrandom_test_linux_fallback)',
8586
]

src/lib.rs

+26-1
Original file line numberDiff line numberDiff line change
@@ -205,6 +205,17 @@
205205
//! result, our code should correctly handle it and return an error like
206206
//! [`Error::UNEXPECTED`].
207207
//!
208+
//! ## Sanitizer support
209+
//!
210+
//! If your code uses `getrandom_uninit` and you use memory sanitizer
211+
//! (i.e. `-Zsanitizer=memory`), then you need to pass `getrandom_sanitize`
212+
//! configuration flag for `getrandom_uninit` to unpoison destination buffer.
213+
//!
214+
//! For example, it can be done like this (requires Nightly compiler):
215+
//! ```text
216+
//! RUSTFLAGS="-Zsanitizer=memory --cfg getrandom_sanitize" cargo test -Zbuild-std --target=x86_64-unknown-linux-gnu
217+
//! ```
218+
//!
208219
//! [1]: https://manned.org/getrandom.2
209220
//! [2]: https://manned.org/urandom.4
210221
//! [3]: https://www.unix.com/man-page/mojave/2/getentropy/
@@ -254,6 +265,7 @@
254265
#![no_std]
255266
#![warn(rust_2018_idioms, unused_lifetimes, missing_docs)]
256267
#![cfg_attr(docsrs, feature(doc_auto_cfg))]
268+
#![cfg_attr(getrandom_sanitize, feature(cfg_sanitize))]
257269
#![deny(
258270
clippy::cast_lossless,
259271
clippy::cast_possible_truncation,
@@ -474,7 +486,20 @@ pub fn getrandom_uninit(dest: &mut [MaybeUninit<u8>]) -> Result<&mut [u8], Error
474486
if !dest.is_empty() {
475487
imp::getrandom_inner(dest)?;
476488
}
489+
490+
#[cfg(getrandom_sanitize)]
491+
#[cfg(sanitize = "memory")]
492+
extern "C" {
493+
fn __msan_unpoison(a: *mut core::ffi::c_void, size: usize);
494+
}
495+
477496
// SAFETY: `dest` has been fully initialized by `imp::getrandom_inner`
478497
// since it returned `Ok`.
479-
Ok(unsafe { slice_assume_init_mut(dest) })
498+
Ok(unsafe {
499+
#[cfg(getrandom_sanitize)]
500+
#[cfg(sanitize = "memory")]
501+
__msan_unpoison(dest.as_mut_ptr().cast(), dest.len());
502+
503+
slice_assume_init_mut(dest)
504+
})
480505
}

0 commit comments

Comments
 (0)