mirror of
https://github.com/torvalds/linux.git
synced 2024-11-16 09:02:00 +00:00
x86, kaslr: randomize module base load address
Randomize the load address of modules in the kernel to make kASLR effective for modules. Modules can only be loaded within a particular range of virtual address space. This patch adds 10 bits of entropy to the load address by adding 1-1024 * PAGE_SIZE to the beginning range where modules are loaded. The single base offset was chosen because randomizing each module load ends up wasting/fragmenting memory too much. Prior approaches to minimizing fragmentation while doing randomization tend to result in worse entropy than just doing a single base address offset. Example kASLR boot without this change, with a single module loaded: ---[ Modules ]--- 0xffffffffc0000000-0xffffffffc0001000 4K ro GLB x pte 0xffffffffc0001000-0xffffffffc0002000 4K ro GLB NX pte 0xffffffffc0002000-0xffffffffc0004000 8K RW GLB NX pte 0xffffffffc0004000-0xffffffffc0200000 2032K pte 0xffffffffc0200000-0xffffffffff000000 1006M pmd ---[ End Modules ]--- Example kASLR boot after this change, same module loaded: ---[ Modules ]--- 0xffffffffc0000000-0xffffffffc0200000 2M pmd 0xffffffffc0200000-0xffffffffc03bf000 1788K pte 0xffffffffc03bf000-0xffffffffc03c0000 4K ro GLB x pte 0xffffffffc03c0000-0xffffffffc03c1000 4K ro GLB NX pte 0xffffffffc03c1000-0xffffffffc03c3000 8K RW GLB NX pte 0xffffffffc03c3000-0xffffffffc0400000 244K pte 0xffffffffc0400000-0xffffffffff000000 1004M pmd ---[ End Modules ]--- Signed-off-by: Andy Honig <ahonig@google.com> Link: http://lkml.kernel.org/r/20140226005916.GA27083@www.outflux.net Signed-off-by: Kees Cook <keescook@chromium.org> Signed-off-by: H. Peter Anvin <hpa@linux.intel.com>
This commit is contained in:
parent
cfbf8d4857
commit
e2b32e6785
@ -2053,8 +2053,8 @@ bytes respectively. Such letter suffixes can also be entirely omitted.
|
|||||||
IOAPICs that may be present in the system.
|
IOAPICs that may be present in the system.
|
||||||
|
|
||||||
nokaslr [X86]
|
nokaslr [X86]
|
||||||
Disable kernel base offset ASLR (Address Space
|
Disable kernel and module base offset ASLR (Address
|
||||||
Layout Randomization) if built into the kernel.
|
Space Layout Randomization) if built into the kernel.
|
||||||
|
|
||||||
noautogroup Disable scheduler automatic task group creation.
|
noautogroup Disable scheduler automatic task group creation.
|
||||||
|
|
||||||
|
@ -28,6 +28,7 @@
|
|||||||
#include <linux/mm.h>
|
#include <linux/mm.h>
|
||||||
#include <linux/gfp.h>
|
#include <linux/gfp.h>
|
||||||
#include <linux/jump_label.h>
|
#include <linux/jump_label.h>
|
||||||
|
#include <linux/random.h>
|
||||||
|
|
||||||
#include <asm/page.h>
|
#include <asm/page.h>
|
||||||
#include <asm/pgtable.h>
|
#include <asm/pgtable.h>
|
||||||
@ -43,13 +44,49 @@ do { \
|
|||||||
} while (0)
|
} while (0)
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
#ifdef CONFIG_RANDOMIZE_BASE
|
||||||
|
static unsigned long module_load_offset;
|
||||||
|
static int randomize_modules = 1;
|
||||||
|
|
||||||
|
static int __init parse_nokaslr(char *p)
|
||||||
|
{
|
||||||
|
randomize_modules = 0;
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
early_param("nokaslr", parse_nokaslr);
|
||||||
|
|
||||||
|
static unsigned long int get_module_load_offset(void)
|
||||||
|
{
|
||||||
|
if (randomize_modules) {
|
||||||
|
mutex_lock(&module_mutex);
|
||||||
|
/*
|
||||||
|
* Calculate the module_load_offset the first time this
|
||||||
|
* code is called. Once calculated it stays the same until
|
||||||
|
* reboot.
|
||||||
|
*/
|
||||||
|
if (module_load_offset == 0)
|
||||||
|
module_load_offset =
|
||||||
|
(get_random_int() % 1024 + 1) * PAGE_SIZE;
|
||||||
|
mutex_unlock(&module_mutex);
|
||||||
|
}
|
||||||
|
return module_load_offset;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
static unsigned long int get_module_load_offset(void)
|
||||||
|
{
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
#endif
|
||||||
|
|
||||||
void *module_alloc(unsigned long size)
|
void *module_alloc(unsigned long size)
|
||||||
{
|
{
|
||||||
if (PAGE_ALIGN(size) > MODULES_LEN)
|
if (PAGE_ALIGN(size) > MODULES_LEN)
|
||||||
return NULL;
|
return NULL;
|
||||||
return __vmalloc_node_range(size, 1, MODULES_VADDR, MODULES_END,
|
return __vmalloc_node_range(size, 1,
|
||||||
GFP_KERNEL | __GFP_HIGHMEM, PAGE_KERNEL_EXEC,
|
MODULES_VADDR + get_module_load_offset(),
|
||||||
NUMA_NO_NODE, __builtin_return_address(0));
|
MODULES_END, GFP_KERNEL | __GFP_HIGHMEM,
|
||||||
|
PAGE_KERNEL_EXEC, NUMA_NO_NODE,
|
||||||
|
__builtin_return_address(0));
|
||||||
}
|
}
|
||||||
|
|
||||||
#ifdef CONFIG_X86_32
|
#ifdef CONFIG_X86_32
|
||||||
|
Loading…
Reference in New Issue
Block a user