gcc-plugins: Add initial x86_64 kernexec plugin
Subsystems (3)
RFC 1/1 gcc-plugins: Add initial x86_64 kernexec plugin
This plugin, ported from PaX, instruments C function call sites (and returns) to set the high bit of the instruction pointer to force any attempts to execute userspace memory into the faulting non-canonical address range. This can be thought of as a weak form of SMEP emulation.
For function pointer calls, the compiler attempts an optimization of "set high bit", which is an "or" when registers are available:
3bf: 48 b8 00 00 00 00 00 movabs $0x8000000000000000,%rax 3c6: 00 00 80 3c9: 48 09 d8 or %rbx,%rax 3cc: ff d0 callq *%rax
And btsq for returns:
36: 48 0f ba 2c 24 3f btsq $0x3f,(%rsp) 3c: c3 retq
Note: assembly instrumentation still needs to be ported from PaX. Without this, there is significant coverage missing.
Signed-off-by Kees Cook <[email protected]>
--- arch/Kconfig | 17 ++ arch/x86/include/asm/module.h | 9 +- scripts/Makefile.gcc-plugins | 10 +- scripts/gcc-plugins/kernexec_plugin.c | 405 ++++++++++++++++++++++++++++++++++ scripts/link-vmlinux.sh | 2 +- 5 files changed, 439 insertions(+), 4 deletions(-) create mode 100644 scripts/gcc-plugins/kernexec_plugin.c
arch/Kconfig +17 -0
@@ -410,6 +410,23 @@ config GCC_PLUGIN_LATENT_ENTROPY * https://grsecurity.net/ * https://pax.grsecurity.net/ +config GCC_PLUGIN_KERNEXEC + bool "Provide weak SMEP emulation by instrumenting function calls" + depends on GCC_PLUGINS && X86_64 + help + For x86_64 CPUs that lack Supervisor Mode Execute Prevention (SMEP), + the kernel can be instrumented so that C call sites set the high + bit on the target address. This means that attempts to execute + userspace memory will force the execution to land in the + non-canonical memory region and trigger a fault (instead of letting + an attacker execute userspace memory). + + For systems with SMEP, select "n"; this option is redundant. + + This plugin was ported from grsecurity/PaX. More information at: + * https://grsecurity.net/ + * https://pax.grsecurity.net/ + config HAVE_CC_STACKPROTECTOR bool help
arch/x86/include/asm/module.h +7 -2
@@ -5,6 +5,7 @@#ifdef CONFIG_X86_64 /* X86_64 does not define MODULE_PROC_FAMILY */ +#define MODULE_PROC_FAMILY ""#elif definedCONFIG_M486 #define MODULE_PROC_FAMILY "486 "#elif definedCONFIG_M586
@@ -57,8 +58,12 @@#error unknown processor family#endif -#ifdef CONFIG_X86_32 -# define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY +#ifdef CONFIG_GCC_PLUGIN_KERNEXEC +#define MODULE_GCC_PLUGIN_KERNEXEC "KERNEXEC_BTS " +#else +#define MODULE_GCC_PLUGIN_KERNEXEC ""#endif +#define MODULE_ARCH_VERMAGIC MODULE_PROC_FAMILY MODULE_GCC_PLUGIN_KERNEXEC +#endif /* _ASM_X86_MODULE_H */
scripts/Makefile.gcc-plugins +9 -1
@@ -25,9 +25,16 @@ ifdef CONFIG_GCC_PLUGINS endif endif + gcc-plugin-$(CONFIG_GCC_PLUGIN_KERNEXEC) += kernexec_plugin.so + gcc-plugin-cflags-$(CONFIG_GCC_PLUGIN_KERNEXEC) += -DKERNEXEC_PLUGIN + gcc-plugin-aflags-$(CONFIG_GCC_PLUGIN_KERNEXEC) += -fplugin=$(objtree)/scripts/gcc-plugins/kernexec_plugin.so + gcc-plugin-aflags-$(CONFIG_GCC_PLUGIN_KERNEXEC) += -DKERNEXEC_PLUGIN + GCC_PLUGINS_CFLAGS := $(strip $(addprefix -fplugin=$(objtree)/scripts/gcc-plugins/, $(gcc-plugin-y)) $(gcc-plugin-cflags-y)) + GCC_PLUGINS_AFLAGS := $(gcc-plugin-aflags-y) - export PLUGINCC GCC_PLUGINS_CFLAGS GCC_PLUGIN GCC_PLUGIN_SUBDIR + export PLUGINCC GCC_PLUGIN GCC_PLUGIN_SUBDIR + export GCC_PLUGINS_CFLAGS GCC_PLUGINS_AFLAGS export SANCOV_PLUGIN DISABLE_LATENT_ENTROPY_PLUGIN ifneq ($(PLUGINCC),)
@@ -36,6 +43,7 @@ ifdef CONFIG_GCC_PLUGINS endif KBUILD_CFLAGS += $(GCC_PLUGINS_CFLAGS) + KBUILD_AFLAGS += $(GCC_PLUGINS_AFLAGS) GCC_PLUGIN := $(gcc-plugin-y) GCC_PLUGIN_SUBDIR := $(gcc-plugin-subdir-y) endif
scripts/gcc-plugins/kernexec_plugin.c new file +405 -0
405 lines not on this page · raw message
scripts/link-vmlinux.sh +1 -1
@@ -220,7 +220,7 @@ else fi; # final build of init/ -${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init GCC_PLUGINS_CFLAGS="${GCC_PLUGINS_CFLAGS}" +${MAKE} -f "${srctree}/scripts/Makefile.build" obj=init GCC_PLUGINS_CFLAGS="${GCC_PLUGINS_CFLAGS}" GCC_PLUGINS_AFLAGS="${GCC_PLUGINS_AFLAGS}" archive_builtin
Signature · 6 lines
2.7.4 -- Kees Cook Nexus Security