bug-gnulib
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [PATCH] getentropy, getrandom: new modules


From: Bruno Haible
Subject: Re: [PATCH] getentropy, getrandom: new modules
Date: Sat, 30 May 2020 17:34:47 +0200
User-agent: KMail/5.1.3 (Linux/4.4.0-177-generic; KDE/5.18.0; x86_64; ; )

Now that we have a <sys/random.h> module with test cases, we see that
there is a conflict with the function defined on Solaris 11.3 and newer:

../gllib/sys/random.h: In member function 
‘gnulib::_gl_getrandom_wrapper::operator gnulib::_gl_getrandom_wrapper::type() 
const’:
../gllib/sys/random.h:535:1: error: invalid conversion from ‘int (*)(void*, 
std::size_t, uint_t) {aka int (*)(void*, long unsigned int, unsigned int)}’ to 
‘gnulib::_gl_getrandom_wrapper::type {aka long int (*)(void*, long unsigned 
int, unsigned int)}’ [-fpermissive]
 _GL_CXXALIAS_SYS (getrandom, ssize_t,
 ^

See https://docs.oracle.com/cd/E88353_01/html/E37841/getrandom-2.html

Thus, we need to override the function if it has a different return type.


2020-05-30  Bruno Haible  <bruno@clisp.org>

        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/doc/glibc-functions/getrandom.texi 
b/doc/glibc-functions/getrandom.texi
index 2f4debc..2d93556 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 9b6ecb4..f20ffe0 100644
--- a/lib/getrandom.c
+++ b/lib/getrandom.c
@@ -21,16 +21,21 @@
 
 #include <sys/random.h>
 
-#include "minmax.h"
 #include <fcntl.h>
 #include <stdbool.h>
 #include <unistd.h>
 
+#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 3997cf4..4d12db9 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 79e5520..9fee059 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 <sys/random.h>
+              #include <sys/types.h>
+              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 d78307f..2ab96ef 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 f7b3ff9..e94686d 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 1d0eb7c..b88507b 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 3c84f87..8b25958 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));
 




reply via email to

[Prev in Thread] Current Thread [Next in Thread]