From patchwork Fri Nov 5 18:20:23 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Jonathan Wakely X-Patchwork-Id: 47131 Return-Path: X-Original-To: patchwork@sourceware.org Delivered-To: patchwork@sourceware.org Received: from server2.sourceware.org (localhost [IPv6:::1]) by sourceware.org (Postfix) with ESMTP id 86F4C385800B for ; Fri, 5 Nov 2021 18:21:36 +0000 (GMT) DKIM-Filter: OpenDKIM Filter v2.11.0 sourceware.org 86F4C385800B DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gcc.gnu.org; s=default; t=1636136496; bh=dIb6cZ44YTpLx1+DA+cmtiMCwh389YTwLE82zDu5xqQ=; h=To:Subject:Date:In-Reply-To:References:List-Id:List-Unsubscribe: List-Archive:List-Post:List-Help:List-Subscribe:From:Reply-To:Cc: From; b=xKjpaoEE+pwQt+qsuirEwUf1DtraarUHb0HLkm4IyRsF+FHfPoiiLHNHXMm2xPumU /c8CxzaJ0XP90+2XeQ1ICT3td4R7Ahqhu6z6L4xjfQSMb96CLNwNzwdwhLKGwLKfOz N9jC/Lyi7tfzD21P2b6iID1PXedv+fB+Y15did2Y= X-Original-To: gcc-patches@gcc.gnu.org Delivered-To: gcc-patches@gcc.gnu.org Received: from us-smtp-delivery-124.mimecast.com (us-smtp-delivery-124.mimecast.com [170.10.129.124]) by sourceware.org (Postfix) with ESMTPS id 8C9A03858408 for ; Fri, 5 Nov 2021 18:20:36 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.4.1 sourceware.org 8C9A03858408 Received: from mimecast-mx01.redhat.com (mimecast-mx01.redhat.com [209.132.183.4]) (Using TLS) by relay.mimecast.com with ESMTP id us-mta-121-FxXa_I2mO6CCCy43kUbORg-1; Fri, 05 Nov 2021 14:20:26 -0400 X-MC-Unique: FxXa_I2mO6CCCy43kUbORg-1 Received: from smtp.corp.redhat.com (int-mx06.intmail.prod.int.phx2.redhat.com [10.5.11.16]) (using TLSv1.2 with cipher AECDH-AES256-SHA (256/256 bits)) (No client certificate requested) by mimecast-mx01.redhat.com (Postfix) with ESMTPS id 4FE2687D541; Fri, 5 Nov 2021 18:20:25 +0000 (UTC) Received: from localhost (unknown [10.33.36.17]) by smtp.corp.redhat.com (Postfix) with ESMTP id 9263C6788C; Fri, 5 Nov 2021 18:20:24 +0000 (UTC) To: libstdc++@gcc.gnu.org, gcc-patches@gcc.gnu.org Subject: [committed] libstdc++: Support getentropy and arc4random in std::random_device Date: Fri, 5 Nov 2021 18:20:23 +0000 Message-Id: <20211105182023.2257591-1-jwakely@redhat.com> In-Reply-To: References: MIME-Version: 1.0 X-Scanned-By: MIMEDefang 2.79 on 10.5.11.16 X-Mimecast-Spam-Score: 0 X-Mimecast-Originator: redhat.com X-Spam-Status: No, score=-14.1 required=5.0 tests=BAYES_00, DKIMWL_WL_HIGH, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, GIT_PATCH_0, RCVD_IN_DNSWL_LOW, RCVD_IN_MSPIKE_H4, RCVD_IN_MSPIKE_WL, SPF_HELO_NONE, SPF_NONE, TXREP autolearn=unavailable autolearn_force=no version=3.4.4 X-Spam-Checker-Version: SpamAssassin 3.4.4 (2020-01-24) on server2.sourceware.org X-BeenThere: gcc-patches@gcc.gnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gcc-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-Patchwork-Original-From: Jonathan Wakely via Gcc-patches From: Jonathan Wakely Reply-To: Jonathan Wakely Cc: euloanty@live.com Errors-To: gcc-patches-bounces+patchwork=sourceware.org@gcc.gnu.org Sender: "Gcc-patches" This adds additional "getentropy" and "arc4random" tokens to std::random_device. The former is supported on Glibc and OpenBSD (and apparently wasm), and the latter is supported on various BSDs. I'm trying to test this on OpenBSD but I can't bootstrap GCC using the system clang. libstdc++-v3/ChangeLog: * acinclude.m4 (GLIBCXX_CHECK_GETENTROPY, GLIBCXX_CHECK_ARC4RANDOM): Define. * configure.ac (GLIBCXX_CHECK_GETENTROPY, GLIBCXX_CHECK_ARC4RANDOM): Use them. * config.h.in: Regenerate. * configure: Regenerate. * src/c++11/random.cc (random_device): Add getentropy and arc4random as sources. * testsuite/26_numerics/random/random_device/cons/token.cc: Check new tokens. * testsuite/26_numerics/random/random_device/entropy.cc: Likewise. --- libstdc++-v3/acinclude.m4 | 46 ++++++++ libstdc++-v3/config.h.in | 6 + libstdc++-v3/configure | 103 ++++++++++++++++++ libstdc++-v3/configure.ac | 4 + libstdc++-v3/src/c++11/random.cc | 69 +++++++++++- .../random/random_device/cons/token.cc | 1 + .../random/random_device/entropy.cc | 7 ++ 7 files changed, 234 insertions(+), 2 deletions(-) diff --git a/libstdc++-v3/acinclude.m4 b/libstdc++-v3/acinclude.m4 index 90ecc4a87a2..497af5723e1 100644 --- a/libstdc++-v3/acinclude.m4 +++ b/libstdc++-v3/acinclude.m4 @@ -4830,6 +4830,52 @@ AC_DEFUN([GLIBCXX_CHECK_EXCEPTION_PTR_SYMVER], [ fi ]) +dnl +dnl Check whether getentropy is present in . +dnl +AC_DEFUN([GLIBCXX_CHECK_GETENTROPY], [ + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_MSG_CHECKING([for getentropy]) + AC_CACHE_VAL(glibcxx_cv_getentropy, [ + AC_TRY_COMPILE( + [#include ], + [unsigned i; + ::getentropy(&i, sizeof(i));], + [glibcxx_cv_getentropy=yes], [glibcxx_cv_getentropy=no]) + ]) + + if test $glibcxx_cv_getentropy = yes; then + AC_DEFINE(HAVE_GETENTROPY, 1, [Define if getentropy is available in .]) + fi + AC_MSG_RESULT($glibcxx_cv_getentropy) + AC_LANG_RESTORE +]) + +dnl +dnl Check whether arc4random is present in . +dnl +AC_DEFUN([GLIBCXX_CHECK_ARC4RANDOM], [ + + AC_LANG_SAVE + AC_LANG_CPLUSPLUS + AC_MSG_CHECKING([for arc4random]) + AC_CACHE_VAL(glibcxx_cv_arc4random, [ + AC_TRY_COMPILE( + [#include ], + [unsigned i = ::arc4random();], + [glibcxx_cv_arc4random=yes], [glibcxx_cv_arc4random=no]) + ]) + + if test $glibcxx_cv_arc4random = yes; then + AC_DEFINE(HAVE_ARC4RANDOM, 1, [Define if arc4random is available in .]) + fi + AC_MSG_RESULT($glibcxx_cv_arc4random) + AC_LANG_RESTORE +]) + + # Macros from the top-level gcc directory. m4_include([../config/gc++filt.m4]) m4_include([../config/tls.m4]) diff --git a/libstdc++-v3/config.h.in b/libstdc++-v3/config.h.in index 228a758325e..420021fcb1a 100644 --- a/libstdc++-v3/config.h.in +++ b/libstdc++-v3/config.h.in @@ -9,6 +9,9 @@ /* Define to 1 if you have the `aligned_alloc' function. */ #undef HAVE_ALIGNED_ALLOC +/* Define if arc4random is available in . */ +#undef HAVE_ARC4RANDOM + /* Define to 1 if you have the header file. */ #undef HAVE_ARPA_INET_H @@ -132,6 +135,9 @@ /* Define to 1 if you have the `frexpl' function. */ #undef HAVE_FREXPL +/* Define if getentropy is available in . */ +#undef HAVE_GETENTROPY + /* Define if _Unwind_GetIPInfo is available. */ #undef HAVE_GETIPINFO diff --git a/libstdc++-v3/configure b/libstdc++-v3/configure index c1aea827070..21371031b66 100755 --- a/libstdc++-v3/configure +++ b/libstdc++-v3/configure @@ -75429,6 +75429,109 @@ $as_echo "#define _GLIBCXX_X86_RDSEED 1" >>confdefs.h $as_echo "$ac_cv_x86_rdseed" >&6; } +# Check for other random number APIs + + + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for getentropy" >&5 +$as_echo_n "checking for getentropy... " >&6; } + if ${glibcxx_cv_getentropy+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +unsigned i; + ::getentropy(&i, sizeof(i)); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_getentropy=yes +else + glibcxx_cv_getentropy=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + + + if test $glibcxx_cv_getentropy = yes; then + +$as_echo "#define HAVE_GETENTROPY 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_getentropy" >&5 +$as_echo "$glibcxx_cv_getentropy" >&6; } + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + + + + ac_ext=cpp +ac_cpp='$CXXCPP $CPPFLAGS' +ac_compile='$CXX -c $CXXFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CXX -o conftest$ac_exeext $CXXFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_cxx_compiler_gnu + + { $as_echo "$as_me:${as_lineno-$LINENO}: checking for arc4random" >&5 +$as_echo_n "checking for arc4random... " >&6; } + if ${glibcxx_cv_arc4random+:} false; then : + $as_echo_n "(cached) " >&6 +else + + cat confdefs.h - <<_ACEOF >conftest.$ac_ext +/* end confdefs.h. */ +#include +int +main () +{ +unsigned i = ::arc4random(); + ; + return 0; +} +_ACEOF +if ac_fn_cxx_try_compile "$LINENO"; then : + glibcxx_cv_arc4random=yes +else + glibcxx_cv_arc4random=no +fi +rm -f core conftest.err conftest.$ac_objext conftest.$ac_ext + +fi + + + if test $glibcxx_cv_arc4random = yes; then + +$as_echo "#define HAVE_ARC4RANDOM 1" >>confdefs.h + + fi + { $as_echo "$as_me:${as_lineno-$LINENO}: result: $glibcxx_cv_arc4random" >&5 +$as_echo "$glibcxx_cv_arc4random" >&6; } + ac_ext=c +ac_cpp='$CPP $CPPFLAGS' +ac_compile='$CC -c $CFLAGS $CPPFLAGS conftest.$ac_ext >&5' +ac_link='$CC -o conftest$ac_exeext $CFLAGS $CPPFLAGS $LDFLAGS conftest.$ac_ext $LIBS >&5' +ac_compiler_gnu=$ac_cv_c_compiler_gnu + + + # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. # Do checks for resource limit functions. diff --git a/libstdc++-v3/configure.ac b/libstdc++-v3/configure.ac index 2d68b3672b9..5b3c92f4bd7 100644 --- a/libstdc++-v3/configure.ac +++ b/libstdc++-v3/configure.ac @@ -468,6 +468,10 @@ GLIBCXX_CHECK_X86_RDRAND # Check if assembler supports rdseed opcode. GLIBCXX_CHECK_X86_RDSEED +# Check for other random number APIs +GLIBCXX_CHECK_GETENTROPY +GLIBCXX_CHECK_ARC4RANDOM + # This depends on GLIBCXX_ENABLE_SYMVERS and GLIBCXX_IS_NATIVE. GLIBCXX_CONFIGURE_TESTSUITE diff --git a/libstdc++-v3/src/c++11/random.cc b/libstdc++-v3/src/c++11/random.cc index 4b88818646f..4a553e0d84f 100644 --- a/libstdc++-v3/src/c++11/random.cc +++ b/libstdc++-v3/src/c++11/random.cc @@ -68,7 +68,12 @@ # include #endif -#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM +#ifdef _GLIBCXX_HAVE_GETENTROPY +# include +#endif + +#if defined _GLIBCXX_USE_CRT_RAND_S || defined _GLIBCXX_USE_DEV_RANDOM \ + || _GLIBCXX_HAVE_GETENTROPY // The OS provides a source of randomness we can use. # pragma GCC poison _M_mt #elif defined USE_RDRAND || defined USE_RDSEED || defined USE_DARN @@ -166,6 +171,25 @@ namespace std _GLIBCXX_VISIBILITY(default) } #endif +#ifdef _GLIBCXX_HAVE_GETENTROPY + unsigned int + __libc_getentropy(void*) + { + unsigned int val; + if (::getentropy(&val, sizeof(val)) != 0) + std::__throw_runtime_error(__N("random_device: getentropy failed")); + return val; + } +#endif + +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + unsigned int + __libc_arc4random(void*) + { + return ::arc4random(); + } +#endif + #ifdef USE_LCG // TODO: use this to seed std::mt19937 engine too. unsigned @@ -214,7 +238,7 @@ namespace std _GLIBCXX_VISIBILITY(default) #endif enum Which : unsigned { - device_file = 1, prng = 2, rand_s = 4, + device_file = 1, prng = 2, rand_s = 4, getentropy = 8, arc4random = 16, rdseed = 64, rdrand = 128, darn = 256, any = 0xffff }; @@ -256,6 +280,16 @@ namespace std _GLIBCXX_VISIBILITY(default) return device_file; #endif +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + if (func == __libc_arc4random) + return arc4random; +#endif + +#ifdef _GLIBCXX_HAVE_GETENTROPY + if (func == __libc_getentropy) + return getentropy; +#endif + #ifdef USE_LCG if (func == &__lcg) return prng; @@ -311,6 +345,14 @@ namespace std _GLIBCXX_VISIBILITY(default) else if (token == "rand_s") which = rand_s; #endif // _GLIBCXX_USE_CRT_RAND_S +#ifdef _GLIBCXX_HAVE_GETENTROPY + else if (token == "getentropy") + which = getentropy; +#endif // _GLIBCXX_HAVE_GETENTROPY +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + else if (token == "arc4random") + which = arc4random; +#endif // _GLIBCXX_HAVE_ARC4RANDOM #ifdef _GLIBCXX_USE_DEV_RANDOM else if (token == "/dev/urandom" || token == "/dev/random") { @@ -395,6 +437,26 @@ namespace std _GLIBCXX_VISIBILITY(default) } #endif // USE_DARN +#ifdef _GLIBCXX_HAVE_ARC4RANDOM + if (which & arc4random) + { + _M_func = &__libc_arc4random; + return; + } +#endif // _GLIBCXX_HAVE_ARC4RANDOM + +#ifdef _GLIBCXX_HAVE_GETENTROPY + if (which & getentropy) + { + unsigned int i; + if (::getentropy(&i, sizeof(i)) == 0) // On linux the syscall can fail. + { + _M_func = &__libc_getentropy; + return; + } + } +#endif // _GLIBCXX_HAVE_GETENTROPY + #ifdef _GLIBCXX_USE_DEV_RANDOM if (which & device_file) { @@ -548,6 +610,9 @@ namespace std _GLIBCXX_VISIBILITY(default) case rdseed: case darn: return (double) max; + case arc4random: + case getentropy: + return (double) max; case rand_s: case prng: return 0.0; diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc index d6ac3a37c64..e13484e03a5 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/cons/token.cc @@ -53,6 +53,7 @@ test03() const std::string tokens[] = { "rdseed", "rdrand", "darn", "rand_s", "/dev/urandom", "/dev/random", + "getentropy", "arc4random", "mt19937", "prng" }; int count = 0; diff --git a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc index 6f3ebb1b38e..63b7043bf9b 100644 --- a/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc +++ b/libstdc++-v3/testsuite/26_numerics/random/random_device/entropy.cc @@ -28,6 +28,13 @@ test01() const double entropy = std::random_device(token).entropy(); VERIFY( entropy == max ); } + + for (auto token : { "getentropy", "arc4random" }) + if (__gnu_test::random_device_available(token)) + { + const double entropy = std::random_device(token).entropy(); + VERIFY( entropy == max ); + } } int