|
|
Subscribe / Log in / New account

Comparing GCC and Clang security features

By Jonathan Corbet
September 12, 2019

LPC
Hardening must be performed at all levels of a system, including in the compiler that is used to build that system. There are two viable compilers in the free-software community now, each of which offers a different set of security features. Kees Cook ran a session during the Toolchains microconference at the 2019 Linux Plumbers Conference that examined the security-feature support provided by both GCC and LLVM Clang, noting the places where each one could stand to improve.

Cook started by noting that most of the "old-school" security features have long since been supported by both compilers. These include stack canaries, warnings on unsafe format-string use, and more. Rather than look at those, he chose to focus on relatively new security-oriented features.

The first of these is per-function sections — putting each function into its own ELF section. This behavior is requested with the -ffunction-sections switch and is well supported by both [Kees Cook] compilers. The value of per-function sections is that they enable fine-grained address-space layout randomization, where the location of each function can be randomized independently of the others. It is a "bizarre and wonderful" feature, he said.

Implicit fall-through behavior in switch statements is a common source of bugs, so many projects are trying to eliminate it. To that end, both compilers support the -Wimplicit-fallthrough option. GCC has supported a special attribute making fall-through behavior explicit for some time; Clang has just gained that support as well. There are evidently no plans in the Clang community to support fall-through markers in comments, though, as GCC does. The kernel is now free of implicit fall-throughs; of the roughly 500 patches fixing fall-through warnings in the last year, Cook said, about 10% turned out to be addressing real bugs in the code.

Link-time optimization (LTO) works with both compilers now. It's not primarily a security feature, but it turns out to be necessary to implement control-flow integrity, which requires a view of all of the functions in a program. Both compilers support LTO, but updating the build tooling to make use of it is still painful. There are also, he said, concerns that LTO can expose differences between the C memory model and the model that the kernel uses, but nobody has provided any specifics about where things could go wrong. It is theoretically a problem, but "practicality matters" and these concerns shouldn't hold up adoption of LTO unless somebody can demonstrate a real-world problem.

Stack probing is the practice of reading a newly expanded stack in relatively small increments to defeat any attempt to jump over guard pages. GCC can build in this behavior now, controlled by the -fstack-clash-protection flag; Clang still lacks this capability. This feature is more useful in user space than in the kernel, Cook said, since the kernel has fully eliminated the use of variable-length arrays.

Clang provides a -mspeculative-load-hardening flag to turn on mitigations for Spectre v1; GCC does not have this support. Details about this feature can be found in this LLVM documentation. Enabling this feature has a notable performance impact, but it is still less costly than inserting lfence barriers everywhere. An attribute can be used to restrict hardening to specific functions, avoiding the need to slow down the entire program.

Functions do not need to preserve the contents of caller-saved registers, so they normally return with random data in those registers. Clearing those registers at return time, instead, may be useful to block any number of speculative attacks or side channels. The performance impact, Cook said, is tiny. Peter Zijlstra objected, saying that he would like to see a proper description of just what is being mitigated by this technique; the impact may be small, but the accumulation of such measures adds up to "death by a thousand cuts". Cook responded that there is value in bringing the architecture to a known state at function return; it may not block a specific attack right now, but "we don't know what is coming next". There is a patch for GCC implementing register clearing, but not for Clang.

Another relatively controversial measure is automatically initializing stack variables on function entry. GCC can do that now via a plugin; work is being done to add it to Clang, though the specific behavior is not what the kernel community would like. Clang will initialize variables to a poison pattern, but Linus Torvalds would rather be able to count on them being initialized to zero.

There are a couple of concerns about automatic initialization of stack variables, though. One is that it might mask warnings about the use of uninitialized variables; those warnings are still wanted. The tricks used by the GCC plugin can evidently confuse tools like KASAN. And, more importantly, this behavior is seen as a fundamental change to the semantics of C code, essentially creating a fork of the language. That is a big step that not everybody wants to take.

