Auto reinstall system apps on hide list
Since we are parsing through /data/app/ to find target APKs for monitoring, system apps will not be covered in this case. Automatically reinstall system apps as if they received an update and refresh the monitor target after it's done. As a bonus, use RAII idioms for locking pthread_mutex_t.
This commit is contained in:
parent
19ee189468
commit
f4f2274c60
@ -72,7 +72,7 @@ void exec_module_script(const char *stage, const vector<string> &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);
|
||||
}
|
||||
|
@ -72,6 +72,7 @@ void exec_common_script(const char *stage);
|
||||
void exec_module_script(const char *stage, const std::vector<std::string> &module_list);
|
||||
void migrate_img(const char *img);
|
||||
void install_apk(const char *apk);
|
||||
int reinstall_apk(const char *pkg);
|
||||
|
||||
/**************
|
||||
* MagiskHide *
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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();
|
||||
|
@ -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<bool> 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;
|
||||
}
|
||||
|
||||
|
@ -150,6 +150,24 @@ std::vector<std::string> 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);
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user