[libvirt] should we use new Linux syscall getrandom(2)?

Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation? -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Tue, Dec 09, 2014 at 08:03:13AM -0700, Eric Blake wrote:
Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation?
Yes, we should. I remember reading a few weeks back that someone found our current random seed is rather predictable when the libvirt host is booted from a cut-down image running systemd. Since there is no longer 1000000000 lines of shell in the init process the initial PIDs are very stable across each boot attempt. The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ? Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 12/09/2014 08:07 AM, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 08:03:13AM -0700, Eric Blake wrote:
Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation?
Yes, we should. I remember reading a few weeks back that someone found our current random seed is rather predictable when the libvirt host is booted from a cut-down image running systemd. Since there is no longer 1000000000 lines of shell in the init process the initial PIDs are very stable across each boot attempt.
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
I think using it just to set the seed is sufficient - I don't know if using ALL our random bits from the syscall would drain resources that might starve other processes, and we are leaving the crypto code to libraries that probably have their own rules on how they get their random values secure enough for their needs. So minimizing our use to just the seeding process will play nicer with other processes, give us less predictability at startup, and still be something that we can easily override during debugging to get a fixed random sequence if it is ever needed (we have some #if code that is normally off, but can be turned on to generated a repeatable sequence from a fixed seed; using the syscall all the time would defeat that if we ever hit a situation of needing fixed-sequence debugging). -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Tue, Dec 09, 2014 at 08:17:24AM -0700, Eric Blake wrote:
On 12/09/2014 08:07 AM, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 08:03:13AM -0700, Eric Blake wrote:
Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation?
Yes, we should. I remember reading a few weeks back that someone found our current random seed is rather predictable when the libvirt host is booted from a cut-down image running systemd. Since there is no longer 1000000000 lines of shell in the init process the initial PIDs are very stable across each boot attempt.
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
I think using it just to set the seed is sufficient - I don't know if using ALL our random bits from the syscall would drain resources that might starve other processes, and we are leaving the crypto code to libraries that probably have their own rules on how they get their random values secure enough for their needs. So minimizing our use to just the seeding process will play nicer with other processes, give us less predictability at startup, and still be something that we can easily override during debugging to get a fixed random sequence if it is ever needed (we have some #if code that is normally off, but can be turned on to generated a repeatable sequence from a fixed seed; using the syscall all the time would defeat that if we ever hit a situation of needing fixed-sequence debugging).
Agreed, that sounds reasonable Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 09.12.2014 16:07, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 08:03:13AM -0700, Eric Blake wrote:
Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation?
Yes, we should. I remember reading a few weeks back that someone found our current random seed is rather predictable when the libvirt host is booted from a cut-down image running systemd. Since there is no longer 1000000000 lines of shell in the init process the initial PIDs are very stable across each boot attempt.
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
Well, consider that libvirt might be run in a VM with snapshot. IIUC nowadays when the VM is started from the snapshot virRandomBits() produces the same sequence. If we want to prevent that we must use the new syscall every time the virRandomBits() is called. I'm afraid using the syscall just to set the seed won't be sufficient. Michal

