This is the mail archive of the
libc-alpha@sourceware.org
mailing list for the glibc project.
Re: [PATCH] Add getrandom implementation [BZ #17252]
- From: Florian Weimer <fweimer at redhat dot com>
- To: Joseph Myers <joseph at codesourcery dot com>
- Cc: libc-alpha at sourceware dot org
- Date: Sat, 11 Jun 2016 13:13:29 +0200
- Subject: Re: [PATCH] Add getrandom implementation [BZ #17252]
- Authentication-results: sourceware.org; auth=none
- References: <20160610210303 dot 6CE3E40141175 at oldenburg dot str dot redhat dot com> <alpine dot DEB dot 2 dot 20 dot 1606102115300 dot 20503 at digraph dot polyomino dot org dot uk>
On 06/10/2016 11:30 PM, Joseph Myers wrote:
Are we sure we want to keep file descriptors open that the application
can't use? Is it not valid for applications to close all open file
descriptors, or do you think that's only valid on startup before these
functions have been called?
I assumed closing file descriptors is only valid right before an execve.
But I see that historically, we have avoid really hard to keep open
file descriptors not explicitly requested by the application. The
socket for communicating with nscd is one such example. We also do not
keep open Netlink sockets to receive kernel notifications about
configuration changes (which would allow us to skip costly interface
enumeration, at least in theory if the notifications were reliable).
Clearly, we have a requirement that the application doesn't go beyond
the back of the library and unmaps memory regions. I assumed a similar
rule existed for file descriptors. A lot of other libraries use file
descriptors internally as well, so this is certainly a de-facto
requirement for most applications. But it may be the case that glibc
itself cannot rely on this.
Keeping open the file descriptors is not just a performance
optimization. It may be necessary for supporting getrandom after a
chroot call, and one explicitly stated goal of adding the system call
was preventing file descriptor starvation attacks. We also had an
implementation of OpenSSL's RAND_bytes function which did not return the
correct success/failure flags, and that wasn't noticed by anyone.
Apparently, programmers do not check for error returns from random
number generators. Based on that, I concluded it was important to
provide an implementation which cannot fail.
On the other hand, application developers are not expected to call
getrandom (or getentropy) directly. In our implementation, this
depletes the overall entropy pool, and it is also rather slow. The
OpenBSD interface intended for application use is called arc4random (for
historical reasons). Implementing arc4random has both libc aspects
(providing thread safety and invalidating the internal state around
clone/fork) and cryptographic aspects (for performance reasons, it has
to be a deterministic random bit generator, and use the kernel for
seeding only). I think the cryptographic aspect dominates, which is why
it is difficult to implement arc4random as part of glibc.
So a completely different approach would be to provide a thin wrapper
around getrandom, not its limitations, and tell applications to use a
cryptographic library if they need a stream of randomness.
But then, we have lots of of libraries which need 32 or 64 bits to
initialize a keyed hash function to avoid hash collision denial of
service attacks. (The key is set just once and shared across hash
tables.) For this purpose, it is acceptable to call getrandom and get
the bits from the kernel, and it makes sense for glibc to provide
emulation so that the function is always available, simply we cannot
provide arc4random.
Thank you for your other comments, they are helpful.
Florian