]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
s390/boot: avoid page tables memory in kaslr
authorVasily Gorbik <gor@linux.ibm.com>
Fri, 27 Jan 2023 16:08:29 +0000 (17:08 +0100)
committerHeiko Carstens <hca@linux.ibm.com>
Mon, 6 Feb 2023 10:13:55 +0000 (11:13 +0100)
If kernel is build without KASAN support there is a chance that kernel
image is going to be positioned by KASLR code to overlap with identity
mapping page tables.

When kernel is build with KASAN support enabled memory which
is potentially going to be used for page tables and KASAN
shadow mapping is accounted for in KASLR with the use of
kasan_estimate_memory_needs(). Split this function and introduce
vmem_estimate_memory_needs() to cover decompressor's vmem identity
mapping page tables.

Fixes: bb1520d581a3 ("s390/mm: start kernel with DAT enabled")
Reviewed-by: Alexander Gordeev <agordeev@linux.ibm.com>
Signed-off-by: Vasily Gorbik <gor@linux.ibm.com>
Signed-off-by: Heiko Carstens <hca@linux.ibm.com>
arch/s390/boot/boot.h
arch/s390/boot/kaslr.c
arch/s390/boot/vmem.c
arch/s390/include/asm/kasan.h

index e91bbb004efb20296e9eced33c08337ac102f5f7..ed85b144119a03df82f91902b2e2ef1a349fe1f2 100644 (file)
@@ -46,6 +46,7 @@ void sclp_early_setup_buffer(void);
 void print_pgm_check_info(void);
 unsigned long get_random_base(unsigned long safe_addr);
 void setup_vmem(unsigned long asce_limit);
+unsigned long vmem_estimate_memory_needs(unsigned long online_mem_total);
 void __printf(1, 2) decompressor_printk(const char *fmt, ...);
 void error(char *m);
 
index bbf6860ebc45009ca5202be763a7f8bb781475d3..9cab7bbbfd1853b78b920c5c614661f73a072053 100644 (file)
@@ -172,16 +172,18 @@ static unsigned long position_to_address(unsigned long pos, unsigned long kernel
 
 unsigned long get_random_base(unsigned long safe_addr)
 {
+       unsigned long online_mem_total = get_mem_detect_online_total();
        unsigned long memory_limit = get_mem_detect_end();
        unsigned long base_pos, max_pos, kernel_size;
        int i;
 
        /*
         * Avoid putting kernel in the end of physical memory
-        * which kasan will use for shadow memory and early pgtable
-        * mapping allocations.
+        * which vmem and kasan code will use for shadow memory and
+        * pgtable mapping allocations.
         */
        memory_limit -= kasan_estimate_memory_needs(memory_limit);
+       memory_limit -= vmem_estimate_memory_needs(online_mem_total);
 
        safe_addr = ALIGN(safe_addr, THREAD_SIZE);
        kernel_size = vmlinux.image_size + vmlinux.bss_size;
index 82ef57827042df8850a9c55f0ed10ef31432d83c..4e54357ccd00e319b6a0bf651f84457f75ad1718 100644 (file)
@@ -269,3 +269,10 @@ void setup_vmem(unsigned long asce_limit)
 
        init_mm.context.asce = S390_lowcore.kernel_asce;
 }
+
+unsigned long vmem_estimate_memory_needs(unsigned long online_mem_total)
+{
+       unsigned long pages = DIV_ROUND_UP(online_mem_total, PAGE_SIZE);
+
+       return DIV_ROUND_UP(pages, _PAGE_ENTRIES) * _PAGE_TABLE_SIZE * 2;
+}
index f7244cc16240f4794c5d4d0bf697d23ce4bde63a..e5cfc81d5b6128a87c36341e7127bd598b26990d 100644 (file)
@@ -20,9 +20,9 @@ extern void kasan_early_init(void);
  * at the very end of available physical memory. To estimate
  * that, we take into account that kasan would require
  * 1/8 of available physical memory (for shadow memory) +
- * creating page tables for the whole memory + shadow memory
- * region (1 + 1/8). To keep page tables estimates simple take
- * the double of combined ptes size.
+ * creating page tables for the shadow memory region.
+ * To keep page tables estimates simple take the double of
+ * combined ptes size.
  *
  * physmem parameter has to be already adjusted if not entire physical memory
  * would be used (e.g. due to effect of "mem=" option).
@@ -34,7 +34,7 @@ static inline unsigned long kasan_estimate_memory_needs(unsigned long physmem)
        /* for shadow memory */
        kasan_needs = round_up(physmem / 8, PAGE_SIZE);
        /* for paging structures */
-       pages = DIV_ROUND_UP(physmem + kasan_needs, PAGE_SIZE);
+       pages = DIV_ROUND_UP(kasan_needs, PAGE_SIZE);
        kasan_needs += DIV_ROUND_UP(pages, _PAGE_ENTRIES) * _PAGE_TABLE_SIZE * 2;
 
        return kasan_needs;