Rust: Enable HeapEnableTerminationOnCorruption for all Windows Rust programs

Created on 19 Nov 2018  路  2Comments  路  Source: rust-lang/rust

To help protect against heap exploits and bugs in unsafe or third-party code, the Rust compiler should emit code to enable Windows' HeapEnableTerminationOnCorruption feature for all Windows Rust programs.

With HeapEnableTerminationOnCorruption enabled, if the Windows heap manager detects an error in any system heap used by the process, it terminates the process. After a process enables this feature, it cannot be disabled. This feature should not cause any compatibility problems for correct programs.

See MSDN for HeapSetInformation and HeapEnableTerminationOnCorruption:

https://docs.microsoft.com/en-us/windows/desktop/api/heapapi/nf-heapapi-heapsetinformation

Here is how Firefox enables HeapEnableTerminationOnCorruption for its processes:

https://searchfox.org/mozilla-central/rev/5117a4c4e29fcf80a627fecf899a62f117368abf/security/sandbox/chromium/sandbox/win/src/process_mitigations.cc#60-67

https://searchfox.org/mozilla-central/rev/5117a4c4e29fcf80a627fecf899a62f117368abf/toolkit/xre/nsAppRunner.cpp#3912-3917

A-security C-enhancement O-windows

Most helpful comment

I took a stab at implementing this, by adding HeapSetInformation to std::rt::lang_start_internal. But it turned out to be already enabled by default. See https://blogs.msdn.microsoft.com/oldnewthing/20131227-00/?p=2243.

On 64-bit it is already always enabled. On 32-bit it also is when the subsystem major version is 6 or higher. Which is the default, and I am not sure this can be changed to something lower for Rust binaries. We only support the subsystems console and windows, and not setting a version.

Tested with this snippid:

extern crate libc;

fn main() {
    unsafe {
        let ptr = libc::malloc(80);
        libc::free(ptr);
        libc::free(ptr);
    }
}

with as result STATUS_HEAP_CORRUPTION for both 32- and 64-bit:

error: process didn't exit successfully: `target\i686-pc-windows-msvc\debug\windows_mitigations.exe` (exit code: 0xc0000374, STATUS_HEAP_CORRUPTION)

Seems like there is nothing to be done here?

All 2 comments

I took a stab at implementing this, by adding HeapSetInformation to std::rt::lang_start_internal. But it turned out to be already enabled by default. See https://blogs.msdn.microsoft.com/oldnewthing/20131227-00/?p=2243.

On 64-bit it is already always enabled. On 32-bit it also is when the subsystem major version is 6 or higher. Which is the default, and I am not sure this can be changed to something lower for Rust binaries. We only support the subsystems console and windows, and not setting a version.

Tested with this snippid:

extern crate libc;

fn main() {
    unsafe {
        let ptr = libc::malloc(80);
        libc::free(ptr);
        libc::free(ptr);
    }
}

with as result STATUS_HEAP_CORRUPTION for both 32- and 64-bit:

error: process didn't exit successfully: `target\i686-pc-windows-msvc\debug\windows_mitigations.exe` (exit code: 0xc0000374, STATUS_HEAP_CORRUPTION)

Seems like there is nothing to be done here?

Awesome! In that case, I'll close this issue then. Thanks for investigating.

Was this page helpful?
0 / 5 - 0 ratings