summary refs log tree commit diff
diff options
context:
space:
mode:
authorDaniel Verkamp <dverkamp@chromium.org>2019-06-13 19:36:08 -0700
committerchrome-bot <chrome-bot@chromium.org>2019-07-03 16:35:43 -0700
commitda52468b34ceacf8a3d74d191f09cf9d8099a0a6 (patch)
tree2b8f1afbd160ffdacfc2c085565b05e2fa235a49
parent5104b9641cc6e85adcf45bebe636228ae6ab6eee (diff)
downloadcrosvm-da52468b34ceacf8a3d74d191f09cf9d8099a0a6.tar
crosvm-da52468b34ceacf8a3d74d191f09cf9d8099a0a6.tar.gz
crosvm-da52468b34ceacf8a3d74d191f09cf9d8099a0a6.tar.bz2
crosvm-da52468b34ceacf8a3d74d191f09cf9d8099a0a6.tar.lz
crosvm-da52468b34ceacf8a3d74d191f09cf9d8099a0a6.tar.xz
crosvm-da52468b34ceacf8a3d74d191f09cf9d8099a0a6.tar.zst
crosvm-da52468b34ceacf8a3d74d191f09cf9d8099a0a6.zip
tempfile: reimplement using libc::mkdtemp
POSIX provides a standard mkdtemp() function to securely create a
temporary directory; use it rather than reinventing the wheel.

This also drops the dependency of tempfile on rand_ish, which will allow
easier use of the tempfile implementation outside of crosvm.

BUG=chromium:974059
TEST=cargo test -p tempfile

Change-Id: I34a226b046dc6f272106988a78d121a24a377f44
Signed-off-by: Daniel Verkamp <dverkamp@chromium.org>
Reviewed-on: https://chromium-review.googlesource.com/1659971
Tested-by: kokoro <noreply+kokoro@google.com>
Legacy-Commit-Queue: Commit Bot <commit-bot@chromium.org>
Reviewed-by: Dylan Reid <dgreid@chromium.org>
-rw-r--r--Cargo.lock2
-rw-r--r--tempfile/Cargo.toml2
-rw-r--r--tempfile/src/lib.rs47
3 files changed, 32 insertions, 19 deletions
diff --git a/Cargo.lock b/Cargo.lock
index 8446532..beaf37b 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -483,7 +483,7 @@ version = "0.1.0"
 name = "tempfile"
 version = "3.0.7"
 dependencies = [
- "rand_ish 0.1.0",
+ "libc 0.2.44 (registry+https://github.com/rust-lang/crates.io-index)",
 ]
 
 [[package]]
diff --git a/tempfile/Cargo.toml b/tempfile/Cargo.toml
index b12e976..b7ac1c1 100644
--- a/tempfile/Cargo.toml
+++ b/tempfile/Cargo.toml
@@ -5,4 +5,4 @@ authors = ["The Chromium OS Authors"]
 edition = "2018"
 
 [dependencies]
-rand_ish = { path = "../rand_ish" }
+libc = "*"
diff --git a/tempfile/src/lib.rs b/tempfile/src/lib.rs
index 14f235b..0b9e39b 100644
--- a/tempfile/src/lib.rs
+++ b/tempfile/src/lib.rs
@@ -5,8 +5,9 @@
 //! Simplified tempfile which doesn't depend on the `rand` crate, instead using
 //! /dev/urandom as a source of entropy
 
-use rand_ish::urandom_str;
+use libc::mkdtemp;
 use std::env;
+use std::ffi::CString;
 use std::fs;
 use std::io::{Error, ErrorKind, Result};
 use std::path::{Path, PathBuf};
@@ -35,21 +36,35 @@ impl Builder {
     /// dropped.
     /// If the directory can not be created, `Err` is returned.
     pub fn tempdir(&self) -> Result<TempDir> {
-        for _ in 0..NUM_RETRIES {
-            let suffix = urandom_str(12)?;
-            let path = env::temp_dir().join(format!("{}.{}", self.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),
+        // mkdtemp() requires the template to end in 6 X chars, which will be replaced
+        // with random characters to make the path unique.
+        let path_template = env::temp_dir().join(format!("{}.XXXXXX", self.prefix));
+        let template = match path_template.to_str() {
+            Some(s) => CString::new(s)?,
+            None => {
+                return Err(Error::new(
+                    ErrorKind::InvalidData,
+                    "Path to string conversion failed",
+                ))
             }
-        }
-
-        Err(Error::new(
-            ErrorKind::AlreadyExists,
-            "too many tempdirs exist",
-        ))
+        };
+        let ptr = template.into_raw();
+        // Safe because ownership of the buffer is handed off to mkdtemp() only
+        // until it returns, and ownership is reclaimed by calling CString::from_raw()
+        // on the same pointer returned by into_raw().
+        let path = unsafe {
+            let ret = mkdtemp(ptr);
+            let path = CString::from_raw(ptr);
+            if ret.is_null() {
+                return Err(Error::last_os_error());
+            }
+            path
+        };
+        Ok(TempDir {
+            path: PathBuf::from(path.to_str().map_err(|_| {
+                Error::new(ErrorKind::InvalidData, "Path to string conversion failed")
+            })?),
+        })
     }
 }
 
@@ -57,8 +72,6 @@ pub struct TempDir {
     path: PathBuf,
 }
 
-const NUM_RETRIES: u32 = 4;
-
 impl TempDir {
     /// Accesses the tempdir's [`Path`].
     ///