LKML Archive on lore.kernel.org
help / color / mirror / Atom feed
* [PATCH v2 0/9] randomize kernel physical address and virtual address separately
@ 2015-03-02 14:58 Baoquan He
  2015-03-02 14:58 ` [PATCH v2 1/9] remove a unused function parameter Baoquan He
                   ` (9 more replies)
  0 siblings, 10 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

Currently kaslr only randomize physical address of kernel loading, then add the delta
to virtual address of kernel text mapping. Because kernel virtual address can only be
from __START_KERNEL_map to LOAD_PHYSICAL_ADDR+CONFIG_RANDOMIZE_BASE_MAX_OFFSET, namely
[0xffffffff80000000, 0xffffffffc0000000], so physical address can only be randomized
in region [LOAD_PHYSICAL_ADDR, CONFIG_RANDOMIZE_BASE_MAX_OFFSET], namely [16M, 1G].

So hpa and Vivek suggested the randomization should be done separately for both physical
and virtual address. In this patchset the behavior is changed. Randomize both the physical
address where kernel is decompressed and the virtual address where kernel text is mapped.
And physical address can be randomized from where vmlinux was linked to load to maximum
physical memory, possibly near 64T. While virtual address can get a random offset from load
address to CONFIG_RANDOMIZE_BASE_MAX_OFFSET, then added to __START_KERNEL_map. And
relocation handling only depends on virtual address randomization. Means if and only if
virtual address is randomized to a different value, we add the delta to the offset of
kernel relocs.

v1->v2:
    Thanks to Yinghai's patch which make kernel be able to load above 4G in boot stage,
    physical address can be randomized to anywhere, even near 64T.


    Thank Andy Lutomirski for his adding idt patch, finally it's not used in this patchset
    since I didn't make the #PF handler work well. I believe it does work, but I didn't
    make it. Will check why later. Thanks anyway.

Baoquan He (8):
  remove a unused function parameter
  a bug that relocation can not be handled when kernel is loaded above
    2G
  introduce struct slot_area to manage randomization slot info
  add mem_min_overlap to find the first avoid region within a memory
    region
  change process_e820_entry to store slot info into slot_area
  get the random phy addr according to slot_area info
  introduce fetch_random_virt_offset to randomize the kernel text
    mapping address
  change the relocations behavior for kaslr on x86_64

Yinghai Lu (1):
  make kernel be able to load above 4G in boot stage

 arch/x86/boot/compressed/aslr.c     | 194 +++++++++++++++++++++++++++---------
 arch/x86/boot/compressed/misc.c     |  46 ++++++---
 arch/x86/boot/compressed/misc.h     |  22 ++--
 arch/x86/boot/compressed/misc_pgt.c |  61 ++++++++++++
 arch/x86/include/asm/page.h         |   5 +
 arch/x86/mm/ident_map.c             |  74 ++++++++++++++
 arch/x86/mm/init_64.c               |  74 +-------------
 7 files changed, 333 insertions(+), 143 deletions(-)
 create mode 100644 arch/x86/boot/compressed/misc_pgt.c
 create mode 100644 arch/x86/mm/ident_map.c

-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 1/9] remove a unused function parameter
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-03 18:32   ` Yinghai Lu
  2015-03-02 14:58 ` [PATCH v2 2/9] a bug that relocation can not be handled when kernel is loaded above 2G Baoquan He
                   ` (8 subsequent siblings)
  9 siblings, 1 reply; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

Make a clean up to simplify the later change.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/aslr.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 7083c16..6a22129 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -142,7 +142,7 @@ static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two)
 }
 
 static void mem_avoid_init(unsigned long input, unsigned long input_size,
-			   unsigned long output, unsigned long output_size)
+			   unsigned long output_size)
 {
 	u64 initrd_start, initrd_size;
 	u64 cmd_line, cmd_line_size;
@@ -349,7 +349,7 @@ unsigned char *choose_kernel_location(struct boot_params *params,
 
 	/* Record the various known unsafe memory ranges. */
 	mem_avoid_init((unsigned long)input, input_size,
-		       (unsigned long)output, output_size);
+		       output_size);
 
 	/* Walk e820 and find a random address. */
 	random = find_random_addr(choice, output_size);
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 2/9] a bug that relocation can not be handled when kernel is loaded above 2G
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
  2015-03-02 14:58 ` [PATCH v2 1/9] remove a unused function parameter Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-02 14:58 ` [PATCH v2 3/9] make kernel be able to load above 4G in boot stage Baoquan He
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

When process 32 bit relocation tables a local variable extended is
defined to calculate the physical address of relocs entry. However
it's type is int which is enough for i386, for x86_64 not enough.
That's why relocation can only be handled when kernel is loaded
below 2G, otherwise a overflow will happen and cause system hang.

Here change it to long as 32 bit inverse relocation processing does,
and this change is safe for i386 relocation handling too.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/misc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index 5903089..ac5c05e 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -278,7 +278,7 @@ static void handle_relocations(void *output, unsigned long output_len)
 	 * So we work backwards from the end of the decompressed image.
 	 */
 	for (reloc = output + output_len - sizeof(*reloc); *reloc; reloc--) {
-		int extended = *reloc;
+		long extended = *reloc;
 		extended += map;
 
 		ptr = (unsigned long)extended;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 3/9] make kernel be able to load above 4G in boot stage
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
  2015-03-02 14:58 ` [PATCH v2 1/9] remove a unused function parameter Baoquan He
  2015-03-02 14:58 ` [PATCH v2 2/9] a bug that relocation can not be handled when kernel is loaded above 2G Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-02 15:58   ` Baoquan He
  2015-03-02 14:58 ` [PATCH v2 4/9] introduce struct slot_area to manage randomization slot info Baoquan He
                   ` (6 subsequent siblings)
  9 siblings, 1 reply; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo; +Cc: linux-kernel

From: Yinghai Lu <yinghai@kernel.org>

split kernel_ident_mapping_init() and call that in boot::decompress_kernel
stage. it will cover new range that is above 4G.

-v2: fix one typo, use round_up/round_down and use MACRO for size.

Signed-off-by: Yinghai Lu <yinghai@kernel.org>
---
 arch/x86/boot/compressed/misc.c     | 10 +++++
 arch/x86/boot/compressed/misc_pgt.c | 61 ++++++++++++++++++++++++++++++
 arch/x86/include/asm/page.h         |  5 +++
 arch/x86/mm/ident_map.c             | 74 +++++++++++++++++++++++++++++++++++++
 arch/x86/mm/init_64.c               | 74 +------------------------------------
 5 files changed, 151 insertions(+), 73 deletions(-)
 create mode 100644 arch/x86/boot/compressed/misc_pgt.c
 create mode 100644 arch/x86/mm/ident_map.c

diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index ac5c05e..c9d8187 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -9,6 +9,11 @@
  * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
  */
 
+#ifdef CONFIG_X86_64
+#define __pa(x)  ((unsigned long)(x))
+#define __va(x)  ((void *)((unsigned long)(x)))
+#endif
+
 #include "misc.h"
 #include "../string.h"
 
@@ -366,6 +371,8 @@ static void parse_elf(void *output)
 	free(phdrs);
 }
 
+#include "misc_pgt.c"
+
 asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
 				  unsigned char *input_data,
 				  unsigned long input_len,
@@ -421,6 +428,9 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
 		error("Wrong destination address");
 #endif
 
+	if (output != output_orig)
+		fill_linux64_pagetable((unsigned long)output, output_len);
+
 	debug_putstr("\nDecompressing Linux... ");
 	decompress(input_data, input_len, NULL, NULL, output, NULL, error);
 	parse_elf(output);
diff --git a/arch/x86/boot/compressed/misc_pgt.c b/arch/x86/boot/compressed/misc_pgt.c
new file mode 100644
index 0000000..2783f0f
--- /dev/null
+++ b/arch/x86/boot/compressed/misc_pgt.c
@@ -0,0 +1,61 @@
+
+#ifdef CONFIG_X86_64
+#include <asm/init.h>
+#include <asm/pgtable.h>
+
+#include "../../mm/ident_map.c"
+
+struct alloc_pgt_data {
+	unsigned char *pgt_buf;
+	unsigned long pgt_buf_size;
+	unsigned long pgt_buf_offset;
+};
+
+static void *alloc_pgt_page(void *context)
+{
+	struct alloc_pgt_data *d = (struct alloc_pgt_data *)context;
+	unsigned char *p = (unsigned char *)d->pgt_buf;
+
+	if (d->pgt_buf_offset >= d->pgt_buf_size) {
+		debug_putstr("out of pgt_buf in misc.c\n");
+		return NULL;
+	}
+
+	p += d->pgt_buf_offset;
+	d->pgt_buf_offset += PAGE_SIZE;
+
+	return p;
+}
+
+/* 4 pages to cover cross 512G boundary */
+#define PGT_BUF_SIZE (PAGE_SIZE*4)
+
+unsigned long __force_order;
+static unsigned char pgt_buf[PGT_BUF_SIZE] __aligned(PAGE_SIZE);
+
+static void fill_linux64_pagetable(unsigned long start, unsigned long size)
+{
+	struct alloc_pgt_data data = {
+		.pgt_buf = (unsigned char *) pgt_buf,
+		.pgt_buf_size = sizeof(pgt_buf),
+		.pgt_buf_offset = 0,
+	};
+	struct x86_mapping_info mapping_info = {
+		.alloc_pgt_page = alloc_pgt_page,
+		.context = &data,
+		.pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
+	};
+	unsigned long end = start + size;
+	pgd_t *level4p = (pgd_t *)read_cr3();
+
+	/* align boundary to 2M */
+	start = round_down(start, PMD_SIZE);
+	end = round_up(end, PMD_SIZE);
+	if (start >= (1UL<<32))
+		kernel_ident_mapping_init(&mapping_info, level4p, start, end);
+}
+#else
+static void fill_linux64_pagetable(unsigned long start, unsigned long size)
+{
+}
+#endif
diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
index 802dde3..cf8f619 100644
--- a/arch/x86/include/asm/page.h
+++ b/arch/x86/include/asm/page.h
@@ -37,7 +37,10 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
 	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
 #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
 
+#ifndef __pa
 #define __pa(x)		__phys_addr((unsigned long)(x))
+#endif
+
 #define __pa_nodebug(x)	__phys_addr_nodebug((unsigned long)(x))
 /* __pa_symbol should be used for C visible symbols.
    This seems to be the official gcc blessed way to do such arithmetic. */
@@ -51,7 +54,9 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
 #define __pa_symbol(x) \
 	__phys_addr_symbol(__phys_reloc_hide((unsigned long)(x)))
 
+#ifndef __va
 #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
+#endif
 
 #define __boot_va(x)		__va(x)
 #define __boot_pa(x)		__pa(x)
diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
new file mode 100644
index 0000000..751ca92
--- /dev/null
+++ b/arch/x86/mm/ident_map.c
@@ -0,0 +1,74 @@
+
+static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
+			   unsigned long addr, unsigned long end)
+{
+	addr &= PMD_MASK;
+	for (; addr < end; addr += PMD_SIZE) {
+		pmd_t *pmd = pmd_page + pmd_index(addr);
+
+		if (!pmd_present(*pmd))
+			set_pmd(pmd, __pmd(addr | pmd_flag));
+	}
+}
+static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
+			  unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+
+	for (; addr < end; addr = next) {
+		pud_t *pud = pud_page + pud_index(addr);
+		pmd_t *pmd;
+
+		next = (addr & PUD_MASK) + PUD_SIZE;
+		if (next > end)
+			next = end;
+
+		if (pud_present(*pud)) {
+			pmd = pmd_offset(pud, 0);
+			ident_pmd_init(info->pmd_flag, pmd, addr, next);
+			continue;
+		}
+		pmd = (pmd_t *)info->alloc_pgt_page(info->context);
+		if (!pmd)
+			return -ENOMEM;
+		ident_pmd_init(info->pmd_flag, pmd, addr, next);
+		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
+	}
+
+	return 0;
+}
+
+int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
+			      unsigned long addr, unsigned long end)
+{
+	unsigned long next;
+	int result;
+	int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
+
+	for (; addr < end; addr = next) {
+		pgd_t *pgd = pgd_page + pgd_index(addr) + off;
+		pud_t *pud;
+
+		next = (addr & PGDIR_MASK) + PGDIR_SIZE;
+		if (next > end)
+			next = end;
+
+		if (pgd_present(*pgd)) {
+			pud = pud_offset(pgd, 0);
+			result = ident_pud_init(info, pud, addr, next);
+			if (result)
+				return result;
+			continue;
+		}
+
+		pud = (pud_t *)info->alloc_pgt_page(info->context);
+		if (!pud)
+			return -ENOMEM;
+		result = ident_pud_init(info, pud, addr, next);
+		if (result)
+			return result;
+		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
+	}
+
+	return 0;
+}
diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
index 30eb05a..c30efb6 100644
--- a/arch/x86/mm/init_64.c
+++ b/arch/x86/mm/init_64.c
@@ -56,79 +56,7 @@
 
 #include "mm_internal.h"
 
-static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
-			   unsigned long addr, unsigned long end)
-{
-	addr &= PMD_MASK;
-	for (; addr < end; addr += PMD_SIZE) {
-		pmd_t *pmd = pmd_page + pmd_index(addr);
-
-		if (!pmd_present(*pmd))
-			set_pmd(pmd, __pmd(addr | pmd_flag));
-	}
-}
-static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
-			  unsigned long addr, unsigned long end)
-{
-	unsigned long next;
-
-	for (; addr < end; addr = next) {
-		pud_t *pud = pud_page + pud_index(addr);
-		pmd_t *pmd;
-
-		next = (addr & PUD_MASK) + PUD_SIZE;
-		if (next > end)
-			next = end;
-
-		if (pud_present(*pud)) {
-			pmd = pmd_offset(pud, 0);
-			ident_pmd_init(info->pmd_flag, pmd, addr, next);
-			continue;
-		}
-		pmd = (pmd_t *)info->alloc_pgt_page(info->context);
-		if (!pmd)
-			return -ENOMEM;
-		ident_pmd_init(info->pmd_flag, pmd, addr, next);
-		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
-	}
-
-	return 0;
-}
-
-int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
-			      unsigned long addr, unsigned long end)
-{
-	unsigned long next;
-	int result;
-	int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
-
-	for (; addr < end; addr = next) {
-		pgd_t *pgd = pgd_page + pgd_index(addr) + off;
-		pud_t *pud;
-
-		next = (addr & PGDIR_MASK) + PGDIR_SIZE;
-		if (next > end)
-			next = end;
-
-		if (pgd_present(*pgd)) {
-			pud = pud_offset(pgd, 0);
-			result = ident_pud_init(info, pud, addr, next);
-			if (result)
-				return result;
-			continue;
-		}
-
-		pud = (pud_t *)info->alloc_pgt_page(info->context);
-		if (!pud)
-			return -ENOMEM;
-		result = ident_pud_init(info, pud, addr, next);
-		if (result)
-			return result;
-		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
-	}
-
-	return 0;
-}
+#include "ident_map.c"
 
 static int __init parse_direct_gbpages_off(char *arg)
 {
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 4/9] introduce struct slot_area to manage randomization slot info
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
                   ` (2 preceding siblings ...)
  2015-03-02 14:58 ` [PATCH v2 3/9] make kernel be able to load above 4G in boot stage Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-02 14:58 ` [PATCH v2 5/9] add mem_min_overlap to find the first avoid region within a memory region Baoquan He
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

Kernel is expected to be randomly reloaded anywhere in the whole
physical memory area, it could be near 64T at most. In this case
there could be about 4*1024*1024 randomization slots. Hence the
old slot array will cost too much memory and can not be used any
more.

Here introduce struct slot_area to manage randomization slot info
in one contiguous memory area excluding the avoid area. slot_areas
is used to store all slot area info. Since setup_data is a linked
list, could contain many datas by pointer to point one by one,
excluding them will split RAM memory into many smaller areas, here
only take the first 100 slot areas if too many of them.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/aslr.c | 12 ++++++++++++
 1 file changed, 12 insertions(+)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 6a22129..26610a2 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -215,8 +215,20 @@ static bool mem_avoid_overlap(struct mem_vector *img)
 
 static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
 			   CONFIG_PHYSICAL_ALIGN];
+
+struct slot_area {
+	unsigned long addr;
+	int num;
+};
+
+#define MAX_SLOT_AREA 100
+
+static struct slot_area slot_areas[MAX_SLOT_AREA];
+
 static unsigned long slot_max;
 
+static unsigned long slot_area_index;
+
 static void slots_append(unsigned long addr)
 {
 	/* Overflowing the slots list should be impossible. */
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 5/9] add mem_min_overlap to find the first avoid region within a memory region
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
                   ` (3 preceding siblings ...)
  2015-03-02 14:58 ` [PATCH v2 4/9] introduce struct slot_area to manage randomization slot info Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-02 14:58 ` [PATCH v2 6/9] change process_e820_entry to store slot info into slot_area Baoquan He
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

Given a memory region mem_min_overlap will iterate all avoid region
to find the first one which overlap with it. This function will be
used later.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/aslr.c | 32 ++++++++++++++++++++++++++++++++
 1 file changed, 32 insertions(+)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 26610a2..ded3959 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -213,6 +213,38 @@ static bool mem_avoid_overlap(struct mem_vector *img)
 	return false;
 }
 
