summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Prilik <prilik@google.com>2019-01-14 14:19:04 -0800
committerchrome-bot <chrome-bot@chromium.org>2019-01-17 20:20:50 -0800
commit2200604d9c101888df658f9483290a13952c6b1c (patch)
tree8b3982baeeb7f61824f95bd8a91a972f3104b729
parenta4d5bd4bc271c505097f18ea0506926dbdf8d682 (diff)
downloadcrosvm-2200604d9c101888df658f9483290a13952c6b1c.tar
crosvm-2200604d9c101888df658f9483290a13952c6b1c.tar.gz
crosvm-2200604d9c101888df658f9483290a13952c6b1c.tar.bz2
crosvm-2200604d9c101888df658f9483290a13952c6b1c.tar.lz
crosvm-2200604d9c101888df658f9483290a13952c6b1c.tar.xz
crosvm-2200604d9c101888df658f9483290a13952c6b1c.tar.zst
crosvm-2200604d9c101888df658f9483290a13952c6b1c.zip
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 <prilik@google.com>
Tested-by: kokoro <noreply+kokoro@google.com>
Reviewed-by: Zach Reizner <zachr@chromium.org>
-rw-r--r--Cargo.lock40
-rw-r--r--Cargo.toml5
-rw-r--r--rand_ish/Cargo.toml4
-rw-r--r--rand_ish/src/lib.rs42
-rw-r--r--src/linux.rs24
-rw-r--r--src/main.rs2
-rw-r--r--tempdir/Cargo.toml7
-rw-r--r--tempdir/src/lib.rs54
-rw-r--r--tests/plugins.rs8
9 files changed, 132 insertions, 54 deletions
diff --git a/Cargo.lock b/Cargo.lock
index a8ef1c9..95e5cb3 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -62,11 +62,6 @@ dependencies = [
 ]
 
 [[package]]
-name = "bitflags"
-version = "1.0.1"
-source = "registry+https://github.com/rust-lang/crates.io-index"
-
-[[package]]
 name = "byteorder"
 version = "1.1.0"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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",
@@ -161,20 +156,6 @@ dependencies = [
 ]
 
 [[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"
 source = "registry+https://github.com/rust-lang/crates.io-index"
@@ -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<String> {
+    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::<io::Result<String>>()
+}
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<TempDir> {
+        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::<String>());
+    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)