From 32fed17969c70ed17739632b5f96e7240afd75fa Mon Sep 17 00:00:00 2001 From: MidnightRocket Date: Sun, 30 Mar 2025 20:15:29 +0200 Subject: [PATCH] mktemp: Prevent race condition when setting permissions for tempdir This prevents a race conditions vulnerability in the tempdir implementation, where an attacker potentially could modify the created temporary directory, before the restrictive permissions are set. The race conditions occurs in the moment between the temporary directory is created, and the proper permissions are set. # The fix This patch changes the `make_temp_dir` to create the temporary directory with the proper permissions creation time. Rather than first create, then set permissions. This is done by giving the permissions to the builder. See [tempfile doc](https://github.com/Stebalien/tempfile/blob/95540ed3fcb9ca74845c02aee058726b2dca58b7/src/lib.rs#L449-L450). # Severity Low The attack is only possible if the umask is configured to allow writes by group or other for created file/directories. # Related Resources See: https://cwe.mitre.org/data/definitions/377.html --- src/uu/mktemp/src/mktemp.rs | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/src/uu/mktemp/src/mktemp.rs b/src/uu/mktemp/src/mktemp.rs index 8376615fd..54456a67e 100644 --- a/src/uu/mktemp/src/mktemp.rs +++ b/src/uu/mktemp/src/mktemp.rs @@ -458,12 +458,18 @@ fn dry_exec(tmpdir: &Path, prefix: &str, rand: usize, suffix: &str) -> UResult

UResult { let mut builder = Builder::new(); builder.prefix(prefix).rand_bytes(rand).suffix(suffix); + + // On *nix platforms grant read-write-execute for owner only. + // The directory is created with these permission at creation time, using mkdir(3) syscall. + // This is not relevant on Windows systems. See: https://docs.rs/tempfile/latest/tempfile/#security + // `fs` is not imported on Windows anyways. + #[cfg(not(windows))] + builder.permissions(fs::Permissions::from_mode(0o700)); + match builder.tempdir_in(dir) { Ok(d) => { // `into_path` consumes the TempDir without removing it let path = d.into_path(); - #[cfg(not(windows))] - fs::set_permissions(&path, fs::Permissions::from_mode(0o700))?; Ok(path) } Err(e) if e.kind() == ErrorKind::NotFound => {