Skip to content

Commit 7f68c78

Browse files
authored
Merge pull request rust-random#9 from jasonbking/illumos
8 Update Solaris getrandom
2 parents 10fdedd + 819fb3f commit 7f68c78

File tree

3 files changed

+102
-100
lines changed

3 files changed

+102
-100
lines changed

src/lib.rs

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,7 @@
100100
target_os = "android",
101101
target_os = "netbsd",
102102
target_os = "solaris",
103+
target_os = "illumos",
103104
target_os = "redox",
104105
target_os = "dragonfly",
105106
target_os = "haiku",
@@ -138,7 +139,7 @@ mod_use!(cfg(target_os = "macos"), macos);
138139
mod_use!(cfg(target_os = "netbsd"), netbsd);
139140
mod_use!(cfg(target_os = "openbsd"), openbsd_bitrig);
140141
mod_use!(cfg(target_os = "redox"), redox);
141-
mod_use!(cfg(target_os = "solaris"), solaris);
142+
mod_use!(cfg(any(target_os = "solaris", target_os = "illumos")), solarish);
142143
mod_use!(cfg(windows), windows);
143144
mod_use!(cfg(target_env = "sgx"), sgx);
144145

@@ -171,6 +172,7 @@ mod_use!(
171172
target_os = "freebsd",
172173
target_os = "fuchsia",
173174
target_os = "haiku",
175+
target_os = "illumos",
174176
target_os = "ios",
175177
target_os = "linux",
176178
target_os = "macos",

src/solaris.rs

Lines changed: 0 additions & 99 deletions
This file was deleted.

src/solarish.rs

Lines changed: 99 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,99 @@
1+
// Copyright 2018 Developers of the Rand project.
2+
//
3+
// Licensed under the Apache License, Version 2.0 <LICENSE-APACHE or
4+
// https://www.apache.org/licenses/LICENSE-2.0> or the MIT license
5+
// <LICENSE-MIT or https://opensource.org/licenses/MIT>, at your
6+
// option. This file may not be copied, modified, or distributed
7+
// except according to those terms.
8+
9+
//! Implementation for the Solaris family
10+
//!
11+
//! Read from `/dev/random`, with chunks of limited size (256 bytes).
12+
//! `/dev/random` uses the Hash_DRBG with SHA512 algorithm from NIST SP 800-90A.
13+
//! `/dev/urandom` uses the FIPS 186-2 algorithm, which is considered less
14+
//! secure. We choose to read from `/dev/random`.
15+
//!
16+
//! Since Solaris 11.3 and mid-2015 illumos, the `getrandom` syscall is available.
17+
//! To make sure we can compile on both Solaris and its derivatives, as well as
18+
//! function, we check for the existance of getrandom(2) in libc by calling
19+
//! libc::dlsym.
20+
extern crate libc;
21+
22+
use super::Error;
23+
use std::cell::RefCell;
24+
use std::fs::File;
25+
use std::io;
26+
use std::io::Read;
27+
use utils::use_init;
28+
29+
#[cfg(target_os = "illumos")]
30+
type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::ssize_t;
31+
#[cfg(target_os = "solaris")]
32+
type GetRandomFn = unsafe extern "C" fn(*mut u8, libc::size_t, libc::c_uint) -> libc::c_int;
33+
34+
enum RngSource {
35+
GetRandom(GetRandomFn),
36+
Device(File),
37+
}
38+
39+
thread_local!(
40+
static RNG_SOURCE: RefCell<Option<RngSource>> = RefCell::new(None);
41+
);
42+
43+
fn libc_getrandom(rand: GetRandomFn, dest: &mut [u8]) -> Result<(), Error> {
44+
let ret = unsafe { rand(dest.as_mut_ptr(), dest.len(), 0) as libc::ssize_t };
45+
46+
if ret == -1 || ret != dest.len() as libc::ssize_t {
47+
Err(io::Error::last_os_error().into())
48+
} else {
49+
Ok(())
50+
}
51+
}
52+
53+
pub fn getrandom_inner(dest: &mut [u8]) -> Result<(), Error> {
54+
// 256 bytes is the lowest common denominator across all the Solaris
55+
// derived platforms for atomically obtaining random data.
56+
RNG_SOURCE.with(|f| {
57+
use_init(
58+
f,
59+
|| {
60+
let s = match fetch_getrandom() {
61+
Some(fptr) => RngSource::GetRandom(fptr),
62+
None => RngSource::Device(File::open("/dev/random")?),
63+
};
64+
Ok(s)
65+
},
66+
|f| {
67+
match f {
68+
RngSource::GetRandom(rp) => {
69+
for chunk in dest.chunks_mut(256) {
70+
libc_getrandom(*rp, chunk)?
71+
}
72+
}
73+
RngSource::Device(randf) => {
74+
for chunk in dest.chunks_mut(256) {
75+
randf.read_exact(chunk)?
76+
}
77+
}
78+
};
79+
Ok(())
80+
},
81+
)
82+
})
83+
}
84+
85+
fn fetch_getrandom() -> Option<GetRandomFn> {
86+
use std::mem;
87+
use std::sync::atomic::{AtomicUsize, Ordering};
88+
89+
static FPTR: AtomicUsize = AtomicUsize::new(1);
90+
91+
if FPTR.load(Ordering::SeqCst) == 1 {
92+
let name = "getrandom\0";
93+
let addr = unsafe { libc::dlsym(libc::RTLD_DEFAULT, name.as_ptr() as *const _) as usize };
94+
FPTR.store(addr, Ordering::SeqCst);
95+
}
96+
97+
let ptr = FPTR.load(Ordering::SeqCst);
98+
unsafe { mem::transmute::<usize, Option<GetRandomFn>>(ptr) }
99+
}

0 commit comments

Comments
 (0)