-
Notifications
You must be signed in to change notification settings - Fork 132
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Optimization option recommendations should have caveats #660
Comments
In particular, -fno-strict-aliasing should never ever ever be suggested anyway. The correct fix is always to fix your aliasing issues, which the compiler can already usually diagnose and you should recommend the relevant -Werror instead. If you do have strict-aliasing issues and don't fix them then UB will simply lead to random other bugs in random other parts of the optimizer since this option doesn't actually make it "well defined". |
To elaborate on this, while compilers who implement that option are surely saying they support a dialect where aliasing is allowed, it doesn't magically make such aliasing-violating-constructs okay. For example, we often find that aliasing violations go hand-in-hand with unaligned reads and writes. |
I disagree. In particular, I don't think they should be "moved" to a new section. The document is complicated enough already. If you want to add a special marking to some options, sure, though I think it may be harder to separate these cases than it might first appear.
That's true for all unintentional vulnerabilities. Sure, it's better if the vulnerability was removed from the source code. However, since it's quite hard to be perfect, we enable various options to reduce security risks. Risk is a function of likelihood and impact - if we reduce the likelihood or impact of a vulnerability, then we've reduce its risk. Let's focus on The reason The Linux kernel developers are very concerned about performance and security. If they're willing to enable an option for security, then that is excellent evidence it's worth adding. Is it better to write perfect code and never ever make a mistake, like, ever? Well, sure. Compiler options can't eliminate the value of good code. But that's not a real-world alternative. In practice, code has mistakes, so we need to enable options that reduce risks (likelihood or impact) from the incorrect code that WILL exist.
The
A "no UB" option would probably have such a massive performance overhead that no one could practically enable it in production. I can't see how you'd do that without massive changes to the C or C++ languages. That said, if there were such an option, and it had no impact on performance, then I would strongly urge its use specifically as a hardening option. I think we'll need to wait for flying pigs first :-). Since that's not practically available, we need to identify what we can do as a practical matter to reduce risks. And that's okay. All life has risks, but we can typically take steps to manage those risks. |
This discussion reminds me of the 1965 book Unsafe at Any Speed. To oversimplify, car makers argued that drivers should simply never make mistakes. This was found to be absurd; drivers were unable to never make mistakes. The result: cars were redesigned to handle the real-world situation that mistakes are inevitable. Specifically they were designed to be less likely to kill people in the accidents that do happen, including seat belts, better cabin protection, etc. Sure, it's much better to NOT be in an accident. But since the existence of accidents is 100% certain, we need to use cars designed to handle this unfortunate but expected reality. Similarly, it's much better to not make a mistake in code. But since the existence of mistakes in code is 100% certain, we also need to select compiler options to handle this unfortunate but expected reality. |
Let me just reiterate that it's actively dangerous and harmful to security to recommend -fno-strict-aliasing since it results in -Werror=strict-aliasing not providing diagnostics. That means that users do not see fatal -Werrors for their bad code. So bugs that would otherwise be caught and fixed are not caught and not fixed and crash or do worse things. If you would simply recommend the -Werror then it would fail to build and thus not be insecure. |
My argument in the original issue was to then go full hog and use various additional options to define a dialect of C, like We can also think about e.g. There is nothing particularly special about To give another example:
Or, and I'm sorry to make this argument, why even let people use I don't understand why this option in particular is special but the candidates I listed above, which do cause people to be confused when they write erroneous code (they often file GCC bugs over it), don't matter. Why is this particular pessimisation acceptable and special? Compiler optimisations often produce unexpected results? Anything interprocedural often leads to "spooky action at a distance" and I spend a fair amount of time helping people debug those -- should we recommend disabling anything IPA or LTO?
The kernel chooses to use this dialect and that's fine for them. It's a choice they've made. My point is that it's not as simple as an option to be slapped on and most people won't need it. The kernel also disables all vectorisation because it needs to e.g. save/restore SIMD registers (this works out well because it keeps code size down too), that doesn't mean all programs should do it. The kernel using something also isn't a strong argument for general-purpose code because they're in a specific domain. The kernel people don't generally file missed optimisation bugs, for example, because they already disable vectorisation as I mention above. The option was only added to Clang for the kernel to begin with in 2018. This doesn't imply it's particularly well-tested en-masse or that there's demand for it otherwise.
I didn't make the argument that UB is never problematic - I don't think it's fair to reduce it to that. I wouldn't have filed it if it was just about that because we've all been in those discussions before. I just think if the guide really wants to go this route, it should cover a bunch more, not single this out (with IMO insufficient background / explanation). |
Eli makes an interesting point here which ties in with the We're recommending use of i.e. What's the line between making development catch problems vs. making sure you don't get weird runtime reports from customers when something is deployed? |
I'm sympathetic to there being two schools of thought on options such as The reality is that there is not a one-size-fits all solution, particularly since we've decided that the scope of the guide goes beyond application code and should be applicable to embedded development as well. We are also motivated by trying to improve the situation for existing code bases, which (unfortunately) are quite likely to use pointer casts for type punning. In the embedded space, standardized methods of type punning may not apply either, e.g., That said, the argument that I think it would be great if we could expand the I agree with @david-a-wheeler that we should be conservative with spreading out the recommended options over several sections, but I'd be open to separating the options affecting language-level behavior to a separate table in Section 3, like. we now separate the warning options. I'd tend to agree that the current Table 2 caption does not really capture the nature of the I'd also be more than happy to consider additional options in this category. If there are volunteers to contribute PRs in that regard please open separate own issues / PRs for additional option proposals to facilitate discussion on their individual merits. I don't see not covering all options eliminating UB as a consistency problem though. We don't cover every hardening option available either, but we will consider any option that is brought to our attention. There were a lot of discussions in the Compiler Hardening BP calls over the the ones highlighted here in particular, but in the end we decided to include them since there were sufficient examples of real-world deployment to justify them. @thesamesam You keep bringing up Wireshark deploying of the guide recommendations with the implication that it was done with little consideration. @oakimk and I are from the same organization and we had a very good discussion around the project's needs and the threats relevant to Wireshark prior to him proposing the MR question and came to an agreement on the flags to propose there. While I cannot speak for the other examples you allude to, I can assure you a lot consideration went in to the flags to enable in that particular case. |
Just responding on the Wireshark bit first as I want to clear that up ASAP:
Sure, I wasn't trying to suggest carelessness. I'm sorry for giving that impression as I didn't mean to. No disrespect or anything like that was intended! Apologies to you and @oakimk as I really was not trying to convey carelessness or anything of that sort. I thought it was a direct port given that the commit message didn't communicate anything beyond following the guide. I in part reached that conclusion because I didn't see any discussion of binary size or performance being discussed in the PR either. I don't see it as a bad thing if people do that, given we want the guide to be easy to follow and obvious wins for most people. I didn't see any discussion over there about things being definitely included vs some for discussion etc, so I assumed that the whole thing was being used (which wasn't assuming bad faith, as I don't think this is unreasonable for people to be doing, even). But my point is that these aren't obvious wins and the guide doesn't provide the nuance I'm describing above. |
Yeah, there's a bunch of categories. Some stuff pretty much everybody should use as a bare minimum and it matches every major Linux distribution, and some stuff really does need careful evaluation with knowledge of the project. What I'm concerned about is people who are trying to do the right thing getting confused and thinking every flag mentioned should be adopted. We should be more honest about this, though, and not include a TL;DR then. I don't object to documenting some of these flags we currently disagree on at all, but I think that section really gives the impression that one can slap that on and be done with it? One reason I picked on Wireshark in particular was because I maintain it in Gentoo and I also know that it's a particularly large application which benefits a lot from more aggressive optimisation (both in binary size as well as startup time). But my perspective was maybe coloured a bit by my somewhat poor experience in CPython where I tried to give feedback on them adopting some of these flags (not the same ones we're discussing here) and it didn't really go anywhere. Maybe to put it another way: I think "for production code" is a bit too definitive unlike the other rows in that table which are unobjectionable, and it gives the impression they're of the same tier. Also, typically, production mode means stuff with fewer checks and is faster, but this is the opposite (which might be desirable but I don't think it's clear). Especially given that below the table, we say:
--
You're absolutely right, of course, but then we run into other issues, like SSP not being always appropriate there either, or indeed fortification. I'm just not sure if it's going to scale to have everything in one document like this? There's {embedded, regular} x {development, production} x {exploit mitigation, C nasal demons / footgun prevention}. |
I think this really gets to the heart of the matter. One of the big challenges we are trying to address with the guide is making the material easier to digest for a larger audience. The TL;DR and the summary of the situational options was an attempt at that, with the idea that it'll allow people to get started without reading the very long guide from start to finish before gaining any actionable advice. I'm very open to alternative suggestions for presentation, but I think we need something like the TL;DR that acts as a way to get started with less time commitment. I can completely see "for production code" being inadequate in communicating the caveats, so rewording that is maybe a good starting point in addressing the concerns within the current structure, along with improving the description of |
In the particular case of Wireshark and It's all very well and good to say "it should be reported to the compiler maintainers and fixed in the compiler," but that's not really an option for production code that is built on a wide variety of platforms, compilers, compiler versions, optimization levels, etc. Especially given the number of people who compile adding their own optimization flags and then file issues about problems they see with it. |
We discussed this issue during the C/C++ Compiler BP Guide call 2023-10-17 as well and one of the conclusions there as well was that the evidence (pointed to in the guide) makes a good case for We should make it clearer though that the intent with the We will also revisit the |
The compiler options guide currently mixes two things:
-fno-strict-aliasing
,-fno-strict-overflow
,-fno-delete-null-pointer-checks
)The issue with this is that the options that fall into case 2) aren't necessarily wins:
-fno-strict-aliasing
-only bugs.-fno-delete-null-pointer-checks
doing anything may well crop up in other contexts, because the real reason that caused the compiler to believe the check could be removed should be fixed).I'm not suggesting they be removed entirely from the guide, but I do think they belong in their own section and clearly marked as at least somewhat opinionated and not in the same class as the other options the guide recommends.
I would love to be able to recommend the Compiler Options Hardening Guide for C and C++ wholeheartedly, but I don't feel I can at the moment because of this.
https://gitlab.com/wireshark/wireshark/-/merge_requests/16860 is an example, but definitely not the only one, of the recommended/mentioned options being grabbed wholesale.
The text was updated successfully, but these errors were encountered: