Skip to content

Commit

Permalink
AK: Prevent passing lengths greater than 256 to getentropy()
Browse files Browse the repository at this point in the history
From the getentropy() man page, "The maximum permitted value for the
length argument is 256". Several of our tests were passing lengths of
several thousand bytes, causing getentropy() to fail with EIO, which we
were completely ignoring. This caused these tests to only test long
sequences of 0x00.

We now loop over the provided buffer to fill it 256 bytes at a time. If
getentropy() fails for any reason, we fall back to the default method of
filling it with one random byte at a time.
  • Loading branch information
trflynn89 authored and awesomekling committed Apr 3, 2023
1 parent cb0c863 commit f7960ff
Showing 1 changed file with 28 additions and 13 deletions.
41 changes: 28 additions & 13 deletions AK/Random.h
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,7 @@
#include <AK/Platform.h>
#include <AK/StdLibExtras.h>
#include <AK/Types.h>

#if defined(AK_OS_SERENITY) || defined(AK_OS_ANDROID)
# include <stdlib.h>
#endif
#include <stdlib.h>

#if defined(__unix__)
# include <unistd.h>
Expand All @@ -22,24 +19,42 @@
# include <sys/random.h>
#endif

#if defined(AK_OS_WINDOWS)
# include <stdlib.h>
#endif

namespace AK {

inline void fill_with_random([[maybe_unused]] void* buffer, [[maybe_unused]] size_t length)
{
#if defined(AK_OS_SERENITY) || defined(AK_OS_ANDROID)
arc4random_buf(buffer, length);
#elif defined(OSS_FUZZ)
#elif defined(__unix__) or defined(AK_OS_MACOS)
[[maybe_unused]] int rc = getentropy(buffer, length);
#else
char* char_buffer = static_cast<char*>(buffer);
for (size_t i = 0; i < length; i++) {
char_buffer[i] = rand();
auto fill_with_random_fallback = [&]() {
char* char_buffer = static_cast<char*>(buffer);
for (size_t i = 0; i < length; i++)
char_buffer[i] = rand();
};

# if defined(__unix__) or defined(AK_OS_MACOS)
// The maximum permitted value for the getentropy length argument.
static constexpr size_t getentropy_length_limit = 256;

auto iterations = length / getentropy_length_limit;
auto remainder = length % getentropy_length_limit;
auto address = reinterpret_cast<FlatPtr>(buffer);

for (size_t i = 0; i < iterations; ++i) {
if (getentropy(reinterpret_cast<void*>(address), getentropy_length_limit) != 0) {
fill_with_random_fallback();
return;
}

address += getentropy_length_limit;
}

if (remainder == 0 || getentropy(reinterpret_cast<void*>(address), remainder) == 0)
return;
# endif

fill_with_random_fallback();
#endif
}

Expand Down

0 comments on commit f7960ff

Please sign in to comment.