When creating a virtio-rng device, libvirt rejects /dev/urandom as a source, and requires either /dev/hwrng or /dev/random.
This is incorrect behaviour on Linux systems - /dev/urandom is appropriate for generating secure random numbers.
Since /dev/random needlessly blocks, guests can perform a DoS on each other's virtio-rng access, which could result in serious security consequences, such as thin-clones generating their long-term secrets using non-secret RNG state.
virtio-rng does not want secure random numbers as its data source, it wants actual entropy. Using /dev/urandom in the host would be feeding the output of a PRNG into the guest's PRNG and claiming it was entropy which is very wrong. Don't take my word for it - the Linux PRNG maintainer, Peter Anvin, explicitly says that using /dev/urandom with virtio-rng is wrong.
If you're concerned about starvation there is rate limiting ability with virtio-rng config or you can hook it up to a egd daemon.
/dev/random is also a PRNG (the same PRNG in fact), it just does weird blocking stuff due to the author's misunderstanding of entropy.
/dev/urandom behaves well enough, and is far more suitable for providing seeds to guests - which is what most people using virtio-rng need.
We're not changing this unless Peter Anvin changes his recommendation, which currently states that we should not use /dev/urandom, so please take this upstream to qemu-devel / lkml mailing lists if you disagree with his assertion that /dev/urandom should not be used for virtio-rng.
You may take his (silly) recommendation if you want, but the enforcing it in code is unproductive and prevents secure guest cloning.
Please check with the security team before re-closing.
As I've said before, this is based on the recommendations from QEMU / Kernel guys who are the experts in this area.
"Using /dev/urandom is a very serious cryptographic error, as well as completely pointless.
The whole point of this is to provided distilled entropy to the guest, so that it can seed true entropy into *its* entropy pool. As such, using /dev/urandom is:
a) needlessly slow. It will churn the host kernel PRNG needlessly,
and not provide any backpressure when the host pool is already
drained. Using /dev/random instead will indicate that the host
pool is drained, and not pass a bunch of PRNG noise across an
expensive channel when the PRNG in the *guest* could do the PRNG
expansion just as well.
b) cryptographically incorrect. This will tell the guest that it
is being provided with entropy that it doesn't actually have, which
will mean the guest severely overestimates the entropy that it has
available to it. To put it differently: /dev/random in the guest
will behave like (a very expensive version of) /dev/urandom from
a cryptographic point of view.
The right interface to the host kernel, therefore, is /dev/random."
This is nonsensical and not based on actual cryptographic knowledge.
Point (a) - there's rate-limiting code there, that can be used if needed.
Point (b) - they're both PRNGs. The concept of counting consumed entropy is superstition.
If /dev/urandom is an insecure PRNG, then it's not safe to use anywhere. If it is, then it's safe to use here.
Created attachment 872882 [details]
Patch to allow /dev/urandom and make it default for virtio-rng "random" backend.
Comment on attachment 872882 [details]
Patch to allow /dev/urandom and make it default for virtio-rng "random" backend.
Per above discussion this patch is fundamentally flawed and will not be applied
Could you please review on the assumption that you (and the other authorities you seem to have placed trust in) are wrong? That would be most appreciated.
(In reply to Daniel Berrange from comment #9)
> Comment on attachment 872882 [details]
> Patch to allow /dev/urandom and make it default for virtio-rng "random"
> Per above discussion this patch is fundamentally flawed and will not be
I have to agree with Michael Samuel (as well as other kernel crypto experts) - once the nonblocking pool is seeded, /dev/urandom is considered safe. This is however badly conveyed through manpages, so there's widespread confusion about urandom being insecure - the only solution is to go read drivers/char/random.c, I guess. Or the many discussions on getrandom()/getentropy() where people reiterate this fact.
Regardless, I believe the default should still be /dev/random as it matches the intended behavior more closely. However artificially limiting the user is IMHO wrong here - libvirt should allow /dev/urandom or any other char device, just not as default.
One of the use cases I have is non-production (testing) systems with lifetime in minutes where the quality of the random data doesn't matter, but focus is rather placed on speed.
Since libvirt allows using the egd daemon, I wrote my own (C) implementation of a "fake egd", providing random data from any char device or fifo via the egd protocol (attached), which can be used as an ugly workaround, but I believe the correct solution is the one mentioned above.
Please consider reopening the bug.
Created attachment 1073278 [details]
fake entropy generation (non-)daemon
(start as "./fake_egd 127.0.0.1 4999 /dev/urandom &" from ie. rc.local)
example xml snippet:
<rate bytes='1024' period='10'/>
<backend model='egd' type='tcp'>
<source mode='connect' host='127.0.0.1' service='4999'/>
After seeding both /dev/random and /dev/urandom provide cryptographically secure random numbers. And we *do* seed them very early in the boot process, it would be a *very* serious vulnerability if we didn't.
The only difference between them is that /dev/random is guaranteed to provide you with *fresh* entropy, not with better entropy. Both will generate cryptographically secure random numbers after initial seeding was performed.
That's why this is the default behaviour of the newly introduced syscall: getrandom(2) - block before enough entropy gathered, never block after.
As Daniel Bernstein said (a.k.a. djb):
Cryptographers are certainly not responsible for this superstitious
nonsense. Think about this for a moment: whoever wrote the /dev/random
manual page seems to simultaneously believe that
(1) we can't figure out how to deterministically expand one 256-bit
/dev/random output into an endless stream of unpredictable keys
(this is what we need from urandom), but
(2) we _can_ figure out how to use a single key to safely encrypt
many messages (this is what we need from SSL, PGP, etc.).
For a cryptographer this doesn't even pass the laugh test.
Thus enforcing use of /dev/random is misguided at best and most likely actively damaging as users will try to overcome this limitation with dubious code.
More explanations you can read at http://www.2uo.de/myths-about-urandom/
1 - https://firstname.lastname@example.org/msg04763.html
In my opinion, we should not be limiting the solution to /dev/random. Just allow the sysadmin to pick their source. Put a warning in syslog if you feel strongly. I don't know if /dev/hwrng is blocked also. People should be able to whatever source they have a tolerance for.
Hmm, I was astonished to find out that
> <backend model='random'>/dev/urandom</backend>
breaks the config. I thought I had something wrong with my host system.
If there was an upvote button on bugzilla, I would have pressed it with this one :-)
For upstream qemu, we should also change the default to using getrandom(), and get rid of the confusion entirely.
hpa was difficult to convince upstream, but we have enough research to show the output of /dev/urandom is (a) good to use, (b) not any worse than /dev/random.
We can have libvirt use /dev/random by default, but let's remove the restriction to not use /dev/urandom.
Also, once upstream qemu gets getrandom() support, libvirt should switch to that.
Unfortunately glibc hasn't wired up getrandom() support yet.
You can work around this using syscall() but it's a big pain.
I started a thread to discuss:
Everyone here should be CCd
Patch posted to drop the libvirt whitelisting:
The patch is upstream now:
Author: Cole Robinson <email@example.com>
Date: Wed Apr 13 15:09:30 2016 -0400
conf: Drop restrictions on rng backend path
Upstream documentation (https://libvirt.org/formatdomain.html#elementsRng) doesn't mention it. Not sure from which version it's available.
Fixed in version v1.3.4
Proposed patch to document the version in formatdomain.html: