diff mbox

[v2] Add getrandom implementation [BZ #17252]

Message ID 88371300-c533-9886-f1de-e34f17f7cbb4@redhat.com
State Superseded
Delegated to: Carlos O'Donell
Headers show

Commit Message

Florian Weimer June 27, 2016, 3:07 p.m. UTC
The attached patch does not attempt to make it less likely that the 
getrandom emulation will fail.  The file descriptor is kept open only 
for the duration of the call.  I move the declaration to <sys/random.h> 
(a new file) and added some documentation.

I kept the protection against symbol interposition.  I dropped the 
getrandom alias because it would lead to compile failures because 
certain forms of autoconf checks would succeed, but compilation would 
likely fail because neither <stdlib.h> nor <unistd.h> declare getrandom.

It looks like I have to split all GRND_RANDOM tests into an xtest 
because on idle build servers, even the few bytes that are currently 
consumed with GRND_RANDOM cause very long blocking, beyond any 
reasonable test timeout.

Thanks,
Florian

Comments

Rical Jasan June 30, 2016, 9:32 a.m. UTC | #1
On 06/27/2016 08:07 AM, Florian Weimer wrote:
> The attached patch does not attempt to make it less likely that the
> getrandom emulation will fail.  The file descriptor is kept open only
> for the duration of the call.  I move the declaration to <sys/random.h>
> (a new file) and added some documentation.
> 
> I kept the protection against symbol interposition.  I dropped the
> getrandom alias because it would lead to compile failures because
> certain forms of autoconf checks would succeed, but compilation would
> likely fail because neither <stdlib.h> nor <unistd.h> declare getrandom.
> 
> It looks like I have to split all GRND_RANDOM tests into an xtest
> because on idle build servers, even the few bytes that are currently
> consumed with GRND_RANDOM cause very long blocking, beyond any
> reasonable test timeout.
> 
> Thanks,
> Florian
> 
> getrandom.patch
> 
> 
> Add getrandom implementation [BZ #17252]
> 
> The emulation opens /dev/random and /dev/urandom (depending
> on the flags), reads random bytes, and closes the descriptor
> again.
> 
> 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 gzlibc (which could well be used
> by other libraries in the same process image).
> 
> 2016-06-27  Florian Weimer  <fweimer@redhat.com>
> 
> 	[BZ #17252]
> 	* stdlib/sys/random.h: New file.
> 	(headers): Add it.
> 	* stdlib/Makefile (routines): Add getrandom.
> 	(tests): Add tst-getrandom.
> 	* stdlib/Versions (GLIBC_2.24): Add __getrandom.
> 	* stdlib/getrandom.c: New file.
> 	* stdlib/tst-getrandom.c: Likewise.
> 	* sysdep/posix/getrandom.c: Likewise.
> 	* sysdep/posix/getrandom_emulation.c: Likewise.
> 	* sysdeps/unix/sysv/linux/getrandom.c: Likewise.
> 	* sysdeps/unix/sysv/linux/kernel-features.h
> 	(__ASSUME_GETRANDOM_SYSCALL): Define.
> 	* manual/crypt.texi (Unpredictable Bytes): New section.
> 	* manual/math.texi (Pseudo-Random Numbers): Add cross-reference.
> 	* sysdeps/arm/nacl/libc.abilist: Add __getrandom.
> 	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
> 	Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
> 	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.
> 
> diff --git a/NEWS b/NEWS
> index e2737d5..c6b32de 100644
> --- a/NEWS
> +++ b/NEWS
> @@ -14,6 +14,10 @@ Version 2.24
>    unchanged).  Linux 3.2 or later kernel headers are required on all
>    architectures.
>  
> +* The getrandom function and the <sys/random.h> header file have been added.
> +  This function will use the Linux getrandom system call to obtain random
> +  data if available.
> +
>  * The pap_AN locale has been deleted.  This has been deprecated for a long
>    time.  It has been replaced by pap_AW & pap_CW, both of which have long
>    been included in previous releases.
> diff --git a/manual/crypt.texi b/manual/crypt.texi
> index 659688b..f446f8f 100644
> --- a/manual/crypt.texi
> +++ b/manual/crypt.texi
> @@ -45,6 +45,7 @@ encrypted authentication use normal DES.
>  * getpass::                     Prompting the user for a password.
>  * crypt::                       A one-way function for passwords.
>  * DES Encryption::              Routines for DES encryption.
> +* Unpredictable Bytes::         Randomness for cryptography purposes.
>  @end menu
>  
>  @node Legal Problems
> @@ -428,3 +429,83 @@ each byte.
>  The @code{ecb_crypt}, @code{cbc_crypt}, and @code{des_setparity}
>  functions and their accompanying macros are all defined in the header
>  @file{rpc/des_crypt.h}.
> +
> +@node Unpredictable Bytes
> +@section Generating Unpredictable Bytes
> +
> +Some cryptographic applications (such as session key generation) need
> +unpredictable bytes.
> +
> +@comment sys/random.h
> +@comment GNU
> +@deftypefun ssize_t getrandom (void *@var{buffer}, size_t @var{length}, unsigned int @var{flags})
> +@safety{@mtsafe{}@assafe{}@acsafe{}}
> +
> +This function writes @var{length} bytes of random data to the array
> +starting at @var{buffer}.  On succes, this function returns the number

success

> +of bytes which have been written to the buffer (which can be less than
> +@var{length}).  On error, @code{-1} is returned, and @code{errno} is
> +updated accordingly.
> +
> +The @code{getrandom} function is declared in the header file
> +@file{sys/stat.h}.  It is a GNU extension.

sys/random.h

> +
> +The following flags are defined for the @var{flags} argument:
> +
> +@table @code
> +@item GRND_RANDOM
> +Use the blocking pool instead of the non-blocking pool to obtain
> +randomness.  By default, the non-blocking pool is used.  The blocking
> +pool corresponds to @file{/dev/random}, and the non-blocking pool to
> +@file{/dev/urandom}.
> +
> +@item GRND_NONBLOCK
> +Instead of blocking, return to the caller immediately if no data is
> +available.
> +@end table
> +
> +Even access to the non-blocking pool can block if the system has just
> +booted and the pool has not yet been initialized.
> +
> +If the @var{flags} argument is zero, the @code{getrandom} implementation
> +in @theglibc{} will only return once @var{length} bytes have been
> +written to @var{buffer}, or there is an error (except @code{EINTR}), and
> +such a function call is not a cancelallation point.

cancellation

> +
> +@strong{Note:} If the system lacks support for the @code{getrandom}
> +system call, the @code{getrandom} function uses emulation based on the
> +@file{/dev/random} and @file{/dev/urandom} device nodes.  This results
> +in additional failure scenarios, listed below as ``emulation only''.
> +
> +The @code{getrandom} function can fail with several errors, some of
> +which are listed below.  In addition, if @var{flags} is not zero, the
> +function may not fill the buffer completely and return a value less than
> +@var{length}.
> +
> +@table @code
> +@item EAGAIN
> +No random data was available and @code{GRND_NONBLOCK} was specified in
> +@var{flags}.
> +
> +@item EFAULT
> +The the combination of @var{buffer} and @var{length} arguments specifies
> +an invalid memory range.
> +
> +@item EINTR
> +The system call was interrupted (only if flags is not zero).
> +
> +@item EINVAL
> +The @var{flags} argument contains an invalid combination of flags.
> +
> +@item ENOENT
> +@itemx EACCES
> +The current file system namespace lacks the required device node, or the
> +device node is inaccessible (emulation only).
> +
> +@item EMFILE
> +@itemx ENFILE
> +The random device node could not be opened due to process or system
> +limits (emulation only).
> +@end table
> +
> +@end deftypefun
> diff --git a/manual/math.texi b/manual/math.texi
> index 5c9f7b9..138b1f2 100644
> --- a/manual/math.texi
> +++ b/manual/math.texi
> @@ -1413,7 +1413,8 @@ is convenient when you are debugging a program, but it is unhelpful if
>  you want the program to behave unpredictably.  If you want a different
>  pseudo-random series each time your program runs, you must specify a
>  different seed each time.  For ordinary purposes, basing the seed on the
> -current time works well.
> +current time works well.  For random numbers in cryptography, see
> +@ref{Unpredictable Bytes}.

That won't render correctly in info.  Try: "For random numbers in
cryptography, @pxref{Unpredictable Bytes}."

>  
>  You can obtain repeatable sequences of numbers on a particular machine type
>  by specifying the same initial seed value for the random number
> diff --git a/stdlib/Makefile b/stdlib/Makefile
> index fc6f23d..9055993 100644
> --- a/stdlib/Makefile
> +++ b/stdlib/Makefile
> @@ -28,7 +28,7 @@ headers	:= stdlib.h bits/stdlib.h bits/stdlib-ldbl.h bits/stdlib-float.h      \
>  	   errno.h sys/errno.h bits/errno.h				      \
>  	   ucontext.h sys/ucontext.h					      \
>  	   alloca.h fmtmsg.h						      \
> -	   bits/stdlib-bsearch.h
> +	   bits/stdlib-bsearch.h sys/random.h
>  
>  routines	:=							      \
>  	atof atoi atol atoll						      \
> @@ -45,7 +45,7 @@ routines	:=							      \
>  	srand48 seed48 lcong48						      \
>  	drand48_r erand48_r lrand48_r nrand48_r mrand48_r jrand48_r	      \
>  	srand48_r seed48_r lcong48_r					      \
> -	drand48-iter							      \
> +	drand48-iter getrandom						      \
>  	strtol strtoul strtoll strtoull					      \
>  	strtol_l strtoul_l strtoll_l strtoull_l				      \
>  	strtof strtod strtold						      \
> @@ -77,7 +77,7 @@ tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
>  		   tst-tininess tst-strtod-underflow tst-tls-atexit	    \
>  		   tst-setcontext3 tst-tls-atexit-nodelete		    \
>  		   tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l    \
> -		   tst-quick_exit tst-thread-quick_exit
> +		   tst-quick_exit tst-thread-quick_exit tst-getrandom
>  tests-static	:= tst-secure-getenv
>  ifeq ($(have-cxx-thread_local),yes)
>  CFLAGS-tst-quick_exit.o = -std=c++11
> diff --git a/stdlib/Versions b/stdlib/Versions
> index 9c06b43..8d79f46 100644
> --- a/stdlib/Versions
> +++ b/stdlib/Versions
> @@ -111,6 +111,7 @@ libc {
>    }
>    GLIBC_2.24 {
>      quick_exit;
> +    __getrandom;
>    }
>    GLIBC_PRIVATE {
>      # functions which have an additional interface since they are
> diff --git a/stdlib/getrandom.c b/stdlib/getrandom.c
> new file mode 100644
> index 0000000..f0b3181
> --- /dev/null
> +++ b/stdlib/getrandom.c
> @@ -0,0 +1,31 @@
> +/* Stub for 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 <sys/random.h>
> +
> +/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
> +   number of bytes written, or -1 on error.  */
> +ssize_t
> +__getrandom (void *buffer, size_t length, unsigned int flags)
> +{
> +  __set_errno (ENOSYS);
> +  return -1;
> +}
> +
> +stub_warning (__getrandom)
> diff --git a/stdlib/sys/random.h b/stdlib/sys/random.h
> new file mode 100644
> index 0000000..377fbe2
> --- /dev/null
> +++ b/stdlib/sys/random.h
> @@ -0,0 +1,35 @@
> +/* Interfaces for obtaining random bytes.
> +   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/>.  */
> +
> +#ifndef _SYS_RANDOM_H
> +#define _SYS_RANDOM_H

Isn't there a preferred way of doing this that defines _SYS_RANDOM_H to
1?  I seem to remember a wiki page that talked about protecting against
typos.

> +
> +/* Flags for use with  getrandom.  */
> +# define GRND_NONBLOCK 1
> +# define GRND_RANDOM 2
> +
> +/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
> +   number of bytes written, or -1 on error.  */
> +ssize_t __getrandom (void *__buffer, size_t __length, unsigned int __flags)
> +  __THROW __wur;
> +
> +/* Prevent accidental interposition of the getrandom symbol.  */
> +#define getrandom(buffer, length, flags) \
> +  (0 + __getrandom (buffer, length, flags))
> +
> +#endif /* _SYS_RANDOM_H */
> diff --git a/stdlib/tst-getrandom.c b/stdlib/tst-getrandom.c
> new file mode 100644
> index 0000000..c49c89a
> --- /dev/null
> +++ b/stdlib/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 <sys/random.h>
> +
> +/* Set to true if any errors is encountered.  */

are 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;
> +        }
> +    }

How strict is the coding style about unnecessary parentheses?  Two sets
could be removed here.  I think there are a few places in the test file,
but some I'd say improve readability where there are multi-line conditions.

> +  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",

spurious

> +              length, flags);
> +      errors = true;
> +    }
> +}
> +
> +/* Call getrandom repeatedly to fille the buffer.  */

