Back

GCC Preparing to Introduce “-Fhardened” Security Hardening Option

106 points10 monthsphoronix.com
woodruffw10 months ago

Does anybody know how this interacts (or is intended to interact) with nested functions? My understanding is that GCC enables executable stacks when nested functions are used[1]; it'd be interesting to know whether they produce an error for this combination or continue to silently disable that mitigation.

[1]: https://gcc.gnu.org/onlinedocs/gccint/Trampolines.html#Suppo...

dooglius10 months ago

As indicated in that page, this is only an issue when one takes the address of a nested function, it doesn't happen merely by using nested functions.

jcalvinowens10 months ago

Why would you ever want to do that? It's a weird GNU extension, I've personally never seen it used in real code. I'm really curious.

woodruffw10 months ago

I don't ever want to do it. I'm worried that code I rely on will do it, and I'll end up building (or running) binaries that are missing basic security mitigations.

jcalvinowens10 months ago

You can always build with clang, it doesn't support this feature.

A desire to support clang is ubiquitous enough nowadays that weird stuff like this is getting ripped out of most active open source projects.

rwmj10 months ago

I think the background to this is simplifying the mess of RPM macros which are needed to set all these flags:

https://src.fedoraproject.org/rpms/redhat-rpm-config/blob/ra... https://src.fedoraproject.org/rpms/redhat-rpm-config/blob/ra... https://src.fedoraproject.org/rpms/redhat-rpm-config/blob/ra...

(and several other places). I'm sure Debian has something similar as do other distros, so having one flag which does it all is an advantage.

nerpderp8210 months ago

Do you know if any distros are going to enable it by default? I think -Fhardened should be opt-out not in.

mrlonglong10 months ago

Why is it "-Fhardened" and not "-fhardened"?

kevincox10 months ago

That is Hacker News butchering the title. The flag is in fact -fhardened as stated in TFA.

mrlonglong10 months ago

Glad to hear that. I was a bit worried the GCC boffins had lost it or something.

redfern31410 months ago

Every instance in the source article uses lower case; not sure if they changed it or the title just got mangled when posting

tutfbhuf10 months ago

Does it make sense to compile the linux kernel with -Fhardened?

rwmj10 months ago

I don't think it would work. Linux uses internal string functions while _FORTIFY_SOURCE works with help from glibc, plus PIE is just not an appropriate memory model for kernel code.

josefx10 months ago

Hardening flags can be problematic depending on which assumptions they make. Some years ago Golang ran into problems with kernels proactively checking for the stack guard page, since Go doesn't use any that safety feature just ended up corrupting random memory on every system call.

dmix10 months ago

Did Go address these issues or is it more fundamental?

josefx10 months ago

They switched to using a C shim for system calls like they where already using for other operating systems without a stable/public system call interface.

I think the affected distros also ended up removing the check over other issues.

nicce10 months ago

Performance impact would be too much likely. Control-flow integrity protections alone usually apply 5% overhead.

nerpderp8210 months ago

This line of reasoning will lead to always using insecure systems over secure ones. We lost much larger percentages due sidechannel mitigations. Layout has more effect than -O1 to -03 (Berger et al). Machines have never been faster than they are now, when will they be fast enough to also safe by default?

nicce10 months ago

It is not that simple.

Especially in kernel, is the likelihood of bugs so big that we increase the electricity consumption of everyone using Linux by default?

Sidechannel mitigations are not valid comparison, since it is protection against known, reproducible issues, not against "maybe there is a serious bug".

We should utilize the gains we get in increased computational power instead of wasting everything to inefficient software.

Machines are still not efficient enough to use garbage collected languages alone, which do not have the issues these compiler options mitigate. With efficient software, we can reduce the electricity bill and other resources.

+1
RetroTechie10 months ago
+1
MiguelX41310 months ago
chc410 months ago

Android already supports enabling kCFI[0], and says they saw negligable performance and code size impact. Even if it was 5%, security mitigations with a large security impact probably make sense to enable for a lot of usecases.

0: https://source.android.com/docs/security/test/kcfi

nicce10 months ago

There is actually study which notes both Anrdoid and Linux Kernel.

On Linux kernel the performance impact was from 2% to up to 25% and size increased around 30%.

On Android there was too much variance, but they note that Google got around 2-3% overhead, which sounds reasonable.

Without hardware acceleration (e.g. Intel CET), it will likely come with great cost. But we are yet to see those benchmarks.

But I would argue that you can take bigger impact for performance on Android or consumer phones anyway, since they are not performing high computation 24/7 usually, and they already have more computation power than most users require.

