{"id":711,"date":"2014-01-27T14:28:18","date_gmt":"2014-01-27T22:28:18","guid":{"rendered":"http:\/\/www.outflux.net\/blog\/?p=711"},"modified":"2017-01-18T17:20:00","modified_gmt":"2017-01-19T01:20:00","slug":"fstack-protector-strong","status":"publish","type":"post","link":"https:\/\/outflux.net\/blog\/archives\/2014\/01\/27\/fstack-protector-strong\/","title":{"rendered":"-fstack-protector-strong"},"content":{"rendered":"<p>There will be a new option in gcc 4.9 named &#8220;<code>-fstack-protector-strong<\/code>&#8220;, which offers an improved version of &#8220;<code>-fstack-protector<\/code>&#8221; without going all the way to &#8220;<code>-fstack-protector-all<\/code>&#8220;. 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.<\/p>\n<p>Since traditionally stack overflows happen with string-based manipulations, the default (<code>-fstack-protector<\/code>), only includes the canary code when a function defines an 8 (<code>--param=ssp-buffer-size=<strong>N<\/strong><\/code>, N=8 by default) or more byte local character array. This means just a few functions get the checking, but they&#8217;re probably the most likely to need it, so it&#8217;s an okay balance. Various distributions ended up lowering their default <code>--param=ssp-buffer-size<\/code> 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&#8217;t covering them.<\/p>\n<p>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, <code>-fstack-protector-all<\/code> was defined to add the canary to <strong>all<\/strong> 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&#8217;re paranoid. :)<\/p>\n<p>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 <a href=\"http:\/\/gcc.gnu.org\/ml\/gcc-patches\/2012-06\/msg00974.html\">created<\/a> the new option <code>-fstack-protector-strong<\/code>, which enables the canary in many more <a href=\"https:\/\/docs.google.com\/a\/google.com\/document\/d\/1xXBH6rRZue4f296vGt9YQcuLVQHeE516stHwt8M9xyU\">conditions<\/a>:<\/p>\n<ul>\n<li>local variable&#8217;s address used as part of the right hand side of an assignment or function argument<\/li>\n<li>local variable is an array (or union containing an array), regardless of array type or length<\/li>\n<li>uses register local variables<\/li>\n<\/ul>\n<p>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 <code>-fstack-protector-all<\/code> for about 10 months now.<\/p>\n<p>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&#8217;m using <code>memcpy<\/code> here for clarity, the builds will need to turn off FORTIFY_SOURCE, which would also notice the overflow.<\/p>\n<pre class=\"brush:c\">\r\n#include &lt;stdio.h&gt;\r\n#include &lt;stdlib.h&gt;\r\n#include &lt;string.h&gt;\r\n\r\nstruct no_chars {\r\n    unsigned int len;\r\n    unsigned int data;\r\n};\r\n\r\nint main(int argc, char * argv[])\r\n{\r\n    struct no_chars info = { };\r\n\r\n    if (argc &lt; 3) {\r\n        fprintf(stderr, \"Usage: %s LENGTH DATA...\\n\", argv[0]);\r\n        return 1;\r\n    }\r\n\r\n    info.len = atoi(argv[1]);\r\n    memcpy(&info.data, argv[2], info.len);\r\n\r\n    return 0;\r\n}\r\n<\/pre>\n<p>Built with everything disabled, this faults trying to return to an invalid VMA:<\/p>\n<ul>\n<pre>\r\n$ gcc -Wall -O2 <strong>-U_FORTIFY_SOURCE -fno-stack-protector<\/strong> \/tmp\/boom.c -o \/tmp\/boom\r\n$ \/tmp\/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\nSegmentation fault (core dumped)\r\n<\/pre>\n<\/ul>\n<p>Built with FORTIFY_SOURCE enabled, we see the expected catch of the overflow in <code>memcpy<\/code>:<\/p>\n<ul>\n<pre>\r\n$ gcc -Wall -O2 <strong>-D_FORTIFY_SOURCE=2<\/strong> -fno-stack-protector \/tmp\/boom.c -o \/tmp\/boom\r\n$ \/tmp\/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n*** buffer overflow detected ***: \/tmp\/boom terminated\r\n...\r\n<\/pre>\n<\/ul>\n<p>So, we&#8217;ll leave FORTIFY_SOURCE disabled for our comparisons. With pre-4.9 gcc, we can see that <code>-fstack-protector<\/code> does not get triggered to protect this function:<\/p>\n<ul>\n<pre>\r\n$ gcc -Wall -O2 -U_FORTIFY_SOURCE <strong>-fstack-protector<\/strong> \/tmp\/boom.c -o \/tmp\/boom\r\n$ \/tmp\/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\nSegmentation fault (core dumped)\r\n<\/pre>\n<\/ul>\n<p>However, using <code>-fstack-protector-all<\/code> does trigger the protection, as expected:<\/p>\n<ul>\n<pre>\r\n$ gcc -Wall -O2 -U_FORTIFY_SOURCE <strong>-fstack-protector-all<\/strong> \/tmp\/boom.c -o \/tmp\/boom\r\n$ \/tmp\/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n*** stack smashing detected ***: \/tmp\/boom terminated\r\nAborted (core dumped)\r\n<\/pre>\n<\/ul>\n<p>And finally, using the gcc snapshot of 4.9, here is <code>-fstack-protector-strong<\/code> doing its job:<\/p>\n<ul>\n<pre>\r\n$ \/usr\/lib\/gcc-snapshot\/bin\/gcc -Wall -O2 -U_FORTIFY_SOURCE <strong>-fstack-protector-strong<\/strong> \/tmp\/boom.c -o \/tmp\/boom\r\n$ \/tmp\/boom 64 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA\r\n*** stack smashing detected ***: \/tmp\/boom terminated\r\nAborted (core dumped)\r\n<\/pre>\n<\/ul>\n<p>For Linux 3.14, I&#8217;ve <a href=\"http:\/\/git.kernel.org\/linus\/8779657d29c0ebcc0c94ede4df2f497baf1b563f\">added support<\/a> for <code>-fstack-protector-strong<\/code> via the new <code>CONFIG_CC_STACKPROTECTOR_STRONG<\/code> option. The old <code>CONFIG_CC_STACKPROTECTOR<\/code> will be available as <code>CONFIG_CC_STACKPROTECTOR_REGULAR<\/code>. When comparing the results on builds via <code>size<\/code> and <code>objdump -d<\/code> analysis, here&#8217;s what I found with gcc 4.9:<\/p>\n<p>A normal x86_64 &#8220;defconfig&#8221; build, without stack protector had a kernel text size of 11430641 bytes with 36110 function bodies. Adding <code>CONFIG_CC_STACKPROTECTOR_REGULAR<\/code> increased the kernel text size to 11468490 (a +0.33% change), with 1015 of 36110 functions stack-protected (2.81%). Using <code>CONFIG_CC_STACKPROTECTOR_STRONG<\/code> 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 <code>-fstack-protector-all<\/code> was added back to the kernel.<\/p>\n<p>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 <code>-fstack-protector-strong<\/code> instead of <code>-fstack-protector<\/code>. For Ubuntu, it&#8217;s much simpler because it&#8217;ll just be the compiler default.<\/p>\n<p style='text-align:left'>&copy; 2014 &#8211; 2017, <a href=\"https:\/\/outflux.net\/blog\/\">Kees Cook<\/a>. This work is licensed under a <a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/4.0\/\">Creative Commons Attribution-ShareAlike 4.0 License<\/a>.<br \/><a rel=\"license\" href=\"http:\/\/creativecommons.org\/licenses\/by-sa\/4.0\/\"><img decoding=\"async\" alt=\"CC BY-SA 4.0\" style=\"border-width:0\" src=\"https:\/\/i.creativecommons.org\/l\/by-sa\/4.0\/88x31.png\" \/><\/a> <\/p>\n","protected":false},"excerpt":{"rendered":"<p>There will be a new option in gcc 4.9 named &#8220;-fstack-protector-strong&#8220;, which offers an improved version of &#8220;-fstack-protector&#8221; without going all the way to &#8220;-fstack-protector-all&#8220;. 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, [&hellip;]<\/p>\n","protected":false},"author":2,"featured_media":0,"comment_status":"open","ping_status":"closed","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[5,20,18,6,14,19],"tags":[],"_links":{"self":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/711"}],"collection":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/users\/2"}],"replies":[{"embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/comments?post=711"}],"version-history":[{"count":20,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/711\/revisions"}],"predecessor-version":[{"id":994,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/711\/revisions\/994"}],"wp:attachment":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/media?parent=711"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/categories?post=711"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/tags?post=711"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}