From a3c49de6a5d321dceb55ff049dde3d948c0396e4 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Thu, 21 Dec 2017 03:36:18 +0800 Subject: [PATCH] Refactor magiskboot --- build.py | 6 +- core/jni/core/magiskinit.c | 44 +++-- core/jni/include/cpio.h | 2 + core/jni/include/vector.h | 8 +- core/jni/magiskboot/bootimg.c | 6 +- core/jni/magiskboot/compress.c | 4 +- core/jni/magiskboot/hexpatch.c | 2 +- core/jni/magiskboot/magiskboot.h | 2 +- core/jni/magiskboot/main.c | 62 +++---- core/jni/magiskboot/ramdisk.c | 280 +++++++++++++++---------------- core/jni/resetprop/resetprop.cpp | 2 +- core/jni/utils/cpio.c | 223 ++++++++++++------------ core/jni/utils/vector.c | 18 +- scripts/boot_patch.sh | 26 +-- scripts/magisk_uninstaller.sh | 9 +- scripts/util_functions.sh | 4 +- 16 files changed, 351 insertions(+), 347 deletions(-) diff --git a/build.py b/build.py index fa020954d..2df6e4767 100755 --- a/build.py +++ b/build.py @@ -266,7 +266,7 @@ def zip_main(args): with open(source, 'r') as script: # Add version info util_functions.sh util_func = script.read().replace( - 'MAGISK_VERSION_STUB', 'MAGISK_VER="{}"\nMAGISK_VER_CODE={}'.format(args.versionString, args.versionCode)) + '#MAGISK_VERSION_STUB', 'MAGISK_VER="{}"\nMAGISK_VER_CODE={}'.format(args.versionString, args.versionCode)) target = os.path.join('common', 'util_functions.sh') print('zip: ' + source + ' -> ' + target) zipf.writestr(target, util_func) @@ -316,11 +316,9 @@ def zip_uninstaller(args): source = os.path.join('scripts', 'util_functions.sh') with open(source, 'r') as script: # Remove the stub - util_func = script.read().replace( - 'MAGISK_VERSION_STUB', '') target = os.path.join('util_functions.sh') print('zip: ' + source + ' -> ' + target) - zipf.writestr(target, util_func) + zipf.writestr(target, script.read()) # Prebuilts for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']: diff --git a/core/jni/core/magiskinit.c b/core/jni/core/magiskinit.c index 78a13f95b..8794dd964 100644 --- a/core/jni/core/magiskinit.c +++ b/core/jni/core/magiskinit.c @@ -182,22 +182,24 @@ static void patch_ramdisk(int root) { close(fd); free(addr); - char *key, *value; - full_read("/.backup/.magisk", &addr, &size); - for (char *tok = strtok(addr, "\n"); tok; tok = strtok(NULL, "\n")) { - key = tok; - value = strchr(tok, '=') + 1; - value[-1] = '\0'; - if (strcmp(key, "KEEPVERITY") == 0) - keepverity = strcmp(value, "true") == 0; - else if (strcmp(key, "KEEPFORCEENCRYPT") == 0) - keepencrypt = strcmp(value, "true") == 0; - } + /* Disabled for now */ - excl_list = (char *[]) { "system_root", "system", "vendor", NULL }; - in_order_walk(root, fstab_patch_cb); - if (!keepverity) - unlink("/verity_key"); + // char *key, *value; + // full_read("/.backup/.magisk", &addr, &size); + // for (char *tok = strtok(addr, "\n"); tok; tok = strtok(NULL, "\n")) { + // key = tok; + // value = strchr(tok, '=') + 1; + // value[-1] = '\0'; + // if (strcmp(key, "KEEPVERITY") == 0) + // keepverity = strcmp(value, "true") == 0; + // else if (strcmp(key, "KEEPFORCEENCRYPT") == 0) + // keepencrypt = strcmp(value, "true") == 0; + // } + + // excl_list = (char *[]) { "system_root", "system", "vendor", NULL }; + // in_order_walk(root, fstab_patch_cb); + // if (!keepverity) + // unlink("/verity_key"); } static int strend(const char *s1, const char *s2) { @@ -472,17 +474,11 @@ int main(int argc, char *argv[]) { close(system_root); } else { - char *ramdisk_xz = NULL; - if (access("/ramdisk-recovery.xz", R_OK) == 0) - ramdisk_xz = "/ramdisk-recovery.xz"; - else if (access("/ramdisk.cpio.xz", R_OK) == 0) - ramdisk_xz = "/ramdisk.cpio.xz"; - - if (ramdisk_xz) { - // High compress mode + if (access("/ramdisk.cpio.xz", R_OK) == 0) { + // High compression mode void *addr; size_t size; - mmap_ro(ramdisk_xz, &addr, &size); + mmap_ro("/ramdisk.cpio.xz", &addr, &size); int fd = creat("/ramdisk.cpio", 0); unxz(addr, size, fd); munmap(addr, size); diff --git a/core/jni/include/cpio.h b/core/jni/include/cpio.h index 81a8342a9..0c7a3f85c 100644 --- a/core/jni/include/cpio.h +++ b/core/jni/include/cpio.h @@ -42,6 +42,8 @@ typedef struct cpio_newc_header { } cpio_newc_header; // Basic cpio functions +void cpio_free(cpio_entry *e); +int cpio_find(struct vector *v, const char *entry); int cpio_cmp(const void *a, const void *b); void parse_cpio(struct vector *v, const char *filename); void dump_cpio(struct vector *v, const char *filename); diff --git a/core/jni/include/vector.h b/core/jni/include/vector.h index 8be1b0745..9156b0c6d 100644 --- a/core/jni/include/vector.h +++ b/core/jni/include/vector.h @@ -7,8 +7,8 @@ #include struct vector { - size_t size; - size_t cap; + unsigned size; + unsigned cap; void **data; }; @@ -26,11 +26,11 @@ struct vector *vec_dup(struct vector *v); /* Usage: vec_for_each(vector *v, void *e) */ #define vec_for_each(v, e) \ e = v ? (v)->data[0] : NULL; \ - for (size_t _ = 0; v && _ < (v)->size; ++_, e = (v)->data[_]) + for (int _ = 0; v && _ < (v)->size; ++_, e = (v)->data[_]) #define vec_for_each_r(v, e) \ e = v ? (v)->data[(v)->size - 1] : NULL; \ - for (size_t _ = (v)->size; v && _ > 0; --_, e = (v)->data[_ - 1]) + for (int _ = ((int) (v)->size) - 1; v && _ >= 0; --_, e = (v)->data[_]) #define vec_cur(v) vec_entry(v)[_] diff --git a/core/jni/magiskboot/bootimg.c b/core/jni/magiskboot/bootimg.c index 3025077c5..2e48c8b82 100644 --- a/core/jni/magiskboot/bootimg.c +++ b/core/jni/magiskboot/bootimg.c @@ -55,7 +55,6 @@ static void print_hdr(const boot_img_hdr *hdr) { } fprintf(stderr, "NAME [%s]\n", hdr->name); fprintf(stderr, "CMDLINE [%s]\n", hdr->cmdline); - fprintf(stderr, "\n"); } int parse_img(const char *image, boot_img *boot) { @@ -63,7 +62,7 @@ int parse_img(const char *image, boot_img *boot) { int is_blk = mmap_ro(image, &boot->map_addr, &boot->map_size); // Parse image - fprintf(stderr, "Parsing boot image: [%s]\n\n", image); + fprintf(stderr, "Parsing boot image: [%s]\n", image); for (size_t pos = 0; pos < boot->map_size; pos += 256) { switch (check_type(boot->map_addr + pos)) { case CHROMEOS: @@ -143,7 +142,6 @@ int parse_img(const char *image, boot_img *boot) { fprintf(stderr, "KERNEL_FMT [%s]\n", fmt); get_type_name(boot->ramdisk_type, fmt); fprintf(stderr, "RAMDISK_FMT [%s]\n", fmt); - fprintf(stderr, "\n"); return boot->flags & CHROMEOS_FLAG ? CHROMEOS_RET : ((is_blk && boot->tail_size < 500 * 1024) ? INSUF_BLOCK_RET : 0); @@ -206,7 +204,7 @@ void repack(const char* orig_image, const char* out_image) { // Parse original image parse_img(orig_image, &boot); - fprintf(stderr, "Repack to boot image: [%s]\n\n", out_image); + fprintf(stderr, "Repack to boot image: [%s]\n", out_image); // Create new image int fd = creat(out_image, 0644); diff --git a/core/jni/magiskboot/compress.c b/core/jni/magiskboot/compress.c index f57772741..e82f27250 100644 --- a/core/jni/magiskboot/compress.c +++ b/core/jni/magiskboot/compress.c @@ -437,7 +437,7 @@ void decomp_file(char *from, const char *to) { fd = STDOUT_FILENO; } else { fd = creat(to, 0644); - fprintf(stderr, "Decompressing to [%s]\n\n", to); + fprintf(stderr, "Decompressing to [%s]\n", to); } decomp(type, fd, file, size); @@ -498,7 +498,7 @@ void comp_file(const char *method, const char *from, const char *to) { fd = STDOUT_FILENO; } else { fd = creat(dest, 0644); - fprintf(stderr, "Compressing to [%s]\n\n", dest); + fprintf(stderr, "Compressing to [%s]\n", dest); } comp(type, fd, file, size); close(fd); diff --git a/core/jni/magiskboot/hexpatch.c b/core/jni/magiskboot/hexpatch.c index 8fb3ad399..2442fc084 100644 --- a/core/jni/magiskboot/hexpatch.c +++ b/core/jni/magiskboot/hexpatch.c @@ -26,7 +26,7 @@ void hexpatch(const char *image, const char *from, const char *to) { hex2byte(to, patch); for (size_t i = 0; filesize > 0 && i < filesize - patternsize; ++i) { if (memcmp(file + i, pattern, patternsize) == 0) { - fprintf(stderr, "Pattern %s found!\nPatching to %s\n", from, to); + fprintf(stderr, "Patch @ %08X [%s]->[%s]\n", (unsigned) i, from, to); memset(file + i, 0, patternsize); memcpy(file + i, patch, patchsize); i += patternsize - 1; diff --git a/core/jni/magiskboot/magiskboot.h b/core/jni/magiskboot/magiskboot.h index dd6c0ce03..dfcd06efe 100644 --- a/core/jni/magiskboot/magiskboot.h +++ b/core/jni/magiskboot/magiskboot.h @@ -18,7 +18,7 @@ void unpack(const char *image); void repack(const char* orig_image, const char* out_image); void hexpatch(const char *image, const char *from, const char *to); int parse_img(const char *image, boot_img *boot); -int cpio_commands(const char *cmd, int argc, char *argv[]); +int cpio_commands(int argc, char *argv[]); void comp_file(const char *method, const char *from, const char *to); void decomp_file(char *from, const char *to); int dtb_commands(const char *cmd, int argc, char *argv[]); diff --git a/core/jni/magiskboot/main.c b/core/jni/magiskboot/main.c index 02a047743..15bbdf0ba 100644 --- a/core/jni/magiskboot/main.c +++ b/core/jni/magiskboot/main.c @@ -36,34 +36,39 @@ static void usage(char *arg0) { " --hexpatch \n" " Search in , and replace with \n" "\n" - " --cpio- [flags...] [args...]\n" - " Do cpio related cmds to (modifications are done directly)\n" + " --cpio [commands...]\n" + " Do cpio commands to (modifications are done directly)\n" + " Each command is a single argument, use quotes if necessary\n" " Supported commands:\n" - " -rm [-r] \n" - " Remove entry from , flag [-r] to remove recursively\n" - " -mkdir \n" - " Create directory as an \n" - " -ln \n" - " Create symlink to point to \n" - " -mv \n" - " Move to \n" - " -add \n" - " Add as an ; replaces if already exists\n" - " -extract [ ]\n" - " Extract to , or extract all to current directory\n" - " -test\n" + " rm [-r] ENTRY\n" + " Remove ENTRY, specify [-r] to remove recursively\n" + " mkdir MODE ENTRY\n" + " Create directory ENTRY in permissions MODE\n" + " ln TARGET ENTRY\n" + " Create a symlink to TARGET with the name ENTRY\n" + " mv SOURCE DEST\n" + " Move SOURCE to DEST\n" + " add MODE ENTRY INFILE\n" + " Add INFILE as ENTRY in permissions MODE; replaces ENTRY if exists\n" + " extract [ENTRY OUT]\n" + " Extract ENTRY to OUT, or extract all entries to current directory\n" + " test\n" + " Test the current cpio's patch status\n" " Return value: 0/stock 1/Magisk 2/other (phh, SuperSU, Xposed)\n" - " -patch \n" + " patch KEEPVERITY KEEPFORCEENCRYPT\n" " Ramdisk patches. KEEP**** are boolean values\n" - " This command is no longer used in Magisk installations\n" - " -backup [SHA1]\n" - " Create ramdisk backups into from \n" + " backup ORIG [SHA1]\n" + " Create ramdisk backups from ORIG\n" + " SHA1 of stock boot image is optional\n" + " restore\n" + " Restore ramdisk from ramdisk backup stored within incpio\n" + " magisk ORIG HIGHCOMP KEEPVERITY KEEPFORCEENCRYPT [SHA1]\n" + " Do Magisk patches and backups all in one step\n" + " Create ramdisk backups from ORIG\n" " HIGHCOMP, KEEP**** are boolean values\n" " SHA1 of stock boot image is optional\n" - " -restore\n" - " Restore ramdisk from ramdisk backup within \n" - " -stocksha1\n" - " Get stock boot SHA1 recorded within \n" + " sha1\n" + " Print stock boot SHA1 if previously stored\n" "\n" " --dtb- \n" " Do dtb related cmds to (modifications are done directly)\n" @@ -104,11 +109,11 @@ static void usage(char *arg0) { } int main(int argc, char *argv[]) { - fprintf(stderr, "MagiskBoot v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) - Boot Image Modification Tool\n\n"); + fprintf(stderr, "MagiskBoot v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu) - Boot Image Modification Tool\n"); umask(0); if (argc > 1 && strcmp(argv[1], "--cleanup") == 0) { - fprintf(stderr, "Cleaning up...\n\n"); + fprintf(stderr, "Cleaning up...\n"); char name[PATH_MAX]; unlink(KERNEL_FILE); unlink(RAMDISK_FILE); @@ -146,11 +151,8 @@ int main(int argc, char *argv[]) { comp_file(method, argv[2], argc > 3 ? argv[3] : NULL); } else if (argc > 4 && strcmp(argv[1], "--hexpatch") == 0) { hexpatch(argv[2], argv[3], argv[4]); - } else if (argc > 2 && strncmp(argv[1], "--cpio", 6) == 0) { - char *cmd = argv[1] + 6; - if (*cmd == '\0') usage(argv[0]); - else ++cmd; - if (cpio_commands(cmd, argc - 2, argv + 2)) usage(argv[0]); + } else if (argc > 2 && strcmp(argv[1], "--cpio") == 0) { + if (cpio_commands(argc - 2, argv + 2)) usage(argv[0]); } else if (argc > 2 && strncmp(argv[1], "--dtb", 5) == 0) { char *cmd = argv[1] + 5; if (*cmd == '\0') usage(argv[0]); diff --git a/core/jni/magiskboot/ramdisk.c b/core/jni/magiskboot/ramdisk.c index b565f1f95..378ef3366 100644 --- a/core/jni/magiskboot/ramdisk.c +++ b/core/jni/magiskboot/ramdisk.c @@ -9,19 +9,21 @@ #include "cpio.h" static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) { - cpio_entry *f; - vec_for_each(v, f) { + cpio_entry *e; + vec_for_each(v, e) { + if (!e) continue; if (!keepverity) { - if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { - patch_verity(&f->data, &f->filesize, 1); - } else if (strcmp(f->filename, "verity_key") == 0) { + if (strncmp(e->filename, ".backup", 7) && strstr(e->filename, "fstab") && S_ISREG(e->mode)) { + patch_verity(&e->data, &e->filesize, 1); + } else if (strcmp(e->filename, "verity_key") == 0) { fprintf(stderr, "Remove [verity_key]\n"); - f->remove = 1; + cpio_free(e); + vec_cur(v) = NULL; } } if (!keepforceencrypt) { - if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { - patch_encryption(&f->data, &f->filesize); + if (strstr(e->filename, "fstab") != NULL && S_ISREG(e->mode)) { + patch_encryption(&e->data, &e->filesize); } } } @@ -32,33 +34,28 @@ static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) { #define OTHER_PATCH 0x2 static int cpio_test(struct vector *v) { - int ret = STOCK_BOOT; - cpio_entry *f; const char *OTHER_LIST[] = { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", "boot/sbin/launch_daemonsu.sh", NULL }; const char *MAGISK_LIST[] = { ".backup/.magisk", "init.magisk.rc", "overlay/init.magisk.rc", NULL }; - vec_for_each(v, f) { - for (int i = 0; OTHER_LIST[i]; ++i) { - if (strcmp(f->filename, OTHER_LIST[i]) == 0) { - // Already find other files, abort - return OTHER_PATCH; - } - } - for (int i = 0; MAGISK_LIST[i]; ++i) { - if (strcmp(f->filename, MAGISK_LIST[i]) == 0) - ret = MAGISK_PATCH; - } - } - cpio_vec_destroy(v); - return ret; + + for (int i = 0; OTHER_LIST[i]; ++i) + if (cpio_find(v, OTHER_LIST[i]) > 0) + return OTHER_PATCH; + + for (int i = 0; MAGISK_LIST[i]; ++i) + if (cpio_find(v, MAGISK_LIST[i]) > 0) + return MAGISK_PATCH; + + return STOCK_BOOT; } -static char *cpio_stocksha1(struct vector *v) { - cpio_entry *f; +static char *cpio_sha1(struct vector *v) { + cpio_entry *e; char sha1[41]; - vec_for_each(v, f) { - if (strcmp(f->filename, "init.magisk.rc") == 0 - || strcmp(f->filename, "overlay/init.magisk.rc") == 0) { - for (void *pos = f->data; pos < f->data + f->filesize; pos = strchr(pos + 1, '\n') + 1) { + vec_for_each(v, e) { + if (!e) continue; + if (strcmp(e->filename, "init.magisk.rc") == 0 + || strcmp(e->filename, "overlay/init.magisk.rc") == 0) { + for (void *pos = e->data; pos < e->data + e->filesize; pos = strchr(pos + 1, '\n') + 1) { if (memcmp(pos, "# STOCKSHA1=", 12) == 0) { pos += 12; memcpy(sha1, pos, 40); @@ -66,61 +63,47 @@ static char *cpio_stocksha1(struct vector *v) { return strdup(sha1); } } - } else if (strcmp(f->filename, ".backup/.sha1") == 0) { - return f->data; + } else if (strcmp(e->filename, ".backup/.sha1") == 0) { + return e->data; } } return NULL; } -static struct vector *cpio_backup(struct vector *v, const char *orig, const char *keepverity, - const char *keepforceencrypt, const char *sha1) { - struct vector o_body, *o = &o_body, *ret; +static void cpio_backup(struct vector *v, struct vector *bak, const char *orig, const char *sha1) { + struct vector o_body, *o = &o_body; cpio_entry *m, *n, *rem, *cksm; char buf[PATH_MAX]; int res, backup; - ret = xcalloc(sizeof(*ret), 1); - - vec_init(o); - vec_init(ret); - m = xcalloc(sizeof(*m), 1); m->filename = strdup(".backup"); m->mode = S_IFDIR; - vec_push_back(ret, m); - - m = xcalloc(sizeof(*m), 1); - m->filename = strdup(".backup/.magisk"); - m->mode = S_IFREG; - m->data = xmalloc(50); - snprintf(m->data, 50, "KEEPVERITY=%s\nKEEPFORCEENCRYPT=%s\n", keepverity, keepforceencrypt); - m->filesize = strlen(m->data) + 1; - vec_push_back(ret, m); + vec_push_back(bak, m); rem = xcalloc(sizeof(*rem), 1); rem->filename = strdup(".backup/.rmlist"); rem->mode = S_IFREG; - vec_push_back(ret, rem); if (sha1) { fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1); cksm = xcalloc(sizeof(*cksm), 1); - vec_push_back(ret, cksm); + vec_push_back(bak, cksm); cksm->filename = strdup(".backup/.sha1"); cksm->mode = S_IFREG; cksm->data = strdup(sha1); cksm->filesize = strlen(sha1) + 1; } + vec_init(o); parse_cpio(o, orig); // Remove possible backups in original ramdisk cpio_rm(o, 1, ".backup"); cpio_rm(v, 1, ".backup"); // Sort both vectors before comparing - vec_sort(v, cpio_cmp); vec_sort(o, cpio_cmp); + vec_sort(v, cpio_cmp); // Start comparing size_t i = 0, j = 0; @@ -153,7 +136,6 @@ static struct vector *cpio_backup(struct vector *v, const char *orig, const char } else { // Someting new in ramdisk, record in rem ++j; - if (n->remove) continue; rem->data = xrealloc(rem->data, rem->filesize + strlen(n->filename) + 1); memcpy(rem->data + rem->filesize, n->filename, strlen(n->filename) + 1); rem->filesize += strlen(n->filename) + 1; @@ -161,51 +143,49 @@ static struct vector *cpio_backup(struct vector *v, const char *orig, const char } if (backup) { sprintf(buf, ".backup/%s", m->filename); + fprintf(stderr, "[%s] -> [%s]\n", m->filename, buf); free(m->filename); m->filename = strdup(buf); - fprintf(stderr, "[%s] -> [%s]\n", buf, m->filename); - vec_push_back(ret, m); + vec_push_back(bak, m); // NULL the original entry, so it won't be freed vec_entry(o)[i - 1] = NULL; } } - if (rem->filesize == 0) - rem->remove = 1; + if (rem->filesize) + vec_push_back(bak, rem); + else + cpio_free(rem); // Cleanup cpio_vec_destroy(o); - - return ret; } static void cpio_restore(struct vector *v) { - cpio_entry *f, *n; - vec_for_each(v, f) { - if (strncmp(f->filename, ".backup", 7) == 0) { - f->remove = 1; - if (f->filename[7] == '\0') continue; - if (f->filename[8] == '.') { - if (strcmp(f->filename, ".backup/.rmlist") == 0) { - for (int pos = 0; pos < f->filesize; pos += strlen(f->data + pos) + 1) - cpio_rm(v, 0, f->data + pos); + cpio_entry *e; + vec_for_each(v, e) { + if (!e) continue; + if (strncmp(e->filename, ".backup", 7) == 0) { + if (e->filename[7] == '\0') continue; + if (e->filename[8] == '.') { + if (strcmp(e->filename, ".backup/.rmlist") == 0) { + for (int pos = 0; pos < e->filesize; pos += strlen(e->data + pos) + 1) + cpio_rm(v, 0, e->data + pos); } continue; } else { - n = xcalloc(sizeof(*n), 1); - memcpy(n, f, sizeof(*f)); - n->filename = strdup(f->filename + 8); - n->data = f->data; - f->data = NULL; - n->remove = 0; - fprintf(stderr, "Restore [%s] -> [%s]\n", f->filename, n->filename); - cpio_vec_insert(v, n); + fprintf(stderr, "Restore [%s] -> [%s]\n", e->filename, e->filename + 8); + vec_cur(v) = NULL; + char *new_name = strdup(e->filename + 8); + free(e->filename); + e->filename = new_name; + cpio_vec_insert(v, e); } } - if (strncmp(f->filename, "overlay", 7) == 0) - f->remove = 1; } // Some known stuff we can remove + cpio_rm(v, 1, ".backup"); + cpio_rm(v, 1, "overlay"); cpio_rm(v, 0, "sbin/magic_mask.sh"); cpio_rm(v, 0, "init.magisk.rc"); cpio_rm(v, 0, "magisk"); @@ -235,25 +215,16 @@ static void restore_high_compress(struct vector *v, const char *incpio) { } static void enable_high_compress(struct vector *v, struct vector *b, const char *incpio) { - cpio_entry *e, *magiskinit, *init; + cpio_entry *init, *magiskinit; // Swap magiskinit with original init - vec_for_each(b, e) { - if (strcmp(e->filename, ".backup/init") == 0) { - free(e->filename); - e->filename = strdup("init"); - init = e; - vec_for_each(v, e) { - if (strcmp(e->filename, "init") == 0) { - magiskinit = e; - vec_cur(v) = init; - break; - } - } - vec_cur(b) = NULL; - break; - } - } + int i = cpio_find(b, ".backup/init"), j = cpio_find(v, "init"); + init = vec_entry(b)[i]; + magiskinit = vec_entry(v)[j]; + free(init->filename); + init->filename = strdup("init"); + vec_entry(v)[j] = init; + vec_entry(b)[i] = NULL; dump_cpio(v, incpio); cpio_vec_destroy(v); @@ -269,64 +240,93 @@ static void enable_high_compress(struct vector *v, struct vector *b, const char cpio_add(v, 0, "ramdisk.cpio.xz", incpio); } -int cpio_commands(const char *command, int argc, char *argv[]) { +int cpio_commands(int argc, char *argv[]) { char *incpio = argv[0]; ++argv; --argc; + struct vector v; vec_init(&v); parse_cpio(&v, incpio); - if (strcmp(command, "test") == 0) { - exit(cpio_test(&v)); - } else if (strcmp(command, "restore") == 0) { - restore_high_compress(&v, incpio); - cpio_restore(&v); - } else if (strcmp(command, "stocksha1") == 0) { - printf("%s\n", cpio_stocksha1(&v)); - return 0; - } else if (argc >= 4 && strcmp(command, "backup") == 0) { - struct vector *back; - cpio_entry *e; - back = cpio_backup(&v, argv[0], argv[2], argv[3], argc > 4 ? argv[4] : NULL); + int cmdc; + char *cmdv[6]; - // Enable high compression mode - if (strcmp(argv[1], "true") == 0) - enable_high_compress(&v, back, incpio); + while (argc) { + cmdc = 0; + for (char *tok = strtok(argv[0], " "); tok; tok = strtok(NULL, " ")) + cmdv[cmdc++] = tok; - vec_for_each(back, e) - if (e) vec_push_back(&v, e); - - } else if (argc > 0 && strcmp(command, "rm") == 0) { - int recursive = 0; - if (argc == 2 && strcmp(argv[0], "-r") == 0) { - recursive = 1; - ++argv; - } - cpio_rm(&v, recursive, argv[0]); - } else if (argc == 2 && strcmp(command, "mv") == 0) { - if (cpio_mv(&v, argv[0], argv[1])) - return 1; - } else if (argc == 2 && strcmp(command, "patch") == 0) { - cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0); - } else if (strcmp(command, "extract") == 0) { - if (argc == 2) { - return cpio_extract(&v, argv[0], argv[1]); - } else { - cpio_extract_all(&v); + if (strcmp(cmdv[0], "test") == 0) { + exit(cpio_test(&v)); + } else if (strcmp(cmdv[0], "restore") == 0) { + restore_high_compress(&v, incpio); + cpio_restore(&v); + } else if (strcmp(cmdv[0], "sha1") == 0) { + char *sha1 = cpio_sha1(&v); + if (sha1) + printf("%s\n", sha1); return 0; + } else if (cmdc >= 2 && strcmp(cmdv[0], "backup") == 0) { + struct vector back; + vec_init(&back); + cpio_backup(&v, &back, cmdv[1], cmdc > 2 ? cmdv[2] : NULL); + cpio_entry *e; + vec_for_each(&back, e) + if (e) vec_push_back(&v, e); + vec_destroy(&back); + } else if (cmdc >= 5 && strcmp(cmdv[0], "magisk") == 0) { + cpio_patch(&v, strcmp(cmdv[3], "true") == 0, strcmp(cmdv[4], "true") == 0); + + struct vector back; + vec_init(&back); + cpio_backup(&v, &back, cmdv[1], cmdc > 5 ? cmdv[5] : NULL); + + cpio_entry *e; + e = xcalloc(sizeof(*e), 1); + e->filename = strdup(".backup/.magisk"); + e->mode = S_IFREG; + e->data = xmalloc(50); + snprintf(e->data, 50, "KEEPVERITY=%s\nKEEPFORCEENCRYPT=%s\n", cmdv[3], cmdv[4]); + e->filesize = strlen(e->data) + 1; + vec_push_back(&back, e); + + // Enable high compression mode + if (strcmp(cmdv[2], "true") == 0) + enable_high_compress(&v, &back, incpio); + + vec_for_each(&back, e) + if (e) vec_push_back(&v, e); + vec_destroy(&back); + } else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) { + int recur = cmdc > 2 && strcmp(cmdv[1], "-r") == 0; + cpio_rm(&v, recur, cmdv[1 + recur]); + } else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) { + cpio_mv(&v, cmdv[1], cmdv[2]); + } else if (cmdc == 3 && strcmp(cmdv[0], "patch") == 0) { + cpio_patch(&v, strcmp(cmdv[1], "true") == 0, strcmp(cmdv[2], "true") == 0); + } else if (strcmp(cmdv[0], "extract") == 0) { + if (cmdc == 3) { + return cpio_extract(&v, cmdv[1], cmdv[2]); + } else { + cpio_extract_all(&v); + return 0; + } + } else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) { + cpio_mkdir(&v, strtoul(cmdv[1], NULL, 8), cmdv[2]); + } else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) { + cpio_ln(&v, cmdv[1], cmdv[2]); + } else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) { + cpio_add(&v, strtoul(cmdv[1], NULL, 8), cmdv[2], cmdv[3]); + } else { + return 1; } - } else if (argc == 2 && strcmp(command, "mkdir") == 0) { - cpio_mkdir(&v, strtoul(argv[0], NULL, 8), argv[1]); - } else if (argc == 2 && strcmp(command, "ln") == 0) { - cpio_ln(&v, argv[0], argv[1]); - } else if (argc == 3 && strcmp(command, "add") == 0) { - cpio_add(&v, strtoul(argv[0], NULL, 8), argv[1], argv[2]); - } else { - return 1; + + --argc; + ++argv; } dump_cpio(&v, incpio); cpio_vec_destroy(&v); - exit(0); + return 0; } diff --git a/core/jni/resetprop/resetprop.cpp b/core/jni/resetprop/resetprop.cpp index 00d02e991..12686bff9 100644 --- a/core/jni/resetprop/resetprop.cpp +++ b/core/jni/resetprop/resetprop.cpp @@ -209,7 +209,7 @@ public: vector prop_list; static int prop_cmp(const void *p1, const void *p2) { - return strcmp((*((property **) p1))->name, (*((property **) p2))->name); + return strcmp(((property *) p1)->name, ((property *) p2)->name); } static void print_all_props_cb(const char *name, const char *value) { diff --git a/core/jni/utils/cpio.c b/core/jni/utils/cpio.c index 020a9e4c4..0307d29e6 100644 --- a/core/jni/utils/cpio.c +++ b/core/jni/utils/cpio.c @@ -22,34 +22,42 @@ static uint32_t x8u(char *hex) { return val; } -static void cpio_free(cpio_entry *f) { - if (f) { - free(f->filename); - free(f->data); - free(f); +void cpio_free(cpio_entry *e) { + if (e) { + free(e->filename); + free(e->data); + free(e); } } +int cpio_find(struct vector *v, const char *entry) { + cpio_entry *e; + vec_for_each(v, e) { + if (!e) continue; + if (strcmp(e->filename, entry) == 0) + return _; + } + return -1; +} + int cpio_cmp(const void *a, const void *b) { - return strcmp((*(cpio_entry **) a)->filename, (*(cpio_entry **) b)->filename); + return strcmp(((cpio_entry *) a)->filename, ((cpio_entry *) b)->filename); } void cpio_vec_insert(struct vector *v, cpio_entry *n) { - cpio_entry *f; - vec_for_each(v, f) { - if (strcmp(f->filename, n->filename) == 0) { - // Replace, then all is done - cpio_free(f); - vec_cur(v) = n; - return; - } + int i = cpio_find(v, n->filename); + if (i > 0) { + // Replace, then all is done + cpio_free(vec_entry(v)[i]); + vec_entry(v)[i] = n; + return; } vec_push_back(v, n); } // Parse cpio file to a vector of cpio_entry void parse_cpio(struct vector *v, const char *filename) { - fprintf(stderr, "Loading cpio: [%s]\n\n", filename); + fprintf(stderr, "Loading cpio: [%s]\n", filename); int fd = open(filename, O_RDONLY); if (fd < 0) return; cpio_newc_header header; @@ -91,35 +99,34 @@ void parse_cpio(struct vector *v, const char *filename) { } void dump_cpio(struct vector *v, const char *filename) { - fprintf(stderr, "\nDump cpio: [%s]\n\n", filename); - int fd = creat(filename, 0644); + fprintf(stderr, "Dump cpio: [%s]\n", filename); unsigned inode = 300000; char header[111]; // Sort by name vec_sort(v, cpio_cmp); - cpio_entry *f; - vec_for_each(v, f) { - if (f->remove) continue; + cpio_entry *e; + int fd = creat(filename, 0644); + vec_for_each(v, e) { sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", - inode++, // f->ino - f->mode, - f->uid, - f->gid, - 1, // f->nlink - 0, // f->mtime - f->filesize, - 0, // f->devmajor - 0, // f->devminor - 0, // f->rdevmajor - 0, // f->rdevminor - (uint32_t) strlen(f->filename) + 1, - 0 // f->check + inode++, // e->ino + e->mode, + e->uid, + e->gid, + 1, // e->nlink + 0, // e->mtime + e->filesize, + 0, // e->devmajor + 0, // e->devminor + 0, // e->rdevmajor + 0, // e->rdevminor + (uint32_t) strlen(e->filename) + 1, + 0 // e->check ); xwrite(fd, header, 110); - xwrite(fd, f->filename, strlen(f->filename) + 1); + xwrite(fd, e->filename, strlen(e->filename) + 1); file_align(fd, 4, 1); - if (f->filesize) { - xwrite(fd, f->data, f->filesize); + if (e->filesize) { + xwrite(fd, e->data, e->filesize); file_align(fd, 4, 1); } } @@ -133,23 +140,22 @@ void dump_cpio(struct vector *v, const char *filename) { void cpio_vec_destroy(struct vector *v) { // Free each cpio_entry - cpio_entry *f; - vec_for_each(v, f) { - cpio_free(f); - } + cpio_entry *e; + vec_for_each(v, e) + cpio_free(e); vec_destroy(v); } void cpio_rm(struct vector *v, int recursive, const char *entry) { - cpio_entry *f; - vec_for_each(v, f) { - if (strncmp(f->filename, entry, strlen(entry)) == 0) { - char next = f->filename[strlen(entry)]; - if ((recursive && next == '/') || next == '\0') { - if (!f->remove) { - fprintf(stderr, "Remove [%s]\n", f->filename); - f->remove = 1; - } + cpio_entry *e; + size_t len = strlen(entry); + vec_for_each(v, e) { + if (!e) continue; + if (strncmp(e->filename, entry, len) == 0) { + if ((recursive && e->filename[len] == '/') || e->filename[len] == '\0') { + fprintf(stderr, "Remove [%s]\n", e->filename); + cpio_free(e); + vec_cur(v) = NULL; if (!recursive) return; } } @@ -157,97 +163,94 @@ void cpio_rm(struct vector *v, int recursive, const char *entry) { } void cpio_mkdir(struct vector *v, mode_t mode, const char *entry) { - cpio_entry *f = xcalloc(sizeof(*f), 1); - f->mode = S_IFDIR | mode; - f->filename = strdup(entry); - cpio_vec_insert(v, f); + cpio_entry *e = xcalloc(sizeof(*e), 1); + e->mode = S_IFDIR | mode; + e->filename = strdup(entry); + cpio_vec_insert(v, e); fprintf(stderr, "Create directory [%s] (%04o)\n",entry, mode); } void cpio_ln(struct vector *v, const char *target, const char *entry) { - cpio_entry *f = xcalloc(sizeof(*f), 1); - f->mode = S_IFLNK; - f->filename = strdup(entry); - f->filesize = strlen(target); - f->data = strdup(target); - cpio_vec_insert(v, f); + cpio_entry *e = xcalloc(sizeof(*e), 1); + e->mode = S_IFLNK; + e->filename = strdup(entry); + e->filesize = strlen(target); + e->data = strdup(target); + cpio_vec_insert(v, e); fprintf(stderr, "Create symlink [%s] -> [%s]\n", entry, target); } void cpio_add(struct vector *v, mode_t mode, const char *entry, const char *filename) { int fd = xopen(filename, O_RDONLY); - cpio_entry *f = xcalloc(sizeof(*f), 1); - f->mode = S_IFREG | mode; - f->filename = strdup(entry); - f->filesize = lseek(fd, 0, SEEK_END); + cpio_entry *e = xcalloc(sizeof(*e), 1); + e->mode = S_IFREG | mode; + e->filename = strdup(entry); + e->filesize = lseek(fd, 0, SEEK_END); lseek(fd, 0, SEEK_SET); - f->data = xmalloc(f->filesize); - xxread(fd, f->data, f->filesize); + e->data = xmalloc(e->filesize); + xxread(fd, e->data, e->filesize); close(fd); - cpio_vec_insert(v, f); + cpio_vec_insert(v, e); fprintf(stderr, "Add entry [%s] (%04o)\n", entry, mode); } int cpio_mv(struct vector *v, const char *from, const char *to) { - struct cpio_entry *f, *t; - vec_for_each(v, f) { - if (strcmp(f->filename, from) == 0) { - fprintf(stderr, "Move [%s] -> [%s]\n", from, to); - vec_for_each(v, t) { - if (strcmp(t->filename, to) == 0) { - t->remove = 1; - break; - } - } - free(f->filename); - f->filename = strdup(to); - return 0; + struct cpio_entry *e; + int f = cpio_find(v, from), t = cpio_find(v, to); + if (f > 0) { + if (t > 0) { + cpio_free(vec_entry(v)[t]); + vec_entry(v)[t] = NULL; } + e = vec_entry(v)[f]; + free(e->filename); + e->filename = strdup(to); + return 0; } fprintf(stderr, "Cannot find entry %s\n", from); return 1; } int cpio_extract(struct vector *v, const char *entry, const char *filename) { - cpio_entry *f; - vec_for_each(v, f) { - if (strcmp(f->filename, entry) == 0) { - fprintf(stderr, "Extracting [%s] to [%s]\n\n", entry, filename); - if (S_ISREG(f->mode)) { - int fd = creat(filename, f->mode & 0777); - xwrite(fd, f->data, f->filesize); - fchown(fd, f->uid, f->gid); - close(fd); - } else if (S_ISLNK(f->mode)) { - char *target = xcalloc(f->filesize + 1, 1); - memcpy(target, f->data, f->filesize); - unlink(filename); - symlink(target, filename); - } - return 0; + int i = cpio_find(v, entry); + if (i > 0) { + cpio_entry *e = vec_entry(v)[i]; + fprintf(stderr, "Extracting [%s] to [%s]\n", entry, filename); + if (S_ISREG(e->mode)) { + int fd = creat(filename, e->mode & 0777); + xwrite(fd, e->data, e->filesize); + fchown(fd, e->uid, e->gid); + close(fd); + } else if (S_ISLNK(e->mode)) { + char *target = xcalloc(e->filesize + 1, 1); + memcpy(target, e->data, e->filesize); + unlink(filename); + symlink(target, filename); } + return 0; } fprintf(stderr, "Cannot find the file entry [%s]\n", entry); return 1; } void cpio_extract_all(struct vector *v) { - cpio_entry *f; - vec_for_each(v, f) { - fprintf(stderr, "Extracting [%s]\n", f->filename); - unlink(f->filename); - rmdir(f->filename); - if (S_ISDIR(f->mode)) { - mkdir(f->filename, f->mode & 0777); - } else if (S_ISREG(f->mode)) { - int fd = creat(f->filename, f->mode & 0777); - xwrite(fd, f->data, f->filesize); - fchown(fd, f->uid, f->gid); + cpio_entry *e; + vec_for_each(v, e) { + if (!e) continue; + fprintf(stderr, "Extracting [%s]\n", e->filename); + unlink(e->filename); + rmdir(e->filename); + if (S_ISDIR(e->mode)) { + mkdir(e->filename, e->mode & 0777); + } else if (S_ISREG(e->mode)) { + int fd = creat(e->filename, e->mode & 0777); + xwrite(fd, e->data, e->filesize); + fchown(fd, e->uid, e->gid); close(fd); - } else if (S_ISLNK(f->mode)) { - char *target = xcalloc(f->filesize + 1, 1); - memcpy(target, f->data, f->filesize); - symlink(target, f->filename); + } else if (S_ISLNK(e->mode)) { + char *target = xcalloc(e->filesize + 1, 1); + memcpy(target, e->data, e->filesize); + symlink(target, e->filename); } } } diff --git a/core/jni/utils/vector.c b/core/jni/utils/vector.c index 43e5d6b59..4fcb28beb 100644 --- a/core/jni/utils/vector.c +++ b/core/jni/utils/vector.c @@ -29,9 +29,25 @@ void *vec_pop_back(struct vector *v) { return ret; } +static int (*cmp)(const void *, const void *); + +static int vec_comp(const void *a, const void *b) { + void *aa = *((void **)a), *bb = *((void **)b); + if (aa == NULL && bb == NULL) return 0; + else if (aa == NULL) return 1; + else if (bb == NULL) return -1; + else return cmp ? cmp(aa, bb) : 0; +} + void vec_sort(struct vector *v, int (*compar)(const void *, const void *)) { if (v == NULL) return; - qsort(vec_entry(v), vec_size(v), sizeof(void*), compar); + cmp = compar; + qsort(vec_entry(v), vec_size(v), sizeof(void*), vec_comp); + void *e; + vec_for_each_r(v, e) { + if (e) break; + --vec_size(v); + } } /* Will cleanup only the vector itself diff --git a/scripts/boot_patch.sh b/scripts/boot_patch.sh index f9871baa3..8198d2f6e 100644 --- a/scripts/boot_patch.sh +++ b/scripts/boot_patch.sh @@ -89,6 +89,7 @@ case $? in 2 ) ui_print "! Insufficient boot partition size detected" HIGHCOMP=true + ui_print "- Enable high compression mode" ;; 3 ) ui_print "- ChromeOS boot image detected" @@ -103,20 +104,13 @@ case $? in abort "! Stock kernel cannot be patched, please use a custom kernel" esac -if [ -f /sdcard/ramdisk-recovery.img ]; then - HIGHCOMP=true - ui_print "- Detected ramdisk-recovery.img" -fi - -$HIGHCOMP && ui_print "- Enable high compression mode" - ########################################################################################## # Ramdisk restores ########################################################################################## # Test patch status and do restore, after this section, ramdisk.cpio.orig is guaranteed to exist ui_print "- Checking ramdisk status" -./magiskboot --cpio-test ramdisk.cpio +./magiskboot --cpio ramdisk.cpio test case $? in 0 ) # Stock boot ui_print "- Stock boot image detected!" @@ -129,8 +123,8 @@ case $? in 1 ) # Magisk patched ui_print "- Magisk patched image detected!" # Find SHA1 of stock boot image - [ -z $SHA1 ] && SHA1=`./magiskboot --cpio-stocksha1 ramdisk.cpio 2>/dev/null` - ./magiskboot --cpio-restore ramdisk.cpio + [ -z $SHA1 ] && SHA1=`./magiskboot --cpio ramdisk.cpio sha1 2>/dev/null` + ./magiskboot --cpio ramdisk.cpio restore cp -af ramdisk.cpio ramdisk.cpio.orig ;; 2 ) # Other patched @@ -145,18 +139,12 @@ esac ui_print "- Patching ramdisk" -./magiskboot --cpio-add ramdisk.cpio 750 init magiskinit -./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig $HIGHCOMP $KEEPVERITY $KEEPFORCEENCRYPT $SHA1 +./magiskboot --cpio ramdisk.cpio \ +'add 750 init magiskinit' \ +"magisk ramdisk.cpio.orig $HIGHCOMP $KEEPVERITY $KEEPFORCEENCRYPT $SHA1" rm -f ramdisk.cpio.orig -if [ -f /sdcard/ramdisk-recovery.img ]; then - ui_print "- Adding ramdisk-recovery.img" - ./magiskboot --decompress - < /sdcard/ramdisk-recovery.img | ./magiskboot --compress=xz - ramdisk-recovery.xz - ./magiskboot --cpio-add ramdisk.cpio 0 ramdisk-recovery.xz ramdisk-recovery.xz - rm ramdisk-recovery.xz -fi - ########################################################################################## # Binary patches ########################################################################################## diff --git a/scripts/magisk_uninstaller.sh b/scripts/magisk_uninstaller.sh index 48caa78d3..6f75c4707 100644 --- a/scripts/magisk_uninstaller.sh +++ b/scripts/magisk_uninstaller.sh @@ -71,7 +71,7 @@ esac # Detect boot image state ui_print "- Checking ramdisk status" -./magiskboot --cpio-test ramdisk.cpio +./magiskboot --cpio ramdisk.cpio test case $? in 0 ) # Stock boot ui_print "- Stock boot image detected!" @@ -80,13 +80,13 @@ case $? in 1 ) # Magisk patched ui_print "- Magisk patched image detected!" # Find SHA1 of stock boot image - [ -z $SHA1 ] && SHA1=`./magiskboot --cpio-stocksha1 ramdisk.cpio 2>/dev/null` + [ -z $SHA1 ] && SHA1=`./magiskboot --cpio ramdisk.cpio sha1 2>/dev/null` OK=false [ ! -z $SHA1 ] && restore_imgs $SHA1 && OK=true if ! $OK; then ui_print "! Boot image backup unavailable" ui_print "- Restoring ramdisk with internal backup" - ./magiskboot --cpio-restore ramdisk.cpio + ./magiskboot --cpio ramdisk.cpio restore ./magiskboot --repack $BOOTIMAGE # Sign chromeos boot $CHROMEOS && sign_chromeos @@ -104,6 +104,7 @@ cd / ui_print "- Removing Magisk files" rm -rf /cache/*magisk* /cache/unblock /data/*magisk* /data/cache/*magisk* /data/property/*magisk* \ /data/Magisk.apk /data/busybox /data/custom_ramdisk_patch.sh /data/app/com.topjohnwu.magisk* \ - /data/user*/*/magisk.db /data/user*/*/com.topjohnwu.magisk /data/adb/*magisk* 2>/dev/null + /data/user*/*/magisk.db /data/user*/*/com.topjohnwu.magisk /data/user*/*/.tmp.magisk.config \ + /data/adb/*magisk* 2>/dev/null $BOOTMODE && reboot diff --git a/scripts/util_functions.sh b/scripts/util_functions.sh index f5c7ce092..34e126352 100644 --- a/scripts/util_functions.sh +++ b/scripts/util_functions.sh @@ -7,11 +7,11 @@ # ########################################################################################## -MAGISK_VERSION_STUB +#MAGISK_VERSION_STUB SCRIPT_VERSION=$MAGISK_VER_CODE # Default location, will override if needed -MAGISKBIN=/data/adb/magisk +[ -d /data/adb/magisk ] && MAGISKBIN=/data/adb/magisk || MAGISKBIN=/data/magisk BOOTSIGNER="/system/bin/dalvikvm -Xnodex2oat -Xnoimage-dex2oat -cp \$APK com.topjohnwu.magisk.utils.BootSigner" BOOTSIGNED=false