From cda57dd4b40cd3c2a608ddc34d1c4867e1714ac2 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 4 Nov 2018 03:38:06 -0500 Subject: [PATCH] Fully migrate Magisk to C++ --- native/jni/Android.mk | 24 +- .../daemon/{bootstages.c => bootstages.cpp} | 673 +++++++++--------- native/jni/daemon/{daemon.c => daemon.cpp} | 6 +- native/jni/daemon/{db.c => db.cpp} | 46 +- .../daemon/{log_daemon.c => log_daemon.cpp} | 56 +- native/jni/daemon/{magisk.c => magisk.cpp} | 3 +- native/jni/daemon/{socket.c => socket.cpp} | 8 +- native/jni/include/db.h | 35 +- native/jni/include/img.h | 8 + native/jni/include/magisk.h | 4 +- native/jni/include/resetprop.h | 25 +- native/jni/magiskhide/hide_utils.cpp | 8 +- native/jni/magiskhide/magiskhide.cpp | 6 +- native/jni/magiskhide/magiskhide.h | 2 - native/jni/misc/{applets.c => applets.cpp} | 0 native/jni/misc/{img.c => img.cpp} | 2 +- native/jni/resetprop/resetprop.cpp | 40 +- native/jni/su/{connect.c => connect.cpp} | 21 +- native/jni/su/{pts.c => pts.cpp} | 1 - native/jni/su/{su.c => su.cpp} | 29 +- native/jni/su/su.h | 32 +- native/jni/su/{su_daemon.c => su_daemon.cpp} | 65 +- native/jni/utils/Android.mk | 3 +- native/jni/utils/include/array.h | 12 +- native/jni/utils/include/selinux.h | 1 - native/jni/utils/include/utils.h | 4 - native/jni/utils/legacy.c | 41 -- 27 files changed, 548 insertions(+), 607 deletions(-) rename native/jni/daemon/{bootstages.c => bootstages.cpp} (73%) rename native/jni/daemon/{daemon.c => daemon.cpp} (97%) rename native/jni/daemon/{db.c => db.cpp} (87%) rename native/jni/daemon/{log_daemon.c => log_daemon.cpp} (78%) rename native/jni/daemon/{magisk.c => magisk.cpp} (99%) rename native/jni/daemon/{socket.c => socket.cpp} (96%) rename native/jni/misc/{applets.c => applets.cpp} (100%) rename native/jni/misc/{img.c => img.cpp} (99%) rename native/jni/su/{connect.c => connect.cpp} (91%) rename native/jni/su/{pts.c => pts.cpp} (99%) rename native/jni/su/{su.c => su.cpp} (94%) rename native/jni/su/{su_daemon.c => su_daemon.cpp} (89%) delete mode 100644 native/jni/utils/legacy.c diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 5e3773967..cb5a63cca 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -32,14 +32,14 @@ LOCAL_C_INCLUDES := \ $(LIBUTILS) LOCAL_SRC_FILES := \ - misc/applets.c \ - misc/img.c \ - daemon/magisk.c \ - daemon/daemon.c \ - daemon/log_daemon.c \ - daemon/bootstages.c \ - daemon/socket.c \ - daemon/db.c \ + misc/applets.cpp \ + misc/img.cpp \ + daemon/magisk.cpp \ + daemon/daemon.cpp \ + daemon/log_daemon.cpp \ + daemon/bootstages.cpp \ + daemon/socket.cpp \ + daemon/db.cpp \ magiskhide/magiskhide.cpp \ magiskhide/proc_monitor.cpp \ magiskhide/hide_utils.cpp \ @@ -47,10 +47,10 @@ LOCAL_SRC_FILES := \ resetprop/resetprop.cpp \ resetprop/system_property_api.cpp \ resetprop/system_property_set.cpp \ - su/su.c \ - su/connect.c \ - su/pts.c \ - su/su_daemon.c + su/su.cpp \ + su/connect.cpp \ + su/pts.cpp \ + su/su_daemon.cpp LOCAL_LDLIBS := -llog include $(BUILD_EXECUTABLE) diff --git a/native/jni/daemon/bootstages.c b/native/jni/daemon/bootstages.cpp similarity index 73% rename from native/jni/daemon/bootstages.c rename to native/jni/daemon/bootstages.cpp index fc97cf571..01697c8e9 100644 --- a/native/jni/daemon/bootstages.c +++ b/native/jni/daemon/bootstages.cpp @@ -24,13 +24,13 @@ #include "flags.h" static char buf[PATH_MAX], buf2[PATH_MAX]; -static struct vector module_list; +static Array module_list; -extern char **environ; +static int bind_mount(const char *from, const char *to); -/****************** - * Node structure * - ******************/ +/*************** + * Magic Mount * + ***************/ // Precedence: MODULE > SKEL > INTER > DUMMY #define IS_DUMMY 0x01 /* mount from mirror */ @@ -42,73 +42,236 @@ extern char **environ; #define IS_LNK(n) (n->type == DT_LNK) #define IS_REG(n) (n->type == DT_REG) -struct node_entry { +class node_entry { +public: const char *module; /* Only used when status & IS_MODULE */ char *name; uint8_t type; uint8_t status; - struct node_entry *parent; - struct vector *children; + node_entry *parent; + Array children; + + node_entry() = default; + node_entry(const char *, const char *, uint8_t type = 0, uint8_t status = 0); + node_entry(const char *, uint8_t type = 0, uint8_t status = 0); + ~node_entry(); + void create_module_tree(const char *module); + void magic_mount(); + +private: + char *get_path(); + node_entry *insert(node_entry *); + void clone_skeleton(); + int get_path(char *path); }; -static void concat_path(struct node_entry *node) { - if (node->parent) - concat_path(node->parent); - size_t len = strlen(buf); - buf[len] = '/'; - strcpy(buf + len + 1, node->name); +node_entry::node_entry(const char *module, const char *name, uint8_t type, uint8_t status) + : node_entry(name, type, status) { + this->module = module; } -static char *get_full_path(struct node_entry *node) { - buf[0] = '\0'; - concat_path(node); +node_entry::node_entry(const char *name, uint8_t type, uint8_t status) + : type(type), status(status), parent(nullptr) { + this->name = strdup(name); +} + +node_entry::~node_entry() { + free(name); + for (auto &node : children) + delete node; +} + +char *node_entry::get_path() { + get_path(buf); return strdup(buf); } -// Free the node -static void destroy_node(struct node_entry *node) { - free(node->name); - vec_destroy(node->children); - free(node->children); - free(node); +int node_entry::get_path(char *path) { + int len = 0; + if (parent) + len = parent->get_path(path); + len += sprintf(path + len, "/%s", name); + return len; } -// Free the node and all children recursively -static void destroy_subtree(struct node_entry *node) { - // Never free parent, since it shall be freed by themselves - struct node_entry *e; - vec_for_each(node->children, e) { - destroy_subtree(e); - } - destroy_node(node); -} - -// Return the child -static struct node_entry *insert_child(struct node_entry *p, struct node_entry *c) { - c->parent = p; - if (p->children == NULL) { - p->children = xmalloc(sizeof(struct vector)); - vec_init(p->children); - } - struct node_entry *e; - vec_for_each(p->children, e) { - if (strcmp(e->name, c->name) == 0) { - // Exist duplicate - if (c->status > e->status) { - // Precedence is higher, replace with new node - destroy_subtree(e); - vec_cur(p->children) = c; - return c; +node_entry *node_entry::insert(node_entry *node) { + node->parent = this; + for (auto &child : children) { + if (strcmp(child->name, node->name) == 0) { + if (node->status > child->status) { + // The new node has higher precedence + delete child; + child = node; + return node; } else { - // Free the new entry, return old - destroy_node(c); - return e; + delete node; + return child; } } } - // New entry, push back - vec_push_back(p->children, c); - return c; + children.push_back(node); + return node; +} + +void node_entry::create_module_tree(const char *module) { + DIR *dir; + struct dirent *entry; + + char *full_path = get_path(); + snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, full_path); + + if (!(dir = xopendir(buf))) + goto cleanup; + + while ((entry = xreaddir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + // Create new node + node_entry *node = new node_entry(module, entry->d_name, entry->d_type); + snprintf(buf, PATH_MAX, "%s/%s", full_path, node->name); + + /* + * Clone the parent in the following condition: + * 1. File in module is a symlink + * 2. Target file do not exist + * 3. Target file is a symlink (exclude /system/vendor) + */ + bool clone = false; + if (IS_LNK(node) || access(buf, F_OK) == -1) { + clone = true; + } else if (parent != nullptr || strcmp(node->name, "vendor") != 0) { + struct stat s; + xstat(buf, &s); + if (S_ISLNK(s.st_mode)) + clone = true; + } + + if (clone) { + // Mark self as a skeleton + status |= IS_SKEL; /* This will not overwrite if parent is module */ + node->status = IS_MODULE; + } else if (IS_DIR(node)) { + // Check if marked as replace + snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MOUNTPOINT, module, buf); + if (access(buf2, F_OK) == 0) { + // Replace everything, mark as leaf + node->status = IS_MODULE; + } else { + // This will be an intermediate node + node->status = IS_INTER; + } + } else if (IS_REG(node)) { + // This is a file, mark as leaf + node->status = IS_MODULE; + } + node = insert(node); + if (node->status & (IS_SKEL | IS_INTER)) { + // Intermediate folder, travel deeper + node->create_module_tree(module); + } + } + closedir(dir); + +cleanup: + free(full_path); +} + +void node_entry::clone_skeleton() { + DIR *dir; + struct dirent *entry; + struct node_entry *dummy; + + // Clone the structure + char *full_path = get_path(); + snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path); + if (!(dir = xopendir(buf))) + goto cleanup; + while ((entry = xreaddir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + // Create dummy node + dummy = new node_entry(entry->d_name, entry->d_type, IS_DUMMY); + insert(dummy); + } + closedir(dir); + + if (status & IS_SKEL) { + struct stat s; + char *con; + xstat(full_path, &s); + getfilecon(full_path, &con); + LOGI("mnt_tmpfs : %s\n", full_path); + xmount("tmpfs", full_path, "tmpfs", 0, nullptr); + chmod(full_path, s.st_mode & 0777); + chown(full_path, s.st_uid, s.st_gid); + setfilecon(full_path, con); + free(con); + } + + for (auto &child : children) { + snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name); + + // Create the dummy file/directory + if (IS_DIR(child)) + xmkdir(buf, 0755); + else if (IS_REG(child)) + close(creat(buf, 0644)); + // Links will be handled later + + if (child->parent->parent == nullptr && strcmp(child->name, "vendor") == 0) { + if (IS_LNK(child)) { + cp_afc(MIRRDIR "/system/vendor", "/system/vendor"); + LOGI("creat_link: %s <- %s\n", "/system/vendor", MIRRDIR "/system/vendor"); + } + // Skip + continue; + } else if (child->status & IS_MODULE) { + // Mount from module file to dummy file + snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, child->module, full_path, child->name); + } else if (child->status & (IS_SKEL | IS_INTER)) { + // It's an intermediate folder, recursive clone + child->clone_skeleton(); + continue; + } else if (child->status & IS_DUMMY) { + // Mount from mirror to dummy file + snprintf(buf2, PATH_MAX, "%s%s/%s", MIRRDIR, full_path, child->name); + } + + if (IS_LNK(child)) { + // Copy symlinks directly + cp_afc(buf2, buf); +#ifdef MAGISK_DEBUG + LOGI("creat_link: %s <- %s\n",buf, buf2); +#else + LOGI("creat_link: %s\n", buf); +#endif + } else { + snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name); + bind_mount(buf2, buf); + } + } + +cleanup: + free(full_path); +} + +void node_entry::magic_mount() { + if (status & IS_MODULE) { + // Mount module item + char *real_path = get_path(); + snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, real_path); + bind_mount(buf, real_path); + free(real_path); + } else if (status & IS_SKEL) { + // The node is labeled to be cloned with skeleton, lets do it + clone_skeleton(); + } else if (status & IS_INTER) { + // It's an intermediate node, travel deeper + for (auto &child : children) + child->magic_mount(); + } + // The only thing goes here should be vendor placeholder + // There should be no dummies, so don't need to handle it here } /*********** @@ -144,11 +307,12 @@ static void exec_common_script(const char* stage) { if (access(buf2, X_OK) == -1) continue; LOGI("%s.d: exec [%s]\n", stage, entry->d_name); - int pid = exec_command(0, NULL, - strcmp(stage, "post-fs-data") ? set_path : set_mirror_path, - "sh", buf2, NULL); + int pid = exec_command( + 0, nullptr, + strcmp(stage, "post-fs-data") ? set_path : set_mirror_path, + "sh", buf2, nullptr); if (pid != -1) - waitpid(pid, NULL, 0); + waitpid(pid, nullptr, 0); } } @@ -156,206 +320,19 @@ static void exec_common_script(const char* stage) { } static void exec_module_script(const char* stage) { - char *module; - vec_for_each(&module_list, module) { + for (auto &module : module_list) { snprintf(buf2, PATH_MAX, "%s/%s/%s.sh", MOUNTPOINT, module, stage); snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, module); if (access(buf2, F_OK) == -1 || access(buf, F_OK) == 0) continue; LOGI("%s: exec [%s.sh]\n", module, stage); - int pid = exec_command(0, NULL, - strcmp(stage, "post-fs-data") ? set_path : set_mirror_path, - "sh", buf2, NULL); + int pid = exec_command( + 0, nullptr, + strcmp(stage, "post-fs-data") ? set_path : set_mirror_path, + "sh", buf2, nullptr); if (pid != -1) - waitpid(pid, NULL, 0); + waitpid(pid, nullptr, 0); } - -} - -/*************** - * Magic Mount * - ***************/ - -static int bind_mount(const char *from, const char *to) { - int ret = xmount(from, to, NULL, MS_BIND, NULL); -#ifdef MAGISK_DEBUG - LOGI("bind_mount: %s <- %s\n", to, from); -#else - LOGI("bind_mount: %s\n", to); -#endif - return ret; -} - -static void construct_tree(const char *module, struct node_entry *parent) { - DIR *dir; - struct dirent *entry; - struct node_entry *node; - - char *parent_path = get_full_path(parent); - snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, module, parent_path); - - if (!(dir = xopendir(buf))) - goto cleanup; - - while ((entry = xreaddir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - // Create new node - node = xcalloc(sizeof(*node), 1); - node->module = module; - node->name = strdup(entry->d_name); - node->type = entry->d_type; - snprintf(buf, PATH_MAX, "%s/%s", parent_path, node->name); - - /* - * Clone the parent in the following condition: - * 1. File in module is a symlink - * 2. Target file do not exist - * 3. Target file is a symlink, but not /system/vendor - */ - int clone = 0; - if (IS_LNK(node) || access(buf, F_OK) == -1) { - clone = 1; - } else if (parent->parent != NULL || strcmp(node->name, "vendor") != 0) { - struct stat s; - xstat(buf, &s); - if (S_ISLNK(s.st_mode)) - clone = 1; - } - - if (clone) { - // Mark the parent folder as a skeleton - parent->status |= IS_SKEL; /* This will not overwrite if parent is module */ - node->status = IS_MODULE; - } else if (IS_DIR(node)) { - // Check if marked as replace - snprintf(buf2, PATH_MAX, "%s/%s%s/.replace", MOUNTPOINT, module, buf); - if (access(buf2, F_OK) == 0) { - // Replace everything, mark as leaf - node->status = IS_MODULE; - } else { - // This will be an intermediate node - node->status = IS_INTER; - } - } else if (IS_REG(node)) { - // This is a leaf, mark as target - node->status = IS_MODULE; - } - node = insert_child(parent, node); - if (node->status & (IS_SKEL | IS_INTER)) { - // Intermediate folder, travel deeper - construct_tree(module, node); - } - } - - closedir(dir); - -cleanup: - free(parent_path); -} - -static void clone_skeleton(struct node_entry *node) { - DIR *dir; - struct dirent *entry; - struct node_entry *dummy, *child; - - // Clone the structure - char *full_path = get_full_path(node); - snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path); - if (!(dir = xopendir(buf))) - goto cleanup; - while ((entry = xreaddir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - // Create dummy node - dummy = xcalloc(sizeof(*dummy), 1); - dummy->name = strdup(entry->d_name); - dummy->type = entry->d_type; - dummy->status = IS_DUMMY; - insert_child(node, dummy); - } - closedir(dir); - - if (node->status & IS_SKEL) { - struct stat s; - char *con; - xstat(full_path, &s); - getfilecon(full_path, &con); - LOGI("mnt_tmpfs : %s\n", full_path); - xmount("tmpfs", full_path, "tmpfs", 0, NULL); - chmod(full_path, s.st_mode & 0777); - chown(full_path, s.st_uid, s.st_gid); - setfilecon(full_path, con); - free(con); - } - - vec_for_each(node->children, child) { - snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name); - - // Create the dummy file/directory - if (IS_DIR(child)) - xmkdir(buf, 0755); - else if (IS_REG(child)) - close(creat(buf, 0644)); - // Links will be handled later - - if (child->parent->parent == NULL && strcmp(child->name, "vendor") == 0) { - if (IS_LNK(child)) { - cp_afc(MIRRDIR "/system/vendor", "/system/vendor"); - LOGI("creat_link: %s <- %s\n", "/system/vendor", MIRRDIR "/system/vendor"); - } - // Skip - continue; - } else if (child->status & IS_MODULE) { - // Mount from module file to dummy file - snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MOUNTPOINT, child->module, full_path, child->name); - } else if (child->status & (IS_SKEL | IS_INTER)) { - // It's an intermediate folder, recursive clone - clone_skeleton(child); - continue; - } else if (child->status & IS_DUMMY) { - // Mount from mirror to dummy file - snprintf(buf2, PATH_MAX, "%s%s/%s", MIRRDIR, full_path, child->name); - } - - if (IS_LNK(child)) { - // Copy symlinks directly - cp_afc(buf2, buf); -#ifdef MAGISK_DEBUG - LOGI("creat_link: %s <- %s\n",buf, buf2); -#else - LOGI("creat_link: %s\n", buf); -#endif - } else { - snprintf(buf, PATH_MAX, "%s/%s", full_path, child->name); - bind_mount(buf2, buf); - } - } - -cleanup: - free(full_path); -} - -static void magic_mount(struct node_entry *node) { - char *real_path; - struct node_entry *child; - - if (node->status & IS_MODULE) { - // The real deal, mount module item - real_path = get_full_path(node); - snprintf(buf, PATH_MAX, "%s/%s%s", MOUNTPOINT, node->module, real_path); - bind_mount(buf, real_path); - free(real_path); - } else if (node->status & IS_SKEL) { - // The node is labeled to be cloned with skeleton, lets do it - clone_skeleton(node); - } else if (node->status & IS_INTER) { - // It's an intermediate node, travel deeper - vec_for_each(node->children, child) - magic_mount(child); - } - // The only thing goes here should be vendor placeholder - // There should be no dummies, so don't need to handle it here } /**************** @@ -399,8 +376,18 @@ static void simple_mount(const char *path) { * Miscellaneous * *****************/ -#define alt_img ((char *[]) \ -{ "/cache/magisk.img", "/data/magisk_merge.img", "/data/adb/magisk_merge.img", NULL }) +static int bind_mount(const char *from, const char *to) { + int ret = xmount(from, to, nullptr, MS_BIND, nullptr); +#ifdef MAGISK_DEBUG + LOGI("bind_mount: %s <- %s\n", to, from); +#else + LOGI("bind_mount: %s\n", to); +#endif + return ret; +} + +#define alt_img ((const char *[]) \ +{ "/cache/magisk.img", "/data/magisk_merge.img", "/data/adb/magisk_merge.img", nullptr }) static int prepare_img() { // Merge images @@ -419,7 +406,7 @@ static int prepare_img() { LOGI("* Mounting " MAINIMG "\n"); // Mounting magisk image char *magiskloop = mount_image(MAINIMG, MOUNTPOINT); - if (magiskloop == NULL) + if (magiskloop == nullptr) return 1; xmkdir(COREDIR, 0755); @@ -447,7 +434,7 @@ static int prepare_img() { snprintf(buf, PATH_MAX, "%s/%s/disable", MOUNTPOINT, entry->d_name); if (access(buf, F_OK) == 0) continue; - vec_push_back(&module_list, strdup(entry->d_name)); + module_list.push_back(strdup(entry->d_name)); } } closedir(dir); @@ -459,19 +446,19 @@ static int prepare_img() { } static void install_apk(const char *apk) { - setfilecon(apk, "u:object_r:"SEPOL_FILE_DOMAIN":s0"); + setfilecon(apk, "u:object_r:" SEPOL_FILE_DOMAIN ":s0"); while (1) { sleep(5); LOGD("apk_install: attempting to install APK"); int apk_res = -1, pid; - pid = exec_command(1, &apk_res, NULL, "/system/bin/pm", "install", "-r", apk, NULL); + pid = exec_command(1, &apk_res, nullptr, "/system/bin/pm", "install", "-r", apk, nullptr); if (pid != -1) { int err = 0; while (fdgets(buf, PATH_MAX, apk_res) > 0) { LOGD("apk_install: %s", buf); - err |= strstr(buf, "Error:") != NULL; + err |= strstr(buf, "Error:") != nullptr; } - waitpid(pid, NULL, 0); + waitpid(pid, nullptr, 0); close(apk_res); // Keep trying until pm is started if (err) @@ -482,38 +469,35 @@ static void install_apk(const char *apk) { unlink(apk); } -static int check_data() { - struct vector v; - vec_init(&v); - file_to_vector("/proc/mounts", &v); - char *line; - int mnt = 0; - vec_for_each(&v, line) { - if (strstr(line, " /data ") && strstr(line, "tmpfs") == NULL) { - mnt = 1; - break; - } +static bool check_data() { + bool mnt = false; + bool data = false; + Array mounts; + file_to_array("/proc/mounts", mounts); + for (auto &line : mounts) { + if (strstr(line, " /data ") && strstr(line, "tmpfs") == nullptr) + mnt = true; + free(line); } - vec_deep_destroy(&v); - int data = 0; + mounts.clear(); if (mnt) { char *crypto = getprop("ro.crypto.state"); - if (crypto != NULL) { + if (crypto != nullptr) { if (strcmp(crypto, "unencrypted") == 0) { // Unencrypted, we can directly access data - data = 1; + data = true; } else { // Encrypted, check whether vold is started char *vold = getprop("init.svc.vold"); - if (vold != NULL) { + if (vold != nullptr) { free(vold); - data = 1; + data = true; } } free(crypto); } else { // ro.crypto.state is not set, assume it's unencrypted - data = 1; + data = true; } } return data; @@ -521,18 +505,18 @@ static int check_data() { extern int launch_magiskhide(); -static void *start_magisk_hide(void *args) { +static void *start_magisk_hide(void *) { launch_magiskhide(); - return NULL; + return nullptr; } static void auto_start_magiskhide() { if (!start_log_daemon()) return; - char *hide_prop = getprop2(MAGISKHIDE_PROP, 1); - if (hide_prop == NULL || strcmp(hide_prop, "0") != 0) { + char *hide_prop = getprop(MAGISKHIDE_PROP, 1); + if (hide_prop == nullptr || strcmp(hide_prop, "0") != 0) { pthread_t thread; - xpthread_create(&thread, NULL, start_magisk_hide, NULL); + xpthread_create(&thread, nullptr, start_magisk_hide, nullptr); pthread_detach(thread); } free(hide_prop); @@ -565,7 +549,7 @@ void unlock_blocks() { static void unblock_boot_process() { close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT, 0)); - pthread_exit(NULL); + pthread_exit(nullptr); } static const char wrapper[] = @@ -621,7 +605,7 @@ void startup() { void *magisk, *init; size_t magisk_size, init_size; - xmount(NULL, "/", NULL, MS_REMOUNT, NULL); + xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr); // Remove some traits of Magisk unlink(MAGISKRC); @@ -645,7 +629,7 @@ void startup() { close(sbin); // Mount the /sbin tmpfs overlay - xmount("tmpfs", "/sbin", "tmpfs", 0, NULL); + xmount("tmpfs", "/sbin", "tmpfs", 0, nullptr); chmod("/sbin", 0755); setfilecon("/sbin", "u:object_r:rootfs:s0"); sbin = xopen("/sbin", O_RDONLY | O_CLOEXEC); @@ -665,15 +649,15 @@ void startup() { fd = creat("/sbin/magisk", 0755); xwrite(fd, wrapper, sizeof(wrapper) - 1); close(fd); - setfilecon("/sbin/magisk.bin", "u:object_r:"SEPOL_FILE_DOMAIN":s0"); - setfilecon("/sbin/magisk", "u:object_r:"SEPOL_FILE_DOMAIN":s0"); + setfilecon("/sbin/magisk.bin", "u:object_r:" SEPOL_FILE_DOMAIN ":s0"); + setfilecon("/sbin/magisk", "u:object_r:" SEPOL_FILE_DOMAIN ":s0"); // Setup magiskinit symlinks fd = creat("/sbin/magiskinit", 0755); xwrite(fd, init, init_size); close(fd); free(init); - setfilecon("/sbin/magiskinit", "u:object_r:"SEPOL_FILE_DOMAIN":s0"); + setfilecon("/sbin/magiskinit", "u:object_r:" SEPOL_FILE_DOMAIN ":s0"); for (int i = 0; init_applet[i]; ++i) { snprintf(buf, PATH_MAX, "/sbin/%s", init_applet[i]); xsymlink("/sbin/magiskinit", buf); @@ -691,10 +675,10 @@ void startup() { close(root); // Alternative binaries paths - char *alt_bin[] = { "/cache/data_bin", "/data/magisk", + const char *alt_bin[] = { "/cache/data_bin", "/data/magisk", "/data/data/com.topjohnwu.magisk/install", - "/data/user_de/0/com.topjohnwu.magisk/install", NULL }; - char *bin_path = NULL; + "/data/user_de/0/com.topjohnwu.magisk/install", nullptr }; + const char *bin_path = nullptr; for (int i = 0; alt_bin[i]; ++i) { struct stat st; if (lstat(alt_bin[i], &st) != -1 && !S_ISLNK(st.st_mode)) { @@ -723,19 +707,17 @@ void startup() { xmkdir(BLOCKDIR, 0755); LOGI("* Mounting mirrors"); - struct vector mounts; - vec_init(&mounts); - file_to_vector("/proc/mounts", &mounts); - char *line; + Array mounts; + file_to_array("/proc/mounts", mounts); int skip_initramfs = 0; // Check whether skip_initramfs device - vec_for_each(&mounts, line) { + for (auto &line : mounts) { if (strstr(line, " /system_root ")) { bind_mount("/system_root/system", MIRRDIR "/system"); skip_initramfs = 1; } else if (!skip_initramfs && strstr(line, " /system ")) { sscanf(line, "%s %*s %s", buf, buf2); - xmount(buf, MIRRDIR "/system", buf2, MS_RDONLY, NULL); + xmount(buf, MIRRDIR "/system", buf2, MS_RDONLY, nullptr); #ifdef MAGISK_DEBUG LOGI("mount: %s <- %s\n", MIRRDIR "/system", buf); #else @@ -745,7 +727,7 @@ void startup() { seperate_vendor = 1; sscanf(line, "%s %*s %s", buf, buf2); xmkdir(MIRRDIR "/vendor", 0755); - xmount(buf, MIRRDIR "/vendor", buf2, MS_RDONLY, NULL); + xmount(buf, MIRRDIR "/vendor", buf2, MS_RDONLY, nullptr); #ifdef MAGISK_DEBUG LOGI("mount: %s <- %s\n", MIRRDIR "/vendor", buf); #else @@ -754,7 +736,7 @@ void startup() { } free(line); } - vec_destroy(&mounts); + mounts.clear(); if (!seperate_vendor) { xsymlink(MIRRDIR "/system/vendor", MIRRDIR "/vendor"); #ifdef MAGISK_DEBUG @@ -767,12 +749,23 @@ void startup() { bind_mount(DATABIN, MIRRDIR "/bin"); if (access(MIRRDIR "/bin/busybox", X_OK) == 0) { LOGI("* Setting up internal busybox"); - exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, NULL); + exec_command_sync(MIRRDIR "/bin/busybox", "--install", "-s", BBPATH, nullptr); xsymlink(MIRRDIR "/bin/busybox", BBPATH "/busybox"); } // Start post-fs-data mode - execl("/sbin/magisk.bin", "magisk", "--post-fs-data", NULL); + execl("/sbin/magisk.bin", "magisk", "--post-fs-data", nullptr); +} + +static void core_only() { + // Systemless hosts + if (access(HOSTSFILE, F_OK) == 0) { + LOGI("* Enabling systemless hosts file support"); + bind_mount(HOSTSFILE, "/system/etc/hosts"); + } + + auto_start_magiskhide(); + unblock_boot_process(); } void post_fs_data(int client) { @@ -783,20 +776,20 @@ void post_fs_data(int client) { // If post-fs-data mode is started, it means startup succeeded setup_done = 1; - xmount(NULL, "/", NULL, MS_REMOUNT | MS_RDONLY, NULL); + xmount(nullptr, "/", nullptr, MS_REMOUNT | MS_RDONLY, nullptr); // Start log_daemon start_log_daemon(); LOGI("** post-fs-data mode running\n"); - // Allocate buffer - vec_init(&module_list); - // Merge, trim, mount magisk.img, which will also travel through the modules // After this, it will create the module list - if (prepare_img()) - goto core_only; // Mounting fails, we can only do core only stuffs + if (prepare_img()) { + // Mounting fails, we can only do core only stuffs + core_only(); + return; + } restorecon(); chmod(SECURE_DIR, 0700); @@ -806,30 +799,31 @@ void post_fs_data(int client) { exec_common_script("post-fs-data"); // Core only mode - if (access(DISABLEFILE, F_OK) == 0) - goto core_only; + if (access(DISABLEFILE, F_OK) == 0) { + core_only(); + return; + } // Execute module scripts LOGI("* Running module post-fs-data scripts\n"); exec_module_script("post-fs-data"); - char *module; - struct node_entry *sys_root, *ven_root = NULL, *child; - // Create the system root entry - sys_root = xcalloc(sizeof(*sys_root), 1); - sys_root->name = strdup("system"); + node_entry *sys_root = new node_entry("system"); sys_root->status = IS_INTER; - int has_modules = 0; + // Vendor root entry + node_entry *ven_root = nullptr; + + bool has_modules = false; LOGI("* Loading modules\n"); - vec_for_each(&module_list, module) { + for (auto &module : module_list) { // Read props snprintf(buf, PATH_MAX, "%s/%s/system.prop", MOUNTPOINT, module); if (access(buf, F_OK) == 0) { LOGI("%s: loading [system.prop]\n", module); - read_prop_file(buf, 0); + load_prop_file(buf, 0); } // Check whether enable auto_mount snprintf(buf, PATH_MAX, "%s/%s/auto_mount", MOUNTPOINT, module); @@ -841,7 +835,7 @@ void post_fs_data(int client) { continue; // Construct structure - has_modules = 1; + has_modules = true; LOGI("%s: constructing magic mount structure\n", module); // If /system/vendor exists in module, create a link outside snprintf(buf, PATH_MAX, "%s/%s/system/vendor", MOUNTPOINT, module); @@ -850,44 +844,31 @@ void post_fs_data(int client) { unlink(buf2); xsymlink(buf, buf2); } - construct_tree(module, sys_root); + sys_root->create_module_tree(module); } if (has_modules) { // Extract the vendor node out of system tree and swap with placeholder - vec_for_each(sys_root->children, child) { + for (auto &child : sys_root->children) { if (strcmp(child->name, "vendor") == 0) { ven_root = child; - child = xcalloc(sizeof(*child), 1); - child->type = seperate_vendor ? DT_LNK : DT_DIR; + child = new node_entry("vendor", seperate_vendor ? DT_LNK : DT_DIR); child->parent = ven_root->parent; - child->name = strdup("vendor"); - child->status = 0; - // Swap! - vec_cur(sys_root->children) = child; - ven_root->parent = NULL; + ven_root->parent = nullptr; break; } } // Magic!! - magic_mount(sys_root); - if (ven_root) magic_mount(ven_root); + sys_root->magic_mount(); + if (ven_root) ven_root->magic_mount(); } // Cleanup memory - destroy_subtree(sys_root); - if (ven_root) destroy_subtree(ven_root); + delete sys_root; + if (ven_root) delete ven_root; -core_only: - // Systemless hosts - if (access(HOSTSFILE, F_OK) == 0) { - LOGI("* Enabling systemless hosts file support"); - bind_mount(HOSTSFILE, "/system/etc/hosts"); - } - - auto_start_magiskhide(); - unblock_boot_process(); + core_only(); } void late_start(int client) { @@ -903,7 +884,7 @@ void late_start(int client) { if (!setup_done) { // The setup failed for some reason, reboot and try again - exec_command_sync("/system/bin/reboot", NULL); + exec_command_sync("/system/bin/reboot", nullptr); return; } @@ -932,9 +913,9 @@ core_only: struct db_strings str; memset(&str, 0, sizeof(str)); get_db_strings(db, SU_MANAGER, &str); - if (validate_manager(str.s[SU_MANAGER], 0, NULL)) { + if (validate_manager(str.s[SU_MANAGER], 0, nullptr)) { // There is no manager installed, install the stub - exec_command_sync("/sbin/magiskinit", "-x", "manager", "/data/magisk.apk", NULL); + exec_command_sync("/sbin/magiskinit", "-x", "manager", "/data/magisk.apk", nullptr); install_apk("/data/magisk.apk"); } sqlite3_close_v2(db); @@ -942,7 +923,9 @@ core_only: } // All boot stage done, cleanup - vec_deep_destroy(&module_list); + for (auto &module : module_list) + free(module); + module_list.clear(); } void boot_complete(int client) { diff --git a/native/jni/daemon/daemon.c b/native/jni/daemon/daemon.cpp similarity index 97% rename from native/jni/daemon/daemon.c rename to native/jni/daemon/daemon.cpp index 5d134bfc0..e3e9c50a5 100644 --- a/native/jni/daemon/daemon.c +++ b/native/jni/daemon/daemon.cpp @@ -31,7 +31,7 @@ static void get_client_cred(int fd, struct ucred *cred) { static void *request_handler(void *args) { int client = *((int *) args); - free(args); + delete (int *) args; int req = read_int(client); struct ucred credential; @@ -88,7 +88,7 @@ static void *request_handler(void *args) { static void main_daemon() { android_logging(); setsid(); - setcon("u:r:"SEPOL_PROC_DOMAIN":s0"); + setcon("u:r:" SEPOL_PROC_DOMAIN ":s0"); int fd = xopen("/dev/null", O_RDWR | O_CLOEXEC); xdup2(fd, STDOUT_FILENO); xdup2(fd, STDERR_FILENO); @@ -123,7 +123,7 @@ static void main_daemon() { // Loop forever to listen for requests while(1) { - int *client = xmalloc(sizeof(int)); + int *client = new int; *client = xaccept4(fd, NULL, NULL, SOCK_CLOEXEC); pthread_t thread; xpthread_create(&thread, NULL, request_handler, client); diff --git a/native/jni/daemon/db.c b/native/jni/daemon/db.cpp similarity index 87% rename from native/jni/daemon/db.c rename to native/jni/daemon/db.cpp index a2101591a..577c664cf 100644 --- a/native/jni/daemon/db.c +++ b/native/jni/daemon/db.cpp @@ -10,8 +10,8 @@ #define DB_VERSION 7 -static int ver_cb(void *v, int col_num, char **data, char **col_name) { - *((int *) v) = atoi(data[0]); +static int ver_cb(void *ver, int, char **data, char **) { + *((int *) ver) = atoi(data[0]); return 0; } @@ -19,7 +19,7 @@ static int ver_cb(void *v, int col_num, char **data, char **col_name) { if (err) { \ LOGE("sqlite3_exec: %s\n", err); \ sqlite3_free(err); \ - return NULL; \ + return nullptr; \ } static sqlite3 *open_and_init_db() { @@ -27,7 +27,7 @@ static sqlite3 *open_and_init_db() { int ret = sqlite3_open(MAGISKDB, &db); if (ret) { LOGE("sqlite3 open failure: %s\n", sqlite3_errstr(ret)); - return NULL; + return nullptr; } int ver, upgrade = 0; char *err; @@ -36,7 +36,7 @@ static sqlite3 *open_and_init_db() { if (ver > DB_VERSION) { // Don't support downgrading database sqlite3_close_v2(db); - return NULL; + return nullptr; } if (ver < 3) { // Policies @@ -44,20 +44,20 @@ static sqlite3 *open_and_init_db() { "CREATE TABLE IF NOT EXISTS policies " "(uid INT, package_name TEXT, policy INT, until INT, " "logging INT, notification INT, PRIMARY KEY(uid))", - NULL, NULL, &err); + nullptr, nullptr, &err); err_abort(err); // Logs sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS logs " "(from_uid INT, package_name TEXT, app_name TEXT, from_pid INT, " "to_uid INT, action INT, time INT, command TEXT)", - NULL, NULL, &err); + nullptr, nullptr, &err); err_abort(err); // Settings sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS settings " "(key TEXT, value INT, PRIMARY KEY(key))", - NULL, NULL, &err); + nullptr, nullptr, &err); err_abort(err); ver = 3; upgrade = 1; @@ -67,13 +67,13 @@ static sqlite3 *open_and_init_db() { sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS strings " "(key TEXT, value TEXT, PRIMARY KEY(key))", - NULL, NULL, &err); + nullptr, nullptr, &err); err_abort(err); ver = 4; upgrade = 1; } if (ver == 4) { - sqlite3_exec(db, "UPDATE policies SET uid=uid%100000", NULL, NULL, &err); + sqlite3_exec(db, "UPDATE policies SET uid=uid%100000", nullptr, nullptr, &err); err_abort(err); /* Skip version 5 */ ver = 6; @@ -84,7 +84,7 @@ static sqlite3 *open_and_init_db() { sqlite3_exec(db, "CREATE TABLE IF NOT EXISTS hidelist " "(process TEXT, PRIMARY KEY(process))", - NULL, NULL, &err); + nullptr, nullptr, &err); err_abort(err); ver = 7; upgrade =1 ; @@ -94,7 +94,7 @@ static sqlite3 *open_and_init_db() { // Set version char query[32]; sprintf(query, "PRAGMA user_version=%d", ver); - sqlite3_exec(db, query, NULL, NULL, &err); + sqlite3_exec(db, query, nullptr, nullptr, &err); err_abort(err); } return db; @@ -102,7 +102,7 @@ static sqlite3 *open_and_init_db() { sqlite3 *get_magiskdb() { sqlite3 *db = open_and_init_db(); - if (db == NULL) { + if (db == nullptr) { // Open fails, remove and reconstruct unlink(MAGISKDB); db = open_and_init_db(); @@ -111,7 +111,7 @@ sqlite3 *get_magiskdb() { } static int settings_cb(void *v, int col_num, char **data, char **col_name) { - struct db_settings *dbs = v; + auto dbs = (db_settings *) v; int key = -1, value; for (int i = 0; i < col_num; ++i) { if (strcmp(col_name[i], "key") == 0) { @@ -131,7 +131,7 @@ static int settings_cb(void *v, int col_num, char **data, char **col_name) { } int get_db_settings(sqlite3 *db, int key, struct db_settings *dbs) { - if (db == NULL) + if (db == nullptr) return 1; char *err; if (key > 0) { @@ -150,7 +150,7 @@ int get_db_settings(sqlite3 *db, int key, struct db_settings *dbs) { } static int strings_cb(void *v, int col_num, char **data, char **col_name) { - struct db_strings *dbs = v; + auto dbs = (db_strings *) v; int key = -1; char *value; for (int i = 0; i < col_num; ++i) { @@ -171,7 +171,7 @@ static int strings_cb(void *v, int col_num, char **data, char **col_name) { } int get_db_strings(sqlite3 *db, int key, struct db_strings *str) { - if (db == NULL) + if (db == nullptr) return 1; char *err; if (key > 0) { @@ -190,7 +190,7 @@ int get_db_strings(sqlite3 *db, int key, struct db_strings *str) { } static int policy_cb(void *v, int col_num, char **data, char **col_name) { - struct su_access *su = v; + auto su = (su_access *) v; for (int i = 0; i < col_num; i++) { if (strcmp(col_name[i], "policy") == 0) su->policy = (policy_t) atoi(data[i]); @@ -204,11 +204,11 @@ static int policy_cb(void *v, int col_num, char **data, char **col_name) { } int get_uid_policy(sqlite3 *db, int uid, struct su_access *su) { - if (db == NULL) + if (db == nullptr) return 1; char query[256], *err; sprintf(query, "SELECT policy, logging, notification FROM policies " - "WHERE uid=%d AND (until=0 OR until>%li)", uid, time(NULL)); + "WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr)); sqlite3_exec(db, query, policy_cb, su, &err); if (err) { LOGE("sqlite3_exec: %s\n", err); @@ -219,7 +219,7 @@ int get_uid_policy(sqlite3 *db, int uid, struct su_access *su) { } int validate_manager(char *alt_pkg, int userid, struct stat *st) { - if (st == NULL) { + if (st == nullptr) { struct stat stat; st = &stat; } @@ -229,7 +229,7 @@ int validate_manager(char *alt_pkg, int userid, struct stat *st) { sprintf(app_path, "%s/%d/%s", base, userid, alt_pkg[0] ? alt_pkg : "xxx"); if (stat(app_path, st)) { // Check the official package name - sprintf(app_path, "%s/%d/"JAVA_PACKAGE_NAME, base, userid); + sprintf(app_path, "%s/%d/" JAVA_PACKAGE_NAME, base, userid); if (stat(app_path, st)) { LOGE("su: cannot find manager"); memset(st, 0, sizeof(*st)); @@ -256,7 +256,7 @@ int exec_sql(const char *sql) { sqlite3 *db = get_magiskdb(); if (db) { char *err; - sqlite3_exec(db, sql, print_cb, NULL, &err); + sqlite3_exec(db, sql, print_cb, nullptr, &err); sqlite3_close_v2(db); if (err) { fprintf(stderr, "sql_err: %s\n", err); diff --git a/native/jni/daemon/log_daemon.c b/native/jni/daemon/log_daemon.cpp similarity index 78% rename from native/jni/daemon/log_daemon.c rename to native/jni/daemon/log_daemon.cpp index f29bb0887..58d83a33b 100644 --- a/native/jni/daemon/log_daemon.c +++ b/native/jni/daemon/log_daemon.cpp @@ -19,7 +19,7 @@ #include "flags.h" int log_daemon_started = 0; -static struct vector log_cmd, clear_cmd; +static Array log_cmd, clear_cmd; static pthread_mutex_t lock = PTHREAD_MUTEX_INITIALIZER; enum { @@ -33,7 +33,7 @@ struct log_listener { }; static int am_proc_start_filter(const char *log) { - return strstr(log, "am_proc_start") != NULL; + return strstr(log, "am_proc_start") != nullptr; } static int magisk_log_filter(const char *log) { @@ -52,17 +52,17 @@ static struct log_listener events[] = { }; #define EVENT_NUM (sizeof(events) / sizeof(struct log_listener)) -static void sigpipe_handler(int sig) { +static void sigpipe_handler(int) { close(events[HIDE_EVENT].fd); events[HIDE_EVENT].fd = -1; } -static void *monitor_thread(void *args) { +static void *monitor_thread(void *) { // Block SIGPIPE to prevent interruption sigset_t block_set; sigemptyset(&block_set); sigaddset(&block_set, SIGPIPE); - pthread_sigmask(SIG_SETMASK, &block_set, NULL); + pthread_sigmask(SIG_SETMASK, &block_set, nullptr); // Give the main daemon some time before we monitor it sleep(5); int fd; @@ -77,12 +77,12 @@ static void *monitor_thread(void *args) { } } -static void *logcat_thread(void *args) { +static void *logcat_thread(void *) { int log_fd = -1, log_pid; char line[4096]; while (1) { // Start logcat - log_pid = exec_array(0, &log_fd, NULL, (const char **) vec_entry(&log_cmd)); + log_pid = exec_array(0, &log_fd, nullptr, log_cmd.data()); FILE *logs = fdopen(log_fd, "r"); while (fgets(line, sizeof(line), logs)) { if (line[0] == '-') @@ -99,12 +99,12 @@ static void *logcat_thread(void *args) { fclose(logs); log_fd = -1; kill(log_pid, SIGTERM); - waitpid(log_pid, NULL, 0); + waitpid(log_pid, nullptr, 0); LOGI("magisklogd: logcat output EOF"); // Clear buffer - log_pid = exec_array(0, NULL, NULL, (const char **) vec_entry(&clear_cmd)); - waitpid(log_pid, NULL, 0); + log_pid = exec_array(0, nullptr, nullptr, clear_cmd.data()); + waitpid(log_pid, nullptr, 0); } } @@ -117,36 +117,42 @@ static void log_daemon() { struct sigaction act; memset(&act, 0, sizeof(act)); act.sa_handler = sigpipe_handler; - sigaction(SIGPIPE, &act, NULL); + sigaction(SIGPIPE, &act, nullptr); // Setup log dumps rename(LOGFILE, LOGFILE ".bak"); events[LOG_EVENT].fd = xopen(LOGFILE, O_CREAT | O_WRONLY | O_TRUNC | O_CLOEXEC | O_APPEND, 0644); // Construct cmdline - vec_init(&log_cmd); - vec_push_back(&log_cmd, MIRRDIR "/system/bin/logcat"); + log_cmd.push_back(MIRRDIR "/system/bin/logcat"); // Test whether these buffers actually works const char* b[] = { "main", "events", "crash" }; for (int i = 0; i < 3; ++i) { - if (exec_command_sync(MIRRDIR "/system/bin/logcat", "-b", b[i], "-d", "-f", "/dev/null", NULL) == 0) - vec_push_back_all(&log_cmd, "-b", b[i], NULL); + if (exec_command_sync(MIRRDIR "/system/bin/logcat", "-b", b[i], "-d", "-f", "/dev/null", nullptr) == 0) { + log_cmd.push_back("-b"); + log_cmd.push_back(b[i]); + } } chmod("/dev/null", 0666); - vec_dup(&log_cmd, &clear_cmd); - vec_push_back_all(&log_cmd, "-v", "threadtime", "-s", "am_proc_start", "Magisk", NULL); + clear_cmd = log_cmd; + log_cmd.push_back("-v"); + log_cmd.push_back("threadtime"); + log_cmd.push_back("-s"); + log_cmd.push_back("am_proc_start"); + log_cmd.push_back("Magisk"); #ifdef MAGISK_DEBUG - vec_push_back(&log_cmd, "*:F"); + log_cmd.push_back("*:F"); #endif - vec_push_back(&log_cmd, NULL); - vec_push_back(&clear_cmd, "-c"); - vec_push_back(&clear_cmd, NULL); + log_cmd.push_back(nullptr); + + clear_cmd.push_back("-c"); + clear_cmd.push_back(nullptr); // Start worker threads pthread_t thread; - pthread_create(&thread, NULL, monitor_thread, NULL); + pthread_create(&thread, nullptr, monitor_thread, nullptr); pthread_detach(thread); - xpthread_create(&thread, NULL, logcat_thread, NULL); + xpthread_create(&thread, nullptr, logcat_thread, nullptr); pthread_detach(thread); // Handle socket requests @@ -157,7 +163,7 @@ static void log_daemon() { exit(1); xlisten(sockfd, 10); while(1) { - int fd = xaccept4(sockfd, NULL, NULL, SOCK_CLOEXEC); + int fd = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC); switch(read_int(fd)) { case HIDE_CONNECT: pthread_mutex_lock(&lock); @@ -175,7 +181,7 @@ static void log_daemon() { int start_log_daemon() { if (!log_daemon_started) { - if (exec_command_sync(MIRRDIR "/system/bin/logcat", "-d", "-f", "/dev/null", NULL) == 0) { + if (exec_command_sync(MIRRDIR "/system/bin/logcat", "-d", "-f", "/dev/null", nullptr) == 0) { if (fork_dont_care() == 0) log_daemon(); log_daemon_started = 1; diff --git a/native/jni/daemon/magisk.c b/native/jni/daemon/magisk.cpp similarity index 99% rename from native/jni/daemon/magisk.c rename to native/jni/daemon/magisk.cpp index 6520f3727..ac9489613 100644 --- a/native/jni/daemon/magisk.c +++ b/native/jni/daemon/magisk.cpp @@ -26,7 +26,7 @@ static int create_links(const char *bin, const char *path) { return ret; } -static void usage() { +[[noreturn]] static void usage() { fprintf(stderr, "Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) multi-call binary\n" "\n" @@ -117,5 +117,4 @@ int magisk_main(int argc, char *argv[]) { } usage(); - return 1; } diff --git a/native/jni/daemon/socket.c b/native/jni/daemon/socket.cpp similarity index 96% rename from native/jni/daemon/socket.c rename to native/jni/daemon/socket.cpp index 9456c2fe7..3ad18eff9 100644 --- a/native/jni/daemon/socket.c +++ b/native/jni/daemon/socket.cpp @@ -50,6 +50,7 @@ int socket_accept(int sockfd, int timeout) { int recv_fd(int sockfd) { // Need to receive data from the message, otherwise don't care about it. char iovbuf; + struct cmsghdr *cmsg; struct iovec iov = { .iov_base = &iovbuf, @@ -79,7 +80,7 @@ int recv_fd(int sockfd) { goto error; } - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + cmsg = CMSG_FIRSTHDR(&msg); if (cmsg == NULL || cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || @@ -104,8 +105,9 @@ error: */ void send_fd(int sockfd, int fd) { // Need to send some data in the message, this will do. + char junk[] = { '\0' }; struct iovec iov = { - .iov_base = "", + .iov_base = junk, .iov_len = 1, }; @@ -166,7 +168,7 @@ void write_int_be(int fd, int val) { } static char *rd_str(int fd, int len) { - char* val = xmalloc(sizeof(char) * (len + 1)); + char *val = (char *) xmalloc(sizeof(char) * (len + 1)); xxread(fd, val, len); val[len] = '\0'; return val; diff --git a/native/jni/include/db.h b/native/jni/include/db.h index 3aedf2fee..b2ef566fb 100644 --- a/native/jni/include/db.h +++ b/native/jni/include/db.h @@ -4,10 +4,6 @@ #include #include -#ifdef __cplusplus -extern "C" { -#endif - /*************** * DB Settings * ***************/ @@ -19,7 +15,7 @@ extern "C" { "mnt_ns" \ }) -#define DB_SETTINGS_NUM (sizeof(DB_SETTING_KEYS) / sizeof(char*)) +#define DB_SETTINGS_NUM 3 // Settings indices enum { @@ -52,15 +48,14 @@ enum { struct db_settings { int v[DB_SETTINGS_NUM]; + db_settings() + : v { + ROOT_ACCESS_APPS_AND_ADB, + MULTIUSER_MODE_OWNER_ONLY, + NAMESPACE_MODE_REQUESTER + } {} }; -#define DEFAULT_DB_SETTINGS \ -(struct db_settings) { .v = { \ -ROOT_ACCESS_APPS_AND_ADB, \ -MULTIUSER_MODE_OWNER_ONLY, \ -NAMESPACE_MODE_REQUESTER, \ -}} - /************** * DB Strings * **************/ @@ -70,7 +65,7 @@ NAMESPACE_MODE_REQUESTER, \ "requester", \ }) -#define DB_STRING_NUM (sizeof(DB_STRING_KEYS) / sizeof(char*)) +#define DB_STRING_NUM 1 // Strings indices enum { @@ -79,6 +74,10 @@ enum { struct db_strings { char s[DB_STRING_NUM][128]; + db_strings() { + for (int i = 0; i < DB_STRING_NUM; ++i) + s[i][0] = '\0'; + } }; /************* @@ -97,19 +96,19 @@ struct su_access { int notify; }; -#define DEFAULT_SU_ACCESS (struct su_access) { \ +#define DEFAULT_SU_ACCESS (su_access) { \ .policy = QUERY, \ .log = 1, \ .notify = 1 \ } -#define SILENT_SU_ACCESS (struct su_access) { \ +#define SILENT_SU_ACCESS (su_access) { \ .policy = ALLOW, \ .log = 0, \ .notify = 0 \ } -#define NO_SU_ACCESS (struct su_access) { \ +#define NO_SU_ACCESS (su_access) { \ .policy = DENY, \ .log = 0, \ .notify = 0 \ @@ -126,8 +125,4 @@ 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/img.h b/native/jni/include/img.h index 089b9b2c1..e48281612 100644 --- a/native/jni/include/img.h +++ b/native/jni/include/img.h @@ -1,6 +1,10 @@ #ifndef IMG_H #define IMG_H +#ifdef __cplusplus +extern "C" { +#endif + int create_img(const char *img, int size); int resize_img(const char *img, int size); char *mount_image(const char *img, const char *target); @@ -8,4 +12,8 @@ int umount_image(const char *target, const char *device); int merge_img(const char *source, const char *target); int trim_img(const char *img, const char *mount, char *loop); +#ifdef __cplusplus +} +#endif + #endif //IMG_H diff --git a/native/jni/include/magisk.h b/native/jni/include/magisk.h index 30115a9a2..6909f39f3 100644 --- a/native/jni/include/magisk.h +++ b/native/jni/include/magisk.h @@ -45,8 +45,8 @@ extern "C" { extern char *argv0; /* For changing process name */ -#define applet_names ((char *[]) { "magisk", "su", "resetprop", "magiskhide", "imgtool", NULL }) -#define init_applet ((char *[]) { "magiskpolicy", "supolicy", NULL }) +#define applet_names ((const char *[]) { "magisk", "su", "resetprop", "magiskhide", "imgtool", NULL }) +#define init_applet ((const char *[]) { "magiskpolicy", "supolicy", NULL }) extern int (*applet_main[]) (int, char *[]), (*init_applet_main[]) (int, char *[]); diff --git a/native/jni/include/resetprop.h b/native/jni/include/resetprop.h index 817403d25..eaad8733f 100644 --- a/native/jni/include/resetprop.h +++ b/native/jni/include/resetprop.h @@ -1,25 +1,12 @@ /* resetprop.h - API for resetprop */ -#ifndef _RESETPROP_H_ -#define _RESETPROP_H_ - -#ifdef __cplusplus -extern "C" { -#endif +#pragma once 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); -char *getprop(const char *name); -char *getprop2(const char *name, int persist); -int deleteprop(const char *name); -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, int persist); +int setprop(const char *name, const char *value, const bool trigger = true); +char *getprop(const char *name, bool persist = false); +void getprop(void (*callback)(const char *, const char *, void *), void *cookie, bool persist = false); +int deleteprop(const char *name, bool persist = false); +int load_prop_file(const char *filename, const bool trigger = true); -#ifdef __cplusplus -} -#endif - -#endif diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index f383190cb..734390a62 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -51,7 +51,7 @@ void hide_sensitive_props() { value = getprop(prop_key[i]); if (value) { if (strcmp(value, prop_value[i]) != 0) - setprop2(prop_key[i], prop_value[i], 0); + setprop(prop_key[i], prop_value[i], false); free(value); } } @@ -133,10 +133,10 @@ static void kill_process(const char *name) { void clean_magisk_props() { LOGD("hide_utils: Cleaning magisk props\n"); - getprop_all([](const char *name, auto, auto) -> void { + getprop([](const char *name, auto, auto) -> void { if (strstr(name, "magisk")) - deleteprop2(name, 0); - }, nullptr, 0); + deleteprop(name); + }, nullptr, false); } static int add_list(sqlite3 *db, char *proc) { diff --git a/native/jni/magiskhide/magiskhide.cpp b/native/jni/magiskhide/magiskhide.cpp index 1e3177f8f..4b55ba1f2 100644 --- a/native/jni/magiskhide/magiskhide.cpp +++ b/native/jni/magiskhide/magiskhide.cpp @@ -39,14 +39,14 @@ int launch_magiskhide() { if (!log_daemon_started) { setprop(MAGISKHIDE_PROP, "0"); // Remove without actually removing persist props - deleteprop2(MAGISKHIDE_PROP, 0); + deleteprop(MAGISKHIDE_PROP); return LOGCAT_DISABLED; } hide_enabled = 1; LOGI("* Starting MagiskHide\n"); - deleteprop2(MAGISKHIDE_PROP, 1); + deleteprop(MAGISKHIDE_PROP, true); hide_sensitive_props(); @@ -77,7 +77,7 @@ int stop_magiskhide() { hide_enabled = 0; setprop(MAGISKHIDE_PROP, "0"); // Remove without actually removing persist props - deleteprop2(MAGISKHIDE_PROP, 0); + deleteprop(MAGISKHIDE_PROP); pthread_kill(proc_monitor_thread, TERM_THREAD); return DAEMON_SUCCESS; diff --git a/native/jni/magiskhide/magiskhide.h b/native/jni/magiskhide/magiskhide.h index 53a0e9c56..288776818 100644 --- a/native/jni/magiskhide/magiskhide.h +++ b/native/jni/magiskhide/magiskhide.h @@ -9,9 +9,7 @@ #define TERM_THREAD SIGUSR1 // Daemon entries -extern "C" { int launch_magiskhide(); -} int stop_magiskhide(); int add_list(int client); int rm_list(int client); diff --git a/native/jni/misc/applets.c b/native/jni/misc/applets.cpp similarity index 100% rename from native/jni/misc/applets.c rename to native/jni/misc/applets.cpp diff --git a/native/jni/misc/img.c b/native/jni/misc/img.cpp similarity index 99% rename from native/jni/misc/img.c rename to native/jni/misc/img.cpp index ab3d90b51..573b2532f 100644 --- a/native/jni/misc/img.c +++ b/native/jni/misc/img.cpp @@ -1,4 +1,4 @@ -/* img.c - All image related functions +/* img.cpp - All image related functions */ #include diff --git a/native/jni/resetprop/resetprop.cpp b/native/jni/resetprop/resetprop.cpp index d2c32e9d8..bd455cfab 100644 --- a/native/jni/resetprop/resetprop.cpp +++ b/native/jni/resetprop/resetprop.cpp @@ -112,9 +112,9 @@ static int init_resetprop() { return 0; } -static void print_props(int persist) { +static void print_props(bool persist) { auto prop_list = Array(); - getprop_all(collect_props, &prop_list, persist); + getprop(collect_props, &prop_list, persist); prop_list.sort(); for (auto &prop : prop_list) printf("[%s]: [%s]\n", prop.name, prop.value); @@ -129,12 +129,8 @@ int prop_exist(const char *name) { return __system_property_find(name) != nullptr; } -char *getprop(const char *name) { - return getprop2(name, 0); -} - // Get prop by name, return string (should free manually!) -char *getprop2(const char *name, int persist) { +char *getprop(const char *name, bool persist) { if (!check_legal_property_name(name) || init_resetprop()) return nullptr; const prop_info *pi = __system_property_find(name); @@ -157,7 +153,7 @@ char *getprop2(const char *name, int persist) { } } -void getprop_all(void (*callback)(const char *, const char *, void *), void *cookie, int persist) { +void getprop(void (*callback)(const char *, const char *, void *), void *cookie, bool persist) { if (init_resetprop()) return; read_cb_t read_cb(callback, cookie); __system_property_foreach(read_props, &read_cb); @@ -167,11 +163,7 @@ void getprop_all(void (*callback)(const char *, const char *, void *), void *coo } } -int setprop(const char *name, const char *value) { - return setprop2(name, value, 1); -} - -int setprop2(const char *name, const char *value, const int trigger) { +int setprop(const char *name, const char *value, const bool trigger) { if (!check_legal_property_name(name)) return 1; if (init_resetprop()) @@ -205,11 +197,7 @@ int setprop2(const char *name, const char *value, const int trigger) { return ret; } -int deleteprop(const char *name) { - return deleteprop2(name, 1); -} - -int deleteprop2(const char *name, int persist) { +int deleteprop(const char *name, bool persist) { if (!check_legal_property_name(name)) return 1; if (init_resetprop()) return -1; @@ -221,7 +209,7 @@ int deleteprop2(const char *name, int persist) { return __system_property_del(name) && !(persist && strncmp(name, "persist.", 8) == 0); } -int read_prop_file(const char* filename, const int trigger) { +int load_prop_file(const char *filename, const bool trigger) { if (init_resetprop()) return -1; LOGD("resetprop: Load prop file [%s]\n", filename); FILE *fp = fopen(filename, "r"); @@ -255,7 +243,7 @@ int read_prop_file(const char* filename, const int trigger) { if ( ((pch == nullptr) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue; // Separate the string *pch = '\0'; - setprop2(line + i, pch + 1, trigger); + setprop(line + i, pch + 1, trigger); } free(line); fclose(fp); @@ -264,8 +252,8 @@ int read_prop_file(const char* filename, const int trigger) { int resetprop_main(int argc, char *argv[]) { log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; }; - - int trigger = 1, persist = 0; + + bool trigger = true, persist = false; char *argv0 = argv[0], *prop; --argc; @@ -277,9 +265,9 @@ int resetprop_main(int argc, char *argv[]) { switch (argv[0][idx]) { case '-': if (strcmp(argv[0], "--file") == 0 && argc == 2) { - return read_prop_file(argv[1], trigger); + return load_prop_file(argv[1], trigger); } else if (strcmp(argv[0], "--delete") == 0 && argc == 2) { - return deleteprop2(argv[1], persist); + return deleteprop(argv[1], persist); } else if (strcmp(argv[0], "--help") == 0) { usage(argv0); } @@ -309,13 +297,13 @@ int resetprop_main(int argc, char *argv[]) { print_props(persist); return 0; case 1: - prop = getprop2(argv[0], persist); + prop = getprop(argv[0], persist); if (prop == nullptr) return 1; printf("%s\n", prop); free(prop); return 0; case 2: - return setprop2(argv[0], argv[1], trigger); + return setprop(argv[0], argv[1], trigger); default: usage(argv0); } diff --git a/native/jni/su/connect.c b/native/jni/su/connect.cpp similarity index 91% rename from native/jni/su/connect.c rename to native/jni/su/connect.cpp index ff08a3e91..6bdb5a3ff 100644 --- a/native/jni/su/connect.c +++ b/native/jni/su/connect.cpp @@ -19,7 +19,7 @@ #define AM_PATH "/system/bin/app_process", "/system/bin", "com.android.commands.am.Am" -static char *get_command(const struct su_request *to) { +static const char *get_command(const struct su_request *to) { if (to->command[0]) return to->command; if (to->shell[0]) @@ -27,7 +27,7 @@ static char *get_command(const struct su_request *to) { return DEFAULT_SHELL; } -static void silent_run(char * const args[]) { +static void silent_run(const char *args[]) { if (fork_dont_care()) return; int zero = open("/dev/zero", O_RDONLY | O_CLOEXEC); @@ -36,7 +36,7 @@ static void silent_run(char * const args[]) { xdup2(null, 1); xdup2(null, 2); setenv("CLASSPATH", "/system/framework/am.jar", 1); - execv(args[0], args); + execv(args[0], (char **) args); PLOGE("exec am"); _exit(EXIT_FAILURE); } @@ -71,7 +71,7 @@ void app_log(struct su_context *ctx) { char policy[2]; sprintf(policy, "%d", ctx->info->access.policy); - char *cmd[] = { + const char *cmd[] = { AM_PATH, "broadcast", "-a", "android.intent.action.BOOT_COMPLETED", "-p", DB_STR(ctx->info, SU_MANAGER), @@ -84,7 +84,7 @@ void app_log(struct su_context *ctx) { "--ei", "policy", policy, "--es", "command", get_command(&ctx->req), "--ez", "notify", ctx->info->access.notify ? "true" : "false", - NULL + nullptr }; silent_run(cmd); } @@ -101,7 +101,7 @@ void app_notify(struct su_context *ctx) { char policy[2]; sprintf(policy, "%d", ctx->info->access.policy); - char *cmd[] = { + const char *cmd[] = { AM_PATH, "broadcast", "-a", "android.intent.action.BOOT_COMPLETED", "-p", DB_STR(ctx->info, SU_MANAGER), @@ -110,7 +110,7 @@ void app_notify(struct su_context *ctx) { "--es", "action", "notify", "--ei", "from.uid", fromUid, "--ei", "policy", policy, - NULL + nullptr }; silent_run(cmd); } @@ -118,15 +118,15 @@ void app_notify(struct su_context *ctx) { void app_connect(const char *socket, struct su_info *info) { char user[8]; setup_user(user, info); - char *cmd[] = { + const char *cmd[] = { AM_PATH, "broadcast", "-a", "android.intent.action.BOOT_COMPLETED", "-p", DB_STR(info, SU_MANAGER), "-f", "0x00000020", "--user", user, "--es", "action", "request", - "--es", "socket", (char *) socket, - NULL + "--es", "socket", socket, + nullptr }; silent_run(cmd); } @@ -135,4 +135,3 @@ void socket_send_request(int fd, struct su_info *info) { write_key_token(fd, "uid", info->uid); write_string_be(fd, "eof"); } - diff --git a/native/jni/su/pts.c b/native/jni/su/pts.cpp similarity index 99% rename from native/jni/su/pts.c rename to native/jni/su/pts.cpp index e9d4d60fc..9a480b770 100644 --- a/native/jni/su/pts.c +++ b/native/jni/su/pts.cpp @@ -9,7 +9,6 @@ * helper functions to handle raw input mode and terminal window resizing */ -#define _GNU_SOURCE #include #include #include diff --git a/native/jni/su/su.c b/native/jni/su/su.cpp similarity index 94% rename from native/jni/su/su.c rename to native/jni/su/su.cpp index 018e22140..09dee5980 100644 --- a/native/jni/su/su.c +++ b/native/jni/su/su.cpp @@ -8,7 +8,6 @@ /* su.c - The main function running in the daemon */ -#define _GNU_SOURCE #include #include #include @@ -95,6 +94,12 @@ static void setup_sighandlers(void (*handler)(int)) { } } +// Default values +su_req_base::su_req_base() + : uid(UID_ROOT), login(false), keepenv(false), mount_master(false) {} +su_request::su_request() + : shell(DEFAULT_SHELL), command("") {} + /* * Connect daemon, send argc, argv, cwd, pts slave */ @@ -112,15 +117,7 @@ int su_client_main(int argc, char *argv[]) { { NULL, 0, NULL, 0 }, }; - struct su_request su_req = { - .uid = UID_ROOT, - .login = 0, - .keepenv = 0, - .mount_master = 0, - .shell = DEFAULT_SHELL, - .command = "", - }; - + su_request su_req; for (int i = 0; i < argc; i++) { // Replace -cn with -z, -mm with -M for supporting getopt_long @@ -140,11 +137,11 @@ int su_client_main(int argc, char *argv[]) { usage(EXIT_SUCCESS); break; case 'l': - su_req.login = 1; + su_req.login = true; break; case 'm': case 'p': - su_req.keepenv = 1; + su_req.keepenv = true; break; case 's': su_req.shell = optarg; @@ -159,7 +156,7 @@ int su_client_main(int argc, char *argv[]) { // Do nothing, placed here for legacy support :) break; case 'M': - su_req.mount_master = 1; + su_req.mount_master = true; break; default: /* Bionic getopt_long doesn't terminate its error output by newline */ @@ -169,7 +166,7 @@ int su_client_main(int argc, char *argv[]) { } if (optind < argc && strcmp(argv[optind], "-") == 0) { - su_req.login = 1; + su_req.login = true; optind++; } /* username or uid */ @@ -200,7 +197,7 @@ int su_client_main(int argc, char *argv[]) { } // Send su_request - xwrite(fd, &su_req, 4 * sizeof(unsigned)); + xwrite(fd, &su_req, sizeof(su_req_base)); write_string(fd, su_req.shell); write_string(fd, su_req.command); @@ -242,4 +239,4 @@ int su_client_main(int argc, char *argv[]) { close(fd); return code; -} \ No newline at end of file +} diff --git a/native/jni/su/su.h b/native/jni/su/su.h index 6244803ac..c829d8662 100644 --- a/native/jni/su/su.h +++ b/native/jni/su/su.h @@ -17,9 +17,9 @@ #define ATTY_OUT 2 #define ATTY_ERR 4 -struct su_info { +class su_info { +public: unsigned uid; /* Unique key to find su_info */ - pthread_mutex_t lock; /* Internal lock */ int count; /* Just a count for debugging purpose */ /* These values should be guarded with internal lock */ @@ -31,19 +31,33 @@ struct su_info { /* These should be guarded with global cache lock */ int ref; int life; + + su_info(unsigned uid); + ~su_info(); + void lock(); + void unlock(); + +private: + pthread_mutex_t _lock; /* Internal lock */ }; #define DB_SET(i, e) (i)->dbs.v[e] #define DB_STR(i, e) (i)->str.s[e] -struct su_request { +struct su_req_base { unsigned uid; - unsigned login; - unsigned keepenv; - unsigned mount_master; - char *shell; - char *command; -}; + bool login; + bool keepenv; + bool mount_master; +protected: + su_req_base(); +} __attribute__((packed)); + +struct su_request : public su_req_base { + const char *shell; + const char *command; + su_request(); +} __attribute__((packed)); struct su_context { struct su_info *info; diff --git a/native/jni/su/su_daemon.c b/native/jni/su/su_daemon.cpp similarity index 89% rename from native/jni/su/su_daemon.c rename to native/jni/su/su_daemon.cpp index b37bba858..685c3bb44 100644 --- a/native/jni/su/su_daemon.c +++ b/native/jni/su/su_daemon.cpp @@ -1,8 +1,3 @@ -/* su_daemon.c - The entrypoint for su, connect to daemon and send correct info - */ - -#define _GNU_SOURCE - #include #include #include @@ -25,32 +20,45 @@ #define TIMEOUT 3 #define LOCK_CACHE() pthread_mutex_lock(&cache_lock) -#define LOCK_INFO() pthread_mutex_lock(&info->lock) #define UNLOCK_CACHE() pthread_mutex_unlock(&cache_lock) -#define UNLOCK_INFO() pthread_mutex_unlock(&info->lock) static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; -static struct su_info *cache; +static su_info *cache; + +su_info::su_info(unsigned uid) : + uid(uid), access(DEFAULT_SU_ACCESS), _lock(PTHREAD_MUTEX_INITIALIZER), + count(0), ref(0), life(0), mgr_st({}) {} + +su_info::~su_info() { + pthread_mutex_destroy(&_lock); +} + +void su_info::lock() { + pthread_mutex_lock(&_lock); +} + +void su_info::unlock() { + pthread_mutex_unlock(&_lock); +} static void *info_collector(void *node) { - struct su_info *info = node; + su_info *info = (su_info *) node; while (1) { sleep(1); if (info->life) { LOCK_CACHE(); if (--info->life == 0 && cache && info->uid == cache->uid) - cache = NULL; + cache = nullptr; UNLOCK_CACHE(); } if (!info->life && !info->ref) { - pthread_mutex_destroy(&info->lock); - free(info); - return NULL; + delete info; + return nullptr; } } } -static void database_check(struct su_info *info) { +static void database_check(su_info *info) { int uid = info->uid; sqlite3 *db = get_magiskdb(); if (db) { @@ -84,20 +92,16 @@ static void database_check(struct su_info *info) { } static struct su_info *get_su_info(unsigned uid) { - struct su_info *info; - int cache_miss = 0; + su_info *info; + bool cache_miss = false; LOCK_CACHE(); if (cache && cache->uid == uid) { info = cache; } else { - cache_miss = 1; - info = xcalloc(1, sizeof(*info)); - info->uid = uid; - info->dbs = DEFAULT_DB_SETTINGS; - info->access = DEFAULT_SU_ACCESS; - pthread_mutex_init(&info->lock, NULL); + cache_miss = true; + info = new su_info(uid); cache = info; } @@ -108,7 +112,7 @@ static struct su_info *get_su_info(unsigned uid) { // Start a thread to maintain the cache if (cache_miss) { pthread_t thread; - xpthread_create(&thread, NULL, info_collector, info); + xpthread_create(&thread, nullptr, info_collector, info); pthread_detach(thread); } @@ -117,7 +121,7 @@ static struct su_info *get_su_info(unsigned uid) { LOGD("su: request from uid=[%d] (#%d)\n", info->uid, ++info->count); // Lock before the policy is determined - LOCK_INFO(); + info->lock(); if (info->access.policy == QUERY) { // Not cached, get data from database @@ -173,14 +177,14 @@ static struct su_info *get_su_info(unsigned uid) { } else { socket_send_request(fd, info); int ret = read_int_be(fd); - info->access.policy = ret < 0 ? DENY : ret; + info->access.policy = ret < 0 ? DENY : static_cast(ret); close(fd); } close(sockfd); } // Unlock - UNLOCK_INFO(); + info->unlock(); return info; } @@ -224,7 +228,7 @@ static void set_identity(unsigned uid) { void su_daemon_handler(int client, struct ucred *credential) { LOGD("su: request from client: %d\n", client); - struct su_info *info = get_su_info(credential->uid); + su_info *info = get_su_info(credential->uid); // Fail fast if (info->access.policy == DENY && DB_STR(info, SU_MANAGER)[0] == '\0') { @@ -289,7 +293,7 @@ void su_daemon_handler(int client, struct ucred *credential) { } // Read su_request - xxread(client, &ctx.req, 4 * sizeof(unsigned)); + xxread(client, &ctx.req, sizeof(su_req_base)); ctx.req.shell = read_string(client); ctx.req.command = read_string(client); @@ -367,7 +371,7 @@ void su_daemon_handler(int client, struct ucred *credential) { app_notify(&ctx); if (info->access.policy == ALLOW) { - char* argv[] = { NULL, NULL, NULL, NULL }; + const char *argv[] = { nullptr, nullptr, nullptr, nullptr }; argv[0] = ctx.req.login ? "-" : ctx.req.shell; @@ -381,7 +385,7 @@ void su_daemon_handler(int client, struct ucred *credential) { populate_environment(&ctx.req); set_identity(ctx.req.uid); - execvp(ctx.req.shell, argv); + execvp(ctx.req.shell, (char **) argv); fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell, strerror(errno)); PLOGE("exec"); exit(EXIT_FAILURE); @@ -391,4 +395,3 @@ void su_daemon_handler(int client, struct ucred *credential) { exit(EXIT_FAILURE); } } - diff --git a/native/jni/utils/Android.mk b/native/jni/utils/Android.mk index 85c2a88f5..55d56c734 100644 --- a/native/jni/utils/Android.mk +++ b/native/jni/utils/Android.mk @@ -9,7 +9,6 @@ LOCAL_SRC_FILES := \ selinux.cpp \ logging.cpp \ xwrap.cpp \ - vector.c \ - legacy.c + vector.c include $(BUILD_STATIC_LIBRARY) diff --git a/native/jni/utils/include/array.h b/native/jni/utils/include/array.h index 9ad47aa5e..d296895e1 100644 --- a/native/jni/utils/include/array.h +++ b/native/jni/utils/include/array.h @@ -66,6 +66,15 @@ public: T* _node; }; + T& operator = (const T& a) { + _size = a._size; + _capacity = a._capacity; + _data = new T[_capacity]; + for(int i = 0; i < _size; ++i) + _data[i] = (T&&) a[i]; + return *this; + } + iterator begin() const { return iterator(_data); } iterator end() const { return iterator(_data + _size); } @@ -149,7 +158,8 @@ private: _capacity *= 2; T* temp = _data; _data = new T[_capacity]; - for(int i = 0; i < _size; ++i) _data[i] = (T&&) temp[i]; + for(int i = 0; i < _size; ++i) + _data[i] = (T&&) temp[i]; delete [] temp; } }; diff --git a/native/jni/utils/include/selinux.h b/native/jni/utils/include/selinux.h index 73389611b..41ad7aa80 100644 --- a/native/jni/utils/include/selinux.h +++ b/native/jni/utils/include/selinux.h @@ -4,7 +4,6 @@ extern "C" { #endif - extern void (*freecon)(char * con); extern int (*setcon)(const char * con); extern int (*getfilecon)(const char *path, char ** con); diff --git a/native/jni/utils/include/utils.h b/native/jni/utils/include/utils.h index b2da22d2a..c9f4aaed8 100644 --- a/native/jni/utils/include/utils.h +++ b/native/jni/utils/include/utils.h @@ -18,8 +18,6 @@ int file_to_array(const char* filename, Array &arr); extern "C" { #endif -#include "vector.h" - #define UID_SHELL (get_shell_uid()) #define UID_ROOT 0 #define UID_SYSTEM (get_system_uid()) @@ -86,8 +84,6 @@ int xpoll(struct pollfd *fds, nfds_t nfds, int timeout); unsigned get_shell_uid(); unsigned get_system_uid(); unsigned get_radio_uid(); -int file_to_vector(const char* filename, struct vector *v); -int vector_to_file(const char* filename, struct vector *v); ssize_t fdgets(char *buf, size_t size, int fd); int is_num(const char *s); int exec_array(int err, int *fd, void (*cb)(void), const char *argv[]); diff --git a/native/jni/utils/legacy.c b/native/jni/utils/legacy.c deleted file mode 100644 index 2207cc3b5..000000000 --- a/native/jni/utils/legacy.c +++ /dev/null @@ -1,41 +0,0 @@ -#include -#include -#include - -#include "utils.h" -#include "logging.h" - -/* All the string should be freed manually!! */ -int file_to_vector(const char* filename, struct vector *v) { - 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'; - vec_push_back(v, line); - line = NULL; - } - fclose(fp); - return 0; -} - -int vector_to_file(const char *filename, struct vector *v) { - FILE *fp = xfopen(filename, "w"); - if (fp == NULL) - return 1; - char *line; - vec_for_each(v, line) { - fprintf(fp, "%s\n", line); - } - fclose(fp); - return 0; -} \ No newline at end of file