Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

arch: Introduce post-init read-only memory

One of the easiest ways to protect the kernel from attack is to reduce
the internal attack surface exposed when a "write" flaw is available. By
making as much of the kernel read-only as possible, we reduce the
attack surface.

Many things are written to only during __init, and never changed
again. These cannot be made "const" since the compiler will do the wrong
thing (we do actually need to write to them). Instead, move these items
into a memory region that will be made read-only during mark_rodata_ro()
which happens after all kernel __init code has finished.

This introduces __ro_after_init as a way to mark such memory, and adds
some documentation about the existing __read_mostly marking.

This improves the security of the Linux kernel by marking formerly
read-write memory regions as read-only on a fully booted up system.

Based on work by PaX Team and Brad Spengler.

Signed-off-by: Kees Cook <keescook@chromium.org>
Cc: Andy Lutomirski <luto@amacapital.net>
Cc: Arnd Bergmann <arnd@arndb.de>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brad Spengler <spender@grsecurity.net>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: David Brown <david.brown@linaro.org>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Emese Revfy <re.emese@gmail.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Mathias Krause <minipli@googlemail.com>
Cc: Michael Ellerman <mpe@ellerman.id.au>
Cc: PaX Team <pageexec@freemail.hu>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: kernel-hardening@lists.openwall.com
Cc: linux-arch <linux-arch@vger.kernel.org>
Link: http://lkml.kernel.org/r/1455748879-21872-5-git-send-email-keescook@chromium.org
Signed-off-by: Ingo Molnar <mingo@kernel.org>

authored by

Kees Cook and committed by
Ingo Molnar
c74ba8b3 9ccaf77c

+18
+3
arch/parisc/include/asm/cache.h
··· 22 22 23 23 #define __read_mostly __attribute__((__section__(".data..read_mostly"))) 24 24 25 + /* Read-only memory is marked before mark_rodata_ro() is called. */ 26 + #define __ro_after_init __read_mostly 27 + 25 28 void parisc_cache_init(void); /* initializes cache-flushing */ 26 29 void disable_sr_hashing_asm(int); /* low level support for above */ 27 30 void disable_sr_hashing(void); /* turns off space register hashing */
+1
include/asm-generic/vmlinux.lds.h
··· 256 256 .rodata : AT(ADDR(.rodata) - LOAD_OFFSET) { \ 257 257 VMLINUX_SYMBOL(__start_rodata) = .; \ 258 258 *(.rodata) *(.rodata.*) \ 259 + *(.data..ro_after_init) /* Read only after init */ \ 259 260 *(__vermagic) /* Kernel version magic */ \ 260 261 . = ALIGN(8); \ 261 262 VMLINUX_SYMBOL(__start___tracepoints_ptrs) = .; \
+14
include/linux/cache.h
··· 12 12 #define SMP_CACHE_BYTES L1_CACHE_BYTES 13 13 #endif 14 14 15 + /* 16 + * __read_mostly is used to keep rarely changing variables out of frequently 17 + * updated cachelines. If an architecture doesn't support it, ignore the 18 + * hint. 19 + */ 15 20 #ifndef __read_mostly 16 21 #define __read_mostly 22 + #endif 23 + 24 + /* 25 + * __ro_after_init is used to mark things that are read-only after init (i.e. 26 + * after mark_rodata_ro() has been called). These are effectively read-only, 27 + * but may get written to during init, so can't live in .rodata (via "const"). 28 + */ 29 + #ifndef __ro_after_init 30 + #define __ro_after_init __attribute__((__section__(".data..ro_after_init"))) 17 31 #endif 18 32 19 33 #ifndef ____cacheline_aligned