Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/arch/x86/lib/kaslr.c
26424 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Entropy functions used on early boot for KASLR base and memory
4
* randomization. The base randomization is done in the compressed
5
* kernel and memory randomization is done early when the regular
6
* kernel starts. This file is included in the compressed kernel and
7
* normally linked in the regular.
8
*/
9
#include <asm/asm.h>
10
#include <asm/kaslr.h>
11
#include <asm/tsc.h>
12
#include <asm/archrandom.h>
13
#include <asm/e820/api.h>
14
#include <asm/shared/io.h>
15
16
/*
17
* When built for the regular kernel, several functions need to be stubbed out
18
* or changed to their regular kernel equivalent.
19
*/
20
#ifndef KASLR_COMPRESSED_BOOT
21
#include <asm/cpufeature.h>
22
#include <asm/setup.h>
23
24
#define debug_putstr(v) early_printk("%s", v)
25
#define has_cpuflag(f) boot_cpu_has(f)
26
#define get_boot_seed() kaslr_offset()
27
#endif
28
29
#define I8254_PORT_CONTROL 0x43
30
#define I8254_PORT_COUNTER0 0x40
31
#define I8254_CMD_READBACK 0xC0
32
#define I8254_SELECT_COUNTER0 0x02
33
#define I8254_STATUS_NOTREADY 0x40
34
static inline u16 i8254(void)
35
{
36
u16 status, timer;
37
38
do {
39
outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
40
I8254_PORT_CONTROL);
41
status = inb(I8254_PORT_COUNTER0);
42
timer = inb(I8254_PORT_COUNTER0);
43
timer |= inb(I8254_PORT_COUNTER0) << 8;
44
} while (status & I8254_STATUS_NOTREADY);
45
46
return timer;
47
}
48
49
unsigned long kaslr_get_random_long(const char *purpose)
50
{
51
#ifdef CONFIG_X86_64
52
const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
53
#else
54
const unsigned long mix_const = 0x3f39e593UL;
55
#endif
56
unsigned long raw, random = get_boot_seed();
57
bool use_i8254 = true;
58
59
if (purpose) {
60
debug_putstr(purpose);
61
debug_putstr(" KASLR using");
62
}
63
64
if (has_cpuflag(X86_FEATURE_RDRAND)) {
65
if (purpose)
66
debug_putstr(" RDRAND");
67
if (rdrand_long(&raw)) {
68
random ^= raw;
69
use_i8254 = false;
70
}
71
}
72
73
if (has_cpuflag(X86_FEATURE_TSC)) {
74
if (purpose)
75
debug_putstr(" RDTSC");
76
raw = rdtsc();
77
78
random ^= raw;
79
use_i8254 = false;
80
}
81
82
if (use_i8254) {
83
if (purpose)
84
debug_putstr(" i8254");
85
random ^= i8254();
86
}
87
88
/* Circular multiply for better bit diffusion */
89
asm(_ASM_MUL "%3"
90
: "=a" (random), "=d" (raw)
91
: "a" (random), "rm" (mix_const));
92
random += raw;
93
94
if (purpose)
95
debug_putstr("...\n");
96
97
return random;
98
}
99
100