From 27c688252dab56b55b9a1c8a22f103659de72508 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 1 Nov 2018 13:23:12 -0400 Subject: [PATCH] Store hidelist in magisk database --- native/jni/Android.mk | 6 +- native/jni/daemon/db.c | 12 +- native/jni/include/daemon.h | 8 + native/jni/include/db.h | 12 +- native/jni/include/magisk.h | 9 +- native/jni/include/resetprop.h | 8 + .../{hide_utils.c => hide_utils.cpp} | 185 +++++++++--------- .../{magiskhide.c => magiskhide.cpp} | 22 +-- native/jni/magiskhide/magiskhide.h | 7 +- .../{proc_monitor.c => proc_monitor.cpp} | 56 +++--- native/jni/utils/Android.mk | 1 + native/jni/utils/include/utils.hpp | 6 + native/jni/utils/utils.cpp | 25 +++ 13 files changed, 209 insertions(+), 148 deletions(-) rename native/jni/magiskhide/{hide_utils.c => hide_utils.cpp} (58%) rename native/jni/magiskhide/{magiskhide.c => magiskhide.cpp} (91%) rename native/jni/magiskhide/{proc_monitor.c => proc_monitor.cpp} (78%) create mode 100644 native/jni/utils/include/utils.hpp create mode 100644 native/jni/utils/utils.cpp diff --git a/native/jni/Android.mk b/native/jni/Android.mk index e008ab1fe..b079aa82b 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -40,9 +40,9 @@ LOCAL_SRC_FILES := \ daemon/bootstages.c \ daemon/socket.c \ daemon/db.c \ - magiskhide/magiskhide.c \ - magiskhide/proc_monitor.c \ - magiskhide/hide_utils.c \ + magiskhide/magiskhide.cpp \ + magiskhide/proc_monitor.cpp \ + magiskhide/hide_utils.cpp \ resetprop/persist_properties.c \ resetprop/resetprop.c \ resetprop/system_property_api.cpp \ diff --git a/native/jni/daemon/db.c b/native/jni/daemon/db.c index 9b7caebff..a2101591a 100644 --- a/native/jni/daemon/db.c +++ b/native/jni/daemon/db.c @@ -8,7 +8,7 @@ #include "magisk.h" #include "db.h" -#define DB_VERSION 6 +#define DB_VERSION 7 static int ver_cb(void *v, int col_num, char **data, char **col_name) { *((int *) v) = atoi(data[0]); @@ -79,6 +79,16 @@ static sqlite3 *open_and_init_db() { ver = 6; upgrade = 1; } + if (ver == 5 || ver == 6) { + // Hide list + sqlite3_exec(db, + "CREATE TABLE IF NOT EXISTS hidelist " + "(process TEXT, PRIMARY KEY(process))", + NULL, NULL, &err); + err_abort(err); + ver = 7; + upgrade =1 ; + } if (upgrade) { // Set version diff --git a/native/jni/include/daemon.h b/native/jni/include/daemon.h index 6006219f0..26e80dca6 100644 --- a/native/jni/include/daemon.h +++ b/native/jni/include/daemon.h @@ -8,6 +8,10 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + extern int setup_done; extern int seperate_vendor; @@ -95,4 +99,8 @@ void ls_hide_list(int client); void su_daemon_handler(int client, struct ucred *credential); +#ifdef __cplusplus +} +#endif + #endif diff --git a/native/jni/include/db.h b/native/jni/include/db.h index 3c9c92f51..3aedf2fee 100644 --- a/native/jni/include/db.h +++ b/native/jni/include/db.h @@ -4,12 +4,16 @@ #include #include +#ifdef __cplusplus +extern "C" { +#endif + /*************** * DB Settings * ***************/ #define DB_SETTING_KEYS \ -((char *[]) { \ +((const char *[]) { \ "root_access", \ "multiuser_mode", \ "mnt_ns" \ @@ -62,7 +66,7 @@ NAMESPACE_MODE_REQUESTER, \ **************/ #define DB_STRING_KEYS \ -((char *[]) { \ +((const char *[]) { \ "requester", \ }) @@ -122,4 +126,8 @@ int get_uid_policy(sqlite3 *db, int uid, struct su_access *su); int validate_manager(char *alt_pkg, int userid, struct stat *st); int exec_sql(const char *sql); +#ifdef __cplusplus +} +#endif + #endif //DB_H diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 73aa40581..30115a9a2 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -6,6 +6,10 @@ #include "logging.h" +#ifdef __cplusplus +extern "C" { +#endif + #define MAIN_SOCKET "d30138f2310a9fb9c54a3e0c21f58591" #define LOG_SOCKET "5864cd77f2f8c59b3882e2d35dbf51e4" #define JAVA_PACKAGE_NAME "com.topjohnwu.magisk" @@ -19,7 +23,6 @@ #define MOUNTPOINT MAGISKTMP "/img" #define COREDIR MOUNTPOINT "/.core" #define HOSTSFILE COREDIR "/hosts" -#define HIDELIST COREDIR "/hidelist" #define SECURE_DIR "/data/adb" #define MAINIMG SECURE_DIR "/magisk.img" #define DATABIN SECURE_DIR "/magisk" @@ -55,4 +58,8 @@ int su_client_main(int argc, char *argv[]); int resetprop_main(int argc, char *argv[]); int imgtool_main(int argc, char *argv[]); +#ifdef __cplusplus +} +#endif + #endif diff --git a/native/jni/include/resetprop.h b/native/jni/include/resetprop.h index f04822298..6c8f17701 100644 --- a/native/jni/include/resetprop.h +++ b/native/jni/include/resetprop.h @@ -4,6 +4,10 @@ #ifndef _RESETPROP_H_ #define _RESETPROP_H_ +#ifdef __cplusplus +extern "C" { +#endif + int prop_exist(const char *name); int setprop(const char *name, const char *value); int setprop2(const char *name, const char *value, const int trigger); @@ -14,4 +18,8 @@ int deleteprop2(const char *name, const int persist); int read_prop_file(const char* filename, const int trigger); void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie); +#ifdef __cplusplus +} +#endif + #endif diff --git a/native/jni/magiskhide/hide_utils.c b/native/jni/magiskhide/hide_utils.cpp similarity index 58% rename from native/jni/magiskhide/hide_utils.c rename to native/jni/magiskhide/hide_utils.cpp index 8b222b87e..2dfee4d2b 100644 --- a/native/jni/magiskhide/hide_utils.c +++ b/native/jni/magiskhide/hide_utils.cpp @@ -1,6 +1,3 @@ -/* hide_utils.c - Some utility functions for MagiskHide - */ - #include #include #include @@ -12,20 +9,23 @@ #include #include "magisk.h" -#include "utils.h" +#include "utils.hpp" #include "resetprop.h" #include "magiskhide.h" #include "daemon.h" +#include "db.h" -static char *prop_key[] = - { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", "ro.boot.veritymode", - "ro.boot.warranty_bit", "ro.warranty_bit", "ro.debuggable", "ro.secure", - "ro.build.type", "ro.build.tags", "ro.build.selinux", NULL }; +auto hide_list = Array(); -static char *prop_value[] = - { "locked", "green", "1", "enforcing", - "0", "0", "0", "1", - "user", "release-keys", "0", NULL }; +static const char *prop_key[] = + { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", + "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit", "ro.debuggable", + "ro.secure", "ro.build.type", "ro.build.tags", "ro.build.selinux", nullptr }; + +static const char *prop_value[] = + { "locked", "green", "1", + "enforcing", "0", "0", "0", + "1", "user", "release-keys", "0", nullptr }; static const char *proc_name; static gid_t proc_gid; @@ -57,12 +57,6 @@ void hide_sensitive_props() { } } -static void rm_magisk_prop(const char *name, const char *value, void *v) { - if (strstr(name, "magisk")) { - deleteprop2(name, 0); - } -} - /* Call func for each process */ static void ps(void (*func)(int)) { DIR *dir; @@ -139,123 +133,128 @@ static void kill_process(const char *name) { void clean_magisk_props() { LOGD("hide_utils: Cleaning magisk props\n"); - getprop_all(rm_magisk_prop, NULL); + getprop_all([] (const char *name, auto, auto) -> void + { + if (strstr(name, "magisk")) + deleteprop2(name, 0); + }, nullptr); } -int add_list(char *proc) { - if (!hideEnabled) { - free(proc); - return HIDE_NOT_ENABLED; - } - - char *line; - struct vector *new_list = xmalloc(sizeof(*new_list)); - if (new_list == NULL) - return DAEMON_ERROR; - vec_init(new_list); - - vec_for_each(hide_list, line) { +static int add_list(sqlite3 *db, char *proc) { + for (auto &s : hide_list) { // They should be unique - if (strcmp(line, proc) == 0) { + if (strcmp(s, proc) == 0) { free(proc); - vec_destroy(new_list); - free(new_list); return HIDE_ITEM_EXIST; } - vec_push_back(new_list, line); } - vec_push_back(new_list, proc); LOGI("hide_list add: [%s]\n", proc); kill_process(proc); // Critical region - pthread_mutex_lock(&hide_lock); - vec_destroy(hide_list); - free(hide_list); - hide_list = new_list; - pthread_mutex_unlock(&hide_lock); + pthread_mutex_lock(&list_lock); + hide_list.push_back(proc); + pthread_mutex_unlock(&list_lock); + + // Add to database + char sql[128]; + sprintf(sql, "INSERT INTO hidelist (process) VALUES('%s')", proc); + sqlite3_exec(db, sql, nullptr, nullptr, nullptr); - pthread_mutex_lock(&file_lock); - vector_to_file(HIDELIST, hide_list); // Do not complain if file not found - pthread_mutex_unlock(&file_lock); return DAEMON_SUCCESS; } +int add_list(char *proc) { + if (!hide_enabled) { + free(proc); + return HIDE_NOT_ENABLED; + } + + sqlite3 *db = get_magiskdb(); + if (db) { + int ret = add_list(db, proc); + sqlite3_close_v2(db); + return ret; + } + return DAEMON_ERROR; +} + int rm_list(char *proc) { - if (!hideEnabled) { + if (!hide_enabled) { free(proc); return HIDE_NOT_ENABLED; } int ret = DAEMON_ERROR; - char *line; - int do_rm = 0; - struct vector *new_list = xmalloc(sizeof(*new_list)); - if (new_list == NULL) - goto error; - vec_init(new_list); - vec_for_each(hide_list, line) { - if (strcmp(line, proc) == 0) { - free(proc); - proc = line; - do_rm = 1; - continue; + // Update list in critical region + bool do_rm = false; + pthread_mutex_lock(&list_lock); + for (auto it = hide_list.begin(); it != hide_list.end(); ++it) { + if (strcmp(*it, proc) == 0) { + do_rm = true; + LOGI("hide_list rm: [%s]\n", proc); + free(*it); + hide_list.erase(it); + break; } - vec_push_back(new_list, line); } + pthread_mutex_unlock(&list_lock); if (do_rm) { - LOGI("hide_list rm: [%s]\n", proc); kill_process(proc); - // Critical region - pthread_mutex_lock(&hide_lock); - vec_destroy(hide_list); - free(hide_list); - hide_list = new_list; - pthread_mutex_unlock(&hide_lock); - + sqlite3 *db = get_magiskdb(); + if (db == nullptr) + goto error; + char sql[128]; + sprintf(sql, "DELETE FROM hidelist WHERE process='%s'", proc); + sqlite3_exec(db, sql, nullptr, nullptr, nullptr); + sqlite3_close_v2(db); ret = DAEMON_SUCCESS; - pthread_mutex_lock(&file_lock); - vector_to_file(HIDELIST, hide_list); // Do not complain if file not found - pthread_mutex_unlock(&file_lock); } else { ret = HIDE_ITEM_NOT_EXIST; - vec_destroy(new_list); - free(new_list); } -error: + error: free(proc); return ret; } +#define LEGACY_LIST MOUNTPOINT "/.core/hidelist" + int init_list() { - LOGD("hide_list: initialize...\n"); - if ((hide_list = xmalloc(sizeof(*hide_list))) == NULL) + LOGD("hide_list: initialize\n"); + + sqlite3 *db = get_magiskdb(); + if (db == nullptr) return 1; - vec_init(hide_list); - // Might error if file doesn't exist, no need to report - file_to_vector(HIDELIST, hide_list); + sqlite3_exec(db, "SELECT process FROM hidelist", + [] (auto, auto, char **data, auto) -> int + { + LOGI("hide_list: [%s]\n", data[0]); + hide_list.push_back(strdup(data[0])); + return 0; + }, nullptr, nullptr); - char *line; - vec_for_each(hide_list, line) { - LOGI("hide_list: [%s]\n", line); - kill_process(line); + // Migrate old hide list into database + if (access(LEGACY_LIST, R_OK) == 0) { + auto tmp = Array(); + file_to_array(LEGACY_LIST, tmp); + for (auto &s : tmp) + add_list(db, s); + unlink(LEGACY_LIST); } + + sqlite3_close_v2(db); return 0; } int destroy_list() { - char *line; - vec_for_each(hide_list, line) { - kill_process(line); - } - vec_deep_destroy(hide_list); - free(hide_list); - hide_list = NULL; + for (auto &str : hide_list) + free(str); + hide_list.clear(); return 0; } @@ -274,15 +273,13 @@ void rm_hide_list(int client) { } void ls_hide_list(int client) { - if (!hideEnabled) { + if (!hide_enabled) { write_int(client, HIDE_NOT_ENABLED); return; } write_int(client, DAEMON_SUCCESS); - write_int(client, vec_size(hide_list)); - char *s; - vec_for_each(hide_list, s) { + write_int(client, hide_list.size()); + for (auto &s : hide_list) write_string(client, s); - } close(client); } diff --git a/native/jni/magiskhide/magiskhide.c b/native/jni/magiskhide/magiskhide.cpp similarity index 91% rename from native/jni/magiskhide/magiskhide.c rename to native/jni/magiskhide/magiskhide.cpp index a7629863a..5a1d0c5cc 100644 --- a/native/jni/magiskhide/magiskhide.c +++ b/native/jni/magiskhide/magiskhide.cpp @@ -1,6 +1,3 @@ -/* magiskhide.c - initialize the environment for Magiskhide - */ - #include #include #include @@ -17,11 +14,9 @@ #include "resetprop.h" #include "flags.h" -struct vector *hide_list = NULL; - -int hideEnabled = 0; +int hide_enabled = 0; static pthread_t proc_monitor_thread; -pthread_mutex_t hide_lock, file_lock; +pthread_mutex_t list_lock; static void usage(char *arg0) { fprintf(stderr, @@ -38,7 +33,7 @@ static void usage(char *arg0) { } void launch_magiskhide(int client) { - if (hideEnabled) { + if (hide_enabled) { if (client > 0) { write_int(client, HIDE_IS_ENABLED); close(client); @@ -57,7 +52,7 @@ void launch_magiskhide(int client) { return; } - hideEnabled = 1; + hide_enabled = 1; LOGI("* Starting MagiskHide\n"); deleteprop2(MAGISKHIDE_PROP, 1); @@ -65,8 +60,7 @@ void launch_magiskhide(int client) { hide_sensitive_props(); // Initialize the mutex lock - pthread_mutex_init(&hide_lock, NULL); - pthread_mutex_init(&file_lock, NULL); + pthread_mutex_init(&list_lock, nullptr); // Initialize the hide list if (init_list()) @@ -87,7 +81,7 @@ void launch_magiskhide(int client) { return; error: - hideEnabled = 0; + hide_enabled = 0; if (client > 0) { write_int(client, DAEMON_ERROR); close(client); @@ -96,7 +90,7 @@ error: } void stop_magiskhide(int client) { - if (!hideEnabled) { + if (!hide_enabled) { write_int(client, HIDE_NOT_ENABLED); close(client); return; @@ -104,7 +98,7 @@ void stop_magiskhide(int client) { LOGI("* Stopping MagiskHide\n"); - hideEnabled = 0; + hide_enabled = 0; setprop(MAGISKHIDE_PROP, "0"); // Remove without actually removing persist props deleteprop2(MAGISKHIDE_PROP, 0); diff --git a/native/jni/magiskhide/magiskhide.h b/native/jni/magiskhide/magiskhide.h index e3b8539a5..66a4dbdcf 100644 --- a/native/jni/magiskhide/magiskhide.h +++ b/native/jni/magiskhide/magiskhide.h @@ -2,6 +2,7 @@ #define MAGISK_HIDE_H #include +#include "array.h" #define TERM_THREAD SIGUSR1 @@ -19,8 +20,8 @@ int rm_list(char *proc); int init_list(); int destroy_list(); -extern int hideEnabled; -extern struct vector *hide_list; -extern pthread_mutex_t hide_lock, file_lock; +extern int hide_enabled; +extern pthread_mutex_t list_lock; +extern Array hide_list; #endif diff --git a/native/jni/magiskhide/proc_monitor.c b/native/jni/magiskhide/proc_monitor.cpp similarity index 78% rename from native/jni/magiskhide/proc_monitor.c rename to native/jni/magiskhide/proc_monitor.cpp index b29507a3e..d54f3a32d 100644 --- a/native/jni/magiskhide/proc_monitor.c +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -1,4 +1,4 @@ -/* proc_monitor.c - Monitor am_proc_start events and unmount +/* proc_monitor.cpp - Monitor am_proc_start events and unmount * * We monitor the logcat am_proc_start events. When a target starts up, * we pause it ASAP, and fork a new process to join its mount namespace @@ -18,22 +18,21 @@ #include "magisk.h" #include "daemon.h" -#include "utils.h" +#include "utils.hpp" #include "magiskhide.h" #include "flags.h" static int sockfd = -1; // Workaround for the lack of pthread_cancel -static void term_thread(int sig) { +static void term_thread(int) { LOGD("proc_monitor: running cleanup\n"); destroy_list(); - hideEnabled = 0; + hide_enabled = 0; close(sockfd); sockfd = -1; - pthread_mutex_destroy(&hide_lock); - pthread_mutex_destroy(&file_lock); - LOGD("proc_monitor: terminating...\n"); + pthread_mutex_destroy(&list_lock); + LOGD("proc_monitor: terminating\n"); pthread_exit(NULL); } @@ -63,8 +62,8 @@ static int parse_ppid(int pid) { static void hide_daemon(int pid) { LOGD("hide_daemon: start unmount for pid=[%d]\n", pid); - char *line, buffer[PATH_MAX]; - struct vector mount_list; + char buffer[PATH_MAX]; + auto mounts = Array(); manage_selinux(); clean_magisk_props(); @@ -73,33 +72,31 @@ static void hide_daemon(int pid) { goto exit; snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid); - vec_init(&mount_list); - file_to_vector(buffer, &mount_list); + file_to_array(buffer, mounts); // Unmount dummy skeletons and /sbin links - vec_for_each(&mount_list, line) { - if (strstr(line, "tmpfs /system/") || strstr(line, "tmpfs /vendor/") || strstr(line, "tmpfs /sbin")) { - sscanf(line, "%*s %4096s", buffer); + for (auto &s : mounts) { + if (strstr(s, "tmpfs /system/") || strstr(s, "tmpfs /vendor/") || strstr(s, "tmpfs /sbin")) { + sscanf(s, "%*s %4096s", buffer); lazy_unmount(buffer); } - free(line); + free(s); } - vec_destroy(&mount_list); + mounts.clear(); // Re-read mount infos snprintf(buffer, sizeof(buffer), "/proc/%d/mounts", pid); - vec_init(&mount_list); - file_to_vector(buffer, &mount_list); + file_to_array(buffer, mounts); // Unmount everything under /system, /vendor, and loop mounts - vec_for_each(&mount_list, line) { - if (strstr(line, "/dev/block/loop") || strstr(line, " /system/") || strstr(line, " /vendor/")) { - sscanf(line, "%*s %4096s", buffer); + for (auto &s : mounts) { + if (strstr(s, "/dev/block/loop") || strstr(s, " /system/") || strstr(s, " /vendor/")) { + sscanf(s, "%*s %4096s", buffer); lazy_unmount(buffer); } - free(line); + free(s); } - vec_destroy(&mount_list); + mounts.clear(); exit: // Send resume signal @@ -159,16 +156,15 @@ void proc_monitor() { if (colon) *colon = '\0'; - int hide = 0; - pthread_mutex_lock(&hide_lock); - char *line; - vec_for_each(hide_list, line) { - if (strcmp(proc, line) == 0) { - hide = 1; + bool hide = false; + pthread_mutex_lock(&list_lock); + for (auto &s : hide_list) { + if (strcmp(proc, s) == 0) { + hide = true; break; } } - pthread_mutex_unlock(&hide_lock); + pthread_mutex_unlock(&list_lock); if (!hide) continue; diff --git a/native/jni/utils/Android.mk b/native/jni/utils/Android.mk index a243ff984..b44d3d6cb 100644 --- a/native/jni/utils/Android.mk +++ b/native/jni/utils/Android.mk @@ -4,6 +4,7 @@ include $(CLEAR_VARS) LOCAL_MODULE:= libutils LOCAL_C_INCLUDES := jni/include $(LIBUTILS) LOCAL_SRC_FILES := \ + utils.cpp \ file.c \ list.c \ misc.c \ diff --git a/native/jni/utils/include/utils.hpp b/native/jni/utils/include/utils.hpp new file mode 100644 index 000000000..0218eaa25 --- /dev/null +++ b/native/jni/utils/include/utils.hpp @@ -0,0 +1,6 @@ +#pragma once + +#include "utils.h" +#include "array.h" + +int file_to_array(const char* filename, Array &arr); \ No newline at end of file diff --git a/native/jni/utils/utils.cpp b/native/jni/utils/utils.cpp new file mode 100644 index 000000000..3f3a5b2d0 --- /dev/null +++ b/native/jni/utils/utils.cpp @@ -0,0 +1,25 @@ +#include + +#include "utils.hpp" + +int file_to_array(const char *filename, Array &arr) { + if (access(filename, R_OK) != 0) + return 1; + char *line = NULL; + size_t len = 0; + ssize_t read; + + FILE *fp = xfopen(filename, "r"); + if (fp == NULL) + return 1; + + while ((read = getline(&line, &len, fp)) != -1) { + // Remove end newline + if (line[read - 1] == '\n') + line[read - 1] = '\0'; + arr.push_back(line); + line = NULL; + } + fclose(fp); + return 0; +}