From: Bruno Haible Date: Sat, 30 May 2020 15:33:46 +0000 (+0200) Subject: getrandom: Override incompatible system function on Solaris 11. X-Git-Tag: v1.0~4011 X-Git-Url: https://gitweb.git.savannah.gnu.org/gitweb/?a=commitdiff_plain;h=67ae31b60bedc0a3f1ff4c06177054685b9dcc95;p=gnulib.git getrandom: Override incompatible system function on Solaris 11. * lib/sys_random.in.h (getrandom): Override if REPLACE_GETRANDOM is 1. * lib/getrandom.c (getrandom): When the system has getrandom, just invoke it. * m4/getrandom.m4 (gl_FUNC_GETRANDOM): Set REPLACE_GETRANDOM if the system's getrandom function's prototype is not the expected one. * m4/sys_random_h.m4 (gl_SYS_RANDOM_H_DEFAULTS): Initialize REPLACE_GETRANDOM. * modules/sys_random (Makefile.am): Substitute REPLACE_GETRANDOM. * modules/getrandom (modules/getrandom): Consider REPLACE_GETRANDOM. * tests/test-getrandom.c (main): Allow error EINVAL as an alternative to EAGAIN. * doc/glibc-functions/getrandom.texi: Mention the new module and the Solaris problem. --- diff --git a/ChangeLog b/ChangeLog index c5a3bd5868..bf57624351 100644 --- a/ChangeLog +++ b/ChangeLog @@ -1,3 +1,20 @@ +2020-05-30 Bruno Haible + + getrandom: Override incompatible system function on Solaris 11. + * lib/sys_random.in.h (getrandom): Override if REPLACE_GETRANDOM is 1. + * lib/getrandom.c (getrandom): When the system has getrandom, just + invoke it. + * m4/getrandom.m4 (gl_FUNC_GETRANDOM): Set REPLACE_GETRANDOM if the + system's getrandom function's prototype is not the expected one. + * m4/sys_random_h.m4 (gl_SYS_RANDOM_H_DEFAULTS): Initialize + REPLACE_GETRANDOM. + * modules/sys_random (Makefile.am): Substitute REPLACE_GETRANDOM. + * modules/getrandom (modules/getrandom): Consider REPLACE_GETRANDOM. + * tests/test-getrandom.c (main): Allow error EINVAL as an alternative to + EAGAIN. + * doc/glibc-functions/getrandom.texi: Mention the new module and the + Solaris problem. + 2020-05-30 Bruno Haible sys_random: Add C++ tests. diff --git a/doc/glibc-functions/getrandom.texi b/doc/glibc-functions/getrandom.texi index 2f4debcfef..2d93556537 100644 --- a/doc/glibc-functions/getrandom.texi +++ b/doc/glibc-functions/getrandom.texi @@ -15,7 +15,7 @@ Documentation: @uref{https://www.kernel.org/doc/man-pages/online/pages/man2/getrandom.2.html,,man getrandom}. @end itemize -Gnulib module: --- +Gnulib module: getrandom Portability problems fixed by Gnulib: @itemize @@ -23,6 +23,9 @@ Portability problems fixed by Gnulib: This function is missing on some platforms: glibc 2.24, Mac OS X 10.5, FreeBSD 11.0, NetBSD 5.0, OpenBSD 3.8, Solaris 11.0, Android 9.0. +@item +This function has a different return type on some platforms: +Solaris 11.4. @end itemize Portability problems not fixed by Gnulib: diff --git a/lib/getrandom.c b/lib/getrandom.c index 9b6ecb43be..f20ffe0112 100644 --- a/lib/getrandom.c +++ b/lib/getrandom.c @@ -21,16 +21,21 @@ #include -#include "minmax.h" #include #include #include +#include "minmax.h" + /* Set BUFFER (of size LENGTH) to random bytes under the control of FLAGS. Return the number of bytes written, or -1 on error. */ ssize_t getrandom (void *buffer, size_t length, unsigned int flags) +#undef getrandom { +#if HAVE_GETRANDOM + return getrandom (buffer, length, flags); +#else static int randfd[2] = { -1, -1 }; bool devrandom = (flags & GRND_RANDOM) != 0; int fd = randfd[devrandom]; @@ -49,4 +54,5 @@ getrandom (void *buffer, size_t length, unsigned int flags) } return read (fd, buffer, length); +#endif } diff --git a/lib/sys_random.in.h b/lib/sys_random.in.h index 3997cf4c3b..4d12db95ea 100644 --- a/lib/sys_random.in.h +++ b/lib/sys_random.in.h @@ -51,13 +51,25 @@ #if @GNULIB_GETRANDOM@ /* Fill a buffer with random bytes. */ -# if !@HAVE_GETRANDOM@ +# if @REPLACE_GETRANDOM@ +# if !(defined __cplusplus && defined GNULIB_NAMESPACE) +# undef getrandom +# define getrandom rpl_getrandom +# endif +_GL_FUNCDECL_RPL (getrandom, ssize_t, + (void *buffer, size_t length, unsigned int flags) + _GL_ARG_NONNULL ((1))); +_GL_CXXALIAS_RPL (getrandom, ssize_t, + (void *buffer, size_t length, unsigned int flags)); +# else +# if !@HAVE_GETRANDOM@ _GL_FUNCDECL_SYS (getrandom, ssize_t, (void *buffer, size_t length, unsigned int flags) _GL_ARG_NONNULL ((1))); -# endif +# endif _GL_CXXALIAS_SYS (getrandom, ssize_t, (void *buffer, size_t length, unsigned int flags)); +# endif _GL_CXXALIASWARN (getrandom); #elif defined GNULIB_POSIXCHECK # undef getrandom diff --git a/m4/getrandom.m4 b/m4/getrandom.m4 index 79e5520931..9fee059e43 100644 --- a/m4/getrandom.m4 +++ b/m4/getrandom.m4 @@ -1,4 +1,4 @@ -# getrandom.m4 serial 2 +# getrandom.m4 serial 3 dnl Copyright 2020 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -12,5 +12,23 @@ AC_DEFUN([gl_FUNC_GETRANDOM], AC_CHECK_FUNCS_ONCE([getrandom]) if test "$ac_cv_func_getrandom" != yes; then HAVE_GETRANDOM=0 + else + dnl On Solaris 11.4 the return type is 'int', not 'ssize_t'. + AC_CACHE_CHECK([whether getrandom is compatible with its GNU+BSD signature], + [gl_cv_func_getrandom_ok], + [AC_COMPILE_IFELSE( + [AC_LANG_PROGRAM( + [[#include + #include + ssize_t getrandom (void *, size_t, unsigned int); + ]], + [[]]) + ], + [gl_cv_func_getrandom_ok=yes], + [gl_cv_func_getrandom_ok=no]) + ]) + if test $gl_cv_func_getrandom_ok = no; then + REPLACE_GETRANDOM=1 + fi fi ]) diff --git a/m4/sys_random_h.m4 b/m4/sys_random_h.m4 index d78307f53b..2ab96ef88e 100644 --- a/m4/sys_random_h.m4 +++ b/m4/sys_random_h.m4 @@ -1,4 +1,4 @@ -# sys_random_h.m4 serial 1 +# sys_random_h.m4 serial 2 dnl Copyright (C) 2020 Free Software Foundation, Inc. dnl This file is free software; the Free Software Foundation dnl gives unlimited permission to copy and/or distribute it, @@ -40,4 +40,5 @@ AC_DEFUN([gl_SYS_RANDOM_H_DEFAULTS], GNULIB_GETRANDOM=0; AC_SUBST([GNULIB_GETRANDOM]) dnl Assume proper GNU behavior unless another module says otherwise. HAVE_GETRANDOM=1; AC_SUBST([HAVE_GETRANDOM]) + REPLACE_GETRANDOM=1; AC_SUBST([REPLACE_GETRANDOM]) ]) diff --git a/modules/getrandom b/modules/getrandom index f7b3ff9e29..e94686d6ff 100644 --- a/modules/getrandom +++ b/modules/getrandom @@ -8,13 +8,13 @@ m4/getrandom.m4 Depends-on: sys_random crypto/gc-random [test $HAVE_GETRANDOM = 0] -fcntl-h [test $HAVE_GETRANDOM = 0] -minmax [test $HAVE_GETRANDOM = 0] -open [test $HAVE_GETRANDOM = 0] +fcntl-h [test $HAVE_GETRANDOM = 0 || test $REPLACE_GETRANDOM = 1] +minmax [test $HAVE_GETRANDOM = 0 || test $REPLACE_GETRANDOM = 1] +open [test $HAVE_GETRANDOM = 0 || test $REPLACE_GETRANDOM = 1] configure.ac: gl_FUNC_GETRANDOM -if test $HAVE_GETRANDOM = 0; then +if test $HAVE_GETRANDOM = 0 || test $REPLACE_GETRANDOM = 1; then AC_LIBOBJ([getrandom]) fi gl_SYS_RANDOM_MODULE_INDICATOR([getrandom]) diff --git a/modules/sys_random b/modules/sys_random index 1d0eb7ce01..b88507bb92 100644 --- a/modules/sys_random +++ b/modules/sys_random @@ -32,6 +32,7 @@ sys/random.h: sys_random.in.h $(top_builddir)/config.status $(CXXDEFS_H) $(ARG_N -e 's|@''HAVE_SYS_RANDOM_H''@|$(HAVE_SYS_RANDOM_H)|g' \ -e 's/@''GNULIB_GETRANDOM''@/$(GNULIB_GETRANDOM)/g' \ -e 's/@''HAVE_GETRANDOM''@/$(HAVE_GETRANDOM)/g' \ + -e 's/@''REPLACE_GETRANDOM''@/$(REPLACE_GETRANDOM)/g' \ -e '/definitions of _GL_FUNCDECL_RPL/r $(CXXDEFS_H)' \ -e '/definition of _GL_ARG_NONNULL/r $(ARG_NONNULL_H)' \ -e '/definition of _GL_WARN_ON_USE/r $(WARN_ON_USE_H)' \ diff --git a/tests/test-getrandom.c b/tests/test-getrandom.c index 3c84f871ef..8b25958665 100644 --- a/tests/test-getrandom.c +++ b/tests/test-getrandom.c @@ -75,7 +75,8 @@ main (void) ret = getrandom (large_buf, sizeof (large_buf), GRND_RANDOM | GRND_NONBLOCK); /* It is very unlikely that so many truly random bytes were ready. */ if (ret < 0) - ASSERT (errno == ENOSYS || errno == EAGAIN); + ASSERT (errno == ENOSYS || errno == EAGAIN + || errno == EINVAL /* Solaris */); else ASSERT (ret > 0 && ret < sizeof (large_buf));