Prevent Magisk database race condition

The database should only be accessed by a single process, which is magiskd.
This means 'magisk --sqlite [SQL]' has to be updated to pass the SQL command to the daemon.
In addition, open the database connection with SQLITE_OPEN_FULLMUTEX to support multithread in magiskd.
This commit is contained in:
topjohnwu
2018-11-16 03:20:30 -05:00
parent ba70269398
commit ab5fedda0b
8 changed files with 130 additions and 150 deletions

View File

@@ -140,7 +140,7 @@ void clean_magisk_props() {
}, nullptr, false);
}
static int add_list(sqlite3 *db, const char *proc) {
int add_list(const char *proc) {
for (auto &s : hide_list) {
// They should be unique
if (s == proc)
@@ -149,30 +149,21 @@ static int add_list(sqlite3 *db, const char *proc) {
LOGI("hide_list add: [%s]\n", proc);
// Add to database
char sql[4096];
snprintf(sql, sizeof(sql), "INSERT INTO hidelist (process) VALUES('%s')", proc);
char *err = db_exec(sql);
db_err_cmd(err, return DAEMON_ERROR);
// Critical region
pthread_mutex_lock(&list_lock);
hide_list.push_back(proc);
kill_process(proc);
pthread_mutex_unlock(&list_lock);
// Add to database
char sql[4096];
snprintf(sql, sizeof(sql), "INSERT INTO hidelist (process) VALUES('%s')", proc);
sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
return DAEMON_SUCCESS;
}
int add_list(const char *proc) {
sqlite3 *db = get_magiskdb();
if (db) {
int ret = add_list(db, proc);
sqlite3_close_v2(db);
return ret;
}
return DAEMON_ERROR;
}
int add_list(int client) {
char *proc = read_string(client);
int ret = add_list(proc);
@@ -196,13 +187,10 @@ static int rm_list(const char *proc) {
pthread_mutex_unlock(&list_lock);
if (do_rm) {
sqlite3 *db = get_magiskdb();
if (db == nullptr)
return DAEMON_ERROR;
char sql[4096];
snprintf(sql, sizeof(sql), "DELETE FROM hidelist WHERE process='%s'", proc);
sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
sqlite3_close_v2(db);
char *err = db_exec(sql);
db_err(err);
return DAEMON_SUCCESS;
} else {
return HIDE_ITEM_NOT_EXIST;
@@ -218,31 +206,27 @@ int rm_list(int client) {
#define LEGACY_LIST MOUNTPOINT "/.core/hidelist"
static int collect_list(void *, int, char **data, char**) {
LOGI("hide_list: [%s]\n", data[0]);
hide_list.push_back(data[0]);
return 0;
}
bool init_list() {
LOGD("hide_list: initialize\n");
sqlite3 *db = get_magiskdb();
if (db == nullptr)
return false;
sqlite3_exec(db, "SELECT process FROM hidelist",
[] (auto, auto, char **data, auto) -> int
{
LOGI("hide_list: [%s]\n", data[0]);
hide_list.push_back(data[0]);
return 0;
}, nullptr, nullptr);
char *err = db_exec("SELECT process FROM hidelist", collect_list);
db_err_cmd(err, return false);
// Migrate old hide list into database
if (access(LEGACY_LIST, R_OK) == 0) {
Vector<CharArray> tmp;
file_to_vector(LEGACY_LIST, tmp);
for (auto &s : tmp)
add_list(db, s);
add_list(s);
unlink(LEGACY_LIST);
}
sqlite3_close_v2(db);
return true;
}
@@ -256,12 +240,11 @@ void ls_list(int client) {
}
static void set_hide_config() {
sqlite3 *db = get_magiskdb();
char sql[64];
sprintf(sql, "REPLACE INTO settings (key,value) VALUES('%s',%d)",
DB_SETTING_KEYS[HIDE_CONFIG], hide_enabled);
sqlite3_exec(db, sql, nullptr, nullptr, nullptr);
sqlite3_close_v2(db);
char *err = db_exec(sql);
db_err(err);
}
int launch_magiskhide(int client) {
@@ -314,10 +297,8 @@ int stop_magiskhide() {
void auto_start_magiskhide() {
if (!start_log_daemon())
return;
sqlite3 *db = get_magiskdb();
db_settings dbs;
get_db_settings(db, &dbs, HIDE_CONFIG);
sqlite3_close_v2(db);
get_db_settings(&dbs, HIDE_CONFIG);
if (dbs[HIDE_CONFIG]) {
pthread_t thread;
xpthread_create(&thread, nullptr, [](void*) -> void* {