diff --git a/absl/functional/function_ref.h b/absl/functional/function_ref.h index 6e03ac2e04e..5790a652518 100644 --- a/absl/functional/function_ref.h +++ b/absl/functional/function_ref.h @@ -122,6 +122,7 @@ class FunctionRef { // To help prevent subtle lifetime bugs, FunctionRef is not assignable. // Typically, it should only be used as an argument type. FunctionRef& operator=(const FunctionRef& rhs) = delete; + FunctionRef(const FunctionRef& rhs) = default; // Call the underlying object. R operator()(Args... args) const { diff --git a/absl/random/internal/seed_material.cc b/absl/random/internal/seed_material.cc index 4d38a57419e..0fcba509a9f 100644 --- a/absl/random/internal/seed_material.cc +++ b/absl/random/internal/seed_material.cc @@ -50,6 +50,12 @@ #endif +#if defined(__GLIBC__) && \ + (__GLIBC__ > 2 || (__GLIBC__ == 2 && __GLIBC_MINOR__ >= 25)) +// glibc >= 2.25 has getentropy() +#define ABSL_RANDOM_USE_GET_ENTROPY 1 +#endif + #if defined(ABSL_RANDOM_USE_BCRYPT) #include @@ -122,8 +128,29 @@ bool ReadSeedMaterialFromOSEntropyImpl(absl::Span values) { #else +#if defined(ABSL_RANDOM_USE_GET_ENTROPY) +// On *nix, use getentropy() if supported. Note that libc may support +// getentropy(), but the kernel may not, in which case this function will return +// false. +bool ReadSeedMaterialFromGetEntropy(absl::Span values) { + auto buffer = reinterpret_cast(values.data()); + size_t buffer_size = sizeof(uint32_t) * values.size(); + while (buffer_size > 0) { + // getentropy() has a maximum permitted length of 256. + size_t to_read = std::min(buffer_size, 256); + int result = getentropy(buffer, to_read); + if (result < 0) { + return false; + } + buffer += to_read; + buffer_size -= to_read; + } + return true; +} +#endif // defined(ABSL_RANDOM_GETENTROPY) + // On *nix, read entropy from /dev/urandom. -bool ReadSeedMaterialFromOSEntropyImpl(absl::Span values) { +bool ReadSeedMaterialFromDevURandom(absl::Span values) { const char kEntropyFile[] = "/dev/urandom"; auto buffer = reinterpret_cast(values.data()); @@ -150,6 +177,17 @@ bool ReadSeedMaterialFromOSEntropyImpl(absl::Span values) { return success; } +bool ReadSeedMaterialFromOSEntropyImpl(absl::Span values) { +#if defined(ABSL_RANDOM_USE_GET_ENTROPY) + if (ReadSeedMaterialFromGetEntropy(values)) { + return true; + } +#endif + // Libc may support getentropy, but the kernel may not, so we still have + // to fallback to ReadSeedMaterialFromDevURandom(). + return ReadSeedMaterialFromDevURandom(values); +} + #endif } // namespace