fill

> +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/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
> index 2f7751d..b8fb2d5 100644
> --- a/sysdeps/arm/nacl/libc.abilist
> +++ b/sysdeps/arm/nacl/libc.abilist
> @@ -1840,4 +1840,5 @@ GLIBC_2.23 fts64_close F
>  GLIBC_2.23 fts64_open F
>  GLIBC_2.23 fts64_read F
>  GLIBC_2.23 fts64_set F
> +GLIBC_2.24 __getrandom F
>  GLIBC_2.24 quick_exit F
> diff --git a/sysdeps/posix/getrandom.c b/sysdeps/posix/getrandom.c
> new file mode 100644
> index 0000000..030d8cb
> --- /dev/null
> +++ b/sysdeps/posix/getrandom.c
> @@ -0,0 +1,27 @@
> +/* 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"
> +
> +/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
> +   number of bytes written, or -1 on error.  */
> +ssize_t
> +__getrandom (void *buffer, size_t length, unsigned int flags)
> +{
> +  return getrandom_emulation (buffer, length, flags);
> +}
> diff --git a/sysdeps/posix/getrandom_emulation.c b/sysdeps/posix/getrandom_emulation.c
> new file mode 100644
> index 0000000..75534d9
> --- /dev/null
> +++ b/sysdeps/posix/getrandom_emulation.c
> @@ -0,0 +1,111 @@
> +/* 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 <libc-lock.h>
> +#include <not-cancel.h>
> +#include <stdbool.h>
> +#include <stdio.h>
> +#include <unistd.h>
> +
> +/* Support flags by this emulation.  Additional flags will cause the
> +   emulation to fail with EINVAL.  */
> +#define GETRANDOM_SUPPORTED_FLAGS (GRND_RANDOM | GRND_NONBLOCK)
> +
> +/* Open the device node for the random device requested by FLAGS.
> +   Return -1 on error (and set errno), and the file descriptor on
> +   success.  */
> +static int
> +getrandom_open_fd (int flags)
> +{
> +  int open_flags = O_RDONLY | O_CLOEXEC;
> +  if (flags & GRND_NONBLOCK)
> +    open_flags |= O_NONBLOCK;
> +  const char *device;
> +  if (flags & GRND_RANDOM)
> +    device = "/dev/random";
> +  else
> +    device = "/dev/urandom";
> +  return open_not_cancel (device, open_flags, 0);
> +}
> +
> +/* Attempt to read LENGTH bytes from FD, avoiding short reads.
> +   Intended for getrandom calls without any flags.  */
> +static ssize_t
> +getrandom_read_fd (int fd, void *buffer, size_t length)
> +{
> +  void *end = buffer + length;
> +  while (buffer < end)
> +    {
> +      /* EINTR can occur without any flags during early userspace
> +         initialization.  */
> +      ssize_t ret = TEMP_FAILURE_RETRY
> +        (read_not_cancel (fd, buffer, end - buffer));
> +      if (ret < 0)
> +        /* Do not report the short read, return the error.  */
> +        return -1;
> +      if (ret == 0)
> +        __libc_fatal ("error: end of file on randomness device\n");
> +      buffer += ret;
> +    }
> +  return length;
> +}
> +
> +static void
> +getrandom_close_fd (void *pfd)
> +{
> +  close_not_cancel_no_status (*(int *) pfd);
> +}
> +
> +/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
> +   number of bytes written, or -1 on error.  Implementation based on
> +   emulation with /dev/urandom and /dev/random.  */
> +static ssize_t
> +getrandom_emulation (void *buffer, size_t length, unsigned int flags)
> +{
> +  /* Check if any unsupported flags have been requested.  */
> +  if (flags & ~GETRANDOM_SUPPORTED_FLAGS)
> +    {
> +      __set_errno (EINVAL);
> +      return -1;
> +    }
> +
> +  int fd = getrandom_open_fd (flags);
> +  if (fd < 0)
> +    return -1;
> +
> +  /* If flags is zero, avoid short reads.  */
> +  if (flags == 0)
> +    {
> +      ssize_t ret = getrandom_read_fd (fd, buffer, length);
> +      close_not_cancel_no_status (fd);
> +      return ret;
> +    }
> +  else
> +    {
> +      /* Some flags are set.  Allow cancellation, and pass short reads
> +         to the caller.  */
> +      ssize_t ret;
> +      __libc_cleanup_push (getrandom_close_fd, &fd);
> +      ret = __read (fd, buffer, length);
> +      __libc_cleanup_pop (1);
> +      return ret;
> +    }
> +}

