Tech News
← Back to articles

Hardening mode for the compiler

read original related products more articles

This is a joint proposal from: @AaronBallman, @shafik, @Endill, and @cor3ntin (with helpful input from others!)

Safety and security of C and C++ programs has been an important issue in the ecosystem for a while. Both WG21 and WG14 are making plans on how to improve these aspects of the language from their end, but the standard is constrained by what it can talk about and the speed at which it can move. Implementations need to be the driving force behind improving this situation; we’re ultimately responsible for the quality of what we provide our users. To that end, we should seriously consider what the Clang approach to hardening will be.

Thankfully, our implementation already provides a ton of mechanisms to help users improve the safety and security of their code. Unfortunately, those mechanisms are scattered throughout the implementation (some are feature flags, some are machine flags, some are macros, some are warnings, etc), poorly documented or not documented at all, and are not always easy to use. There are guides online to help users, but this requires more proactive consideration from users than we think is reasonable.

We’re proposing a path forward to unify a lot of our existing mechanisms in an easy-to-use way for users.

Setting User Expectations

One difficult decision we frequently face is “will this change break existing code?”. To date, user expectations have been set that we will work hard to avoid breaking their existing, working, correct code. For example, when deciding whether to emit a diagnostic or not, if we cannot prove something is wrong, we will frequently suppress the diagnostic (reduce false positives). However, this is in direct conflict with the needs for safety and security. In that scenario, if we cannot prove something is right, we should generally diagnose the construct (increase false positives). So this mode needs to set user expectations appropriately: your code breaking between compiler releases is a feature, not a bug. Obviously, we still want to strive for a low false positive rate in hardened code; it’s just that we should feel comfortable with rejecting correct, but suspicious, code. This includes a need for potentially ABI breaking changes; when the next spectre vulnerability hits, we want users to get the mitigation automatically rather than having to learn that they need the mitigation at all.

Prior Art in GCC

GCC has added a -fhardened mode (Instrumentation Options (Using the GNU Compiler Collection (GCC))). This mode enables several feature flags ( -ftrivial-auto-var-init , -fstack-protector-strong , etc) and predefines some macros ( _FORTIFY_SOURCE=3 , _GLIBCXX_ASSERTIONS ). It does not currently modify any diagnostic behavior or set any machine flags.

We could follow GCC’s lead and do exactly as they do and add -fhardened which aims for compatibility with GCC. However, we do not recommend aiming for an identical implementation between Clang and GCC. Differences in behavior between the two compilers already makes matching features difficult. When it comes to omnibus options, it becomes even harder. So we will likely never behave the same as GCC anyway – better to set user expectations up front that Clang and GCC hardening aim to solve the same problem, but may do so in different ways sometimes.

Goals

... continue reading