Skip to content

Commit

Permalink
x86/tdx: Make RDRAND/RDSEED loop forever
Browse files Browse the repository at this point in the history
The hardware random generator behind RDRAND/RDSEED has limited
bandwidth and can be in theory starved for some time by other cores.
That's an potential attack against a TDX guest's random number
generation. The RDRAND/RDSEED users generally fall back to some other
method if the default retry loop (10 retries) fails, but these other
methods are usually guessable by a malicious host (like RDTSC or
interrupt timing or some other methods), which might help the host with
guessing

Just make them loop forever inside TDX until a valid random number
is retrieved.

While that's a potential DOS, a malicious host has already other
ways to DOS. It cannot be used for a DOS from other guests, because
those will be eventually interrupted, which allows this guest to make
progress.

Note this only affects the kernel users.

Signed-off-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
  • Loading branch information
Andi Kleen authored and Kuppuswamy Sathyanarayanan committed Sep 2, 2021
1 parent 09144dd commit 1fe89e7
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 10 deletions.
39 changes: 29 additions & 10 deletions arch/x86/include/asm/archrandom.h
Original file line number Diff line number Diff line change
Expand Up @@ -10,13 +10,24 @@
#ifndef ASM_X86_ARCHRANDOM_H
#define ASM_X86_ARCHRANDOM_H

#include <linux/protected_guest.h>
#include <asm/processor.h>
#include <asm/cpufeature.h>

#define RDRAND_RETRY_LOOPS 10

/* Unconditional execution of RDRAND and RDSEED */

static inline bool rd_loop(void)
{
#if defined(BOOT_COMPRESSED_MISC_H) && defined(CONFIG_INTEL_TDX_GUEST)
/* In decompression code */
return early_is_tdx_guest();
#else
return prot_guest_has(PATTR_GUEST_RAND_LOOP);
#endif
}

static inline bool __must_check rdrand_long(unsigned long *v)
{
bool ok;
Expand All @@ -27,7 +38,7 @@ static inline bool __must_check rdrand_long(unsigned long *v)
: CC_OUT(c) (ok), [out] "=r" (*v));
if (ok)
return true;
} while (--retry);
} while (--retry || rd_loop());
return false;
}

Expand All @@ -41,26 +52,34 @@ static inline bool __must_check rdrand_int(unsigned int *v)
: CC_OUT(c) (ok), [out] "=r" (*v));
if (ok)
return true;
} while (--retry);
} while (--retry || rd_loop());
return false;
}

static inline bool __must_check rdseed_long(unsigned long *v)
{
bool ok;
asm volatile("rdseed %[out]"
CC_SET(c)
: CC_OUT(c) (ok), [out] "=r" (*v));
return ok;
do {
asm volatile("rdseed %[out]"
CC_SET(c)
: CC_OUT(c) (ok), [out] "=r" (*v));
if (ok)
return ok;
} while (rd_loop());
return false;
}

static inline bool __must_check rdseed_int(unsigned int *v)
{
bool ok;
asm volatile("rdseed %[out]"
CC_SET(c)
: CC_OUT(c) (ok), [out] "=r" (*v));
return ok;
do {
asm volatile("rdseed %[out]"
CC_SET(c)
: CC_OUT(c) (ok), [out] "=r" (*v));
if (ok)
return ok;
} while (rd_loop());
return false;
}

/*
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kernel/cpu/intel.c
Original file line number Diff line number Diff line change
Expand Up @@ -89,6 +89,7 @@ bool intel_prot_guest_has(unsigned int flag)
case PATTR_MEM_ENCRYPT:
case PATTR_GUEST_SECURE_TIME:
case PATTR_GUEST_CPUID_FILTER:
case PATTR_GUEST_RAND_LOOP:
return tdx_guest_enabled;
case PATTR_GUEST_DEVICE_FILTER:
return tdx_filter_enabled() && tdx_guest_enabled;
Expand Down
1 change: 1 addition & 0 deletions include/linux/protected_guest.h
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,7 @@
#define PATTR_GUEST_DEVICE_FILTER 6 /* Guest Device filter */
#define PATTR_GUEST_SECURE_TIME 7 /* Guest Secure Time */
#define PATTR_GUEST_CPUID_FILTER 8 /* Guest CPUID Filter */
#define PATTR_GUEST_RAND_LOOP 9 /* Hardware RNG must succeed */

/* 0x800 - 0x8ff reserved for AMD */
#define PATTR_SME 0x800
Expand Down

0 comments on commit 1fe89e7

Please sign in to comment.