codeblog code is freedom — patching my itch

January 27, 2014

-fstack-protector-strong

Filed under: Blogging,Chrome OS,Debian,Security,Ubuntu,Ubuntu-Server — kees @ 2:28 pm

There will be a new option in gcc 4.9 named “-fstack-protector-strong“, which offers an improved version of “-fstack-protector” without going all the way to “-fstack-protector-all“. The stack protector feature itself adds a known canary to the stack during function preamble, and checks it when the function returns. If it changed, there was a stack overflow, and the program aborts. This is fine, but figuring out when to include it is the reason behind the various options.

Since traditionally stack overflows happen with string-based manipulations, the default (-fstack-protector), only includes the canary code when a function defines an 8 (--param=ssp-buffer-size=N, N=8 by default) or more byte local character array. This means just a few functions get the checking, but they’re probably the most likely to need it, so it’s an okay balance. Various distributions ended up lowering their default --param=ssp-buffer-size option down to 4, since there were still cases of functions that should have been protected but the conservative gcc upstream default of 8 wasn’t covering them.

However, even with the increased function coverage, there are rare cases when a stack overflow happens on other kinds of stack variables. To handle this more paranoid concern, -fstack-protector-all was defined to add the canary to all functions. This results in substantial use of stack space for saving the canary on deep stack users, and measurable (though surprisingly still relatively low) performance hit due to all the saving/checking. For a long time, Chrome OS used this, since we’re paranoid. :)

In the interest of gaining back some of the lost performance and not hitting our Chrome OS build images with such a giant stack-protector hammer, Han Shen from the Chrome OS compiler team created the new option -fstack-protector-strong, which enables the canary in many more conditions:

  • local variable’s address used as part of the right hand side of an assignment or function argument
  • local variable is an array (or union containing an array), regardless of array type or length
  • uses register local variables

This meant we were covering all the more paranoid conditions that might lead to a stack overflow. Chrome OS has been using this option instead of -fstack-protector-all for about 10 months now.

As a quick demonstration of the options, you can see this example program under various conditions. It tries to show off an example of shoving serialized data into a non-character variable, like might happen in some network address manipulations or streaming data parsing. Since I’m using memcpy here for clarity, the builds will need to turn off FORTIFY_SOURCE, which would also notice the overflow.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>

struct no_chars {
    unsigned int len;
    unsigned int data;
};

int main(int argc, char * argv[])
{
    struct no_chars info = { };

    if (argc < 3) {
        fprintf(stderr, "Usage: %s LENGTH DATA...\n", argv[0]);
        return 1;
    }

    info.len = atoi(argv[1]);
    memcpy(&info.data, argv[2], info.len);

    return 0;
}

Built with everything disabled, this faults trying to return to an invalid VMA:

    $ gcc -Wall -O2 -U_FORTIFY_SOURCE -fno-stack-protector /tmp/boom.c -o /tmp/boom
    $ /tmp/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    Segmentation fault (core dumped)
    

Built with FORTIFY_SOURCE enabled, we see the expected catch of the overflow in memcpy:

    $ gcc -Wall -O2 -D_FORTIFY_SOURCE=2 -fno-stack-protector /tmp/boom.c -o /tmp/boom
    $ /tmp/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    *** buffer overflow detected ***: /tmp/boom terminated
    ...
    

So, we’ll leave FORTIFY_SOURCE disabled for our comparisons. With pre-4.9 gcc, we can see that -fstack-protector does not get triggered to protect this function:

    $ gcc -Wall -O2 -U_FORTIFY_SOURCE -fstack-protector /tmp/boom.c -o /tmp/boom
    $ /tmp/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    Segmentation fault (core dumped)
    

However, using -fstack-protector-all does trigger the protection, as expected:

    $ gcc -Wall -O2 -U_FORTIFY_SOURCE -fstack-protector-all /tmp/boom.c -o /tmp/boom
    $ /tmp/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    *** stack smashing detected ***: /tmp/boom terminated
    Aborted (core dumped)
    

And finally, using the gcc snapshot of 4.9, here is -fstack-protector-strong doing its job:

    $ /usr/lib/gcc-snapshot/bin/gcc -Wall -O2 -U_FORTIFY_SOURCE -fstack-protector-strong /tmp/boom.c -o /tmp/boom
    $ /tmp/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
    *** stack smashing detected ***: /tmp/boom terminated
    Aborted (core dumped)
    

For Linux 3.14, I’ve added support for -fstack-protector-strong via the new CONFIG_CC_STACKPROTECTOR_STRONG option. The old CONFIG_CC_STACKPROTECTOR will be available as CONFIG_CC_STACKPROTECTOR_REGULAR. When comparing the results on builds via size and objdump -d analysis, here’s what I found with gcc 4.9:

A normal x86_64 “defconfig” build, without stack protector had a kernel text size of 11430641 bytes with 36110 function bodies. Adding CONFIG_CC_STACKPROTECTOR_REGULAR increased the kernel text size to 11468490 (a +0.33% change), with 1015 of 36110 functions stack-protected (2.81%). Using CONFIG_CC_STACKPROTECTOR_STRONG increased the kernel text size to 11692790 (+2.24%), with 7401 of 36110 functions stack-protected (20.5%). And 20% is a far-cry from 100% if support for -fstack-protector-all was added back to the kernel.

The next bit of work will be figuring out the best way to detect the version of gcc in use when doing Debian package builds, and using -fstack-protector-strong instead of -fstack-protector. For Ubuntu, it’s much simpler because it’ll just be the compiler default.

© 2014 – 2017, Kees Cook. This work is licensed under a Creative Commons Attribution-ShareAlike 4.0 License.
CC BY-SA 4.0

33 Comments

  1. What’s the deal with register locals? I though the “register” keyword was pretty much ignored by modern C compilers. Or is it just being used as an heuristic for crufty old code?

    Comment by pdw — January 27, 2014 @ 4:36 pm

  2. I don’t remember the reasoning right now. I’ll ask Han Shen. :)

    Comment by kees — January 27, 2014 @ 4:43 pm

  3. Why not just enable -fstack-protector-strong by default in upstream GCC. There is no reason for this not to be the default in every distribution of GCC, otherwise user-compiled binaries are vulnerable on Debian.

    Comment by Paul Wise — January 27, 2014 @ 7:03 pm

  4. Shouldn’t it be “local variable’s address used as part of the *left* hand side of an assignment” instead? Or do I misunderstand something?

    Comment by Nikolai Kondrashov — January 27, 2014 @ 10:58 pm

  5. This is an interface nitpick deep from the peanut gallery.

    Have you considered a “valued argument”, i.e. -fstack-protector=foo (where foo in {regular, strong, all})? Seems more extensible.

    Comment by tomás zerolo — January 28, 2014 @ 12:17 am

  6. Han Shen told me it was to catch unusual ways to get a reference to the frame address, with things like “register unsigned rsp __asm__(“rsp”);”, etc.

    Comment by kees — January 28, 2014 @ 12:41 pm

  7. I’d love to see this become the upstream gcc default. All it needs is someone with the time and interest to convince upstream to do it, and to fix any upstream test failures that might result from the change.

    It wasn’t a “valued argument” because there wasn’t an expectation for these various modes. As a result, I suspect leaving the behavior as it was seemed like the best way forward.

    Comment by kees — January 28, 2014 @ 12:44 pm

  8. Meh, but a function defining a “register uint32_t h;” for use in a tight inner loop should probably not be penalised like that… the “asm” is what triggers the trick, really.

    Comment by mirabilos — January 29, 2014 @ 1:33 am

  9. fstack-protector-all can protect all the fuctions ,even the local static vars,but the local static vars are not in the stack ,right?

    Comment by Jessica — December 26, 2014 @ 1:57 am

  10. Is there any other flag which makes fstack protection disable even after using fstack protection flag??

    Comment by Arvind — January 4, 2015 @ 11:03 pm

  11. Why -fstack-protector doesn’t work with threads???

    Comment by Arvind — January 9, 2015 @ 4:58 am

  12. -fstack-protector works fine with threads. The glibc canary is per-process, so each thread has the same canary check. There isn’t a way to turn it off at run time since it’s built into the machine code being executed.

    Comment by kees — February 3, 2015 @ 1:46 pm

  13. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | Debeelop – Native App Developer Team — July 27, 2016 @ 1:56 pm

  14. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses – Find Bravo — July 27, 2016 @ 2:00 pm

  15. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | Operating System Candy — July 27, 2016 @ 4:21 pm

  16. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses – Buy App Reviews — July 27, 2016 @ 4:31 pm

  17. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | SDK News — July 27, 2016 @ 7:47 pm

  18. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | DigitalMofo — July 27, 2016 @ 9:10 pm

  19. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses - InfoSec News — July 28, 2016 @ 5:16 pm

  20. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses – SourceCode — July 29, 2016 @ 11:14 pm

  21. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | Gamers APK — July 30, 2016 @ 1:41 pm

  22. […] protects against stack buffer overflows[4], but additionally provides coverage for more array types[5], as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses APK Mods — August 8, 2016 @ 12:42 am

  23. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses Modded APK — August 8, 2016 @ 2:45 am

  24. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses – Android — August 8, 2016 @ 12:52 pm

  25. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | find it — August 16, 2016 @ 4:37 am

  26. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses – Blogs Melas Banget — August 20, 2016 @ 10:03 am

  27. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protective Android with extra Linux kernel defenses - Cyanogenmod — August 30, 2016 @ 3:36 pm

  28. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | — September 15, 2016 @ 7:26 am

  29. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses – Romo Jemek — September 25, 2016 @ 4:28 am

  30. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | is your passion — October 8, 2016 @ 3:47 am

  31. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | mas ponci — October 10, 2016 @ 3:02 pm

  32. […] protects against stack buffer overflows, but additionally provides coverage for more array types, as the original only protected character arrays. Stack-protector-strong was implemented by Han […]

    Pingback by Protecting Android with more Linux kernel defenses | APK Gets — November 26, 2016 @ 11:45 pm

  33. This may be a naive question, but, what would be a real-world example of writing a string to an int variable?

    Comment by Yaron Shragai — February 14, 2017 @ 4:30 pm

Powered by WordPress