From 2200604d9c101888df658f9483290a13952c6b1c Mon Sep 17 00:00:00 2001 From: Daniel Prilik Date: Mon, 14 Jan 2019 14:19:04 -0800 Subject: remove rand crate the few uses of rand::thread_rng() have been replaced with either prngs or reads from /dev/urandom. the implementations are under the `rand_ish` minicrate. `protoc-rust` depends on `tempdir`, which relies on rand, so `tempdir` has been patched with a rewritten version that does not have rand as a dependency. BUG=chromium:921795 TEST=cargo test --features plugin Change-Id: I6f1c7d7a1aeef4dd55ac71e58294d16c291b8871 Reviewed-on: https://chromium-review.googlesource.com/1409705 Commit-Ready: Daniel Prilik Tested-by: kokoro Reviewed-by: Zach Reizner --- Cargo.lock | 40 +++++---------------------------------- Cargo.toml | 5 ++++- rand_ish/Cargo.toml | 4 ++++ rand_ish/src/lib.rs | 42 +++++++++++++++++++++++++++++++++++++++++ src/linux.rs | 24 +++++++++++------------- src/main.rs | 2 +- tempdir/Cargo.toml | 7 +++++++ tempdir/src/lib.rs | 54 +++++++++++++++++++++++++++++++++++++++++++++++++++++ tests/plugins.rs | 8 ++++---- 9 files changed, 132 insertions(+), 54 deletions(-) create mode 100644 rand_ish/Cargo.toml create mode 100644 rand_ish/src/lib.rs create mode 100644 tempdir/Cargo.toml create mode 100644 tempdir/src/lib.rs diff --git a/Cargo.lock b/Cargo.lock index a8ef1c9..95e5cb3 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -61,11 +61,6 @@ dependencies = [ "syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)", ] -[[package]] -name = "bitflags" -version = "1.0.1" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "byteorder" version = "1.1.0" @@ -105,7 +100,7 @@ dependencies = [ "plugin_proto 0.16.0", "protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "qcow 0.1.0", - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_ish 0.1.0", "resources 0.1.0", "sync 0.1.0", "sys_util 0.1.0", @@ -160,20 +155,6 @@ dependencies = [ "vm_control 0.1.0", ] -[[package]] -name = "fuchsia-zircon" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)", - "fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", -] - -[[package]] -name = "fuchsia-zircon-sys" -version = "0.3.3" -source = "registry+https://github.com/rust-lang/crates.io-index" - [[package]] name = "getopts" version = "0.2.17" @@ -353,7 +334,7 @@ source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ "protobuf 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", "protoc 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)", - "tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)", + "tempdir 0.3.5", ] [[package]] @@ -384,13 +365,8 @@ dependencies = [ ] [[package]] -name = "rand" -version = "0.3.20" -source = "registry+https://github.com/rust-lang/crates.io-index" -dependencies = [ - "fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)", - "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)", -] +name = "rand_ish" +version = "0.1.0" [[package]] name = "resources" @@ -434,9 +410,8 @@ version = "0.1.0" [[package]] name = "tempdir" version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" dependencies = [ - "rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)", + "rand_ish 0.1.0", ] [[package]] @@ -514,12 +489,9 @@ dependencies = [ ] [metadata] -"checksum bitflags 1.0.1 (registry+https://github.com/rust-lang/crates.io-index)" = "b3c30d3802dfb7281680d6285f2ccdaa8c2d8fee41f93805dba5c4cf50dc23cf" "checksum byteorder 1.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "ff81738b726f5d099632ceaffe7fb65b90212e8dce59d518729e7e8634032d3d" "checksum cc 1.0.15 (registry+https://github.com/rust-lang/crates.io-index)" = "0ebb87d1116151416c0cf66a0e3fb6430cccd120fd6300794b4dfaa050ac40ba" "checksum cfg-if 0.1.2 (registry+https://github.com/rust-lang/crates.io-index)" = "d4c819a1287eb618df47cc647173c5c4c66ba19d888a6e50d605672aed3140de" -"checksum fuchsia-zircon 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "2e9763c69ebaae630ba35f74888db465e49e259ba1bc0eda7d06f4a067615d82" -"checksum fuchsia-zircon-sys 0.3.3 (registry+https://github.com/rust-lang/crates.io-index)" = "3dcaa9ae7725d12cdb85b3ad99a434db70b468c09ded17e012d86b5c1010f7a7" "checksum getopts 0.2.17 (registry+https://github.com/rust-lang/crates.io-index)" = "b900c08c1939860ce8b54dc6a89e26e00c04c380fd0e09796799bd7f12861e05" "checksum libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)" = "10923947f84a519a45c8fefb7dd1b3e8c08747993381adee176d7a82b4195311" "checksum log 0.4.1 (registry+https://github.com/rust-lang/crates.io-index)" = "89f010e843f2b1a31dbd316b3b8d443758bc634bed37aabade59c686d644e0a2" @@ -529,7 +501,5 @@ dependencies = [ "checksum protoc 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "5379c34ea2f9c69b99e6f25f6d0e6619876195ae7a3dcaf69f66bdb6c2e4dceb" "checksum protoc-rust 1.4.3 (registry+https://github.com/rust-lang/crates.io-index)" = "e211a7f56b2d020a59d483f652cfdfa6fd42e37bf544c0231e373807aa316c45" "checksum quote 0.6.10 (registry+https://github.com/rust-lang/crates.io-index)" = "53fa22a1994bd0f9372d7a816207d8a2677ad0325b073f5c5332760f0fb62b5c" -"checksum rand 0.3.20 (registry+https://github.com/rust-lang/crates.io-index)" = "512870020642bb8c221bf68baa1b2573da814f6ccfe5c9699b1c303047abe9b1" "checksum syn 0.15.21 (registry+https://github.com/rust-lang/crates.io-index)" = "816b7af21405b011a23554ea2dc3f6576dc86ca557047c34098c1d741f10f823" -"checksum tempdir 0.3.5 (registry+https://github.com/rust-lang/crates.io-index)" = "87974a6f5c1dfb344d733055601650059a3363de2a6104819293baff662132d6" "checksum unicode-xid 0.1.0 (registry+https://github.com/rust-lang/crates.io-index)" = "fc72304796d0818e357ead4e000d19c9c174ab23dc11093ac919054d20a6a7fc" diff --git a/Cargo.toml b/Cargo.toml index 7ab3b16..1521d4f 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,8 @@ exclude = [ "sync", "sys_util", "syscall_defines", + "tempdir", + "rand_ish", ] [features] @@ -51,8 +53,8 @@ crosvm_plugin = { path = "crosvm_plugin", optional = true } protobuf = { version = "=1.4.3", optional = true } resources = { path = "resources" } p9 = { path = "p9" } -rand = "=0.3.20" sync = { path = "sync" } +rand_ish = { path = "rand_ish" } [target.'cfg(target_arch = "x86_64")'.dependencies] x86_64 = { path = "x86_64" } @@ -70,3 +72,4 @@ poll_token_derive = { path = "sys_util/poll_token_derive" } sync = { path = "sync" } sys_util = { path = "sys_util" } syscall_defines = { path = "syscall_defines" } +tempdir = { path = "tempdir" } diff --git a/rand_ish/Cargo.toml b/rand_ish/Cargo.toml new file mode 100644 index 0000000..031b97e --- /dev/null +++ b/rand_ish/Cargo.toml @@ -0,0 +1,4 @@ +[package] +name = "rand_ish" +version = "0.1.0" +authors = ["The Chromium OS Authors"] diff --git a/rand_ish/src/lib.rs b/rand_ish/src/lib.rs new file mode 100644 index 0000000..4372f97 --- /dev/null +++ b/rand_ish/src/lib.rs @@ -0,0 +1,42 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +use std::fs::File; +use std::io::{self, Read}; + +/// A simple prng based on a Linear congruential generator +/// https://en.wikipedia.org/wiki/Linear_congruential_generator +pub struct SimpleRng { + seed: u64, +} + +impl SimpleRng { + /// Create a new SimpleRng + pub fn new(seed: u64) -> SimpleRng { + SimpleRng { seed } + } + + /// Generate random u64 + pub fn rng(&mut self) -> u64 { + // a simple Linear congruential generator + let a: u64 = 6364136223846793005; + let c: u64 = 1442695040888963407; + self.seed = a.wrapping_mul(self.seed).wrapping_add(c); + self.seed + } +} + +/// Samples `/dev/urandom` and generates a random ASCII string of length `len` +pub fn urandom_str(len: usize) -> io::Result { + const ASCII_CHARS: &'static [u8] = b" + ABCDEFGHIJKLMNOPQRSTUVWXYZ\ + abcdefghijklmnopqrstuvwxyz\ + 0123456789"; + + File::open("/dev/urandom")? + .bytes() + .map(|b| b.map(|b| ASCII_CHARS[b as usize % ASCII_CHARS.len()] as char)) + .take(len) + .collect::>() +} diff --git a/src/linux.rs b/src/linux.rs index 1bca0bf..a0f036b 100644 --- a/src/linux.rs +++ b/src/linux.rs @@ -18,11 +18,9 @@ use std::sync::atomic::{AtomicBool, Ordering}; use std::sync::{Arc, Barrier}; use std::thread; use std::thread::JoinHandle; -use std::time::Duration; +use std::time::{Duration, SystemTime, UNIX_EPOCH}; use libc::{self, c_int}; -use rand::distributions::{IndependentSample, Range}; -use rand::thread_rng; use byteorder::{ByteOrder, LittleEndian}; use devices::{self, PciDevice, VirtioPciDevice}; @@ -31,6 +29,7 @@ use kvm::*; use msg_socket::{MsgReceiver, MsgSender, MsgSocket, UnlinkMsgSocket}; use net_util::{Error as NetError, Tap}; use qcow::{self, ImageType, QcowFile}; +use rand_ish::SimpleRng; use sys_util; use sys_util::*; use vhost; @@ -907,10 +906,12 @@ fn run_control( // Used to add jitter to timer values so that we don't have a thundering herd problem when // multiple VMs are running. - let mut rng = thread_rng(); - let lowmem_jitter_ms = Range::new(0, 200); - let freemem_jitter_secs = Range::new(0, 12); - let interval_jitter_secs = Range::new(0, 6); + let mut simple_rng = SimpleRng::new( + SystemTime::now() + .duration_since(UNIX_EPOCH) + .expect("time went backwards") + .subsec_nanos() as u64, + ); let mut vcpu_handles = Vec::with_capacity(linux.vcpus.len()); let vcpu_thread_barrier = Arc::new(Barrier::new(linux.vcpus.len() + 1)); @@ -1031,8 +1032,7 @@ fn run_control( // Add some jitter to the timer so that if there are multiple VMs running // they don't all start ballooning at exactly the same time. - let lowmem_dur = - Duration::from_millis(1000 + lowmem_jitter_ms.ind_sample(&mut rng)); + let lowmem_dur = Duration::from_millis(1000 + simple_rng.rng() % 200); lowmem_timer .reset(lowmem_dur, None) .map_err(Error::ResetTimerFd)?; @@ -1040,10 +1040,8 @@ fn run_control( // Also start a timer to check when we can start giving memory back. Do the // first check after a minute (with jitter) and subsequent checks after // every 30 seconds (with jitter). - let freemem_dur = - Duration::from_secs(60 + freemem_jitter_secs.ind_sample(&mut rng)); - let freemem_int = - Duration::from_secs(30 + interval_jitter_secs.ind_sample(&mut rng)); + let freemem_dur = Duration::from_secs(60 + simple_rng.rng() % 12); + let freemem_int = Duration::from_secs(30 + simple_rng.rng() % 6); freemem_timer .reset(freemem_dur, Some(freemem_int)) .map_err(Error::ResetTimerFd)?; diff --git a/src/main.rs b/src/main.rs index 9cb7b3c..b616adf 100644 --- a/src/main.rs +++ b/src/main.rs @@ -29,7 +29,7 @@ extern crate msg_socket; extern crate plugin_proto; #[cfg(feature = "plugin")] extern crate protobuf; -extern crate rand; +extern crate rand_ish; extern crate resources; extern crate sync; extern crate vhost; diff --git a/tempdir/Cargo.toml b/tempdir/Cargo.toml new file mode 100644 index 0000000..9a3bed9 --- /dev/null +++ b/tempdir/Cargo.toml @@ -0,0 +1,7 @@ +[package] +name = "tempdir" +version = "0.3.5" +authors = ["The Chromium OS Authors"] + +[dependencies] +rand_ish = { path = "../rand_ish" } diff --git a/tempdir/src/lib.rs b/tempdir/src/lib.rs new file mode 100644 index 0000000..ab0bb8a --- /dev/null +++ b/tempdir/src/lib.rs @@ -0,0 +1,54 @@ +// Copyright 2019 The Chromium OS Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. + +//! Simplified tempdir which doesn't depend on the `rand` crate, instead using +//! /dev/urandom as a source of entropy + +extern crate rand_ish; + +use std::env; +use std::fs; +use std::io::{self, Error, ErrorKind}; +use std::path::{Path, PathBuf}; +use rand_ish::urandom_str; + +pub struct TempDir { + path: PathBuf, +} + +const NUM_RETRIES: u32 = 4; + +impl TempDir { + /// Tries to make a tempdir inside of `env::temp_dir()` with a specified + /// prefix. The directory and it's content is destroyed when TempDir is + /// dropped. + /// If the directory can not be created, `Err` is returned. + pub fn new(prefix: &str) -> io::Result { + for _ in 0..NUM_RETRIES { + let suffix = urandom_str(12)?; + let path = env::temp_dir().join(format!("{}.{}", prefix, suffix)); + + match fs::create_dir(&path) { + Ok(_) => return Ok(TempDir { path }), + Err(ref e) if e.kind() == ErrorKind::AlreadyExists => {} + Err(e) => return Err(e), + } + } + + Err(Error::new(ErrorKind::AlreadyExists, "too many tempdirs exist")) + } + + /// Accesses the tempdir's [`Path`]. + /// + /// [`Path`]: http://doc.rust-lang.org/std/path/struct.Path.html + pub fn path(&self) -> &Path { + self.path.as_ref() + } +} + +impl Drop for TempDir { + fn drop(&mut self) { + let _ = fs::remove_dir_all(&self.path); + } +} diff --git a/tests/plugins.rs b/tests/plugins.rs index 20adcab..6176a32 100644 --- a/tests/plugins.rs +++ b/tests/plugins.rs @@ -4,11 +4,9 @@ #![cfg(feature = "plugin")] -extern crate rand; +extern crate rand_ish; extern crate sys_util; -use rand::{thread_rng, Rng}; - use std::env::{current_exe, var_os}; use std::ffi::OsString; use std::fs::{remove_file, File}; @@ -19,6 +17,7 @@ use std::process::{Command, Stdio}; use std::thread::sleep; use std::time::Duration; +use rand_ish::urandom_str; use sys_util::{ioctl, SharedMemory}; struct RemovePath(PathBuf); @@ -56,7 +55,8 @@ fn get_crosvm_path() -> PathBuf { fn build_plugin(src: &str) -> RemovePath { let libcrosvm_plugin_dir = get_target_path(); let mut out_bin = libcrosvm_plugin_dir.clone(); - out_bin.push(thread_rng().gen_ascii_chars().take(10).collect::()); + let randbin = urandom_str(10).expect("failed to generate random bin name"); + out_bin.push(randbin); let mut child = Command::new(var_os("CC").unwrap_or(OsString::from("cc"))) .args(&["-Icrosvm_plugin", "-pthread", "-o"]) // crosvm.h location and set output path. .arg(&out_bin) -- cgit 1.4.1