Skip to content

Commit

Permalink
Prevent a few code paths from running when we know the disk database …
Browse files Browse the repository at this point in the history
…is not available (e.g. broken or more recent than this particular FTL binary can handle (like checking out a very old branch))

Signed-off-by: DL6ER <[email protected]>
  • Loading branch information
DL6ER committed Jan 3, 2025
1 parent 76e8373 commit a47c35e
Show file tree
Hide file tree
Showing 5 changed files with 74 additions and 17 deletions.
6 changes: 5 additions & 1 deletion src/api/auth.c
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,8 @@
#include "config/password.h"
// database session functions
#include "database/session-table.h"
// FTLDBerror()
#include "database/common.h"

static uint16_t max_sessions = 0;
static struct session *auth_data = NULL;
Expand All @@ -51,7 +53,9 @@ void init_api(void)
log_crit("Could not allocate memory for API sessions, check config value of webserver.api.max_sessions");
exit(EXIT_FAILURE);
}
restore_db_sessions(auth_data, max_sessions);

if(!FTLDBerror())
restore_db_sessions(auth_data, max_sessions);
}

void free_api(void)
Expand Down
32 changes: 27 additions & 5 deletions src/database/common.c
Original file line number Diff line number Diff line change
Expand Up @@ -127,10 +127,6 @@ sqlite3* _dbopen(const bool readonly, const bool create, const char *func, const

int dbquery(sqlite3* db, const char *format, ...)
{
// Return early if the database is known to be broken
if(FTLDBerror())
return SQLITE_ERROR;

va_list args;
va_start(args, format);
char *query = sqlite3_vmprintf(format, args);
Expand Down Expand Up @@ -311,6 +307,7 @@ void db_init(void)
{
log_warn("Database not available, please ensure the database is unlocked when starting pihole-FTL !");
dbclose(&db);
DBerror = true;
return;
}
else
Expand All @@ -328,6 +325,7 @@ void db_init(void)
{
log_err("Counter table not initialized, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -343,6 +341,7 @@ void db_init(void)
{
log_err("Network table not initialized, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -358,6 +357,7 @@ void db_init(void)
{
log_err("Unable to unify clients in network table, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -373,6 +373,7 @@ void db_init(void)
{
log_err("Network-addresses table not initialized, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -388,6 +389,7 @@ void db_init(void)
{
log_err("Message table not initialized, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -403,6 +405,7 @@ void db_init(void)
{
log_err("Column additional_info not initialized, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -418,6 +421,7 @@ void db_init(void)
{
log_err("Network addresses table not initialized, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -433,6 +437,7 @@ void db_init(void)
{
log_err("Aliasclients table not initialized, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -448,6 +453,7 @@ void db_init(void)
{
log_info("Queries table not optimized, database not available");
dbclose(&db);
DBerror = true;
return;
}

Expand All @@ -469,6 +475,7 @@ void db_init(void)
{
log_info("Link table for additional_info not generated, database not available");
dbclose(&db);
DBerror = true;
return;
}

Expand All @@ -490,6 +497,7 @@ void db_init(void)
{
log_info("Additional records not generated, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -505,6 +513,7 @@ void db_init(void)
{
log_info("Additional records not generated, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -520,6 +529,7 @@ void db_init(void)
{
log_info("FTL table description cannot be added, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -535,6 +545,7 @@ void db_init(void)
{
log_info("Session table cannot be created, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -550,6 +561,7 @@ void db_init(void)
{
log_info("Session table cannot be updated, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -565,6 +577,7 @@ void db_init(void)
{
log_info("regex_id cannot be renamed to list_id, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -580,6 +593,7 @@ void db_init(void)
{
log_info("Session table cannot be updated, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -595,6 +609,7 @@ void db_init(void)
{
log_info("Session table cannot be updated, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -610,6 +625,7 @@ void db_init(void)
{
log_info("Network addresses network_id index cannot be added, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -625,6 +641,7 @@ void db_init(void)
{
log_info("Additional column 'ede' in the query_storage table cannot be added, database not available");
dbclose(&db);
DBerror = true;
return;
}
// Get updated version
Expand All @@ -642,7 +659,12 @@ void db_init(void)
// Last check after all migrations, if this happens, it will cause the
// CI to fail the tests
if(dbversion != MEMDB_VERSION)
log_err("Expected query database version %d but found %d", MEMDB_VERSION, dbversion);
{
log_err("Expected query database version %d but found %d, database not available", MEMDB_VERSION, dbversion);
dbclose(&db);
DBerror = true;
return;
}

lock_shm();
import_aliasclients(db);
Expand Down
46 changes: 38 additions & 8 deletions src/database/query-table.c
Original file line number Diff line number Diff line change
Expand Up @@ -124,15 +124,14 @@ bool init_memory_database(void)
}
}

// Attach disk database
if(!attach_database(_memdb, NULL, config.files.database.v.s, "disk"))
return false;
// Attach disk database. This may fail if the database is unavailable
const bool attached = attach_database(_memdb, NULL, config.files.database.v.s, "disk");

// Enable WAL mode for the on-disk database (pihole-FTL.db) if
// configured (default is yes). User may not want to enable WAL
// mode if the database is on a network share as all processes
// accessing the database must be on the same host in WAL mode.
if(config.database.useWAL.v.b)
if(config.database.useWAL.v.b && attached)
{
// Change journal mode to WAL
// - WAL is significantly faster in most scenarios.
Expand All @@ -149,7 +148,7 @@ bool init_memory_database(void)
return false;
}
}
else
else if(attached)
{
// Unlike the other journaling modes, PRAGMA journal_mode=WAL is
// persistent. If a process sets WAL mode, then closes and
Expand Down Expand Up @@ -224,7 +223,11 @@ bool init_memory_database(void)
return false;
}

load_queries_from_disk();
// Attach disk database
if(attached)
load_queries_from_disk();
else
log_err("init_memory_database(): Failed to attach disk database");

// Everything went well
return true;
Expand Down Expand Up @@ -352,6 +355,10 @@ bool attach_database(sqlite3* db, const char **message, const char *path, const
bool okay = false;
sqlite3_stmt *stmt = NULL;

// Only try to attach database if it is not known to be broken
if(FTLDBerror())
return false;

log_debug(DEBUG_DATABASE, "ATTACH %s AS %s", path, alias);

// ATTACH database file on-disk
Expand Down Expand Up @@ -583,6 +590,11 @@ bool export_queries_to_disk(bool final)
{
bool okay = false;
const double time = double_time() - (final ? 0.0 : REPLY_TIMEOUT);

// Only try to export to database if it is known to not be broken
if(FTLDBerror())
return false;

const char *querystr = "INSERT INTO disk.query_storage SELECT * FROM query_storage WHERE id > ? AND timestamp < ?";

log_debug(DEBUG_DATABASE, "Storing queries on disk WHERE id > %lu (max is %lu) and timestamp < %f",
Expand Down Expand Up @@ -1064,6 +1076,10 @@ void DB_read_queries(void)
"dnssec "\
"FROM queries WHERE timestamp >= ?";

// Only try to import from database if it is known to not be broken
if(FTLDBerror())
return;

log_info("Parsing queries in database");

// Prepare SQLite3 statement
Expand Down Expand Up @@ -1382,12 +1398,22 @@ void DB_read_queries(void)
log_info("Imported %u queries from the long-term database", counters->queries);
}

void update_disk_db_idx(void)
void init_disk_db_idx(void)
{
// Query the database to get the maximum database ID is important to avoid
// starting counting from zero (would result in a UNIQUE constraint violation)
const char *querystr = "SELECT MAX(id) FROM disk.query_storage";

// If the disk database is broken, we cannot import queries from it,
// however, as we will also never export any queries, we can safely
// assume any index
if(FTLDBerror())
{
last_disk_db_idx = 0;
last_mem_db_idx = 0;
return;
}

// Prepare SQLite3 statement
sqlite3_stmt *stmt = NULL;
sqlite3 *memdb = get_memdb();
Expand All @@ -1397,7 +1423,7 @@ void update_disk_db_idx(void)
if(rc == SQLITE_OK && (rc = sqlite3_step(stmt)) == SQLITE_ROW)
last_disk_db_idx = sqlite3_column_int64(stmt, 0);
else
log_err("update_disk_db_idx(): Failed to get MAX(id) from disk.query_storage: %s",
log_err("init_disk_db_idx(): Failed to get MAX(id) from disk.query_storage: %s",
sqlite3_errstr(rc));

// Finalize statement
Expand All @@ -1416,6 +1442,10 @@ bool queries_to_database(void)
unsigned int added = 0, updated = 0;
sqlite3_int64 idx = 0;

// Only try to export to database if it is known to not be broken
if(FTLDBerror())
return false;

// Skip, we never store nor count queries recorded while have been in
// maximum privacy mode in the database
if(config.misc.privacylevel.v.privacy_level >= PRIVACY_MAXIMUM)
Expand Down
2 changes: 1 addition & 1 deletion src/database/query-table.h
Original file line number Diff line number Diff line change
Expand Up @@ -118,7 +118,7 @@ bool export_queries_to_disk(bool final);
bool delete_old_queries_from_db(const bool use_memdb, const double mintime);
bool add_additional_info_column(sqlite3 *db);
void DB_read_queries(void);
void update_disk_db_idx(void);
void init_disk_db_idx(void);
bool queries_to_database(void);

bool optimize_queries_table(sqlite3 *db);
Expand Down
5 changes: 3 additions & 2 deletions src/dnsmasq_interface.c
Original file line number Diff line number Diff line change
Expand Up @@ -3118,7 +3118,8 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw, bool dnsmasq_start)
log_crit("Cannot initialize in-memory database.");

// Flush messages stored in the long-term database
flush_message_table();
if(!FTLDBerror())
flush_message_table();

// Verify checksum of this binary early on to ensure that the binary is
// not corrupted and that the binary is not tampered with. We can only
Expand All @@ -3127,7 +3128,7 @@ void FTL_fork_and_bind_sockets(struct passwd *ent_pw, bool dnsmasq_start)
verify_FTL(false);

// Initialize in-memory database starting index
update_disk_db_idx();
init_disk_db_idx();

// Handle real-time signals in this process (and its children)
// Helper processes are already split from the main instance
Expand Down

0 comments on commit a47c35e

Please sign in to comment.