1b2d24b97SGerald Schaefer // SPDX-License-Identifier: GPL-2.0 2b2d24b97SGerald Schaefer /* 3b2d24b97SGerald Schaefer * Copyright IBM Corp. 2019 4b2d24b97SGerald Schaefer */ 5ca5999fdSMike Rapoport #include <linux/pgtable.h> 665fddcfcSMike Rapoport #include <asm/mem_detect.h> 7b2d24b97SGerald Schaefer #include <asm/cpacf.h> 8b2d24b97SGerald Schaefer #include <asm/timex.h> 9b2d24b97SGerald Schaefer #include <asm/sclp.h> 10*0c4ec024SVasily Gorbik #include <asm/kasan.h> 11b2d24b97SGerald Schaefer #include "compressed/decompressor.h" 12868202ceSVasily Gorbik #include "boot.h" 13b2d24b97SGerald Schaefer 14b2d24b97SGerald Schaefer #define PRNG_MODE_TDES 1 15b2d24b97SGerald Schaefer #define PRNG_MODE_SHA512 2 16b2d24b97SGerald Schaefer #define PRNG_MODE_TRNG 3 17b2d24b97SGerald Schaefer 18b2d24b97SGerald Schaefer struct prno_parm { 19b2d24b97SGerald Schaefer u32 res; 20b2d24b97SGerald Schaefer u32 reseed_counter; 21b2d24b97SGerald Schaefer u64 stream_bytes; 22b2d24b97SGerald Schaefer u8 V[112]; 23b2d24b97SGerald Schaefer u8 C[112]; 24b2d24b97SGerald Schaefer }; 25b2d24b97SGerald Schaefer 26b2d24b97SGerald Schaefer struct prng_parm { 27b2d24b97SGerald Schaefer u8 parm_block[32]; 28b2d24b97SGerald Schaefer u32 reseed_counter; 29b2d24b97SGerald Schaefer u64 byte_counter; 30b2d24b97SGerald Schaefer }; 31b2d24b97SGerald Schaefer 32b2d24b97SGerald Schaefer static int check_prng(void) 33b2d24b97SGerald Schaefer { 34b2d24b97SGerald Schaefer if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG)) { 35b2d24b97SGerald Schaefer sclp_early_printk("KASLR disabled: CPU has no PRNG\n"); 36b2d24b97SGerald Schaefer return 0; 37b2d24b97SGerald Schaefer } 38b2d24b97SGerald Schaefer if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG)) 39b2d24b97SGerald Schaefer return PRNG_MODE_TRNG; 40b2d24b97SGerald Schaefer if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN)) 41b2d24b97SGerald Schaefer return PRNG_MODE_SHA512; 42b2d24b97SGerald Schaefer else 43b2d24b97SGerald Schaefer return PRNG_MODE_TDES; 44b2d24b97SGerald Schaefer } 45b2d24b97SGerald Schaefer 4607a699bcSVasily Gorbik static int get_random(unsigned long limit, unsigned long *value) 47b2d24b97SGerald Schaefer { 48b2d24b97SGerald Schaefer struct prng_parm prng = { 49b2d24b97SGerald Schaefer /* initial parameter block for tdes mode, copied from libica */ 50b2d24b97SGerald Schaefer .parm_block = { 51b2d24b97SGerald Schaefer 0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52, 52b2d24b97SGerald Schaefer 0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4, 53b2d24b97SGerald Schaefer 0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF, 54b2d24b97SGerald Schaefer 0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0 55b2d24b97SGerald Schaefer }, 56b2d24b97SGerald Schaefer }; 57b2d24b97SGerald Schaefer unsigned long seed, random; 58b2d24b97SGerald Schaefer struct prno_parm prno; 59b2d24b97SGerald Schaefer __u64 entropy[4]; 60b2d24b97SGerald Schaefer int mode, i; 61b2d24b97SGerald Schaefer 62b2d24b97SGerald Schaefer mode = check_prng(); 63b2d24b97SGerald Schaefer seed = get_tod_clock_fast(); 64b2d24b97SGerald Schaefer switch (mode) { 65b2d24b97SGerald Schaefer case PRNG_MODE_TRNG: 66b2d24b97SGerald Schaefer cpacf_trng(NULL, 0, (u8 *) &random, sizeof(random)); 67b2d24b97SGerald Schaefer break; 68b2d24b97SGerald Schaefer case PRNG_MODE_SHA512: 69b2d24b97SGerald Schaefer cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, &prno, NULL, 0, 70b2d24b97SGerald Schaefer (u8 *) &seed, sizeof(seed)); 71b2d24b97SGerald Schaefer cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prno, (u8 *) &random, 72b2d24b97SGerald Schaefer sizeof(random), NULL, 0); 73b2d24b97SGerald Schaefer break; 74b2d24b97SGerald Schaefer case PRNG_MODE_TDES: 75b2d24b97SGerald Schaefer /* add entropy */ 76b2d24b97SGerald Schaefer *(unsigned long *) prng.parm_block ^= seed; 77b2d24b97SGerald Schaefer for (i = 0; i < 16; i++) { 78b2d24b97SGerald Schaefer cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block, 79788d6715SNathan Chancellor (u8 *) entropy, (u8 *) entropy, 80b2d24b97SGerald Schaefer sizeof(entropy)); 81b2d24b97SGerald Schaefer memcpy(prng.parm_block, entropy, sizeof(entropy)); 82b2d24b97SGerald Schaefer } 83b2d24b97SGerald Schaefer random = seed; 84b2d24b97SGerald Schaefer cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block, (u8 *) &random, 85b2d24b97SGerald Schaefer (u8 *) &random, sizeof(random)); 86b2d24b97SGerald Schaefer break; 87b2d24b97SGerald Schaefer default: 8807a699bcSVasily Gorbik return -1; 89b2d24b97SGerald Schaefer } 9007a699bcSVasily Gorbik *value = random % limit; 9107a699bcSVasily Gorbik return 0; 92b2d24b97SGerald Schaefer } 93b2d24b97SGerald Schaefer 945c46f276SVasily Gorbik /* 955c46f276SVasily Gorbik * To randomize kernel base address we have to consider several facts: 965c46f276SVasily Gorbik * 1. physical online memory might not be continuous and have holes. mem_detect 975c46f276SVasily Gorbik * info contains list of online memory ranges we should consider. 985c46f276SVasily Gorbik * 2. we have several memory regions which are occupied and we should not 995c46f276SVasily Gorbik * overlap and destroy them. Currently safe_addr tells us the border below 1005c46f276SVasily Gorbik * which all those occupied regions are. We are safe to use anything above 1015c46f276SVasily Gorbik * safe_addr. 1025c46f276SVasily Gorbik * 3. the upper limit might apply as well, even if memory above that limit is 1035c46f276SVasily Gorbik * online. Currently those limitations are: 1045c46f276SVasily Gorbik * 3.1. Limit set by "mem=" kernel command line option 1055c46f276SVasily Gorbik * 3.2. memory reserved at the end for kasan initialization. 1065c46f276SVasily Gorbik * 4. kernel base address must be aligned to THREAD_SIZE (kernel stack size). 1075c46f276SVasily Gorbik * Which is required for CONFIG_CHECK_STACK. Currently THREAD_SIZE is 4 pages 1085c46f276SVasily Gorbik * (16 pages when the kernel is built with kasan enabled) 1095c46f276SVasily Gorbik * Assumptions: 1105c46f276SVasily Gorbik * 1. kernel size (including .bss size) and upper memory limit are page aligned. 1115c46f276SVasily Gorbik * 2. mem_detect memory region start is THREAD_SIZE aligned / end is PAGE_SIZE 1125c46f276SVasily Gorbik * aligned (in practice memory configurations granularity on z/VM and LPAR 1135c46f276SVasily Gorbik * is 1mb). 1145c46f276SVasily Gorbik * 1155c46f276SVasily Gorbik * To guarantee uniform distribution of kernel base address among all suitable 1165c46f276SVasily Gorbik * addresses we generate random value just once. For that we need to build a 1175c46f276SVasily Gorbik * continuous range in which every value would be suitable. We can build this 1185c46f276SVasily Gorbik * range by simply counting all suitable addresses (let's call them positions) 1195c46f276SVasily Gorbik * which would be valid as kernel base address. To count positions we iterate 1205c46f276SVasily Gorbik * over online memory ranges. For each range which is big enough for the 1215c46f276SVasily Gorbik * kernel image we count all suitable addresses we can put the kernel image at 1225c46f276SVasily Gorbik * that is 1235c46f276SVasily Gorbik * (end - start - kernel_size) / THREAD_SIZE + 1 1245c46f276SVasily Gorbik * Two functions count_valid_kernel_positions and position_to_address help 1255c46f276SVasily Gorbik * to count positions in memory range given and then convert position back 1265c46f276SVasily Gorbik * to address. 1275c46f276SVasily Gorbik */ 1285c46f276SVasily Gorbik static unsigned long count_valid_kernel_positions(unsigned long kernel_size, 1295c46f276SVasily Gorbik unsigned long _min, 1305c46f276SVasily Gorbik unsigned long _max) 1315c46f276SVasily Gorbik { 1325c46f276SVasily Gorbik unsigned long start, end, pos = 0; 1335c46f276SVasily Gorbik int i; 1345c46f276SVasily Gorbik 1355c46f276SVasily Gorbik for_each_mem_detect_block(i, &start, &end) { 1365c46f276SVasily Gorbik if (_min >= end) 1375c46f276SVasily Gorbik continue; 1385c46f276SVasily Gorbik if (start >= _max) 1395c46f276SVasily Gorbik break; 1405c46f276SVasily Gorbik start = max(_min, start); 1415c46f276SVasily Gorbik end = min(_max, end); 1425c46f276SVasily Gorbik if (end - start < kernel_size) 1435c46f276SVasily Gorbik continue; 1445c46f276SVasily Gorbik pos += (end - start - kernel_size) / THREAD_SIZE + 1; 1455c46f276SVasily Gorbik } 1465c46f276SVasily Gorbik 1475c46f276SVasily Gorbik return pos; 1485c46f276SVasily Gorbik } 1495c46f276SVasily Gorbik 1505c46f276SVasily Gorbik static unsigned long position_to_address(unsigned long pos, unsigned long kernel_size, 1515c46f276SVasily Gorbik unsigned long _min, unsigned long _max) 1525c46f276SVasily Gorbik { 1535c46f276SVasily Gorbik unsigned long start, end; 1545c46f276SVasily Gorbik int i; 1555c46f276SVasily Gorbik 1565c46f276SVasily Gorbik for_each_mem_detect_block(i, &start, &end) { 1575c46f276SVasily Gorbik if (_min >= end) 1585c46f276SVasily Gorbik continue; 1595c46f276SVasily Gorbik if (start >= _max) 1605c46f276SVasily Gorbik break; 1615c46f276SVasily Gorbik start = max(_min, start); 1625c46f276SVasily Gorbik end = min(_max, end); 1635c46f276SVasily Gorbik if (end - start < kernel_size) 1645c46f276SVasily Gorbik continue; 1655c46f276SVasily Gorbik if ((end - start - kernel_size) / THREAD_SIZE + 1 >= pos) 1665c46f276SVasily Gorbik return start + (pos - 1) * THREAD_SIZE; 1675c46f276SVasily Gorbik pos -= (end - start - kernel_size) / THREAD_SIZE + 1; 1685c46f276SVasily Gorbik } 1695c46f276SVasily Gorbik 1705c46f276SVasily Gorbik return 0; 1715c46f276SVasily Gorbik } 1725c46f276SVasily Gorbik 173b2d24b97SGerald Schaefer unsigned long get_random_base(unsigned long safe_addr) 174b2d24b97SGerald Schaefer { 1755c46f276SVasily Gorbik unsigned long memory_limit = get_mem_detect_end(); 1765c46f276SVasily Gorbik unsigned long base_pos, max_pos, kernel_size; 177759d4899SVasily Gorbik unsigned long kasan_needs; 178b2d24b97SGerald Schaefer int i; 179b2d24b97SGerald Schaefer 1805c46f276SVasily Gorbik if (memory_end_set) 1815c46f276SVasily Gorbik memory_limit = min(memory_limit, memory_end); 1825c46f276SVasily Gorbik 183*0c4ec024SVasily Gorbik /* 184*0c4ec024SVasily Gorbik * Avoid putting kernel in the end of physical memory 185*0c4ec024SVasily Gorbik * which kasan will use for shadow memory and early pgtable 186*0c4ec024SVasily Gorbik * mapping allocations. 187*0c4ec024SVasily Gorbik */ 188*0c4ec024SVasily Gorbik memory_limit -= kasan_estimate_memory_needs(memory_limit); 189*0c4ec024SVasily Gorbik 190b2d24b97SGerald Schaefer if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && INITRD_START && INITRD_SIZE) { 191b2d24b97SGerald Schaefer if (safe_addr < INITRD_START + INITRD_SIZE) 192b2d24b97SGerald Schaefer safe_addr = INITRD_START + INITRD_SIZE; 193b2d24b97SGerald Schaefer } 194b2d24b97SGerald Schaefer safe_addr = ALIGN(safe_addr, THREAD_SIZE); 195b2d24b97SGerald Schaefer 196b2d24b97SGerald Schaefer kernel_size = vmlinux.image_size + vmlinux.bss_size; 1975c46f276SVasily Gorbik if (safe_addr + kernel_size > memory_limit) 1985c46f276SVasily Gorbik return 0; 1995c46f276SVasily Gorbik 2005c46f276SVasily Gorbik max_pos = count_valid_kernel_positions(kernel_size, safe_addr, memory_limit); 2015c46f276SVasily Gorbik if (!max_pos) { 202b2d24b97SGerald Schaefer sclp_early_printk("KASLR disabled: not enough memory\n"); 203b2d24b97SGerald Schaefer return 0; 204b2d24b97SGerald Schaefer } 205b2d24b97SGerald Schaefer 2065c46f276SVasily Gorbik /* we need a value in the range [1, base_pos] inclusive */ 2075c46f276SVasily Gorbik if (get_random(max_pos, &base_pos)) 208b2d24b97SGerald Schaefer return 0; 2095c46f276SVasily Gorbik return position_to_address(base_pos + 1, kernel_size, safe_addr, memory_limit); 210b2d24b97SGerald Schaefer } 211