https://bugs.webkit.org/show_bug.cgi?id=170095
Reviewed by Michael Catanzaro.
In this patch, we introduce RandomDevice, which keeps /dev/urandom opened
to avoid repeatedly open and close urandom file descriptor in Linux.
The purpose is similar to std::random_device, but WTF::RandomDevice explicitly
avoids using ARC4, which is recently attempted to be removed from the WebKit
tree[1].
[1]: https://trac.webkit.org/r214329
* WTF.xcodeproj/project.pbxproj:
* wtf/CMakeLists.txt:
* wtf/OSRandomSource.cpp:
(WTF::cryptographicallyRandomValuesFromOS):
(WTF::crashUnableToOpenURandom): Deleted.
(WTF::crashUnableToReadFromURandom): Deleted.
* wtf/RandomDevice.cpp: Copied from Source/WTF/wtf/OSRandomSource.cpp.
(WTF::crashUnableToOpenURandom):
(WTF::crashUnableToReadFromURandom):
(WTF::RandomDevice::RandomDevice):
(WTF::RandomDevice::~RandomDevice):
(WTF::RandomDevice::cryptographicallyRandomValues):
* wtf/RandomDevice.h: Added.
git-svn-id: https://svn.webkit.org/repository/webkit/trunk@214867
268f45cc-cd09-0410-ab3c-
d52691b4dbfc
+2017-04-03 Yusuke Suzuki <utatane.tea@gmail.com>
+
+ [WTF] Introduce WTF::RandomDevice which keeps /dev/urandom opened
+ https://bugs.webkit.org/show_bug.cgi?id=170095
+
+ Reviewed by Michael Catanzaro.
+
+ In this patch, we introduce RandomDevice, which keeps /dev/urandom opened
+ to avoid repeatedly open and close urandom file descriptor in Linux.
+
+ The purpose is similar to std::random_device, but WTF::RandomDevice explicitly
+ avoids using ARC4, which is recently attempted to be removed from the WebKit
+ tree[1].
+
+ [1]: https://trac.webkit.org/r214329
+
+ * WTF.xcodeproj/project.pbxproj:
+ * wtf/CMakeLists.txt:
+ * wtf/OSRandomSource.cpp:
+ (WTF::cryptographicallyRandomValuesFromOS):
+ (WTF::crashUnableToOpenURandom): Deleted.
+ (WTF::crashUnableToReadFromURandom): Deleted.
+ * wtf/RandomDevice.cpp: Copied from Source/WTF/wtf/OSRandomSource.cpp.
+ (WTF::crashUnableToOpenURandom):
+ (WTF::crashUnableToReadFromURandom):
+ (WTF::RandomDevice::RandomDevice):
+ (WTF::RandomDevice::~RandomDevice):
+ (WTF::RandomDevice::cryptographicallyRandomValues):
+ * wtf/RandomDevice.h: Added.
+
2017-04-03 Filip Pizlo <fpizlo@apple.com>
WTF::Liveness should have an API that focuses on actions at instruction boundaries
FE8925B01D00DAEC0046907E /* Indenter.h in Headers */ = {isa = PBXBuildFile; fileRef = FE8925AF1D00DAEC0046907E /* Indenter.h */; };
FEDACD3D1630F83F00C69634 /* StackStats.cpp in Sources */ = {isa = PBXBuildFile; fileRef = FEDACD3B1630F83F00C69634 /* StackStats.cpp */; };
FEDACD3E1630F83F00C69634 /* StackStats.h in Headers */ = {isa = PBXBuildFile; fileRef = FEDACD3C1630F83F00C69634 /* StackStats.h */; };
+ FC6EC2BF20F849969C6A5BE1 /* RandomDevice.h in Headers */ = {isa = PBXBuildFile; fileRef = 24F1B248619F412296D1C19C /* RandomDevice.h */; };
+ A3B725EC987446AD93F1A440 /* RandomDevice.cpp in Sources */ = {isa = PBXBuildFile; fileRef = C8F597CA2A57417FBAB92FD6 /* RandomDevice.cpp */; };
/* End PBXBuildFile section */
/* Begin PBXContainerItemProxy section */
FE8925AF1D00DAEC0046907E /* Indenter.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = Indenter.h; sourceTree = "<group>"; };
FEDACD3B1630F83F00C69634 /* StackStats.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; path = StackStats.cpp; sourceTree = "<group>"; };
FEDACD3C1630F83F00C69634 /* StackStats.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = StackStats.h; sourceTree = "<group>"; };
+ 24F1B248619F412296D1C19C /* RandomDevice.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = RandomDevice.h; path = RandomDevice.h; sourceTree = "<group>"; };
+ C8F597CA2A57417FBAB92FD6 /* RandomDevice.cpp */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.cpp.cpp; name = RandomDevice.cpp; path = RandomDevice.cpp; sourceTree = "<group>"; };
/* End PBXFileReference section */
/* Begin PBXFrameworksBuildPhase section */
0FC4488216FE9FE100844BE9 /* ProcessID.h */,
143F611D1565F0F900DB514A /* RAMSize.cpp */,
143F611E1565F0F900DB514A /* RAMSize.h */,
+ 24F1B248619F412296D1C19C /* RandomDevice.h */,
+ C8F597CA2A57417FBAB92FD6 /* RandomDevice.cpp */,
A8A472FB151A825B004123FF /* RandomNumber.cpp */,
A8A472FC151A825B004123FF /* RandomNumber.h */,
A8A472FD151A825B004123FF /* RandomNumberSeed.h */,
0F9D3363165DBA73005AD387 /* PrintStream.h in Headers */,
0FC4488316FE9FE100844BE9 /* ProcessID.h in Headers */,
143F61201565F0F900DB514A /* RAMSize.h in Headers */,
+ FC6EC2BF20F849969C6A5BE1 /* RandomDevice.h in Headers */,
A8A47415151A825B004123FF /* RandomNumber.h in Headers */,
A8A47416151A825B004123FF /* RandomNumberSeed.h in Headers */,
0F725CAC1C50461600AD943A /* RangeSet.h in Headers */,
DCEE22031CEA7551000C2396 /* PlatformUserPreferredLanguagesMac.mm in Sources */,
0F9D3362165DBA73005AD387 /* PrintStream.cpp in Sources */,
143F611F1565F0F900DB514A /* RAMSize.cpp in Sources */,
+ A3B725EC987446AD93F1A440 /* RandomDevice.cpp in Sources */,
A8A47414151A825B004123FF /* RandomNumber.cpp in Sources */,
A8A4741A151A825B004123FF /* RefCountedLeakCounter.cpp in Sources */,
2CDED0F318115C85004DBA70 /* RunLoop.cpp in Sources */,
PrintStream.h
ProcessID.h
RAMSize.h
+ RandomDevice.h
RandomNumber.h
RandomNumberSeed.h
Range.h
ParkingLot.cpp
PrintStream.cpp
RAMSize.cpp
+ RandomDevice.cpp
RandomNumber.cpp
RefCountedLeakCounter.cpp
RunLoop.cpp
#include "config.h"
#include "OSRandomSource.h"
-#include <stdint.h>
-#include <stdlib.h>
-
-#if !OS(DARWIN) && OS(UNIX)
-#include <errno.h>
-#include <fcntl.h>
-#include <unistd.h>
-#endif
-
-#if OS(WINDOWS)
-#include <windows.h>
-#include <wincrypt.h> // windows.h must be included before wincrypt.h.
-#endif
-
-#if OS(DARWIN)
-#include "CommonCryptoSPI.h"
-#endif
+#include <wtf/NeverDestroyed.h>
+#include <wtf/RandomDevice.h>
namespace WTF {
-#if !OS(DARWIN) && OS(UNIX)
-NEVER_INLINE NO_RETURN_DUE_TO_CRASH static void crashUnableToOpenURandom()
-{
- CRASH();
-}
-
-NEVER_INLINE NO_RETURN_DUE_TO_CRASH static void crashUnableToReadFromURandom()
-{
- CRASH();
-}
-#endif
-
void cryptographicallyRandomValuesFromOS(unsigned char* buffer, size_t length)
{
-#if OS(DARWIN)
- RELEASE_ASSERT(!CCRandomCopyBytes(kCCRandomDefault, buffer, length));
-#elif OS(UNIX)
- int fd = open("/dev/urandom", O_RDONLY, 0);
- if (fd < 0)
- crashUnableToOpenURandom(); // We need /dev/urandom for this API to work...
-
- ssize_t amountRead = 0;
- while (static_cast<size_t>(amountRead) < length) {
- ssize_t currentRead = read(fd, buffer + amountRead, length - amountRead);
- // We need to check for both EAGAIN and EINTR since on some systems /dev/urandom
- // is blocking and on others it is non-blocking.
- if (currentRead == -1) {
- if (!(errno == EAGAIN || errno == EINTR))
- crashUnableToReadFromURandom();
- } else
- amountRead += currentRead;
- }
-
- close(fd);
-
-#elif OS(WINDOWS)
- HCRYPTPROV hCryptProv = 0;
- if (!CryptAcquireContext(&hCryptProv, 0, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
- CRASH();
- if (!CryptGenRandom(hCryptProv, length, buffer))
- CRASH();
- CryptReleaseContext(hCryptProv, 0);
-#else
- #error "This configuration doesn't have a strong source of randomness."
- // WARNING: When adding new sources of OS randomness, the randomness must
- // be of cryptographic quality!
-#endif
+ static NeverDestroyed<RandomDevice> device;
+ device.get().cryptographicallyRandomValues(buffer, length);
}
}
--- /dev/null
+/*
+ * Copyright (C) 2011 Google Inc.
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include "config.h"
+#include "RandomDevice.h"
+
+#include <stdint.h>
+#include <stdlib.h>
+
+#if !OS(DARWIN) && OS(UNIX)
+#include <errno.h>
+#include <fcntl.h>
+#include <unistd.h>
+#endif
+
+#if OS(WINDOWS)
+#include <windows.h>
+#include <wincrypt.h> // windows.h must be included before wincrypt.h.
+#endif
+
+#if OS(DARWIN)
+#include "CommonCryptoSPI.h"
+#endif
+
+namespace WTF {
+
+#if !OS(DARWIN) && OS(UNIX)
+NEVER_INLINE NO_RETURN_DUE_TO_CRASH static void crashUnableToOpenURandom()
+{
+ CRASH();
+}
+
+NEVER_INLINE NO_RETURN_DUE_TO_CRASH static void crashUnableToReadFromURandom()
+{
+ CRASH();
+}
+#endif
+
+#if !OS(DARWIN) && !OS(WINDOWS)
+RandomDevice::RandomDevice()
+{
+ int ret = 0;
+ do {
+ ret = open("/dev/urandom", O_RDONLY, 0);
+ } while (ret == -1 && errno == EINTR);
+ m_fd = ret;
+ if (m_fd < 0)
+ crashUnableToOpenURandom(); // We need /dev/urandom for this API to work...
+}
+#endif
+
+#if !OS(DARWIN) && !OS(WINDOWS)
+RandomDevice::~RandomDevice()
+{
+ close(m_fd);
+}
+#endif
+
+// FIXME: Make this call fast by creating the pool in RandomDevice.
+// https://bugs.webkit.org/show_bug.cgi?id=170190
+void RandomDevice::cryptographicallyRandomValues(unsigned char* buffer, size_t length)
+{
+#if OS(DARWIN)
+ RELEASE_ASSERT(!CCRandomCopyBytes(kCCRandomDefault, buffer, length));
+#elif OS(UNIX)
+ ssize_t amountRead = 0;
+ while (static_cast<size_t>(amountRead) < length) {
+ ssize_t currentRead = read(m_fd, buffer + amountRead, length - amountRead);
+ // We need to check for both EAGAIN and EINTR since on some systems /dev/urandom
+ // is blocking and on others it is non-blocking.
+ if (currentRead == -1) {
+ if (!(errno == EAGAIN || errno == EINTR))
+ crashUnableToReadFromURandom();
+ } else
+ amountRead += currentRead;
+ }
+#elif OS(WINDOWS)
+ // FIXME: We cannot ensure that Cryptographic Service Provider context and CryptGenRandom are safe across threads.
+ // If it is safe, we can acquire context per RandomDevice.
+ HCRYPTPROV hCryptProv = 0;
+ if (!CryptAcquireContext(&hCryptProv, 0, MS_DEF_PROV, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT))
+ CRASH();
+ if (!CryptGenRandom(hCryptProv, length, buffer))
+ CRASH();
+ CryptReleaseContext(hCryptProv, 0);
+#else
+#error "This configuration doesn't have a strong source of randomness."
+// WARNING: When adding new sources of OS randomness, the randomness must
+// be of cryptographic quality!
+#endif
+}
+
+}
--- /dev/null
+/*
+ * Copyright (C) 2011 Google Inc.
+ * Copyright (C) 2017 Yusuke Suzuki <utatane.tea@gmail.com>
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ *
+ * THIS SOFTWARE IS PROVIDED BY GOOGLE, INC. ``AS IS'' AND ANY
+ * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
+ * PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL APPLE INC. OR
+ * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
+ * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
+ * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
+ * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
+ * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+ * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
+ * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#pragma once
+
+#include <wtf/Noncopyable.h>
+#include <wtf/StdLibExtras.h>
+
+namespace WTF {
+
+class RandomDevice {
+ WTF_MAKE_NONCOPYABLE(RandomDevice);
+public:
+#if OS(DARWIN) || OS(WINDOWS)
+ RandomDevice() = default;
+#else
+ RandomDevice();
+ ~RandomDevice();
+#endif
+
+ // This function attempts to fill buffer with randomness from the operating
+ // system. Rather than calling this function directly, consider calling
+ // cryptographicallyRandomNumber or cryptographicallyRandomValues.
+ void cryptographicallyRandomValues(unsigned char* buffer, size_t length);
+
+private:
+#if OS(DARWIN) || OS(WINDOWS)
+#elif OS(UNIX)
+ int m_fd { -1 };
+#else
+#error "This configuration doesn't have a strong source of randomness."
+// WARNING: When adding new sources of OS randomness, the randomness must
+// be of cryptographic quality!
+#endif
+};
+
+}