On Tue, Dec 09, 2014 at 05:29:51PM +0100, Michal Privoznik wrote:
On 09.12.2014 16:07, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 08:03:13AM -0700, Eric Blake wrote:
Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation?
Yes, we should. I remember reading a few weeks back that someone found our current random seed is rather predictable when the libvirt host is booted from a cut-down image running systemd. Since there is no longer 1000000000 lines of shell in the init process the initial PIDs are very stable across each boot attempt.
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
Well, consider that libvirt might be run in a VM with snapshot. IIUC nowadays when the VM is started from the snapshot virRandomBits() produces the same sequence. If we want to prevent that we must use the new syscall every time the virRandomBits() is called. I'm afraid using the syscall just to set the seed won't be sufficient.
If you are restoring a VM from a snapshot, the entropy pool for /dev/random will have been preseved too, so you'll still have the same problem. This is just one of 100's of examples of why you should never try to use snapshots as the basis for forking multiple independant VM instances. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 09.12.2014 17:36, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 05:29:51PM +0100, Michal Privoznik wrote:
On 09.12.2014 16:07, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 08:03:13AM -0700, Eric Blake wrote:
Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation?
Yes, we should. I remember reading a few weeks back that someone found our current random seed is rather predictable when the libvirt host is booted from a cut-down image running systemd. Since there is no longer 1000000000 lines of shell in the init process the initial PIDs are very stable across each boot attempt.
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
Well, consider that libvirt might be run in a VM with snapshot. IIUC nowadays when the VM is started from the snapshot virRandomBits() produces the same sequence. If we want to prevent that we must use the new syscall every time the virRandomBits() is called. I'm afraid using the syscall just to set the seed won't be sufficient.
If you are restoring a VM from a snapshot, the entropy pool for /dev/random will have been preseved too, so you'll still have the same problem. This is just one of 100's of examples of why you should never try to use snapshots as the basis for forking multiple independant VM instances.
Correct. But after some time (and some packets, keypresses and mouse movements too) both the syscall and the /dev/random will produce unpredictable sequence. But that's not the case for our RNG. What I'm saying is, if we feel that our RNG is not good enough we should use a better one. Improving seed setting is just deferring problem. Although I can live with Eric's approach too. Michal

On Tue, Dec 09, 2014 at 05:46:54PM +0100, Michal Privoznik wrote:
On 09.12.2014 17:36, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 05:29:51PM +0100, Michal Privoznik wrote:
On 09.12.2014 16:07, Daniel P. Berrange wrote:
On Tue, Dec 09, 2014 at 08:03:13AM -0700, Eric Blake wrote:
Now that Linux has a syscall for getting secure random bytes, should we use that when available in our src/util/virrandom.c implementation?
Yes, we should. I remember reading a few weeks back that someone found our current random seed is rather predictable when the libvirt host is booted from a cut-down image running systemd. Since there is no longer 1000000000 lines of shell in the init process the initial PIDs are very stable across each boot attempt.
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
Well, consider that libvirt might be run in a VM with snapshot. IIUC nowadays when the VM is started from the snapshot virRandomBits() produces the same sequence. If we want to prevent that we must use the new syscall every time the virRandomBits() is called. I'm afraid using the syscall just to set the seed won't be sufficient.
If you are restoring a VM from a snapshot, the entropy pool for /dev/random will have been preseved too, so you'll still have the same problem. This is just one of 100's of examples of why you should never try to use snapshots as the basis for forking multiple independant VM instances.
Correct. But after some time (and some packets, keypresses and mouse movements too) both the syscall and the /dev/random will produce unpredictable sequence. But that's not the case for our RNG. What I'm saying is, if we feel that our RNG is not good enough we should use a better one. Improving seed setting is just deferring problem. Although I can live with Eric's approach too.
I don't think we are saying the RNG is not good enough. We're saying the way we initialize it when libvirtd starts is not good enough. Basically two libvirtd processes started on identical OS instances should not get the same random numbers. Giving a good seed achieves that. Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|

On 12/09/2014 09:49 AM, Daniel P. Berrange wrote:
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
Well, consider that libvirt might be run in a VM with snapshot. IIUC nowadays when the VM is started from the snapshot virRandomBits() produces the same sequence. If we want to prevent that we must use the new syscall every time the virRandomBits() is called. I'm afraid using the syscall just to set the seed won't be sufficient.
Forking two guests from the same point in time is NOT my concern with this proposal (when forking, you should already be coordinating with the forks to clear their entropy pool; virt-sysprep can do this). Rather, this is about making libvirtd startup use a better seed, when it can.
If you are restoring a VM from a snapshot, the entropy pool for /dev/random will have been preseved too, so you'll still have the same problem. This is just one of 100's of examples of why you should never try to use snapshots as the basis for forking multiple independant VM instances.
Correct. But after some time (and some packets, keypresses and mouse movements too) both the syscall and the /dev/random will produce unpredictable sequence. But that's not the case for our RNG. What I'm saying is, if we feel that our RNG is not good enough we should use a better one.
It's not our RNG that is bad, just our seeding.
Improving seed setting is just deferring problem. Although I can live with Eric's approach too.
I don't think we are saying the RNG is not good enough. We're saying the way we initialize it when libvirtd starts is not good enough. Basically two libvirtd processes started on identical OS instances should not get the same random numbers. Giving a good seed achieves that.
Furthermore, my biggest reason for using getrandom(2) _only_ for the seed is that this is the documentation recommended by the syscall itself: http://lists.openwall.net/linux-kernel/2014/07/17/235 The system call getrandom() fills the buffer pointed to by buf with up to buflen random bytes which can be used to seed user space random number generators (i.e., DRBG's) or for other cryptographic processes. It should not be used Monte Carlo simulations or for other probabilistic sampling applications. We do NOT want to be draining /dev/[u]random on every call, but merely seeding our PRNG sufficiently that the rest of our random bits are decently "random" because the seed was unpredictable. -- Eric Blake eblake redhat com +1-919-301-3266 Libvirt virtualization library http://libvirt.org

