A way for build scripts to detect control-flow-guard=on

With Rust 1.47, the Rust flag -C control-flow-guard has been stabilized, mitigating potential memory vulnerabilities in unsafe Rust by utilizing windows' Control Flow Guard mechanism to ensure a memory corruption doesn't subvert control flow.

While most rust code is protected by this mechanism, a lot of Rust program still link to non-Rust, C/C++ code. This is often done through build script that compile C code through the cc crate. Examples include ring, sqlite, and many others. This code won't, by default, be protected by Control Flow Guard. In order for this code to also be protected, one must pass /guard:cf to the C compiler. This can be done today by setting the CFLAGS=/guard:cf environment variable before running cargo build.

This is, however, suboptimal. It requires setting a variable outside of the normal cargo mechanisms in order to ensure the code will be properly protected. It's error prone. Ideally, build scripts should be able to observe the current state of the control-flow-guard flag, and automatically inject the appropriate compiler flag to their compiler when building code. For instance, cc-rs could check if control-flow-guard is enabled and automatically add /guard:cf when invoking the MSVC compiler. See https://github.com/alexcrichton/cc-rs/issues/557

The problem then becomes how to detect the current state of the control-flow-guard flag. Right now, I believe there is no simple way of getting its state. It can be enabled in a myriad of ways (RUSTFLAGS, .cargo/config, cargo rustc arguments...). I can see a few ways of enabling build scripts to check its state:

  • Expose the final RUSTFLAGS to build script, let them parse it to find the control-flow-guard args. This could be useful for other purposes.
  • Add some kind of cfg(control_flow_guard) when rustflags is enabled, which would get populated in CARGO_CFG_*.
  • Make control_flow_guard into a target feature, such that it ends up in CARGO_TARGET_FEATURES?

This would be great. I have the same problem with -C target_cpu and -C target-feature which should be translated to appropriate C flags for ABI and expected code performance to match.