+static unsigned long mem_min_overlap(struct mem_vector *img, struct mem_vector *out)
+{
+	int i;
+	struct setup_data *ptr;
+	unsigned long min = img->start + img->size;
+
+	for (i = 0; i < MEM_AVOID_MAX; i++) {
+		if (mem_overlaps(img, &mem_avoid[i]) && (mem_avoid[i].start < min) ) {
+			*out = mem_avoid[i];
+			min = mem_avoid[i].start;
+		}
+	}
+
+	/* Check all entries in the setup_data linked list. */
+	ptr = (struct setup_data *)(unsigned long)real_mode->hdr.setup_data;
+	while (ptr) {
+		struct mem_vector avoid;
+
+		avoid.start = (unsigned long)ptr;
+		avoid.size = sizeof(*ptr) + ptr->len;
+
+		if (mem_overlaps(img, &avoid) && (avoid.start < min) ) {
+			*out = avoid;
+			min = avoid.start;
+		}
+
+		ptr = (struct setup_data *)(unsigned long)ptr->next;
+	}
+
+	return min;
+}
+
 static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
 			   CONFIG_PHYSICAL_ALIGN];
 
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 6/9] change process_e820_entry to store slot info into slot_area
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
                   ` (4 preceding siblings ...)
  2015-03-02 14:58 ` [PATCH v2 5/9] add mem_min_overlap to find the first avoid region within a memory region Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-02 14:58 ` [PATCH v2 7/9] get the random phy addr according to slot_area info Baoquan He
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

For passed in e820 entry, check if it is overlapped with avoid area.
If no just calculate and store slot info into related slot_area.
Otherwise iterate all avoid areas to find the first one, namely with
lowest starting address among all overlapped avoid areas. Then split
it by exluding that avoid area and store slot info of the preceding
part, then process the left part just as a new e820 memory region.
Repeat this till the whole e820 memory region is processed.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/aslr.c | 71 ++++++++++++++++++++++++++++++-----------
 1 file changed, 52 insertions(+), 19 deletions(-)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index ded3959..1c6fb31 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -280,20 +280,18 @@ static unsigned long slots_fetch_random(void)
 	return slots[get_random_long() % slot_max];
 }
 
-static void process_e820_entry(struct e820entry *entry,
+static int process_e820_entry(struct e820entry *entry,
 			       unsigned long minimum,
 			       unsigned long image_size)
 {
-	struct mem_vector region, img;
+	struct mem_vector region, img, out;
+	struct slot_area slot_area;
+	unsigned long min, start_orig;
 
 	/* Skip non-RAM entries. */
 	if (entry->type != E820_RAM)
 		return;
 
-	/* Ignore entries entirely above our maximum. */
-	if (entry->addr >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
-		return;
-
 	/* Ignore entries entirely below our minimum. */
 	if (entry->addr + entry->size < minimum)
 		return;
@@ -305,6 +303,14 @@ static void process_e820_entry(struct e820entry *entry,
 	if (region.start < minimum)
 		region.start = minimum;
 
+repeat:
+
+	/* Return if slot area array is full */
+	if ( slot_area_index == MAX_SLOT_AREA )
+		return;
+
+	start_orig = region.start;
+
 	/* Potentially raise address to meet alignment requirements. */
 	region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
 
@@ -313,20 +319,47 @@ static void process_e820_entry(struct e820entry *entry,
 		return;
 
 	/* Reduce size by any delta from the original address. */
-	region.size -= region.start - entry->addr;
-
-	/* Reduce maximum size to fit end of image within maximum limit. */
-	if (region.start + region.size > CONFIG_RANDOMIZE_BASE_MAX_OFFSET)
-		region.size = CONFIG_RANDOMIZE_BASE_MAX_OFFSET - region.start;
-
-	/* Walk each aligned slot and check for avoided areas. */
-	for (img.start = region.start, img.size = image_size ;
-	     mem_contains(&region, &img) ;
-	     img.start += CONFIG_PHYSICAL_ALIGN) {
-		if (mem_avoid_overlap(&img))
-			continue;
-		slots_append(img.start);
+	region.size -= region.start - start_orig;
+
+	if ( region.size < image_size )
+		return;
+
+	if (!mem_avoid_overlap(&region)) {
+		slot_area.addr = region.start;
+		if ( image_size <= CONFIG_PHYSICAL_ALIGN)
+			slot_area.num = region.size / CONFIG_PHYSICAL_ALIGN;
+		else
+			slot_area.num = ( region.size - image_size ) /
+				CONFIG_PHYSICAL_ALIGN + 1;
+
+		if (slot_area.num > 0) {
+			slot_areas[slot_area_index++] = slot_area;
+			slot_max += slot_area.num;
+		}
+		return;
 	}
+
+	min = mem_min_overlap(&region, &out);
+
+	if ( min > region.start + image_size ) {
+		unsigned long size = min - region.start;
+
+		slot_area.addr = region.start;
+		if ( image_size <= CONFIG_PHYSICAL_ALIGN)
+                        slot_area.num = (min - region.start ) / CONFIG_PHYSICAL_ALIGN;
+                else
+                        slot_area.num = ( min - region.start - image_size ) /
+                                CONFIG_PHYSICAL_ALIGN + 1;
+
+		if (slot_area.num > 0) {
+			slot_areas[slot_area_index++] = slot_area;
+			slot_max += slot_area.num;
+		}
+	}
+
+	region.size -= out.start - region.start + out.size;
+	region.start = out.start + out.size;
+	goto repeat;
 }
 
 static unsigned long find_random_addr(unsigned long minimum,
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
                   ` (5 preceding siblings ...)
  2015-03-02 14:58 ` [PATCH v2 6/9] change process_e820_entry to store slot info into slot_area Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-03  8:45   ` Yinghai Lu
  2015-03-04 21:28   ` Kees Cook
  2015-03-02 14:58 ` [PATCH v2 8/9] introduce fetch_random_virt_offset to randomize the kernel text mapping address Baoquan He
                   ` (2 subsequent siblings)
  9 siblings, 2 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

Now random value can be used to get related slot info stored in
slot_area, mainly use slot_area.num to position which slot is target.
With this slot its starting address is returned as the physical
address where kernel will put.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/aslr.c | 34 +++++++++++++++++++---------------
 1 file changed, 19 insertions(+), 15 deletions(-)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 1c6fb31..55adee2 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -245,9 +245,6 @@ static unsigned long mem_min_overlap(struct mem_vector *img, struct mem_vector *
 	return min;
 }
 
-static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
-			   CONFIG_PHYSICAL_ALIGN];
-
 struct slot_area {
 	unsigned long addr;
 	int num;
@@ -261,23 +258,28 @@ static unsigned long slot_max;
 
 static unsigned long slot_area_index;
 
-static void slots_append(unsigned long addr)
-{
-	/* Overflowing the slots list should be impossible. */
-	if (slot_max >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
-			CONFIG_PHYSICAL_ALIGN)
-		return;
-
-	slots[slot_max++] = addr;
-}
-
 static unsigned long slots_fetch_random(void)
 {
+	unsigned long random;
+	int i;
+
 	/* Handle case of no slots stored. */
 	if (slot_max == 0)
 		return 0;
 
-	return slots[get_random_long() % slot_max];
+	random = get_random_long() % slot_max;
+
+	for (i=0; i< slot_area_index; i++) {
+		if (random > slot_areas[i].num) {
+			random -= slot_areas[i].num;
+			continue;
+		}
+		return slot_areas[i].addr + random * CONFIG_PHYSICAL_ALIGN;
+	}
+
+	if (i == slot_area_index )
+		debug_putstr("something wrong happened in slots_fetch_random()...\n");
+	return 0;
 }
 
 static int process_e820_entry(struct e820entry *entry,
@@ -362,7 +364,7 @@ repeat:
 	goto repeat;
 }
 
-static unsigned long find_random_addr(unsigned long minimum,
+static unsigned long find_random_phy_addr(unsigned long minimum,
 				      unsigned long size)
 {
 	int i;
@@ -374,6 +376,8 @@ static unsigned long find_random_addr(unsigned long minimum,
 	/* Verify potential e820 positions, appending to slots list. */
 	for (i = 0; i < real_mode->e820_entries; i++) {
 		process_e820_entry(&real_mode->e820_map[i], minimum, size);
+		if ( slot_area_index == MAX_SLOT_AREA )
+			break;
 	}
 
 	return slots_fetch_random();
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 8/9] introduce fetch_random_virt_offset to randomize the kernel text mapping address
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
                   ` (6 preceding siblings ...)
  2015-03-02 14:58 ` [PATCH v2 7/9] get the random phy addr according to slot_area info Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-02 14:58 ` [PATCH v2 9/9] change the relocations behavior for kaslr on x86_64 Baoquan He
  2015-03-05 15:57 ` [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
  9 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

Kaslr extended kernel text mapping region size from 512M to 1G,
namely CONFIG_RANDOMIZE_BASE_MAX_OFFSET. This means kernel text
can be mapped to below region:

[__START_KERNEL_map + LOAD_PHYSICAL_ADDR, __START_KERNEL_map + 1G]

Introduce a function find_random_virt_offset() to get random value
between LOAD_PHYSICAL_ADDR and CONFIG_RANDOMIZE_BASE_MAX_OFFSET.
This random value will be added to __START_KERNEL_map to get the
starting address which kernel text is mapped from. Since slot can
be anywhere of this region, means it is a independent slot_area,
it is easy to get a slot w.r.t random value.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/aslr.c | 22 ++++++++++++++++++++++
 1 file changed, 22 insertions(+)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 55adee2..332a8c4 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -383,6 +383,28 @@ static unsigned long find_random_phy_addr(unsigned long minimum,
 	return slots_fetch_random();
 }
 
+static unsigned long find_random_virt_offset(unsigned long minimum,
+				  unsigned long image_size)
+{
+	unsigned long slot_num, random;
+	struct mem_vector region, img;
+
+	/* Make sure minimum is aligned. */
+	minimum = ALIGN(minimum, CONFIG_PHYSICAL_ALIGN);
+
+	if ( image_size <= CONFIG_PHYSICAL_ALIGN)
+		slot_num = ( CONFIG_RANDOMIZE_BASE_MAX_OFFSET - minimum ) /
+				CONFIG_PHYSICAL_ALIGN;
+	else
+		slot_num = ( CONFIG_RANDOMIZE_BASE_MAX_OFFSET - minimum - image_size ) /
+				CONFIG_PHYSICAL_ALIGN + 1;
+
+	random = get_random_long() % slot_num;
+
+	return random * CONFIG_PHYSICAL_ALIGN + minimum;
+}
+
+
 static void add_kaslr_setup_data(struct boot_params *params, __u8 enabled)
 {
 	struct setup_data *data;
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* [PATCH v2 9/9] change the relocations behavior for kaslr on x86_64
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
                   ` (7 preceding siblings ...)
  2015-03-02 14:58 ` [PATCH v2 8/9] introduce fetch_random_virt_offset to randomize the kernel text mapping address Baoquan He
@ 2015-03-02 14:58 ` Baoquan He
  2015-03-04 23:16   ` Yinghai Lu
  2015-03-05 15:57 ` [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
  9 siblings, 1 reply; 29+ messages in thread
From: Baoquan He @ 2015-03-02 14:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo
  Cc: linux-kernel, Baoquan He

On x86_64, in old kaslr implementaion only physical address of kernel
loading is randomized. Then calculate the delta of physical address
where vmlinux was linked to load and where it is finally loaded. If
delta is not equal to 0, namely there's a new physical address where
kernel is actually decompressed, relocation handling need be done. Then
delta is added to offset of kernel symbol relocation, this makes the
address of kernel text mapping move delta long.

Here the behavior is changed. Randomize both the physical address
where kernel is decompressed and the virtual address where kernel text
is mapped. And physical address can be randomized from where vmlinux
was linked to load to maximum physical memory, possibly near 64T. While
virtual address can get a random offset from load address to
CONFIG_RANDOMIZE_BASE_MAX_OFFSET, then added to __START_KERNEL_map.

And relocation handling only depends on virtual address randomization.
Means if and only if virtual address is randomized to a different value,
we add the delta to the offset of kernel relocs.

Signed-off-by: Baoquan He <bhe@redhat.com>
---
 arch/x86/boot/compressed/aslr.c | 29 ++++++++++++++---------------
 arch/x86/boot/compressed/misc.c | 34 +++++++++++++++++++++-------------
 arch/x86/boot/compressed/misc.h | 22 ++++++++++++----------
 3 files changed, 47 insertions(+), 38 deletions(-)

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 332a8c4..3114ae0 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -426,13 +426,13 @@ static void add_kaslr_setup_data(struct boot_params *params, __u8 enabled)
 
 }
 
-unsigned char *choose_kernel_location(struct boot_params *params,
-				      unsigned char *input,
-				      unsigned long input_size,
-				      unsigned char *output,
-				      unsigned long output_size)
+void choose_kernel_location(struct boot_params *params,
+				unsigned char *input,
+				unsigned long input_size,
+				unsigned char **output,
+				unsigned long output_size,
+				unsigned char **virt_offset)
 {
-	unsigned long choice = (unsigned long)output;
 	unsigned long random;
 
 #ifdef CONFIG_HIBERNATION
@@ -455,17 +455,16 @@ unsigned char *choose_kernel_location(struct boot_params *params,
 		       output_size);
 
 	/* Walk e820 and find a random address. */
-	random = find_random_addr(choice, output_size);
-	if (!random) {
+	random = find_random_phy_addr((unsigned long)*output, output_size);
+	if (!random)
 		debug_putstr("KASLR could not find suitable E820 region...\n");
-		goto out;
-	}
+	else
+		*output = (unsigned char*)random;
 
-	/* Always enforce the minimum. */
-	if (random < choice)
-		goto out;
+	random = find_random_virt_offset(LOAD_PHYSICAL_ADDR, output_size);
+	*virt_offset = (unsigned char*)random;
 
-	choice = random;
 out:
-	return (unsigned char *)choice;
+	if (!random)
+		*virt_offset = (unsigned char*)LOAD_PHYSICAL_ADDR;
 }
diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
index c9d8187..53bb2dc 100644
--- a/arch/x86/boot/compressed/misc.c
+++ b/arch/x86/boot/compressed/misc.c
@@ -236,7 +236,8 @@ static void error(char *x)
 }
 
 #if CONFIG_X86_NEED_RELOCS
