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

From: Baoquan He
Date: Wed Mar 23 2016 - 04:59:19 EST

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>
Kees suggested changing the code comment related to minimum address
to make it more understandable.

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..bbd2d06 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;

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

+ /* Lower minimum to 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 {