...

> diff --git a/sysdeps/unix/sysv/linux/getrandom.c b/sysdeps/unix/sysv/linux/getrandom.c
> new file mode 100644
> index 0000000..4cea107
> --- /dev/null
> +++ b/sysdeps/unix/sysv/linux/getrandom.c
> @@ -0,0 +1,164 @@
> +/* 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 <assert.h>
> +#include <errno.h>
> +#include <kernel-features.h>
> +#include <stdio.h>
> +#include <stdlib.h>
> +#include <sys/random.h>
> +#include <sysdep-cancel.h>
> +#include <unistd.h>
> +
> +#ifdef __NR_getrandom
> +
> +/* getrandom system call wrapper with no flags, and which can only
> +   process INT_MAX bytes at a time, and retries on EINTR.  */
> +static int
> +getrandom_syscall_intmax (void *buffer, size_t length)
> +{
> +  return TEMP_FAILURE_RETRY (INLINE_SYSCALL (getrandom, 3, buffer, length, 0));
> +}
> +
> +/* getrandom system call wrapper with no flags, and which can process
> +   all lengths and retries on EINTR.  */
> +static ssize_t
> +getrandom_syscall_no_flags (void *buffer, size_t length)
> +{
> +  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

report

> +     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 getrandom_result = getrandom_syscall_intmax (p, to_get);
> +      /* Stop on error.  Do not report the short read, return the
> +         error.  */
> +      if (getrandom_result < 0)
> +        return -1;
> +      /* If the system call returns 0 for some reason, we would enter
> +         an infinite loop.  */
> +      assert (getrandom_result > 0 || length == 0);
> +      p += getrandom_result;
> +    }
> +  while (p < end);
> +
> +  return length;
> +}
> +
> +/* getrandom system call wrapper with special support for FLAGS == 0
> +   (EINTR retry, arbitrary lengths).  */
> +static ssize_t
> +getrandom_try_syscall (void *buffer, size_t length, unsigned int flags)
> +{
> +  if (flags == 0)
> +    return getrandom_syscall_no_flags (buffer, length);
> +  else
> +    return SYSCALL_CANCEL (getrandom, buffer, length, flags);
> +}
> +
> +/* Same as getrandom_try_syscall, but terminate the process on an
> +   ENOSYS error.  */
> +static ssize_t
> +getrandom_force_syscall (void *buffer, size_t length, unsigned int flags)
> +{
> +  ssize_t ret = getrandom_try_syscall (buffer, length, flags);
> +  if (ret < 0 && ret == ENOSYS)
> +    __libc_fatal ("error: getrandom system call failed with ENONSYS\n");
> +  return ret;
> +}
> +
> +# ifdef __ASSUME_GETRANDOM_SYSCALL
> +/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
> +   number of bytes written, or -1 on error.  This implementation uses
> +   the system call unconditionally and terminates the process if it
> +   fails with ENOSYS.  */
> +ssize_t
> +__getrandom (void *buffer, size_t length, unsigned int flags)
> +{
> +  return getrandom_force_syscall (buffer, length, flags);
> +}
> +
> +# 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;
> +
> +/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
> +   number of bytes written, or -1 on error.  This implementation falls
> +   back to emulation in case the system call is unavailable.  */
> +ssize_t
> +__getrandom (void *buffer, size_t length, unsigned int 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_try_syscall (buffer, length, flags);
> +        if (ret < 0 && errno == ENOSYS)
> +          {
> +            /* Record that the system call is missign and fall back to

missing

> +               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_force_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. */

Two spaces.

> +
> +# include "getrandom_emulation.c"
> +
> +/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
> +   number of bytes written, or -1 on error.  This implementation uses
> +   emulation with device nodes.  */
> +ssize_t
> +__getrandom (void *buffer, size_t length, unsigned int flags)
> +{
> +  return getrandom_emulation (buffer, length, flags);
> +}
> +
> +#endif

...

Only typos?!  How am I supposed to get reviewing experience like this?  :)

Really though, reading the code, it made sense to me.  I very much liked
it---seemed like a much more complete "if I rolled my own".  API and
documentation feel familiar/consistent.  All the strange and bewildering
workings must be more occult than I am yet able to see, probably buried
in those mysterious SYSCALL_CANCEL, TEMP_FAILURE_RETRY, and
INLINE_SYSCALL incantations obfuscating where I expected a real
getrandom syscall to actually appear.  I can only imagine what they must
do...


Rical
Zack Weinberg June 30, 2016, 12:03 p.m. UTC | #2
On Mon, Jun 27, 2016 at 11:07 AM, Florian Weimer <fweimer@redhat.com> wrote:
> The attached patch does not attempt to make it less likely that the
> getrandom emulation will fail.  The file descriptor is kept open only for
> the duration of the call.  I move the declaration to <sys/random.h> (a new
> file) and added some documentation.

I think it would be better to expose getrandom() as a completely
unadorned syscall.  No fallback and no attempt to paper over any of
the infelicities of the kernel interface.

This is because, what with the delay in adding this to libc, there's
existing code now that makes the system call directly.  We want people
to be able to just swap in the libc wrapper without having to worry
about behavior differences.

A reliable cryptographic RNG should _also_ be added, but under a
different name.  I'd vote for cloning the BSD arc4random() API.

zw
Nikos Mavrogiannopoulos July 13, 2016, 1:09 p.m. UTC | #3
Zack Weinberg <zackw <at> panix.com> writes:

> 
> On Mon, Jun 27, 2016 at 11:07 AM, Florian Weimer <fweimer <at> redhat.com>
wrote:
> > The attached patch does not attempt to make it less likely that the
> > getrandom emulation will fail.  The file descriptor is kept open only for
> > the duration of the call.  I move the declaration to <sys/random.h> (a new
> > file) and added some documentation.
> 
> I think it would be better to expose getrandom() as a completely
> unadorned syscall.  No fallback and no attempt to paper over any of
> the infelicities of the kernel interface.
> This is because, what with the delay in adding this to libc, there's
> existing code now that makes the system call directly.  We want people
> to be able to just swap in the libc wrapper without having to worry
> about behavior differences.

I like the patch, though I agree with the statement above. Most likely the
emulation layer will create more problems than it would solve.

> A reliable cryptographic RNG should _also_ be added, but under a
> different name.  I'd vote for cloning the BSD arc4random() API.

The arc4random API is nice but it has a very unfortunate name. There is some
initial effort to standardize via POSIX a similar API:
http://austingroupbugs.net/view.php?id=859

regards,
Nikos
diff mbox

Patch

Add getrandom implementation [BZ #17252]

The emulation opens /dev/random and /dev/urandom (depending
on the flags), reads random bytes, and closes the descriptor
again.

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 gzlibc (which could well be used
by other libraries in the same process image).

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

	[BZ #17252]
	* stdlib/sys/random.h: New file.
	(headers): Add it.
	* stdlib/Makefile (routines): Add getrandom.
	(tests): Add tst-getrandom.
	* stdlib/Versions (GLIBC_2.24): Add __getrandom.
	* stdlib/getrandom.c: New file.
	* stdlib/tst-getrandom.c: Likewise.
	* sysdep/posix/getrandom.c: Likewise.
	* sysdep/posix/getrandom_emulation.c: Likewise.
	* sysdeps/unix/sysv/linux/getrandom.c: Likewise.
	* sysdeps/unix/sysv/linux/kernel-features.h
	(__ASSUME_GETRANDOM_SYSCALL): Define.
	* manual/crypt.texi (Unpredictable Bytes): New section.
	* manual/math.texi (Pseudo-Random Numbers): Add cross-reference.
	* sysdeps/arm/nacl/libc.abilist: Add __getrandom.
	* sysdeps/unix/sysv/linux/aarch64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/alpha/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/arm/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/hppa/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/i386/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/ia64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/microblaze/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/nios2/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist:
	Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist: Likewise.
	* sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sh/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/64/libc.abilist: Likewise.
	* sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist: Likewise.

diff --git a/NEWS b/NEWS
index e2737d5..c6b32de 100644
--- a/NEWS
+++ b/NEWS
@@ -14,6 +14,10 @@  Version 2.24
   unchanged).  Linux 3.2 or later kernel headers are required on all
   architectures.
 
+* The getrandom function and the <sys/random.h> header file have been added.
+  This function will use the Linux getrandom system call to obtain random
+  data if available.
+
 * The pap_AN locale has been deleted.  This has been deprecated for a long
   time.  It has been replaced by pap_AW & pap_CW, both of which have long
   been included in previous releases.
diff --git a/manual/crypt.texi b/manual/crypt.texi
index 659688b..f446f8f 100644
--- a/manual/crypt.texi
+++ b/manual/crypt.texi
@@ -45,6 +45,7 @@  encrypted authentication use normal DES.
 * getpass::                     Prompting the user for a password.
 * crypt::                       A one-way function for passwords.
 * DES Encryption::              Routines for DES encryption.
+* Unpredictable Bytes::         Randomness for cryptography purposes.
 @end menu
 
 @node Legal Problems
@@ -428,3 +429,83 @@  each byte.
 The @code{ecb_crypt}, @code{cbc_crypt}, and @code{des_setparity}
 functions and their accompanying macros are all defined in the header
 @file{rpc/des_crypt.h}.
+
+@node Unpredictable Bytes
+@section Generating Unpredictable Bytes
+
+Some cryptographic applications (such as session key generation) need
+unpredictable bytes.
+
+@comment sys/random.h
+@comment GNU
+@deftypefun ssize_t getrandom (void *@var{buffer}, size_t @var{length}, unsigned int @var{flags})
+@safety{@mtsafe{}@assafe{}@acsafe{}}
+
+This function writes @var{length} bytes of random data to the array
+starting at @var{buffer}.  On succes, this function returns the number
+of bytes which have been written to the buffer (which can be less than
+@var{length}).  On error, @code{-1} is returned, and @code{errno} is
+updated accordingly.
+
+The @code{getrandom} function is declared in the header file
+@file{sys/stat.h}.  It is a GNU extension.
+
+The following flags are defined for the @var{flags} argument:
+
+@table @code
+@item GRND_RANDOM
+Use the blocking pool instead of the non-blocking pool to obtain
+randomness.  By default, the non-blocking pool is used.  The blocking
+pool corresponds to @file{/dev/random}, and the non-blocking pool to
+@file{/dev/urandom}.
+
+@item GRND_NONBLOCK
+Instead of blocking, return to the caller immediately if no data is
+available.
+@end table
+
+Even access to the non-blocking pool can block if the system has just
+booted and the pool has not yet been initialized.
+
+If the @var{flags} argument is zero, the @code{getrandom} implementation
+in @theglibc{} will only return once @var{length} bytes have been
+written to @var{buffer}, or there is an error (except @code{EINTR}), and
+such a function call is not a cancelallation point.
+
+@strong{Note:} If the system lacks support for the @code{getrandom}
+system call, the @code{getrandom} function uses emulation based on the
+@file{/dev/random} and @file{/dev/urandom} device nodes.  This results
+in additional failure scenarios, listed below as ``emulation only''.
+
+The @code{getrandom} function can fail with several errors, some of
+which are listed below.  In addition, if @var{flags} is not zero, the
+function may not fill the buffer completely and return a value less than
+@var{length}.
+
+@table @code
+@item EAGAIN
+No random data was available and @code{GRND_NONBLOCK} was specified in
+@var{flags}.
+
+@item EFAULT
+The the combination of @var{buffer} and @var{length} arguments specifies
+an invalid memory range.
+
+@item EINTR
+The system call was interrupted (only if flags is not zero).
+
+@item EINVAL
+The @var{flags} argument contains an invalid combination of flags.
+
+@item ENOENT
+@itemx EACCES
+The current file system namespace lacks the required device node, or the
+device node is inaccessible (emulation only).
+
+@item EMFILE
+@itemx ENFILE
+The random device node could not be opened due to process or system
+limits (emulation only).
+@end table
+
+@end deftypefun
diff --git a/manual/math.texi b/manual/math.texi
index 5c9f7b9..138b1f2 100644
--- a/manual/math.texi
+++ b/manual/math.texi
@@ -1413,7 +1413,8 @@  is convenient when you are debugging a program, but it is unhelpful if
 you want the program to behave unpredictably.  If you want a different
 pseudo-random series each time your program runs, you must specify a
 different seed each time.  For ordinary purposes, basing the seed on the
-current time works well.
+current time works well.  For random numbers in cryptography, see
+@ref{Unpredictable Bytes}.
 
 You can obtain repeatable sequences of numbers on a particular machine type
 by specifying the same initial seed value for the random number
diff --git a/stdlib/Makefile b/stdlib/Makefile
index fc6f23d..9055993 100644
--- a/stdlib/Makefile
+++ b/stdlib/Makefile
@@ -28,7 +28,7 @@  headers	:= stdlib.h bits/stdlib.h bits/stdlib-ldbl.h bits/stdlib-float.h      \
 	   errno.h sys/errno.h bits/errno.h				      \
 	   ucontext.h sys/ucontext.h					      \
 	   alloca.h fmtmsg.h						      \
-	   bits/stdlib-bsearch.h
+	   bits/stdlib-bsearch.h sys/random.h
 
 routines	:=							      \
 	atof atoi atol atoll						      \
@@ -45,7 +45,7 @@  routines	:=							      \
 	srand48 seed48 lcong48						      \
 	drand48_r erand48_r lrand48_r nrand48_r mrand48_r jrand48_r	      \
 	srand48_r seed48_r lcong48_r					      \
-	drand48-iter							      \
+	drand48-iter getrandom						      \
 	strtol strtoul strtoll strtoull					      \
 	strtol_l strtoul_l strtoll_l strtoull_l				      \
 	strtof strtod strtold						      \
@@ -77,7 +77,7 @@  tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
 		   tst-tininess tst-strtod-underflow tst-tls-atexit	    \
 		   tst-setcontext3 tst-tls-atexit-nodelete		    \
 		   tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l    \
-		   tst-quick_exit tst-thread-quick_exit
+		   tst-quick_exit tst-thread-quick_exit tst-getrandom
 tests-static	:= tst-secure-getenv
 ifeq ($(have-cxx-thread_local),yes)
 CFLAGS-tst-quick_exit.o = -std=c++11
diff --git a/stdlib/Versions b/stdlib/Versions
index 9c06b43..8d79f46 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -111,6 +111,7 @@  libc {
   }
   GLIBC_2.24 {
     quick_exit;
+    __getrandom;
   }
   GLIBC_PRIVATE {
     # functions which have an additional interface since they are
diff --git a/stdlib/getrandom.c b/stdlib/getrandom.c
new file mode 100644
index 0000000..f0b3181
--- /dev/null
+++ b/stdlib/getrandom.c
@@ -0,0 +1,31 @@ 
+/* Stub for 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 <sys/random.h>
+
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  */
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned int flags)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__getrandom)
diff --git a/stdlib/sys/random.h b/stdlib/sys/random.h
new file mode 100644
index 0000000..377fbe2
--- /dev/null
+++ b/stdlib/sys/random.h
@@ -0,0 +1,35 @@ 
+/* Interfaces for obtaining random bytes.
+   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/>.  */
+
+#ifndef _SYS_RANDOM_H
+#define _SYS_RANDOM_H
+
+/* Flags for use with  getrandom.  */
+# define GRND_NONBLOCK 1
+# define GRND_RANDOM 2
+
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  */
+ssize_t __getrandom (void *__buffer, size_t __length, unsigned int __flags)
+  __THROW __wur;
+
+/* Prevent accidental interposition of the getrandom symbol.  */
+#define getrandom(buffer, length, flags) \
+  (0 + __getrandom (buffer, length, flags))
+
+#endif /* _SYS_RANDOM_H */
diff --git a/stdlib/tst-getrandom.c b/stdlib/tst-getrandom.c
new file mode 100644
index 0000000..c49c89a
--- /dev/null
+++ b/stdlib/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 <sys/random.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/sysdeps/arm/nacl/libc.abilist b/sysdeps/arm/nacl/libc.abilist
index 2f7751d..b8fb2d5 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1840,4 +1840,5 @@  GLIBC_2.23 fts64_close F
 GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/posix/getrandom.c b/sysdeps/posix/getrandom.c
new file mode 100644
index 0000000..030d8cb
--- /dev/null
+++ b/sysdeps/posix/getrandom.c
@@ -0,0 +1,27 @@ 
+/* 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"
+
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  */
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned int flags)
+{
+  return getrandom_emulation (buffer, length, flags);
+}
diff --git a/sysdeps/posix/getrandom_emulation.c b/sysdeps/posix/getrandom_emulation.c
new file mode 100644
index 0000000..75534d9
--- /dev/null
+++ b/sysdeps/posix/getrandom_emulation.c
@@ -0,0 +1,111 @@ 
+/* 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 <libc-lock.h>
+#include <not-cancel.h>
+#include <stdbool.h>
+#include <stdio.h>
+#include <unistd.h>
+
+/* Support flags by this emulation.  Additional flags will cause the
+   emulation to fail with EINVAL.  */
+#define GETRANDOM_SUPPORTED_FLAGS (GRND_RANDOM | GRND_NONBLOCK)
+
+/* Open the device node for the random device requested by FLAGS.
+   Return -1 on error (and set errno), and the file descriptor on
+   success.  */
+static int
+getrandom_open_fd (int flags)
+{
+  int open_flags = O_RDONLY | O_CLOEXEC;
+  if (flags & GRND_NONBLOCK)
+    open_flags |= O_NONBLOCK;
+  const char *device;
+  if (flags & GRND_RANDOM)
+    device = "/dev/random";
+  else
+    device = "/dev/urandom";
+  return open_not_cancel (device, open_flags, 0);
+}
+
+/* Attempt to read LENGTH bytes from FD, avoiding short reads.
+   Intended for getrandom calls without any flags.  */
+static ssize_t
+getrandom_read_fd (int fd, void *buffer, size_t length)
+{
+  void *end = buffer + length;
+  while (buffer < end)
+    {
+      /* EINTR can occur without any flags during early userspace
+         initialization.  */
+      ssize_t ret = TEMP_FAILURE_RETRY
+        (read_not_cancel (fd, buffer, end - buffer));
+      if (ret < 0)
+        /* Do not report the short read, return the error.  */
+        return -1;
+      if (ret == 0)
+        __libc_fatal ("error: end of file on randomness device\n");
+      buffer += ret;
+    }
+  return length;
+}
+
+static void
+getrandom_close_fd (void *pfd)
+{
+  close_not_cancel_no_status (*(int *) pfd);
+}
+
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  Implementation based on
+   emulation with /dev/urandom and /dev/random.  */
+static ssize_t
+getrandom_emulation (void *buffer, size_t length, unsigned int flags)
+{
+  /* Check if any unsupported flags have been requested.  */
+  if (flags & ~GETRANDOM_SUPPORTED_FLAGS)
+    {
+      __set_errno (EINVAL);
+      return -1;
+    }
+
+  int fd = getrandom_open_fd (flags);
+  if (fd < 0)
+    return -1;
+
+  /* If flags is zero, avoid short reads.  */
+  if (flags == 0)
+    {
+      ssize_t ret = getrandom_read_fd (fd, buffer, length);
+      close_not_cancel_no_status (fd);
+      return ret;
+    }
+  else
+    {
+      /* Some flags are set.  Allow cancellation, and pass short reads
+         to the caller.  */
+      ssize_t ret;
+      __libc_cleanup_push (getrandom_close_fd, &fd);
+      ret = __read (fd, buffer, length);
+      __libc_cleanup_pop (1);
+      return ret;
+    }
+}
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 9cdb623..c27bd60 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2088,4 +2088,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index f3f3c70..663ae98 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -1999,6 +1999,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index a93803d..2db0919 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -89,6 +89,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
diff --git a/sysdeps/unix/sysv/linux/getrandom.c b/sysdeps/unix/sysv/linux/getrandom.c
new file mode 100644
index 0000000..4cea107
--- /dev/null
+++ b/sysdeps/unix/sysv/linux/getrandom.c
@@ -0,0 +1,164 @@ 
+/* 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 <assert.h>
+#include <errno.h>
+#include <kernel-features.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/random.h>
+#include <sysdep-cancel.h>
+#include <unistd.h>
+
+#ifdef __NR_getrandom
+
+/* getrandom system call wrapper with no flags, and which can only
+   process INT_MAX bytes at a time, and retries on EINTR.  */
+static int
+getrandom_syscall_intmax (void *buffer, size_t length)
+{
+  return TEMP_FAILURE_RETRY (INLINE_SYSCALL (getrandom, 3, buffer, length, 0));
+}
+
+/* getrandom system call wrapper with no flags, and which can process
+   all lengths and retries on EINTR.  */
+static ssize_t
+getrandom_syscall_no_flags (void *buffer, size_t length)
+{
+  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 getrandom_result = getrandom_syscall_intmax (p, to_get);
+      /* Stop on error.  Do not report the short read, return the
+         error.  */
+      if (getrandom_result < 0)
+        return -1;
+      /* If the system call returns 0 for some reason, we would enter
+         an infinite loop.  */
+      assert (getrandom_result > 0 || length == 0);
+      p += getrandom_result;
+    }
+  while (p < end);
+
+  return length;
+}
+
+/* getrandom system call wrapper with special support for FLAGS == 0
+   (EINTR retry, arbitrary lengths).  */
+static ssize_t
+getrandom_try_syscall (void *buffer, size_t length, unsigned int flags)
+{
+  if (flags == 0)
+    return getrandom_syscall_no_flags (buffer, length);
+  else
+    return SYSCALL_CANCEL (getrandom, buffer, length, flags);
+}
+
+/* Same as getrandom_try_syscall, but terminate the process on an
+   ENOSYS error.  */
+static ssize_t
+getrandom_force_syscall (void *buffer, size_t length, unsigned int flags)
+{
+  ssize_t ret = getrandom_try_syscall (buffer, length, flags);
+  if (ret < 0 && ret == ENOSYS)
+    __libc_fatal ("error: getrandom system call failed with ENONSYS\n");
+  return ret;
+}
+
+# ifdef __ASSUME_GETRANDOM_SYSCALL
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  This implementation uses
+   the system call unconditionally and terminates the process if it
+   fails with ENOSYS.  */
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned int flags)
+{
+  return getrandom_force_syscall (buffer, length, flags);
+}
+
+# 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;
+
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  This implementation falls
+   back to emulation in case the system call is unavailable.  */
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned int 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_try_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_force_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"
+
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  This implementation uses
+   emulation with device nodes.  */
+ssize_t
+__getrandom (void *buffer, size_t length, unsigned int flags)
+{
+  return getrandom_emulation (buffer, length, flags);
+}
+
+#endif
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 58ed133..45a8628 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1853,6 +1853,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index 61cbae0..8235533 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2011,6 +2011,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index d40d264..44b7967 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1875,6 +1875,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/kernel-features.h b/sysdeps/unix/sysv/linux/kernel-features.h
index 1d3b554..4ea4932 100644
--- a/sysdeps/unix/sysv/linux/kernel-features.h
+++ b/sysdeps/unix/sysv/linux/kernel-features.h
@@ -147,3 +147,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
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 64432ae..c0da3e1 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -90,6 +90,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.4 GLIBC_2.4 A
 GLIBC_2.4 _Exit F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 8086c38..8d78844 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1967,6 +1967,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 8c4c3bb..8d0a372 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2088,4 +2088,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index db014ed..a0c9720 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1942,6 +1942,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 33ac881..4654bcd 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1940,6 +1940,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index b8b2c0e..5dd97e5 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1938,6 +1938,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index 0741301..80b39d7 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1933,6 +1933,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index fa04825..f40e205 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2129,4 +2129,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 3d633c0..107d834 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1971,6 +1971,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index a6b164b..e23bba9 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1976,6 +1976,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 7200b76..e938823 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2176,4 +2176,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index de62ecb..155dc21 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -90,6 +90,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 _Exit F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 8da0bc0..ce8ba8d 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1971,6 +1971,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index 59066a9..54d3f0a 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1872,6 +1872,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 01ca9e6..05134a3 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1857,6 +1857,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 245c1c6..ab4bd74 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1963,6 +1963,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index 4478d13..6da3de4 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1901,6 +1901,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index c1a2613..7b6bf09 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2095,4 +2095,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index 35fbf8a..b9901f8 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2095,4 +2095,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index c1a2613..7b6bf09 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2095,4 +2095,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index c1054ce..1ef10d5 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1852,6 +1852,7 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F
 GLIBC_2.3 GLIBC_2.3 A
 GLIBC_2.3 __ctype_b_loc F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index 2fd6d60..ddeb9d2 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2095,4 +2095,5 @@  GLIBC_2.23 fts64_open F
 GLIBC_2.23 fts64_read F
 GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
+GLIBC_2.24 __getrandom F
 GLIBC_2.24 quick_exit F