-static void handle_relocations(void *output, unsigned long output_len)
+static void handle_relocations(void *output, unsigned long output_len,
+					void *virt_offset)
 {
 	int *reloc;
 	unsigned long delta, map, ptr;
@@ -248,11 +249,6 @@ static void handle_relocations(void *output, unsigned long output_len)
 	 * and where it was actually loaded.
 	 */
 	delta = min_addr - LOAD_PHYSICAL_ADDR;
-	if (!delta) {
-		debug_putstr("No relocation needed... ");
-		return;
-	}
-	debug_putstr("Performing relocations... ");
 
 	/*
 	 * The kernel contains a table of relocation addresses. Those
@@ -263,6 +259,16 @@ static void handle_relocations(void *output, unsigned long output_len)
 	 */
 	map = delta - __START_KERNEL_map;
 
+	/*  */
+	if (IS_ENABLED(CONFIG_X86_64))
+		delta = (unsigned long)virt_offset - LOAD_PHYSICAL_ADDR;
+
+	if (!delta) {
+		debug_putstr("No relocation needed... ");
+		return;
+	}
+	debug_putstr("Performing relocations... ");
+
 	/*
 	 * Process relocations: 32 bit relocations first then 64 bit after.
 	 * Three sets of binary relocations are added to the end of the kernel
@@ -316,7 +322,8 @@ static void handle_relocations(void *output, unsigned long output_len)
 #endif
 }
 #else
-static inline void handle_relocations(void *output, unsigned long output_len)
+static inline void handle_relocations(void *output, unsigned long output_len,
+					void *virt_offset)
 { }
 #endif
 
@@ -381,6 +388,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
 				  unsigned long run_size)
 {
 	unsigned char *output_orig = output;
+	unsigned char * virt_offset;
 
 	real_mode = rmode;
 
@@ -408,10 +416,11 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
 	 * the entire decompressed kernel plus relocation table, or the
 	 * entire decompressed kernel plus .bss and .brk sections.
 	 */
-	output = choose_kernel_location(real_mode, input_data, input_len,
-					output,
-					output_len > run_size ? output_len
-							      : run_size);
+	choose_kernel_location(real_mode, input_data, input_len,
+				&output,
+				output_len > run_size ? output_len
+				: run_size,
+				&virt_offset);
 
 	/* Validate memory location choices. */
 	if ((unsigned long)output & (MIN_KERNEL_ALIGN - 1))
@@ -438,8 +447,7 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
 	 * 32-bit always performs relocations. 64-bit relocations are only
 	 * needed if kASLR has chosen a different load address.
 	 */
-	if (!IS_ENABLED(CONFIG_X86_64) || output != output_orig)
-		handle_relocations(output, output_len);
+	handle_relocations(output, output_len, virt_offset);
 	debug_putstr("done.\nBooting the kernel.\n");
 	return output;
 }
diff --git a/arch/x86/boot/compressed/misc.h b/arch/x86/boot/compressed/misc.h
index b901a8b..9da6b89 100644
--- a/arch/x86/boot/compressed/misc.h
+++ b/arch/x86/boot/compressed/misc.h
@@ -59,20 +59,22 @@ int cmdline_find_option_bool(const char *option);
 
 #if CONFIG_RANDOMIZE_BASE
 /* aslr.c */
-unsigned char *choose_kernel_location(struct boot_params *params,
-				      unsigned char *input,
-				      unsigned long input_size,
-				      unsigned char *output,
-				      unsigned long output_size);
+void choose_kernel_location(struct boot_params *params,
+				unsigned char *input,
+				unsigned long input_size,
+				unsigned char **output,
+				unsigned long output_size,
+				unsigned char **virt_offset);
 /* cpuflags.c */
 bool has_cpuflag(int flag);
 #else
 static inline
-unsigned char *choose_kernel_location(struct boot_params *params,
-				      unsigned char *input,
-				      unsigned long input_size,
-				      unsigned char *output,
-				      unsigned long output_size)
+void choose_kernel_location(struct boot_params *params,
+				unsigned char *input,
+				unsigned long input_size,
+				unsigned char *output,
+				unsigned long output_size,
+				unsigned char **virt_offset)
 {
 	return output;
 }
-- 
1.9.3


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 3/9] make kernel be able to load above 4G in boot stage
  2015-03-02 14:58 ` [PATCH v2 3/9] make kernel be able to load above 4G in boot stage Baoquan He
@ 2015-03-02 15:58   ` Baoquan He
  0 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-02 15:58 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo; +Cc: linux-kernel

Oops, I didn't copy the subject of Yinghai's patch, it should be as
below. Will change it back when repost.

x86, boot: Enable ident_mapping for kasl above 4G on 64bit

