Skip to content

Commit

Permalink
Merge pull request #2300 from pi-hole/fix/randomness_crash
Browse files Browse the repository at this point in the history
Prevent crash on failure to source secure randomness
  • Loading branch information
DL6ER authored Mar 1, 2025
2 parents 0840849 + 1bd92e7 commit d154623
Show file tree
Hide file tree
Showing 5 changed files with 177 additions and 50 deletions.
45 changes: 32 additions & 13 deletions src/config/password.c
Original file line number Diff line number Diff line change
Expand Up @@ -93,8 +93,8 @@ static char * __attribute__((malloc)) double_sha256_password(const char *passwor

bool get_secure_randomness(uint8_t *buffer, const size_t length)
{
ssize_t result;

ssize_t result = -1;
const char *generator = "getrandom";
// First try to get randomness in non-blocking mode and print a warning when not enough entropy is available right now
do {
result = getrandom(buffer, length, GRND_NONBLOCK);
Expand All @@ -103,32 +103,51 @@ bool get_secure_randomness(uint8_t *buffer, const size_t length)
// If not enough entropy is available right now, try again in blocking mode
if (result < 0 && errno == EAGAIN)
{
log_warn("getrandom() failed in get_secure_randomness(): Not enough entropy available right now, retrying in blocking mode");
log_warn("Not enough entropy available right now for generating secure randomness, retrying in blocking mode");
// Sleep for 1 second to give the kernel some time to gather entropy
sleepms(1000);
}
else
{
// If the first try was successful, return the result
if (result >= 0)
return true;
goto random_success;
}
do {
result = getrandom(buffer, length, 0);
} while (result < 0 && errno == EINTR);

if (result < 0)
if(result < 0)
{
const int err = errno;
log_err("getrandom() failed in get_secure_randomness(): %s", strerror(errno));
errno = err;
return false;
log_debug(DEBUG_API, "Getting secure randomness failed (%s), trying /dev/urandom", strerror(errno));
generator = "/dev/urandom";
result = getrandom_fallback(buffer, length, 0);
if(result < 0 || result < (ssize_t)length)
{
log_debug(DEBUG_API, "Fallback failed, trying internal DRBG generator");
generator = "internal DRBG";
result = drbg_random(buffer, length);
if(result < 0)
{
// Warning will be printed by drbg_random()
return false;
}

log_debug(DEBUG_API, "Internal DRBG generator successfully used");
}
else
log_debug(DEBUG_API, "Fallback to /dev/urandom successful");
}
else if((size_t)result != length)

// Check if enough bytes were generated
if(result != (ssize_t)length)
{
log_err("getrandom() failed in get_secure_randomness(): Not enough bytes generated (%zu != %zu)", (size_t)result, length);
log_err("Randomness generator (%s) failed: not enough bytes generated (%zd != %zu)", generator, result, length);
return false;
}

random_success:
log_debug(DEBUG_ANY, "Generated %zd bytes of secure randomness", result);
return true;
}

Expand Down Expand Up @@ -185,7 +204,7 @@ static char * __attribute__((malloc)) balloon_password(const char *password,
{
// Parameter check
if(password == NULL || salt == NULL)
return NULL;
return strdup("");

struct timespec start, end;
// Record starting time
Expand Down Expand Up @@ -370,7 +389,7 @@ char * __attribute__((malloc)) create_password(const char *password)
// genrandom() returns cryptographically secure random data
uint8_t salt[SALT_LEN] = { 0 };
if(!get_secure_randomness(salt, sizeof(salt)))
return NULL;
return strdup("");

// Generate balloon PHC-encoded password hash
return balloon_password(password, salt, true);
Expand Down
5 changes: 5 additions & 0 deletions src/daemon.c
Original file line number Diff line number Diff line change
Expand Up @@ -39,6 +39,8 @@
#include <locale.h>
// freeEnvVars()
#include "config/env.h"
// destroy_entropy()
#include "webserver/x509.h"

pthread_t threads[THREADS_MAX] = { 0 };
bool resolver_ready = false;
Expand Down Expand Up @@ -425,6 +427,9 @@ void cleanup(const int ret)
// This should be the last action when c
destroy_shmem();

// De-initialize the random number generator and entropy collector
destroy_entropy();

// Free environment variables
freeEnvVars();

Expand Down
5 changes: 5 additions & 0 deletions src/main.c
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,8 @@
#include "database/query-table.h"
// verify_FTL()
#include "files.h"
// init_entropy()
#include "webserver/x509.h"

char *username;
bool startup = true;
Expand Down Expand Up @@ -62,6 +64,9 @@ int main (int argc, char *argv[])
log_info("########## FTL started on %s! ##########", hostname());
log_FTL_version(false);

// Initialize entropy and random number generator
init_entropy();

// Catch signals not handled by dnsmasq
// We configure real-time signals later (after dnsmasq has forked)
handle_signals();
Expand Down
Loading

0 comments on commit d154623

Please sign in to comment.