Skip to contentSkip to conversation

x86/mm/KASLR: Fix the size of vmemmap section

PATCH Superseded Baoquan He 3 participants 6 messages May 8, 2019 – May 15, 2019

Subsystems (3)

v4 of 5 Superseded Latest is v5 →

lore
Share & tools
lore

Baoquan He

author
#0 lore raw

PATCH v4 1/1 x86/mm/KASLR: Fix the size of vmemmap section

kernel_randomize_memory() hardcodes the size of vmemmap section as 1 TB, to support the maximum amount of system RAM in 4-level paging mode, 64 TB.

However, 1 TB is not enough for vmemmap in 5-level paging mode. Assuming the size of struct page is 64 Bytes, to support 4 PB system RAM in 5-level, 64 TB of vmemmap area is needed. The wrong hardcoding may cause vmemmap stamping into the following cpu_entry_area section, if KASLR puts vmemmap very close to cpu_entry_area , and the actual area of vmemmap is much bigger than 1 TB.

So here calculate the actual size of vmemmap region, then align up to 1 TB boundary. In 4-level it's always 1 TB. In 5-level it's adjusted on demand. The current code reserves 0.5 PB for vmemmap in 5-level. In this new way, the left space can be saved to join randomization to increase the entropy.

---
v3->v4:
Fix the incorrect style of code comment;
Add ack tags from Kirill and Kees.
v3 discussion is here:
http://lkml.kernel.org/r/[email protected]

 arch/x86/mm/kaslr.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/mm/kaslr.c +10 -1
index dc3f058bdf9b..c0eedb85a92f 100644
@@ -52,7 +52,7 @@ static __initdata struct kaslr_memory_region {
 } kaslr_regions[] = {
 	{ &page_offset_base, 0 },
 	{ &vmalloc_base, 0 },
-	{ &vmemmap_base, 1 },
+	{ &vmemmap_base, 0 },
 };
 
 /* Get size in bytes used by the memory region */
@@ -78,6 +78,7 @@ void __init kernel_randomize_memory(void)
 	unsigned long rand, memory_tb;
 	struct rnd_state rand_state;
 	unsigned long remain_entropy;
+	unsigned long vmemmap_size;
 
 	vaddr_start = pgtable_l5_enabled() ? __PAGE_OFFSET_BASE_L5 : __PAGE_OFFSET_BASE_L4;
 	vaddr = vaddr_start;
@@ -109,6 +110,14 @@ void __init kernel_randomize_memory(void)
 	if (memory_tb < kaslr_regions[0].size_tb)
 		kaslr_regions[0].size_tb = memory_tb;
 
+	/*
+	 * Calculate how many TB vmemmap region needs, and aligned to
+	 * 1TB boundary.
+	 */
+	vmemmap_size = (kaslr_regions[0].size_tb << (TB_SHIFT - PAGE_SHIFT)) *
+		sizeof(struct page);
+	kaslr_regions[2].size_tb = DIV_ROUND_UP(vmemmap_size, 1UL << TB_SHIFT);
+
 	/* Calculate entropy available between regions */
 	remain_entropy = vaddr_end - vaddr_start;
 	for (i = 0; i < ARRAY_SIZE(kaslr_regions); i++)
Signature · 1 line
2.17.2
author
#1 lore raw
Quoted 10 lines · Baoquan He

kernel_randomize_memory() hardcodes the size of vmemmap section as 1 TB, to support the maximum amount of system RAM in 4-level paging mode, 64 TB.

However, 1 TB is not enough for vmemmap in 5-level paging mode. Assuming the size of struct page is 64 Bytes, to support 4 PB system RAM in 5-level, 64 TB of vmemmap area is needed. The wrong hardcoding may cause vmemmap stamping into the following cpu_entry_area section, if KASLR puts vmemmap very close to cpu_entry_area , and the actual area of vmemmap is much bigger than 1 TB.

Quoted 8 lines

So here calculate the actual size of vmemmap region, then align up to 1 TB boundary. In 4-level it's always 1 TB. In 5-level it's adjusted on demand. The current code reserves 0.5 PB for vmemmap in 5-level. In this new way, the left space can be saved to join randomization to increase the entropy.

