aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorKees Cook <keescook@chromium.org>2016-05-09 16:22:07 -0400
committerIngo Molnar <mingo@kernel.org>2016-05-10 04:12:04 -0400
commit06486d6c97cebc2433a40a979f3849cd68184de9 (patch)
treeb2b09df50f5b0c5dc88f046fcba7bc5c4d747203
parentc401cf1524153f9c2ede7ab8ece403513925770a (diff)
x86/KASLR: Return earliest overlap when avoiding regions
In preparation for being able to detect where to split up contiguous memory regions that overlap with memory regions to avoid, we need to pass back what the earliest overlapping region was. This modifies the overlap checker to return that information. Based on a separate mem_min_overlap() implementation by Baoquan He. 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: Baoquan He <bhe@redhat.com> 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-5-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, 20 insertions, 9 deletions
diff --git a/arch/x86/boot/compressed/kaslr.c b/arch/x86/boot/compressed/kaslr.c
index 81edf992277a..e55ebcbfa290 100644
--- a/arch/x86/boot/compressed/kaslr.c
+++ b/arch/x86/boot/compressed/kaslr.c
@@ -279,15 +279,24 @@ static void mem_avoid_init(unsigned long input, unsigned long input_size,
279#endif 279#endif
280} 280}
281 281
282/* Does this memory vector overlap a known avoided area? */ 282/*
283static bool mem_avoid_overlap(struct mem_vector *img) 283 * Does this memory vector overlap a known avoided area? If so, record the
284 * overlap region with the lowest address.
285 */
286static bool mem_avoid_overlap(struct mem_vector *img,
287 struct mem_vector *overlap)
284{ 288{
285 int i; 289 int i;
286 struct setup_data *ptr; 290 struct setup_data *ptr;
291 unsigned long earliest = img->start + img->size;
292 bool is_overlapping = false;
287 293
288 for (i = 0; i < MEM_AVOID_MAX; i++) { 294 for (i = 0; i < MEM_AVOID_MAX; i++) {
289 if (mem_overlaps(img, &mem_avoid[i])) 295 if (mem_overlaps(img, &mem_avoid[i]) &&
290 return true; 296 mem_avoid[i].start < earliest) {
297 *overlap = mem_avoid[i];
298 is_overlapping = true;
299 }
291 } 300 }
292 301
293 /* Avoid all entries in the setup_data linked list. */ 302 /* Avoid all entries in the setup_data linked list. */
@@ -298,13 +307,15 @@ static bool mem_avoid_overlap(struct mem_vector *img)
298 avoid.start = (unsigned long)ptr; 307 avoid.start = (unsigned long)ptr;
299 avoid.size = sizeof(*ptr) + ptr->len; 308 avoid.size = sizeof(*ptr) + ptr->len;
300 309
301 if (mem_overlaps(img, &avoid)) 310 if (mem_overlaps(img, &avoid) && (avoid.start < earliest)) {
302 return true; 311 *overlap = avoid;
312 is_overlapping = true;
313 }
303 314
304 ptr = (struct setup_data *)(unsigned long)ptr->next; 315 ptr = (struct setup_data *)(unsigned long)ptr->next;
305 } 316 }
306 317
307 return false; 318 return is_overlapping;
308} 319}
309 320
310static unsigned long slots[KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN]; 321static unsigned long slots[KERNEL_IMAGE_SIZE / CONFIG_PHYSICAL_ALIGN];
@@ -361,7 +372,7 @@ static void process_e820_entry(struct e820entry *entry,
361 unsigned long minimum, 372 unsigned long minimum,
362 unsigned long image_size) 373 unsigned long image_size)
363{ 374{
364 struct mem_vector region, img; 375 struct mem_vector region, img, overlap;
365 376
366 /* Skip non-RAM entries. */ 377 /* Skip non-RAM entries. */
367 if (entry->type != E820_RAM) 378 if (entry->type != E820_RAM)
@@ -400,7 +411,7 @@ static void process_e820_entry(struct e820entry *entry,
400 for (img.start = region.start, img.size = image_size ; 411 for (img.start = region.start, img.size = image_size ;
401 mem_contains(&region, &img) ; 412 mem_contains(&region, &img) ;
402 img.start += CONFIG_PHYSICAL_ALIGN) { 413 img.start += CONFIG_PHYSICAL_ALIGN) {
403 if (mem_avoid_overlap(&img)) 414 if (mem_avoid_overlap(&img, &overlap))
404 continue; 415 continue;
405 slots_append(img.start); 416 slots_append(img.start);
406 } 417 }