diff --git a/native/src/core/bootstages.cpp b/native/src/core/bootstages.cpp index 6b54296ce..8b265a7ef 100644 --- a/native/src/core/bootstages.cpp +++ b/native/src/core/bootstages.cpp @@ -137,7 +137,7 @@ static bool check_safe_mode() { int bootloop_cnt; db_settings dbs; get_db_settings(dbs, BOOTLOOP_COUNT); - bootloop_cnt = dbs[BOOTLOOP_COUNT]; + bootloop_cnt = dbs.bootloop; // Increment the bootloop counter set_db_settings(BOOTLOOP_COUNT, bootloop_cnt + 1); return bootloop_cnt >= 2 || get_prop("persist.sys.safemode", true) == "1" || @@ -187,7 +187,7 @@ bool MagiskD::post_fs_data() const noexcept { exec_common_scripts("post-fs-data"); db_settings dbs; get_db_settings(dbs, ZYGISK_CONFIG); - zygisk_enabled = dbs[ZYGISK_CONFIG]; + zygisk_enabled = dbs.zygisk; initialize_denylist(); setup_mounts(); handle_modules(); diff --git a/native/src/core/db.cpp b/native/src/core/db.cpp index b07cddd0e..d40c2b36f 100644 --- a/native/src/core/db.cpp +++ b/native/src/core/db.cpp @@ -11,41 +11,9 @@ using namespace std; -static sqlite3 *mDB = nullptr; - #define DBLOGV(...) //#define DBLOGV(...) LOGD("magiskdb: " __VA_ARGS__) -int db_strings::get_idx(string_view key) const { - int idx = 0; - for (const char *k : DB_STRING_KEYS) { - if (key == k) - break; - ++idx; - } - return idx; -} - -db_settings::db_settings() { - // Default settings - data[ROOT_ACCESS] = ROOT_ACCESS_APPS_AND_ADB; - data[SU_MULTIUSER_MODE] = MULTIUSER_MODE_OWNER_ONLY; - data[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER; - data[DENYLIST_CONFIG] = false; - data[ZYGISK_CONFIG] = MagiskD().is_emulator(); - data[BOOTLOOP_COUNT] = 0; -} - -int db_settings::get_idx(string_view key) const { - int idx = 0; - for (const char *k : DB_SETTING_KEYS) { - if (key == k) - break; - ++idx; - } - return idx; -} - struct db_result { db_result() = default; db_result(const char *s) : err(s) {} @@ -61,11 +29,11 @@ private: string err; }; -static int sql_exec(sqlite3 *db, const char *sql, sqlite_row_callback callback = nullptr, void *v = nullptr) { - return sql_exec(db, sql, {}, callback, v); +static int sql_exec(sqlite3 *db, const char *sql, sql_exec_callback callback = nullptr, void *v = nullptr) { + return sql_exec(db, sql, nullptr, nullptr, callback, v); } -static db_result open_and_init_db() { +static db_result open_and_init_db_impl(sqlite3 **dbOut) { if (!load_sqlite()) return "Cannot load libsqlite.so"; @@ -79,8 +47,8 @@ static db_result open_and_init_db() { int ver = 0; bool upgrade = false; - auto ver_cb = [](void *ver, auto, StringSlice data) { - *((int *) ver) = parse_int(data[0].c_str()); + auto ver_cb = [](void *ver, auto, DbValues &data) { + *static_cast(ver) = data.get_int(0); }; fn_run_ret(sql_exec, db.get(), "PRAGMA user_version", ver_cb, &ver); if (ver > DB_VERSION) { @@ -190,40 +158,48 @@ static db_result open_and_init_db() { sprintf(query, "PRAGMA user_version=%d", ver); fn_run_ret(sql_exec, db.get(), query); } - mDB = db.release(); + + *dbOut = db.release(); return {}; } -static db_result ensure_db() { - if (mDB == nullptr) { - db_result res = open_and_init_db(); - if (!res) { - // Open fails, remove and reconstruct +sqlite3 *open_and_init_db() { + sqlite3 *db = nullptr; + if (!open_and_init_db_impl(&db)) + return nullptr; + return db; +} + +static sqlite3 *get_db() { + static sqlite3 *db = nullptr; + if (db == nullptr) { + db = open_and_init_db(); + if (db == nullptr) { + // Open failed, remove and reconstruct unlink(MAGISKDB); - return open_and_init_db(); + db = open_and_init_db(); } } - return {}; + return db; } -bool db_exec(const char *sql) { - if (ensure_db() && mDB) { - db_result res = sql_exec(mDB, sql); - return res; - } - return false; -} - -bool db_exec(const char *sql, const db_row_cb &fn) { - if (ensure_db() && mDB) { - auto convert = [](void *cb, StringSlice columns, StringSlice data) { - auto &func = *static_cast(cb); - db_row row; - for (int i = 0; i < columns.size(); ++i) - row[columns[i].c_str()] = data[i].c_str(); - func(row); - }; - db_result res = sql_exec(mDB, sql, convert, (void *) &fn); +bool db_exec(const char *sql, db_bind_callback bind_fn, db_exec_callback exec_fn) { + if (sqlite3 *db = get_db()) { + sql_bind_callback bind_cb = nullptr; + if (bind_fn) { + bind_cb = [](void *v, int index, DbStatement &stmt) { + auto fn = static_cast(v); + fn->operator()(index, stmt); + }; + } + sql_exec_callback exec_cb = nullptr; + if (exec_fn) { + exec_cb = [](void *v, StringSlice columns, DbValues &data) { + auto fn = static_cast(v); + fn->operator()(columns, data); + }; + } + db_result res = sql_exec(db, sql, bind_cb, &bind_fn, exec_cb, &exec_fn); return res; } return false; @@ -231,17 +207,12 @@ bool db_exec(const char *sql, const db_row_cb &fn) { int get_db_settings(db_settings &cfg, int key) { bool res; - auto settings_cb = [&](db_row &row) -> bool { - cfg[row["key"]] = parse_int(row["value"]); - DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data()); - return true; - }; if (key >= 0) { char query[128]; ssprintf(query, sizeof(query), "SELECT * FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]); - res = db_exec(query, settings_cb); + res = db_exec(query, cfg); } else { - res = db_exec("SELECT * FROM settings", settings_cb); + res = db_exec("SELECT * FROM settings", cfg); } return res ? 0 : 1; } @@ -255,17 +226,12 @@ int set_db_settings(int key, int value) { int get_db_strings(db_strings &str, int key) { bool res; - auto string_cb = [&](db_row &row) -> bool { - str[row["key"]] = row["value"]; - DBLOGV("query %s=[%s]\n", row["key"].data(), row["value"].data()); - return true; - }; if (key >= 0) { char query[128]; ssprintf(query, sizeof(query), "SELECT * FROM strings WHERE key='%s'", DB_STRING_KEYS[key]); - res = db_exec(query, string_cb); + res = db_exec(query, str); } else { - res = db_exec("SELECT * FROM strings", string_cb); + res = db_exec("SELECT * FROM strings", str); } return res ? 0 : 1; } @@ -278,18 +244,65 @@ void rm_db_strings(int key) { void exec_sql(owned_fd client) { string sql = read_string(client); - db_exec(sql.data(), [fd = (int) client](db_row &row) -> bool { + db_exec(sql.data(), [fd = (int) client](StringSlice columns, DbValues &data) { string out; - bool first = true; - for (auto it : row) { - if (first) first = false; - else out += '|'; - out += it.first; + for (int i = 0; i < columns.size(); ++i) { + if (i != 0) out += '|'; + out += columns[i].c_str(); out += '='; - out += it.second; + out += data.get_text(i); } write_string(fd, out); - return true; }); write_int(client, 0); } + +db_settings::db_settings() : + root_access(ROOT_ACCESS_APPS_AND_ADB), + multiuser_mode(MULTIUSER_MODE_OWNER_ONLY), + mnt_ns(NAMESPACE_MODE_REQUESTER), + bootloop(0), + denylist(false), + zygisk(MagiskD().is_emulator()) {} + +void db_settings::operator()(StringSlice columns, DbValues &data) { + string_view key; + int val; + for (int i = 0; i < columns.size(); ++i) { + const auto &name = columns[i]; + if (name == "key") { + key = data.get_text(i); + } else if (name == "value") { + val = data.get_int(i); + } + } + if (key == DB_SETTING_KEYS[ROOT_ACCESS]) { + root_access = val; + } else if (key == DB_SETTING_KEYS[SU_MULTIUSER_MODE]) { + multiuser_mode = val; + } else if (key == DB_SETTING_KEYS[SU_MNT_NS]) { + mnt_ns = val; + } else if (key == DB_SETTING_KEYS[BOOTLOOP_COUNT]) { + bootloop = val; + } else if (key == DB_SETTING_KEYS[DENYLIST_CONFIG]) { + denylist = val; + } else if (key == DB_SETTING_KEYS[ZYGISK_CONFIG]) { + zygisk = val; + } +} + +void db_strings::operator()(StringSlice columns, DbValues &data) { + string_view key; + const char *val; + for (int i = 0; i < columns.size(); ++i) { + const auto &name = columns[i]; + if (name == "key") { + key = data.get_text(i); + } else if (name == "value") { + val = data.get_text(i); + } + } + if (key == DB_STRING_KEYS[SU_MANAGER]) { + su_manager = val; + } +} diff --git a/native/src/core/deny/utils.cpp b/native/src/core/deny/utils.cpp index e3e6d74c2..6eefaba78 100644 --- a/native/src/core/deny/utils.cpp +++ b/native/src/core/deny/utils.cpp @@ -222,9 +222,18 @@ static bool ensure_data() { LOGI("denylist: initializing internal data structures\n"); default_new(pkg_to_procs_); - bool res = db_exec("SELECT * FROM denylist", [](db_row &row) -> bool { - add_hide_set(row["package_name"].data(), row["process"].data()); - return true; + bool res = db_exec("SELECT * FROM denylist", [](StringSlice columns, DbValues &data) { + const char *package_name; + const char *process; + for (int i = 0; i < columns.size(); ++i) { + const auto &name = columns[i]; + if (name == "package_name") { + package_name = data.get_text(i); + } else if (name == "process") { + process = data.get_text(i); + } + } + add_hide_set(package_name, process); }); if (!res) goto error; @@ -392,7 +401,7 @@ void initialize_denylist() { if (!denylist_enforced) { db_settings dbs; get_db_settings(dbs, DENYLIST_CONFIG); - if (dbs[DENYLIST_CONFIG]) + if (dbs.denylist) enable_deny(); } } diff --git a/native/src/core/include/db.hpp b/native/src/core/include/db.hpp index 71b70491c..74ad57bdc 100644 --- a/native/src/core/include/db.hpp +++ b/native/src/core/include/db.hpp @@ -6,29 +6,8 @@ #include #include -template -class db_dict { -public: - T& operator [](std::string_view key) { - return data[get_idx(key)]; - } - - const T& operator [](std::string_view key) const { - return data[get_idx(key)]; - } - - T& operator [](int key) { - return data[key]; - } - - const T& operator [](int key) const { - return data[key]; - } - -protected: - T data[N + 1]; - virtual int get_idx(std::string_view key) const = 0; -}; +#include +#include /*************** * DB Settings * @@ -75,11 +54,16 @@ enum { NAMESPACE_MODE_ISOLATE }; -class db_settings : public db_dict { -public: +struct db_settings { + int root_access; + int multiuser_mode; + int mnt_ns; + int bootloop; + bool denylist; + bool zygisk; + db_settings(); -protected: - int get_idx(std::string_view key) const override; + void operator()(StringSlice columns, DbValues &data); }; /************** @@ -93,43 +77,34 @@ enum { SU_MANAGER = 0 }; -class db_strings : public db_dict { -protected: - int get_idx(std::string_view key) const override; +struct db_strings { + std::string su_manager; + + void operator()(StringSlice columns, DbValues &data); }; -/************* - * SU Access * - *************/ - -typedef enum { - QUERY = 0, - DENY = 1, - ALLOW = 2, -} policy_t; - -struct su_access { - policy_t policy; - int log; - int notify; -}; - -#define DEFAULT_SU_ACCESS { QUERY, 1, 1 } -#define SILENT_SU_ACCESS { ALLOW, 0, 0 } -#define NO_SU_ACCESS { DENY, 0, 0 } - /******************** * Public Functions * ********************/ -using db_row = std::map; -using db_row_cb = std::function; -struct owned_fd; +using db_exec_callback = std::function; +using db_bind_callback = std::function; int get_db_settings(db_settings &cfg, int key = -1); int set_db_settings(int key, int value); int get_db_strings(db_strings &str, int key = -1); void rm_db_strings(int key); void exec_sql(owned_fd client); -bool db_exec(const char *sql); -bool db_exec(const char *sql, const db_row_cb &fn); +bool db_exec(const char *sql, db_bind_callback bind_fn = {}, db_exec_callback exec_fn = {}); + +static inline bool db_exec(const char *sql, db_exec_callback exec_fn) { + return db_exec(sql, {}, std::move(exec_fn)); +} + +template +concept DbData = requires(T t, StringSlice s, DbValues &v) { t(s, v); }; + +template +bool db_exec(const char *sql, T &data) { + return db_exec(sql, (db_exec_callback) std::ref(data)); +} diff --git a/native/src/core/include/sqlite.hpp b/native/src/core/include/sqlite.hpp index 4acb56e60..be4cc34f7 100644 --- a/native/src/core/include/sqlite.hpp +++ b/native/src/core/include/sqlite.hpp @@ -15,23 +15,29 @@ struct sqlite3_stmt; extern int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs); extern int (*sqlite3_close)(sqlite3 *db); -extern int (*sqlite3_prepare_v2)(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail); -extern int (*sqlite3_bind_parameter_count)(sqlite3_stmt*); -extern int (*sqlite3_bind_int)(sqlite3_stmt*, int, int); -extern int (*sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -extern int (*sqlite3_column_count)(sqlite3_stmt *pStmt); -extern const char *(*sqlite3_column_name)(sqlite3_stmt*, int N); -extern const char *(*sqlite3_column_text)(sqlite3_stmt*, int iCol); -extern int (*sqlite3_step)(sqlite3_stmt*); -extern int (*sqlite3_finalize)(sqlite3_stmt *pStmt); extern const char *(*sqlite3_errstr)(int); -using StringVec = rust::Vec; +// Transparent wrapper of sqlite3_stmt +struct DbValues { + const char *get_text(int index); + int get_int(int index); + ~DbValues() = delete; +}; + +struct DbStatement { + int bind_text(int index, const char *val); + int bind_text(int index, rust::Str val); + int bind_int64(int index, int64_t val); +}; + using StringSlice = rust::Slice; -using StrSlice = rust::Slice; -using sqlite_row_callback = void(*)(void*, StringSlice, StringSlice); +using sql_bind_callback = void(*)(void*, int, DbStatement&); +using sql_exec_callback = void(*)(void*, StringSlice, DbValues&); #define fn_run_ret(fn, ...) if (int rc = fn(__VA_ARGS__); rc != SQLITE_OK) return rc bool load_sqlite(); -int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback callback, void *v); +sqlite3 *open_and_init_db(); +int sql_exec(sqlite3 *db, rust::Str zSql, + sql_bind_callback bind_cb, void *bind_cookie, + sql_exec_callback exec_cb, void *exec_cookie); diff --git a/native/src/core/package.cpp b/native/src/core/package.cpp index 0a71b4672..2d35b5222 100644 --- a/native/src/core/package.cpp +++ b/native/src/core/package.cpp @@ -197,7 +197,7 @@ int get_manager(int user, string *pkg, bool install) { db_strings str; get_db_strings(str, SU_MANAGER); - string db_pkg(std::move(str[SU_MANAGER])); + string db_pkg(std::move(str.su_manager)); // If database changed, always re-check files if (db_pkg != repackaged_pkg) { diff --git a/native/src/core/sqlite.cpp b/native/src/core/sqlite.cpp index b81fabe62..2d39d96a3 100644 --- a/native/src/core/sqlite.cpp +++ b/native/src/core/sqlite.cpp @@ -9,17 +9,19 @@ using namespace std; int (*sqlite3_open_v2)(const char *filename, sqlite3 **ppDb, int flags, const char *zVfs); int (*sqlite3_close)(sqlite3 *db); -int (*sqlite3_prepare_v2)(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail); -int (*sqlite3_bind_parameter_count)(sqlite3_stmt*); -int (*sqlite3_bind_int)(sqlite3_stmt*, int, int); -int (*sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*)); -int (*sqlite3_column_count)(sqlite3_stmt *pStmt); -const char *(*sqlite3_column_name)(sqlite3_stmt*, int N); -const char *(*sqlite3_column_text)(sqlite3_stmt*, int iCol); -int (*sqlite3_step)(sqlite3_stmt*); -int (*sqlite3_finalize)(sqlite3_stmt *pStmt); const char *(*sqlite3_errstr)(int); +static int (*sqlite3_prepare_v2)(sqlite3 *db, const char *zSql, int nByte, sqlite3_stmt **ppStmt, const char **pzTail); +static int (*sqlite3_bind_parameter_count)(sqlite3_stmt*); +static int (*sqlite3_bind_int64)(sqlite3_stmt*, int, int64_t); +static int (*sqlite3_bind_text)(sqlite3_stmt*,int,const char*,int,void(*)(void*)); +static int (*sqlite3_column_count)(sqlite3_stmt *pStmt); +static const char *(*sqlite3_column_name)(sqlite3_stmt*, int N); +static const char *(*sqlite3_column_text)(sqlite3_stmt*, int iCol); +static int (*sqlite3_column_int)(sqlite3_stmt*, int iCol); +static int (*sqlite3_step)(sqlite3_stmt*); +static int (*sqlite3_finalize)(sqlite3_stmt *pStmt); + // Internal Android linker APIs static void (*android_get_LD_LIBRARY_PATH)(char *buffer, size_t buffer_size); @@ -72,24 +74,28 @@ bool load_sqlite() { DLOAD(sqlite, sqlite3_open_v2); DLOAD(sqlite, sqlite3_close); + DLOAD(sqlite, sqlite3_errstr); DLOAD(sqlite, sqlite3_prepare_v2); DLOAD(sqlite, sqlite3_bind_parameter_count); - DLOAD(sqlite, sqlite3_bind_int); + DLOAD(sqlite, sqlite3_bind_int64); DLOAD(sqlite, sqlite3_bind_text); DLOAD(sqlite, sqlite3_step); DLOAD(sqlite, sqlite3_column_count); DLOAD(sqlite, sqlite3_column_name); DLOAD(sqlite, sqlite3_column_text); + DLOAD(sqlite, sqlite3_column_int); DLOAD(sqlite, sqlite3_finalize); - DLOAD(sqlite, sqlite3_errstr); dl_init = 1; return true; } -int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback callback, void *v) { +using StringVec = rust::Vec; +using sql_exec_callback_real = void(*)(void*, StringSlice, sqlite3_stmt*); +using sql_bind_callback_real = void(*)(void*, int, sqlite3_stmt*); + +int sql_exec(sqlite3 *db, rust::Str zSql, sql_bind_callback bind_cb, void *bind_cookie, sql_exec_callback exec_cb, void *exec_cookie) { const char *sql = zSql.begin(); - auto arg_it = args.begin(); unique_ptr stmt(nullptr, sqlite3_finalize); while (sql != zSql.end()) { @@ -102,9 +108,12 @@ int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback cal } // Step 2: bind arguments - if (int count = sqlite3_bind_parameter_count(stmt.get())) { - for (int i = 1; i <= count && arg_it != args.end(); ++i, ++arg_it) { - fn_run_ret(sqlite3_bind_text, stmt.get(), i, arg_it->data(), arg_it->size(), nullptr); + if (bind_cb) { + if (int count = sqlite3_bind_parameter_count(stmt.get())) { + auto real_cb = reinterpret_cast(bind_cb); + for (int i = 1; i <= count; ++i) { + real_cb(bind_cookie, i, stmt.get()); + } } } @@ -115,7 +124,7 @@ int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback cal int rc = sqlite3_step(stmt.get()); if (rc == SQLITE_DONE) break; if (rc != SQLITE_ROW) return rc; - if (callback == nullptr) continue; + if (exec_cb == nullptr) continue; if (first) { int count = sqlite3_column_count(stmt.get()); for (int i = 0; i < count; ++i) { @@ -123,13 +132,30 @@ int sql_exec(sqlite3 *db, rust::Str zSql, StrSlice args, sqlite_row_callback cal } first = false; } - StringVec data; - for (int i = 0; i < columns.size(); ++i) { - data.emplace_back(sqlite3_column_text(stmt.get(), i)); - } - callback(v, StringSlice(columns), StringSlice(data)); + auto real_cb = reinterpret_cast(exec_cb); + real_cb(exec_cookie, StringSlice(columns), stmt.get()); } } return SQLITE_OK; } + +int DbValues::get_int(int index) { + return sqlite3_column_int(reinterpret_cast(this), index); +} + +const char *DbValues::get_text(int index) { + return sqlite3_column_text(reinterpret_cast(this), index); +} + +int DbStatement::bind_int64(int index, int64_t val) { + return sqlite3_bind_int64(reinterpret_cast(this), index, val); +} + +int DbStatement::bind_text(int index, rust::Str val) { + return sqlite3_bind_text(reinterpret_cast(this), index, val.data(), val.size(), nullptr); +} + +int DbStatement::bind_text(int index, const char *val) { + return sqlite3_bind_text(reinterpret_cast(this), index, val, -1, nullptr); +} diff --git a/native/src/core/su/su.hpp b/native/src/core/su/su.hpp index 68485c286..1cd92d60a 100644 --- a/native/src/core/su/su.hpp +++ b/native/src/core/su/su.hpp @@ -14,6 +14,32 @@ #define ATTY_OUT (1 << 1) #define ATTY_ERR (1 << 2) +typedef enum { + QUERY = 0, + DENY = 1, + ALLOW = 2, +} policy_t; + +struct su_access { + policy_t policy; + int log; + int notify; + + su_access() : policy(QUERY), log(1), notify(1) {} + + void operator()(StringSlice columns, DbValues &data); + void silent_deny() { + policy = DENY; + log = 0; + notify = 0; + } + void silent_allow() { + policy = ALLOW; + log = 0; + notify = 0; + } +}; + class su_info { public: // Unique key diff --git a/native/src/core/su/su_daemon.cpp b/native/src/core/su/su_daemon.cpp index 1031ca87a..0913943f3 100644 --- a/native/src/core/su/su_daemon.cpp +++ b/native/src/core/su/su_daemon.cpp @@ -18,8 +18,7 @@ static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; static shared_ptr cached; su_info::su_info(int uid) : -uid(uid), eval_uid(-1), access(DEFAULT_SU_ACCESS), mgr_uid(-1), -timestamp(0), _lock(PTHREAD_MUTEX_INITIALIZER) {} +uid(uid), eval_uid(-1), mgr_uid(-1), timestamp(0), _lock(PTHREAD_MUTEX_INITIALIZER) {} su_info::~su_info() { pthread_mutex_destroy(&_lock); @@ -42,16 +41,30 @@ void su_info::refresh() { timestamp = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L; } +void su_access::operator()(StringSlice columns, DbValues &data) { + for (int i = 0; i < columns.size(); ++i) { + const auto &name = columns[i]; + if (name == "policy") { + policy = (policy_t) data.get_int(i); + } else if (name == "logging") { + log = data.get_int(i); + } else if (name == "notification") { + notify = data.get_int(i); + } + } + LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n", policy, log, notify); +} + void su_info::check_db() { eval_uid = uid; get_db_settings(cfg); // Check multiuser settings - switch (cfg[SU_MULTIUSER_MODE]) { + switch (cfg.multiuser_mode) { case MULTIUSER_MODE_OWNER_ONLY: if (to_user_id(uid) != 0) { eval_uid = -1; - access = NO_SU_ACCESS; + access.silent_deny(); } break; case MULTIUSER_MODE_OWNER_MANAGED: @@ -67,15 +80,7 @@ void su_info::check_db() { ssprintf(query, sizeof(query), "SELECT policy, logging, notification FROM policies " "WHERE uid=%d AND (until=0 OR until>%li)", eval_uid, time(nullptr)); - bool res = db_exec(query, [&](db_row &row) -> bool { - access.policy = (policy_t) parse_int(row["policy"]); - access.log = parse_int(row["logging"]); - access.notify = parse_int(row["notification"]); - LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n", - access.policy, access.log, access.notify); - return true; - }); - if (!res) + if (!db_exec(query, access)) return; } @@ -93,7 +98,7 @@ bool uid_granted_root(int uid) { get_db_settings(cfg); // Check user root access settings - switch (cfg[ROOT_ACCESS]) { + switch (cfg.root_access) { case ROOT_ACCESS_DISABLED: return false; case ROOT_ACCESS_APPS_ONLY: @@ -109,7 +114,7 @@ bool uid_granted_root(int uid) { } // Check multiuser settings - switch (cfg[SU_MULTIUSER_MODE]) { + switch (cfg.multiuser_mode) { case MULTIUSER_MODE_OWNER_ONLY: if (to_user_id(uid) != 0) return false; @@ -122,28 +127,31 @@ bool uid_granted_root(int uid) { break; } - bool granted = false; - char query[256]; ssprintf(query, sizeof(query), "SELECT policy FROM policies WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr)); - bool res = db_exec(query, [&](db_row &row) -> bool { - granted = parse_int(row["policy"]) == ALLOW; - return true; - }); - if (!res) + su_access access; + access.policy = QUERY; + if (!db_exec(query, access)) return false; - - return granted; + return access.policy == ALLOW; } +struct policy_uid_list : public vector { + void operator()(StringSlice, DbValues &data) { + push_back(data.get_int(0)); + } +}; + void prune_su_access() { cached.reset(); + policy_uid_list uids; + if (!db_exec("SELECT uid FROM policies", uids)) + return; vector app_no_list = get_app_no_list(); vector rm_uids; - bool res = db_exec("SELECT uid FROM policies", [&](db_row &row) -> bool { - int uid = parse_int(row["uid"]); + for (int uid : uids) { int app_id = to_app_id(uid); if (app_id >= AID_APP_START && app_id <= AID_APP_END) { int app_no = app_id - AID_APP_START; @@ -152,11 +160,7 @@ void prune_su_access() { rm_uids.push_back(uid); } } - return true; - }); - if (!res) - return; - + } for (int uid : rm_uids) { char query[256]; ssprintf(query, sizeof(query), "DELETE FROM policies WHERE uid == %d", uid); @@ -167,7 +171,7 @@ void prune_su_access() { static shared_ptr get_su_info(unsigned uid) { if (uid == AID_ROOT) { auto info = make_shared(uid); - info->access = SILENT_SU_ACCESS; + info->access.silent_allow(); return info; } @@ -188,26 +192,26 @@ static shared_ptr get_su_info(unsigned uid) { // If it's the manager, allow it silently if (to_app_id(info->uid) == to_app_id(info->mgr_uid)) { - info->access = SILENT_SU_ACCESS; + info->access.silent_allow(); return info; } // Check su access settings - switch (info->cfg[ROOT_ACCESS]) { + switch (info->cfg.root_access) { case ROOT_ACCESS_DISABLED: LOGW("Root access is disabled!\n"); - info->access = NO_SU_ACCESS; + info->access.silent_deny(); break; case ROOT_ACCESS_ADB_ONLY: if (info->uid != AID_SHELL) { LOGW("Root access limited to ADB only!\n"); - info->access = NO_SU_ACCESS; + info->access.silent_deny(); } break; case ROOT_ACCESS_APPS_ONLY: if (info->uid == AID_SHELL) { LOGW("Root access is disabled for ADB!\n"); - info->access = NO_SU_ACCESS; + info->access.silent_deny(); } break; case ROOT_ACCESS_APPS_AND_ADB: @@ -220,7 +224,7 @@ static shared_ptr get_su_info(unsigned uid) { // If still not determined, check if manager exists if (info->mgr_uid < 0) { - info->access = NO_SU_ACCESS; + info->access.silent_deny(); return info; } } @@ -396,10 +400,10 @@ void su_daemon_handler(int client, const sock_cred *cred) { if (ctx.req.target == -1) ctx.req.target = ctx.pid; else if (ctx.req.target == 0) - ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_GLOBAL; - else if (ctx.info->cfg[SU_MNT_NS] == NAMESPACE_MODE_GLOBAL) - ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER; - switch (ctx.info->cfg[SU_MNT_NS]) { + ctx.info->cfg.mnt_ns = NAMESPACE_MODE_GLOBAL; + else if (ctx.info->cfg.mnt_ns == NAMESPACE_MODE_GLOBAL) + ctx.info->cfg.mnt_ns = NAMESPACE_MODE_REQUESTER; + switch (ctx.info->cfg.mnt_ns) { case NAMESPACE_MODE_GLOBAL: LOGD("su: use global namespace\n"); break;