{"id":491,"date":"2011-04-27T14:39:28","date_gmt":"2011-04-27T22:39:28","guid":{"rendered":"http:\/\/www.outflux.net\/blog\/?p=491"},"modified":"2011-04-27T14:39:28","modified_gmt":"2011-04-27T22:39:28","slug":"non-executable-kernel-memory-progress","status":"publish","type":"post","link":"https:\/\/outflux.net\/blog\/archives\/2011\/04\/27\/non-executable-kernel-memory-progress\/","title":{"rendered":"non-executable kernel memory progress"},"content":{"rendered":"<p>The Linux kernel attempts to protect portions of its memory from unexpected modification (through potential future exploits) by setting areas read-only where the compiler has allowed it (<a href=\"https:\/\/wiki.ubuntu.com\/Security\/Features#rodata\">CONFIG_DEBUG_RODATA<\/a>). This, combined with <a href=\"https:\/\/lkml.org\/lkml\/2009\/12\/13\/272\">marking function pointer tables &#8220;const&#8221;<\/a>, reduces the number of easily writable kernel memory targets for attackers.<\/p>\n<p>However, modules (which are almost the bulk of kernel code) were not handled, and remained read-write, regardless of compiler markings. In 2.6.38, thanks to the efforts of many people (especially Siarhei Liakh and Matthieu Castet), <a href=\"https:\/\/wiki.ubuntu.com\/Security\/Features#module-ronx\">CONFIG_DEBUG_SET_MODULE_RONX<\/a> was created (and CONFIG_DEBUG_RODATA expanded).<\/p>\n<p>To visualize the effects, I <a href=\"http:\/\/www.outflux.net\/software\/patches\/ptdump-modules.patch\">patched<\/a> Arjan van de Ven&#8217;s <code>arch\/x86\/mm\/dump_pagetables.c<\/code> to be a loadable module so I could look at <code>\/sys\/kernel\/debug\/kernel_page_tables<\/code> without needing to rebuild my kernel with CONFIG_X86_PTDUMP.<\/p>\n<p>Comparing Lucid (2.6.32), Maverick (2.6.35), and Natty (2.6.38), it&#8217;s clear to see the effects of the RO\/NX improvements, especially in the &#8220;Modules&#8221; section which has no NX markings at all before 2.6.38:<\/p>\n<pre class=\"brush:shell\">\r\nlucid-amd64# awk '\/Modules\/,\/End Modules\/' \/sys\/kernel\/debug\/kernel_page_tables | grep NX | wc -l\r\n0\r\n\r\nmaverick-amd64# awk '\/Modules\/,\/End Modules\/' \/sys\/kernel\/debug\/kernel_page_tables | grep NX | wc -l\r\n0\r\n\r\nnatty-amd64# awk '\/Modules\/,\/End Modules\/' \/sys\/kernel\/debug\/kernel_page_tables | grep NX | wc -l\r\n76\r\n<\/pre>\n<p>2.6.38&#8217;s memory region is much more granular, since each module has been chopped up for the various segment permissions:<\/p>\n<pre class=\"brush:shell\">\r\nlucid-amd64# awk '\/Modules\/,\/End Modules\/' \/sys\/kernel\/debug\/kernel_page_tables | wc -l\r\n53\r\n\r\nmaverick-amd64# awk '\/Modules\/,\/End Modules\/' \/sys\/kernel\/debug\/kernel_page_tables | wc -l\r\n67\r\n\r\nnatty-amd64# awk '\/Modules\/,\/End Modules\/' \/sys\/kernel\/debug\/kernel_page_tables | wc -l\r\n155\r\n<\/pre>\n<p>For example, here&#8217;s the large &#8220;sunrpc&#8221; module. &#8220;RW&#8221; is read-write, &#8220;ro&#8221; is read-only, &#8220;x&#8221; is executable, and &#8220;NX&#8221; is non-executable:<\/p>\n<pre class=\"brush:shell\">\r\nmaverick-amd64# awk '\/^'$(awk '\/^sunrpc\/ {print $NF}' \/proc\/modules)'\/','!\/GLB\/' \/sys\/kernel\/debug\/kernel_page_tables\r\n0xffffffffa005d000-0xffffffffa0096000         228K     RW             GLB x  pte\r\n0xffffffffa0096000-0xffffffffa0098000           8K                           pte\r\n\r\nnatty-amd64# awk '\/^'$(awk '\/^sunrpc\/ {print $NF}' \/proc\/modules)'\/','!\/GLB\/' \/sys\/kernel\/debug\/kernel_page_tables\r\n0xffffffffa005d000-0xffffffffa007a000         116K     ro             GLB x  pte\r\n0xffffffffa007a000-0xffffffffa0083000          36K     ro             GLB NX pte\r\n0xffffffffa0083000-0xffffffffa0097000          80K     RW             GLB NX pte\r\n0xffffffffa0097000-0xffffffffa0099000           8K                           pte\r\n<\/pre>\n<p>The latter looks a whole lot more like a proper ELF (text segment is read-only and executable, rodata segment is read-only and non-executable, and data segment is read-write and non-executable).<\/p>\n<p>Just another reason to make sure you&#8217;re using your <a href=\"https:\/\/wiki.ubuntu.com\/Security\/Features#nx\">CPU&#8217;s NX bit<\/a> (via 64bit or 32bit-PAE kernels)! (And no, <a href=\"http:\/\/www.phoronix.com\/scan.php?page=article&#038;item=ubuntu_32_pae&#038;num=5\">PAE is not slower<\/a> in any meaningful way.)<\/p>\n<p style='text-align:left'>&copy; 2011, <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>The Linux kernel attempts to protect portions of its memory from unexpected modification (through potential future exploits) by setting areas read-only where the compiler has allowed it (CONFIG_DEBUG_RODATA). This, combined with marking function pointer tables &#8220;const&#8221;, reduces the number of easily writable kernel memory targets for attackers. However, modules (which are almost the bulk of [&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,18,6,14,19],"tags":[],"_links":{"self":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/491"}],"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=491"}],"version-history":[{"count":12,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/491\/revisions"}],"predecessor-version":[{"id":503,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/posts\/491\/revisions\/503"}],"wp:attachment":[{"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/media?parent=491"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/categories?post=491"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/outflux.net\/blog\/wp-json\/wp\/v2\/tags?post=491"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}