aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorBaoquan He <bhe@redhat.com>2016-05-09 16:22:06 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-10 04:12:04 -0400
commitc401cf1524153f9c2ede7ab8ece403513925770a (patch)
treed90fd6e73a738112f0c071eb8e4963dbca8b9c11
parentcb18ef0da259db611fbf52806592fde5f469ae67 (diff)
x86/KASLR: Add 'struct slot_area' to manage random_addr slots
In order to support KASLR moving the kernel anywhere in physical memory (which could be up to 64TB), we need to handle counting the potential randomization locations in a more efficient manner. In the worst case with 64TB, there could be roughly 32 * 1024 * 1024 randomization slots if CONFIG_PHYSICAL_ALIGN is 0x1000000. Currently the starting address of candidate positions is stored into the slots[] array, one at a time. This method would cost too much memory and it's also very inefficient to get and save the slot information into the slot array one by one. This patch introduces 'struct slot_area' to manage each contiguous region of randomization slots. Each slot_area will contain the starting address and how many available slots are in this area. As with the original code, the slot_areas[] will avoid the mem_avoid[] regions. Since setup_data is a linked list, it could contain an unknown number of memory regions to be avoided, which could cause us to fragment the contiguous memory that the slot_area array is tracking. In normal operation this level of fragmentation will be extremely rare, but we choose a suitably large value (100) for the array. If setup_data forces the slot_area array to become highly fragmented and there are more slots available beyond the first 100 found, the rest will be ignored for KASLR selection. The function store_slot_info() is used to calculate the number of slots available in the passed-in memory region and stores it into slot_areas[] after adjusting for alignment and size requirements. Signed-off-by: Baoquan He <bhe@redhat.com> [ Rewrote changelog, squashed with new functions. ] Signed-off-by: Kees Cook <keescook@chromium.org> Cc: Andrew Morton <akpm@linux-foundation.org> Cc: Andy Lutomirski <luto@amacapital.net> Cc: Andy Lutomirski <luto@kernel.org> Cc: Borislav Petkov <bp@alien8.de> Cc: Borislav Petkov <bp@suse.de> Cc: Brian Gerst <brgerst@gmail.com> Cc: Dave Young <dyoung@redhat.com> Cc: Denys Vlasenko <dvlasenk@redhat.com> Cc: H. Peter Anvin <hpa@zytor.com> Cc: Linus Torvalds <torvalds@linux-foundation.org> Cc: Peter Zijlstra <peterz@infradead.org> Cc: Thomas Gleixner <tglx@linutronix.de> Cc: Vivek Goyal <vgoyal@redhat.com> Cc: Yinghai Lu <yinghai@kernel.org> Cc: kernel-hardening@lists.openwall.com Cc: lasse.collin@tukaani.org Link: http://lkml.kernel.org/r/1462825332-10505-4-git-send-email-keescook@chromium.org Signed-off-by: Ingo Molnar <mingo@kernel.org>
-rw-r--r--arch/x86/boot/compressed/kaslr.c29
1 files changed, 29 insertions, 0 deletions
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index f15d7b8d1b16..81edf992277a 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -308,8 +308,37 @@ static bool mem_avoid_overlap(struct mem_vector *img)
308} 308}
309 309
310static unsigned long slots[KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN]; 310static unsigned long slots[KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN];
311
312struct slot_area {
313 unsigned long addr;
314 int num;
315};
316
317#define MAX_SLOT_AREA 100
318
319static struct slot_area slot_areas[MAX_SLOT_AREA];
320
311static unsigned long slot_max; 321static unsigned long slot_max;
312 322
323static unsigned long slot_area_index;
324
325static void store_slot_info(struct mem_vector *region, unsigned long image_size)
326{
327 struct slot_area slot_area;
328
329 if (slot_area_index == MAX_SLOT_AREA)
330 return;
331
332 slot_area.addr = region->start;
333 slot_area.num = (region->size - image_size) /
334 CONFIG_PHYSICAL_ALIGN + 1;
335
336 if (slot_area.num > 0) {
337 slot_areas[slot_area_index++] = slot_area;
338 slot_max += slot_area.num;
339 }
340}
341
313static void slots_append(unsigned long addr) 342static void slots_append(unsigned long addr)
314{ 343{
315 /* Overflowing the slots list should be impossible. */ 344 /* Overflowing the slots list should be impossible. */