public inbox for libc-alpha@sourceware.org
 help / color / mirror / Atom feed
* [PATCH] Add getrandom implementation [BZ #17252]
@ 2016-06-10 21:03 Florian Weimer
  2016-06-10 21:31 ` Joseph Myers
                   ` (3 more replies)
  0 siblings, 4 replies; 62+ messages in thread
From: Florian Weimer @ 2016-06-10 21:03 UTC (permalink / raw)
  To: libc-alpha

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.

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 21:03 [PATCH] Add getrandom implementation [BZ #17252] Florian Weimer
@ 2016-06-10 21:31 ` Joseph Myers
  2016-06-10 21:36   ` Joseph Myers
                     ` (2 more replies)
  2016-06-10 22:15 ` Roland McGrath
                   ` (2 subsequent siblings)
  3 siblings, 3 replies; 62+ messages in thread
From: Joseph Myers @ 2016-06-10 21:31 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

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 S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 21:31 ` Joseph Myers
@ 2016-06-10 21:36   ` Joseph Myers
  2016-06-10 22:00   ` Paul Eggert
  2016-06-11 11:13   ` Florian Weimer
  2 siblings, 0 replies; 62+ messages in thread
From: Joseph Myers @ 2016-06-10 21:36 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

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.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 21:31 ` Joseph Myers
  2016-06-10 21:36   ` Joseph Myers
@ 2016-06-10 22:00   ` Paul Eggert
  2016-06-10 22:06     ` Joseph Myers
  2016-06-11 11:13   ` Florian Weimer
  2 siblings, 1 reply; 62+ messages in thread
From: Paul Eggert @ 2016-06-10 22:00 UTC (permalink / raw)
  To: Joseph Myers, Florian Weimer; +Cc: libc-alpha

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.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 22:00   ` Paul Eggert
@ 2016-06-10 22:06     ` Joseph Myers
  0 siblings, 0 replies; 62+ messages in thread
From: Joseph Myers @ 2016-06-10 22:06 UTC (permalink / raw)
  To: Paul Eggert; +Cc: Florian Weimer, libc-alpha

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.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 21:03 [PATCH] Add getrandom implementation [BZ #17252] Florian Weimer
  2016-06-10 21:31 ` Joseph Myers
@ 2016-06-10 22:15 ` Roland McGrath
  2016-06-10 22:40   ` Joseph Myers
  2016-06-23 17:21   ` Florian Weimer
  2016-06-27 15:07 ` [PATCH v2] " Florian Weimer
  2016-11-14 17:45 ` [PATCH v7] getrandom system call wrapper " Florian Weimer
  3 siblings, 2 replies; 62+ messages in thread
From: Roland McGrath @ 2016-06-10 22:15 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

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.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 22:15 ` Roland McGrath
@ 2016-06-10 22:40   ` Joseph Myers
  2016-06-10 22:45     ` Roland McGrath
  2016-06-23 17:21   ` Florian Weimer
  1 sibling, 1 reply; 62+ messages in thread
From: Joseph Myers @ 2016-06-10 22:40 UTC (permalink / raw)
  To: Roland McGrath; +Cc: Florian Weimer, libc-alpha

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.

-- 
Joseph S. Myers
joseph@codesourcery.com

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 22:40   ` Joseph Myers
@ 2016-06-10 22:45     ` Roland McGrath
  0 siblings, 0 replies; 62+ messages in thread
From: Roland McGrath @ 2016-06-10 22:45 UTC (permalink / raw)
  To: Joseph Myers; +Cc: Florian Weimer, libc-alpha

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 21:31 ` Joseph Myers
  2016-06-10 21:36   ` Joseph Myers
  2016-06-10 22:00   ` Paul Eggert
@ 2016-06-11 11:13   ` Florian Weimer
  2016-06-11 20:10     ` Paul Eggert
  2 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-06-11 11:13 UTC (permalink / raw)
  To: Joseph Myers; +Cc: libc-alpha

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-11 11:13   ` Florian Weimer
@ 2016-06-11 20:10     ` Paul Eggert
  0 siblings, 0 replies; 62+ messages in thread
From: Paul Eggert @ 2016-06-11 20:10 UTC (permalink / raw)
  To: Florian Weimer, Joseph Myers; +Cc: libc-alpha

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?

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-10 22:15 ` Roland McGrath
  2016-06-10 22:40   ` Joseph Myers
@ 2016-06-23 17:21   ` Florian Weimer
  2016-06-25 21:58     ` Paul Eggert
  2016-09-02 22:23     ` Roland McGrath
  1 sibling, 2 replies; 62+ messages in thread
From: Florian Weimer @ 2016-06-23 17:21 UTC (permalink / raw)
  To: Roland McGrath; +Cc: libc-alpha

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-23 17:21   ` Florian Weimer
@ 2016-06-25 21:58     ` Paul Eggert
  2016-09-02 22:23     ` Roland McGrath
  1 sibling, 0 replies; 62+ messages in thread
From: Paul Eggert @ 2016-06-25 21:58 UTC (permalink / raw)
  To: Florian Weimer, Roland McGrath; +Cc: libc-alpha

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.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-06-10 21:03 [PATCH] Add getrandom implementation [BZ #17252] Florian Weimer
  2016-06-10 21:31 ` Joseph Myers
  2016-06-10 22:15 ` Roland McGrath
@ 2016-06-27 15:07 ` Florian Weimer
  2016-06-30  9:33   ` Rical Jasan
  2016-06-30 12:03   ` Zack Weinberg
  2016-11-14 17:45 ` [PATCH v7] getrandom system call wrapper " Florian Weimer
  3 siblings, 2 replies; 62+ messages in thread
From: Florian Weimer @ 2016-06-27 15:07 UTC (permalink / raw)
  To: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 780 bytes --]

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

[-- Attachment #2: getrandom.patch --]
[-- Type: text/x-patch, Size: 41635 bytes --]

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-06-27 15:07 ` [PATCH v2] " Florian Weimer
@ 2016-06-30  9:33   ` Rical Jasan
  2016-09-08  9:53     ` Florian Weimer
  2016-06-30 12:03   ` Zack Weinberg
  1 sibling, 1 reply; 62+ messages in thread
From: Rical Jasan @ 2016-06-30  9:33 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-06-27 15:07 ` [PATCH v2] " Florian Weimer
  2016-06-30  9:33   ` Rical Jasan
@ 2016-06-30 12:03   ` Zack Weinberg
  2016-07-13 13:10     ` Nikos Mavrogiannopoulos
  1 sibling, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-06-30 12:03 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-06-30 12:03   ` Zack Weinberg
@ 2016-07-13 13:10     ` Nikos Mavrogiannopoulos
  0 siblings, 0 replies; 62+ messages in thread
From: Nikos Mavrogiannopoulos @ 2016-07-13 13:10 UTC (permalink / raw)
  To: libc-alpha

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


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH] Add getrandom implementation [BZ #17252]
  2016-06-23 17:21   ` Florian Weimer
  2016-06-25 21:58     ` Paul Eggert
@ 2016-09-02 22:23     ` Roland McGrath
  1 sibling, 0 replies; 62+ messages in thread
From: Roland McGrath @ 2016-09-02 22:23 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-06-30  9:33   ` Rical Jasan
@ 2016-09-08  9:53     ` Florian Weimer
  2016-09-08 10:13       ` Andreas Schwab
  2016-09-08 11:58       ` Rical Jasan
  0 siblings, 2 replies; 62+ messages in thread
From: Florian Weimer @ 2016-09-08  9:53 UTC (permalink / raw)
  To: Rical Jasan; +Cc: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 882 bytes --]

On 06/30/2016 11:32 AM, Rical Jasan wrote:
>> > +#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.

This might defeat the header guard optimization.  Existing practice 
varies, some headers use 1, some don't.

 > How strict is the coding style about unnecessary parentheses?

I prefer adding braces to if statements if they are nested and some have 
else branches.

 > Really though, reading the code, it made sense to me.

Thanks.  I'm attaching a version with your comments (not rebased to 2.25 
though).  We may need this code again if we ever implement a 
arc4random-style interface.

(I think the consensus for getrandom is to add only a thin wrapper 
around the system call, if we are going to add it at all.)

Florian

[-- Attachment #2: getrandom-with-fallback.patch --]
[-- Type: text/x-patch, Size: 41635 bytes --]

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..082ad70 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/random.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 cancellation 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..917d598 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,
+@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..912807c
--- /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 1
+
+/* 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..2e4f7e7
--- /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 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;
+        }
+    }
+  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 spurious bytes\n",
+              length, flags);
+      errors = true;
+    }
+}
+
+/* Call getrandom repeatedly to fill 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..bab2774
--- /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
+     report 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 missing 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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-09-08  9:53     ` Florian Weimer
@ 2016-09-08 10:13       ` Andreas Schwab
  2016-09-08 10:28         ` Florian Weimer
  2016-09-08 11:58       ` Rical Jasan
  1 sibling, 1 reply; 62+ messages in thread
From: Andreas Schwab @ 2016-09-08 10:13 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Rical Jasan, libc-alpha

On Sep 08 2016, Florian Weimer <fweimer@redhat.com> wrote:

> diff --git a/stdlib/tst-getrandom.c b/stdlib/tst-getrandom.c
> new file mode 100644
> index 0000000..2e4f7e7
> --- /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 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)

Please add != 0 (no implicit boolean coercion).

Andreas.

-- 
Andreas Schwab, SUSE Labs, schwab@suse.de
GPG Key fingerprint = 0196 BAD8 1CE9 1970 F4BE  1748 E4D4 88E3 0EEA B9D7
"And now for something completely different."

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-09-08 10:13       ` Andreas Schwab
@ 2016-09-08 10:28         ` Florian Weimer
  0 siblings, 0 replies; 62+ messages in thread
From: Florian Weimer @ 2016-09-08 10:28 UTC (permalink / raw)
  To: Andreas Schwab; +Cc: Rical Jasan, libc-alpha

On 09/08/2016 12:12 PM, Andreas Schwab wrote:

>> +      if (!((flags & GRND_RANDOM)
>> +            && (flags & GRND_NONBLOCK)
>
> Please add != 0 (no implicit boolean coercion).

The wiki says this is okay (search for “foo & BIT”):

   <https://sourceware.org/glibc/wiki/Style_and_Conventions>

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-09-08  9:53     ` Florian Weimer
  2016-09-08 10:13       ` Andreas Schwab
@ 2016-09-08 11:58       ` Rical Jasan
  2016-09-08 12:36         ` Florian Weimer
  1 sibling, 1 reply; 62+ messages in thread
From: Rical Jasan @ 2016-09-08 11:58 UTC (permalink / raw)
  To: Florian Weimer; +Cc: libc-alpha

On 09/08/2016 02:53 AM, Florian Weimer wrote:
> On 06/30/2016 11:32 AM, Rical Jasan wrote:
>>> > +#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.
> 
> This might defeat the header guard optimization.  Existing practice
> varies, some headers use 1, some don't.
> 
>> How strict is the coding style about unnecessary parentheses?
> 
> I prefer adding braces to if statements if they are nested and some have
> else branches.

I won't argue with that.  Looks clean that way.

> 
>> Really though, reading the code, it made sense to me.
> 
> Thanks.  I'm attaching a version with your comments (not rebased to 2.25
> though).  We may need this code again if we ever implement a
> arc4random-style interface.
> 
> (I think the consensus for getrandom is to add only a thin wrapper
> around the system call, if we are going to add it at all.)
> 
> Florian

I'll chip in a few more cents as well.

> 
> getrandom-with-fallback.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

glibc?

> 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..082ad70 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/random.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 cancellation 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

The the

> +an invalid memory range.
> +
> +@item EINTR
> +The system call was interrupted (only if flags is not zero).

@var{flags}

> +
> +@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..917d598 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,
> +@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

I like the manual entries.

> 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..912807c
> --- /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 1
> +
> +/* 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) \

Should this be indented?

> +  (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..2e4f7e7
> --- /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 are encountered.  */
> +static bool errors;
> +
> +/* Test getrandom with a single buffer length.  */
> +static void
> +test_length (char *buffer, int length, unsigned flags)

I know this works, but is there a reason for using char *, int, and
unsigned instead of void *, size_t, and unsigned int?  test_flags below
also uses "unsigned".

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

Same error message in both cases.

> +  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 spurious bytes\n",
> +              length, flags);
> +      errors = true;
> +    }
> +}
> +
> +/* Call getrandom repeatedly to fill 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))

Should be buffer1 and buffer2, I imagine.

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

<abilist snipped>

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

Should this be unsigned int, for consistency?

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

<abilist snipped>

> diff --git a/sysdeps/unix/sysv/linux/getrandom.c b/sysdeps/unix/sysv/linux/getrandom.c
> new file mode 100644
> index 0000000..bab2774
> --- /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
> +     report 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 missing 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

<abilist snipped>

Rical

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v2] Add getrandom implementation [BZ #17252]
  2016-09-08 11:58       ` Rical Jasan
@ 2016-09-08 12:36         ` Florian Weimer
  0 siblings, 0 replies; 62+ messages in thread
From: Florian Weimer @ 2016-09-08 12:36 UTC (permalink / raw)
  To: Rical Jasan; +Cc: libc-alpha

[-- Attachment #1: Type: text/plain, Size: 2691 bytes --]

On 09/08/2016 01:58 PM, Rical Jasan wrote:

>> +#ifndef _SYS_RANDOM_H
>> +#define _SYS_RANDOM_H 1
>> +
>> +/* 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) \
>
> Should this be indented?

No, header file guards do not trigger indentation, so I fixed the first 
two macro definitions instead.

>> +/* Test getrandom with a single buffer length.  */
>> +static void
>> +test_length (char *buffer, int length, unsigned flags)
>
> I know this works, but is there a reason for using char *, int, and
> unsigned instead of void *, size_t, and unsigned int?  test_flags below
> also uses "unsigned".

I'm biased—we failed to spot in time that s390x is a read-implies-exec 
target because of a vaguely related GCC extension (generalized pointer 
arithmetic).  So I tend to avoid relying on things like that. :)

I switch to size_t for the length argument, though.

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

> Same error message in both cases.

They are differentiated by the flags argument.