I think this's worth noticing stable tree:

Quoted 49 lines

---
v3->v4:
Fix the incorrect style of code comment;
Add ack tags from Kirill and Kees.
v3 discussion is here:
http://lkml.kernel.org/r/[email protected]

 arch/x86/mm/kaslr.c | 11 ++++++++++-
 1 file changed, 10 insertions(+), 1 deletion(-)
arch/x86/mm/kaslr.c +10 -1
index dc3f058bdf9b..c0eedb85a92f 100644
@@ -52,7 +52,7 @@ static __initdata struct kaslr_memory_region {
 } kaslr_regions[] = {
 	{ &page_offset_base, 0 },
 	{ &vmalloc_base, 0 },
-	{ &vmemmap_base, 1 },
+	{ &vmemmap_base, 0 },
 };
 
 /* Get size in bytes used by the memory region */
@@ -78,6 +78,7 @@ void __init kernel_randomize_memory(void)
 	unsigned long rand, memory_tb;
 	struct rnd_state rand_state;
 	unsigned long remain_entropy;
+	unsigned long vmemmap_size;
 
 	vaddr_start = pgtable_l5_enabled() ? __PAGE_OFFSET_BASE_L5 : __PAGE_OFFSET_BASE_L4;
 	vaddr = vaddr_start;
@@ -109,6 +110,14 @@ void __init kernel_randomize_memory(void)
 	if (memory_tb < kaslr_regions[0].size_tb)
 		kaslr_regions[0].size_tb = memory_tb;
 
+	/*
+	 * Calculate how many TB vmemmap region needs, and aligned to
+	 * 1TB boundary.
+	 */
+	vmemmap_size = (kaslr_regions[0].size_tb << (TB_SHIFT - PAGE_SHIFT)) *
+		sizeof(struct page);
+	kaslr_regions[2].size_tb = DIV_ROUND_UP(vmemmap_size, 1UL << TB_SHIFT);
+
 	/* Calculate entropy available between regions */
 	remain_entropy = vaddr_end - vaddr_start;
 	for (i = 0; i < ARRAY_SIZE(kaslr_regions); i++)
Signature · 1 line
2.17.2
maintainer
#2 lore raw
Quoted 3 lines · Baoquan He

I think this's worth noticing stable tree:

Fixes ?
Signature · 4 lines
Regards/Gruss,
    Boris.

Good mailing practices for 400: avoid top-posting and trim the reply.
author
#3 lore raw
Quoted 6 lines · Borislav Petkov
Quoted 3 lines · Baoquan He

I think this's worth noticing stable tree:

Fixes ?

Not sure which commit validated 5-level.

Hi Kirill,

Is this commit OK?

Fiexes: eedb92abb9bb ("x86/mm: Make virtual memory layout dynamic for CONFIG_X86_5LEVEL=y")

Thanks
Baoquan

#4 lore raw
Quoted 8 lines · Baoquan He
Quoted 6 lines · Borislav Petkov
Quoted 3 lines · Baoquan He

I think this's worth noticing stable tree:

Fixes ?
Quoted 7 lines

Not sure which commit validated 5-level.

Hi Kirill,

Is this commit OK?

Fiexes: eedb92abb9bb ("x86/mm: Make virtual memory layout dynamic for CONFIG_X86_5LEVEL=y")

Yep.

Signature · 1 line
 Kirill A. Shutemov
author
#5 lore raw
Quoted 11 lines · Kirill A. Shutemov
Quoted 10 lines · Baoquan He
Quoted 6 lines · Borislav Petkov
Quoted 3 lines · Baoquan He

I think this's worth noticing stable tree:

Fixes ?

Not sure which commit validated 5-level.

Quoted 7 lines
Quoted 5 lines

Hi Kirill,

Is this commit OK?

Fiexes: eedb92abb9bb ("x86/mm: Make virtual memory layout dynamic for CONFIG_X86_5LEVEL=y")

Yep.

Thanks for confirming, will use it to update patch.