On Tue, Dec 09, 2014 at 12:57:25PM -0700, Eric Blake wrote:
On 12/09/2014 09:49 AM, Daniel P. Berrange wrote:
The question is how should we make use of it ? Should we use it as the seed for initstate_r, or just use it for virRandomBits directly ?
Well, consider that libvirt might be run in a VM with snapshot. IIUC nowadays when the VM is started from the snapshot virRandomBits() produces the same sequence. If we want to prevent that we must use the new syscall every time the virRandomBits() is called. I'm afraid using the syscall just to set the seed won't be sufficient.
Forking two guests from the same point in time is NOT my concern with this proposal (when forking, you should already be coordinating with the forks to clear their entropy pool; virt-sysprep can do this). Rather, this is about making libvirtd startup use a better seed, when it can.
If you are restoring a VM from a snapshot, the entropy pool for /dev/random will have been preseved too, so you'll still have the same problem. This is just one of 100's of examples of why you should never try to use snapshots as the basis for forking multiple independant VM instances.
Correct. But after some time (and some packets, keypresses and mouse movements too) both the syscall and the /dev/random will produce unpredictable sequence. But that's not the case for our RNG. What I'm saying is, if we feel that our RNG is not good enough we should use a better one.
It's not our RNG that is bad, just our seeding.
Improving seed setting is just deferring problem. Although I can live with Eric's approach too.
I don't think we are saying the RNG is not good enough. We're saying the way we initialize it when libvirtd starts is not good enough. Basically two libvirtd processes started on identical OS instances should not get the same random numbers. Giving a good seed achieves that.
Furthermore, my biggest reason for using getrandom(2) _only_ for the seed is that this is the documentation recommended by the syscall itself:
http://lists.openwall.net/linux-kernel/2014/07/17/235
The system call getrandom() fills the buffer pointed to by buf with up to buflen random bytes which can be used to seed user space random number generators (i.e., DRBG's) or for other cryptographic processes. It should not be used Monte Carlo simulations or for other probabilistic sampling applications.
We do NOT want to be draining /dev/[u]random on every call, but merely seeding our PRNG sufficiently that the rest of our random bits are decently "random" because the seed was unpredictable.
Speaking with Florian Weimer about this, he suggests that we might be better off not using any of the POSIX rand functions at all, and instead using the random number source from a crypto library, which would be gnutls in our case. We allow compilation without gnutls, so guess we'd need to keep the current code as fallback, but if we can use a cryptographically strong RNG by default that sounds like a nice idea - assuming it isn't simply a facade for /dev/urandom :-) http://docs.fedoraproject.org/en-US/Fedora_Security_Team/1/html/Defensive_Co... Regards, Daniel -- |: http://berrange.com -o- http://www.flickr.com/photos/dberrange/ :| |: http://libvirt.org -o- http://virt-manager.org :| |: http://autobuild.org -o- http://search.cpan.org/~danberr/ :| |: http://entangle-photo.org -o- http://live.gnome.org/gtk-vnc :|
participants (3)
-
Daniel P. Berrange
-
Eric Blake
-
Michal Privoznik