https://www.duo.uio.no/bitstream/handle/10852/79829/master.p...

_a_a_a_10 months ago

can you explain what these integrity protections are and why they're needed, or give a link? TIA

nicce10 months ago

Wikipedia summarises it quite well. In short, they attempt to prevent code-reuse attacks (ROP/JOP) https://en.wikipedia.org/wiki/Control-flow_integrity

LoganDark10 months ago

Is it "-Fhardened", "-fhardened", or "-fhardening"?

rurban10 months ago

-fhardened. see the article.

Just the HN headline is wrong

pxeger110 months ago

The auto-capitalisation HN does to headlines seems completely unnecessary to me.

jjgreen10 months ago

For info, it is not applied to edits of the title

LoganDark10 months ago

The article includes "-fhardening" as well. I agree that it's most likely to be -fhardened though.

rurban10 months ago

See https://gcc.gnu.org/pipermail/gcc-patches/2023-September/630...

It's still discussed in gcc-patches, and the name is proposed as -fhardened. Rebased patch is here: https://github.com/rurban/gcc/tree/fhardened

landr0id10 months ago

> -ftrivial-auto-var-init=pattern

Would be nice if this was zero instead of pattern.

formerly_proven10 months ago

From the compiler's PoV this is buggy code so it's better to make it predictably wrong rather than unboundedly incorrect (=security issues) or predictably correct (=people rely on UB).

woodruffw10 months ago

On top of your reasons (which are good ones!), there’s another good reason to avoid default zero initialization in languages like C: zero is a special value for all kinds of sensitive operations (like UID 0 for root).

In other words: a mitigation that initializes all values to 0 may make some uses of uninitialized variables worse than they were before.

google23412310 months ago

0 is also the most common variable value probably :p hard to tell a valid state from an invalid one

woodruffw10 months ago

Yes, that's why the "uninitialized" part is important; we're talking about a mitigation that would make UB potentially easier rather than harder to exploit.

Having 0 as a default initialization value in a language where doing so is well defined makes perfect sense; this is primarily an issue for C and C++ (to a lesser extent).

twic10 months ago

There is a proposal for C++ to zero-initialise automatic (ie local variables):

https://www.open-std.org/jtc1/sc22/wg21/docs/papers/2023/p27...

If that goes through, zeroing automatics would just be doing the same thing.

(FYI the feedback section of that paper is quite funny)

tialaramex10 months ago

Ideally C++ would tell people you can't do that and make it a compiler error ("Ill-formed") but my guess is that too many people insist they ought to be able to take arbitrary C++ 23 code, recompile it with C++ 26 and have that just always work even though the standard doesn't deliver that and so it won't happen.

P2723 is unlikely to happen. The "Erroneous behaviour" P2795 might have a better chance. This would say it's wrong to do uninitialized reads (whereas P2723 says they are initialized to zero and thus it's not wrong) but you always get zero anyway.

I think there's a fair chance WG21 manages to make everybody unhappy by kicking this can into the long grass as they have on many other controversial issues.

Zero is the wrong default, it's better than UB, but it's not good. This is actually a problem in languages like Go where zero defaults are core to the language design. The correct thing is that "I didn't initialize it" won't compile. Force the programmer to write what they meant, sometimes they meant zero, or None, or 0.0 or whatever, but surprisingly often when confronted with the question the programmer realises their design is wrong and needs a design level change.

+2
tsimionescu10 months ago
+2
xamuel10 months ago
saagarjha10 months ago

The proposal discusses the above concern (as it should, since the author has gotten almost every version of possible concerns). Perhaps one of them will win out and alter the proposal appropriately.

vbezhenar10 months ago

UB is a property of standard. GCC implements plenty of deviations from standard. Nothing wrong with that, as long as it's explicitly documented.

I'd even argue that defined behaviour is a subset of undefined behaviour. So I'd value compiler options to force well defined and "expected" behaviour instead of the current insanity.

Clang "optimized" away empty loop. My MCU gets locked because of it. I have to write `b .` with assembly, because C can't cut it. It is insanity.

saagarjha10 months ago

Optimizing out an empty loop in C is illegal.

+1
vbezhenar10 months ago
+1
Karellen10 months ago
javier_e0610 months ago

In my field zeroes are a problem when there is byte shift (not aligned). Specially data transfers. Alignment corruption cannot be detected when the memory area is all zeroes. We use things like 0xaaaa will have you.

blackpill0w10 months ago

I guess the reasoning behind this is that using a pattern (0xFE on GCC 12.2.0) is easier to recognise in a crash dump.

watersb10 months ago

I suppose that this meta-flag won't work with musl libc.