Bug 1074464 - /dev/urandom not available for virtio-rng
Summary: /dev/urandom not available for virtio-rng
Keywords:
Status: CLOSED UPSTREAM
Alias: None
Product: Virtualization Tools
Classification: Community
Component: libvirt
Version: unspecified
Hardware: Unspecified
OS: Linux
unspecified
medium
Target Milestone: ---
Assignee: Libvirt Maintainers
QA Contact:
URL:
Whiteboard:
Depends On:
Blocks: 1257671 1347642 1347669 1374227
TreeView+ depends on / blocked
 
Reported: 2014-03-10 10:12 UTC by Michael Samuel
Modified: 2016-09-08 09:51 UTC (History)
18 users (show)

Fixed In Version:
Doc Type: Bug Fix
Doc Text:
Clone Of:
Environment:
Last Closed: 2016-04-26 15:47:53 UTC


Attachments (Terms of Use)
Patch to allow /dev/urandom and make it default for virtio-rng "random" backend. (3.24 KB, patch)
2014-03-10 23:18 UTC, Michael Samuel
no flags Details | Diff
fake entropy generation (non-)daemon (6.73 KB, text/plain)
2015-09-14 14:46 UTC, Jiri Jaburek
no flags Details

Description Michael Samuel 2014-03-10 10:12:17 UTC
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.

Comment 1 Daniel Berrangé 2014-03-10 10:49:27 UTC
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.

http://lists.gnu.org/archive/html/qemu-devel/2013-03/msg00542.html
http://lists.gnu.org/archive/html/qemu-devel/2013-03/msg00123.html

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.

Comment 2 Michael Samuel 2014-03-10 11:07:44 UTC
/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.

Comment 3 Daniel Berrangé 2014-03-10 11:10:24 UTC
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.

Comment 4 Michael Samuel 2014-03-10 11:49:06 UTC
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.

Comment 5 Daniel Berrangé 2014-03-10 11:53:40 UTC
As I've said before, this is based on the recommendations from QEMU / Kernel guys who are the experts in this area.

Comment 6 Daniel Berrangé 2014-03-10 12:10:01 UTC
http://lists.gnu.org/archive/html/qemu-devel/2012-09/msg02387.html

"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."

Comment 7 Michael Samuel 2014-03-10 12:21:57 UTC
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.

Comment 8 Michael Samuel 2014-03-10 23:18:38 UTC
Created attachment 872882 [details]
Patch to allow /dev/urandom and make it default for virtio-rng "random" backend.

Comment 9 Daniel Berrangé 2014-03-11 10:00:50 UTC
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

Comment 10 Michael Samuel 2014-03-11 10:11:14 UTC
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"
> backend.
> 
> Per above discussion this patch is fundamentally flawed and will not be
> applied

Comment 11 Jiri Jaburek 2015-09-14 14:45:51 UTC
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.

Comment 12 Jiri Jaburek 2015-09-14 14:46:45 UTC
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:
    <rng model='virtio'>
      <rate bytes='1024' period='10'/>
      <backend model='egd' type='tcp'>
        <source mode='connect' host='127.0.0.1' service='4999'/>
        <protocol type='raw'/>
      </backend>
    </rng>

Comment 13 Hubert Kario 2015-09-14 16:42:06 UTC
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[1] 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://www.mail-archive.com/cryptography@randombit.net/msg04763.html

Comment 14 Steve Grubb 2015-09-15 15:21:52 UTC
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.

Comment 15 Michal Karm Babacek 2015-09-24 12:06:50 UTC
Hmm, I was astonished to find out that 
><rng model='virtio'>
> <backend model='random'>/dev/urandom</backend>
></rng>
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 :-)

Cheers
-K-

libvirt-1.1.3.9
virt-manager-1.0.1

Comment 16 Amit Shah 2016-04-15 08:03:18 UTC
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.

Comment 17 Richard W.M. Jones 2016-04-15 08:11:12 UTC
Unfortunately glibc hasn't wired up getrandom() support yet.

https://bugzilla.redhat.com/show_bug.cgi?id=1172273
https://sourceware.org/bugzilla/show_bug.cgi?id=17252

You can work around this using syscall() but it's a big pain.

Comment 18 Cole Robinson 2016-04-15 10:48:05 UTC
I started a thread to discuss:

http://www.redhat.com/archives/libvir-list/2016-April/msg00987.html

Everyone here should be CCd

Comment 19 Cole Robinson 2016-04-23 18:49:57 UTC
Patch posted to drop the libvirt whitelisting:

http://www.redhat.com/archives/libvir-list/2016-April/msg01362.html

Comment 20 Cole Robinson 2016-04-26 15:47:53 UTC
The patch is upstream now:

commit 67f2b72723c242969c5282fcb9acf00cc01f2a54
Author: Cole Robinson <crobinso@redhat.com>
Date:   Wed Apr 13 15:09:30 2016 -0400

    conf: Drop restrictions on rng backend path

Comment 21 Yaniv Kaul 2016-06-13 06:42:54 UTC
Upstream documentation (https://libvirt.org/formatdomain.html#elementsRng) doesn't mention it. Not sure from which version it's available.

Comment 22 Cole Robinson 2016-06-13 12:45:45 UTC
Fixed in version v1.3.4

Comment 23 Ján Tomko 2016-06-14 13:15:53 UTC
Proposed patch to document the version in formatdomain.html:
https://www.redhat.com/archives/libvir-list/2016-June/msg00904.html


Note You need to log in before you can comment on or make changes to this bug.