xref: /openbmc/linux/arch/s390/boot/kaslr.c (revision 5c46f276)
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>
10b2d24b97SGerald Schaefer #include "compressed/decompressor.h"
11868202ceSVasily Gorbik #include "boot.h"
12b2d24b97SGerald Schaefer 
13b2d24b97SGerald Schaefer #define PRNG_MODE_TDES	 1
14b2d24b97SGerald Schaefer #define PRNG_MODE_SHA512 2
15b2d24b97SGerald Schaefer #define PRNG_MODE_TRNG	 3
16b2d24b97SGerald Schaefer 
17b2d24b97SGerald Schaefer struct prno_parm {
18b2d24b97SGerald Schaefer 	u32 res;
19b2d24b97SGerald Schaefer 	u32 reseed_counter;
20b2d24b97SGerald Schaefer 	u64 stream_bytes;
21b2d24b97SGerald Schaefer 	u8  V[112];
22b2d24b97SGerald Schaefer 	u8  C[112];
23b2d24b97SGerald Schaefer };
24b2d24b97SGerald Schaefer 
25b2d24b97SGerald Schaefer struct prng_parm {
26b2d24b97SGerald Schaefer 	u8  parm_block[32];
27b2d24b97SGerald Schaefer 	u32 reseed_counter;
28b2d24b97SGerald Schaefer 	u64 byte_counter;
29b2d24b97SGerald Schaefer };
30b2d24b97SGerald Schaefer 
31b2d24b97SGerald Schaefer static int check_prng(void)
32b2d24b97SGerald Schaefer {
33b2d24b97SGerald Schaefer 	if (!cpacf_query_func(CPACF_KMC, CPACF_KMC_PRNG)) {
34b2d24b97SGerald Schaefer 		sclp_early_printk("KASLR disabled: CPU has no PRNG\n");
35b2d24b97SGerald Schaefer 		return 0;
36b2d24b97SGerald Schaefer 	}
37b2d24b97SGerald Schaefer 	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_TRNG))
38b2d24b97SGerald Schaefer 		return PRNG_MODE_TRNG;
39b2d24b97SGerald Schaefer 	if (cpacf_query_func(CPACF_PRNO, CPACF_PRNO_SHA512_DRNG_GEN))
40b2d24b97SGerald Schaefer 		return PRNG_MODE_SHA512;
41b2d24b97SGerald Schaefer 	else
42b2d24b97SGerald Schaefer 		return PRNG_MODE_TDES;
43b2d24b97SGerald Schaefer }
44b2d24b97SGerald Schaefer 
4507a699bcSVasily Gorbik static int get_random(unsigned long limit, unsigned long *value)
46b2d24b97SGerald Schaefer {
47b2d24b97SGerald Schaefer 	struct prng_parm prng = {
48b2d24b97SGerald Schaefer 		/* initial parameter block for tdes mode, copied from libica */
49b2d24b97SGerald Schaefer 		.parm_block = {
50b2d24b97SGerald Schaefer 			0x0F, 0x2B, 0x8E, 0x63, 0x8C, 0x8E, 0xD2, 0x52,
51b2d24b97SGerald Schaefer 			0x64, 0xB7, 0xA0, 0x7B, 0x75, 0x28, 0xB8, 0xF4,
52b2d24b97SGerald Schaefer 			0x75, 0x5F, 0xD2, 0xA6, 0x8D, 0x97, 0x11, 0xFF,
53b2d24b97SGerald Schaefer 			0x49, 0xD8, 0x23, 0xF3, 0x7E, 0x21, 0xEC, 0xA0
54b2d24b97SGerald Schaefer 		},
55b2d24b97SGerald Schaefer 	};
56b2d24b97SGerald Schaefer 	unsigned long seed, random;
57b2d24b97SGerald Schaefer 	struct prno_parm prno;
58b2d24b97SGerald Schaefer 	__u64 entropy[4];
59b2d24b97SGerald Schaefer 	int mode, i;
60b2d24b97SGerald Schaefer 
61b2d24b97SGerald Schaefer 	mode = check_prng();
62b2d24b97SGerald Schaefer 	seed = get_tod_clock_fast();
63b2d24b97SGerald Schaefer 	switch (mode) {
64b2d24b97SGerald Schaefer 	case PRNG_MODE_TRNG:
65b2d24b97SGerald Schaefer 		cpacf_trng(NULL, 0, (u8 *) &random, sizeof(random));
66b2d24b97SGerald Schaefer 		break;
67b2d24b97SGerald Schaefer 	case PRNG_MODE_SHA512:
68b2d24b97SGerald Schaefer 		cpacf_prno(CPACF_PRNO_SHA512_DRNG_SEED, &prno, NULL, 0,
69b2d24b97SGerald Schaefer 			   (u8 *) &seed, sizeof(seed));
70b2d24b97SGerald Schaefer 		cpacf_prno(CPACF_PRNO_SHA512_DRNG_GEN, &prno, (u8 *) &random,
71b2d24b97SGerald Schaefer 			   sizeof(random), NULL, 0);
72b2d24b97SGerald Schaefer 		break;
73b2d24b97SGerald Schaefer 	case PRNG_MODE_TDES:
74b2d24b97SGerald Schaefer 		/* add entropy */
75b2d24b97SGerald Schaefer 		*(unsigned long *) prng.parm_block ^= seed;
76b2d24b97SGerald Schaefer 		for (i = 0; i < 16; i++) {
77b2d24b97SGerald Schaefer 			cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block,
78788d6715SNathan Chancellor 				  (u8 *) entropy, (u8 *) entropy,
79b2d24b97SGerald Schaefer 				  sizeof(entropy));
80b2d24b97SGerald Schaefer 			memcpy(prng.parm_block, entropy, sizeof(entropy));
81b2d24b97SGerald Schaefer 		}
82b2d24b97SGerald Schaefer 		random = seed;
83b2d24b97SGerald Schaefer 		cpacf_kmc(CPACF_KMC_PRNG, prng.parm_block, (u8 *) &random,
84b2d24b97SGerald Schaefer 			  (u8 *) &random, sizeof(random));
85b2d24b97SGerald Schaefer 		break;
86b2d24b97SGerald Schaefer 	default:
8707a699bcSVasily Gorbik 		return -1;
88b2d24b97SGerald Schaefer 	}
8907a699bcSVasily Gorbik 	*value = random % limit;
9007a699bcSVasily Gorbik 	return 0;
91b2d24b97SGerald Schaefer }
92b2d24b97SGerald Schaefer 
935c46f276SVasily Gorbik /*
945c46f276SVasily Gorbik  * To randomize kernel base address we have to consider several facts:
955c46f276SVasily Gorbik  * 1. physical online memory might not be continuous and have holes. mem_detect
965c46f276SVasily Gorbik  *    info contains list of online memory ranges we should consider.
975c46f276SVasily Gorbik  * 2. we have several memory regions which are occupied and we should not
985c46f276SVasily Gorbik  *    overlap and destroy them. Currently safe_addr tells us the border below
995c46f276SVasily Gorbik  *    which all those occupied regions are. We are safe to use anything above
1005c46f276SVasily Gorbik  *    safe_addr.
1015c46f276SVasily Gorbik  * 3. the upper limit might apply as well, even if memory above that limit is
1025c46f276SVasily Gorbik  *    online. Currently those limitations are:
1035c46f276SVasily Gorbik  *    3.1. Limit set by "mem=" kernel command line option
1045c46f276SVasily Gorbik  *    3.2. memory reserved at the end for kasan initialization.
1055c46f276SVasily Gorbik  * 4. kernel base address must be aligned to THREAD_SIZE (kernel stack size).
1065c46f276SVasily Gorbik  *    Which is required for CONFIG_CHECK_STACK. Currently THREAD_SIZE is 4 pages
1075c46f276SVasily Gorbik  *    (16 pages when the kernel is built with kasan enabled)
1085c46f276SVasily Gorbik  * Assumptions:
1095c46f276SVasily Gorbik  * 1. kernel size (including .bss size) and upper memory limit are page aligned.
1105c46f276SVasily Gorbik  * 2. mem_detect memory region start is THREAD_SIZE aligned / end is PAGE_SIZE
1115c46f276SVasily Gorbik  *    aligned (in practice memory configurations granularity on z/VM and LPAR
1125c46f276SVasily Gorbik  *    is 1mb).
1135c46f276SVasily Gorbik  *
1145c46f276SVasily Gorbik  * To guarantee uniform distribution of kernel base address among all suitable
1155c46f276SVasily Gorbik  * addresses we generate random value just once. For that we need to build a
1165c46f276SVasily Gorbik  * continuous range in which every value would be suitable. We can build this
1175c46f276SVasily Gorbik  * range by simply counting all suitable addresses (let's call them positions)
1185c46f276SVasily Gorbik  * which would be valid as kernel base address. To count positions we iterate
1195c46f276SVasily Gorbik  * over online memory ranges. For each range which is big enough for the
1205c46f276SVasily Gorbik  * kernel image we count all suitable addresses we can put the kernel image at
1215c46f276SVasily Gorbik  * that is
1225c46f276SVasily Gorbik  * (end - start - kernel_size) / THREAD_SIZE + 1
1235c46f276SVasily Gorbik  * Two functions count_valid_kernel_positions and position_to_address help
1245c46f276SVasily Gorbik  * to count positions in memory range given and then convert position back
1255c46f276SVasily Gorbik  * to address.
1265c46f276SVasily Gorbik  */
1275c46f276SVasily Gorbik static unsigned long count_valid_kernel_positions(unsigned long kernel_size,
1285c46f276SVasily Gorbik 						  unsigned long _min,
1295c46f276SVasily Gorbik 						  unsigned long _max)
1305c46f276SVasily Gorbik {
1315c46f276SVasily Gorbik 	unsigned long start, end, pos = 0;
1325c46f276SVasily Gorbik 	int i;
1335c46f276SVasily Gorbik 
1345c46f276SVasily Gorbik 	for_each_mem_detect_block(i, &start, &end) {
1355c46f276SVasily Gorbik 		if (_min >= end)
1365c46f276SVasily Gorbik 			continue;
1375c46f276SVasily Gorbik 		if (start >= _max)
1385c46f276SVasily Gorbik 			break;
1395c46f276SVasily Gorbik 		start = max(_min, start);
1405c46f276SVasily Gorbik 		end = min(_max, end);
1415c46f276SVasily Gorbik 		if (end - start < kernel_size)
1425c46f276SVasily Gorbik 			continue;
1435c46f276SVasily Gorbik 		pos += (end - start - kernel_size) / THREAD_SIZE + 1;
1445c46f276SVasily Gorbik 	}
1455c46f276SVasily Gorbik 
1465c46f276SVasily Gorbik 	return pos;
1475c46f276SVasily Gorbik }
1485c46f276SVasily Gorbik 
1495c46f276SVasily Gorbik static unsigned long position_to_address(unsigned long pos, unsigned long kernel_size,
1505c46f276SVasily Gorbik 				 unsigned long _min, unsigned long _max)
1515c46f276SVasily Gorbik {
1525c46f276SVasily Gorbik 	unsigned long start, end;
1535c46f276SVasily Gorbik 	int i;
1545c46f276SVasily Gorbik 
1555c46f276SVasily Gorbik 	for_each_mem_detect_block(i, &start, &end) {
1565c46f276SVasily Gorbik 		if (_min >= end)
1575c46f276SVasily Gorbik 			continue;
1585c46f276SVasily Gorbik 		if (start >= _max)
1595c46f276SVasily Gorbik 			break;
1605c46f276SVasily Gorbik 		start = max(_min, start);
1615c46f276SVasily Gorbik 		end = min(_max, end);
1625c46f276SVasily Gorbik 		if (end - start < kernel_size)
1635c46f276SVasily Gorbik 			continue;
1645c46f276SVasily Gorbik 		if ((end - start - kernel_size) / THREAD_SIZE + 1 >= pos)
1655c46f276SVasily Gorbik 			return start + (pos - 1) * THREAD_SIZE;
1665c46f276SVasily Gorbik 		pos -= (end - start - kernel_size) / THREAD_SIZE + 1;
1675c46f276SVasily Gorbik 	}
1685c46f276SVasily Gorbik 
1695c46f276SVasily Gorbik 	return 0;
1705c46f276SVasily Gorbik }
1715c46f276SVasily Gorbik 
172b2d24b97SGerald Schaefer unsigned long get_random_base(unsigned long safe_addr)
173b2d24b97SGerald Schaefer {
1745c46f276SVasily Gorbik 	unsigned long memory_limit = get_mem_detect_end();
1755c46f276SVasily Gorbik 	unsigned long base_pos, max_pos, kernel_size;
176759d4899SVasily Gorbik 	unsigned long kasan_needs;
177b2d24b97SGerald Schaefer 	int i;
178b2d24b97SGerald Schaefer 
1795c46f276SVasily Gorbik 	if (memory_end_set)
1805c46f276SVasily Gorbik 		memory_limit = min(memory_limit, memory_end);
1815c46f276SVasily Gorbik 
182b2d24b97SGerald Schaefer 	if (IS_ENABLED(CONFIG_BLK_DEV_INITRD) && INITRD_START && INITRD_SIZE) {
183b2d24b97SGerald Schaefer 		if (safe_addr < INITRD_START + INITRD_SIZE)
184b2d24b97SGerald Schaefer 			safe_addr = INITRD_START + INITRD_SIZE;
185b2d24b97SGerald Schaefer 	}
186b2d24b97SGerald Schaefer 	safe_addr = ALIGN(safe_addr, THREAD_SIZE);
187b2d24b97SGerald Schaefer 
188759d4899SVasily Gorbik 	if ((IS_ENABLED(CONFIG_KASAN))) {
189759d4899SVasily Gorbik 		/*
190759d4899SVasily Gorbik 		 * Estimate kasan memory requirements, which it will reserve
191759d4899SVasily Gorbik 		 * at the very end of available physical memory. To estimate
192759d4899SVasily Gorbik 		 * that, we take into account that kasan would require
193759d4899SVasily Gorbik 		 * 1/8 of available physical memory (for shadow memory) +
194759d4899SVasily Gorbik 		 * creating page tables for the whole memory + shadow memory
195759d4899SVasily Gorbik 		 * region (1 + 1/8). To keep page tables estimates simple take
196759d4899SVasily Gorbik 		 * the double of combined ptes size.
197759d4899SVasily Gorbik 		 */
198759d4899SVasily Gorbik 		memory_limit = get_mem_detect_end();
199759d4899SVasily Gorbik 		if (memory_end_set && memory_limit > memory_end)
200759d4899SVasily Gorbik 			memory_limit = memory_end;
201759d4899SVasily Gorbik 
202759d4899SVasily Gorbik 		/* for shadow memory */
203759d4899SVasily Gorbik 		kasan_needs = memory_limit / 8;
204759d4899SVasily Gorbik 		/* for paging structures */
205759d4899SVasily Gorbik 		kasan_needs += (memory_limit + kasan_needs) / PAGE_SIZE /
206759d4899SVasily Gorbik 			       _PAGE_ENTRIES * _PAGE_TABLE_SIZE * 2;
207759d4899SVasily Gorbik 		memory_limit -= kasan_needs;
208759d4899SVasily Gorbik 	}
209759d4899SVasily Gorbik 
210b2d24b97SGerald Schaefer 	kernel_size = vmlinux.image_size + vmlinux.bss_size;
2115c46f276SVasily Gorbik 	if (safe_addr + kernel_size > memory_limit)
2125c46f276SVasily Gorbik 		return 0;
2135c46f276SVasily Gorbik 
2145c46f276SVasily Gorbik 	max_pos = count_valid_kernel_positions(kernel_size, safe_addr, memory_limit);
2155c46f276SVasily Gorbik 	if (!max_pos) {
216b2d24b97SGerald Schaefer 		sclp_early_printk("KASLR disabled: not enough memory\n");
217b2d24b97SGerald Schaefer 		return 0;
218b2d24b97SGerald Schaefer 	}
219b2d24b97SGerald Schaefer 
2205c46f276SVasily Gorbik 	/* we need a value in the range [1, base_pos] inclusive */
2215c46f276SVasily Gorbik 	if (get_random(max_pos, &base_pos))
222b2d24b97SGerald Schaefer 		return 0;
2235c46f276SVasily Gorbik 	return position_to_address(base_pos + 1, kernel_size, safe_addr, memory_limit);
224b2d24b97SGerald Schaefer }
225