On 03/02/15 at 10:58pm, Baoquan He wrote:
> From: Yinghai Lu <yinghai@kernel.org>
> 
> split kernel_ident_mapping_init() and call that in boot::decompress_kernel
> stage. it will cover new range that is above 4G.
> 
> -v2: fix one typo, use round_up/round_down and use MACRO for size.
> 
> Signed-off-by: Yinghai Lu <yinghai@kernel.org>
> ---
>  arch/x86/boot/compressed/misc.c     | 10 +++++
>  arch/x86/boot/compressed/misc_pgt.c | 61 ++++++++++++++++++++++++++++++
>  arch/x86/include/asm/page.h         |  5 +++
>  arch/x86/mm/ident_map.c             | 74 +++++++++++++++++++++++++++++++++++++
>  arch/x86/mm/init_64.c               | 74 +------------------------------------
>  5 files changed, 151 insertions(+), 73 deletions(-)
>  create mode 100644 arch/x86/boot/compressed/misc_pgt.c
>  create mode 100644 arch/x86/mm/ident_map.c
> 
> diff --git a/arch/x86/boot/compressed/misc.c b/arch/x86/boot/compressed/misc.c
> index ac5c05e..c9d8187 100644
> --- a/arch/x86/boot/compressed/misc.c
> +++ b/arch/x86/boot/compressed/misc.c
> @@ -9,6 +9,11 @@
>   * High loaded stuff by Hans Lermen & Werner Almesberger, Feb. 1996
>   */
>  
> +#ifdef CONFIG_X86_64
> +#define __pa(x)  ((unsigned long)(x))
> +#define __va(x)  ((void *)((unsigned long)(x)))
> +#endif
> +
>  #include "misc.h"
>  #include "../string.h"
>  
> @@ -366,6 +371,8 @@ static void parse_elf(void *output)
>  	free(phdrs);
>  }
>  
> +#include "misc_pgt.c"
> +
>  asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
>  				  unsigned char *input_data,
>  				  unsigned long input_len,
> @@ -421,6 +428,9 @@ asmlinkage __visible void *decompress_kernel(void *rmode, memptr heap,
>  		error("Wrong destination address");
>  #endif
>  
> +	if (output != output_orig)
> +		fill_linux64_pagetable((unsigned long)output, output_len);
> +
>  	debug_putstr("\nDecompressing Linux... ");
>  	decompress(input_data, input_len, NULL, NULL, output, NULL, error);
>  	parse_elf(output);
> diff --git a/arch/x86/boot/compressed/misc_pgt.c b/arch/x86/boot/compressed/misc_pgt.c
> new file mode 100644
> index 0000000..2783f0f
> --- /dev/null
> +++ b/arch/x86/boot/compressed/misc_pgt.c
> @@ -0,0 +1,61 @@
> +
> +#ifdef CONFIG_X86_64
> +#include <asm/init.h>
> +#include <asm/pgtable.h>
> +
> +#include "../../mm/ident_map.c"
> +
> +struct alloc_pgt_data {
> +	unsigned char *pgt_buf;
> +	unsigned long pgt_buf_size;
> +	unsigned long pgt_buf_offset;
> +};
> +
> +static void *alloc_pgt_page(void *context)
> +{
> +	struct alloc_pgt_data *d = (struct alloc_pgt_data *)context;
> +	unsigned char *p = (unsigned char *)d->pgt_buf;
> +
> +	if (d->pgt_buf_offset >= d->pgt_buf_size) {
> +		debug_putstr("out of pgt_buf in misc.c\n");
> +		return NULL;
> +	}
> +
> +	p += d->pgt_buf_offset;
> +	d->pgt_buf_offset += PAGE_SIZE;
> +
> +	return p;
> +}
> +
> +/* 4 pages to cover cross 512G boundary */
> +#define PGT_BUF_SIZE (PAGE_SIZE*4)
> +
> +unsigned long __force_order;
> +static unsigned char pgt_buf[PGT_BUF_SIZE] __aligned(PAGE_SIZE);
> +
> +static void fill_linux64_pagetable(unsigned long start, unsigned long size)
> +{
> +	struct alloc_pgt_data data = {
> +		.pgt_buf = (unsigned char *) pgt_buf,
> +		.pgt_buf_size = sizeof(pgt_buf),
> +		.pgt_buf_offset = 0,
> +	};
> +	struct x86_mapping_info mapping_info = {
> +		.alloc_pgt_page = alloc_pgt_page,
> +		.context = &data,
> +		.pmd_flag = __PAGE_KERNEL_LARGE_EXEC,
> +	};
> +	unsigned long end = start + size;
> +	pgd_t *level4p = (pgd_t *)read_cr3();
> +
> +	/* align boundary to 2M */
> +	start = round_down(start, PMD_SIZE);
> +	end = round_up(end, PMD_SIZE);
> +	if (start >= (1UL<<32))
> +		kernel_ident_mapping_init(&mapping_info, level4p, start, end);
> +}
> +#else
> +static void fill_linux64_pagetable(unsigned long start, unsigned long size)
> +{
> +}
> +#endif
> diff --git a/arch/x86/include/asm/page.h b/arch/x86/include/asm/page.h
> index 802dde3..cf8f619 100644
> --- a/arch/x86/include/asm/page.h
> +++ b/arch/x86/include/asm/page.h
> @@ -37,7 +37,10 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
>  	alloc_page_vma(GFP_HIGHUSER | __GFP_ZERO | movableflags, vma, vaddr)
>  #define __HAVE_ARCH_ALLOC_ZEROED_USER_HIGHPAGE
>  
> +#ifndef __pa
>  #define __pa(x)		__phys_addr((unsigned long)(x))
> +#endif
> +
>  #define __pa_nodebug(x)	__phys_addr_nodebug((unsigned long)(x))
>  /* __pa_symbol should be used for C visible symbols.
>     This seems to be the official gcc blessed way to do such arithmetic. */
> @@ -51,7 +54,9 @@ static inline void copy_user_page(void *to, void *from, unsigned long vaddr,
>  #define __pa_symbol(x) \
>  	__phys_addr_symbol(__phys_reloc_hide((unsigned long)(x)))
>  
> +#ifndef __va
>  #define __va(x)			((void *)((unsigned long)(x)+PAGE_OFFSET))
> +#endif
>  
>  #define __boot_va(x)		__va(x)
>  #define __boot_pa(x)		__pa(x)
> diff --git a/arch/x86/mm/ident_map.c b/arch/x86/mm/ident_map.c
> new file mode 100644
> index 0000000..751ca92
> --- /dev/null
> +++ b/arch/x86/mm/ident_map.c
> @@ -0,0 +1,74 @@
> +
> +static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
> +			   unsigned long addr, unsigned long end)
> +{
> +	addr &= PMD_MASK;
> +	for (; addr < end; addr += PMD_SIZE) {
> +		pmd_t *pmd = pmd_page + pmd_index(addr);
> +
> +		if (!pmd_present(*pmd))
> +			set_pmd(pmd, __pmd(addr | pmd_flag));
> +	}
> +}
> +static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
> +			  unsigned long addr, unsigned long end)
> +{
> +	unsigned long next;
> +
> +	for (; addr < end; addr = next) {
> +		pud_t *pud = pud_page + pud_index(addr);
> +		pmd_t *pmd;
> +
> +		next = (addr & PUD_MASK) + PUD_SIZE;
> +		if (next > end)
> +			next = end;
> +
> +		if (pud_present(*pud)) {
> +			pmd = pmd_offset(pud, 0);
> +			ident_pmd_init(info->pmd_flag, pmd, addr, next);
> +			continue;
> +		}
> +		pmd = (pmd_t *)info->alloc_pgt_page(info->context);
> +		if (!pmd)
> +			return -ENOMEM;
> +		ident_pmd_init(info->pmd_flag, pmd, addr, next);
> +		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
> +	}
> +
> +	return 0;
> +}
> +
> +int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
> +			      unsigned long addr, unsigned long end)
> +{
> +	unsigned long next;
> +	int result;
> +	int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
> +
> +	for (; addr < end; addr = next) {
> +		pgd_t *pgd = pgd_page + pgd_index(addr) + off;
> +		pud_t *pud;
> +
> +		next = (addr & PGDIR_MASK) + PGDIR_SIZE;
> +		if (next > end)
> +			next = end;
> +
> +		if (pgd_present(*pgd)) {
> +			pud = pud_offset(pgd, 0);
> +			result = ident_pud_init(info, pud, addr, next);
> +			if (result)
> +				return result;
> +			continue;
> +		}
> +
> +		pud = (pud_t *)info->alloc_pgt_page(info->context);
> +		if (!pud)
> +			return -ENOMEM;
> +		result = ident_pud_init(info, pud, addr, next);
> +		if (result)
> +			return result;
> +		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
> +	}
> +
> +	return 0;
> +}
> diff --git a/arch/x86/mm/init_64.c b/arch/x86/mm/init_64.c
> index 30eb05a..c30efb6 100644
> --- a/arch/x86/mm/init_64.c
> +++ b/arch/x86/mm/init_64.c
> @@ -56,79 +56,7 @@
>  
>  #include "mm_internal.h"
>  
> -static void ident_pmd_init(unsigned long pmd_flag, pmd_t *pmd_page,
> -			   unsigned long addr, unsigned long end)
> -{
> -	addr &= PMD_MASK;
> -	for (; addr < end; addr += PMD_SIZE) {
> -		pmd_t *pmd = pmd_page + pmd_index(addr);
> -
> -		if (!pmd_present(*pmd))
> -			set_pmd(pmd, __pmd(addr | pmd_flag));
> -	}
> -}
> -static int ident_pud_init(struct x86_mapping_info *info, pud_t *pud_page,
> -			  unsigned long addr, unsigned long end)
> -{
> -	unsigned long next;
> -
> -	for (; addr < end; addr = next) {
> -		pud_t *pud = pud_page + pud_index(addr);
> -		pmd_t *pmd;
> -
> -		next = (addr & PUD_MASK) + PUD_SIZE;
> -		if (next > end)
> -			next = end;
> -
> -		if (pud_present(*pud)) {
> -			pmd = pmd_offset(pud, 0);
> -			ident_pmd_init(info->pmd_flag, pmd, addr, next);
> -			continue;
> -		}
> -		pmd = (pmd_t *)info->alloc_pgt_page(info->context);
> -		if (!pmd)
> -			return -ENOMEM;
> -		ident_pmd_init(info->pmd_flag, pmd, addr, next);
> -		set_pud(pud, __pud(__pa(pmd) | _KERNPG_TABLE));
> -	}
> -
> -	return 0;
> -}
> -
> -int kernel_ident_mapping_init(struct x86_mapping_info *info, pgd_t *pgd_page,
> -			      unsigned long addr, unsigned long end)
> -{
> -	unsigned long next;
> -	int result;
> -	int off = info->kernel_mapping ? pgd_index(__PAGE_OFFSET) : 0;
> -
> -	for (; addr < end; addr = next) {
> -		pgd_t *pgd = pgd_page + pgd_index(addr) + off;
> -		pud_t *pud;
> -
> -		next = (addr & PGDIR_MASK) + PGDIR_SIZE;
> -		if (next > end)
> -			next = end;
> -
> -		if (pgd_present(*pgd)) {
> -			pud = pud_offset(pgd, 0);
> -			result = ident_pud_init(info, pud, addr, next);
> -			if (result)
> -				return result;
> -			continue;
> -		}
> -
> -		pud = (pud_t *)info->alloc_pgt_page(info->context);
> -		if (!pud)
> -			return -ENOMEM;
> -		result = ident_pud_init(info, pud, addr, next);
> -		if (result)
> -			return result;
> -		set_pgd(pgd, __pgd(__pa(pud) | _KERNPG_TABLE));
> -	}
> -
> -	return 0;
> -}
> +#include "ident_map.c"
>  
>  static int __init parse_direct_gbpages_off(char *arg)
>  {
> -- 
> 1.9.3
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-02 14:58 ` [PATCH v2 7/9] get the random phy addr according to slot_area info Baoquan He
@ 2015-03-03  8:45   ` Yinghai Lu
  2015-03-03 11:42     ` Baoquan He
  2015-03-04 15:39     ` Baoquan He
  2015-03-04 21:28   ` Kees Cook
  1 sibling, 2 replies; 29+ messages in thread
From: Yinghai Lu @ 2015-03-03  8:45 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:
> Now random value can be used to get related slot info stored in
> slot_area, mainly use slot_area.num to position which slot is target.
> With this slot its starting address is returned as the physical
> address where kernel will put.
>
> @@ -362,7 +364,7 @@ repeat:
>         goto repeat;
>  }
>
> -static unsigned long find_random_addr(unsigned long minimum,
> +static unsigned long find_random_phy_addr(unsigned long minimum,
>                                       unsigned long size)

You forgot to change calling name.

got:

arch/x86/boot/compressed/aslr.o: In function `choose_kernel_location':
aslr.c:(.text+0x163): undefined reference to `find_random_addr'
make[2]: *** [arch/x86/boot/compressed/vmlinux] Error 1
make[1]: *** [arch/x86/boot/compressed/vmlinux] Error 2

Please make the patch set bisect-able.

after fixing that, on the system with 4G ram: i got:

early console in decompress_kernel
KASLR using RDTSC...
decompress_kernel:
  input: [0x13f5ed3b4-0x13ff6a64b], output: 0x153000000, heap:
[0x13ff76000-0x13ff7dfff]

Decompressing Linux... xz...

XZ-compressed data is corrupt


without the patch, I have:

early console in decompress_kernel
KASLR could not find suitable E820 region...
decompress_kernel:
  input: [0x13f5ee3b4-0x13ff6b64b], output: 0x13cc00000, heap:
[0x13ff76000-0x13ff7dfff]

Decompressing Linux... xz... Parsing ELF... done.
...
[    0.016848] e820: BIOS-provided physical RAM map (sanitized by setup):
[    0.018854] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
[    0.020982] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
[    0.023166] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
[    0.025783] BIOS-e820: [mem 0x0000000000100000-0x00000000bffdffff] usable
[    0.027901] BIOS-e820: [mem 0x00000000bffe0000-0x00000000bfffffff] reserved
[    0.030079] BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff] reserved
[    0.032252] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
[    0.034437] BIOS-e820: [mem 0x0000000100000000-0x000000013fffffff] usable

so you code now select range that is out of boundary to non ram area.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-03  8:45   ` Yinghai Lu
@ 2015-03-03 11:42     ` Baoquan He
  2015-03-03 16:14       ` Yinghai Lu
  2015-03-04 15:39     ` Baoquan He
  1 sibling, 1 reply; 29+ messages in thread
From: Baoquan He @ 2015-03-03 11:42 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On 03/03/15 at 12:45am, Yinghai Lu wrote:
> On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:
> > Now random value can be used to get related slot info stored in
> > slot_area, mainly use slot_area.num to position which slot is target.
> > With this slot its starting address is returned as the physical
> > address where kernel will put.
> >
> > @@ -362,7 +364,7 @@ repeat:
> >         goto repeat;
> >  }
> >
> > -static unsigned long find_random_addr(unsigned long minimum,
> > +static unsigned long find_random_phy_addr(unsigned long minimum,
> >                                       unsigned long size)
> 

Hi Yinghai,

Thanks for testing and reviewing.

Yes, I forgot to change calling name. Must be dizzy during making patch.
Will change.

> You forgot to change calling name.
> 
> got:
> 
> arch/x86/boot/compressed/aslr.o: In function `choose_kernel_location':
> aslr.c:(.text+0x163): undefined reference to `find_random_addr'
> make[2]: *** [arch/x86/boot/compressed/vmlinux] Error 1
> make[1]: *** [arch/x86/boot/compressed/vmlinux] Error 2
> 
> Please make the patch set bisect-able.

Ok, will rearrange patches.
> 
> after fixing that, on the system with 4G ram: i got:
> 
> early console in decompress_kernel
> KASLR using RDTSC...
> decompress_kernel:
>   input: [0x13f5ed3b4-0x13ff6a64b], output: 0x153000000, heap:

Here input means the region where kernel was linked to load? 

In normal kernel the linked address is 0x1000000. In your input region
the result of ALIGN(0x13f5ed3b4, CONFIG_PHYSICAL_ALIGN) is 0x140000000.
And size of this region is smaller than 16M. It should return in
process_e820_entry() with two checks.

I guess you use kexec or a special bootloader to put kernel in this
load address.

I will check code again it doesn't handle this case correctly.

> [0x13ff76000-0x13ff7dfff]
> 
> Decompressing Linux... xz...
> 
> XZ-compressed data is corrupt
> 
> 
> without the patch, I have:
> 
> early console in decompress_kernel
> KASLR could not find suitable E820 region...
> decompress_kernel:
>   input: [0x13f5ee3b4-0x13ff6b64b], output: 0x13cc00000, heap:
> [0x13ff76000-0x13ff7dfff]
> 
> Decompressing Linux... xz... Parsing ELF... done.
> ...
> [    0.016848] e820: BIOS-provided physical RAM map (sanitized by setup):
> [    0.018854] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
> [    0.020982] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
> [    0.023166] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
> [    0.025783] BIOS-e820: [mem 0x0000000000100000-0x00000000bffdffff] usable
> [    0.027901] BIOS-e820: [mem 0x00000000bffe0000-0x00000000bfffffff] reserved
> [    0.030079] BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff] reserved
> [    0.032252] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
> [    0.034437] BIOS-e820: [mem 0x0000000100000000-0x000000013fffffff] usable
> 
> so you code now select range that is out of boundary to non ram area.
> 
> Thanks
> 
> Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-03 11:42     ` Baoquan He
@ 2015-03-03 16:14       ` Yinghai Lu
  2015-03-04 12:08         ` Baoquan He
  0 siblings, 1 reply; 29+ messages in thread
From: Yinghai Lu @ 2015-03-03 16:14 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Tue, Mar 3, 2015 at 3:42 AM, Baoquan He <bhe@redhat.com> wrote:
>
> Here input means the region where kernel was linked to load?
>
> In normal kernel the linked address is 0x1000000. In your input region
> the result of ALIGN(0x13f5ed3b4, CONFIG_PHYSICAL_ALIGN) is 0x140000000.
> And size of this region is smaller than 16M. It should return in
> process_e820_entry() with two checks.
>
> I guess you use kexec or a special bootloader to put kernel in this
> load address.
>


with patched grub2 that load kernel/initrd/param/cmdline etc above 4G.

kernel: read done                           [ linux  9.55MiB  100%  7.25MiB/s ]
params: [13fffc000,13fffffff]
cmdline: [13fffb000,13fffb7fe]
kernel: [13c000000,13f38cfff]
initrd: [139d7c000,13bfff7e3]
initrd: read 1 file done             [ initrd.img  34.51MiB  100%  11.17MiB/s ]
early console in decompress_kernel
KASLR using RDTSC...
decompress_kernel:
  input: [0x13e9ed3b4-0x13f36a64b], output: 0x16c000000, heap:
[0x13f376000-0x13f37dfff]

Decompressing Linux... xz...

XZ-compressed data is corrupt

 -- System halted

13c000000 is loaded address.
0x13e9ed3b4 is the copied address, and decompress_kernel will use it as input.
output is back to 13c000000 if aslr is not used.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 1/9] remove a unused function parameter
  2015-03-02 14:58 ` [PATCH v2 1/9] remove a unused function parameter Baoquan He
@ 2015-03-03 18:32   ` Yinghai Lu
  2015-03-04 15:48     ` Baoquan He
  0 siblings, 1 reply; 29+ messages in thread
From: Yinghai Lu @ 2015-03-03 18:32 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:
> Make a clean up to simplify the later change.
>
> Signed-off-by: Baoquan He <bhe@redhat.com>
> ---
>  arch/x86/boot/compressed/aslr.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
> index 7083c16..6a22129 100644
> --- a/arch/x86/boot/compressed/aslr.c
> +++ b/arch/x86/boot/compressed/aslr.c
> @@ -142,7 +142,7 @@ static bool mem_overlaps(struct mem_vector *one, struct mem_vector *two)
>  }
>
>  static void mem_avoid_init(unsigned long input, unsigned long input_size,
> -                          unsigned long output, unsigned long output_size)
> +                          unsigned long output_size)
>  {
>         u64 initrd_start, initrd_size;
>         u64 cmd_line, cmd_line_size;
> @@ -349,7 +349,7 @@ unsigned char *choose_kernel_location(struct boot_params *params,
>
>         /* Record the various known unsafe memory ranges. */
>         mem_avoid_init((unsigned long)input, input_size,
> -                      (unsigned long)output, output_size);
> +                      output_size);
>
>         /* Walk e820 and find a random address. */
>         random = find_random_addr(choice, output_size);

No, that is not right, but it is not your fault.

let me sort it out.

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-03 16:14       ` Yinghai Lu
@ 2015-03-04 12:08         ` Baoquan He
  0 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-04 12:08 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On 03/03/15 at 08:14am, Yinghai Lu wrote:
> On Tue, Mar 3, 2015 at 3:42 AM, Baoquan He <bhe@redhat.com> wrote:
> >
> > Here input means the region where kernel was linked to load?
> >
> > In normal kernel the linked address is 0x1000000. In your input region
> > the result of ALIGN(0x13f5ed3b4, CONFIG_PHYSICAL_ALIGN) is 0x140000000.
> > And size of this region is smaller than 16M. It should return in
> > process_e820_entry() with two checks.
> >
> > I guess you use kexec or a special bootloader to put kernel in this
> > load address.
> >
> 
> 
Hi Yinghai,

I checked code but didnt' find the code bug. Now I plan to hardcode your
data to the avoid[] array, then test on my laptop. Then I can check what
happened by message printing. Coudl you please help clarify the datas I
wrote below?

> with patched grub2 that load kernel/initrd/param/cmdline etc above 4G.
> 

Here,

avoid[0]
input = 0x13f376000;
input_size = 9.55M since its region is [0x13f376000-0x13f37dfff]

addr = 0x13f37dfff - 0x338d000 = 0x13bff0fff
size = (0x338d000 >> 12) + 32768 + 18 = 45983 = 0xb39f


avoid[1]
initrd [0x13f376000-0x13f37dfff]
addr = 0x13f376000
size = 0x8000


avoid[2]
cmdline [13fffb000,13fffb7fe]
addr = 0x13fffb000
size =  0x13fffb7fe - 0x13fffb000 = 0x7ff

avoid[3]
heap: [0x13f376000-0x13f37dfff]
addr = 0x13f376000
size = BOOT_HEAP_SIZE

avoid[4]
stack: from end of heap
addr = 0x13f37dfff 
size = BOOT_STACK_SIZE;
> kernel: read done                           [ linux  9.55MiB  100%  7.25MiB/s ]
> params: [13fffc000,13fffffff]
> cmdline: [13fffb000,13fffb7fe]
> kernel: [13c000000,13f38cfff]
output_orig = 0x13c000000
output_size = 0x13f38cfff - 0x13c000000 = 0x338d000
> initrd: [139d7c000,13bfff7e3]
> initrd: read 1 file done             [ initrd.img  34.51MiB  100%  11.17MiB/s ]
> early console in decompress_kernel
> KASLR using RDTSC...
> decompress_kernel:
>   input: [0x13e9ed3b4-0x13f36a64b], output: 0x16c000000, heap:

It's very weird to get 0x16c000000 which is out of bound obviously.


> [0x13f376000-0x13f37dfff]
> 
> Decompressing Linux... xz...
> 
> XZ-compressed data is corrupt
> 
>  -- System halted
> 
> 13c000000 is loaded address.
> 0x13e9ed3b4 is the copied address, and decompress_kernel will use it as input.
> output is back to 13c000000 if aslr is not used.
> 
> Thanks
> 
> Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-03  8:45   ` Yinghai Lu
  2015-03-03 11:42     ` Baoquan He
@ 2015-03-04 15:39     ` Baoquan He
  2015-03-04 21:35       ` Yinghai Lu
  2015-03-05  0:30       ` Yinghai Lu
  1 sibling, 2 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-04 15:39 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