>> +      if (getrandom_full (buffer1, sizeof (buffer1), flags)
>> +          && getrandom_full (buffer1, sizeof (buffer1), flags))
>
> Should be buffer1 and buffer2, I imagine.

Right.

>> +/* 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)
>
> Should this be unsigned int, for consistency?

Yes, it should.  Thanks.

I'm also making the applicable changes to the other patch (which is the 
real thing).  Sorry if this isn't clear, this thread is only for 
posterior reference (in case we need this stuff for arc4random).

Florian

[-- Attachment #2: getrandom-with-fallback.patch --]
[-- Type: text/x-patch, Size: 41668 bytes --]

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 glibc (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..43d541f 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 success, 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/random.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 cancellation 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 combination of @var{buffer} and @var{length} arguments specifies an
+invalid memory range.
+
+@item EINTR
+The system call was interrupted (only if @var{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..917d598 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,
+@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..5ce5a84
--- /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 1
+
+/* 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..091dc69
--- /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 are encountered.  */
+static bool errors;
+
+/* Test getrandom with a single buffer length.  */
+static void
+test_length (char *buffer, size_t length, unsigned int 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 (%zu, 0x%x): %m\n", length, flags);
+          errors = true;
+        }
+    }
+  if (ret != length)
+    {
+      if (flags & GRND_RANDOM)
+        {
+          if (ret == 0 || ret > length)
+            {
+              printf ("error: getrandom (%zu, 0x%x) returned %zd\n",
+                      length, flags, ret);
+              errors = true;
+            }
+        }
+      else
+        {
+          printf ("error: getrandom (%zu, 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 (%zu, 0x%x) returned all-zero bytes\n",
+                  length, flags);
+          errors = true;
+        }
+    }
+  if (memcmp (buffer + length, "123", 4) != 0)
+    {
+      printf ("error: getrandom (%zu, 0x%x) wrote spurious bytes\n",
+              length, flags);
+      errors = true;
+    }
+}
+
+/* Call getrandom repeatedly to fill the buffer.  */
+static bool
+getrandom_full (char *buffer, size_t length, unsigned int flags)
+{
+  char *end = buffer + length;
+  while (buffer < end)
+    {
+      ssize_t ret = getrandom (buffer, end - buffer, flags);
+      if (ret < 0)
+        {
+          printf ("error: getrandom (%zu, 0x%x): %m\n", length, flags);
+          errors = true;
+          return false;
+        }
+      buffer += ret;
+    }
+
+  return true;
+}
+
+static void
+test_flags (unsigned int 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 (buffer2, sizeof (buffer2), 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..d4c1434
--- /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 (unsigned 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..bab2774
--- /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
+     report 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 missing 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

^ permalink raw reply	[flat|nested] 62+ messages in thread

* [PATCH v7] getrandom system call wrapper [BZ #17252]
@ 2016-11-14 17:45 ` Florian Weimer
  2016-11-14 18:29   ` Zack Weinberg
  2016-11-17  6:21   ` Mike Frysinger
  0 siblings, 2 replies; 62+ messages in thread
From: Florian Weimer @ 2016-11-14 17:45 UTC (permalink / raw)
  To: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 742 bytes --]

This patch switches back to the ssize_t return time.  This goes against 
Theodore Ts'o preference, but seems to reflect the consensus from the 
largery community.

I weakened the protection against accidental interposition somewhat. 
Since the declaration is a new header file, I do not use a function-like 
macro to prevent a definition of a function named “getrandom”, and 
non-GNU compilers do not get any redirection.  The rationale is that if 
you interpose the function after including <sys/random.h>, you probably 
know what you are doing.  The redirect to __libc_getrandom still 
provides interposition protection if other translation units define a 
getrandom function without knowledge of <sys/random.h>.

Thanks,
Florian

[-- Attachment #2: getrandom-v7.patch --]
[-- Type: text/x-patch, Size: 31323 bytes --]

Add getrandom system call and <sys/random.h> header file [BZ #17252]

2016-11-14  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.25): Add getrandom, __libc_getrandom.
	* stdlib/getrandom.c: New file.
	* stdlib/tst-getrandom.c: Likewise.
	* manual/crypt.texi (Unpredictable Bytes): New section.
	* manual/math.texi (Pseudo-Random Numbers): Add cross-reference.
	* sysdeps/arm/nacl/libc.abilist: Add __libc_getrandom, 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 65184b1..40f3ce4 100644
--- a/NEWS
+++ b/NEWS
@@ -67,6 +67,8 @@ Version 2.25
 * The functions strfromd, strfromf, and strfroml, from ISO/IEC TS 18661-1:2014,
   are added to libc.  They convert a floating-point number into string.
 
+* The getrandom function and the <sys/random.h> header file have been added.
+
 * The <sys/quota.h> header now includes the <linux/quota.h> header.  Support
   for the Linux quota interface which predates kernel version 2.4.22 has
   been removed.
diff --git a/manual/crypt.texi b/manual/crypt.texi
index 9f44740..f99b8be 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,69 @@ 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 success, 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/random.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
+
+The @code{getrandom} function is a cancellation point.
+
+Even access to the non-blocking pool can block if the system has just
+booted and the pool has not yet been initialized.
+
+The @code{getrandom} function can fail with several errors, some of
+which are listed below.  In addition, the function may not fill the
+buffer completely and return a value less than @var{length}.
+
+@table @code
+@item ENOSYS
+The kernel does not implement the @code{getrandom} system call.
+
+@item EAGAIN
+No random data was available and @code{GRND_NONBLOCK} was specified in
+@var{flags}.
+
+@item EFAULT
+The combination of @var{buffer} and @var{length} arguments specifies
+an invalid memory range.
+
+@item EINTR
+The system call was interrupted.  During the system boot process, before
+the kernel randomness pool is initialized, this can happen even if
+@var{flags} is zero.
+
+@item EINVAL
+The @var{flags} argument contains an invalid combination of flags.
+@end table
+
+@end deftypefun
diff --git a/manual/math.texi b/manual/math.texi
index b4bb323..6c0d460 100644
--- a/manual/math.texi
+++ b/manual/math.texi
@@ -1414,7 +1414,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,
+@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 3cce9d9..6c4ed22 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						      \
 	strfromf strfromd strfroml					      \
 	strtol strtoul strtoll strtoull					      \
 	strtol_l strtoul_l strtoll_l strtoull_l				      \
@@ -79,7 +79,8 @@ tests		:= tst-strtol tst-strtod testmb testrand testsort testdiv   \
 		   tst-setcontext3 tst-tls-atexit-nodelete		    \
 		   tst-strtol-locale tst-strtod-nan-locale tst-strfmon_l    \
 		   tst-quick_exit tst-thread-quick_exit tst-width	    \
-		   tst-width-stdint tst-strfrom tst-strfrom-locale
+		   tst-width-stdint tst-strfrom tst-strfrom-locale \
+		   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 54416b7..15905cf 100644
--- a/stdlib/Versions
+++ b/stdlib/Versions
@@ -115,6 +115,7 @@ libc {
   GLIBC_2.25 {
     # s*
     strfromd; strfromf; strfroml;
+    getrandom; __libc_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..a7288eb
--- /dev/null
+++ b/stdlib/getrandom.c
@@ -0,0 +1,33 @@
+/* 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
+__libc_getrandom (void *buffer, size_t length, unsigned int flags)
+{
+  __set_errno (ENOSYS);
+  return -1;
+}
+
+stub_warning (__libc_getrandom)
+
+weak_alias (__libc_getrandom, getrandom)
diff --git a/stdlib/sys/random.h b/stdlib/sys/random.h
new file mode 100644
index 0000000..4d2874f
--- /dev/null
+++ b/stdlib/sys/random.h
@@ -0,0 +1,51 @@
+/* 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 1
+
+#include <features.h>
+#include <sys/types.h>
+
+/* Flags for use with getrandom.  */
+#define GRND_NONBLOCK 1
+#define GRND_RANDOM 2
+
+__BEGIN_DECLS
+
+/* Write LENGTH bytes of randomness starting at BUFFER.  Returns the
+   number of bytes written, or -1 on error.  */
+#ifdef __REDIRECT
+/* For GNU compilers: Redirect getrandom to __libc_getrandom, to
+   protect against accidental interposition.  (Application code should
+   still use the getrandom symbol.)  */
+ssize_t __libc_getrandom (void *__buffer, size_t __length,
+                          unsigned int __flags) __wur;
+extern ssize_t __REDIRECT (getrandom,
+                       (void *__buffer, size_t __length,
+                        unsigned int __flags),
+                       __libc_getrandom);
+#else
+/* Non-GNU compilers call getrandom instead.  */
+ssize_t getrandom (void *__buffer, size_t __length, unsigned int __flags)
+  __wur;
+#endif /* __REDIRECT */
+
+__END_DECLS
+
+#endif /* _SYS_RANDOM_H */
diff --git a/stdlib/tst-getrandom.c b/stdlib/tst-getrandom.c
new file mode 100644
index 0000000..d8816b8
--- /dev/null
+++ b/stdlib/tst-getrandom.c
@@ -0,0 +1,166 @@
+/* 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 are encountered.  */
+static bool errors;
+
+/* Test getrandom with a single buffer length.  */
+static void
+test_length (char *buffer, size_t length, unsigned int 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 (%zu, 0x%x): %m\n", length, flags);
+          errors = true;
+        }
+    }
+  if (ret != length)
+    {
+      if (flags & GRND_RANDOM)
+        {
+          if (ret == 0 || ret > length)
+            {
+              printf ("error: getrandom (%zu, 0x%x) returned %zd\n",
+                      length, flags, ret);
+              errors = true;
+            }
+        }
+      else
+        {
+          printf ("error: getrandom (%zu, 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 (%zu, 0x%x) returned all-zero bytes\n",
+                  length, flags);
+          errors = true;
+        }
+    }
+  if (memcmp (buffer + length, "123", 4) != 0)
+    {
+      printf ("error: getrandom (%zu, 0x%x) wrote spurious bytes\n",
+              length, flags);
+      errors = true;
+    }
+}
+
+/* Call getrandom repeatedly to fill the buffer.  */
+static bool
+getrandom_full (char *buffer, size_t length, unsigned int flags)
+{
+  char *end = buffer + length;
+  while (buffer < end)
+    {
+      ssize_t ret = getrandom (buffer, end - buffer, flags);
+      if (ret < 0)
+        {
+          printf ("error: getrandom (%zu, 0x%x): %m\n", length, flags);
+          errors = true;
+          return false;
+        }
+      buffer += ret;
+    }
+
+  return true;
+}
+
+static void
+test_flags (unsigned int 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 (buffer2, sizeof (buffer2), flags))
+        {
+          if (memcmp (buffer1, buffer2, sizeof (buffer1)) == 0)
+            {
+              printf ("error: getrandom returns constant value\n");
+              errors = true;
+            }
+        }
+    }
+}
+
+static int
+do_test (void)
+{
+  /* Check if getrandom is not supported by this system.  */
+  if (getrandom (NULL, 0, 0) == -1 && errno == ENOSYS)
+    return 77;
+
+  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 807e43d..f52e7e7 100644
--- a/sysdeps/arm/nacl/libc.abilist
+++ b/sysdeps/arm/nacl/libc.abilist
@@ -1843,6 +1843,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 gnu_dev_major F
 GLIBC_2.25 gnu_dev_makedev F
 GLIBC_2.25 gnu_dev_minor F
diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
index 2254c76..79483ea 100644
--- a/sysdeps/unix/syscalls.list
+++ b/sysdeps/unix/syscalls.list
@@ -100,3 +100,4 @@ utimes		-	utimes		i:sp	__utimes	utimes
 vhangup		-	vhangup		i:i	vhangup
 write		-	write		Ci:ibn	__libc_write	__write write
 writev		-	writev		Ci:ipi	__writev	writev
+getrandom	-	getrandom	Ci:bni  __libc_getrandom	getrandom
diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
index 77accdf..77a2231 100644
--- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
@@ -2090,6 +2090,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
index 659b7fc..922e7c3 100644
--- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
+++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
@@ -2001,6 +2001,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
index 8bc979a..7831eb2 100644
--- a/sysdeps/unix/sysv/linux/arm/libc.abilist
+++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
@@ -91,6 +91,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
index 299b705..f6623b7 100644
--- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
+++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
@@ -1855,6 +1855,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
index f00345f..ef04a40 100644
--- a/sysdeps/unix/sysv/linux/i386/libc.abilist
+++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
@@ -2013,6 +2013,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
index e5fcf88..37dde9d 100644
--- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
@@ -1877,6 +1877,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
index 8f382f6..b236ba8 100644
--- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
@@ -92,6 +92,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
index 320b7fe..0983296 100644
--- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
+++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
@@ -1969,6 +1969,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
index 21b1426..6cd5093 100644
--- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
+++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
@@ -2090,6 +2090,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
index 5c4b596..67c0ce0 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
@@ -1944,6 +1944,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
index 001fa6c..88b9f5f 100644
--- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
@@ -1942,6 +1942,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
index 2d87001..b2bfc81 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
@@ -1940,6 +1940,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
index aa1ee66..2cb3e46 100644
--- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
@@ -1935,6 +1935,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
index 2471d68..bd3db24 100644
--- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
+++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
@@ -2131,6 +2131,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
index 4b0cde8..317c8ba 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
@@ -1973,6 +1973,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
index 0557c16..0774b80 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
@@ -1978,6 +1978,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
index 821384e..174f8b2 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
@@ -2178,6 +2178,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
index c40a3f1..b364cae 100644
--- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
@@ -92,6 +92,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
index 5b39a60..66168b9 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
@@ -1973,6 +1973,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
index a9db32f..0e99054 100644
--- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
@@ -1874,6 +1874,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
index 294af0a..c47d2ac 100644
--- a/sysdeps/unix/sysv/linux/sh/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
@@ -1859,6 +1859,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
index 32747bd..923e598 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
@@ -1965,6 +1965,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
index b0ac4d4..836dabb 100644
--- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
@@ -1903,6 +1903,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
index 4d92d81..2f7d425 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
@@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
index a68aef7..5a240a4 100644
--- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
@@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
index 4d92d81..2f7d425 100644
--- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
+++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
@@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
index b8623fc..aa57670 100644
--- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
@@ -1854,6 +1854,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F
diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
index a61d874..1a7bcea 100644
--- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
+++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
@@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
 GLIBC_2.24 GLIBC_2.24 A
 GLIBC_2.24 quick_exit F
 GLIBC_2.25 GLIBC_2.25 A
+GLIBC_2.25 __libc_getrandom F
+GLIBC_2.25 getrandom F
 GLIBC_2.25 strfromd F
 GLIBC_2.25 strfromf F
 GLIBC_2.25 strfroml F

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-14 17:45 ` [PATCH v7] getrandom system call wrapper " Florian Weimer
@ 2016-11-14 18:29   ` Zack Weinberg
  2016-11-15 20:57     ` Richard Henderson
  2016-11-16 15:11     ` Florian Weimer
  2016-11-17  6:21   ` Mike Frysinger
  1 sibling, 2 replies; 62+ messages in thread
From: Zack Weinberg @ 2016-11-14 18:29 UTC (permalink / raw)
  To: libc-alpha

On 11/14/2016 12:44 PM, Florian Weimer wrote:
> This patch switches back to the ssize_t return time.  This goes against
> Theodore Ts'o preference, but seems to reflect the consensus from the
> largery community.

I still don't think this function should be a cancellation point.

> I weakened the protection against accidental interposition somewhat.
> Since the declaration is a new header file, I do not use a function-like
> macro to prevent a definition of a function named “getrandom”, and
> non-GNU compilers do not get any redirection.

We don't normally do this at all.  I don't understand why this function
should be treated differently.  Can you please explain what concrete
situations, involving real, existing code, you're trying to defend
against here?

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-14 18:29   ` Zack Weinberg
@ 2016-11-15 20:57     ` Richard Henderson
  2016-11-16 15:11     ` Florian Weimer
  1 sibling, 0 replies; 62+ messages in thread
From: Richard Henderson @ 2016-11-15 20:57 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha

On 11/14/2016 07:29 PM, Zack Weinberg wrote:
> On 11/14/2016 12:44 PM, Florian Weimer wrote:
>> I weakened the protection against accidental interposition somewhat.
>> Since the declaration is a new header file, I do not use a function-like
>> macro to prevent a definition of a function named “getrandom”, and
>> non-GNU compilers do not get any redirection.
>
> We don't normally do this at all.  I don't understand why this function
> should be treated differently.  Can you please explain what concrete
> situations, involving real, existing code, you're trying to defend
> against here?

It has been proposed that we do this for all new non-standardized symbols.

Which does make sense from a certain point of view.  As far as I can see it 
can't hurt, and can only help when it comes to inter-operating with user 
binaries that could have legitimately used the symbols until now.


r~

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-14 18:29   ` Zack Weinberg
  2016-11-15 20:57     ` Richard Henderson
@ 2016-11-16 15:11     ` Florian Weimer
  2016-11-16 15:20       ` Zack Weinberg
  1 sibling, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-16 15:11 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha

On 11/14/2016 07:29 PM, Zack Weinberg wrote:
> On 11/14/2016 12:44 PM, Florian Weimer wrote:
>> This patch switches back to the ssize_t return time.  This goes against
>> Theodore Ts'o preference, but seems to reflect the consensus from the
>> largery community.
>
> I still don't think this function should be a cancellation point.

I guess we'll have to agree to disagree on this matter.

>> I weakened the protection against accidental interposition somewhat.
>> Since the declaration is a new header file, I do not use a function-like
>> macro to prevent a definition of a function named “getrandom”, and
>> non-GNU compilers do not get any redirection.
>
> We don't normally do this at all.

See the “Evolution of ELF symbol management” thread.  We do it all the 
time, for the benefit of non-libc DSOs in the glibc conglomerate.  I 
think there is broad consensus that we need to extend this to libstdc++ 
at least (in addition to changes needed to enable C++ compilation 
without _GNU_SOURCE).  And once we are at C++, why stop there?  Even 
dynamic languages with a C extension framework would use this.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-16 15:11     ` Florian Weimer
@ 2016-11-16 15:20       ` Zack Weinberg
  2016-11-16 15:52         ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-11-16 15:20 UTC (permalink / raw)
  To: Florian Weimer, libc-alpha

On 11/16/2016 10:11 AM, Florian Weimer wrote:
> On 11/14/2016 07:29 PM, Zack Weinberg wrote:
>> On 11/14/2016 12:44 PM, Florian Weimer wrote:
>>> This patch switches back to the ssize_t return time.  This goes against
>>> Theodore Ts'o preference, but seems to reflect the consensus from the
>>> largery community.
>>
>> I still don't think this function should be a cancellation point.
> 
> I guess we'll have to agree to disagree on this matter.

I am seriously considering escalating my disagreement here to a formal
objection.  I would like to know why you think it is NECESSARY - not
merely convenient or consistent with other stuff - for this function to
be a cancellation point.

(My basic attitude is that adding new cancellation points is always the
Wrong Thing, and should only be done when _unavoidable_; and in this
particular case it is especially bad since applications are probably
going to assume that this function never fails, blocks, or even writes
fewer bytes than requested to the buffer, no matter how clearly we say
that it might.)

>> We don't normally do this at all.
> 
> See the “Evolution of ELF symbol management” thread.  We do it all the
> time, for the benefit of non-libc DSOs in the glibc conglomerate.  I
> think there is broad consensus that we need to extend this to libstdc++
> at least (in addition to changes needed to enable C++ compilation
> without _GNU_SOURCE).  And once we are at C++, why stop there?  Even
> dynamic languages with a C extension framework would use this.

See the reply I'm about to post in that thread.

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-16 15:20       ` Zack Weinberg
@ 2016-11-16 15:52         ` Florian Weimer
  2016-11-16 16:41           ` Zack Weinberg
  2016-11-16 18:02           ` Torvald Riegel
  0 siblings, 2 replies; 62+ messages in thread
From: Florian Weimer @ 2016-11-16 15:52 UTC (permalink / raw)
  To: Zack Weinberg, libc-alpha

On 11/16/2016 04:20 PM, Zack Weinberg wrote:
> On 11/16/2016 10:11 AM, Florian Weimer wrote:
>> On 11/14/2016 07:29 PM, Zack Weinberg wrote:
>>> On 11/14/2016 12:44 PM, Florian Weimer wrote:
>>>> This patch switches back to the ssize_t return time.  This goes against
>>>> Theodore Ts'o preference, but seems to reflect the consensus from the
>>>> largery community.
>>>
>>> I still don't think this function should be a cancellation point.
>>
>> I guess we'll have to agree to disagree on this matter.
>
> I am seriously considering escalating my disagreement here to a formal
> objection.  I would like to know why you think it is NECESSARY - not
> merely convenient or consistent with other stuff - for this function to
> be a cancellation point.

It's necessary if you ever want to cancel a hanging getrandom in a 
context where you cannot install a signal handler (so that you can 
trigger EINTR when getrandom is stuck).

I really don't understand why cancellation points are widely considered 
as evil.  Most code does not use cancellation in a correct way, and it 
will not improve if we simply stop adding new cancellation points. 
Furthermore, it's easy to make a cancellation point go away (just switch 
the cancel state around the call), but at least in library code, it is 
impossible to introduce cancellation into a system call where the 
wrapper does not support it (because you cannot fake your own version of 
cancellation with a do-nothing signal handler).

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-16 15:52         ` Florian Weimer
@ 2016-11-16 16:41           ` Zack Weinberg
  2016-11-17 13:02             ` Florian Weimer
  2016-11-16 18:02           ` Torvald Riegel
  1 sibling, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-11-16 16:41 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On Wed, Nov 16, 2016 at 10:52 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>> I am seriously considering escalating my disagreement here to a
>> formal objection.  I would like to know why you think it is
>> NECESSARY - not merely convenient or consistent with other stuff -
>> for this function to be a cancellation point.
>
> It's necessary if you ever want to cancel a hanging getrandom in a
> context where you cannot install a signal handler (so that you can
> trigger EINTR when getrandom is stuck).

That only pushes the question back a level.  When would it ever be
necessary to do that?  Be as concrete as you possibly can.  Actual
code from a real program, if possible.

> I really don't understand why cancellation points are widely
> considered as evil.  Most code does not use cancellation in a
> correct way, and it will not improve if we simply stop adding new
> cancellation points.

I would argue that most code does not use cancellation correctly in
large part _because_ the set of cancellation points is so large and
amorphous.  It is the same problem that people have with exceptions in
C++; because practically everything you might do exposes you to
cancellation, it's so difficult to know how to write cancel-safe code
that people just apply the big hammer of not using it at all.  Another
useful example is multithreading versus coroutines with explicit yield
points---the latter can be less efficient and/or more verbose, but
it's so much easier to debug that it's worth it.

There's not a lot we can do about the cancellation-point set in POSIX
being so large, but we can at least not make things worse, by not
adding additional cancellation points.

> at least in library code, it is impossible to introduce cancellation
> into a system call where the wrapper does not support it (because
> you cannot fake your own version of cancellation with a do-nothing
> signal handler).

From the perspective that as few operations as possible should be
cancellation points, this is a Good Thing.  And I don't see why it
would be a problem for getrandom in particular.

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-16 15:52         ` Florian Weimer
  2016-11-16 16:41           ` Zack Weinberg
@ 2016-11-16 18:02           ` Torvald Riegel
  2016-11-16 19:53             ` Adhemerval Zanella
  1 sibling, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-16 18:02 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Zack Weinberg, libc-alpha

On Wed, 2016-11-16 at 16:52 +0100, Florian Weimer wrote:
> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
> > On 11/16/2016 10:11 AM, Florian Weimer wrote:
> >> On 11/14/2016 07:29 PM, Zack Weinberg wrote:
> >>> On 11/14/2016 12:44 PM, Florian Weimer wrote:
> >>>> This patch switches back to the ssize_t return time.  This goes against
> >>>> Theodore Ts'o preference, but seems to reflect the consensus from the
> >>>> largery community.
> >>>
> >>> I still don't think this function should be a cancellation point.
> >>
> >> I guess we'll have to agree to disagree on this matter.
> >
> > I am seriously considering escalating my disagreement here to a formal
> > objection.  I would like to know why you think it is NECESSARY - not
> > merely convenient or consistent with other stuff - for this function to
> > be a cancellation point.
> 
> It's necessary if you ever want to cancel a hanging getrandom in a 
> context where you cannot install a signal handler (so that you can 
> trigger EINTR when getrandom is stuck).

I think it would be better to split the getrandom that is a cancellation
point into two functions, getrandom (not a cancellation point) and
getrandom_cancelable (is a cancellation point).  This way, the
functionality is available for programs but requires explicit opt-in,
while the default is not going to lead to surprises in the expected
common case (ie, when randomness is available).  I don't think the
opt-in is a problem because as you said, cancellation requires careful
programming anyway.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-16 18:02           ` Torvald Riegel
@ 2016-11-16 19:53             ` Adhemerval Zanella
  2016-11-17 12:52               ` Torvald Riegel
  0 siblings, 1 reply; 62+ messages in thread
From: Adhemerval Zanella @ 2016-11-16 19:53 UTC (permalink / raw)
  To: libc-alpha



On 16/11/2016 16:02, Torvald Riegel wrote:
> On Wed, 2016-11-16 at 16:52 +0100, Florian Weimer wrote:
>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>>> On 11/16/2016 10:11 AM, Florian Weimer wrote:
>>>> On 11/14/2016 07:29 PM, Zack Weinberg wrote:
>>>>> On 11/14/2016 12:44 PM, Florian Weimer wrote:
>>>>>> This patch switches back to the ssize_t return time.  This goes against
>>>>>> Theodore Ts'o preference, but seems to reflect the consensus from the
>>>>>> largery community.
>>>>>
>>>>> I still don't think this function should be a cancellation point.
>>>>
>>>> I guess we'll have to agree to disagree on this matter.
>>>
>>> I am seriously considering escalating my disagreement here to a formal
>>> objection.  I would like to know why you think it is NECESSARY - not
>>> merely convenient or consistent with other stuff - for this function to
>>> be a cancellation point.
>>
>> It's necessary if you ever want to cancel a hanging getrandom in a 
>> context where you cannot install a signal handler (so that you can 
>> trigger EINTR when getrandom is stuck).
> 
> I think it would be better to split the getrandom that is a cancellation
> point into two functions, getrandom (not a cancellation point) and
> getrandom_cancelable (is a cancellation point).  This way, the
> functionality is available for programs but requires explicit opt-in,
> while the default is not going to lead to surprises in the expected
> common case (ie, when randomness is available).  I don't think the
> opt-in is a problem because as you said, cancellation requires careful
> programming anyway.
> 

I would advise against adding another symbol, it only adds complexity
and most likely one interface would be preferable from application
point of view.

Considering portability, why not following current approach from other
OS/libc? User will probably create more highly level interfaces based
underlying facilities, so I see trying to follow current interface
semantics in a non standard interface seems a better approach.

For instance, OpenBSD getentropy seems a to just direct syscall, so
not cancellation handling (src/libexec/ld.so/<architecture>/ldasm.S).
FreeBSD does not have a similar syscall, but provides a sysctl/KERN_ARND
that does basically the same.  I am not sure about Solaris.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-14 17:45 ` [PATCH v7] getrandom system call wrapper " Florian Weimer
  2016-11-14 18:29   ` Zack Weinberg
@ 2016-11-17  6:21   ` Mike Frysinger
  2016-11-18 13:21     ` Florian Weimer
  1 sibling, 1 reply; 62+ messages in thread
From: Mike Frysinger @ 2016-11-17  6:21 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

[-- Attachment #1: Type: text/plain, Size: 17670 bytes --]

On 14 Nov 2016 18:44, Florian Weimer wrote:

just nits at this point

> +/* Flags for use with getrandom.  */
> +#define GRND_NONBLOCK 1
> +#define GRND_RANDOM 2

if they're bit flags, should we be doing 0x1/0x2 etc ?  otherwise this
will turn into 4, 8, 16, 32, 64, etc... which gets ugly.  the kernel
headers use hex constants.

> +/* Test getrandom with a single buffer length.  */
> +static void
> +test_length (char *buffer, size_t length, unsigned int flags)
> +{
> +  memset (buffer, 0, length);
> +  strcpy (buffer + length, "123");

while this works, it seems pointlessly fragile.  can't you treat it like
a normal "this is the length of the buffer" and carve out space at the
end yourself ?  i.e.
	memset (buffer, 0, length);
	static const char canary[] = "123";
	size_t canary_len = sizeof(canary);
	length -= canary_len;
	strcpy (buffer + length, canary);
	...

	ssize_t ret = getrandom (buffer, length - , flags);

> +  if (ret < 0)
> +    {
> +      if (!((flags & GRND_RANDOM)
> +            && (flags & GRND_NONBLOCK)
> +            && errno != EAGAIN))

seems like it'd be more readable to distribute the ! and to combine the
flags check into a single mask ?  i have to read these lines a few times
to digest what exactly the code is trying to do.

> +      if (getrandom_full (buffer1, sizeof (buffer1), flags)
> +          && getrandom_full (buffer2, sizeof (buffer2), flags))
> +        {
> +          if (memcmp (buffer1, buffer2, sizeof (buffer1)) == 0)

maybe also add a comment that likelihood of this being the same is
extremely rare too.

  return 77;
> +
> +  for (int use_random = 0; use_random < 2; ++use_random)
> +    for (int use_nonblock = 0; use_nonblock < 2; ++use_nonblock)
> +      {
> +        int flags = 0;

unsigned to match the API ?
-mike

> +        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 807e43d..f52e7e7 100644
> --- a/sysdeps/arm/nacl/libc.abilist
> +++ b/sysdeps/arm/nacl/libc.abilist
> @@ -1843,6 +1843,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 gnu_dev_major F
>  GLIBC_2.25 gnu_dev_makedev F
>  GLIBC_2.25 gnu_dev_minor F
> diff --git a/sysdeps/unix/syscalls.list b/sysdeps/unix/syscalls.list
> index 2254c76..79483ea 100644
> --- a/sysdeps/unix/syscalls.list
> +++ b/sysdeps/unix/syscalls.list
> @@ -100,3 +100,4 @@ utimes		-	utimes		i:sp	__utimes	utimes
>  vhangup		-	vhangup		i:i	vhangup
>  write		-	write		Ci:ibn	__libc_write	__write write
>  writev		-	writev		Ci:ipi	__writev	writev
> +getrandom	-	getrandom	Ci:bni  __libc_getrandom	getrandom
> diff --git a/sysdeps/unix/sysv/linux/aarch64/libc.abilist b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> index 77accdf..77a2231 100644
> --- a/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/aarch64/libc.abilist
> @@ -2090,6 +2090,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/alpha/libc.abilist b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> index 659b7fc..922e7c3 100644
> --- a/sysdeps/unix/sysv/linux/alpha/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/alpha/libc.abilist
> @@ -2001,6 +2001,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/arm/libc.abilist b/sysdeps/unix/sysv/linux/arm/libc.abilist
> index 8bc979a..7831eb2 100644
> --- a/sysdeps/unix/sysv/linux/arm/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/arm/libc.abilist
> @@ -91,6 +91,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/hppa/libc.abilist b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> index 299b705..f6623b7 100644
> --- a/sysdeps/unix/sysv/linux/hppa/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/hppa/libc.abilist
> @@ -1855,6 +1855,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/i386/libc.abilist b/sysdeps/unix/sysv/linux/i386/libc.abilist
> index f00345f..ef04a40 100644
> --- a/sysdeps/unix/sysv/linux/i386/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/i386/libc.abilist
> @@ -2013,6 +2013,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/ia64/libc.abilist b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> index e5fcf88..37dde9d 100644
> --- a/sysdeps/unix/sysv/linux/ia64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/ia64/libc.abilist
> @@ -1877,6 +1877,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> index 8f382f6..b236ba8 100644
> --- a/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/coldfire/libc.abilist
> @@ -92,6 +92,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> index 320b7fe..0983296 100644
> --- a/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/m68k/m680x0/libc.abilist
> @@ -1969,6 +1969,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/microblaze/libc.abilist b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> index 21b1426..6cd5093 100644
> --- a/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/microblaze/libc.abilist
> @@ -2090,6 +2090,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> index 5c4b596..67c0ce0 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/fpu/libc.abilist
> @@ -1944,6 +1944,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> index 001fa6c..88b9f5f 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips32/nofpu/libc.abilist
> @@ -1942,6 +1942,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> index 2d87001..b2bfc81 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n32/libc.abilist
> @@ -1940,6 +1940,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> index aa1ee66..2cb3e46 100644
> --- a/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/mips/mips64/n64/libc.abilist
> @@ -1935,6 +1935,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/nios2/libc.abilist b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> index 2471d68..bd3db24 100644
> --- a/sysdeps/unix/sysv/linux/nios2/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/nios2/libc.abilist
> @@ -2131,6 +2131,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> index 4b0cde8..317c8ba 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/fpu/libc.abilist
> @@ -1973,6 +1973,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> index 0557c16..0774b80 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc32/nofpu/libc.abilist
> @@ -1978,6 +1978,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> index 821384e..174f8b2 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc-le.abilist
> @@ -2178,6 +2178,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> index c40a3f1..b364cae 100644
> --- a/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/powerpc/powerpc64/libc.abilist
> @@ -92,6 +92,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> index 5b39a60..66168b9 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-32/libc.abilist
> @@ -1973,6 +1973,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> index a9db32f..0e99054 100644
> --- a/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/s390/s390-64/libc.abilist
> @@ -1874,6 +1874,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/sh/libc.abilist b/sysdeps/unix/sysv/linux/sh/libc.abilist
> index 294af0a..c47d2ac 100644
> --- a/sysdeps/unix/sysv/linux/sh/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sh/libc.abilist
> @@ -1859,6 +1859,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> index 32747bd..923e598 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc32/libc.abilist
> @@ -1965,6 +1965,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> index b0ac4d4..836dabb 100644
> --- a/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/sparc/sparc64/libc.abilist
> @@ -1903,6 +1903,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> index 4d92d81..2f7d425 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx32/libc.abilist
> @@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> index a68aef7..5a240a4 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilegx/tilegx64/libc.abilist
> @@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> index 4d92d81..2f7d425 100644
> --- a/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/tile/tilepro/libc.abilist
> @@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> index b8623fc..aa57670 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/64/libc.abilist
> @@ -1854,6 +1854,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F
> diff --git a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> index a61d874..1a7bcea 100644
> --- a/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> +++ b/sysdeps/unix/sysv/linux/x86_64/x32/libc.abilist
> @@ -2097,6 +2097,8 @@ GLIBC_2.23 fts64_set F
>  GLIBC_2.24 GLIBC_2.24 A
>  GLIBC_2.24 quick_exit F
>  GLIBC_2.25 GLIBC_2.25 A
> +GLIBC_2.25 __libc_getrandom F
> +GLIBC_2.25 getrandom F
>  GLIBC_2.25 strfromd F
>  GLIBC_2.25 strfromf F
>  GLIBC_2.25 strfroml F


[-- Attachment #2: Digital signature --]
[-- Type: application/pgp-signature, Size: 819 bytes --]

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-16 19:53             ` Adhemerval Zanella
@ 2016-11-17 12:52               ` Torvald Riegel
  2016-11-18  8:28                 ` Szabolcs Nagy
  0 siblings, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-17 12:52 UTC (permalink / raw)
  To: Adhemerval Zanella; +Cc: libc-alpha

On Wed, 2016-11-16 at 17:52 -0200, Adhemerval Zanella wrote:
> 
> On 16/11/2016 16:02, Torvald Riegel wrote:
> > On Wed, 2016-11-16 at 16:52 +0100, Florian Weimer wrote:
> >> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
> >>> On 11/16/2016 10:11 AM, Florian Weimer wrote:
> >>>> On 11/14/2016 07:29 PM, Zack Weinberg wrote:
> >>>>> On 11/14/2016 12:44 PM, Florian Weimer wrote:
> >>>>>> This patch switches back to the ssize_t return time.  This goes against
> >>>>>> Theodore Ts'o preference, but seems to reflect the consensus from the
> >>>>>> largery community.
> >>>>>
> >>>>> I still don't think this function should be a cancellation point.
> >>>>
> >>>> I guess we'll have to agree to disagree on this matter.
> >>>
> >>> I am seriously considering escalating my disagreement here to a formal
> >>> objection.  I would like to know why you think it is NECESSARY - not
> >>> merely convenient or consistent with other stuff - for this function to
> >>> be a cancellation point.
> >>
> >> It's necessary if you ever want to cancel a hanging getrandom in a 
> >> context where you cannot install a signal handler (so that you can 
> >> trigger EINTR when getrandom is stuck).
> > 
> > I think it would be better to split the getrandom that is a cancellation
> > point into two functions, getrandom (not a cancellation point) and
> > getrandom_cancelable (is a cancellation point).  This way, the
> > functionality is available for programs but requires explicit opt-in,
> > while the default is not going to lead to surprises in the expected
> > common case (ie, when randomness is available).  I don't think the
> > opt-in is a problem because as you said, cancellation requires careful
> > programming anyway.
> > 
> 
> I would advise against adding another symbol, it only adds complexity
> and most likely one interface would be preferable from application
> point of view.

We could add a parameter too that determines whether it is a
cancellation point.  That avoids your concern about adding another
symbol, and programmers will still have to make a conscious decision
about cancellation.  I don't see how this adds complexity; the
complexity in there is having to choose between the different semantics,
or be aware that it's just one of them when we know that just one of
them is not a one-size-fits-all for all use cases.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-16 16:41           ` Zack Weinberg
@ 2016-11-17 13:02             ` Florian Weimer
  2016-11-17 13:46               ` Zack Weinberg
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-17 13:02 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

On 11/16/2016 05:41 PM, Zack Weinberg wrote:
> On Wed, Nov 16, 2016 at 10:52 AM, Florian Weimer <fweimer@redhat.com> wrote:
>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>>> I am seriously considering escalating my disagreement here to a
>>> formal objection.  I would like to know why you think it is
>>> NECESSARY - not merely convenient or consistent with other stuff -
>>> for this function to be a cancellation point.
>>
>> It's necessary if you ever want to cancel a hanging getrandom in a
>> context where you cannot install a signal handler (so that you can
>> trigger EINTR when getrandom is stuck).
>
> That only pushes the question back a level.  When would it ever be
> necessary to do that?  Be as concrete as you possibly can.  Actual
> code from a real program, if possible.

It's not clear to me what you are asking here.

Do you mean cancellation in general, or cancellation in conjunction with 
getrandom specifically?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17 13:02             ` Florian Weimer
@ 2016-11-17 13:46               ` Zack Weinberg
  2016-11-17 13:50                 ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-11-17 13:46 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On 11/17/2016 08:02 AM, Florian Weimer wrote:
> On 11/16/2016 05:41 PM, Zack Weinberg wrote:
>> On Wed, Nov 16, 2016 at 10:52 AM, Florian Weimer <fweimer@redhat.com>
>> wrote:
>>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>>>> I am seriously considering escalating my disagreement here to a
>>>> formal objection.  I would like to know why you think it is
>>>> NECESSARY - not merely convenient or consistent with other stuff -
>>>> for this function to be a cancellation point.
>>>
>>> It's necessary if you ever want to cancel a hanging getrandom in a
>>> context where you cannot install a signal handler (so that you can
>>> trigger EINTR when getrandom is stuck).
>>
>> That only pushes the question back a level.  When would it ever be
>> necessary to do that?  Be as concrete as you possibly can.  Actual
>> code from a real program, if possible.
> 
> It's not clear to me what you are asking here.
> 
> Do you mean cancellation in general, or cancellation in conjunction with
> getrandom specifically?

Sorry.  I meant cancellation specifically of a thread hanging in getrandom.

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17 13:46               ` Zack Weinberg
@ 2016-11-17 13:50                 ` Florian Weimer
  2016-11-17 13:56                   ` Zack Weinberg
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-17 13:50 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

On 11/17/2016 02:45 PM, Zack Weinberg wrote:
> On 11/17/2016 08:02 AM, Florian Weimer wrote:
>> On 11/16/2016 05:41 PM, Zack Weinberg wrote:
>>> On Wed, Nov 16, 2016 at 10:52 AM, Florian Weimer <fweimer@redhat.com>
>>> wrote:
>>>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>>>>> I am seriously considering escalating my disagreement here to a
>>>>> formal objection.  I would like to know why you think it is
>>>>> NECESSARY - not merely convenient or consistent with other stuff -
>>>>> for this function to be a cancellation point.
>>>>
>>>> It's necessary if you ever want to cancel a hanging getrandom in a
>>>> context where you cannot install a signal handler (so that you can
>>>> trigger EINTR when getrandom is stuck).
>>>
>>> That only pushes the question back a level.  When would it ever be
>>> necessary to do that?  Be as concrete as you possibly can.  Actual
>>> code from a real program, if possible.
>>
>> It's not clear to me what you are asking here.
>>
>> Do you mean cancellation in general, or cancellation in conjunction with
>> getrandom specifically?
>
> Sorry.  I meant cancellation specifically of a thread hanging in getrandom.

I'm not sure how I can provide that, considering that there is currently 
no way to cancel a thread which hangs in getrandom because we do not 
provide a way for applications to implement system calls as cancellation 
points (unless we provide a wrapper for the specific system call, of 
course).

Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17 13:50                 ` Florian Weimer
@ 2016-11-17 13:56                   ` Zack Weinberg
  2016-11-17 15:24                     ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-11-17 13:56 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On 11/17/2016 08:50 AM, Florian Weimer wrote:
> On 11/17/2016 02:45 PM, Zack Weinberg wrote:
>> On 11/17/2016 08:02 AM, Florian Weimer wrote:
>>> On 11/16/2016 05:41 PM, Zack Weinberg wrote:
>>>> On Wed, Nov 16, 2016 at 10:52 AM, Florian Weimer <fweimer@redhat.com>
>>>> wrote:
>>>>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>>>>>> I am seriously considering escalating my disagreement here to a
>>>>>> formal objection.  I would like to know why you think it is
>>>>>> NECESSARY - not merely convenient or consistent with other stuff -
>>>>>> for this function to be a cancellation point.
>>>>>
>>>>> It's necessary if you ever want to cancel a hanging getrandom in a
>>>>> context where you cannot install a signal handler (so that you can
>>>>> trigger EINTR when getrandom is stuck).
>>>>
>>>> That only pushes the question back a level.  When would it ever be
>>>> necessary to do that?  Be as concrete as you possibly can.  Actual
>>>> code from a real program, if possible.
>>>
>>> It's not clear to me what you are asking here.
>>>
>>> Do you mean cancellation in general, or cancellation in conjunction with
>>> getrandom specifically?
>>
>> Sorry.  I meant cancellation specifically of a thread hanging in
>> getrandom.
> 
> I'm not sure how I can provide that, considering that there is currently
> no way to cancel a thread which hangs in getrandom because we do not
> provide a way for applications to implement system calls as cancellation
> points (unless we provide a wrapper for the specific system call, of
> course).

What I'm asking for is evidence that that is actually a problem for at
least one real application.  Also evidence that making getrandom a
cancellation point _won't_ break programs that naively assume it can
never fail.

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17 13:56                   ` Zack Weinberg
@ 2016-11-17 15:24                     ` Florian Weimer
  2016-11-17 17:16                       ` Zack Weinberg
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-17 15:24 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: GNU C Library

On 11/17/2016 02:56 PM, Zack Weinberg wrote:
> On 11/17/2016 08:50 AM, Florian Weimer wrote:
>> On 11/17/2016 02:45 PM, Zack Weinberg wrote:
>>> On 11/17/2016 08:02 AM, Florian Weimer wrote:
>>>> On 11/16/2016 05:41 PM, Zack Weinberg wrote:
>>>>> On Wed, Nov 16, 2016 at 10:52 AM, Florian Weimer <fweimer@redhat.com>
>>>>> wrote:
>>>>>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>>>>>>> I am seriously considering escalating my disagreement here to a
>>>>>>> formal objection.  I would like to know why you think it is
>>>>>>> NECESSARY - not merely convenient or consistent with other stuff -
>>>>>>> for this function to be a cancellation point.
>>>>>>
>>>>>> It's necessary if you ever want to cancel a hanging getrandom in a
>>>>>> context where you cannot install a signal handler (so that you can
>>>>>> trigger EINTR when getrandom is stuck).
>>>>>
>>>>> That only pushes the question back a level.  When would it ever be
>>>>> necessary to do that?  Be as concrete as you possibly can.  Actual
>>>>> code from a real program, if possible.
>>>>
>>>> It's not clear to me what you are asking here.
>>>>
>>>> Do you mean cancellation in general, or cancellation in conjunction with
>>>> getrandom specifically?
>>>
>>> Sorry.  I meant cancellation specifically of a thread hanging in
>>> getrandom.
>>
>> I'm not sure how I can provide that, considering that there is currently
>> no way to cancel a thread which hangs in getrandom because we do not
>> provide a way for applications to implement system calls as cancellation
>> points (unless we provide a wrapper for the specific system call, of
>> course).
>
> What I'm asking for is evidence that that is actually a problem for at
> least one real application.

I found this:

<https://opensource.apple.com/source/ppp/ppp-412.3/Helpers/vpnd/ipsecoptions.c>

ipsec_resolver_thread reads from /dev/random, which can block for a very 
long time.  The thread for it is spawned in ipsec_process_prefs, which 
cancels it when got_terminate returns true.  The intent seems to be that 
is terminated on graceful process termination: read in 
ipsec_process_prefs returns EINTR after a signal handler has run which 
makes got_terminate (defined in main.c in the parent directory) return true.

If the read from /dev/random is replaced with a call to getrandom which 
is not a cancellation point, this would like not work as intended.

Is this the kind of stuff you are looking for?

 > Also evidence that making getrandom a
> cancellation point _won't_ break programs that naively assume it can
> never fail.

Cancellation does not add additional error return cases.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17 15:24                     ` Florian Weimer
@ 2016-11-17 17:16                       ` Zack Weinberg
  2016-11-18 10:27                         ` Szabolcs Nagy
  0 siblings, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-11-17 17:16 UTC (permalink / raw)
  To: Florian Weimer; +Cc: GNU C Library

On 11/17/2016 10:24 AM, Florian Weimer wrote:
> On 11/17/2016 02:56 PM, Zack Weinberg wrote:
>>
>> What I'm asking for is evidence that that is actually a problem for at
>> least one real application.
> 
> I found this:
> 
> <https://opensource.apple.com/source/ppp/ppp-412.3/Helpers/vpnd/ipsecoptions.c>
> 
> ipsec_resolver_thread reads from /dev/random, which can block for a very
> long time.  The thread for it is spawned in ipsec_process_prefs, which
> cancels it when got_terminate returns true.  The intent seems to be that
> is terminated on graceful process termination: read in
> ipsec_process_prefs returns EINTR after a signal handler has run which
> makes got_terminate (defined in main.c in the parent directory) return
> true.

It seems to me that this code does not *need* to cancel the
ipsec_resolver_thread when it does, as it is about to call exit() [I
think] which will blow away all threads anyway.

>> Also evidence that making getrandom a
>> cancellation point _won't_ break programs that naively assume it can
>> never fail.
> 
> Cancellation does not add additional error return cases.

It does add additional _failure_ cases.  Suppose a program that expects
threads only to be at risk of cancellation at points where they do
network I/O, and does all the necessary dancing to make that reliable.
These threads are _already_ using getrandom() where available, via a
portability wrapper that will call into the C library if possible, or
make a direct syscall otherwise.  Being a wrapper, it's not a
cancellation point, and the surrounding code relies on that.  Now you
upgrade glibc, and suddenly getrandom() _is_ a cancellation point, and
the threads can now be cancelled in places where their data structures
are internally inconsistent -- and it doesn't matter that getrandom()
doesn't block under normal conditions, because the generic
cancel-testing code will fire anyway.

[This is just the general argument that adding new cancellation points
to the C library can render existing code buggy without notice.]

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17 12:52               ` Torvald Riegel
@ 2016-11-18  8:28                 ` Szabolcs Nagy
  2016-11-18 14:21                   ` Torvald Riegel
  0 siblings, 1 reply; 62+ messages in thread
From: Szabolcs Nagy @ 2016-11-18  8:28 UTC (permalink / raw)
  To: Torvald Riegel, Adhemerval Zanella; +Cc: nd, libc-alpha

On 17/11/16 12:52, Torvald Riegel wrote:
> On Wed, 2016-11-16 at 17:52 -0200, Adhemerval Zanella wrote:
>>
>> On 16/11/2016 16:02, Torvald Riegel wrote:
>>> On Wed, 2016-11-16 at 16:52 +0100, Florian Weimer wrote:
>>>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
>>>>> On 11/16/2016 10:11 AM, Florian Weimer wrote:
>>>>>> On 11/14/2016 07:29 PM, Zack Weinberg wrote:
>>>>>>> On 11/14/2016 12:44 PM, Florian Weimer wrote:
>>>>>>>> This patch switches back to the ssize_t return time.  This goes against
>>>>>>>> Theodore Ts'o preference, but seems to reflect the consensus from the
>>>>>>>> largery community.
>>>>>>>
>>>>>>> I still don't think this function should be a cancellation point.
>>>>>>
>>>>>> I guess we'll have to agree to disagree on this matter.
>>>>>
>>>>> I am seriously considering escalating my disagreement here to a formal
>>>>> objection.  I would like to know why you think it is NECESSARY - not
>>>>> merely convenient or consistent with other stuff - for this function to
>>>>> be a cancellation point.
>>>>
>>>> It's necessary if you ever want to cancel a hanging getrandom in a 
>>>> context where you cannot install a signal handler (so that you can 
>>>> trigger EINTR when getrandom is stuck).
>>>
>>> I think it would be better to split the getrandom that is a cancellation
>>> point into two functions, getrandom (not a cancellation point) and
>>> getrandom_cancelable (is a cancellation point).  This way, the
>>> functionality is available for programs but requires explicit opt-in,
>>> while the default is not going to lead to surprises in the expected
>>> common case (ie, when randomness is available).  I don't think the
>>> opt-in is a problem because as you said, cancellation requires careful
>>> programming anyway.
>>>
>>
>> I would advise against adding another symbol, it only adds complexity
>> and most likely one interface would be preferable from application
>> point of view.
> 
> We could add a parameter too that determines whether it is a
> cancellation point.  That avoids your concern about adding another

why?

use pthread_setcancelstate.

works with all cancellation points not just getrandom.

> symbol, and programmers will still have to make a conscious decision
> about cancellation.  I don't see how this adds complexity; the
> complexity in there is having to choose between the different semantics,
> or be aware that it's just one of them when we know that just one of
> them is not a one-size-fits-all for all use cases.
> 

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17 17:16                       ` Zack Weinberg
@ 2016-11-18 10:27                         ` Szabolcs Nagy
  2016-11-18 15:46                           ` Torvald Riegel
  2016-11-18 18:50                           ` Zack Weinberg
  0 siblings, 2 replies; 62+ messages in thread
From: Szabolcs Nagy @ 2016-11-18 10:27 UTC (permalink / raw)
  To: Zack Weinberg, Florian Weimer; +Cc: nd, GNU C Library

On 17/11/16 17:16, Zack Weinberg wrote:
> On 11/17/2016 10:24 AM, Florian Weimer wrote:
>> On 11/17/2016 02:56 PM, Zack Weinberg wrote:
>>> Also evidence that making getrandom a
>>> cancellation point _won't_ break programs that naively assume it can
>>> never fail.
>>
>> Cancellation does not add additional error return cases.
> 
> It does add additional _failure_ cases.  Suppose a program that expects
> threads only to be at risk of cancellation at points where they do
> network I/O, and does all the necessary dancing to make that reliable.
> These threads are _already_ using getrandom() where available, via a
> portability wrapper that will call into the C library if possible, or
> make a direct syscall otherwise.  Being a wrapper, it's not a
> cancellation point, and the surrounding code relies on that.  Now you
> upgrade glibc, and suddenly getrandom() _is_ a cancellation point, and
> the threads can now be cancelled in places where their data structures
> are internally inconsistent -- and it doesn't matter that getrandom()
> doesn't block under normal conditions, because the generic
> cancel-testing code will fire anyway.
> 
> [This is just the general argument that adding new cancellation points
> to the C library can render existing code buggy without notice.]

there is no existing code that uses glibc getrandom.

a user can easily turn a cancellation point into
a non-cancellation one if desired, but the other
way is not possible.

blocking syscalls have to be cancellation points
otherwise they cannot be called safely from a long
running process that has to remain responsive:
blocked threads can keep piling up and there is no
way to reuse the resources they hold.

[this is the general argument for adding new
blocking syscalls as cancellation points].

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-17  6:21   ` Mike Frysinger
@ 2016-11-18 13:21     ` Florian Weimer
  0 siblings, 0 replies; 62+ messages in thread
From: Florian Weimer @ 2016-11-18 13:21 UTC (permalink / raw)
  To: GNU C Library

On 11/17/2016 07:21 AM, Mike Frysinger wrote:
> On 14 Nov 2016 18:44, Florian Weimer wrote:
>
> just nits at this point
>
>> +/* Flags for use with getrandom.  */
>> +#define GRND_NONBLOCK 1
>> +#define GRND_RANDOM 2
>
> if they're bit flags, should we be doing 0x1/0x2 etc ?  otherwise this
> will turn into 4, 8, 16, 32, 64, etc... which gets ugly.  the kernel
> headers use hex constants.

Okay, I turned this into:

#define GRND_NONBLOCK 0x01
#define GRND_RANDOM 0x02

Do you want more zero padding?

(I'm not a fan of column alignment because it means that future patches 
will have to make whitespace-only changes to change column alignment, 
which slightly obfuscates the actual change.)

>> +/* Test getrandom with a single buffer length.  */
>> +static void
>> +test_length (char *buffer, size_t length, unsigned int flags)
>> +{
>> +  memset (buffer, 0, length);
>> +  strcpy (buffer + length, "123");
>
> while this works, it seems pointlessly fragile.  can't you treat it like
> a normal "this is the length of the buffer" and carve out space at the
> end yourself ?  i.e.

> 	memset (buffer, 0, length);
> 	static const char canary[] = "123";
> 	size_t canary_len = sizeof(canary);
> 	length -= canary_len;
> 	strcpy (buffer + length, canary);
> 	...
>
> 	ssize_t ret = getrandom (buffer, length - , flags);

I don't think this is much clearer.  I'm going to add a comment:

/* Test getrandom with a single buffer length.  NB: The passed-in
    buffer must have room for four extra bytes after the specified
    length, which are used to test that getrandom leaves those bytes
    unchanged.  */

Hopefully this is clear enough.

>
>> +  if (ret < 0)
>> +    {
>> +      if (!((flags & GRND_RANDOM)
>> +            && (flags & GRND_NONBLOCK)
>> +            && errno != EAGAIN))
>
> seems like it'd be more readable to distribute the ! and to combine the
> flags check into a single mask ?  i have to read these lines a few times
> to digest what exactly the code is trying to do.

What about this?

       /* EAGAIN is an expected error with GRND_RANDOM and
          GRND_NONBLOCK.  */
       if ((flags & GRND_RANDOM)
           && (flags & GRND_NONBLOCK)
           && errno == EAGAIN)
         return;
       printf ("error: getrandom (%zu, 0x%x): %m\n", length, flags);
       errors = true;
       return;

The second return was missing before, the old condition was actually wrong.

>> +      if (getrandom_full (buffer1, sizeof (buffer1), flags)
>> +          && getrandom_full (buffer2, sizeof (buffer2), flags))
>> +        {
>> +          if (memcmp (buffer1, buffer2, sizeof (buffer1)) == 0)
>
> maybe also add a comment that likelihood of this being the same is
> extremely rare too.

This should do it:

           /* The probability that these two 8-byte buffers are equal
              is very small (assuming that two subsequent calls to
              getrandom result are independent, uniformly distributed
              random variables).  */

>> +  for (int use_random = 0; use_random < 2; ++use_random)
>> +    for (int use_nonblock = 0; use_nonblock < 2; ++use_nonblock)
>> +      {
>> +        int flags = 0;
>
> unsigned to match the API ?

Right, thanks.

Do you have any comments about the matter of the cancellation point and 
the redirect to __libc_getrandom?

Thanks,
florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18  8:28                 ` Szabolcs Nagy
@ 2016-11-18 14:21                   ` Torvald Riegel
  2016-11-18 15:13                     ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-18 14:21 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Adhemerval Zanella, nd, libc-alpha

On Fri, 2016-11-18 at 08:28 +0000, Szabolcs Nagy wrote:
> On 17/11/16 12:52, Torvald Riegel wrote:
> > On Wed, 2016-11-16 at 17:52 -0200, Adhemerval Zanella wrote:
> >>
> >> On 16/11/2016 16:02, Torvald Riegel wrote:
> >>> On Wed, 2016-11-16 at 16:52 +0100, Florian Weimer wrote:
> >>>> On 11/16/2016 04:20 PM, Zack Weinberg wrote:
> >>>>> On 11/16/2016 10:11 AM, Florian Weimer wrote:
> >>>>>> On 11/14/2016 07:29 PM, Zack Weinberg wrote:
> >>>>>>> On 11/14/2016 12:44 PM, Florian Weimer wrote:
> >>>>>>>> This patch switches back to the ssize_t return time.  This goes against
> >>>>>>>> Theodore Ts'o preference, but seems to reflect the consensus from the
> >>>>>>>> largery community.
> >>>>>>>
> >>>>>>> I still don't think this function should be a cancellation point.
> >>>>>>
> >>>>>> I guess we'll have to agree to disagree on this matter.
> >>>>>
> >>>>> I am seriously considering escalating my disagreement here to a formal
> >>>>> objection.  I would like to know why you think it is NECESSARY - not
> >>>>> merely convenient or consistent with other stuff - for this function to
> >>>>> be a cancellation point.
> >>>>
> >>>> It's necessary if you ever want to cancel a hanging getrandom in a 
> >>>> context where you cannot install a signal handler (so that you can 
> >>>> trigger EINTR when getrandom is stuck).
> >>>
> >>> I think it would be better to split the getrandom that is a cancellation
> >>> point into two functions, getrandom (not a cancellation point) and
> >>> getrandom_cancelable (is a cancellation point).  This way, the
> >>> functionality is available for programs but requires explicit opt-in,
> >>> while the default is not going to lead to surprises in the expected
> >>> common case (ie, when randomness is available).  I don't think the
> >>> opt-in is a problem because as you said, cancellation requires careful
> >>> programming anyway.
> >>>
> >>
> >> I would advise against adding another symbol, it only adds complexity
> >> and most likely one interface would be preferable from application
> >> point of view.
> > 
> > We could add a parameter too that determines whether it is a
> > cancellation point.  That avoids your concern about adding another
> 
> why?
> 
> use pthread_setcancelstate.
> 
> works with all cancellation points not just getrandom.

As discussed in the thread, there are different opinions about what the
default should be.  There are reasonable arguments for both options.  In
such a case, it seems better to make the choice explicit, simply from an
ease-of-use and interface design perspective.  This is not about whether
it's possible for users to do (they could build their own syscall
wrappers after all too, right? ;) ) but about clean interfaces.

With your proposal, one could argue that, for example, every library has
to be aware of cancellation and how it works if one of the clients of
the library could want to use cancellation; the library either has to
disable it explicitly, or it has to document which additional
cancellation points exist and has to implement the cleanup handlers.
This is error-prone and adds complexity to those use cases.  Therefore,
it seems better to avoid that potential source of bugs and either make
the default to not support cancellation (ie, an opt-in for the
cancellation facility), or make at least make the choice explicit for
users of getrandom (ie, two functions or an additional parameter).

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18 14:21                   ` Torvald Riegel
@ 2016-11-18 15:13                     ` Florian Weimer
  2016-11-18 16:04                       ` Torvald Riegel
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-18 15:13 UTC (permalink / raw)
  To: Torvald Riegel, Szabolcs Nagy; +Cc: Adhemerval Zanella, nd, libc-alpha

On 11/18/2016 03:21 PM, Torvald Riegel wrote:

> As discussed in the thread, there are different opinions about what the
> default should be.  There are reasonable arguments for both options.  In
> such a case, it seems better to make the choice explicit, simply from an
> ease-of-use and interface design perspective.

Unfortunately, this is not the approach that POSIX has chosen.  But 
there is precedent for doing our own thing in this area: the "c" flag 
for fopen.  We cannot use the existing flags argument in getrandom for 
this purpose because its layout is controlled by the kernel.

> This is not about whether
> it's possible for users to do (they could build their own syscall
> wrappers after all too, right? ;) ) but about clean interfaces.

It's not possible to opt in to cancellation at system calls using only 
public glibc interfaces.  The best you can do is to implement 
cancellation from scratch, using a different signal.

> With your proposal, one could argue that, for example, every library has
> to be aware of cancellation and how it works if one of the clients of
> the library could want to use cancellation;

But that is true for most libraries today, no matter what we do about 
getrandom.  getrandom just does not add significant additional exposure 
in this area.

> the library either has to
> disable it explicitly, or it has to document which additional
> cancellation points exist and has to implement the cleanup handlers.
> This is error-prone and adds complexity to those use cases.  Therefore,
> it seems better to avoid that potential source of bugs and either make
> the default to not support cancellation (ie, an opt-in for the
> cancellation facility), or make at least make the choice explicit for
> users of getrandom (ie, two functions or an additional parameter).

I'm increasingly worried that this discussion is actually about thread 
cancellation in general and only peripherally about getrandom. 
Considering the fringe nature of getrandom (it is intended for the 
implementation of PRNG seeding, after all), it seems to be a strange 
choice to attempt to settle this debate.

Does POSIX even say that cancellation has to be enabled for new threads 
by default, like we do?  It's probably too late to change this.

In the end, this is very similar to the ongoing debate about exception 
handling in C++ and other languages.  For most such languages, there are 
large code bases which ban exceptions for various reasons, and others 
which use them with success.  I don't think we can reach agreement which 
one application developers should prefer.  The only thing we can do is 
try to be as consistent as possible (and for getrandom, I think the 
model should be the read function, and not rand).

This discussion is also blocking further work on my part for additional 
randomness generation functions.  More user-oriented interfaces we could 
add, such as getentropy or arc4random, should *not* be cancellation 
points, I think.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18 10:27                         ` Szabolcs Nagy
@ 2016-11-18 15:46                           ` Torvald Riegel
  2016-11-18 18:50                           ` Zack Weinberg
  1 sibling, 0 replies; 62+ messages in thread
From: Torvald Riegel @ 2016-11-18 15:46 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Zack Weinberg, Florian Weimer, nd, GNU C Library

On Fri, 2016-11-18 at 10:27 +0000, Szabolcs Nagy wrote:
> blocking syscalls have to be cancellation points
> otherwise they cannot be called safely from a long
> running process that has to remain responsive:
> blocked threads can keep piling up and there is no
> way to reuse the resources they hold.
> 
> [this is the general argument for adding new
> blocking syscalls as cancellation points].

You are describing just *one* use case.

You also don't define what "remain responsive" is supposed to mean;
there's a difference between being able to cancel any time vs. ensuring
that a syscall will not block indefinitely (eg, I think the common case
for getrandom should be that it does not block indefinitely, and
scenarios in which no randomness can be found nor "generated" are corner
cases).

Related to that, you don't distinguish between what can be done to
recover when a particular syscall does not complete; for example, is
there likely to be a workaround for a getrandom that does complete, or
is calling exit() the most likely response.

You also don't discuss who the expected audience for a syscall wrapper
is. How likely it is that they are aware of cancellation, might make use
of it, etc.?  How likely is the syscall going to be used directly vs.
being hidden by another wrapper that is produced by developers that
understand cancellation?

Just the fact that there are all these different considerations suggests
that there's no clean one-size-fits-all interface.  Hence my suggestion
to at least make the choice explicit (and thus obvious to users), for
example by either an additional parameter or by providing two
wrappers.  

If there is in fact no good default or one-size-fits-all, we should not
pretend that there is.

Finally, pthreads cancellation is a pretty crude means to build
asynchronous / cancellable operations because you cannot cancel just a
particular call; you always cancel a thread, which means that in
general, you need additional synchronization or other constraints to
make sure that you do not cancel at another cancellation point in some
other unrelated operation executed by the same thread.



^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18 15:13                     ` Florian Weimer
@ 2016-11-18 16:04                       ` Torvald Riegel
  2016-11-29  8:16                         ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-18 16:04 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Szabolcs Nagy, Adhemerval Zanella, nd, libc-alpha

On Fri, 2016-11-18 at 16:13 +0100, Florian Weimer wrote:
> On 11/18/2016 03:21 PM, Torvald Riegel wrote:
> 
> > As discussed in the thread, there are different opinions about what the
> > default should be.  There are reasonable arguments for both options.  In
> > such a case, it seems better to make the choice explicit, simply from an
> > ease-of-use and interface design perspective.
> 
> Unfortunately, this is not the approach that POSIX has chosen.  But 
> there is precedent for doing our own thing in this area: the "c" flag 
> for fopen.  We cannot use the existing flags argument in getrandom for 
> this purpose because its layout is controlled by the kernel.

It seems a separate argument would be better than using up space in the
existing flags.  Cancellation is something we add, so we should add to
the underlying interface too, instead of messing with it.

> > This is not about whether
> > it's possible for users to do (they could build their own syscall
> > wrappers after all too, right? ;) ) but about clean interfaces.
> 
> It's not possible to opt in to cancellation at system calls using only 
> public glibc interfaces.  The best you can do is to implement 
> cancellation from scratch, using a different signal.

I agree with that, but I was replying specifically to Scabolcs' comment
that users would have to just disable cancellation around a cancelable
syscall wrapper.

> > With your proposal, one could argue that, for example, every library has
> > to be aware of cancellation and how it works if one of the clients of
> > the library could want to use cancellation;
> 
> But that is true for most libraries today, no matter what we do about 
> getrandom.  getrandom just does not add significant additional exposure 
> in this area.

That's not true for a library that just wraps getrandom functionality.
I think that we should care about that independently of whether the same
problem exists elsewhere, unless it's clear that users will always have
to face the problem (eg, if getrandom would only be usable when also
doing file I/O at the same time).

> > the library either has to
> > disable it explicitly, or it has to document which additional
> > cancellation points exist and has to implement the cleanup handlers.
> > This is error-prone and adds complexity to those use cases.  Therefore,
> > it seems better to avoid that potential source of bugs and either make
> > the default to not support cancellation (ie, an opt-in for the
> > cancellation facility), or make at least make the choice explicit for
> > users of getrandom (ie, two functions or an additional parameter).
> 
> I'm increasingly worried that this discussion is actually about thread 
> cancellation in general and only peripherally about getrandom. 
> Considering the fringe nature of getrandom (it is intended for the 
> implementation of PRNG seeding, after all), it seems to be a strange 
> choice to attempt to settle this debate.

I can understand that you feel burdened by the wider debate, but I'm
also not convinced that we can ignore it just because it does something
that will be executed rarely.  I think the fringe nature might even be
an argument for having to be more careful about cancellation: If
getrandom in that corner over there, far away from other uses of
cancellation, how likely is it that users of it are aware of
cancellation at all?

> Does POSIX even say that cancellation has to be enabled for new threads 
> by default, like we do?  It's probably too late to change this.
> 
> In the end, this is very similar to the ongoing debate about exception 
> handling in C++ and other languages.  For most such languages, there are 
> large code bases which ban exceptions for various reasons, and others 
> which use them with success.  I don't think we can reach agreement which 
> one application developers should prefer.  The only thing we can do is 
> try to be as consistent as possible (and for getrandom, I think the 
> model should be the read function, and not rand).

I don't think this is a clean analogy.

> This discussion is also blocking further work on my part for additional 
> randomness generation functions.  More user-oriented interfaces we could 
> add, such as getentropy or arc4random, should *not* be cancellation 
> points, I think.

That's unfortunate, I agree.

What I haven't seen so far is a convincing argument why we should not
make the choice of cancellation point or not explicit in the wrapper.
Some have voiced broad concerns about the number of symbols (but is this
really such a big deal?), but I haven't seen an argument yet which
expressed detailed concerns about adding a separate argument that
determines whether there is cancellation point or not.

If we can't decide on one solution, mostly because we expect there to be
different use cases and users, why should we try to force a decision
instead of exposing the choice? -- especially given the point you make
about this being a very specialized syscall.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18 10:27                         ` Szabolcs Nagy
  2016-11-18 15:46                           ` Torvald Riegel
@ 2016-11-18 18:50                           ` Zack Weinberg
  2016-11-21 16:57                             ` Torvald Riegel
  2016-11-29  8:24                             ` Florian Weimer
  1 sibling, 2 replies; 62+ messages in thread
From: Zack Weinberg @ 2016-11-18 18:50 UTC (permalink / raw)
  To: Szabolcs Nagy; +Cc: Florian Weimer, nd, GNU C Library

On Fri, Nov 18, 2016 at 5:27 AM, Szabolcs Nagy <szabolcs.nagy@arm.com> wrote:
> On 17/11/16 17:16, Zack Weinberg wrote:
>> [This is just the general argument that adding new cancellation points
>> to the C library can render existing code buggy without notice.]
>
> there is no existing code that uses glibc getrandom.
>
> a user can easily turn a cancellation point into
> a non-cancellation one if desired, but the other
> way is not possible.

I specifically said there was a wrapper that anticipates the
availability of glibc getrandom, and uses a direct syscall in the
meantime.  AC_REPLACE_FUNCS(getrandom) or dlsym("getrandom") or like
that.

> blocking syscalls have to be cancellation points
> otherwise they cannot be called safely from a long
> running process that has to remain responsive:
> blocked threads can keep piling up and there is no
> way to reuse the resources they hold.

This is a valid point - I personally read it as an argument against
adding any new blocking syscalls, but that's not the world we live in.

I don't want to derail this into a general debate over adding new
cancellation points, and I especially don't want to hold up work on a
user-space CSPRNG on something unrelated, because arc4random() is the
top item on _my_ todo list after explicit_bzero().  So here is a
counterproposal.  Most of my concerns about getrandom() being a
cancellation point go away if it is only a cancellation point when it
is actually going to block -- note that I very much do _not_ mean
"when it is called with arguments that permit it to block."  How about
we have the public getrandom do like this:

ssize_t getrandom (void *buffer, size_t length, unsigned int flags)
{
  ssize_t rv = __getrandom_nocancel (buffer, length, flags | GRND_NONBLOCK);
  if (rv == length)
    return rv;
  if (rv < 0 && ((flags & GRND_NONBLOCK) || errno != EAGAIN)
    return rv;
  rv = max(rv, 0);
  return __getrandom_maycancel (buffer + rv, length - rv, flags);
}

I could live with that.

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18 18:50                           ` Zack Weinberg
@ 2016-11-21 16:57                             ` Torvald Riegel
  2016-11-21 17:12                               ` Zack Weinberg
  2016-11-29  8:24                             ` Florian Weimer
  1 sibling, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-21 16:57 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Szabolcs Nagy, Florian Weimer, nd, GNU C Library

On Fri, 2016-11-18 at 13:50 -0500, Zack Weinberg wrote:
> I don't want to derail this into a general debate over adding new
> cancellation points, and I especially don't want to hold up work on a
> user-space CSPRNG on something unrelated, because arc4random() is the
> top item on _my_ todo list after explicit_bzero().  So here is a
> counterproposal.  Most of my concerns about getrandom() being a
> cancellation point go away if it is only a cancellation point when it
> is actually going to block

Is there a way for the caller to ensure that a subsequent call to
getrandom is not going to block?  If there isn't, then the caller has to
conservatively assume that the call may be a cancellation point.

I still think something like 
ssize_t getrandom (/*getrandom parameters*/, bool cancellation_point);  
would probably be the best option because it requires a caller to make a
conscious decision about cancellation (and thus also makes the caller
aware of the whole cancellation thing).


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-21 16:57                             ` Torvald Riegel
@ 2016-11-21 17:12                               ` Zack Weinberg
  2016-11-21 17:30                                 ` Torvald Riegel
  0 siblings, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-11-21 17:12 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: Szabolcs Nagy, Florian Weimer, nd, GNU C Library

On Mon, Nov 21, 2016 at 11:57 AM, Torvald Riegel <triegel@redhat.com> wrote:
> On Fri, 2016-11-18 at 13:50 -0500, Zack Weinberg wrote:
>> I don't want to derail this into a general debate over adding new
>> cancellation points, and I especially don't want to hold up work on a
>> user-space CSPRNG on something unrelated, because arc4random() is the
>> top item on _my_ todo list after explicit_bzero().  So here is a
>> counterproposal.  Most of my concerns about getrandom() being a
>> cancellation point go away if it is only a cancellation point when it
>> is actually going to block
>
> Is there a way for the caller to ensure that a subsequent call to
> getrandom is not going to block?  If there isn't, then the caller has to
> conservatively assume that the call may be a cancellation point.

The whole reason I can live with my proposal is that most code should
be able to assume getrandom *never* blocks.  Specifically, if
getrandom ever blocks once we're past a fairly early stage of boot-up,
that's a bug in either the kernel or the setup procedure.  (I'd *like*
to get to where the kernel wouldn't even start process 1 until it
could guarantee that the RNG would not block, but that's a long way
off.)  So the only code that has to worry about it is early-stage boot
code that has to be written hyper-defensively anyway.

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-21 17:12                               ` Zack Weinberg
@ 2016-11-21 17:30                                 ` Torvald Riegel
  2016-11-21 17:34                                   ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-21 17:30 UTC (permalink / raw)
  To: Zack Weinberg; +Cc: Szabolcs Nagy, Florian Weimer, nd, GNU C Library

On Mon, 2016-11-21 at 12:12 -0500, Zack Weinberg wrote:
> On Mon, Nov 21, 2016 at 11:57 AM, Torvald Riegel <triegel@redhat.com> wrote:
> > On Fri, 2016-11-18 at 13:50 -0500, Zack Weinberg wrote:
> >> I don't want to derail this into a general debate over adding new
> >> cancellation points, and I especially don't want to hold up work on a
> >> user-space CSPRNG on something unrelated, because arc4random() is the
> >> top item on _my_ todo list after explicit_bzero().  So here is a
> >> counterproposal.  Most of my concerns about getrandom() being a
> >> cancellation point go away if it is only a cancellation point when it
> >> is actually going to block
> >
> > Is there a way for the caller to ensure that a subsequent call to
> > getrandom is not going to block?  If there isn't, then the caller has to
> > conservatively assume that the call may be a cancellation point.
> 
> The whole reason I can live with my proposal is that most code should
> be able to assume getrandom *never* blocks.  Specifically, if
> getrandom ever blocks once we're past a fairly early stage of boot-up,
> that's a bug in either the kernel or the setup procedure.

Does the kernel guarantee this, meaning that it's specifically
documented as part of the interface?  Or similarly, does it give a
guarantee under some precondition (which systemd or similar guarantees
to establish)?
I understand why you think this would be useful behavior, but the
"should be able" part in your statement is too vague for us to rely on.

Also, what do you mean specifically by "block"?  If it is just taking a
relatively long time, but will always eventually finish irrespective of
whether other processes do or do not do something, then I wouldn't
classify the behavior as blocking.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-21 17:30                                 ` Torvald Riegel
@ 2016-11-21 17:34                                   ` Florian Weimer
  0 siblings, 0 replies; 62+ messages in thread
From: Florian Weimer @ 2016-11-21 17:34 UTC (permalink / raw)
  To: Torvald Riegel, Zack Weinberg; +Cc: Szabolcs Nagy, nd, GNU C Library

On 11/21/2016 06:30 PM, Torvald Riegel wrote:

> Does the kernel guarantee this, meaning that it's specifically
> documented as part of the interface?

Yes, if the flags argument is 0, the call will only block if the kernel 
randomness pool has not been seeded yet.  And this is the reason why 
people want getrandom: they want to stop reading potentially predictable 
bits from /dev/urandom.

This is documented in the manual page.

Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18 16:04                       ` Torvald Riegel
@ 2016-11-29  8:16                         ` Florian Weimer
  2016-11-29 13:56                           ` Torvald Riegel
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-29  8:16 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: Szabolcs Nagy, Adhemerval Zanella, nd, libc-alpha

On 11/18/2016 05:04 PM, Torvald Riegel wrote:
> On Fri, 2016-11-18 at 16:13 +0100, Florian Weimer wrote:
>> On 11/18/2016 03:21 PM, Torvald Riegel wrote:
>>
>>> As discussed in the thread, there are different opinions about what the
>>> default should be.  There are reasonable arguments for both options.  In
>>> such a case, it seems better to make the choice explicit, simply from an
>>> ease-of-use and interface design perspective.
>>
>> Unfortunately, this is not the approach that POSIX has chosen.  But
>> there is precedent for doing our own thing in this area: the "c" flag
>> for fopen.  We cannot use the existing flags argument in getrandom for
>> this purpose because its layout is controlled by the kernel.
>
> It seems a separate argument would be better than using up space in the
> existing flags.  Cancellation is something we add, so we should add to
> the underlying interface too, instead of messing with it.

Is this separate argument your personal preference, or are you just 
trying to find common ground and reconcile different positions?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-18 18:50                           ` Zack Weinberg
  2016-11-21 16:57                             ` Torvald Riegel
@ 2016-11-29  8:24                             ` Florian Weimer
  1 sibling, 0 replies; 62+ messages in thread
From: Florian Weimer @ 2016-11-29  8:24 UTC (permalink / raw)
  To: Zack Weinberg, Szabolcs Nagy; +Cc: nd, GNU C Library

On 11/18/2016 07:50 PM, Zack Weinberg wrote:

> I don't want to derail this into a general debate over adding new
> cancellation points,  and I especially don't want to hold up work on a
> user-space CSPRNG on something unrelated, because arc4random() is the
> top item on _my_ todo list after explicit_bzero().  So here is a
> counterproposal.  Most of my concerns about getrandom() being a
> cancellation point go away if it is only a cancellation point when it
> is actually going to block -- note that I very much do _not_ mean
> "when it is called with arguments that permit it to block."  How about
> we have the public getrandom do like this:
>
> ssize_t getrandom (void *buffer, size_t length, unsigned int flags)
> {
>   ssize_t rv = __getrandom_nocancel (buffer, length, flags | GRND_NONBLOCK);
>   if (rv == length)
>     return rv;
>   if (rv < 0 && ((flags & GRND_NONBLOCK) || errno != EAGAIN)
>     return rv;
>   rv = max(rv, 0);
>   return __getrandom_maycancel (buffer + rv, length - rv, flags);
> }

This is an intriguing idea, but it actually makes reasoning about 
cancellation more difficult, particularly with GRND_RANDOM.

I haven't seen a rationale for the POSIX design (in which cancellation 
points always check for cancellation, even if they don't block).  I 
suspect it goes something like this: If thread cancellation happens on 
only blocking, then whether cancellation occurs depends on a race: the 
cancellation has to occur while being blocked.  This might never happen. 
  It's hard to tell whether you actually can cancel threads doing this 
(when cancellation is desired), or that they do not get canceled 
accidentally.

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29  8:16                         ` Florian Weimer
@ 2016-11-29 13:56                           ` Torvald Riegel
  2016-11-29 14:40                             ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-29 13:56 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Szabolcs Nagy, Adhemerval Zanella, nd, libc-alpha

On Tue, 2016-11-29 at 09:16 +0100, Florian Weimer wrote:
> On 11/18/2016 05:04 PM, Torvald Riegel wrote:
> > On Fri, 2016-11-18 at 16:13 +0100, Florian Weimer wrote:
> >> On 11/18/2016 03:21 PM, Torvald Riegel wrote:
> >>
> >>> As discussed in the thread, there are different opinions about what the
> >>> default should be.  There are reasonable arguments for both options.  In
> >>> such a case, it seems better to make the choice explicit, simply from an
> >>> ease-of-use and interface design perspective.
> >>
> >> Unfortunately, this is not the approach that POSIX has chosen.  But
> >> there is precedent for doing our own thing in this area: the "c" flag
> >> for fopen.  We cannot use the existing flags argument in getrandom for
> >> this purpose because its layout is controlled by the kernel.
> >
> > It seems a separate argument would be better than using up space in the
> > existing flags.  Cancellation is something we add, so we should add to
> > the underlying interface too, instead of messing with it.
> 
> Is this separate argument your personal preference, or are you just 
> trying to find common ground and reconcile different positions?

It's my personal preference.  Which is partially motivated by trying to
find common ground between the different use cases (and not finding
obvious common group, so therefore make the choice explicit).


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 13:56                           ` Torvald Riegel
@ 2016-11-29 14:40                             ` Florian Weimer
  2016-11-29 15:23                               ` Torvald Riegel
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-29 14:40 UTC (permalink / raw)
  To: Torvald Riegel; +Cc: Szabolcs Nagy, Adhemerval Zanella, nd, libc-alpha

On 11/29/2016 02:56 PM, Torvald Riegel wrote:
> On Tue, 2016-11-29 at 09:16 +0100, Florian Weimer wrote:
>> On 11/18/2016 05:04 PM, Torvald Riegel wrote:
>>> On Fri, 2016-11-18 at 16:13 +0100, Florian Weimer wrote:
>>>> On 11/18/2016 03:21 PM, Torvald Riegel wrote:
>>>>
>>>>> As discussed in the thread, there are different opinions about what the
>>>>> default should be.  There are reasonable arguments for both options.  In
>>>>> such a case, it seems better to make the choice explicit, simply from an
>>>>> ease-of-use and interface design perspective.
>>>>
>>>> Unfortunately, this is not the approach that POSIX has chosen.  But
>>>> there is precedent for doing our own thing in this area: the "c" flag
>>>> for fopen.  We cannot use the existing flags argument in getrandom for
>>>> this purpose because its layout is controlled by the kernel.
>>>
>>> It seems a separate argument would be better than using up space in the
>>> existing flags.  Cancellation is something we add, so we should add to
>>> the underlying interface too, instead of messing with it.
>>
>> Is this separate argument your personal preference, or are you just
>> trying to find common ground and reconcile different positions?
>
> It's my personal preference.  Which is partially motivated by trying to
> find common ground between the different use cases (and not finding
> obvious common group, so therefore make the choice explicit).

Hmph.

I was about to propose a new patch, with two functions:

getrandom, as I posted it the last time (an unadorned system call which 
is also a cancellation point).

getentropy, a thin wrapper which avoids returning EINTR (to match 
OpenBSD and Solaris) and is not a cancellation point.  It would return 
EIO on short reads, too.

The documentation would have said that getrandom is a lower-level 
function for those which need GRND_RANDOM or cancellation, and everyone 
else should call getrandom.

Would this work for you?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 14:40                             ` Florian Weimer
@ 2016-11-29 15:23                               ` Torvald Riegel
  2016-11-29 15:32                                 ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Torvald Riegel @ 2016-11-29 15:23 UTC (permalink / raw)
  To: Florian Weimer; +Cc: Szabolcs Nagy, Adhemerval Zanella, nd, libc-alpha

On Tue, 2016-11-29 at 15:40 +0100, Florian Weimer wrote:
> On 11/29/2016 02:56 PM, Torvald Riegel wrote:
> > On Tue, 2016-11-29 at 09:16 +0100, Florian Weimer wrote:
> >> On 11/18/2016 05:04 PM, Torvald Riegel wrote:
> >>> On Fri, 2016-11-18 at 16:13 +0100, Florian Weimer wrote:
> >>>> On 11/18/2016 03:21 PM, Torvald Riegel wrote:
> >>>>
> >>>>> As discussed in the thread, there are different opinions about what the
> >>>>> default should be.  There are reasonable arguments for both options.  In
> >>>>> such a case, it seems better to make the choice explicit, simply from an
> >>>>> ease-of-use and interface design perspective.
> >>>>
> >>>> Unfortunately, this is not the approach that POSIX has chosen.  But
> >>>> there is precedent for doing our own thing in this area: the "c" flag
> >>>> for fopen.  We cannot use the existing flags argument in getrandom for
> >>>> this purpose because its layout is controlled by the kernel.
> >>>
> >>> It seems a separate argument would be better than using up space in the
> >>> existing flags.  Cancellation is something we add, so we should add to
> >>> the underlying interface too, instead of messing with it.
> >>
> >> Is this separate argument your personal preference, or are you just
> >> trying to find common ground and reconcile different positions?
> >
> > It's my personal preference.  Which is partially motivated by trying to
> > find common ground between the different use cases (and not finding
> > obvious common group, so therefore make the choice explicit).
> 
> Hmph.

Note that I mean that this is my preference specifically in the scenario
of adding some sort of flag to getrandom() and offering only
getrandom().

> I was about to propose a new patch, with two functions:
> 
> getrandom, as I posted it the last time (an unadorned system call which 
> is also a cancellation point).
> 
> getentropy, a thin wrapper which avoids returning EINTR (to match 
> OpenBSD and Solaris) and is not a cancellation point.  It would return 
> EIO on short reads, too.
> 
> The documentation would have said that getrandom is a lower-level 
> function for those which need GRND_RANDOM or cancellation, and everyone 
> else should call getrandom.

I guess one of these should be getentropy (the latter?).

> Would this work for you?

Yeah, I guess so.  I can't really estimate how obvious it would be for
users to have to consider the pair of these (and thus make a conscious
choice and understand what cancellation means) -- but if we can make
this fairly obvious (eg, through proper documentation) and thus are
likely to prevent users from making a mistake, and we have an
alternative for the non-cancellation use case, then I guess this could
be a meaningful solution.


^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 15:23                               ` Torvald Riegel
@ 2016-11-29 15:32                                 ` Florian Weimer
  2016-11-29 15:54                                   ` Zack Weinberg
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-29 15:32 UTC (permalink / raw)
  To: Torvald Riegel, Zack Weinberg
  Cc: Szabolcs Nagy, Adhemerval Zanella, nd, libc-alpha

On 11/29/2016 04:23 PM, Torvald Riegel wrote:
> On Tue, 2016-11-29 at 15:40 +0100, Florian Weimer wrote:
>> On 11/29/2016 02:56 PM, Torvald Riegel wrote:
>>> On Tue, 2016-11-29 at 09:16 +0100, Florian Weimer wrote:
>>>> On 11/18/2016 05:04 PM, Torvald Riegel wrote:
>>>>> On Fri, 2016-11-18 at 16:13 +0100, Florian Weimer wrote:
>>>>>> On 11/18/2016 03:21 PM, Torvald Riegel wrote:
>>>>>>
>>>>>>> As discussed in the thread, there are different opinions about what the
>>>>>>> default should be.  There are reasonable arguments for both options.  In
>>>>>>> such a case, it seems better to make the choice explicit, simply from an
>>>>>>> ease-of-use and interface design perspective.
>>>>>>
>>>>>> Unfortunately, this is not the approach that POSIX has chosen.  But
>>>>>> there is precedent for doing our own thing in this area: the "c" flag
>>>>>> for fopen.  We cannot use the existing flags argument in getrandom for
>>>>>> this purpose because its layout is controlled by the kernel.
>>>>>
>>>>> It seems a separate argument would be better than using up space in the
>>>>> existing flags.  Cancellation is something we add, so we should add to
>>>>> the underlying interface too, instead of messing with it.
>>>>
>>>> Is this separate argument your personal preference, or are you just
>>>> trying to find common ground and reconcile different positions?
>>>
>>> It's my personal preference.  Which is partially motivated by trying to
>>> find common ground between the different use cases (and not finding
>>> obvious common group, so therefore make the choice explicit).
>>
>> Hmph.
>
> Note that I mean that this is my preference specifically in the scenario
> of adding some sort of flag to getrandom() and offering only
> getrandom().
>
>> I was about to propose a new patch, with two functions:
>>
>> getrandom, as I posted it the last time (an unadorned system call which
>> is also a cancellation point).
>>
>> getentropy, a thin wrapper which avoids returning EINTR (to match
>> OpenBSD and Solaris) and is not a cancellation point.  It would return
>> EIO on short reads, too.
>>
>> The documentation would have said that getrandom is a lower-level
>> function for those which need GRND_RANDOM or cancellation, and everyone
>> else should call getrandom.
>
> I guess one of these should be getentropy (the latter?).

Yes, developers should prefer getentropy or a PRNG seeded from getentropy.

>> Would this work for you?
>
> Yeah, I guess so.  I can't really estimate how obvious it would be for
> users to have to consider the pair of these (and thus make a conscious
> choice and understand what cancellation means) -- but if we can make
> this fairly obvious (eg, through proper documentation) and thus are
> likely to prevent users from making a mistake, and we have an
> alternative for the non-cancellation use case, then I guess this could
> be a meaningful solution.

Great.

Zack, what do you think?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 15:32                                 ` Florian Weimer
@ 2016-11-29 15:54                                   ` Zack Weinberg
  2016-11-29 17:53                                     ` Paul Eggert
  0 siblings, 1 reply; 62+ messages in thread
From: Zack Weinberg @ 2016-11-29 15:54 UTC (permalink / raw)
  To: Florian Weimer
  Cc: Torvald Riegel, Szabolcs Nagy, Adhemerval Zanella, nd, GNU C Library

On Tue, Nov 29, 2016 at 10:32 AM, Florian Weimer <fweimer@redhat.com> wrote:
> On 11/29/2016 04:23 PM, Torvald Riegel wrote:
>>
>> On Tue, 2016-11-29 at 15:40 +0100, Florian Weimer wrote:
>>>
>>> I was about to propose a new patch, with two functions:
>>>
>>> getrandom, as I posted it the last time (an unadorned system call which
>>> is also a cancellation point).
>>>
>>> getentropy, a thin wrapper which avoids returning EINTR (to match
>>> OpenBSD and Solaris) and is not a cancellation point.  It would return
>>> EIO on short reads, too.
>>>
>>> The documentation would have said that getrandom is a lower-level
>>> function for those which need GRND_RANDOM or cancellation, and everyone
>>> else should call getrandom.
>>
>> I guess one of these should be getentropy (the latter?).
>
> Yes, developers should prefer getentropy or a PRNG seeded from getentropy.
>
>>> Would this work for you?
>>
>>
>> Yeah, I guess so.  I can't really estimate how obvious it would be for
>> users to have to consider the pair of these (and thus make a conscious
>> choice and understand what cancellation means) -- but if we can make
>> this fairly obvious (eg, through proper documentation) and thus are
>> likely to prevent users from making a mistake, and we have an
>> alternative for the non-cancellation use case, then I guess this could
>> be a meaningful solution.
>
> Great.
>
> Zack, what do you think?

Yeah, this would also work for me.  Would it make sense for getentropy
to loop internally rather than returning a short read?  I am really
worried about people forgetting to handle short reads.

zw

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 15:54                                   ` Zack Weinberg
@ 2016-11-29 17:53                                     ` Paul Eggert
  2016-11-29 18:11                                       ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Paul Eggert @ 2016-11-29 17:53 UTC (permalink / raw)
  To: Zack Weinberg, Florian Weimer
  Cc: Torvald Riegel, Szabolcs Nagy, Adhemerval Zanella, nd, GNU C Library

On 11/29/2016 07:54 AM, Zack Weinberg wrote:
> Would it make sense for getentropy
> to loop internally rather than returning a short read?

FWIW, that is what I was planning when implementing a more-portable 
version of getentropy (I guess that's its name now?) for Gnulib, after 
the API settles down. Gnulib-using applications typically need a small 
number of random bytes. I don't want to worry about modifying these apps 
to take into account the possibility of waiting indefinitely due to a 
bug in the hardware or operating system. If such a wait occurs, it's OK 
with me to just say "fix your platform".

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 17:53                                     ` Paul Eggert
@ 2016-11-29 18:11                                       ` Florian Weimer
  2016-11-29 19:37                                         ` Paul Eggert
  0 siblings, 1 reply; 62+ messages in thread
From: Florian Weimer @ 2016-11-29 18:11 UTC (permalink / raw)
  To: Paul Eggert, Zack Weinberg
  Cc: Torvald Riegel, Szabolcs Nagy, Adhemerval Zanella, nd, GNU C Library

On 11/29/2016 06:53 PM, Paul Eggert wrote:
> On 11/29/2016 07:54 AM, Zack Weinberg wrote:
>> Would it make sense for getentropy
>> to loop internally rather than returning a short read?
>
> FWIW, that is what I was planning when implementing a more-portable
> version of getentropy (I guess that's its name now?) for Gnulib,

How are you going to avoid interposing the implementation in glibc?

Thanks,
Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 18:11                                       ` Florian Weimer
@ 2016-11-29 19:37                                         ` Paul Eggert
  2016-11-30  6:09                                           ` Florian Weimer
  0 siblings, 1 reply; 62+ messages in thread
From: Paul Eggert @ 2016-11-29 19:37 UTC (permalink / raw)
  To: Florian Weimer, Zack Weinberg
  Cc: Torvald Riegel, Szabolcs Nagy, Adhemerval Zanella, nd, GNU C Library

On 11/29/2016 10:11 AM, Florian Weimer wrote:
> How are you going to avoid interposing the implementation in glibc? 

That will depend on how glibc is implemented. Simplest might be to use 
compile-time interposition, which is common in Gnulib. E.g., Gnulib 
would supply its own getentropy.h which does "#define getentropy 
rpl_getentropy", so that Gnulib-using applications always call 
rpl_getentropy from the linker's point of view. This sort of thing is OK 
for Gnulib, as it's not intended to be a separate library.

^ permalink raw reply	[flat|nested] 62+ messages in thread

* Re: [PATCH v7] getrandom system call wrapper [BZ #17252]
  2016-11-29 19:37                                         ` Paul Eggert
@ 2016-11-30  6:09                                           ` Florian Weimer
  0 siblings, 0 replies; 62+ messages in thread
From: Florian Weimer @ 2016-11-30  6:09 UTC (permalink / raw)
  To: Paul Eggert, Zack Weinberg
  Cc: Torvald Riegel, Szabolcs Nagy, Adhemerval Zanella, nd, GNU C Library

On 11/29/2016 08:37 PM, Paul Eggert wrote:
> On 11/29/2016 10:11 AM, Florian Weimer wrote:
>> How are you going to avoid interposing the implementation in glibc?
>
> That will depend on how glibc is implemented. Simplest might be to use
> compile-time interposition, which is common in Gnulib. E.g., Gnulib
> would supply its own getentropy.h which does "#define getentropy
> rpl_getentropy", so that Gnulib-using applications always call
> rpl_getentropy from the linker's point of view. This sort of thing is OK
> for Gnulib, as it's not intended to be a separate library.

This sounds reasonable, thanks.

Florian

^ permalink raw reply	[flat|nested] 62+ messages in thread

end of thread, other threads:[~2016-11-30  6:09 UTC | newest]

Thread overview: 62+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2016-06-10 21:03 [PATCH] Add getrandom implementation [BZ #17252] Florian Weimer
2016-06-10 21:31 ` Joseph Myers
2016-06-10 21:36   ` Joseph Myers
2016-06-10 22:00   ` Paul Eggert
2016-06-10 22:06     ` Joseph Myers
2016-06-11 11:13   ` Florian Weimer
2016-06-11 20:10     ` Paul Eggert
2016-06-10 22:15 ` Roland McGrath
2016-06-10 22:40   ` Joseph Myers
2016-06-10 22:45     ` Roland McGrath
2016-06-23 17:21   ` Florian Weimer
2016-06-25 21:58     ` Paul Eggert
2016-09-02 22:23     ` Roland McGrath
2016-06-27 15:07 ` [PATCH v2] " Florian Weimer
2016-06-30  9:33   ` Rical Jasan
2016-09-08  9:53     ` Florian Weimer
2016-09-08 10:13       ` Andreas Schwab
2016-09-08 10:28         ` Florian Weimer
2016-09-08 11:58       ` Rical Jasan
2016-09-08 12:36         ` Florian Weimer
2016-06-30 12:03   ` Zack Weinberg
2016-07-13 13:10     ` Nikos Mavrogiannopoulos
2016-11-14 17:45 ` [PATCH v7] getrandom system call wrapper " Florian Weimer
2016-11-14 18:29   ` Zack Weinberg
2016-11-15 20:57     ` Richard Henderson
2016-11-16 15:11     ` Florian Weimer
2016-11-16 15:20       ` Zack Weinberg
2016-11-16 15:52         ` Florian Weimer
2016-11-16 16:41           ` Zack Weinberg
2016-11-17 13:02             ` Florian Weimer
2016-11-17 13:46               ` Zack Weinberg
2016-11-17 13:50                 ` Florian Weimer
2016-11-17 13:56                   ` Zack Weinberg
2016-11-17 15:24                     ` Florian Weimer
2016-11-17 17:16                       ` Zack Weinberg
2016-11-18 10:27                         ` Szabolcs Nagy
2016-11-18 15:46                           ` Torvald Riegel
2016-11-18 18:50                           ` Zack Weinberg
2016-11-21 16:57                             ` Torvald Riegel
2016-11-21 17:12                               ` Zack Weinberg
2016-11-21 17:30                                 ` Torvald Riegel
2016-11-21 17:34                                   ` Florian Weimer
2016-11-29  8:24                             ` Florian Weimer
2016-11-16 18:02           ` Torvald Riegel
2016-11-16 19:53             ` Adhemerval Zanella
2016-11-17 12:52               ` Torvald Riegel
2016-11-18  8:28                 ` Szabolcs Nagy
2016-11-18 14:21                   ` Torvald Riegel
2016-11-18 15:13                     ` Florian Weimer
2016-11-18 16:04                       ` Torvald Riegel
2016-11-29  8:16                         ` Florian Weimer
2016-11-29 13:56                           ` Torvald Riegel
2016-11-29 14:40                             ` Florian Weimer
2016-11-29 15:23                               ` Torvald Riegel
2016-11-29 15:32                                 ` Florian Weimer
2016-11-29 15:54                                   ` Zack Weinberg
2016-11-29 17:53                                     ` Paul Eggert
2016-11-29 18:11                                       ` Florian Weimer
2016-11-29 19:37                                         ` Paul Eggert
2016-11-30  6:09                                           ` Florian Weimer
2016-11-17  6:21   ` Mike Frysinger
2016-11-18 13:21     ` Florian Weimer

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for read-only IMAP folder(s) and NNTP newsgroup(s).