Commit 11fdf97a authored by Kees Cook's avatar Kees Cook Committed by Ingo Molnar

x86/KASLR: Clarify identity map interface

This extracts the call to prepare_level4() into a top-level function
that the user of the pagetable.c interface must call to initialize
the new page tables. For clarity and to match the "finalize" function,
it has been renamed to initialize_identity_maps(). This function also
gains the initialization of mapping_info so we don't have to do it each
time in add_identity_map().

Additionally add copyright notice to the top, to make it clear that the
bulk of the pagetable.c code was written by Yinghai, and that I just
added bugs later. :)
Signed-off-by: default avatarKees Cook <keescook@chromium.org>
Cc: Andrew Morton <akpm@linux-foundation.org>
Cc: Andrey Ryabinin <aryabinin@virtuozzo.com>
Cc: Andy Lutomirski <luto@kernel.org>
Cc: Baoquan He <bhe@redhat.com>
Cc: Borislav Petkov <bp@alien8.de>
Cc: Brian Gerst <brgerst@gmail.com>
Cc: Denys Vlasenko <dvlasenk@redhat.com>
Cc: Dmitry Vyukov <dvyukov@google.com>
Cc: H. Peter Anvin <hpa@zytor.com>
Cc: H.J. Lu <hjl.tools@gmail.com>
Cc: Josh Poimboeuf <jpoimboe@redhat.com>
Cc: Linus Torvalds <torvalds@linux-foundation.org>
Cc: Peter Zijlstra <peterz@infradead.org>
Cc: Thomas Gleixner <tglx@linutronix.de>
Cc: Yinghai Lu <yinghai@kernel.org>
Link: http://lkml.kernel.org/r/1464216334-17200-3-git-send-email-keescook@chromium.orgSigned-off-by: default avatarIngo Molnar <mingo@kernel.org>
parent 98f78525
...@@ -478,6 +478,9 @@ unsigned char *choose_random_location(unsigned long input, ...@@ -478,6 +478,9 @@ unsigned char *choose_random_location(unsigned long input,
boot_params->hdr.loadflags |= KASLR_FLAG; boot_params->hdr.loadflags |= KASLR_FLAG;
/* Prepare to add new identity pagetables on demand. */
initialize_identity_maps();
/* Record the various known unsafe memory ranges. */ /* Record the various known unsafe memory ranges. */
mem_avoid_init(input, input_size, output); mem_avoid_init(input, input_size, output);
......
...@@ -85,10 +85,13 @@ unsigned char *choose_random_location(unsigned long input_ptr, ...@@ -85,10 +85,13 @@ unsigned char *choose_random_location(unsigned long input_ptr,
#endif #endif
#ifdef CONFIG_X86_64 #ifdef CONFIG_X86_64
void initialize_identity_maps(void);
void add_identity_map(unsigned long start, unsigned long size); void add_identity_map(unsigned long start, unsigned long size);
void finalize_identity_maps(void); void finalize_identity_maps(void);
extern unsigned char _pgtable[]; extern unsigned char _pgtable[];
#else #else
static inline void initialize_identity_maps(void)
{ }
static inline void add_identity_map(unsigned long start, unsigned long size) static inline void add_identity_map(unsigned long start, unsigned long size)
{ } { }
static inline void finalize_identity_maps(void) static inline void finalize_identity_maps(void)
......
...@@ -2,6 +2,9 @@ ...@@ -2,6 +2,9 @@
* This code is used on x86_64 to create page table identity mappings on * This code is used on x86_64 to create page table identity mappings on
* demand by building up a new set of page tables (or appending to the * demand by building up a new set of page tables (or appending to the
* existing ones), and then switching over to them when ready. * existing ones), and then switching over to them when ready.
*
* Copyright (C) 2015-2016 Yinghai Lu
* Copyright (C) 2016 Kees Cook
*/ */
/* /*
...@@ -59,9 +62,21 @@ static struct alloc_pgt_data pgt_data; ...@@ -59,9 +62,21 @@ static struct alloc_pgt_data pgt_data;
/* The top level page table entry pointer. */ /* The top level page table entry pointer. */
static unsigned long level4p; static unsigned long level4p;
/*
* Mapping information structure passed to kernel_ident_mapping_init().
* Due to relocation, pointers must be assigned at run time not build time.
*/
static struct x86_mapping_info mapping_info = {
.pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
};
/* Locates and clears a region for a new top level page table. */ /* Locates and clears a region for a new top level page table. */
static void prepare_level4(void) void initialize_identity_maps(void)
{ {
/* Init mapping_info with run-time function/buffer pointers. */
mapping_info.alloc_pgt_page = alloc_pgt_page;
mapping_info.context = &pgt_data;
/* /*
* It should be impossible for this not to already be true, * It should be impossible for this not to already be true,
* but since calling this a second time would rewind the other * but since calling this a second time would rewind the other
...@@ -96,17 +111,8 @@ static void prepare_level4(void) ...@@ -96,17 +111,8 @@ static void prepare_level4(void)
*/ */
void add_identity_map(unsigned long start, unsigned long size) void add_identity_map(unsigned long start, unsigned long size)
{ {
struct x86_mapping_info mapping_info = {
.alloc_pgt_page = alloc_pgt_page,
.context = &pgt_data,
.pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
};
unsigned long end = start + size; unsigned long end = start + size;
/* Make sure we have a top level page table ready to use. */
if (!level4p)
prepare_level4();
/* Align boundary to 2M. */ /* Align boundary to 2M. */
start = round_down(start, PMD_SIZE); start = round_down(start, PMD_SIZE);
end = round_up(end, PMD_SIZE); end = round_up(end, PMD_SIZE);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment