From e16d604d0d6afc8ace0ee02b696de97ee17fc00f Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Mon, 1 May 2017 01:58:52 +0800 Subject: [PATCH] Implement Magic Mount --- jni/Android.mk | 4 +- jni/daemon/bootstages.c | 494 +++++++++++++++++++++++++++++++++++ jni/daemon/daemon.c | 17 +- jni/daemon/late_start.c | 23 -- jni/daemon/post_fs.c | 21 -- jni/daemon/post_fs_data.c | 84 ------ jni/magisk.h | 11 +- jni/magiskboot/cpio.c | 2 +- jni/magiskhide/magiskhide.c | 6 +- jni/magiskhide/magiskhide.h | 2 - jni/magiskhide/pre_process.c | 6 +- jni/magiskpolicy | 2 +- jni/main.c | 20 +- jni/resetprop/resetprop.cpp | 10 +- jni/resetprop/resetprop.h | 3 +- jni/utils/misc.c | 58 ++-- jni/utils/utils.h | 5 +- jni/utils/vector.h | 8 +- jni/utils/xwrap.c | 8 +- 19 files changed, 581 insertions(+), 203 deletions(-) create mode 100644 jni/daemon/bootstages.c delete mode 100644 jni/daemon/late_start.c delete mode 100644 jni/daemon/post_fs.c delete mode 100644 jni/daemon/post_fs_data.c diff --git a/jni/Android.mk b/jni/Android.mk index bfb0c78a3..ef67f5f48 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -22,9 +22,7 @@ LOCAL_SRC_FILES := \ daemon/daemon.c \ daemon/socket_trans.c \ daemon/log_monitor.c \ - daemon/post_fs.c \ - daemon/post_fs_data.c \ - daemon/late_start.c \ + daemon/bootstages.c \ magiskhide/magiskhide.c \ magiskhide/hide_daemon.c \ magiskhide/proc_monitor.c \ diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c new file mode 100644 index 000000000..f232dbe68 --- /dev/null +++ b/jni/daemon/bootstages.c @@ -0,0 +1,494 @@ +/* post_fs_data.c - post-fs-data actions + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "magisk.h" +#include "utils.h" +#include "daemon.h" +#include "resetprop.h" + +static char *buf, *buf2; +static struct vector module_list; + +/****************** + * Node structure * + ******************/ + +#define DO_NOTHING 0x0 /* intermediate node */ + +#define IS_MODULE 0x1 /* mount from module */ +#define IS_DUMMY 0x2 /* mount from mirror */ +#define IS_SKEL 0x4 /* mount from skeleton */ + +struct node_entry { + const char *module; + char *name; + uint8_t type; + uint8_t status; + struct node_entry *parent; + struct vector *children; +}; + +/****************** + * Image handling * + ******************/ + +static char *loopsetup(const char *img) { + char device[20]; + struct loop_info64 info; + int i, lfd, ffd; + memset(&info, 0, sizeof(info)); + // First get an empty loop device + for (i = 0; i <= 7; ++i) { + sprintf(device, "/dev/block/loop%d", i); + lfd = xopen(device, O_RDWR); + if (ioctl(lfd, LOOP_GET_STATUS64, &info) == -1) + break; + close(lfd); + } + if (i == 8) return NULL; + ffd = xopen(img, O_RDWR); + if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) + return NULL; + strcpy((char *) info.lo_file_name, img); + ioctl(lfd, LOOP_SET_STATUS64, &info); + return strdup(device); +} + +static char *mount_image(const char *img, const char *target) { + char *device = loopsetup(img); + if (device) + xmount(device, target, "ext4", 0, NULL); + return device; +} + +/*********** + * Scripts * + ***********/ + +void exec_common_script(const char* stage) { + DIR *dir; + struct dirent *entry; + snprintf(buf, PATH_MAX, "/magisk/.core/%s.d", stage); + + if (!(dir = opendir(buf))) + return; + + while ((entry = xreaddir(dir))) { + if (entry->d_type == DT_REG) { + snprintf(buf, PATH_MAX, "%s/%s", buf, entry->d_name); + if (access(buf, X_OK) == -1) + continue; + LOGI("%s.d: exec [%s]\n", stage, entry->d_name); + char *const command[] = { "sh", buf, NULL }; + int pid = run_command(NULL, "/system/bin/sh", command); + if (pid != -1) + waitpid(pid, NULL, 0); + } + } + + closedir(dir); +} + +void exec_module_script(const char* stage) { + char *module; + vec_for_each(&module_list, module) { + snprintf(buf, PATH_MAX, "/magisk/%s/%s.sh", module, stage); + if (access(buf, F_OK) == -1) + continue; + LOGI("%s: exec [%s.sh]\n", module, stage); + char *const command[] = { "sh", buf, NULL }; + int pid = run_command(NULL, "/system/bin/sh", command); + if (pid != -1) + waitpid(pid, NULL, 0); + } + +} + +/*************** + * Magic Mount * + ***************/ + +static int hasChild(struct node_entry *node, const char *name) { + struct node_entry *child; + vec_for_each(node->children, child) { + if (strcmp(child->name, name) == 0) + return 1; + } + return 0; +} + +static char *get_full_path(struct node_entry *node) { + char buffer[PATH_MAX], temp[PATH_MAX]; + // Concat the paths + struct node_entry *cur = node; + strcpy(buffer, node->name); + while (cur->parent) { + strcpy(temp, buffer); + snprintf(buffer, sizeof(buffer), "%s/%s", cur->parent->name, temp); + cur = cur->parent; + } + return strdup(buffer); +} + +static void destroy_subtree(struct node_entry *node) { + // Never free parent, since it shall be freed by themselves + free(node->name); + struct node_entry *e; + vec_for_each(node->children, e) { + destroy_subtree(e); + } + vec_destroy(node->children); + free(node->children); + free(node); +} + +static void 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, replace + destroy_subtree(e); + vec_entry(p->children)[_] = c; + return; + } + } + // New entry, push back + vec_push_back(p->children, c); +} + +static void construct_tree(const char *module, const char *path, struct node_entry *parent) { + DIR *dir; + struct dirent *entry; + struct node_entry *node; + + snprintf(buf, PATH_MAX, "/magisk/%s/%s", module, path); + + if (!(dir = xopendir(buf))) + return; + + 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; + insert_child(parent, node); + char *real_path = get_full_path(node); + // Check if the entry has a correspond target + if (entry->d_type == DT_LNK || access(real_path, F_OK) == -1) { + // Mark the parent folder as a skeleton + parent->status = IS_SKEL; + node->status = IS_MODULE; + } else { + if (entry->d_type == DT_DIR) { + // Check if marked as replace + snprintf(buf, PATH_MAX, "/magisk/%s/%s/%s/.replace", module, path, entry->d_name); + if (access(buf, F_OK) == 0) { + // Replace everything, mark as leaf + node->status = IS_MODULE; + } else { + // Travel deeper + snprintf(buf, PATH_MAX, "%s/%s", path, entry->d_name); + char *new_path = strdup(buf); + construct_tree(module, new_path, node); + free(new_path); + } + } else if (entry->d_type == DT_REG) { + // This is a leaf, mark as target + node->status = IS_MODULE; + } + } + free(real_path); + } + + closedir(dir); +} + +static void clone_skeleton(struct node_entry *node, const char *real_path) { + DIR *dir; + struct dirent *entry; + struct node_entry *dummy, *child; + + // Clone the structure + dir = xopendir(real_path); + while ((entry = xreaddir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (!hasChild(node, entry->d_name)) { + // 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); + } + } + + snprintf(buf, PATH_MAX, "/dev/magisk/dummy%s", real_path); + xmkdir_p(buf, 0755); + bind_mount(buf, real_path); + + vec_for_each(node->children, child) { + snprintf(buf, PATH_MAX, "/dev/magisk/dummy%s/%s", real_path, child->name); + if (child->type == DT_DIR) { + xmkdir(buf, 0755); + } else if (child->type == DT_REG) { + close(open_new(buf)); + } + if (child->status == IS_MODULE) { + // Mount from module file to dummy file + snprintf(buf2, PATH_MAX, "/magisk/%s%s/%s", child->module, real_path, child->name); + } else if (child->status == IS_DUMMY) { + // Mount from mirror to dummy file + snprintf(buf2, PATH_MAX, "/dev/magisk/mirror%s/%s", real_path, child->name); + } else if (child->status == IS_SKEL) { + // It's another skeleton, recursive call and end + char *s = get_full_path(child); + clone_skeleton(child, s); + free(s); + continue; + } + if (child->type == DT_LNK) { + // Symlink special treatments + char *temp = xmalloc(PATH_MAX); + xreadlink(buf2, temp, PATH_MAX); + symlink(temp, buf); + free(temp); + LOGD("cplink: %s -> %s\n", buf2, buf); + } else { + snprintf(buf, PATH_MAX, "%s/%s", real_path, child->name); + bind_mount(buf2, buf); + } + } +} + +static void magic_mount(struct node_entry *node) { + char *real_path; + struct node_entry *child; + + if (strcmp(node->name, "vendor") == 0 && strcmp(node->parent->name, "/system") == 0) + return; + + if (node->status == DO_NOTHING) { + vec_for_each(node->children, child) + magic_mount(child); + } else { + real_path = get_full_path(node); + if (node->status == IS_MODULE) { + snprintf(buf, PATH_MAX, "/magisk/%s%s", node->module, real_path); + bind_mount(buf, real_path); + } else if (node->status == IS_SKEL) { + clone_skeleton(node, real_path); + } + free(real_path); + } +} + +/**************** + * Entry points * + ****************/ + +static void *start_magisk_hide(void *args) { + launch_magiskhide(-1); + return NULL; +} + +void post_fs(int client) { + LOGI("** post-fs mode running\n"); + // ack + write_int(client, 0); + close(client); + + // TODO: Simple bind mounts + + // Allocate buffer + buf = xmalloc(PATH_MAX); + buf2 = xmalloc(PATH_MAX); + +unblock: + unblock_boot_process(); +} + +void post_fs_data(int client) { + // ack + write_int(client, 0); + close(client); + if (!check_data()) + goto unblock; + + // Allocate buffer + if (buf == NULL) buf = xmalloc(PATH_MAX); + if (buf2 == NULL) buf2 = xmalloc(PATH_MAX); + + LOGI("** post-fs-data mode running\n"); + LOGI("* Mounting magisk.img\n"); + // Mounting magisk image + char *magiskimg = mount_image("/data/magisk.img", "/magisk"); + free(magiskimg); + + // Run common scripts + LOGI("* Running post-fs-data.d scripts\n"); + exec_common_script("post-fs-data"); + + DIR *dir; + struct dirent *entry; + char *module; + struct node_entry *sys_root, *ven_root = NULL, *child; + + if (!(dir = xopendir("/magisk"))) + goto unblock; + + // Create the system root entry + sys_root = xcalloc(sizeof(*sys_root), 1); + sys_root->name = strdup("/system"); + + int has_modules = 0; + + // Travel through each modules + vec_init(&module_list); + LOGI("* Loading modules\n"); + while ((entry = xreaddir(dir))) { + if (entry->d_type == DT_DIR) { + if (strcmp(entry->d_name, ".") == 0 || + strcmp(entry->d_name, "..") == 0 || + strcmp(entry->d_name, ".core") == 0 || + strcmp(entry->d_name, "lost+found") == 0) + continue; + // Check whether disable + snprintf(buf, PATH_MAX, "/magisk/%s/disable", entry->d_name); + if (access(buf, F_OK) == 0) + continue; + // Add the module to list + module = strdup(entry->d_name); + vec_push_back(&module_list, module); + // Read props + snprintf(buf, PATH_MAX, "/magisk/%s/system.prop", module); + if (access(buf, F_OK) == 0) { + LOGI("%s: loading [system.prop]\n", module); + read_prop_file(buf, 0); + } + // Check whether enable auto_mount + snprintf(buf, PATH_MAX, "/magisk/%s/auto_mount", module); + if (access(buf, F_OK) == -1) + continue; + // Double check whether the system folder exists + snprintf(buf, PATH_MAX, "/magisk/%s/system", module); + if (access(buf, F_OK) == -1) + continue; + // Construct structure + has_modules = 1; + LOGI("%s: constructing magic mount structure\n", module); + construct_tree(module, "system", sys_root); + } + } + + closedir(dir); + + if (has_modules) { + // Mount mirrors + LOGI("* Mounting system/vendor mirrors"); + char block[256]; + int seperate_vendor = 0; + struct vector mounts; + vec_init(&mounts); + file_to_vector("/proc/mounts", &mounts); + char *line; + vec_for_each(&mounts, line) { + if (strstr(line, " /system ")) { + sscanf(line, "%s", block); + xmkdir_p("/dev/magisk/mirror/system", 0755); + xmount(block, "/dev/magisk/mirror/system", "ext4", MS_RDONLY, NULL); + LOGD("mount: %s -> /dev/magisk/mirror/system\n", block); + continue; + } + if (strstr(line, " /vendor ")) { + seperate_vendor = 1; + sscanf(line, "%s", block); + xmkdir_p("/dev/magisk/mirror/vendor", 0755); + xmount(block, "/dev/magisk/mirror/vendor", "ext4", MS_RDONLY, NULL); + LOGD("mount: %s -> /dev/magisk/mirror/vendor\n", block); + continue; + } + } + vec_deep_destroy(&mounts); + if (!seperate_vendor) { + symlink("/dev/magisk/mirror/system/vendor", "/dev/magisk/mirror/vendor"); + LOGD("link: /dev/magisk/mirror/system/vendor -> /dev/magisk/mirror/vendor\n"); + } + + // Magic!! + + magic_mount(sys_root); + // Get the vendor node if exists + vec_for_each(sys_root->children, child) { + if (strcmp(child->name, "vendor") == 0) { + ven_root = child; + free(ven_root->name); + ven_root->name = strdup("/vendor"); + ven_root->parent = NULL; + break; + } + } + if (ven_root) + magic_mount(ven_root); + } + + // Cleanup memory + destroy_subtree(sys_root); + + // Execute module scripts + LOGI("* Running module post-fs-data scripts\n"); + exec_module_script("post-fs-data"); + + // Start magiskhide if enabled + char *hide_prop = getprop("persist.magisk.hide"); + if (hide_prop) { + if (strcmp(hide_prop, "1") == 0) { + pthread_t thread; + xpthread_create(&thread, NULL, start_magisk_hide, NULL); + } + free(hide_prop); + } + +unblock: + unblock_boot_process(); +} + +void late_start(int client) { + LOGI("** late_start service mode running\n"); + // ack + write_int(client, 0); + close(client); + + // Wait till the full patch is done + pthread_join(sepol_patch, NULL); + + // Run scripts after full patch, most reliable way to run scripts + LOGI("* Running service.d scripts\n"); + exec_common_script("service"); + LOGI("* Running module service scripts\n"); + exec_module_script("service"); + + // All boot stage done, cleanup everything + free(buf); + free(buf2); + vec_deep_destroy(&module_list); +} diff --git a/jni/daemon/daemon.c b/jni/daemon/daemon.c index 70e406dc9..070bfcef3 100644 --- a/jni/daemon/daemon.c +++ b/jni/daemon/daemon.c @@ -31,8 +31,6 @@ static void *request_handler(void *args) { int client = *((int *) args); free(args); client_request req = read_int(client); - char *s; - int pid, status, code; switch (req) { case LAUNCH_MAGISKHIDE: launch_magiskhide(client); @@ -67,11 +65,7 @@ static void *request_handler(void *args) { late_start(client); break; case TEST: - s = read_string(client); - LOGI("%s\n", s); - free(s); - write_int(client, 0); - close(client); + // test(client); break; } return NULL; @@ -94,7 +88,7 @@ static void *large_sepol_patch(void *args) { LOGD("sepol: Starting large patch thread\n"); // Patch su to everything sepol_allow("su", ALL, ALL, ALL); - dump_policydb("/sys/fs/selinux/load"); + dump_policydb(SELINUX_LOAD); LOGD("sepol: Large patch done\n"); destroy_policydb(); return NULL; @@ -117,11 +111,14 @@ void start_daemon() { xsetsid(); setcon("u:r:su:s0"); umask(022); + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); // Patch selinux with medium patch before we do anything - load_policydb("/sys/fs/selinux/policy"); + load_policydb(SELINUX_POLICY); sepol_med_rules(); - dump_policydb("/sys/fs/selinux/load"); + dump_policydb(SELINUX_LOAD); // Continue the larger patch in another thread, we will need to join later pthread_create(&sepol_patch, NULL, large_sepol_patch, NULL); diff --git a/jni/daemon/late_start.c b/jni/daemon/late_start.c deleted file mode 100644 index 06e446267..000000000 --- a/jni/daemon/late_start.c +++ /dev/null @@ -1,23 +0,0 @@ -/* late_start.c - late_start service actions - */ - -#include -#include -#include - -#include "magisk.h" -#include "daemon.h" -#include "utils.h" - -void late_start(int client) { - LOGI("** late_start service mode running\n"); - // ack - write_int(client, 0); - close(client); - - // Wait till the full patch is done - pthread_join(sepol_patch, NULL); - - // Run scripts after full patch, most reliable way to run scripts - exec_common_script("service"); -} diff --git a/jni/daemon/post_fs.c b/jni/daemon/post_fs.c deleted file mode 100644 index 19c28f7c7..000000000 --- a/jni/daemon/post_fs.c +++ /dev/null @@ -1,21 +0,0 @@ -/* post_fs.c - post-fs actions - */ - -#include - -#include "magisk.h" -#include "utils.h" -#include "daemon.h" - -void post_fs(int client) { - LOGI("** post-fs mode running\n"); - // ack - write_int(client, 0); - - // TODO: Simple bind mounts - - close(client); - -unblock: - unblock_boot_process(); -} diff --git a/jni/daemon/post_fs_data.c b/jni/daemon/post_fs_data.c deleted file mode 100644 index 99b6b9aac..000000000 --- a/jni/daemon/post_fs_data.c +++ /dev/null @@ -1,84 +0,0 @@ -/* post_fs_data.c - post-fs-data actions - */ - -#include -#include -#include -#include -#include -#include -#include -#include - -#include "magisk.h" -#include "utils.h" -#include "daemon.h" -#include "resetprop.h" - -static char *loopsetup(const char *img) { - char device[20]; - struct loop_info64 info; - int i, lfd, ffd; - memset(&info, 0, sizeof(info)); - // First get an empty loop device - for (i = 0; i <= 7; ++i) { - sprintf(device, "/dev/block/loop%d", i); - lfd = xopen(device, O_RDWR); - if (ioctl(lfd, LOOP_GET_STATUS64, &info) == -1) - break; - close(lfd); - } - if (i == 8) return NULL; - ffd = xopen(img, O_RDWR); - if (ioctl(lfd, LOOP_SET_FD, ffd) == -1) - return NULL; - strcpy((char *) info.lo_file_name, img); - ioctl(lfd, LOOP_SET_STATUS64, &info); - return strdup(device); -} - -static void *start_magisk_hide(void *args) { - // Setup default error handler for thread - err_handler = exit_thread; - launch_magiskhide(-1); - return NULL; -} - -char *mount_image(const char *img, const char *target) { - char *device = loopsetup(img); - if (device) - xmount(device, target, "ext4", 0, NULL); - return device; -} - -void post_fs_data(int client) { - // ack - write_int(client, 0); - close(client); - if (!check_data()) - goto unblock; - - LOGI("** post-fs-data mode running\n"); - LOGI("* Mounting magisk.img\n"); - // Mounting magisk image - char *magiskimg = mount_image("/data/magisk.img", "/magisk"); - free(magiskimg); - - // TODO: Magic Mounts, modules etc. - - // Run common scripts - exec_common_script("post-fs-data"); - - // Start magiskhide if enabled - char *hide_prop = getprop("persist.magisk.hide"); - if (hide_prop) { - if (strcmp(hide_prop, "1") == 0) { - pthread_t thread; - xpthread_create(&thread, NULL, start_magisk_hide, NULL); - } - free(hide_prop); - } - -unblock: - unblock_boot_process(); -} diff --git a/jni/magisk.h b/jni/magisk.h index 1ac8fdc87..60f77eee9 100644 --- a/jni/magisk.h +++ b/jni/magisk.h @@ -10,12 +10,6 @@ #include #include -#ifndef MAGISK_VER_CODE -#define MAGISK_VER_CODE 99999 -#endif -#ifndef MAGISK_VERSION -#define MAGISK_VERSION VER_DEBUG -#endif #define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK" #define str(a) #a @@ -30,6 +24,11 @@ #define ARG_MAX 4096 #endif +#define SELINUX_PATH "/sys/fs/selinux/" +#define SELINUX_ENFORCE SELINUX_PATH "enforce" +#define SELINUX_POLICY SELINUX_PATH "policy" +#define SELINUX_LOAD SELINUX_PATH "load" + // Global handler for PLOGE extern __thread void (*err_handler)(void); diff --git a/jni/magiskboot/cpio.c b/jni/magiskboot/cpio.c index 2a77324c6..96057cadc 100644 --- a/jni/magiskboot/cpio.c +++ b/jni/magiskboot/cpio.c @@ -283,7 +283,7 @@ static void cpio_extract(const char *entry, const char *filename, struct vector static void cpio_backup(const char *orig, struct vector *v) { struct vector o_body, *o = &o_body, bak; cpio_file *m, *n, *dir, *rem; - char chk1[21], chk2[21], buf[PATH_MAX]; + char buf[PATH_MAX]; int res, doBak; dir = xcalloc(sizeof(*dir), 1); diff --git a/jni/magiskhide/magiskhide.c b/jni/magiskhide/magiskhide.c index c2fb50d33..653866563 100644 --- a/jni/magiskhide/magiskhide.c +++ b/jni/magiskhide/magiskhide.c @@ -60,8 +60,10 @@ void launch_magiskhide(int client) { if (init_resetprop()) goto error; - if (setprop2("persist.magisk.hide", "1", 0)) - goto error; + if (client != -1) { + if (setprop("persist.magisk.hide", "1")) + goto error; + } hide_sensitive_props(); diff --git a/jni/magiskhide/magiskhide.h b/jni/magiskhide/magiskhide.h index e1f6d05aa..94feb2e02 100644 --- a/jni/magiskhide/magiskhide.h +++ b/jni/magiskhide/magiskhide.h @@ -5,8 +5,6 @@ #define HIDELIST "/magisk/.core/magiskhide/hidelist" #define DUMMYPATH "/dev/magisk/dummy" -#define ENFORCE_FILE "/sys/fs/selinux/enforce" -#define POLICY_FILE "/sys/fs/selinux/policy" typedef enum { HIDE_ERROR = -1, diff --git a/jni/magiskhide/pre_process.c b/jni/magiskhide/pre_process.c index b8473b9a2..1a71f2f59 100644 --- a/jni/magiskhide/pre_process.c +++ b/jni/magiskhide/pre_process.c @@ -29,15 +29,15 @@ static int isMocked = 0; void manage_selinux() { if (isMocked) return; char val[1]; - int fd = xopen(ENFORCE_FILE, O_RDONLY); + int fd = xopen(SELINUX_ENFORCE, O_RDONLY); xxread(fd, val, 1); close(fd); // Permissive if (val[0] == '0') { LOGI("hide_daemon: Permissive detected, hide the state\n"); - chmod(ENFORCE_FILE, 0640); - chmod(POLICY_FILE, 0440); + chmod(SELINUX_ENFORCE, 0640); + chmod(SELINUX_POLICY, 0440); isMocked = 1; } } diff --git a/jni/magiskpolicy b/jni/magiskpolicy index 3e106a9dc..feec3e825 160000 --- a/jni/magiskpolicy +++ b/jni/magiskpolicy @@ -1 +1 @@ -Subproject commit 3e106a9dc53400b2dde2e80cff277a5552a447ac +Subproject commit feec3e82558b1640e2deb88fde19e50fe589bbcb diff --git a/jni/main.c b/jni/main.c index 254e26bf8..745476359 100644 --- a/jni/main.c +++ b/jni/main.c @@ -35,7 +35,8 @@ static void usage() { " post-fs, post-fs-data, service\n" "\n" "Options:\n" - " -v print client and daemon version\n" + " -c print client version\n" + " -v print daemon version\n" " -V print daemon version code\n" "\n" "Supported applets:\n" @@ -57,12 +58,14 @@ int main(int argc, char *argv[]) { else arg = argv[0]; if (strcmp(arg, "magisk") == 0) { if (argc < 2) usage(); - if (strcmp(argv[1], "-v") == 0) { - printf("Client: %s\n", MAGISK_VER_STR); + if (strcmp(argv[1], "-c") == 0) { + printf("%s\n", MAGISK_VER_STR); + return 0; + } else if (strcmp(argv[1], "-v") == 0) { int fd = connect_daemon(); write_int(fd, CHECK_VERSION); char *v = read_string(fd); - printf("Daemon: %s\n", v); + printf("%s\n", v); free(v); return 0; } else if (strcmp(argv[1], "-V") == 0) { @@ -92,10 +95,11 @@ int main(int argc, char *argv[]) { return read_int(fd); } else if (strcmp(argv[1], "--test") == 0) { // Temporary testing entry - int fd = connect_daemon(); - write_int(fd, TEST); - write_string(fd, argv[2]); - return read_int(fd); + // int fd = connect_daemon(); + // write_int(fd, TEST); + // return read_int(fd); + // test(); + return 0; } else { // It's calling applets --argc; diff --git a/jni/resetprop/resetprop.cpp b/jni/resetprop/resetprop.cpp index cfe740680..4f1a8f466 100644 --- a/jni/resetprop/resetprop.cpp +++ b/jni/resetprop/resetprop.cpp @@ -151,7 +151,7 @@ int setprop(const char *name, const char *value) { return setprop2(name, value, 1); } -int setprop2(const char *name, const char *value, int trigger) { +int setprop2(const char *name, const char *value, const int trigger) { int ret; char *check = getprop(name); @@ -190,7 +190,7 @@ int deleteprop(const char *name) { return 0; } -int read_prop_file(const char* filename) { +int read_prop_file(const char* filename, const int trigger) { PRINT_D("resetprop: Load prop file [%s]\n", filename); FILE *fp = fopen(filename, "r"); if (fp == NULL) { @@ -223,7 +223,7 @@ int read_prop_file(const char* filename) { if ( ((pch == NULL) || (i >= (pch - line))) || (pch >= line + read - 1) ) continue; // Separate the string *pch = '\0'; - setprop(line + i, pch + 1); + setprop2(line + i, pch + 1, trigger); } free(line); fclose(fp); @@ -234,7 +234,7 @@ int resetprop_main(int argc, char *argv[]) { int del = 0, file = 0, trigger = 1; - int exp_arg = 2, stdout_bak, null; + int exp_arg = 2; char *name, *value, *filename; if (argc < 3) { @@ -283,7 +283,7 @@ int resetprop_main(int argc, char *argv[]) { return -1; if (file) { - return read_prop_file(filename); + return read_prop_file(filename, trigger); } else if (del) { return deleteprop(name); } else { diff --git a/jni/resetprop/resetprop.h b/jni/resetprop/resetprop.h index c5650abd6..e6fe11c9c 100644 --- a/jni/resetprop/resetprop.h +++ b/jni/resetprop/resetprop.h @@ -10,9 +10,10 @@ extern "C" { int init_resetprop(); int setprop(const char *name, const char *value); -int setprop2(const char *name, const char *value, int trigger); +int setprop2(const char *name, const char *value, const int trigger); char *getprop(const char *name); int deleteprop(const char *name); +int read_prop_file(const char* filename, const int trigger); #ifdef __cplusplus } diff --git a/jni/utils/misc.c b/jni/utils/misc.c index d5d614cdf..db4537821 100644 --- a/jni/utils/misc.c +++ b/jni/utils/misc.c @@ -9,6 +9,7 @@ #include #include #include +#include #include #include #include @@ -238,10 +239,9 @@ int run_command(int *fd, const char *path, char *const argv[]) { xdup2(sv[0], STDOUT_FILENO); xdup2(sv[0], STDERR_FILENO); } else { - int null = open("/dev/null", O_RDWR); - xdup2(null, STDIN_FILENO); - xdup2(null, STDOUT_FILENO); - xdup2(null, STDERR_FILENO); + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); } execv(path, argv); @@ -249,29 +249,33 @@ int run_command(int *fd, const char *path, char *const argv[]) { return -1; } -#define MAGISK_CORE "/magisk/.core/" - -void exec_common_script(const char* stage) { - DIR *dir; - struct dirent *entry; - char buf[PATH_MAX]; - snprintf(buf, sizeof(buf), MAGISK_CORE "%s.d", stage); - - if (!(dir = opendir(buf))) - return; - - while ((entry = xreaddir(dir))) { - if (entry->d_type == DT_REG) { - snprintf(buf, sizeof(buf), MAGISK_CORE "%s.d/%s", stage, entry->d_name); - if (access(buf, X_OK) == -1) - continue; - LOGI("%s.d: exec [%s]\n", stage, entry->d_name); - char *const command[] = { "sh", buf, NULL }; - int pid = run_command(NULL, "/system/bin/sh", command); - if (pid != -1) - waitpid(pid, NULL, 0); +int mkdir_p(const char *pathname, mode_t mode) { + char *path = strdup(pathname), *p; + errno = 0; + for (p = path + 1; *p; ++p) { + if (*p == '/') { + *p = '\0'; + if (mkdir(path, mode) == -1) { + if (errno != EEXIST) + return -1; + } + *p = '/'; } } - - closedir(dir); + if (mkdir(path, mode) == -1) { + if (errno != EEXIST) + return -1; + } + free(path); + return 0; +} + +int bind_mount(const char *from, const char *to) { + int ret = xmount(from, to, NULL, MS_BIND, NULL); + LOGD("bind_mount: %s -> %s\n", from, to); + return ret; +} + +int open_new(const char *filename) { + return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); } diff --git a/jni/utils/utils.h b/jni/utils/utils.h index f0a4d029c..6748372b6 100644 --- a/jni/utils/utils.h +++ b/jni/utils/utils.h @@ -61,6 +61,7 @@ int xmkdir(const char *pathname, mode_t mode); void *xmmap(void *addr, size_t length, int prot, int flags, int fd, off_t offset); ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count); +int xmkdir_p(const char *pathname, mode_t mode); // misc.c @@ -79,6 +80,8 @@ void unlock_blocks(); void unblock_boot_process(); void setup_sighandlers(void (*handler)(int)); int run_command(int *fd, const char *path, char *const argv[]); -void exec_common_script(const char* stage); +int mkdir_p(const char *pathname, mode_t mode); +int bind_mount(const char *from, const char *to); +int open_new(const char *filename); #endif diff --git a/jni/utils/vector.h b/jni/utils/vector.h index af6e51bdf..224b2a0a0 100644 --- a/jni/utils/vector.h +++ b/jni/utils/vector.h @@ -21,11 +21,11 @@ void vec_deep_destroy(struct vector *v); #define vec_entry(v) (v)->data /* Usage: vec_for_each(vector *v, void *e) */ #define vec_for_each(v, e) \ - e = (v)->data[0]; \ - for (size_t _ = 0; _ < (v)->size; ++_, e = (v)->data[_]) + e = v ? (v)->data[0] : NULL; \ + for (size_t _ = 0; v && _ < (v)->size; ++_, e = (v)->data[_]) #define vec_for_each_r(v, e) \ - e = (v)->data[(v)->size - 1]; \ - for (size_t _ = (v)->size; _ > 0; --_, e = (v)->data[_ - 1]) + e = v ? (v)->data[(v)->size - 1] : NULL; \ + for (size_t _ = (v)->size; v && _ > 0; --_, e = (v)->data[_ - 1]) #endif \ No newline at end of file diff --git a/jni/utils/xwrap.c b/jni/utils/xwrap.c index 536c85c74..968e76e6c 100644 --- a/jni/utils/xwrap.c +++ b/jni/utils/xwrap.c @@ -298,4 +298,10 @@ ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count) { return ret; } - +int xmkdir_p(const char *pathname, mode_t mode) { + int ret = mkdir_p(pathname, mode); + if (ret == -1) { + PLOGE("mkdir_p %s", pathname); + } + return ret; +}