From: Michael Biebl Date: Tue, 14 May 2019 13:12:35 +0200 Subject: random-util: eat up bad RDRAND values seen on AMD CPUs An ugly, ugly work-around for #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: #11810 (cherry picked from commit 1c53d4a070edbec8ad2d384ba0014d0eb6bae077) --- src/basic/random-util.c | 15 ++++++++++++++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/src/basic/random-util.c b/src/basic/random-util.c index f7decf6..38f8180 100644 --- a/src/basic/random-util.c +++ b/src/basic/random-util.c @@ -37,6 +37,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) { @@ -56,7 +57,7 @@ int rdrand(unsigned long *ret) { asm volatile("rdrand %0;" "setc %1" - : "=r" (*ret), + : "=r" (v), "=qm" (err)); #if HAS_FEATURE_MEMORY_SANITIZER @@ -66,6 +67,18 @@ int rdrand(unsigned long *ret) { 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: + * https://github.com/systemd/systemd/issues/11810 */ + 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; #else return -EOPNOTSUPP;