Simplify get manager app info logic

This commit is contained in:
topjohnwu 2021-09-17 02:07:32 -07:00
parent 82f303e1c6
commit 7b25e74418
7 changed files with 46 additions and 45 deletions

View File

@ -106,9 +106,10 @@ static bool magisk_env() {
LOGI("* Initializing Magisk environment\n"); LOGI("* Initializing Magisk environment\n");
string pkg; string pkg;
check_manager(&pkg); get_manager(&pkg);
sprintf(buf, "%s/0/%s/install", APP_DATA_DIR, pkg.data()); sprintf(buf, "%s/0/%s/install", APP_DATA_DIR,
pkg.empty() ? "xxx" /* Ensure non-exist path */ : pkg.data());
// Alternative binaries paths // Alternative binaries paths
const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", buf }; const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", buf };
@ -354,7 +355,7 @@ void boot_complete(int client) {
if (access(SECURE_DIR, F_OK) != 0) if (access(SECURE_DIR, F_OK) != 0)
xmkdir(SECURE_DIR, 0700); xmkdir(SECURE_DIR, 0700);
if (!check_manager()) { if (!get_manager()) {
if (access(MANAGERAPK, F_OK) == 0) { if (access(MANAGERAPK, F_OK) == 0) {
// Only try to install APK when no manager is installed // Only try to install APK when no manager is installed
// Magisk Manager should be upgraded by itself, not through recovery installs // Magisk Manager should be upgraded by itself, not through recovery installs

View File

@ -341,41 +341,39 @@ int get_uid_policy(su_access &su, int uid) {
return 0; return 0;
} }
bool check_manager(string *pkg) { bool get_manager(int user_id, std::string *pkg, struct stat *st) {
db_strings str; db_strings str;
get_db_strings(str, SU_MANAGER); get_db_strings(str, SU_MANAGER);
bool ret = validate_manager(str[SU_MANAGER], 0, nullptr);
if (pkg) {
if (ret)
pkg->swap(str[SU_MANAGER]);
else
*pkg = "xxx"; /* Make sure the return pkg can never exist */
}
return ret;
}
bool validate_manager(string &pkg, int userid, struct stat *st) {
struct stat tmp_st;
if (st == nullptr)
st = &tmp_st;
// Prefer DE storage
char app_path[128]; char app_path[128];
sprintf(app_path, "%s/%d/%s", APP_DATA_DIR, userid, pkg.data());
if (pkg.empty() || stat(app_path, st)) { if (!str[SU_MANAGER].empty()) {
// Check the official package name // App is repackaged
sprintf(app_path, "%s/%d/" JAVA_PACKAGE_NAME, APP_DATA_DIR, userid); sprintf(app_path, "%s/%d/%s", APP_DATA_DIR, user_id, str[SU_MANAGER].data());
if (stat(app_path, st)) { if (stat(app_path, st) == 0) {
LOGE("su: cannot find manager\n"); if (pkg)
memset(st, 0, sizeof(*st)); pkg->swap(str[SU_MANAGER]);
pkg.clear(); return true;
return false;
} else {
// Switch to official package if exists
pkg = JAVA_PACKAGE_NAME;
} }
} }
return true;
// Check the official package name
sprintf(app_path, "%s/%d/" JAVA_PACKAGE_NAME, APP_DATA_DIR, user_id);
if (stat(app_path, st) == 0) {
if (pkg)
*pkg = JAVA_PACKAGE_NAME;
return true;
} else {
LOGE("su: cannot find manager\n");
memset(st, 0, sizeof(*st));
if (pkg)
pkg->clear();
return false;
}
}
bool get_manager(string *pkg) {
struct stat st;
return get_manager(0, pkg, &st);
} }
void exec_sql(int client) { void exec_sql(int client) {

View File

@ -126,8 +126,8 @@ using db_row_cb = std::function<bool(db_row&)>;
int get_db_settings(db_settings &cfg, int key = -1); int get_db_settings(db_settings &cfg, int key = -1);
int get_db_strings(db_strings &str, int key = -1); int get_db_strings(db_strings &str, int key = -1);
int get_uid_policy(su_access &su, int uid); int get_uid_policy(su_access &su, int uid);
bool check_manager(std::string *pkg = nullptr); bool get_manager(int user_id, std::string *pkg, struct stat *st);
bool validate_manager(std::string &pkg, int userid, struct stat *st); bool get_manager(std::string *pkg = nullptr);
void exec_sql(int client); void exec_sql(int client);
char *db_exec(const char *sql); char *db_exec(const char *sql);
char *db_exec(const char *sql, const db_row_cb &fn); char *db_exec(const char *sql, const db_row_cb &fn);

View File

@ -106,7 +106,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
// First try content provider call method // First try content provider call method
if (mode >= CONTENT_PROVIDER) { if (mode >= CONTENT_PROVIDER) {
sprintf(target, "content://%s.provider", info->str[SU_MANAGER].data()); sprintf(target, "content://%s.provider", info->mgr_pkg.data());
vector<const char *> args{ CALL_PROVIDER }; vector<const char *> args{ CALL_PROVIDER };
for (auto &e : data) { for (auto &e : data) {
e.add_bind(args); e.add_bind(args);
@ -137,7 +137,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
if (mode >= PKG_ACTIVITY) { if (mode >= PKG_ACTIVITY) {
// Then try start activity without component name // Then try start activity without component name
strcpy(target, info->str[SU_MANAGER].data()); strcpy(target, info->mgr_pkg.data());
exec_command_sync(exec); exec_command_sync(exec);
if (check_no_error(exec.fd)) if (check_no_error(exec.fd))
return; return;
@ -145,7 +145,7 @@ static void exec_cmd(const char *action, vector<Extra> &data,
// Finally, fallback to start activity with component name // Finally, fallback to start activity with component name
args[4] = "-n"; args[4] = "-n";
sprintf(target, "%s/.ui.surequest.SuRequestActivity", info->str[SU_MANAGER].data()); sprintf(target, "%s/.ui.surequest.SuRequestActivity", info->mgr_pkg.data());
exec.fd = -2; exec.fd = -2;
exec.fork = fork_dont_care; exec.fork = fork_dont_care;
exec_command(exec); exec_command(exec);

View File

@ -20,8 +20,8 @@ public:
/* These should be guarded with internal lock */ /* These should be guarded with internal lock */
db_settings cfg; db_settings cfg;
db_strings str;
su_access access; su_access access;
std::string mgr_pkg;
struct stat mgr_st; struct stat mgr_st;
/* This should be guarded with global cache lock */ /* This should be guarded with global cache lock */

View File

@ -47,18 +47,17 @@ void su_info::refresh() {
static void database_check(const shared_ptr<su_info> &info) { static void database_check(const shared_ptr<su_info> &info) {
int uid = info->uid; int uid = info->uid;
get_db_settings(info->cfg); get_db_settings(info->cfg);
get_db_strings(info->str);
// Check multiuser settings // Check multiuser settings
switch (info->cfg[SU_MULTIUSER_MODE]) { switch (info->cfg[SU_MULTIUSER_MODE]) {
case MULTIUSER_MODE_OWNER_ONLY: case MULTIUSER_MODE_OWNER_ONLY:
if (info->uid / 100000) { if (to_user_id(uid) != 0) {
uid = -1; uid = -1;
info->access = NO_SU_ACCESS; info->access = NO_SU_ACCESS;
} }
break; break;
case MULTIUSER_MODE_OWNER_MANAGED: case MULTIUSER_MODE_OWNER_MANAGED:
uid = info->uid % 100000; uid = to_app_id(uid);
break; break;
case MULTIUSER_MODE_USER: case MULTIUSER_MODE_USER:
default: default:
@ -70,7 +69,7 @@ static void database_check(const shared_ptr<su_info> &info) {
// We need to check our manager // We need to check our manager
if (info->access.log || info->access.notify) if (info->access.log || info->access.notify)
validate_manager(info->str[SU_MANAGER], uid / 100000, &info->mgr_st); get_manager(to_user_id(uid), &info->mgr_pkg, &info->mgr_st);
} }
static shared_ptr<su_info> get_su_info(unsigned uid) { static shared_ptr<su_info> get_su_info(unsigned uid) {
@ -93,7 +92,7 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
database_check(info); database_check(info);
// If it's root or the manager, allow it silently // If it's root or the manager, allow it silently
if (info->uid == UID_ROOT || (info->uid % 100000) == (info->mgr_st.st_uid % 100000)) { if (info->uid == UID_ROOT || to_app_id(info->uid) == to_app_id(info->mgr_st.st_uid)) {
info->access = SILENT_SU_ACCESS; info->access = SILENT_SU_ACCESS;
return info; return info;
} }
@ -125,7 +124,7 @@ static shared_ptr<su_info> get_su_info(unsigned uid) {
return info; return info;
// If still not determined, check if manager exists // If still not determined, check if manager exists
if (info->str[SU_MANAGER].empty()) { if (info->mgr_pkg.empty()) {
info->access = NO_SU_ACCESS; info->access = NO_SU_ACCESS;
return info; return info;
} }

View File

@ -12,6 +12,9 @@
clazz(const clazz &) = delete; \ clazz(const clazz &) = delete; \
clazz(clazz &&) = delete; clazz(clazz &&) = delete;
#define to_app_id(uid) (uid % 100000)
#define to_user_id(uid) (uid / 100000)
class mutex_guard { class mutex_guard {
DISALLOW_COPY_AND_MOVE(mutex_guard) DISALLOW_COPY_AND_MOVE(mutex_guard)
public: public: