diff mbox

Add getrandom implementation [BZ #17252]

Message ID 20160610210303.6CE3E40141175@oldenburg.str.redhat.com
State New
Headers show

Commit Message

Florian Weimer June 10, 2016, 9:03 p.m. UTC
The emulation opens /dev/random and /dev/urandom and uses
these descriptors.  There are safeguards to detect application
which have overridden these descriptors.

The getrandom function is defined as a macro in such a way that
a direct attempt to define a getrandom function will either
fail to compile, or fail to interpose the __getrandom symbol.
The intent is that legacy implementations will not accidentally
preempt the implementation in libc (which could well be used
by other libraries in the same process image).

2016-06-10  Florian Weimer  <fweimer@redhat.com>

	[BZ #17252]
	* posix/Makefile (routines): Add getrandom.
	(tests): Add tst-getrandom.
	* posix/getrandom.c: New file.
	* posix/getrandom_emulation.c: Likewise.
	* posix/tst-getrandom.c: Likewise.
	* posix/Versions (GLIBC_2.24.getrandom): Add getrandom,
	__getrandom.
	* posix/unistd.h (__getrandom): Declare.
	(getrandom): Define.
	* sysdeps/unix/sysv/linux/kernel-features.h
	(__ASSUME_GETRANDOM_SYSCALL): Define.

Comments

Joseph Myers June 10, 2016, 9:30 p.m. UTC | #1
On Fri, 10 Jun 2016, Florian Weimer wrote:

> The emulation opens /dev/random and /dev/urandom and uses
> these descriptors.  There are safeguards to detect application
> which have overridden these descriptors.

I think a substantial comment somewhere is needed explaining these 
safeguards and the rationale for them.

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?

New functions need documentation in the manual, and a NEWS entry.

> +  # We use a dedicated symbol version so that we can scan the
> +  # .gnu.version_r section to identify binaries which use the
> +  # getrandom function.  This allows us to avoid lazy opening of the
> +  # emulation file descriptors if this proves too error-prone.

I understand this even less than the other safeguards.  Why is this 
different from all other functions?  What is "us"?  I don't see any 
special dynamic linker code to check for this version, for example.

> +
> +ssize_t
> +__getrandom (void *buffer, size_t length, unsigned flags)

Missing comment above function definition.  We use "unsigned int" not 
plain "unsigned".

I'm not sure quite why this code is going in posix/, or the declaration in 
unistd.h.  It's not a POSIX function, or particularly closely related to 
one.  There's an Austin Group discussion of such interfaces 
<http://austingroupbugs.net/view.php?id=859>, but no real sign that 
anything like that would end up in the next major POSIX revision, and all 
the proposal there use <stdlib.h>.

> diff --git a/posix/getrandom_emulation.c b/posix/getrandom_emulation.c

Lots more functions here missing comments.

> +static int
> +getrandom_validate_fd
> +  (const char *device, int fd, struct getrandom_emulation_fd *pfd)

That's not how we wrap prototypes.

static int
getrandom_validate_fd (const char *device, int fd,
		       struct getrandom_emulation_fd *pfd)

would be more normal style.

> +static int
> +getrandom_move_fd_target (int fd, int target)
> +{
> +  int newfd = fcntl_not_cancel (fd, F_DUPFD, target);

I'd expect F_DUPFD_CLOEXEC to be used here if available (maybe always 
available?).

> +      {
> +        int flags = O_RDONLY;
> +        if (nonblock)
> +          flags |= O_NONBLOCK;
> +        fd = open_not_cancel (device, flags, 0);

And O_CLOEXEC here.

> +#ifdef __USE_GNU
> +/* Flags for use with  getrandom.  */
> +# define GRND_NONBLOCK 1
> +# define GRND_RANDOM 2
> +
> +ssize_t __getrandom (void *__buffer, size_t __length, unsigned __flags);
> +#define getrandom(buffer, length, flags) \
> +  (0 + __getrandom (buffer, length, flags))

Missing comment on function prototype.
Joseph Myers June 10, 2016, 9:36 p.m. UTC | #2
On Fri, 10 Jun 2016, Joseph Myers wrote:

> > +  # We use a dedicated symbol version so that we can scan the
> > +  # .gnu.version_r section to identify binaries which use the
> > +  # getrandom function.  This allows us to avoid lazy opening of the
> > +  # emulation file descriptors if this proves too error-prone.
> 
> I understand this even less than the other safeguards.  Why is this 
> different from all other functions?  What is "us"?  I don't see any 
> special dynamic linker code to check for this version, for example.

And, what happens to this version for new ports where GLIBC_2.25 or later 
is the minimum symbol version?  And what inheritance relations does it 
have with other symbol versions (not that I'm clear on what significance 
the inheritance relations actually have)?

Versioning a symbol in a way different from all our other symbol 
versioning seems high-risk and needs a compelling justification.
Paul Eggert June 10, 2016, 10 p.m. UTC | #3
On 06/10/2016 02: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

Yes, it's valid.

How about if we use a simpler implementation instead, one that opens, 
reads, and closes /dev/whatever each time getrandom is called? That 
would be a bit slower slower but would avoid this problem and probably 
other problems.

Performance should not the overriding goal here, as anybody who wants 
lots of random numbers efficiently shouldn't be using getrandom, 
regardless of whether it is a syscall.
Joseph Myers June 10, 2016, 10:06 p.m. UTC | #4
On Fri, 10 Jun 2016, Paul Eggert wrote:

> How about if we use a simpler implementation instead, one that opens, reads,
> and closes /dev/whatever each time getrandom is called? That would be a bit
> slower slower but would avoid this problem and probably other problems.

That would certainly be my preference.  (You still need O_CLOEXEC on the 
open, as for all cases where file descriptors are used internally in 
glibc, to avoid leaking file descriptors to concurrent fork and exec from 
other threads.)

It's in the nature of this code - returning cryptographically-secure 
random numbers - to be used in security-critical places.  And for such 
code, there are advantages to being simple enough to be obviously safe and 
not to need lots of complicated defensive code.
Roland McGrath June 10, 2016, 10:15 p.m. UTC | #5
You need to start with rationale justifying the new nonstandard API and why
it belongs in libc, let alone why it should litter a POSIX-standard header.
Joseph Myers June 10, 2016, 10:40 p.m. UTC | #6
On Fri, 10 Jun 2016, Roland McGrath wrote:

> You need to start with rationale justifying the new nonstandard API and why
> it belongs in libc, let alone why it should litter a POSIX-standard header.

Also compare and contrast the BSD-compatible getentropy, which was also 
requested in the bug referenced.
Roland McGrath June 10, 2016, 10:45 p.m. UTC | #7
As a general procedure thing, I'd recommend that for all new API additions
the first concrete patch should be one that just adds the declaration,
ENOSYS stub implementation (including Versions file additions), and
documentation.  Such a patch can be a reasonable starting point for
discussion about the API if the person starting the discussion prefers it
to just starting a discussion thread code about an abstract idea.  But we
should settle API issues and achieve consensus on adding the API at all and
its details (function signatures, etc.) before dealing with reviewing
implementation issues.


Thanks,
Roland
Florian Weimer June 11, 2016, 11:13 a.m. UTC | #8
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
Paul Eggert June 11, 2016, 8:10 p.m. UTC | #9
On 06/11/2016 04:13 AM, Florian Weimer wrote:
> 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.

Yes, as an app developer I prefer primitives like OpenBSD arc4random_buf 
that are always successful. In contrast, Linux getrandom (BUF, LEN, 0) 
is guaranteed to succeed only when called with LEN <= 256, which is good 
enough for hash nonces but not for general-purpose use.

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

Sorry, I don't understand. What's the difficulty? Why can't glibc 
implement the cryptographic aspect of arc4random_buf via an internal 
deterministic random bit generator? Can't glibc borrow a bit generator 
from Internet RFC 7539, or from GNU Coreutils, or whatever?
Florian Weimer June 23, 2016, 5:20 p.m. UTC | #10
On 06/11/2016 12:15 AM, Roland McGrath wrote:
> You need to start with rationale justifying the new nonstandard API and why
> it belongs in libc,

Based on the last discussion, I assumed that we had consensus that we'd 
add wrappers for system calls which do not have merely niche applications.

There are about a dozen widely used cryptographic libraries on GNU/Linux 
which would use the system call to seed their PRNGs.  The /dev/urandom 
interface is considered insufficient, due to the boot-time 
initialization issue, and due to the potential unavailability of the 
device node.

In addition, many libraries need a one-time entropy source to initialize 
cookies (like our stack guard), or keys for randomized hash tables.

 > let alone why it should litter a POSIX-standard header.

We can certainly put into something like <sys/random.h>.

But if there is no consensus to evolve the Linux-specific glibc API, I 
don't know what to do.

getrandom support in glibc is requested rather often.  Here is a recent 
example:

   <https://www.python.org/dev/peps/pep-0522/>

Thanks,
Florian
Paul Eggert June 25, 2016, 9:58 p.m. UTC | #11
On 06/23/2016 07:20 PM, Florian Weimer wrote:
> getrandom support in glibc is requested rather often.

As a (mostly) application developer I'd like to second those requests. 
If glibc provided getrandom, I expect that it would be used by many GNU 
applications, e.g., GNU Emacs.
Roland McGrath Sept. 2, 2016, 10:23 p.m. UTC | #12
> Based on the last discussion, I assumed that we had consensus that we'd 
> add wrappers for system calls which do not have merely niche applications.

I don't agree with that.  getrandom is a case that is justifiable on its
own terms as a new OS-independent GNU API, so make the case that way and
don't make the API (or any more of the implementation than needs to be)
Linux-specific.
diff mbox

Patch

diff --git a/posix/Makefile b/posix/Makefile
index 5b0e298..68ad2cc 100644
--- a/posix/Makefile
+++ b/posix/Makefile
@@ -59,7 +59,8 @@  routines :=								      \
 	spawnattr_getsigmask spawnattr_getschedpolicy spawnattr_getschedparam \
 	spawnattr_setsigmask spawnattr_setschedpolicy spawnattr_setschedparam \
 	posix_madvise							      \
-	get_child_max sched_cpucount sched_cpualloc sched_cpufree
+	get_child_max sched_cpucount sched_cpualloc sched_cpufree \
+	getrandom
 
 aux		:= init-posix environ
 tests		:= tstgetopt testfnm runtests runptests	     \
@@ -90,7 +91,7 @@  tests		:= tstgetopt testfnm runtests runptests	     \
 		   bug-getopt5 tst-getopt_long1 bug-regex34 bug-regex35 \
 		   tst-pathconf tst-getaddrinfo4 tst-rxspencer-no-utf8 \
 		   tst-fnmatch3 bug-regex36 tst-getaddrinfo5 \
-		   tst-posix_spawn-fd
+		   tst-posix_spawn-fd tst-getrandom
 xtests		:= bug-ga2
 ifeq (yes,$(build-shared))
 test-srcs	:= globtest
diff --git a/posix/Versions b/posix/Versions
index bb481a5..23f2c85 100644
--- a/posix/Versions
+++ b/posix/Versions
@@ -134,6 +134,20 @@  libc {
   GLIBC_2.11 {
     execvpe;
   }
+
+  # We use a dedicated symbol version so that we can scan the
+  # .gnu.version_r section to identify binaries which use the
+  # getrandom function.  This allows us to avoid lazy opening of the
+  # emulation file descriptors if this proves too error-prone.
+  #
+  # The getrandom alias is for configure checks; applications
+  # will call __getrandom instead (through a macro wrapper,
+  # which is intended to prevent accidental interposition).
+  GLIBC_2.24.getrandom {
+    getrandom;
+    __getrandom;
+  }
+
   GLIBC_PRIVATE {
     __libc_fork; __libc_pread; __libc_pwrite;
   }
diff --git a/posix/getrandom.c b/posix/getrandom.c
new file mode 100644
index 0000000..57d18ac
--- /dev/null
+++ b/posix/getrandom.c
@@ -0,0 +1,32 @@ 
+/* Generic version of getrandom, based on emulation.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include "getrandom_emulation.c"
+
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned flags)
+{
+  return getrandom_emulation (buffer, length, flags);
+}
+
+/* We use a macro wrapper to make accidental interposition of an
+   incompatible version less likely.  The getrandom alias is provided
+   so that configure checks which do not use a proper prototype will
+   work.  */
+#undef getrandom
+strong_alias (__getrandom, getrandom)
diff --git a/posix/getrandom_emulation.c b/posix/getrandom_emulation.c
new file mode 100644
index 0000000..89886b1
--- /dev/null
+++ b/posix/getrandom_emulation.c
@@ -0,0 +1,264 @@ 
+/* Emulation of the getrandom system call.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <atomic.h>
+#include <errno.h>
+#include <fcntl.h>
+#include <not-cancel.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+#if __WORDSIZE == 32
+
+/* On 32-bit architectures, we need to split the value so that we can
+   use atomics.  */
+typedef struct
+{
+  uint32_t low;
+  uint32_t high;
+} getrandom_fd_attribute;
+
+static void
+getrandom_fd_attribute_store (getrandom_fd_attribute *target,
+                              unsigned long long source)
+{
+  atomic_store_relaxed (&target->low, (uint32_t) source);
+  atomic_store_relaxed (&target->high, (uint32_t) (source >> 32));
+}
+
+static bool
+getrandom_fd_attribute_equal (getrandom_fd_attribute *actual,
+                              unsigned long long expected)
+{
+  uint32_t expected_low = expected;
+  uint32_t expected_high = expected >> 32;
+  return atomic_load_relaxed (&actual->low) == expected_low
+    && atomic_load_relaxed (&actual->high) == expected_high;
+}
+
+#else  /* __WORDSIZE != 32 */
+
+_Static_assert (__WORDSIZE == 64, "supported word size");
+
+/* On 64-bit architectures, we can use atomics directly.  */
+typedef uint64_t getrandom_fd_attribute;
+
+static void
+getrandom_fd_attribute_store (getrandom_fd_attribute *target,
+                              getrandom_fd_attribute source)
+{
+  atomic_store_relaxed (target, source);
+}
+
+static bool
+getrandom_fd_attribute_equal (getrandom_fd_attribute *actual,
+                              getrandom_fd_attribute expected)
+{
+  return atomic_load_relaxed (actual) == expected;
+}
+
+#endif  /* __WORDSIZE */
+
+/* The size of dev_t varies across architectures.  */
+typedef __typeof__ (((struct stat64) {}).st_dev) getrandom_dev_t;
+
+_Static_assert (sizeof (getrandom_dev_t) <= sizeof (getrandom_fd_attribute),
+                "size of dev_t");
+_Static_assert (sizeof (ino64_t) <= sizeof (getrandom_fd_attribute),
+                "size of ino64_t");
+
+/* We pair each emulation file descriptor with the device and inode
+   value at the time of the open call.  This will allow us to detect
+   if an application has messed with the file descriptor.  */
+struct getrandom_emulation_fd
+{
+  int fd;
+  getrandom_fd_attribute dev;
+  getrandom_fd_attribute ino;
+};
+
+static void
+__attribute__ ((noreturn))
+getrandom_fd_failure (const char *device, const char *op, int fd)
+{
+  char descriptor[32];
+  if (fd >= 0)
+    __snprintf (descriptor, sizeof (descriptor), ", descriptor %d", fd);
+  else
+    descriptor[0] = '\0';
+  char message[128];
+  __snprintf (message, sizeof (message),
+              "Could not %s randomness source %s, error code %d%s",
+              op, device, errno, descriptor);
+  __libc_fatal (message);
+}
+
+static int
+getrandom_validate_fd
+  (const char *device, int fd, struct getrandom_emulation_fd *pfd)
+{
+  struct stat64 st;
+  if (fstat64 (fd, &st) < 0)
+    getrandom_fd_failure (device, "fstat64", fd);
+  if (getrandom_fd_attribute_equal (&pfd->dev, st.st_dev)
+      && getrandom_fd_attribute_equal (&pfd->ino, st.st_ino))
+    return fd;
+  char message[256];
+  __snprintf (message, sizeof (message),
+              "Unexpected inode for randomness source %s"
+              " (descriptor %d): %llu/%llu",
+              device, fd, (unsigned long long) st.st_dev,
+              (unsigned long long) st.st_ino);
+  __libc_fatal (message);
+}
+
+/* Try to relocate the descriptor FD to a descriptor >= TARGET.
+   Returns the new descriptor on success, or the old descriptor on
+   failure.  */
+static int
+getrandom_move_fd_target (int fd, int target)
+{
+  int newfd = fcntl_not_cancel (fd, F_DUPFD, target);
+  if (newfd >= 0)
+    close_not_cancel (fd);
+  else
+    newfd = fd;
+  return newfd;
+}
+
+/* Try to move the file descriptor FD out of the way, to make it less
+   likely that it will interfere with application use (such as the
+   select function).  Returns the file descriptor (which may have
+   changed).  */
+static int
+getrandom_move_fd (int fd)
+{
+  int newfd = getrandom_move_fd_target (fd, 1024);
+  if (newfd == fd)
+    newfd = getrandom_move_fd_target (fd, 512);
+  return newfd;
+}
+
+/* If *PFD->fd is negative, atomically replace it with a file
+   descriptor for DEVICE.  If NONBLOCK is true, make the descriptor
+   non-blocking.  Return the file descriptor.  */
+static int
+getrandom_get_fd (const char *device, struct getrandom_emulation_fd *pfd,
+                  bool nonblock)
+{
+  while (true)
+    {
+      /* Synchronize with the CAS below.  */
+      int fd = atomic_load_acquire (&pfd->fd);
+      if (fd >= 0)
+        return getrandom_validate_fd (device, fd, pfd);
+
+      /* We need to obtain a file descriptor for the random
+         device.  */
+      {
+        int flags = O_RDONLY;
+        if (nonblock)
+          flags |= O_NONBLOCK;
+        fd = open_not_cancel (device, flags, 0);
+      }
+      if (fd < 0)
+        getrandom_fd_failure (device, "open", -1);
+      fd = getrandom_move_fd (fd);
+
+      /* Obtain inode information to validate the file descriptor
+         later.  */
+      struct stat64 st;
+      if (fstat64 (fd, &st) < 0)
+        getrandom_fd_failure (device, "fstat64", fd);
+
+      /* We always write the same value, so it does not matter which
+         value is read by getrandom_validate_fd.  */
+      getrandom_fd_attribute_store (&pfd->dev, st.st_dev);
+      getrandom_fd_attribute_store (&pfd->ino, st.st_ino);
+
+      int expected = -1;
+      /* Synchronize with the atomic_load_acquire above.  */
+      if (atomic_compare_exchange_weak_release (&pfd->fd, &expected, fd))
+        return fd;
+
+      /* The CAS failed.  Close the file descriptor and try again.  */
+      close_not_cancel (fd);
+    }
+}
+
+/* The file descriptors used for emulation.  */
+static struct getrandom_emulation_fd getrandom_random_fd = { .fd = -1 };
+static struct getrandom_emulation_fd getrandom_nonblock_fd = { .fd = -1 };
+static struct getrandom_emulation_fd getrandom_urandom_fd = { .fd = -1 };
+
+#define GETRANDOM_SUPPORTED_FLAGS (GRND_RANDOM | GRND_NONBLOCK)
+
+static ssize_t
+getrandom_emulation (void *buffer, size_t length, unsigned flags)
+{
+  /* Check if any unsupported flags have been requested.  */
+  if (flags & ~GETRANDOM_SUPPORTED_FLAGS)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  if (flags & GRND_RANDOM)
+    {
+      int fd;
+      const char *device = "/dev/random";
+      if (flags & GRND_NONBLOCK)
+        fd = getrandom_get_fd (device, &getrandom_nonblock_fd, true);
+      else
+        fd = getrandom_get_fd (device, &getrandom_random_fd, false);
+      ssize_t ret = __read (fd, buffer, length);
+      if (ret < 0 && errno == EBADF)
+        /* EBADF errors are fatal.  */
+        getrandom_fd_failure (device, "read", fd);
+      /* The caller is expected to handle any error.  */
+      return ret;
+    }
+
+  /* GRND_RANDOM is not set.  We need to terminate the process on
+     failure, to mirror the system call behavior (the system call is
+     guaranteed not to fail after initialization).  */
+
+  const char *device = "/dev/urandom";
+
+  /* /dev/urandom is not supposed to block, so we ignore the
+     GRND_NONBLOCK flag.  */
+  int fd = getrandom_get_fd (device, &getrandom_urandom_fd, false);
+
+  void *end = buffer + length;
+  while (buffer < end)
+    {
+      ssize_t ret = TEMP_FAILURE_RETRY
+        (read_not_cancel (fd, buffer, end - buffer));
+      if (ret < 0)
+        getrandom_fd_failure (device, "read", fd);
+      buffer += ret;
+
+      /* Paranoia: This catches cases where the application exchanges
+         another file descriptor which return EOF.  We would have an
+         infinite loop otherwise.  */
+      getrandom_validate_fd (device, fd, &getrandom_urandom_fd);
+    }
+
+  return length;
+}
diff --git a/posix/tst-getrandom.c b/posix/tst-getrandom.c
new file mode 100644
index 0000000..11a811c
--- /dev/null
+++ b/posix/tst-getrandom.c
@@ -0,0 +1,162 @@ 
+/* Tests for the getrandom function.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+
+/* Set to true if any errors is encountered.  */
+static bool errors;
+
+/* Test getrandom with a single buffer length.  */
+static void
+test_length (char *buffer, int length, unsigned flags)
+{
+  memset (buffer, 0, length);
+  strcpy (buffer + length, "123");
+  ssize_t ret = getrandom (buffer, length, flags);
+  if (ret < 0)
+    {
+      if (!((flags & GRND_RANDOM)
+            && (flags & GRND_NONBLOCK)
+            && errno != EAGAIN))
+        {
+          printf ("error: getrandom (%d, 0x%x): %m\n", length, flags);
+          errors = true;
+        }
+    }
+  if (ret != length)
+    {
+      if (flags & GRND_RANDOM)
+        {
+          if (ret == 0 || ret > length)
+            {
+              printf ("error: getrandom (%d, 0x%x) returned %zd\n",
+                      length, flags, ret);
+              errors = true;
+            }
+        }
+      else
+        {
+          printf ("error: getrandom (%d, 0x%x) returned %zd\n",
+                  length, flags, ret);
+          errors = true;
+        }
+    }
+  if (length >= 7)
+    {
+      /* One spurious test failure in 2**56 is sufficiently
+         unlikely.  */
+      int non_null = 0;
+      for (int i = 0; i < length; ++i)
+        non_null += buffer[i] != 0;
+      if (non_null == 0)
+        {
+          printf ("error: getrandom (%d, 0x%x) returned all-zero bytes\n",
+                  length, flags);
+          errors = true;
+        }
+    }
+  if (memcmp (buffer + length, "123", 4) != 0)
+    {
+      printf ("error: getrandom (%d, 0x%x) wrote spurios bytes\n",
+              length, flags);
+      errors = true;
+    }
+}
+
+/* Call getrandom repeatedly to fille the buffer.  */
+static bool
+getrandom_full (char *buffer, int length, unsigned flags)
+{
+  char *end = buffer + length;
+  while (buffer < end)
+    {
+      ssize_t ret = getrandom (buffer, end - buffer, flags);
+      if (ret < 0)
+        {
+          printf ("error: getrandom (%d, 0x%x): %m\n", length, flags);
+          errors = true;
+          return false;
+        }
+      buffer += ret;
+    }
+
+  return true;
+}
+
+static void
+test_flags (unsigned flags)
+{
+  /* Test various lengths, but only for !GRND_RANDOM, to conserve
+     entropy.  */
+  {
+    enum { max_length = 300 };
+    char buffer[max_length + 4];
+    if (flags & GRND_RANDOM)
+      test_length (buffer, 0, flags);
+    else
+      {
+        for (int length = 0; length <= 9; ++length)
+          test_length (buffer, length, flags);
+        test_length (buffer, 16, flags);
+        test_length (buffer, max_length, flags);
+      }
+  }
+
+  /* Test that getrandom returns different data.  */
+  if (!(flags & GRND_NONBLOCK))
+    {
+      char buffer1[8];
+      memset (buffer1, 0, sizeof (buffer1));
+
+      char buffer2[8];
+      memset (buffer2, 0, sizeof (buffer2));
+
+      if (getrandom_full (buffer1, sizeof (buffer1), flags)
+          && getrandom_full (buffer1, sizeof (buffer1), flags))
+        {
+          if (memcmp (buffer1, buffer2, sizeof (buffer1)) == 0)
+            {
+              printf ("error: getrandom returns constant value\n");
+              errors = true;
+            }
+        }
+    }
+}
+
+static int
+do_test (void)
+{
+  for (int use_random = 0; use_random < 2; ++use_random)
+    for (int use_nonblock = 0; use_nonblock < 2; ++use_nonblock)
+      {
+        int flags = 0;
+        if (use_random)
+          flags |= GRND_RANDOM;
+        if (use_nonblock)
+          flags |= GRND_NONBLOCK;
+        test_flags (flags);
+      }
+  return errors;
+}
+
+#define TEST_FUNCTION do_test ()
+#include "../test-skeleton.c"
diff --git a/posix/unistd.h b/posix/unistd.h
index 625ba77..1360310 100644
--- a/posix/unistd.h
+++ b/posix/unistd.h
@@ -1157,6 +1157,16 @@  extern int pthread_atfork (void (*__prepare) (void),
 			   void (*__child) (void)) __THROW;
 #endif
 
+#ifdef __USE_GNU
+/* Flags for use with  getrandom.  */
+# define GRND_NONBLOCK 1
+# define GRND_RANDOM 2
+
+ssize_t __getrandom (void *__buffer, size_t __length, unsigned __flags);
+#define getrandom(buffer, length, flags) \
+  (0 + __getrandom (buffer, length, flags))
+
+#endif	/* __USE_GNU */
 
 /* Define some macros helping to catch buffer overflows.  */
 #if __USE_FORTIFY_LEVEL > 0 && defined __fortify_function
diff --git a/sysdeps/unix/sysv/linux/getrandom.c b/sysdeps/unix/sysv/linux/getrandom.c
new file mode 100644
index 0000000..3bf6f85
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/getrandom.c
@@ -0,0 +1,149 @@ 
+/* Linux version of getrandom.
+   Copyright (C) 2016 Free Software Foundation, Inc.
+   This file is part of the GNU C Library.
+
+   The GNU C Library is free software; you can redistribute it and/or
+   modify it under the terms of the GNU Lesser General Public
+   License as published by the Free Software Foundation; either
+   version 2.1 of the License, or (at your option) any later version.
+
+   The GNU C Library is distributed in the hope that it will be useful,
+   but WITHOUT ANY WARRANTY; without even the implied warranty of
+   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+   Lesser General Public License for more details.
+
+   You should have received a copy of the GNU Lesser General Public
+   License along with the GNU C Library; if not, see
+   <http://www.gnu.org/licenses/>.  */
+
+#include <errno.h>
+#include <kernel-features.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#undef getrandom
+
+#ifdef __NR_getrandom
+
+/* Wrapper which can only process INT_MAX bytes at a time.  */
+static int
+getrandom_syscall_intmax (void *buffer, size_t length, unsigned flags)
+{
+  int ret;
+  do
+    ret = INLINE_SYSCALL (getrandom, 3, buffer, length, flags);
+  /* getrandom can fail with EINTR in the blocking urandom case if the
+     pool has not been initialized yet.  Retry in this case.  */
+  while (ret < 0
+         && !(flags & GRND_RANDOM)
+         && !(flags & GRND_NONBLOCK)
+         && errno == EINTR);
+  return ret;
+}
+
+/* System call wrapper which can process all lengths and retries on
+   EINTR if necessary.  */
+static ssize_t
+getrandom_syscall (void *buffer, size_t length, unsigned flags)
+{
+  void *p = buffer;
+  void *end = buffer + length;
+
+  /* Execute the system call even for length == 0, so that we properly
+     reported ENOSYS.  Otherwise, the detection of system call
+     availability will not work.  */
+  do
+    {
+      size_t to_get = end - p;
+      /* The system call returns an int, so it cannot process more
+         than INT_MAX bytes at a time.  */
+      if (to_get > INT_MAX)
+        to_get = INT_MAX;
+      int ret = getrandom_syscall_intmax (p, to_get, flags);
+      /* Stop on error. */
+      if (ret < 0)
+        return ret;
+      p += ret;
+      /* Stop on a short read, unless no flags were specified.  In
+         this case, we continue calling the system call, so that
+         application code does not have to deal with short reads.  */
+      if (ret < to_get && flags != 0)
+        return p - buffer;
+    }
+  while (p < end);
+
+  return length;
+}
+
+
+# ifdef __ASSUME_GETRANDOM_SYSCALL
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned flags)
+{
+  ssize_t ret = getrandom_syscall (buffer, length, flags);
+  if (ret < 0 && ret == ENOSYS)
+    __libc_fatal ("getrandom system call failed with ENONSYS");
+  return ret;
+}
+
+# else /* !__ASSUME_GETRANDOM_SYSCALL */
+#  include "getrandom_emulation.c"
+
+/* Possible values: 0: not initialized, 1: system call present,
+   2: system call missing.  */
+static int have_getrandom;
+
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned flags)
+{
+  /* Relaxed MO means that we may issue some additional failing system
+     calls because concurrent calls to __getrandom are not
+     synchronized, but optimizing for repeated calls is more
+     important.  */
+  switch (atomic_load_relaxed (&have_getrandom))
+    {
+    case 0:
+      /* Not yet initialized.  */
+      {
+        ssize_t ret = getrandom_syscall (buffer, length, flags);
+        if (ret < 0 && errno == ENOSYS)
+          {
+            /* Record that the system call is missign and fall back to
+               emulation.  */
+            atomic_store_relaxed (&have_getrandom, 2);
+            return getrandom_emulation (buffer, length, flags);
+          }
+        atomic_store_relaxed (&have_getrandom, 1);
+        return ret;
+      }
+    case 1:
+      /* System call is available.  */
+      return getrandom_syscall (buffer, length, flags);
+    case 2:
+      /* System call is missing.  */
+      return getrandom_emulation (buffer, length, flags);
+    }
+  abort ();
+}
+# endif /* __ASSUME_GETRANDOM_SYSCALL */
+
+#else  /* !__NR_getrandom */
+
+/* The kernel headers do not mention the getrandom system call.  We
+   can only perform emulation. */
+
+# include "getrandom_emulation.c"
+
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned flags)
+{
+  return getrandom_emulation (buffer, length, flags);
+}
+
+#endif
+
+/* We use a macro wrapper to make accidental interposition of an
+   incompatible version less likely.  The getrandom alias is provided
+   so that configure checks which do not use a proper prototype will
+   work.  */
+strong_alias (__getrandom, getrandom)
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index 02c530b..eb41124 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -151,3 +151,8 @@ 
    separate syscalls were only added later.  */
 #define __ASSUME_SENDMSG_SYSCALL	1
 #define __ASSUME_RECVMSG_SYSCALL	1
+
+/* getrandom was added on many architectures in Linux 3.17. */
+#if __LINUX_KERNEL_VERSION >= 0x031100
+# define __ASSUME_GETRANDOM_SYSCALL
+#endif