Skip to content
Browse files

random-util: eat up bad RDRAND values seen on AMD CPUs

An ugly, ugly work-around for systemd#11810. And no, we shouldn't have to do
this. This is something for AMD, the firmware or the kernel to
fix/work-around, not us. But nonetheless, this should do it for now.

Fixes: systemd#11810
  • Loading branch information...
poettering authored and Mic92 committed May 10, 2019
1 parent 6b8d75f commit 5fb35fbc783516e2014115c3488134a2afb8494c
Showing with 14 additions and 1 deletion.
  1. +14 −1 src/basic/random-util.c
@@ -34,6 +34,7 @@ int rdrand(unsigned long *ret) {

#if defined(__i386__) || defined(__x86_64__)
static int have_rdrand = -1;
unsigned long v;
unsigned char err;

if (have_rdrand < 0) {
@@ -53,12 +54,24 @@ int rdrand(unsigned long *ret) {

asm volatile("rdrand %0;"
"setc %1"
: "=r" (*ret),
: "=r" (v),
"=qm" (err));
msan_unpoison(&err, sizeof(err));
if (!err)
return -EAGAIN;

/* Apparently on some AMD CPUs RDRAND will sometimes (after a suspend/resume cycle?) report success
* via the carry flag but nonetheless return the same fixed value -1 in all cases. This appears to be
* a bad bug in the CPU or firmware. Let's deal with that and work-around this by explicitly checking
* for this special value (and also 0, just to be sure) and filtering it out. This is a work-around
* only however and something AMD really should fix properly. The Linux kernel should probably work
* around this issue by turning off RDRAND altogether on those CPUs. See:
* */
if (v == 0 || v == ULONG_MAX)
return log_debug_errno(SYNTHETIC_ERRNO(EUCLEAN),
"RDRAND returned suspicious value %lx, assuming bad hardware RNG, not using value.", v);

*ret = v;
return 0;

0 comments on commit 5fb35fb

Please sign in to comment.
You can’t perform that action at this time.