@@ -106,6 +106,8 @@ const std::map<std::string, QueryPlanner::Opcode> kSQLOpcodes = {
106106 OpComparator (" IfNotZero" ),
107107};
108108
109+ RecursiveMutex SQLiteDBInstance::kPrimaryAttachMutex ;
110+
109111// / The SQLiteSQLPlugin implements the "sql" registry for internal/core.
110112class SQLiteSQLPlugin : public SQLPlugin {
111113 public:
@@ -147,29 +149,29 @@ Status SQLiteSQLPlugin::query(const std::string& query,
147149 bool use_cache) const {
148150 auto dbc = SQLiteDBManager::get ();
149151 dbc->useCache (use_cache);
150- auto result = queryInternal (query, results, dbc-> db () );
152+ auto result = queryInternal (query, results, dbc);
151153 dbc->clearAffectedTables ();
152154 return result;
153155}
154156
155157Status SQLiteSQLPlugin::getQueryColumns (const std::string& query,
156158 TableColumns& columns) const {
157159 auto dbc = SQLiteDBManager::get ();
158- return getQueryColumnsInternal (query, columns, dbc-> db () );
160+ return getQueryColumnsInternal (query, columns, dbc);
159161}
160162
161163Status SQLiteSQLPlugin::getQueryTables (const std::string& query,
162164 std::vector<std::string>& tables) const {
163165 auto dbc = SQLiteDBManager::get ();
164- QueryPlanner planner (query, dbc-> db () );
166+ QueryPlanner planner (query, dbc);
165167 tables = planner.tables ();
166168 return Status (0 );
167169}
168170
169171SQLInternal::SQLInternal (const std::string& query, bool use_cache) {
170172 auto dbc = SQLiteDBManager::get ();
171173 dbc->useCache (use_cache);
172- status_ = queryInternal (query, results_, dbc-> db () );
174+ status_ = queryInternal (query, results_, dbc);
173175
174176 // One of the advantages of using SQLInternal (aside from the Registry-bypass)
175177 // is the ability to "deep-inspect" the table attributes and actions.
@@ -207,7 +209,7 @@ void SQLiteSQLPlugin::detach(const std::string& name) {
207209}
208210
209211SQLiteDBInstance::SQLiteDBInstance (sqlite3*& db, Mutex& mtx)
210- : db_(db), lock_(mtx, MUTEX_IMPL ::try_to_lock) {
212+ : db_(db), lock_(mtx, boost ::try_to_lock) {
211213 if (lock_.owns_lock ()) {
212214 primary_ = true ;
213215 } else {
@@ -251,8 +253,11 @@ bool SQLiteDBInstance::useCache() const {
251253 return use_cache_;
252254}
253255
254- WriteLock SQLiteDBInstance::attachLock () const {
255- return WriteLock (attach_mutex_);
256+ RecursiveLock SQLiteDBInstance::attachLock () const {
257+ if (isPrimary ()) {
258+ return RecursiveLock (kPrimaryAttachMutex );
259+ }
260+ return RecursiveLock (attach_mutex_);
256261}
257262
258263void SQLiteDBInstance::addAffectedTable (VirtualTableContent* table) {
@@ -371,10 +376,11 @@ SQLiteDBManager::~SQLiteDBManager() {
371376 }
372377}
373378
374- QueryPlanner::QueryPlanner (const std::string& query, sqlite3* db) {
379+ QueryPlanner::QueryPlanner (const std::string& query,
380+ const SQLiteDBInstanceRef& instance) {
375381 QueryData plan;
376- queryInternal (" EXPLAIN QUERY PLAN " + query, plan, db );
377- queryInternal (" EXPLAIN " + query, program_, db );
382+ queryInternal (" EXPLAIN QUERY PLAN " + query, plan, instance );
383+ queryInternal (" EXPLAIN " + query, program_, instance );
378384
379385 for (const auto & row : plan) {
380386 auto details = osquery::split (row.at (" detail" ));
@@ -442,10 +448,13 @@ int queryDataCallback(void* argument, int argc, char* argv[], char* column[]) {
442448 return 0 ;
443449}
444450
445- Status queryInternal (const std::string& q, QueryData& results, sqlite3* db) {
451+ Status queryInternal (const std::string& q,
452+ QueryData& results,
453+ const SQLiteDBInstanceRef& instance) {
446454 char * err = nullptr ;
447- sqlite3_exec (db, q.c_str (), queryDataCallback, &results, &err);
448- sqlite3_db_release_memory (db);
455+ auto lock = instance->attachLock ();
456+ sqlite3_exec (instance->db (), q.c_str (), queryDataCallback, &results, &err);
457+ sqlite3_db_release_memory (instance->db ());
449458 if (err != nullptr ) {
450459 auto error_string = std::string (err);
451460 sqlite3_free (err);
@@ -456,55 +465,62 @@ Status queryInternal(const std::string& q, QueryData& results, sqlite3* db) {
456465
457466Status getQueryColumnsInternal (const std::string& q,
458467 TableColumns& columns,
459- sqlite3* db) {
460- // Turn the query into a prepared statement
461- sqlite3_stmt* stmt{nullptr };
462- auto rc = sqlite3_prepare_v2 (
463- db, q.c_str (), static_cast <int >(q.length () + 1 ), &stmt, nullptr );
464- if (rc != SQLITE_OK || stmt == nullptr ) {
465- if (stmt != nullptr ) {
466- sqlite3_finalize (stmt);
468+ const SQLiteDBInstanceRef& instance) {
469+ Status status = Status ();
470+ TableColumns results;
471+ {
472+ auto lock = instance->attachLock ();
473+
474+ // Turn the query into a prepared statement
475+ sqlite3_stmt* stmt{nullptr };
476+ auto rc = sqlite3_prepare_v2 (instance->db (),
477+ q.c_str (),
478+ static_cast <int >(q.length () + 1 ),
479+ &stmt,
480+ nullptr );
481+ if (rc != SQLITE_OK || stmt == nullptr ) {
482+ if (stmt != nullptr ) {
483+ sqlite3_finalize (stmt);
484+ }
485+ return Status (1 , sqlite3_errmsg (instance->db ()));
467486 }
468- return Status (1 , sqlite3_errmsg (db));
469- }
470487
471- // Get column count
472- auto num_columns = sqlite3_column_count (stmt);
473- TableColumns results;
474- results.reserve (num_columns);
488+ // Get column count
489+ auto num_columns = sqlite3_column_count (stmt);
490+ results.reserve (num_columns);
475491
476- // Get column names and types
477- Status status = Status ();
478- bool unknown_type = false ;
479- for (int i = 0 ; i < num_columns; ++i) {
480- auto col_name = sqlite3_column_name (stmt, i);
481- auto col_type = sqlite3_column_decltype (stmt, i);
482-
483- if (col_name == nullptr ) {
484- status = Status (1 , " Could not get column type" );
485- break ;
486- }
492+ // Get column names and types
493+ bool unknown_type = false ;
494+ for (int i = 0 ; i < num_columns; ++i) {
495+ auto col_name = sqlite3_column_name (stmt, i);
496+ auto col_type = sqlite3_column_decltype (stmt, i);
497+
498+ if (col_name == nullptr ) {
499+ status = Status (1 , " Could not get column type" );
500+ break ;
501+ }
487502
488- if (col_type == nullptr ) {
489- // Types are only returned for table columns (not expressions).
490- col_type = " UNKNOWN" ;
491- unknown_type = true ;
503+ if (col_type == nullptr ) {
504+ // Types are only returned for table columns (not expressions).
505+ col_type = " UNKNOWN" ;
506+ unknown_type = true ;
507+ }
508+ results.push_back (std::make_tuple (
509+ col_name, columnTypeName (col_type), ColumnOptions::DEFAULT ));
492510 }
493- results.push_back (std::make_tuple (
494- col_name, columnTypeName (col_type), ColumnOptions::DEFAULT ));
495- }
496511
497- // An unknown type means we have to parse the plan and SQLite opcodes.
498- if (unknown_type) {
499- QueryPlanner planner (q, db);
500- planner.applyTypes (results);
512+ // An unknown type means we have to parse the plan and SQLite opcodes.
513+ if (unknown_type) {
514+ QueryPlanner planner (q, instance);
515+ planner.applyTypes (results);
516+ }
517+ sqlite3_finalize (stmt);
501518 }
502519
503520 if (status.ok ()) {
504521 columns = std::move (results);
505522 }
506523
507- sqlite3_finalize (stmt);
508524 return status;
509525}
510526}
0 commit comments