[-- Attachment #1: Type: text/plain, Size: 1712 bytes --]

Hi Yinghai,

I got the reason and made a debug patch to fix it. Could you please
apply it on top of this patchset and try again? Then it will behave well
and just return 0x13c000000 since no random is got.

Please check the attachment.

Thanks
Baoquan

On 03/03/15 at 12:45am, Yinghai Lu wrote:

> after fixing that, on the system with 4G ram: i got:
> 
> early console in decompress_kernel
> KASLR using RDTSC...
> decompress_kernel:
>   input: [0x13f5ed3b4-0x13ff6a64b], output: 0x153000000, heap:
> [0x13ff76000-0x13ff7dfff]
> 
> Decompressing Linux... xz...
> 
> XZ-compressed data is corrupt
> 
> 
> without the patch, I have:
> 
> early console in decompress_kernel
> KASLR could not find suitable E820 region...
> decompress_kernel:
>   input: [0x13f5ee3b4-0x13ff6b64b], output: 0x13cc00000, heap:
> [0x13ff76000-0x13ff7dfff]
> 
> Decompressing Linux... xz... Parsing ELF... done.
> ...
> [    0.016848] e820: BIOS-provided physical RAM map (sanitized by setup):
> [    0.018854] BIOS-e820: [mem 0x0000000000000000-0x000000000009fbff] usable
> [    0.020982] BIOS-e820: [mem 0x000000000009fc00-0x000000000009ffff] reserved
> [    0.023166] BIOS-e820: [mem 0x00000000000f0000-0x00000000000fffff] reserved
> [    0.025783] BIOS-e820: [mem 0x0000000000100000-0x00000000bffdffff] usable
> [    0.027901] BIOS-e820: [mem 0x00000000bffe0000-0x00000000bfffffff] reserved
> [    0.030079] BIOS-e820: [mem 0x00000000feffc000-0x00000000feffffff] reserved
> [    0.032252] BIOS-e820: [mem 0x00000000fffc0000-0x00000000ffffffff] reserved
> [    0.034437] BIOS-e820: [mem 0x0000000100000000-0x000000013fffffff] usable
> 
> so you code now select range that is out of boundary to non ram area.
> 
> Thanks
> 
> Yinghai

[-- Attachment #2: yh-fix.patch --]
[-- Type: text/plain, Size: 745 bytes --]

diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
index 3114ae0..e351b99 100644
--- a/arch/x86/boot/compressed/aslr.c
+++ b/arch/x86/boot/compressed/aslr.c
@@ -301,18 +301,17 @@ static int process_e820_entry(struct e820entry *entry,
 	region.start = entry->addr;
 	region.size = entry->size;
 
+repeat:
+	start_orig = region.start;
+
 	/* Potentially raise address to minimum location. */
 	if (region.start < minimum)
 		region.start = minimum;
 
-repeat:
-
 	/* Return if slot area array is full */
 	if ( slot_area_index == MAX_SLOT_AREA )
 		return;
 
-	start_orig = region.start;
-
 	/* Potentially raise address to meet alignment requirements. */
 	region.start = ALIGN(region.start, CONFIG_PHYSICAL_ALIGN);
 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 1/9] remove a unused function parameter
  2015-03-03 18:32   ` Yinghai Lu
@ 2015-03-04 15:48     ` Baoquan He
  0 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-04 15:48 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On 03/03/15 at 10:32am, Yinghai Lu wrote:
> On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:
> >  static void mem_avoid_init(unsigned long input, unsigned long input_size,
> > -                          unsigned long output, unsigned long output_size)
> > +                          unsigned long output_size)
> >  {
> >         u64 initrd_start, initrd_size;
> >         u64 cmd_line, cmd_line_size;
> > @@ -349,7 +349,7 @@ unsigned char *choose_kernel_location(struct boot_params *params,
> >
> >         /* Record the various known unsafe memory ranges. */
> >         mem_avoid_init((unsigned long)input, input_size,
> > -                      (unsigned long)output, output_size);
> > +                      output_size);
> >
> >         /* Walk e820 and find a random address. */
> >         random = find_random_addr(choice, output_size);
> 
> No, that is not right, but it is not your fault.
> 
> let me sort it out.

All right, I saw your posting to address related issue, will take it
out from next repost.

Thanks
Baoquan


^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-02 14:58 ` [PATCH v2 7/9] get the random phy addr according to slot_area info Baoquan He
  2015-03-03  8:45   ` Yinghai Lu
@ 2015-03-04 21:28   ` Kees Cook
  2015-03-04 23:43     ` Baoquan He
  1 sibling, 1 reply; 29+ messages in thread
From: Kees Cook @ 2015-03-04 21:28 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Yinghai Lu, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar, LKML

On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:
> Now random value can be used to get related slot info stored in
> slot_area, mainly use slot_area.num to position which slot is target.
> With this slot its starting address is returned as the physical
> address where kernel will put.
>
> Signed-off-by: Baoquan He <bhe@redhat.com>
> ---
>  arch/x86/boot/compressed/aslr.c | 34 +++++++++++++++++++---------------
>  1 file changed, 19 insertions(+), 15 deletions(-)
>
> diff --git a/arch/x86/boot/compressed/aslr.c b/arch/x86/boot/compressed/aslr.c
> index 1c6fb31..55adee2 100644
> --- a/arch/x86/boot/compressed/aslr.c
> +++ b/arch/x86/boot/compressed/aslr.c
> @@ -245,9 +245,6 @@ static unsigned long mem_min_overlap(struct mem_vector *img, struct mem_vector *
>         return min;
>  }
>
> -static unsigned long slots[CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
> -                          CONFIG_PHYSICAL_ALIGN];
> -
>  struct slot_area {
>         unsigned long addr;
>         int num;
> @@ -261,23 +258,28 @@ static unsigned long slot_max;
>
>  static unsigned long slot_area_index;
>
> -static void slots_append(unsigned long addr)
> -{
> -       /* Overflowing the slots list should be impossible. */
> -       if (slot_max >= CONFIG_RANDOMIZE_BASE_MAX_OFFSET /
> -                       CONFIG_PHYSICAL_ALIGN)
> -               return;
> -
> -       slots[slot_max++] = addr;
> -}
> -
>  static unsigned long slots_fetch_random(void)
>  {
> +       unsigned long random;
> +       int i;
> +
>         /* Handle case of no slots stored. */
>         if (slot_max == 0)
>                 return 0;
>
> -       return slots[get_random_long() % slot_max];
> +       random = get_random_long() % slot_max;
> +
> +       for (i=0; i< slot_area_index; i++) {
> +               if (random > slot_areas[i].num) {
> +                       random -= slot_areas[i].num;
> +                       continue;
> +               }
> +               return slot_areas[i].addr + random * CONFIG_PHYSICAL_ALIGN;
> +       }
> +
> +       if (i == slot_area_index )
> +               debug_putstr("something wrong happened in slots_fetch_random()...\n");
> +       return 0;
>  }
>
>  static int process_e820_entry(struct e820entry *entry,
> @@ -362,7 +364,7 @@ repeat:
>         goto repeat;
>  }
>
> -static unsigned long find_random_addr(unsigned long minimum,
> +static unsigned long find_random_phy_addr(unsigned long minimum,
>                                       unsigned long size)
>  {
>         int i;
> @@ -374,6 +376,8 @@ static unsigned long find_random_addr(unsigned long minimum,
>         /* Verify potential e820 positions, appending to slots list. */
>         for (i = 0; i < real_mode->e820_entries; i++) {
>                 process_e820_entry(&real_mode->e820_map[i], minimum, size);
> +               if ( slot_area_index == MAX_SLOT_AREA )
> +                       break;

I wonder if this should emit a printk warning?

-Kees

>         }
>
>         return slots_fetch_random();
> --
> 1.9.3
>



-- 
Kees Cook
Chrome OS Security

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-04 15:39     ` Baoquan He
@ 2015-03-04 21:35       ` Yinghai Lu
  2015-03-05  0:12         ` Yinghai Lu
  2015-03-05  0:30       ` Yinghai Lu
  1 sibling, 1 reply; 29+ messages in thread
From: Yinghai Lu @ 2015-03-04 21:35 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Wed, Mar 4, 2015 at 7:39 AM, Baoquan He <bhe@redhat.com> wrote:
>
> I got the reason and made a debug patch to fix it. Could you please
> apply it on top of this patchset and try again? Then it will behave well
> and just return 0x13c000000 since no random is got.

random_base can not be move down?

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 9/9] change the relocations behavior for kaslr on x86_64
  2015-03-02 14:58 ` [PATCH v2 9/9] change the relocations behavior for kaslr on x86_64 Baoquan He
@ 2015-03-04 23:16   ` Yinghai Lu
  2015-03-04 23:41     ` Baoquan He
  0 siblings, 1 reply; 29+ messages in thread
From: Yinghai Lu @ 2015-03-04 23:16 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:

> @@ -455,17 +455,16 @@ unsigned char *choose_kernel_location(struct boot_params *params,
>                        output_size);

you forgot to change

        /* Record the various known unsafe memory ranges. */
        mem_avoid_init((unsigned long)input, input_size,
                       (unsigned long)output, init_size);

to

        /* Record the various known unsafe memory ranges. */
        mem_avoid_init((unsigned long)input, input_size,
                       (unsigned long)*output, init_size);

>
>         /* Walk e820 and find a random address. */
> -       random = find_random_addr(choice, output_size);
> -       if (!random) {
> +       random = find_random_phy_addr((unsigned long)*output, output_size);
> +       if (!random)
>                 debug_putstr("KASLR could not find suitable E820 region...\n");
> -               goto out;
> -       }
> +       else
> +               *output = (unsigned char*)random;

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 9/9] change the relocations behavior for kaslr on x86_64
  2015-03-04 23:16   ` Yinghai Lu
@ 2015-03-04 23:41     ` Baoquan He
  0 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-04 23:41 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On 03/04/15 at 03:16pm, Yinghai Lu wrote:
> On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:
> 
> > @@ -455,17 +455,16 @@ unsigned char *choose_kernel_location(struct boot_params *params,
> >                        output_size);
> 
> you forgot to change
> 
>         /* Record the various known unsafe memory ranges. */
>         mem_avoid_init((unsigned long)input, input_size,
>                        (unsigned long)output, init_size);
> 
> to
> 
>         /* Record the various known unsafe memory ranges. */
>         mem_avoid_init((unsigned long)input, input_size,
>                        (unsigned long)*output, init_size);
No, I removed output in patch 1/9 since it's not used in
mem_avoid_init(). It doesn't have this problem. But in next post it need
be done like this.

> 
> >
> >         /* Walk e820 and find a random address. */
> > -       random = find_random_addr(choice, output_size);
> > -       if (!random) {
> > +       random = find_random_phy_addr((unsigned long)*output, output_size);
> > +       if (!random)
> >                 debug_putstr("KASLR could not find suitable E820 region...\n");
> > -               goto out;
> > -       }
> > +       else
> > +               *output = (unsigned char*)random;

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-04 21:28   ` Kees Cook
@ 2015-03-04 23:43     ` Baoquan He
  0 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-04 23:43 UTC (permalink / raw)
  To: Kees Cook
  Cc: H. Peter Anvin, Yinghai Lu, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar, LKML

On 03/04/15 at 01:28pm, Kees Cook wrote:
> On Mon, Mar 2, 2015 at 6:58 AM, Baoquan He <bhe@redhat.com> wrote:
> > -static unsigned long find_random_addr(unsigned long minimum,
> > +static unsigned long find_random_phy_addr(unsigned long minimum,
> >                                       unsigned long size)
> >  {
> >         int i;
> > @@ -374,6 +376,8 @@ static unsigned long find_random_addr(unsigned long minimum,
> >         /* Verify potential e820 positions, appending to slots list. */
> >         for (i = 0; i < real_mode->e820_entries; i++) {
> >                 process_e820_entry(&real_mode->e820_map[i], minimum, size);
> > +               if ( slot_area_index == MAX_SLOT_AREA )
> > +                       break;
> 
> I wonder if this should emit a printk warning?

Yes, good suggestion. Will add.

Thanks
Baoquan

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-04 21:35       ` Yinghai Lu
@ 2015-03-05  0:12         ` Yinghai Lu
  2015-03-05  1:55           ` Baoquan He
  0 siblings, 1 reply; 29+ messages in thread
From: Yinghai Lu @ 2015-03-05  0:12 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Wed, Mar 4, 2015 at 1:35 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> On Wed, Mar 4, 2015 at 7:39 AM, Baoquan He <bhe@redhat.com> wrote:
>>
>> I got the reason and made a debug patch to fix it. Could you please
>> apply it on top of this patchset and try again? Then it will behave well
>> and just return 0x13c000000 since no random is got.
>
> random_base can not be move down?
>

Modify the min_addr will allow move down, and it is safe as we put all
related into mem_avoid now.


kernel: read done                           [ linux  9.55MiB  100%  7.26MiB/s ]
params: [13fffc000,13fffffff]
cmdline: [13fffb000,13fffb7fe]
kernel: [13c000000,13f394fff]
initrd: [139d7c000,13bfff7e3]
initrd: read 1 file done             [ initrd.img  34.51MiB  100%  11.39MiB/s ]
early console in decompress_kernel
decompress_kernel:
  input: [0x13e9ee3b4-0x13f36b9df], output: [0x13c000000-0x13f394fff],
heap: [0x13f376ac0-0x13f37eabf]
boot via startup_64
KASLR using RDTSC...
KASLR using RDTSC...
                     new output: [0x6f000000-0x72394fff]

Decompressing Linux... xz... Parsing ELF... Performing relocations... done.
Booting the kernel.
[    0.000000] bootconsole [uart0] enabled
[    0.000000] Kernel Layout:
[    0.000000]   .text: [0x6f000000-0x70096a9c]
[    0.000000] .rodata: [0x70200000-0x70a4efff]
[    0.000000]   .data: [0x70c00000-0x70e4e9bf]
[    0.000000]   .init: [0x70e50000-0x7120bfff]
[    0.000000]    .bss: [0x71219000-0x7234efff]
[    0.000000]    .brk: [0x7234f000-0x72374fff]


Please check

https://git.kernel.org/cgit/linux/kernel/git/yinghai/linux-yinghai.git/log/?h=for-x86-4.0-rc2-aslr

for updated patches.

Your patches still have some format warning, Please use
./scripts/checkpatch.pl
to find them and fix them before next post.

Also patch should have "x86,kasl" in the title.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-04 15:39     ` Baoquan He
  2015-03-04 21:35       ` Yinghai Lu
@ 2015-03-05  0:30       ` Yinghai Lu
  2015-03-05  1:48         ` Baoquan He
  1 sibling, 1 reply; 29+ messages in thread
From: Yinghai Lu @ 2015-03-05  0:30 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Wed, Mar 4, 2015 at 7:39 AM, Baoquan He <bhe@redhat.com> wrote:
> Hi Yinghai,
>
> I got the reason and made a debug patch to fix it. Could you please
> apply it on top of this patchset and try again? Then it will behave well
> and just return 0x13c000000 since no random is got.
>

the fix should be fold into your patch 6.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-05  0:30       ` Yinghai Lu
@ 2015-03-05  1:48         ` Baoquan He
  0 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-05  1:48 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On 03/04/15 at 04:30pm, Yinghai Lu wrote:
> On Wed, Mar 4, 2015 at 7:39 AM, Baoquan He <bhe@redhat.com> wrote:
> > Hi Yinghai,
> >
> > I got the reason and made a debug patch to fix it. Could you please
> > apply it on top of this patchset and try again? Then it will behave well
> > and just return 0x13c000000 since no random is got.
> >
> 
> the fix should be fold into your patch 6.

Yeah, will do.

> 
> Thanks
> 
> Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 7/9] get the random phy addr according to slot_area info
  2015-03-05  0:12         ` Yinghai Lu
@ 2015-03-05  1:55           ` Baoquan He
  0 siblings, 0 replies; 29+ messages in thread
From: Baoquan He @ 2015-03-05  1:55 UTC (permalink / raw)
  To: Yinghai Lu
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On 03/04/15 at 04:12pm, Yinghai Lu wrote:
> On Wed, Mar 4, 2015 at 1:35 PM, Yinghai Lu <yinghai@kernel.org> wrote:
> > On Wed, Mar 4, 2015 at 7:39 AM, Baoquan He <bhe@redhat.com> wrote:
> >>
> >> I got the reason and made a debug patch to fix it. Could you please
> >> apply it on top of this patchset and try again? Then it will behave well
> >> and just return 0x13c000000 since no random is got.
> >
> > random_base can not be move down?
> >
> 
> Modify the min_addr will allow move down, and it is safe as we put all
> related into mem_avoid now.

I am considering this random_base issue, but planned to do it after the
main work is done. I am wondering why not set it as 16M since all
related has been avoided and safe?

> 
> 
> https://git.kernel.org/cgit/linux/kernel/git/yinghai/linux-yinghai.git/log/?h=for-x86-4.0-rc2-aslr
> 
> for updated patches.
> 
> Your patches still have some format warning, Please use
> ./scripts/checkpatch.pl
> to find them and fix them before next post.
> 
> Also patch should have "x86,kasl" in the title.

Yes, will do.

Thanks
Baoquan

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 0/9] randomize kernel physical address and virtual address separately
  2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
                   ` (8 preceding siblings ...)
  2015-03-02 14:58 ` [PATCH v2 9/9] change the relocations behavior for kaslr on x86_64 Baoquan He
@ 2015-03-05 15:57 ` Baoquan He
  2015-03-06  1:37   ` Yinghai Lu
  9 siblings, 1 reply; 29+ messages in thread
From: Baoquan He @ 2015-03-05 15:57 UTC (permalink / raw)
  To: hpa, yinghai, keescook, vgoyal, luto, akpm, tglx, mingo; +Cc: linux-kernel

Hi Yinghai,

I have rearrange my patchset, they depend on your patchset in below
link. How should I post them? 

https://git.kernel.org/cgit/linux/kernel/git/yinghai/linux-yinghai.git/log/?h=for-x86-4.0-rc2-aslr


I post a patchset which includes your below patches?

x86, kaslr, 64bit: Set new or extra ident_mapping
x86, boot: Split kernel_ident_mapping_init to another file
x86, kaslr: Consolidate the mem_avoid filling
x86, kaslr: Get kaslr_enabled back correctly
x86, boot: Keep data from ZO boot stage to VO kernel stage.
x86, boot: Move ZO to end of buffer
x86, kaslr: Use init_size instead of run_size

Thanks
Baoquan

On 03/02/15 at 10:58pm, Baoquan He wrote:
> Currently kaslr only randomize physical address of kernel loading, then add the delta
> to virtual address of kernel text mapping. Because kernel virtual address can only be
> from __START_KERNEL_map to LOAD_PHYSICAL_ADDR+CONFIG_RANDOMIZE_BASE_MAX_OFFSET, namely
> [0xffffffff80000000, 0xffffffffc0000000], so physical address can only be randomized
> in region [LOAD_PHYSICAL_ADDR, CONFIG_RANDOMIZE_BASE_MAX_OFFSET], namely [16M, 1G].
> 
> So hpa and Vivek suggested the randomization should be done separately for both physical
> and virtual address. In this patchset the behavior is changed. Randomize both the physical
> address where kernel is decompressed and the virtual address where kernel text is mapped.
> And physical address can be randomized from where vmlinux was linked to load to maximum
> physical memory, possibly near 64T. While virtual address can get a random offset from load
> address to CONFIG_RANDOMIZE_BASE_MAX_OFFSET, then added to __START_KERNEL_map. And
> relocation handling only depends on virtual address randomization. Means if and only if
> virtual address is randomized to a different value, we add the delta to the offset of
> kernel relocs.
> 
> v1->v2:
>     Thanks to Yinghai's patch which make kernel be able to load above 4G in boot stage,
>     physical address can be randomized to anywhere, even near 64T.
> 
> 
>     Thank Andy Lutomirski for his adding idt patch, finally it's not used in this patchset
>     since I didn't make the #PF handler work well. I believe it does work, but I didn't
>     make it. Will check why later. Thanks anyway.
> 
> Baoquan He (8):
>   remove a unused function parameter
>   a bug that relocation can not be handled when kernel is loaded above
>     2G
>   introduce struct slot_area to manage randomization slot info
>   add mem_min_overlap to find the first avoid region within a memory
>     region
>   change process_e820_entry to store slot info into slot_area
>   get the random phy addr according to slot_area info
>   introduce fetch_random_virt_offset to randomize the kernel text
>     mapping address
>   change the relocations behavior for kaslr on x86_64
> 
> Yinghai Lu (1):
>   make kernel be able to load above 4G in boot stage
> 
>  arch/x86/boot/compressed/aslr.c     | 194 +++++++++++++++++++++++++++---------
>  arch/x86/boot/compressed/misc.c     |  46 ++++++---
>  arch/x86/boot/compressed/misc.h     |  22 ++--
>  arch/x86/boot/compressed/misc_pgt.c |  61 ++++++++++++
>  arch/x86/include/asm/page.h         |   5 +
>  arch/x86/mm/ident_map.c             |  74 ++++++++++++++
>  arch/x86/mm/init_64.c               |  74 +-------------
>  7 files changed, 333 insertions(+), 143 deletions(-)
>  create mode 100644 arch/x86/boot/compressed/misc_pgt.c
>  create mode 100644 arch/x86/mm/ident_map.c
> 
> -- 
> 1.9.3
> 

^ permalink raw reply	[flat|nested] 29+ messages in thread

* Re: [PATCH v2 0/9] randomize kernel physical address and virtual address separately
  2015-03-05 15:57 ` [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
@ 2015-03-06  1:37   ` Yinghai Lu
  0 siblings, 0 replies; 29+ messages in thread
From: Yinghai Lu @ 2015-03-06  1:37 UTC (permalink / raw)
  To: Baoquan He
  Cc: H. Peter Anvin, Kees Cook, Vivek Goyal, Andy Lutomirski,
	Andrew Morton, Thomas Gleixner, Ingo Molnar,
	Linux Kernel Mailing List

On Thu, Mar 5, 2015 at 7:57 AM, Baoquan He <bhe@redhat.com> wrote:
> Hi Yinghai,
>
> I have rearrange my patchset, they depend on your patchset in below
> link. How should I post them?

Please check

https://git.kernel.org/cgit/linux/kernel/git/yinghai/linux-yinghai.git/log/?h=for-x86-4.0-rc2-aslr

again, I dropped patches for setup_data cleanup from that branch.

Also fix one bug in
x86, kaslr, 64bit: Set new or extra ident_mapping

please rebase your patches on top of that branch and post your patches only
for more review.

Thanks

Yinghai

^ permalink raw reply	[flat|nested] 29+ messages in thread

end of thread, other threads:[~2015-03-06  1:37 UTC | newest]

Thread overview: 29+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-03-02 14:58 [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
2015-03-02 14:58 ` [PATCH v2 1/9] remove a unused function parameter Baoquan He
2015-03-03 18:32   ` Yinghai Lu
2015-03-04 15:48     ` Baoquan He
2015-03-02 14:58 ` [PATCH v2 2/9] a bug that relocation can not be handled when kernel is loaded above 2G Baoquan He
2015-03-02 14:58 ` [PATCH v2 3/9] make kernel be able to load above 4G in boot stage Baoquan He
2015-03-02 15:58   ` Baoquan He
2015-03-02 14:58 ` [PATCH v2 4/9] introduce struct slot_area to manage randomization slot info Baoquan He
2015-03-02 14:58 ` [PATCH v2 5/9] add mem_min_overlap to find the first avoid region within a memory region Baoquan He
2015-03-02 14:58 ` [PATCH v2 6/9] change process_e820_entry to store slot info into slot_area Baoquan He
2015-03-02 14:58 ` [PATCH v2 7/9] get the random phy addr according to slot_area info Baoquan He
2015-03-03  8:45   ` Yinghai Lu
2015-03-03 11:42     ` Baoquan He
2015-03-03 16:14       ` Yinghai Lu
2015-03-04 12:08         ` Baoquan He
2015-03-04 15:39     ` Baoquan He
2015-03-04 21:35       ` Yinghai Lu
2015-03-05  0:12         ` Yinghai Lu
2015-03-05  1:55           ` Baoquan He
2015-03-05  0:30       ` Yinghai Lu
2015-03-05  1:48         ` Baoquan He
2015-03-04 21:28   ` Kees Cook
2015-03-04 23:43     ` Baoquan He
2015-03-02 14:58 ` [PATCH v2 8/9] introduce fetch_random_virt_offset to randomize the kernel text mapping address Baoquan He
2015-03-02 14:58 ` [PATCH v2 9/9] change the relocations behavior for kaslr on x86_64 Baoquan He
2015-03-04 23:16   ` Yinghai Lu
2015-03-04 23:41     ` Baoquan He
2015-03-05 15:57 ` [PATCH v2 0/9] randomize kernel physical address and virtual address separately Baoquan He
2015-03-06  1:37   ` Yinghai Lu

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).