Home Home > GIT Browse
summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBorislav Petkov <bp@suse.de>2019-03-07 16:13:26 +0100
committerBorislav Petkov <bp@suse.de>2019-03-07 16:13:26 +0100
commit5560ba628a0e1797b7ff77f17d0df3aa362f3bf7 (patch)
treee36d500618f1f45f7ac4c90759cff92f585f664a
parentc17380106061878c212f71fbaec46f51b14205dc (diff)
- x86/kaslr: Fix incorrect i8254 outb() parameters (bsc#1114279).
- Refresh patches.suse/0003-x86-KASLR-public-the-function-for-getting-random-lon.patch. suse-commit: fc169b3a5cc6c606556bef28d21ed21b85169080
-rw-r--r--arch/x86/lib/kaslr.c61
-rw-r--r--arch/x86/lib/random.c4
2 files changed, 61 insertions, 4 deletions
diff --git a/arch/x86/lib/kaslr.c b/arch/x86/lib/kaslr.c
index aedc56f652ac..2aee2fb45a9b 100644
--- a/arch/x86/lib/kaslr.c
+++ b/arch/x86/lib/kaslr.c
@@ -25,10 +25,67 @@
#define get_boot_seed() kaslr_offset()
#endif
-#include "random.c"
+#define I8254_PORT_CONTROL 0x43
+#define I8254_PORT_COUNTER0 0x40
+#define I8254_CMD_READBACK 0xC0
+#define I8254_SELECT_COUNTER0 0x02
+#define I8254_STATUS_NOTREADY 0x40
+static inline u16 i8254(void)
+{
+ u16 status, timer;
+
+ do {
+ outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
+ I8254_PORT_CONTROL);
+ status = inb(I8254_PORT_COUNTER0);
+ timer = inb(I8254_PORT_COUNTER0);
+ timer |= inb(I8254_PORT_COUNTER0) << 8;
+ } while (status & I8254_STATUS_NOTREADY);
+
+ return timer;
+}
unsigned long kaslr_get_random_long(const char *purpose)
{
+#ifdef CONFIG_X86_64
+ const unsigned long mix_const = 0x5d6008cbf3848dd3UL;
+#else
+ const unsigned long mix_const = 0x3f39e593UL;
+#endif
+ unsigned long raw, random = get_boot_seed();
+ bool use_i8254 = true;
+
+ debug_putstr(purpose);
debug_putstr(" KASLR using");
- return get_random_long(purpose);
+
+ if (has_cpuflag(X86_FEATURE_RDRAND)) {
+ debug_putstr(" RDRAND");
+ if (rdrand_long(&raw)) {
+ random ^= raw;
+ use_i8254 = false;
+ }
+ }
+
+ if (has_cpuflag(X86_FEATURE_TSC)) {
+ debug_putstr(" RDTSC");
+ raw = rdtsc();
+
+ random ^= raw;
+ use_i8254 = false;
+ }
+
+ if (use_i8254) {
+ debug_putstr(" i8254");
+ random ^= i8254();
+ }
+
+ /* Circular multiply for better bit diffusion */
+ asm(_ASM_MUL "%3"
+ : "=a" (random), "=d" (raw)
+ : "a" (random), "rm" (mix_const));
+ random += raw;
+
+ debug_putstr("...\n");
+
+ return random;
}
diff --git a/arch/x86/lib/random.c b/arch/x86/lib/random.c
index 52bb5dad14a3..45554e9c12d4 100644
--- a/arch/x86/lib/random.c
+++ b/arch/x86/lib/random.c
@@ -11,8 +11,8 @@ static inline u16 i8254(void)
u16 status, timer;
do {
- outb(I8254_PORT_CONTROL,
- I8254_CMD_READBACK | I8254_SELECT_COUNTER0);
+ outb(I8254_CMD_READBACK | I8254_SELECT_COUNTER0,
+ I8254_PORT_CONTROL);
status = inb(I8254_PORT_COUNTER0);
timer = inb(I8254_PORT_COUNTER0);
timer |= inb(I8254_PORT_COUNTER0) << 8;