diff --git a/native/jni/core/scripting.cpp b/native/jni/core/scripting.cpp index fe7b8872d..addbaab97 100644 --- a/native/jni/core/scripting.cpp +++ b/native/jni/core/scripting.cpp @@ -72,7 +72,7 @@ void exec_module_script(const char *stage, const vector &module_list) { } static const char migrate_script[] = -"IMG=%s;" +"IMG=/data/adb/tmp.img;" "MNT=/dev/img_mnt;" "e2fsck -yf $IMG;" "mkdir -p $MNT;" @@ -91,27 +91,54 @@ static const char migrate_script[] = void migrate_img(const char *img) { LOGI("* Migrating %s\n", img); exec_t exec { .pre_exec = set_path }; - char cmds[sizeof(migrate_script) + 32]; - sprintf(cmds, migrate_script, img); - exec_command_sync(exec, "/system/bin/sh", "-c", cmds); + rename(img, "/data/adb/tmp.img"); + exec_command_sync(exec, "/system/bin/sh", "-c", migrate_script); } static const char install_script[] = +"APK=%s;" "while true; do" -" OUT=`pm install -r $APK`;" +" OUT=`pm install -r $APK 2>&1`;" " log -t Magisk \"apk_install: $OUT\";" -" if echo \"$OUT\" | grep -q 'Error:'; then" +" if echo \"$OUT\" | grep -qE \"Can't|Error:\"; then" " sleep 5;" " continue;" " fi;" " break;" -"done"; +"done;" +"rm -f $APK"; void install_apk(const char *apk) { setfilecon(apk, "u:object_r:" SEPOL_FILE_DOMAIN ":s0"); LOGI("apk_install: %s\n", apk); exec_t exec { .pre_exec = set_mirror_path }; char cmds[sizeof(install_script) + 4096]; - sprintf(cmds, "APK=%s;%s;rm -f $APK", apk, install_script); - exec_command_sync(exec, "/system/bin/sh", "-c", cmds); + sprintf(cmds, install_script, apk); + exec_command_sync(exec, MIRRDIR "/system/bin/sh", "-c", cmds); +} + +static const char reinstall_script[] = +"PKG=%s;" +"while true; do" +" OUT=`pm path $PKG 2>&1`;" +" [ -z $OUT ] && exit 1;" +" if echo \"$OUT\" | grep -qE \"Can't|Error:\"; then" +" sleep 5;" +" continue;" +" fi;" +" APK=`echo $OUT | cut -d':' -f2`;" +" log -t Magisk \"apk_install: $APK\";" +" OUT=`pm install -r $APK`;" +" [ $? -eq 0 ] || exit 1;" +" log -t Magisk \"apk_install: $OUT\";" +" break;" +"done;" +"exit 0"; + +// Reinstall system apps to data +int reinstall_apk(const char *pkg) { + exec_t exec { .pre_exec = set_mirror_path }; + char cmds[sizeof(reinstall_script) + 256]; + sprintf(cmds, reinstall_script, pkg); + return exec_command_sync(exec, MIRRDIR "/system/bin/sh", "-c", cmds); } diff --git a/native/jni/include/daemon.h b/native/jni/include/daemon.h index 85df78c9b..abd9d2652 100644 --- a/native/jni/include/daemon.h +++ b/native/jni/include/daemon.h @@ -72,6 +72,7 @@ void exec_common_script(const char *stage); void exec_module_script(const char *stage, const std::vector &module_list); void migrate_img(const char *img); void install_apk(const char *apk); +int reinstall_apk(const char *pkg); /************** * MagiskHide * diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index 4082fc9ab..d36b5f142 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -188,10 +188,12 @@ int add_list(const char *pkg) { LOGI("hide_list add: [%s]\n", pkg); // Critical region - pthread_mutex_lock(&list_lock); - hide_list.emplace_back(pkg); - int uid = add_pkg_uid(pkg); - pthread_mutex_unlock(&list_lock); + int uid; + { + MutexGuard lock(list_lock); + hide_list.emplace_back(pkg); + uid = add_pkg_uid(pkg); + } kill_process(uid); return DAEMON_SUCCESS; @@ -207,36 +209,33 @@ int add_list(int client) { static int rm_list(const char *pkg) { // Critical region - bool remove = false; - pthread_mutex_lock(&list_lock); - for (auto it = hide_list.begin(); it != hide_list.end(); ++it) { - if (*it == pkg) { - remove = true; - LOGI("hide_list rm: [%s]\n", pkg); - hide_list.erase(it); - break; + { + MutexGuard lock(list_lock); + bool remove = false; + for (auto it = hide_list.begin(); it != hide_list.end(); ++it) { + if (*it == pkg) { + remove = true; + LOGI("hide_list rm: [%s]\n", pkg); + hide_list.erase(it); + break; + } } + if (!remove) + return HIDE_ITEM_NOT_EXIST; } - if (remove) - refresh_uid(); - pthread_mutex_unlock(&list_lock); - - if (remove) { - char sql[4096]; - snprintf(sql, sizeof(sql), "DELETE FROM hidelist WHERE process='%s'", pkg); - char *err = db_exec(sql); - db_err(err); - return DAEMON_SUCCESS; - } else { - return HIDE_ITEM_NOT_EXIST; - } + char sql[4096]; + snprintf(sql, sizeof(sql), "DELETE FROM hidelist WHERE process='%s'", pkg); + char *err = db_exec(sql); + db_err(err); + return DAEMON_SUCCESS; } int rm_list(int client) { char *pkg = read_string(client); int ret = rm_list(pkg); free(pkg); - update_inotify_mask(); + if (ret == DAEMON_SUCCESS) + update_inotify_mask(true); return ret; } diff --git a/native/jni/magiskhide/magiskhide.h b/native/jni/magiskhide/magiskhide.h index 1d0a638da..8699c419a 100644 --- a/native/jni/magiskhide/magiskhide.h +++ b/native/jni/magiskhide/magiskhide.h @@ -26,7 +26,7 @@ int rm_list(int client); void ls_list(int client); // Update APK list for inotify -void update_inotify_mask(); +void update_inotify_mask(bool refresh = false); // Process monitor void proc_monitor(); diff --git a/native/jni/magiskhide/proc_monitor.cpp b/native/jni/magiskhide/proc_monitor.cpp index b89fe3972..599c61d3c 100644 --- a/native/jni/magiskhide/proc_monitor.cpp +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -205,6 +205,8 @@ static char *append_path(char *eof, const char *name) { #define DATA_APP "/data/app" static int new_inotify; +static int data_app_wd; +static vector app_in_data; static void find_apks(char *path, char *eof) { DIR *dir = opendir(path); if (dir == nullptr) @@ -225,11 +227,12 @@ static void find_apks(char *path, char *eof) { if ((dash = strchr(path, '-')) == nullptr) continue; *dash = '\0'; - for (auto &s : hide_list) { - if (s == path + sizeof(DATA_APP)) { + for (int i = 0; i < hide_list.size(); ++i) { + if (hide_list[i] == path + sizeof(DATA_APP)) { *dash = '-'; append_path(eof, entry->d_name); xinotify_add_watch(new_inotify, path, IN_OPEN | IN_DELETE); + app_in_data[i] = true; break; } } @@ -241,7 +244,7 @@ static void find_apks(char *path, char *eof) { } // Iterate through /data/app and search all .apk files -void update_inotify_mask() { +void update_inotify_mask(bool refresh) { char buf[4096]; new_inotify = inotify_init(); @@ -252,12 +255,41 @@ void update_inotify_mask() { LOGI("proc_monitor: Updating inotify list\n"); strcpy(buf, DATA_APP); - pthread_mutex_lock(&list_lock); - find_apks(buf, buf + sizeof(DATA_APP) - 1); - pthread_mutex_unlock(&list_lock); + app_in_data.clear(); + bool reinstall = false; + { + MutexGuard lock(list_lock); + app_in_data.resize(hide_list.size(), false); + find_apks(buf, buf + sizeof(DATA_APP) - 1); + // Stop monitoring /data/app + if (inotify_fd >= 0) + inotify_rm_watch(inotify_fd, data_app_wd); + // All apps on the hide list should be installed in data + auto it = hide_list.begin(); + for (bool in_data : app_in_data) { + if (!in_data) { + if (reinstall_apk(it->c_str()) != 0) { + // Reinstallation failed, remove from hide list + hide_list.erase(it); + refresh = true; + continue; + } + reinstall = true; + } + it++; + } + if (refresh && !reinstall) + refresh_uid(); + } + if (reinstall) { + // Rerun detection + close(new_inotify); + update_inotify_mask(refresh); + return; + } // Add /data/app itself to the watch list to detect app (un)installations/updates - xinotify_add_watch(new_inotify, DATA_APP, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE); + data_app_wd = xinotify_add_watch(new_inotify, DATA_APP, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE); int tmp = inotify_fd; inotify_fd = new_inotify; @@ -289,15 +321,11 @@ void proc_monitor() { if (event->mask & IN_OPEN) { // Since we're just watching files, // extracting file name is not possible from querying event - pthread_mutex_lock(&list_lock); + MutexGuard lock(list_lock); crawl_procfs(process_pid); - pthread_mutex_unlock(&list_lock); - } else { + } else if (!(event->mask & IN_IGNORED)) { LOGI("proc_monitor: inotify: /data/app change detected\n"); - pthread_mutex_lock(&list_lock); - refresh_uid(); - pthread_mutex_unlock(&list_lock); - update_inotify_mask(); + update_inotify_mask(true); break; } diff --git a/native/jni/utils/include/utils.h b/native/jni/utils/include/utils.h index 22bac5886..181f51022 100644 --- a/native/jni/utils/include/utils.h +++ b/native/jni/utils/include/utils.h @@ -150,6 +150,24 @@ std::vector file_to_vector(const char *filename); // misc.cpp +class MutexGuard { +public: + explicit MutexGuard(pthread_mutex_t &m): mutex(&m) { + pthread_mutex_lock(mutex); + } + + explicit MutexGuard(pthread_mutex_t *m): mutex(m) { + pthread_mutex_lock(mutex); + } + + ~MutexGuard() { + pthread_mutex_unlock(mutex); + } + +private: + pthread_mutex_t *mutex; +}; + int new_daemon_thread(void *(*start_routine) (void *), void *arg = nullptr, const pthread_attr_t *attr = nullptr);