1
Fork 0
mirror of https://github.com/RGBCube/uutils-coreutils synced 2025-07-28 03:27:44 +00:00

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](95540ed3fc/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
This commit is contained in:
MidnightRocket 2025-03-30 20:15:29 +02:00
parent ed8689eaa3
commit 32fed17969
No known key found for this signature in database
GPG key ID: DA1FD6C6670E36D7

View file

@ -458,12 +458,18 @@ fn dry_exec(tmpdir: &Path, prefix: &str, rand: usize, suffix: &str) -> UResult<P
fn make_temp_dir(dir: &Path, prefix: &str, rand: usize, suffix: &str) -> UResult<PathBuf> {
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 => {