* [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: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 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 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
* 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
* [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-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
* 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
* [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 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 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-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 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 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-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-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-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-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 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 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-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
* 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-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
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).