summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorThiago Macieira <thiago.macieira@intel.com>2017-06-16 21:39:04 -0700
committerThiago Macieira <thiago.macieira@intel.com>2017-06-30 21:19:10 +0000
commit120ecc976fc3d5504d234702f68c2ad3898b77a4 (patch)
treebfd8b6248a3e1d1e1cd90ab5f29e2bf4012aca79
parent078f04254e1ab7e4e7cb4b7ff5f371ab22a020cc (diff)
QRandomGenerator: use getentropy on Linux & OpenBSD
The getentropy function, first found in OpenBSD, is present in glibc since version 2.25 and Bionic since Android 6.0 and NDK r11. It uses the Linux 3.17 getrandom system call. Unlike glibc's getrandom() wrapper, the glibc implementation of getentropy() function is not a POSIX thread cancellation point, so we prefer to use that even though we have to break the reading into 256-byte blocks. The big advantage is that these functions work even in the absence of a /dev/urandom device node, in addition to a few cycles shaved off by not having to open a file descriptor and close it at exit. What's more, the glibc implementation blocks until entropy is available on early boot, so we don't have to worry about a failure mode. The Bionic implementation will fall back by itself to /dev/urandom and, failing that, gathering entropy from elsewhere in the system in a way it cannot fail either. uClibc has a wrapper to getrandom(2) but no getentropy(3). MUSL has neither. Change-Id: Ia53158e207a94bf49489fffd14c8cee1b968a619 Reviewed-by: Lars Knoll <lars.knoll@qt.io>
-rw-r--r--config.tests/unix/getentropy/getentropy.cpp35
-rw-r--r--config.tests/unix/getentropy/getentropy.pro1
-rw-r--r--src/corelib/configure.json10
-rw-r--r--src/corelib/global/minimum-linux.S12
-rw-r--r--src/corelib/global/qconfig-bootstrapped.h1
-rw-r--r--src/corelib/global/qrandom.cpp47
-rw-r--r--tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp2
7 files changed, 96 insertions, 12 deletions
diff --git a/config.tests/unix/getentropy/getentropy.cpp b/config.tests/unix/getentropy/getentropy.cpp
new file mode 100644
index 0000000000..6cb4dc3a95
--- /dev/null
+++ b/config.tests/unix/getentropy/getentropy.cpp
@@ -0,0 +1,35 @@
+/****************************************************************************
+**
+** Copyright (C) 2017 Intel Corporation.
+** Contact: https://www.qt.io/licensing/
+**
+** This file is part of the test suite of the Qt Toolkit.
+**
+** $QT_BEGIN_LICENSE:GPL-EXCEPT$
+** Commercial License Usage
+** Licensees holding valid commercial Qt licenses may use this file in
+** accordance with the commercial license agreement provided with the
+** Software or, alternatively, in accordance with the terms contained in
+** a written agreement between you and The Qt Company. For licensing terms
+** and conditions see https://www.qt.io/terms-conditions. For further
+** information use the contact form at https://www.qt.io/contact-us.
+**
+** GNU General Public License Usage
+** Alternatively, this file may be used under the terms of the GNU
+** General Public License version 3 as published by the Free Software
+** Foundation with exceptions as appearing in the file LICENSE.GPL3-EXCEPT
+** included in the packaging of this file. Please review the following
+** information to ensure the GNU General Public License requirements will
+** be met: https://www.gnu.org/licenses/gpl-3.0.html.
+**
+** $QT_END_LICENSE$
+**
+****************************************************************************/
+
+#include <unistd.h>
+
+int main()
+{
+ char buf[32];
+ return getentropy(buf, sizeof(buf));
+}
diff --git a/config.tests/unix/getentropy/getentropy.pro b/config.tests/unix/getentropy/getentropy.pro
new file mode 100644
index 0000000000..bdd626b513
--- /dev/null
+++ b/config.tests/unix/getentropy/getentropy.pro
@@ -0,0 +1 @@
+SOURCES = getentropy.cpp
diff --git a/src/corelib/configure.json b/src/corelib/configure.json
index 0da3bff713..5e2cb025d3 100644
--- a/src/corelib/configure.json
+++ b/src/corelib/configure.json
@@ -163,6 +163,11 @@
"type": "compile",
"test": "unix/futimesat"
},
+ "getentropy": {
+ "label": "getentropy()",
+ "type": "compile",
+ "test": "unix/getentropy"
+ },
"posix-iconv": {
"label": "POSIX iconv",
"type": "compile",
@@ -277,6 +282,11 @@
"condition": "!config.win32 && !features.futimens && !features.futimes && tests.futimesat",
"output": [ "privateFeature" ]
},
+ "getentropy": {
+ "label": "getentropy()",
+ "condition": "config.unix && tests.getentropy",
+ "output": [ "privateFeature" ]
+ },
"glib": {
"label": "GLib",
"autoDetect": "!config.win32",
diff --git a/src/corelib/global/minimum-linux.S b/src/corelib/global/minimum-linux.S
index 3c0fa09a0a..3d97ea7ec8 100644
--- a/src/corelib/global/minimum-linux.S
+++ b/src/corelib/global/minimum-linux.S
@@ -37,6 +37,8 @@
**
****************************************************************************/
+#include "private/qglobal_p.h"
+
/* Copied from #include <elf.h>:
*/
#define ELF_NOTE_GNU "GNU"
@@ -76,7 +78,7 @@
/* Minimum Linux kernel version:
* We require the following features in Qt (unconditional, no fallback):
- * Feature Added in version
+ * Feature Added in version Macro
* - inotify_init1 before 2.6.12-rc12
* - futex(2) before 2.6.12-rc12
* - FUTEX_PRIVATE_FLAG 2.6.22
@@ -84,9 +86,15 @@
* - eventfd 2.6.23
* - pipe2 & dup3 2.6.27
* - accept4 2.6.28
+ * - getrandom 3.17 QT_CONFIG(getentropy)
*/
+#if QT_CONFIG(getentropy)
+ .long 3
+ .long 17
+ .long 0
+#else
.long 2
.long 6
.long 28
-
+#endif
diff --git a/src/corelib/global/qconfig-bootstrapped.h b/src/corelib/global/qconfig-bootstrapped.h
index a6a56b5d59..7dba4ae5da 100644
--- a/src/corelib/global/qconfig-bootstrapped.h
+++ b/src/corelib/global/qconfig-bootstrapped.h
@@ -76,6 +76,7 @@
# define QT_FEATURE_alloca_malloc_h -1
#endif
#define QT_FEATURE_cxx11_random (QT_HAS_INCLUDE(<random>) ? 1 : -1)
+#define QT_FEATURE_getentropy -1
#define QT_FEATURE_iconv -1
#define QT_FEATURE_icu -1
#define QT_FEATURE_journald -1
diff --git a/src/corelib/global/qrandom.cpp b/src/corelib/global/qrandom.cpp
index 0fa67f69f8..daa9f25122 100644
--- a/src/corelib/global/qrandom.cpp
+++ b/src/corelib/global/qrandom.cpp
@@ -48,15 +48,19 @@
#include <errno.h>
-#if QT_CONFIG(cxx11_random)
-# include <random>
-# include "qdeadlinetimer.h"
-# include "qhashfunctions.h"
-#endif
+#if QT_CONFIG(getentropy)
+# include <sys/random.h>
+#else
+# if QT_CONFIG(cxx11_random)
+# include <random>
+# include "qdeadlinetimer.h"
+# include "qhashfunctions.h"
+# endif
-#if QT_CONFIG(sys_auxv)
-# include <sys/auxv.h>
-#endif
+# if QT_CONFIG(sys_auxv)
+# include <sys/auxv.h>
+# endif
+#endif // !QT_CONFIG(getentropy)
#ifdef Q_OS_UNIX
# include <fcntl.h>
@@ -111,7 +115,26 @@ out:
#endif
namespace {
-#ifdef Q_OS_UNIX
+#if QT_CONFIG(getentropy)
+class SystemRandom
+{
+public:
+ enum { EfficientBufferFill = true };
+ static qssize_t fillBuffer(void *buffer, qssize_t count) Q_DECL_NOTHROW
+ {
+ // getentropy can read at most 256 bytes, so break the reading
+ qssize_t read = 0;
+ while (count - read > 256) {
+ // getentropy can't fail under normal circumstances
+ read += getentropy(reinterpret_cast<uchar *>(buffer) + read, 256);
+ }
+
+ getentropy(reinterpret_cast<uchar *>(buffer) + read, count - read);
+ return count;
+ }
+};
+
+#elif defined(Q_OS_UNIX)
class SystemRandom
{
static QBasicAtomicInt s_fdp1; // "file descriptor plus 1"
@@ -208,6 +231,12 @@ static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW
return value;
});
}
+#elif QT_CONFIG(getentropy)
+static void fallback_update_seed(unsigned) {}
+static void fallback_fill(quint32 *, qssize_t) Q_DECL_NOTHROW
+{
+ // no fallback necessary, getentropy cannot fail under normal circumstances
+}
#elif defined(Q_OS_BSD4)
static void fallback_update_seed(unsigned) {}
static void fallback_fill(quint32 *ptr, qssize_t left) Q_DECL_NOTHROW
diff --git a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
index 83bee29d1a..ce2232f310 100644
--- a/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
+++ b/tests/auto/corelib/global/qrandomgenerator/tst_qrandomgenerator.cpp
@@ -38,7 +38,7 @@
# include <random>
#endif
-#if QT_CONFIG(cxx11_random) || defined(Q_OS_BSD4) || defined(Q_OS_WIN)
+#if !QT_CONFIG(getentropy) && (QT_CONFIG(cxx11_random) || defined(Q_OS_BSD4) || defined(Q_OS_WIN))
# define HAVE_FALLBACK_ENGINE
#endif