Skip to content

Commit

Permalink
Rollup merge of rust-lang#89999 - talagrand:GetTempPath2, r=m-ou-se
Browse files Browse the repository at this point in the history
Update std::env::temp_dir to use GetTempPath2 on Windows when available.

As a security measure, Windows 11 introduces a new temporary directory API, GetTempPath2.
When the calling process is running as SYSTEM, a separate temporary directory
will be returned inaccessible to non-SYSTEM processes. For non-SYSTEM processes
the behavior will be the same as before.

This can help mitigate against attacks such as this one:
https://medium.com/csis-techblog/cve-2020-1088-yet-another-arbitrary-delete-eop-a00b97d8c3e2

Compatibility risk: Software which relies on temporary files to communicate between SYSTEM and non-SYSTEM
processes may be affected by this change. In many cases, such patterns may be vulnerable to the very
attacks the new API was introduced to harden against.
I'm unclear on the Rust project's tolerance for such change-of-behavior in the standard library. If anything,
this PR is meant to raise awareness of the issue and hopefully start the conversation.

How tested: Taking the example code from the documentation and running it through psexec (from SysInternals) on
Win10 and Win11.
On Win10:
C:\test>psexec -s C:\test\main.exe
<...>
Temporary directory: C:\WINDOWS\TEMP\

On Win11:
C:\test>psexec -s C:\test\main.exe
<...>
Temporary directory: C:\Windows\SystemTemp\
  • Loading branch information
matthiaskrgr authored Dec 8, 2021
2 parents abba5ed + 1d26e41 commit 5d1aa35
Show file tree
Hide file tree
Showing 3 changed files with 16 additions and 13 deletions.
21 changes: 9 additions & 12 deletions library/std/src/env.rs
Original file line number Diff line number Diff line change
Expand Up @@ -583,28 +583,25 @@ pub fn home_dir() -> Option<PathBuf> {
/// may result in "insecure temporary file" security vulnerabilities. Consider
/// using a crate that securely creates temporary files or directories.
///
/// # Unix
/// # Platform-specific behavior
///
/// Returns the value of the `TMPDIR` environment variable if it is
/// On Unix, returns the value of the `TMPDIR` environment variable if it is
/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
/// is no global temporary folder (it is usually allocated per-app), it returns
/// `/data/local/tmp`.
/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
/// [`GetTempPath`][GetTempPath], which this function uses internally.
/// Note that, this [may change in the future][changes].
///
/// # Windows
///
/// Returns the value of, in order, the `TMP`, `TEMP`,
/// `USERPROFILE` environment variable if any are set and not the empty
/// string. Otherwise, `temp_dir` returns the path of the Windows directory.
/// This behavior is identical to that of [`GetTempPath`][msdn], which this
/// function uses internally.
///
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
/// [changes]: io#platform-specific-behavior
/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
///
/// ```no_run
/// use std::env;
///
/// fn main() {
/// let mut dir = env::temp_dir();
/// let dir = env::temp_dir();
/// println!("Temporary directory: {}", dir.display());
/// }
/// ```
Expand Down
6 changes: 6 additions & 0 deletions library/std/src/sys/windows/c.rs
Original file line number Diff line number Diff line change
Expand Up @@ -1110,6 +1110,12 @@ compat_fn! {
-> () {
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
}

// >= Win11 / Server 2022
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD {
GetTempPathW(nBufferLength, lpBuffer)
}
}

compat_fn! {
Expand Down
2 changes: 1 addition & 1 deletion library/std/src/sys/windows/os.rs
Original file line number Diff line number Diff line change
Expand Up @@ -275,7 +275,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
}

pub fn temp_dir() -> PathBuf {
super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPathW(sz, buf) }, super::os2path).unwrap()
super::fill_utf16_buf(|buf, sz| unsafe { c::GetTempPath2W(sz, buf) }, super::os2path).unwrap()
}

#[cfg(not(target_vendor = "uwp"))]
Expand Down

0 comments on commit 5d1aa35

Please sign in to comment.