The next technique is structure layout randomization; GCC has been able to do this for the kernel via a plugin for a couple of years. There is a port of this support for Clang, but it seems to be stalled at the moment. Cook said that this feature is for "really paranoid builds" but is not really needed for most.

Signed integer overflow is technically undefined behavior in C — though Zijlstra quickly interjected that, in the kernel, it is well defined as twos-complement wrapping. Most of the time, the overflow of a signed int is unexpected, Cook said. Both compilers support the -fsanitize=signed-overflow flag, but its behavior is not ideal. If warnings are enabled, the build size grows by about 6%; if they are not enabled, the program just dies instead — not desirable behavior for the kernel. The warning also allows the overflow to happen; Cook would rather see the value saturate and stay there. Best, he said, would be to support a user-defined handler that can decide what to do about signed overflows.

Unsigned integer overflow, instead, is often done intentionally in the kernel. That behavior is well defined in C, but overflows can still lead to exploits. Clang can trap unsigned overflows now, while GCC cannot. Once again, though, he would rather see a mode where the value saturates rather than being allowed to wrap.

Control-flow integrity (CFI) is, to put it briefly, ensuring that code always jumps to a location that was intended to be jumped to. One aspect of that problem is returns from functions, which should go only to the place the function was called from. X86 processors can support this "backward-edge" checking in hardware, so no compiler support is needed. Arm64 processors have the PAC instruction, but those must be inserted by the compiler. Both compilers have support for these instructions. For processors without backward-edge CFI support, software needs to implement a shadow stack to preserve the integrity of function returns. Clang had support for shadow stacks, but problems resulted and the support has been removed; GCC has never had this support.

"Forward-edge" CFI, instead, ensures that indirect jumps go to the intended location; it's a matter of validating the destination as an appropriate target for the jump. Hardware support is limited to verifying that a given location is, indeed, the entry point of a function; that gives a big reduction in the attack surface, Cook said, but still does not provide a lot of real-world protection since attackers can just chain function calls together. X86 implements this feature with the ENDBR instruction, while Arm has BTI; both compilers support this feature. In software, Clang can make things tighter by checking in software that the called function has the correct prototype as well. But what we really need, Cook said, is truly fine-grained forward-edge CFI.

With that last item, Cook's talk concluded. The conversation returned briefly to integer overflow before things wound down; H. Peter Anvin suggested that, if the desire was to change the semantics of the integer type, a better approach might be to switch to a language like C++ where such changes are more readily supported. It is fair to say, though, that this suggestion was not widely accepted by the audience.

