From 99db0672b45f6c8fc6ef1adfba0bb16fa950d3dc Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 14 Feb 2019 04:08:05 -0500 Subject: [PATCH] Minor MagiskHide adjustments - Fail fast on unsupported systems - Show proper fail message on unsupported systems - inotify_fd shall be swapped out before closing to prevent the proc_monitor thread to read from incomplete inotify fd --- native/jni/magiskhide/hide_utils.cpp | 5 ++- native/jni/magiskhide/magiskhide.cpp | 21 ++++++------ native/jni/magiskhide/magiskhide.h | 3 +- native/jni/magiskhide/proc_monitor.cpp | 47 ++++++++++---------------- 4 files changed, 34 insertions(+), 42 deletions(-) diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index b75b1f3ac..9b8a7a587 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -297,7 +297,7 @@ static void set_hide_config() { } static inline void launch_err(int client, int code = DAEMON_ERROR) { - if (code == DAEMON_ERROR) + if (code != HIDE_IS_ENABLED) hide_enabled = false; if (client >= 0) { write_int(client, code); @@ -315,6 +315,9 @@ void launch_magiskhide(int client) { if (hide_enabled) launch_err(client, HIDE_IS_ENABLED); + if (access("/proc/1/ns/mnt", F_OK) != 0) + launch_err(client, HIDE_NO_NS); + hide_enabled = true; set_hide_config(); LOGI("* Starting MagiskHide\n"); diff --git a/native/jni/magiskhide/magiskhide.cpp b/native/jni/magiskhide/magiskhide.cpp index 5dfcd9d00..4a7187dfd 100644 --- a/native/jni/magiskhide/magiskhide.cpp +++ b/native/jni/magiskhide/magiskhide.cpp @@ -20,16 +20,12 @@ bool hide_enabled = false; FULL_VER(MagiskHide) "\n\n" "Usage: %s [--option [arguments...] ]\n\n" "Options:\n" - " --status Return the status of MagiskHide\n" - " --enable Start magiskhide\n" - " --disable Stop magiskhide\n" - " --add TARGET Add TARGET to the hide list\n" - " --rm TARGET Remove TARGET from the hide list\n" - " --ls Print out the current hide list\n" - "\n" - "TARGET can be either a package name or a specific component name\n" - "If TARGET is a package name, all components of the app will be targeted\n" - "A component name is composed of /\n" + " --status Return the status of magiskhide\n" + " --enable Start magiskhide\n" + " --disable Stop magiskhide\n" + " --add PKG Add PKG to the hide list\n" + " --rm PKG Remove PKG from the hide list\n" + " --ls List the current hide list\n" , arg0); exit(1); } @@ -122,6 +118,9 @@ int magiskhide_main(int argc, char *argv[]) { case HIDE_ITEM_NOT_EXIST: fprintf(stderr, "[%s] does not exist in hide list\n", argv[2]); break; + case HIDE_NO_NS: + fprintf(stderr, "Your kernel doesn't support mount namespace\n"); + break; /* Errors */ case ROOT_REQUIRED: @@ -129,7 +128,7 @@ int magiskhide_main(int argc, char *argv[]) { break; case DAEMON_ERROR: default: - fprintf(stderr, "Error occured in daemon...\n"); + fprintf(stderr, "Daemon error\n"); return DAEMON_ERROR; } diff --git a/native/jni/magiskhide/magiskhide.h b/native/jni/magiskhide/magiskhide.h index 93caf3ed3..1d0a638da 100644 --- a/native/jni/magiskhide/magiskhide.h +++ b/native/jni/magiskhide/magiskhide.h @@ -68,7 +68,8 @@ enum { HIDE_IS_ENABLED = DAEMON_LAST, HIDE_NOT_ENABLED, HIDE_ITEM_EXIST, - HIDE_ITEM_NOT_EXIST + HIDE_ITEM_NOT_EXIST, + HIDE_NO_NS }; #endif diff --git a/native/jni/magiskhide/proc_monitor.cpp b/native/jni/magiskhide/proc_monitor.cpp index 7ca4f523e..f87c619a8 100644 --- a/native/jni/magiskhide/proc_monitor.cpp +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -33,10 +33,6 @@ extern char *system_block, *vendor_block, *data_block; static int inotify_fd = -1; -#define EVENT_SIZE sizeof(struct inotify_event) -#define EVENT_BUF_LEN (1024 * (EVENT_SIZE + 16)) -#define __ALIGN_EVENT __attribute__ ((aligned(__alignof__(struct inotify_event)))) - // Workaround for the lack of pthread_cancel static void term_thread(int) { LOGD("proc_monitor: running cleanup\n"); @@ -208,7 +204,7 @@ static char *append_path(char *eof, const char *name) { } #define DATA_APP "/data/app" - +static int new_inotify; static void find_apks(char *path, char *eof) { DIR *dir = opendir(path); if (dir == nullptr) @@ -231,7 +227,7 @@ static void find_apks(char *path, char *eof) { if (s == path + sizeof(DATA_APP)) { *dash = '-'; append_path(eof, entry->d_name); - xinotify_add_watch(inotify_fd, path, IN_OPEN | IN_DELETE); + xinotify_add_watch(new_inotify, path, IN_OPEN | IN_DELETE); *eof = '\0'; break; } @@ -247,23 +243,27 @@ static void find_apks(char *path, char *eof) { void update_inotify_mask() { char buf[4096]; - if (inotify_fd >= 0) - close(inotify_fd); - - inotify_fd = inotify_init(); - if (inotify_fd < 0) { + new_inotify = inotify_init(); + if (new_inotify < 0) { LOGE("proc_monitor: Cannot initialize inotify: %s\n", strerror(errno)); term_thread(TERM_THREAD); } - LOGI("proc_monitor: Updating APK list\n"); + 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); // Add /data/app itself to the watch list to detect app (un)installations/updates - xinotify_add_watch(inotify_fd, DATA_APP, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE); + xinotify_add_watch(new_inotify, DATA_APP, IN_CLOSE_WRITE | IN_MOVED_TO | IN_DELETE); + + if (inotify_fd >= 0) { + // Swap and close old fd + int tmp = inotify_fd; + inotify_fd = new_inotify; + close(tmp); + } } void proc_monitor() { @@ -278,25 +278,13 @@ void proc_monitor() { act.sa_handler = term_thread; sigaction(TERM_THREAD, &act, nullptr); - if (access("/proc/1/ns/mnt", F_OK) != 0) { - LOGE("proc_monitor: Your kernel doesn't support mount namespace :(\n"); - term_thread(TERM_THREAD); - } - // Read inotify events struct inotify_event *event; ssize_t len; char *p; - char buffer[EVENT_BUF_LEN] __ALIGN_EVENT; - for (;;) { - len = read(inotify_fd, buffer, EVENT_BUF_LEN); - if (len == -1) { - PLOGE("proc_monitor: read inotify"); - sleep(1); - continue; - } - - for (p = buffer; p < buffer + len; ) { + char buf[4096]; + while ((len = read(inotify_fd, buf, sizeof(buf))) >= 0) { + for (p = buf; p < buf + len; ) { event = (struct inotify_event *)p; if (event->mask & IN_OPEN) { @@ -314,7 +302,8 @@ void proc_monitor() { break; } - p += EVENT_SIZE + event->len; + p += sizeof(*event) + event->len; } } + PLOGE("proc_monitor: read inotify"); }