Skip to content

Commit 923f8da

Browse files
authored
Rollup merge of rust-lang#89999 - talagrand:GetTempPath2, r=m-ou-se
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\
2 parents 0fb1c37 + 1d26e41 commit 923f8da

File tree

3 files changed

+16
-13
lines changed

3 files changed

+16
-13
lines changed

library/std/src/env.rs

+9-12
Original file line numberDiff line numberDiff line change
@@ -583,28 +583,25 @@ pub fn home_dir() -> Option<PathBuf> {
583583
/// may result in "insecure temporary file" security vulnerabilities. Consider
584584
/// using a crate that securely creates temporary files or directories.
585585
///
586-
/// # Unix
586+
/// # Platform-specific behavior
587587
///
588-
/// Returns the value of the `TMPDIR` environment variable if it is
588+
/// On Unix, returns the value of the `TMPDIR` environment variable if it is
589589
/// set, otherwise for non-Android it returns `/tmp`. If Android, since there
590590
/// is no global temporary folder (it is usually allocated per-app), it returns
591591
/// `/data/local/tmp`.
592+
/// On Windows, the behavior is equivalent to that of [`GetTempPath2`][GetTempPath2] /
593+
/// [`GetTempPath`][GetTempPath], which this function uses internally.
594+
/// Note that, this [may change in the future][changes].
592595
///
593-
/// # Windows
594-
///
595-
/// Returns the value of, in order, the `TMP`, `TEMP`,
596-
/// `USERPROFILE` environment variable if any are set and not the empty
597-
/// string. Otherwise, `temp_dir` returns the path of the Windows directory.
598-
/// This behavior is identical to that of [`GetTempPath`][msdn], which this
599-
/// function uses internally.
600-
///
601-
/// [msdn]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
596+
/// [changes]: io#platform-specific-behavior
597+
/// [GetTempPath2]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
598+
/// [GetTempPath]: https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppatha
602599
///
603600
/// ```no_run
604601
/// use std::env;
605602
///
606603
/// fn main() {
607-
/// let mut dir = env::temp_dir();
604+
/// let dir = env::temp_dir();
608605
/// println!("Temporary directory: {}", dir.display());
609606
/// }
610607
/// ```

library/std/src/sys/windows/c.rs

+6
Original file line numberDiff line numberDiff line change
@@ -1110,6 +1110,12 @@ compat_fn! {
11101110
-> () {
11111111
GetSystemTimeAsFileTime(lpSystemTimeAsFileTime)
11121112
}
1113+
1114+
// >= Win11 / Server 2022
1115+
// https://docs.microsoft.com/en-us/windows/win32/api/fileapi/nf-fileapi-gettemppath2a
1116+
pub fn GetTempPath2W(nBufferLength: DWORD, lpBuffer: LPCWSTR) -> DWORD {
1117+
GetTempPathW(nBufferLength, lpBuffer)
1118+
}
11131119
}
11141120

11151121
compat_fn! {

library/std/src/sys/windows/os.rs

+1-1
Original file line numberDiff line numberDiff line change
@@ -275,7 +275,7 @@ pub fn unsetenv(n: &OsStr) -> io::Result<()> {
275275
}
276276

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

281281
#[cfg(not(target_vendor = "uwp"))]

0 commit comments

Comments
 (0)