[PATCH v4 19/20] x86, kaslr: Allow random address to be below loaded address

From: Baoquan He
Date: Tue Mar 22 2016 - 03:35:31 EST


From: Yinghai Lu <yinghai@xxxxxxxxxx>

Now new randomized output can only be chosen from regions above loaded
address. In this case, for bootloaders like kexec which always loads
kernel near the end of ram, it doesn't do randomization at all. Or kernel
is loaded in a very big starting address, we should not give up that area
is loaded in a very large address, then the area below the large loaded
address will be given up. This is not reasonable.

With correct tracking in mem_avoid we can allow random output below
loaded address. With this change, though kexec can get random ouput
below its loaded address of kernel.

Now we just pick 512M as min_addr. If kernel loaded address is bigger than
512M, E.g 8G. Then [512M, 8G) can be added into random output candidate area.

Signed-off-by: Yinghai Lu <yinghai@xxxxxxxxxx>
---
arch/x86/boot/compressed/aslr.c | 10 ++++++++--
1 file changed, 8 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index ddfc3d0..d072ca7 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -446,7 +446,8 @@ void choose_kernel_location(unsigned char *input,
unsigned long output_size,
unsigned char **virt_offset)
{
- unsigned long random;
+ unsigned long random, min_addr;
+
*virt_offset = (unsigned char *)LOAD_PHYSICAL_ADDR;

#ifdef CONFIG_HIBERNATION
@@ -467,8 +468,13 @@ void choose_kernel_location(unsigned char *input,
mem_avoid_init((unsigned long)input, input_size,
(unsigned long)*output);

+ /* start from 512M */
+ min_addr = (unsigned long)*output;
+ if (min_addr > (512UL<<20))
+ min_addr = 512UL<<20;
+
/* Walk e820 and find a random address. */
- random = find_random_phy_addr((unsigned long)*output, output_size);
+ random = find_random_phy_addr(min_addr, output_size);
if (!random)
debug_putstr("KASLR could not find suitable E820 region...\n");
else {
--
2.5.0