Skip to content

Commit 140876b

Browse files
authored
ci: enforce that getrandom does not contain potential panics (#515)
The check is done by compiling `cdylib` which exposes `getrandom_uninit` and checking that the result does not contain any strings with "panic". For now CI only checks `linux_android_with_fallback`, `linux_android`, `rdrand`, `wasi`, and `getentropy` backends. Other backend checks could be added in future PRs.
1 parent 7db8280 commit 140876b

File tree

4 files changed

+115
-0
lines changed

4 files changed

+115
-0
lines changed

.github/workflows/nopanic.yaml

Lines changed: 72 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,72 @@
1+
name: No panic
2+
3+
on:
4+
push:
5+
branches: master
6+
pull_request:
7+
branches: master
8+
9+
permissions:
10+
contents: read
11+
12+
defaults:
13+
run:
14+
working-directory: nopanic_check
15+
16+
env:
17+
RUSTFLAGS: "-Dwarnings"
18+
19+
jobs:
20+
linux:
21+
name: Linux
22+
runs-on: ubuntu-latest
23+
steps:
24+
- uses: actions/checkout@v4
25+
- uses: dtolnay/rust-toolchain@master
26+
with:
27+
# We need Nightly for the rust-std component for wasm32-wasip2
28+
toolchain: nightly-2024-10-14
29+
targets: wasm32-wasip1, wasm32-wasip2
30+
31+
- name: Build (linux_android_with_fallback.rs)
32+
run: cargo build --release
33+
- name: Check (linux_android_with_fallback.rs)
34+
run: ret=$(grep panic target/release/libgetrandom_wrapper.so; echo $?); [ $ret -eq 1 ]
35+
36+
- name: Build (linux_android.rs)
37+
env:
38+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="linux_getrandom"
39+
run: cargo build --release
40+
- name: Check (linux_android.rs)
41+
run: ret=$(grep panic target/release/libgetrandom_wrapper.so; echo $?); [ $ret -eq 1 ]
42+
43+
- name: Build (rdrand.rs)
44+
env:
45+
RUSTFLAGS: -Dwarnings --cfg getrandom_backend="rdrand"
46+
run: cargo build --release
47+
- name: Check (rdrand.rs)
48+
run: ret=$(grep panic target/release/libgetrandom_wrapper.so; echo $?); [ $ret -eq 1 ]
49+
50+
- name: Build (wasi.rs, preview 1)
51+
run: cargo build --release --target wasm32-wasip1
52+
- name: Check (wasi.rs, preview 1)
53+
run: ret=$(grep panic target/wasm32-wasip1/release/getrandom_wrapper.wasm; echo $?); [ $ret -eq 1 ]
54+
55+
- name: Build (wasi.rs, preview 2)
56+
run: cargo build --release --target wasm32-wasip2
57+
- name: Check (wasi.rs, preview 2)
58+
run: ret=$(grep panic target/wasm32-wasip2/release/getrandom_wrapper.wasm; echo $?); [ $ret -eq 1 ]
59+
60+
macos:
61+
name: macOS
62+
runs-on: ubuntu-latest
63+
steps:
64+
- uses: actions/checkout@v4
65+
- uses: dtolnay/rust-toolchain@master
66+
with:
67+
toolchain: stable
68+
69+
- name: Build (getentropy.rs)
70+
run: cargo build --release
71+
- name: Check (getentropy.rs)
72+
run: ret=$(grep panic target/release/libgetrandom_wrapper.so; echo $?); [ $ret -eq 1 ]

nopanic_check/Cargo.toml

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
[package]
2+
name = "nopanic_check"
3+
description = "Helper crate for checking that getrandom implementation does not contain potential panics"
4+
version = "0.1.0"
5+
edition = "2021"
6+
publish = false
7+
8+
[lib]
9+
name = "getrandom_wrapper"
10+
crate-type = ["cdylib"]
11+
12+
[dependencies]
13+
getrandom = { path = ".." }
14+
15+
[profile.release]
16+
panic = "abort"

nopanic_check/src/lib.rs

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,18 @@
1+
// WASI preview 2 requires enabled std
2+
#![cfg_attr(not(all(target_arch = "wasm32", target_env = "p2")), no_std)]
3+
4+
#[cfg(not(any(test, all(target_arch = "wasm32", target_env = "p2"))))]
5+
#[panic_handler]
6+
fn panic(_info: &core::panic::PanicInfo) -> ! {
7+
extern "C" {
8+
fn panic_nonexistent() -> !;
9+
}
10+
unsafe { panic_nonexistent() }
11+
}
12+
13+
#[no_mangle]
14+
pub extern "C" fn getrandom_wrapper(buf_ptr: *mut u8, buf_len: usize) -> u32 {
15+
let buf = unsafe { core::slice::from_raw_parts_mut(buf_ptr.cast(), buf_len) };
16+
let res = getrandom::getrandom_uninit(buf).map(|_| ());
17+
unsafe { core::mem::transmute(res) }
18+
}

src/lib.rs

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -195,6 +195,15 @@
195195
//! on every call to `getrandom`, hence after the first successful call one
196196
//! can be reasonably confident that no errors will occur.
197197
//!
198+
//! ## Panic handling
199+
//!
200+
//! We strive to eliminate all potential panics from our implementation.
201+
//! In other words, when compiled with enabled optimizations, generated
202+
//! binary code for `getrandom` functions should not contain any panic
203+
//! branches. Even if platform misbiheaves and returns an unexpected
204+
//! result, our code should correctly handle it and return an error like
205+
//! [`Error::UNEXPECTED`].
206+
//!
198207
//! [1]: https://manned.org/getrandom.2
199208
//! [2]: https://manned.org/urandom.4
200209
//! [3]: https://www.unix.com/man-page/mojave/2/getentropy/

0 commit comments

Comments
 (0)