#if BUILDFLAG(IS_AIX) // AIX has no 64-bit support for O_CLOEXEC. static constexpr int kOpenFlags = O_RDONLY; #else static constexpr int kOpenFlags = O_RDONLY | O_CLOEXEC; #endif
// We keep the file descriptor for /dev/urandom around so we don't need to // reopen it (which is expensive), and since we may not even be able to reopen // it if we are later put in a sandbox. This class wraps the file descriptor so // we can use a static-local variable to handle opening it on the first access. class URandomFd {
public:
URandomFd() : fd_(HANDLE_EINTR(open("/dev/urandom", kOpenFlags))) {
CHECK(fd_ >= 0) << "Cannot open /dev/urandom";
}
bool KernelSupportsGetRandom() {
int32_t major = 0;
int32_t minor = 0;
int32_t bugfix = 0;
KernelVersionNumbers(&major, &minor, &bugfix); if (major > 3 || (major == 3 && minor >= 17)) return true; returnfalse;
}
bool GetRandomSyscall(void* output, size_t output_length) { // We have to call `getrandom` via Linux Syscall Support, rather than through // the libc wrapper, because we might not have an up-to-date libc (e.g. on // some bots). const ssize_t r =
HANDLE_EINTR(syscall(__NR_getrandom, output, output_length, 0));
// Return success only on total success. In case errno == ENOSYS (or any other // error), we'll fall through to reading from urandom below. if (output_length == static_cast<size_t>(r)) {
MSAN_UNPOISON(output, output_length); return true;
} returnfalse;
} #endif// (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || // BUILDFLAG(IS_ANDROID)) && !BUILDFLAG(IS_NACL)
// Note: the BoringSSL feature takes precedence over the getrandom() trial if // both are enabled.
BASE_FEATURE(kUseGetrandomForRandBytes, "UseGetrandomForRandBytes",
FEATURE_ENABLED_BY_DEFAULT);
void RandBytes(void* output, size_t output_length, bool avoid_allocation) { #if !defined(MOZ_ZUCCHINI) #if !BUILDFLAG(IS_NACL) // The BoringSSL experiment takes priority over everything else. if (!avoid_allocation && internal::UseBoringSSLForRandBytes()) { // Ensure BoringSSL is initialized so it can use things like RDRAND.
CRYPTO_library_init(); // BoringSSL's RAND_bytes always returns 1. Any error aborts the program.
(void)RAND_bytes(static_cast<uint8_t*>(output), output_length); return;
} #endif #endif// !defined(MOZ_ZUCCHINI) #if (BUILDFLAG(IS_LINUX) || BUILDFLAG(IS_CHROMEOS) || \
BUILDFLAG(IS_ANDROID)) && \
!BUILDFLAG(IS_NACL) #if !defined(MOZ_ZUCCHINI) if (avoid_allocation || UseGetrandom()) { // On Android it is mandatory to check that the kernel _version_ has the // support for a syscall before calling. The same check is made on Linux and // ChromeOS to avoid making a syscall that predictably returns ENOSYS. staticconstbool kernel_has_support = KernelSupportsGetRandom(); if (kernel_has_support && GetRandomSyscall(output, output_length)) return;
} #endif// !defined(MOZ_ZUCCHINI) #elif BUILDFLAG(IS_MAC) // TODO(crbug.com/995996): Enable this on iOS too, when sys/random.h arrives // in its SDK. if (getentropy(output, output_length) == 0) { return;
} #endif
// If the OS-specific mechanisms didn't work, fall through to reading from // urandom. // // TODO(crbug.com/995996): When we no longer need to support old Linux // kernels, we can get rid of this /dev/urandom branch altogether. constint urandom_fd = GetUrandomFD(); constbool success =
ReadFromFD(urandom_fd, static_cast<char*>(output), output_length);
CHECK(success);
}
} // namespace
namespace internal {
double RandDoubleAvoidAllocation() {
uint64_t number;
RandBytes(&number, sizeof(number), /*avoid_allocation=*/true); // This transformation is explained in rand_util.cc. return (number >> 11) * 0x1.0p-53;
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.