[Your editor thanks the Linux Foundation, LWN's travel sponsor, for supporting his travel to this event.]

Index entries for this article
SecurityClang
SecurityGCC
SecurityTools/Compilers
ConferenceLinux Plumbers Conference/2019


to post comments

Comparing GCC and Clang security features

Posted Sep 13, 2019 0:38 UTC (Fri) by sami (subscriber, #4163) [Link]

> Clang had support for shadow stacks, but problems resulted and the support has been removed

The problems were specific to x86. Clang supports shadow call stacks on arm64: https://clang.llvm.org/docs/ShadowCallStack.html

Comparing GCC and Clang security features

Posted Sep 13, 2019 11:52 UTC (Fri) by nix (subscriber, #2304) [Link] (4 responses)

I see a possible synergy here with the not-yet-quite-designed CTF backtrace section code. The thing that makes -fsanitize=signed-overflow into a bloated pig is replicated warnings for signed overflow for every single potential overflow locus in the program. One can shrink that a lot by printfing the function name and line number separately from the constant text so the constant text can be deduplicated, but if some backtrace section somewhere (like, say, the only one I have any influence over :) ) could be used to map from address to rough idea of lineno in function and get function names even for static functions, one could use this to eliminate the non-deduplicable function name and lineno info too.

Just a thought, and barely even a woolly thought, certainly not anything like a *design* yet (I mean, I'm not even sure if it makes sense to encode even a vague guess at linenos in a backtrace section: it's not worth introducing them just for this, but if we might need them *anyway*, this could serve as another user: it seems unlikely but it might be true, so I'll keep this potential usecase in mind when I get back to the backtrace stuff).

Actually printing the warnings would still add repeated code at every locus, but at least not repeated big strings. Maybe, possibly, an improvement...

Comparing GCC and Clang security features

Posted Sep 13, 2019 12:49 UTC (Fri) by eru (subscriber, #2753) [Link] (3 responses)

Back when compilers that checked things at run-time were popular, Intel included the single byte instruction INTO (interrupt if overflow flag set) into the x86 instruction set. I think it is still there. Using that the checking would have almost no effect on code size, if you can handle the resulting signal smartly.

Comparing GCC and Clang security features

Posted Sep 13, 2019 13:01 UTC (Fri) by nix (subscriber, #2304) [Link] (1 responses)

The code bloat here isn't really caused the overflow checks: those are fairly cheap. The problem is printing useful errors (including the locus of the problem) on error. Just a printf call is a lot bigger than the overflow checks, and the error-locus strings right now really explode the number of constant strings in the program.

Comparing GCC and Clang security features

Posted Sep 13, 2019 13:31 UTC (Fri) by eru (subscriber, #2753) [Link]

So using debug information is not an option? (Maybe that takes even more space).
How about something like what coverage instrumentation does? (Which includes adding some initialized constant data structures for each function).
For every function you would store the name, and an array mapping from the offsets of the overflow checks to line numbers. Not very much data there, since not every line needs to be mapped. I assume that after the trap there is some way to figure out the function where it happened and then find the map.

Comparing GCC and Clang security features

Posted Sep 25, 2019 20:38 UTC (Wed) by anton (subscriber, #25547) [Link]

INTO is not in AMD64. It has been replaced with one of the REX prefixes. However, a JO with a single-byte offset is also pretty small.

Comparing GCC and Clang security features

Posted Sep 13, 2019 11:58 UTC (Fri) by nix (subscriber, #2304) [Link] (1 responses)

FYI: finegrained forward-edge CFI verifies that indirect jumps go to a function with the right prototype. (An even finer-grained mode could be imagined that validates that at least some indirect calls for which this sort of thing is statically computable call only those functions which it is known that it is possible for that call-site to indirectly call, ruling out even some functions with the right prototype. A good intermediate state might be able to rule out indirect calls to functions whose address is never taken, even if they have the right prototype. Since most functions' addresses are never taken, this might reduce the set of ROP gadgets significantly.)

Comparing GCC and Clang security features

Posted Sep 13, 2019 15:40 UTC (Fri) by sami (subscriber, #4163) [Link]

> A good intermediate state might be able to rule out indirect calls to functions whose address is never taken

Clang's CFI implementation does exactly this.

Comparing GCC and Clang security features

Posted Sep 13, 2019 13:22 UTC (Fri) by ballombe (subscriber, #9523) [Link] (9 responses)

Really compilers should just support the keywords __wrap, __trap, __saturate, __overflow and allow to
declare each integer type separately
__wrap long int i;
__saturate unsigned long int j;
__overflow short int k;
etc.
instead of having a global setting.

Comparing GCC and Clang security features

Posted Sep 13, 2019 17:20 UTC (Fri) by mathstuf (subscriber, #69389) [Link] (2 responses)

That means you have even more hard-to-understand implicit conversion rules. What do you get if you add a __trap and __saturate integer? What if they're different sizes? Different signedness? Better to add all the variants of the operators as functions to the standard library. That would also make upcasts explicit (e.g., sataddu64(somei64, someu8)) while you're at it too.

Oh, you also might want __extend where operations return the next larger integer size to guarantee that the result fits.

Comparing GCC and Clang security features

Posted Sep 14, 2019 16:53 UTC (Sat) by ballombe (subscriber, #9523) [Link]

> What do you get if you add a __trap and __saturate integer? What if they're different sizes?

compilation error.

Comparing GCC and Clang security features

Posted Sep 14, 2019 17:34 UTC (Sat) by mpr22 (subscriber, #60784) [Link]

> What do you get if you add a __trap and __saturate integer?

There are two outcomes that for me would honour the principle of least astonishment:

Defined behaviour "compile-time error" as ballombe suggests, or in the alternative, defined behaviour "always follow the overflow semantics of the left-hand operand and ignore the overflow semantics of the right-hand operand".

Comparing GCC and Clang security features

Posted Sep 16, 2019 5:57 UTC (Mon) by dvdeug (guest, #10998) [Link]

Ada's plethora of integer types don't seem to have been a great success; programmers write a lot of casts between integer types, and more recent languages haven't emulated it. Also, Ada has a lot of builtin support for such things, including type overloading depending on the result (i.e. in x := f(5), which f is called can depend on the type of x.) In C, without function overloading, if they're separate types, we need to add, in addition to abs, labs, llabs, imaxabs, wabs, wlabs, wllabs, sabs, slabs, sllabs, tabs, tlabs, tllabs, oabs, olabs, and ollabs. And they're going to have to be different types, since the most negative integer (-2,147,483,648) needs to trap on tabs and go to the most positive integer (2,147,483,647) on sabs.

I'm not even sure you can have these types for short int, given the type extension rules in C. This type of thing is easy to say, but hard to clearly define, and even if defined, feels like would have been an overcomplex mess.

Comparing GCC and Clang security features

Posted Sep 16, 2019 7:10 UTC (Mon) by neilbrown (subscriber, #359) [Link] (4 responses)

> Really compilers should just support the keywords __wrap, __trap, __saturate, __overflow and allow to
> declare each integer type separately

These attributes are attributes of the integer operation, not of the integer itself - a bit like 'volatile' which Linus has ranted about.

Maybe it would be even better to think of them as attributes of the assignment.

a = b + c

traps on overflow.

a @= b+c

wraps if b+c overflowed (the symbol has a wrapping around it)

a #= b + c

saturates on overflow (the remnant of the real value gets hashed out)

if you try (b + c) * x you always get a trap, because overflow is mostly bad.
Of course, you could always do
(_tmp @= b+ c) * x
if you really want to wrap a nested expression.

Comparing GCC and Clang security features

Posted Sep 16, 2019 14:56 UTC (Mon) by nybble41 (subscriber, #55106) [Link] (2 responses)

Or rather than defining a bunch of new assignment operators, how about __builtin_wrapv(expr) evaluates expr in a context where signed overflow wraps, and __builtin_trapv(expr) does the same but in a context where signed overflow generates an exception? (For lexically scoped operations only, of course—code in other functions shouldn't be affected even if expr includes a function call.) The effect would be the same as if expr were compiled with the -fwrapv or -ftrapv option, respectively.

Comparing GCC and Clang security features

Posted Sep 16, 2019 17:10 UTC (Mon) by excors (subscriber, #95769) [Link] (1 responses)

I think that would behave very unintuitively, because of integer promotions. In code like "unsigned char x = __builtin_wrapv((unsigned char)0x80 + (unsigned char)0x80);", the '+' operator converts its arguments to int and returns an int, so there is no overflow inside the __builtin_wrapv. The assignment converts it to unsigned char, which may overflow, but that's outside the wrapv and will still have implementation-defined behaviour.

The rules for promotion and conversion mean that arithmetic in C is already pretty confusing, so I'm not sure it's a good idea to make it many times more complex with a whole new set of types or operators or magic evaluation contexts.

(Incidentally it looks like you can change the overflow behaviour at function scope with "#pragma GCC optimize("-ftrapv")" etc, which seems slightly less confusing than trying to change it at expression scope. Except it doesn't detect the overflow if e.g. the function gets inlined and evaluated at compile time, so -ftrapv is not actually useful for security.)

Comparing GCC and Clang security features

Posted Sep 16, 2019 22:04 UTC (Mon) by nybble41 (subscriber, #55106) [Link]

In the "unsigned char" case there is no overflow (technically) because the unsigned conversion is defined to use modulo arithmetic. For "signed char", however, you would put the assignment inside, i.e.:

signed char x, y, z;
__builtin_wrapv(x = y + z);

Comparing GCC and Clang security features

Posted Sep 16, 2019 17:54 UTC (Mon) by rgmoore (✭ supporter ✭, #75) [Link]

Maybe it would be even better to think of them as attributes of the assignment.

This sounds like a million bugs waiting to happen. When I use an integer in a context where an overflow might result in a bug, I want a guarantee that the integer hasn't overflowed. Assigning an overflow type to the integer when you declare it provides that guarantee. Requiring the overflow type to the assignment means you can only guarantee the integer hasn't overflowed by going back and checking every assignment to make sure they're of the correct type.

More generally, when would you ever want the same variable to have different overflow behavior in different assignments? Why, for example, would you ever want to have one assignment saturate and another one wrap? I can't think of an example for when that would be sensible, so giving you the power to do it at the expense of removing the utility of the overflow types in guaranteeing that a given value will behave predictably seems like a terrible mistake.

Comparing GCC and Clang security features

Posted Sep 13, 2019 17:38 UTC (Fri) by rweikusat2 (subscriber, #117920) [Link] (18 responses)

> Cook responded that there is value in bringing the architecture to a known state at function return; it may not block a specific
> attack right now, but "we don't know what is coming next".

This is an appeal to ignorance (logical fallacy).

Comparing GCC and Clang security features

Posted Sep 13, 2019 18:41 UTC (Fri) by rahulsundaram (subscriber, #21946) [Link] (15 responses)

> This is an appeal to ignorance (logical fallacy).

Aka proactive security? What about this one?

"The kernel is now free of implicit fall-throughs; of the roughly 500 patches fixing fall-through warnings in the last year, Cook said, about 10% turned out to be addressing real bugs in the code."

Comparing GCC and Clang security features

Posted Sep 13, 2019 20:11 UTC (Fri) by rweikusat2 (subscriber, #117920) [Link] (14 responses)

No. That's invalid reasoning aka invalid reasoning, and nothing else.

Comparing GCC and Clang security features

Posted Sep 13, 2019 20:42 UTC (Fri) by Cyberax (✭ supporter ✭, #52523) [Link] (13 responses)

No. This is a valid reasoning from the past experience.

Comparing GCC and Clang security features

Posted Sep 14, 2019 0:49 UTC (Sat) by rweikusat2 (subscriber, #117920) [Link] (12 responses)

Comparing GCC and Clang security features

Posted Sep 14, 2019 7:06 UTC (Sat) by pbonzini (subscriber, #60935) [Link] (10 responses)

Call it paranoia if you want, but it is certainly not ignorance. It is definitely a known fact that even the smallest knowledge of register contents has in the past been turned into exploits

Comparing GCC and Clang security features

Posted Sep 15, 2019 19:37 UTC (Sun) by rweikusat2 (subscriber, #117920) [Link]

That's definitely not a known fact as an exploit this 'feature' is supposed to 'defend' against would otherwise need to exist, ie, nobody would have to resort to "we don't what will happen in future" as reason for "why is this of value".

Comparing GCC and Clang security features

Posted Sep 15, 2019 19:53 UTC (Sun) by rweikusat2 (subscriber, #117920) [Link] (5 responses)

For a practical example. This ARM64 (mnemonical) machine code for a function supposed to strip trailing newlines from a string.
  46b710:       8b214001        add     x1, x0, w1, uxtw
  46b714:       eb01001f        cmp     x0, x1
  46b718:       540000a3        b.cc    46b72c 
  46b71c:       14000007        b       46b738 
  46b720:       d1000421        sub     x1, x1, #0x1
  46b724:       eb01001f        cmp     x0, x1
  46b728:       540000c0        b.eq    46b740 
  46b72c:       385ff022        ldurb   w2, [x1,#-1]
  46b730:       7100285f        cmp     w2, #0xa
  46b734:       54ffff60        b.eq    46b720 
  46b738:       3900003f        strb    wzr, [x1]
  46b73c:       d65f03c0        ret
  46b740:       aa0003e1        mov     x1, x0
  46b744:       3900003f        strb    wzr, [x1]
  46b748:       d65f03c0        ret
This is called with a pointer to the string in x0 and its length in w1. After the function has finished, x1 points to a null byte written over the the first trailing newline or immediately behind the string if there were no newlines. w2 contains the rightmost character which wasn't a newline or 10 if there were only newlines in the string. There's no information in these registers which isn't already available at the call site, hence, there's absolutely no point in changing the values of these two registers before returning from the function.

Comparing GCC and Clang security features

Posted Sep 15, 2019 20:14 UTC (Sun) by Cyberax (✭ supporter ✭, #52523) [Link] (2 responses)

So all the software you're writing consists of newline stripping? No other functions whatsoever?

That... explains things.

Comparing GCC and Clang security features

Posted Sep 15, 2019 21:00 UTC (Sun) by rweikusat2 (subscriber, #117920) [Link] (1 responses)

As usual, your wild speculations about me are impolite, untrue and besides the point.

Comparing GCC and Clang security features

Posted Sep 15, 2019 21:06 UTC (Sun) by Cyberax (✭ supporter ✭, #52523) [Link]

Nope, it's on point exactly.

It doesn't seem that you understand the issue. It's possible to guarantee that ONE particular and easy function has no adverse effects from clobbered registers, it's not possible to prove that ALL functions are equally safe.

Comparing GCC and Clang security features

Posted Sep 15, 2019 21:11 UTC (Sun) by mjg59 (subscriber, #23239) [Link]

You're able to guarantee which registers a compiler will use without manual inspection of the output?

Comparing GCC and Clang security features

Posted Sep 19, 2019 11:28 UTC (Thu) by jschrod (subscriber, #1646) [Link]

Proof by example. No, proof by simple example.

How valuable.

Comparing GCC and Clang security features

Posted Sep 15, 2019 20:09 UTC (Sun) by ken (subscriber, #625) [Link]

I must say I'm really skeptical about cleaning out caller saved registers. If you are cleaning up all registered used inside a called function on return you could potentially need to clear like 10-16 of them depending on what architecture you run on.

And without even a single example of when that would have help it does sound a bit excessive.

Comparing GCC and Clang security features

Posted Sep 15, 2019 20:34 UTC (Sun) by ballombe (subscriber, #9523) [Link] (1 responses)

Or maybe the register clean up code can make some future attack easier.
Paranoia cuts both way.

Comparing GCC and Clang security features

Posted Sep 19, 2019 10:39 UTC (Thu) by dvdeug (guest, #10998) [Link]

Pseudo-paranoia cuts both ways. But real paranoia has to follow patterns. It's hard to justify that register clean up makes some future attack easier; all it's doing is providing less information to the other functions. It's easy to imagine cases where the register clean up makes some future attack harder; the example rweikusat2 shows how string functions can leave pointers to strings in registers, and if that's working on sensitive information and something calls it and returns without sanitizing its own registers, it would return that information in registers. The expectation from a programmer that the only thing returned is what is explicitly returned would be violated.

Comparing GCC and Clang security features

Posted Sep 20, 2019 1:46 UTC (Fri) by kmweber (guest, #114635) [Link]

As is typically the case, the person who resorted to merely shouting "fallacy" rather than substantively explaining the alleged error in the argument has failed to understand both the argument they're responding to and the fallacy they're inaccurately name-dropping.

There's a difference between "we don't know with certainty that this is a safe state, so there is a chance that this is unsafe so let's not take any chances" (which is the argument actually being made) and "we dony know it's safe; therefore it is definitely unsafe" (which would indeed be an argument to ignorance).

Comparing GCC and Clang security features

Posted Sep 13, 2019 22:14 UTC (Fri) by Paf (subscriber, #91811) [Link] (1 responses)

This is a deliberately simplistic analysis, taking one sentence and turning it in to an independent logical proposition.

I’ll expand the sentence in to the context you know exists and you can tell me if it’s still “arguing from ignorance”.

“Many récent security vulnerabilities have come from leaking internal state that was not previously recognized as important. Therefore, it is worth scrubbing potential sources of this internal state information, even without specific attacks identified for that particular vector.”

Comparing GCC and Clang security features

Posted Sep 15, 2019 20:47 UTC (Sun) by flussence (guest, #85566) [Link]

> This is a deliberately simplistic analysis, taking one sentence and turning it in to an independent logical proposition.

And IIRC, doing so is such a tired logical fallacy that it even has its own pretentious latin label.

Comparing GCC and Clang security features

Posted Sep 14, 2019 2:23 UTC (Sat) by willy (subscriber, #9762) [Link] (3 responses)

Rather than C++, Rust has its advocates:

https://github.com/fishinabarrel/linux-kernel-module-rust

(click the link to the LSSNA presentation for some of their reasoning)

Comparing GCC and Clang security features

Posted Sep 14, 2019 8:49 UTC (Sat) by alonz (subscriber, #815) [Link] (2 responses)

That's quite different: switching to Rust implies a full rewrite of relevant code. Switching the kernel to compile as C++ is expected to be several orders of magnitude easier - at least in theory, much of the code should just compile as-is, and much of the rest can be fixed mechanically.

(I agree that Rust would provide more value—but at a hugely higher cost.)

Comparing GCC and Clang security features

Posted Sep 17, 2019 2:48 UTC (Tue) by roc (subscriber, #30627) [Link] (1 responses)

C++ isn't ideal for implementing wrappers around integer types. It's too easy for your wrapper type to be "non-trivial for the purposes of calls" (http://itanium-cxx-abi.github.io/cxx-abi/abi.html#non-tri...), in which case function parameters and results of that type must be passed by reference instead of by value, imposing significant performance penalties in some cases.

Comparing GCC and Clang security features

Posted Sep 17, 2019 13:10 UTC (Tue) by foom (subscriber, #14868) [Link]

While that can be true in general, it won't be for an integer wrapping type. There is no reason to write a custom move/copy constructor, or destructor, for such a type.

Additionally, if you're ok using a compiler extension, Clang has an attribute that can be used to force trivial abi, if you do have a type which can be passed in registers despite having non-trivial constructors/destructors: https://clang.llvm.org/docs/AttributeReference.html#trivi...

Comparing GCC and Clang security features

Posted Sep 16, 2019 15:04 UTC (Mon) by jgh (subscriber, #92451) [Link]

For uninitialized variables, how about hardware support for a poison bit?

Registers and stack locs would be written with a poisoned value at function head, and similar to an FP NaN, this should propagate on copies; it should trap on arithmetic or indirection use. It would be silently overwritten by a valid value.

For best protection the full memory hierachy would support it (the DRAM layer, eg, could use a know-bad ECC). A cpu-chip-only implementation could get partial protection by not writing farther out than the last-level cache.

Comparing GCC and Clang security features

Posted Sep 21, 2019 12:52 UTC (Sat) by robert_s (subscriber, #42402) [Link]

If we're really being paranoid, I'd be more interested in zeroing entire stack frames on return. Many functions leave a lot of potentially useful (or sensitive) values lying around that could be read-beyond-bounds into.


Copyright © 2019, Eklektix, Inc.
This article may be redistributed under the terms of the Creative Commons CC BY-SA 4.0 license
Comments and public postings are copyrighted by their creators.
Linux is a registered trademark of Linus Torvalds