From a5e4f3cc6b18b7c44df609e153646d936797b4bc Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Fri, 1 Dec 2017 17:17:24 +0800 Subject: [PATCH] Separate cpio logic from MagiskBoot --- jni/Android.mk | 3 +- jni/include/cpio.h | 57 +++++++++ jni/magiskboot/cpio.h | 56 --------- jni/magiskboot/magiskboot.h | 14 +++ jni/magiskboot/ramdisk.c | 146 ++++++++++++++++++++++ jni/{magiskboot => utils}/cpio.c | 203 +++++-------------------------- 6 files changed, 251 insertions(+), 228 deletions(-) create mode 100644 jni/include/cpio.h delete mode 100644 jni/magiskboot/cpio.h create mode 100644 jni/magiskboot/ramdisk.c rename jni/{magiskboot => utils}/cpio.c (69%) diff --git a/jni/Android.mk b/jni/Android.mk index 51df2c8db..852993d46 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -100,12 +100,13 @@ LOCAL_SRC_FILES := \ magiskboot/bootimg.c \ magiskboot/hexpatch.c \ magiskboot/compress.c \ - magiskboot/cpio.c \ magiskboot/sha1.c \ magiskboot/types.c \ magiskboot/dtb.c \ + magiskboot/ramdisk.c \ utils/xwrap.c \ utils/file.c \ + utils/cpio.c \ utils/vector.c LOCAL_CFLAGS := -DNO_SELINUX diff --git a/jni/include/cpio.h b/jni/include/cpio.h new file mode 100644 index 000000000..d6de8facf --- /dev/null +++ b/jni/include/cpio.h @@ -0,0 +1,57 @@ +#ifndef _CPIO_H_ +#define _CPIO_H_ + +#include + +#include "vector.h" + +typedef struct cpio_entry { + // uint32_t ino; + uint32_t mode; + uint32_t uid; + uint32_t gid; + // uint32_t nlink; + // uint32_t mtime; + uint32_t filesize; + // uint32_t devmajor; + // uint32_t devminor; + // uint32_t rdevmajor; + // uint32_t rdevminor; + uint32_t namesize; + // uint32_t check; + char *filename; + char *data; + int remove; +} cpio_entry; + +typedef struct cpio_newc_header { + char magic[6]; + char ino[8]; + char mode[8]; + char uid[8]; + char gid[8]; + char nlink[8]; + char mtime[8]; + char filesize[8]; + char devmajor[8]; + char devminor[8]; + char rdevmajor[8]; + char rdevminor[8]; + char namesize[8]; + char check[8]; +} cpio_newc_header; + +void parse_cpio(const char *filename, struct vector *v); +void dump_cpio(const char *filename, struct vector *v); +void cpio_vec_destroy(struct vector *v); +void cpio_rm(int recursive, const char *entry, struct vector *v); +void cpio_mkdir(mode_t mode, const char *entry, struct vector *v); +void cpio_add(mode_t mode, const char *entry, const char *filename, struct vector *v); +void cpio_mv(struct vector *v, const char *from, const char *to); +void cpio_test(struct vector *v); +void cpio_extract(const char *entry, const char *filename, struct vector *v); +void cpio_backup(const char *orig, const char *sha1, struct vector *v); +int cpio_restore(struct vector *v); +void cpio_stocksha1(struct vector *v); + +#endif diff --git a/jni/magiskboot/cpio.h b/jni/magiskboot/cpio.h deleted file mode 100644 index 9a1a2b85a..000000000 --- a/jni/magiskboot/cpio.h +++ /dev/null @@ -1,56 +0,0 @@ -#ifndef _CPIO_H_ -#define _CPIO_H_ - -#include - -typedef struct cpio_entry { - // uint32_t ino; - uint32_t mode; - uint32_t uid; - uint32_t gid; - // uint32_t nlink; - // uint32_t mtime; - uint32_t filesize; - // uint32_t devmajor; - // uint32_t devminor; - // uint32_t rdevmajor; - // uint32_t rdevminor; - uint32_t namesize; - // uint32_t check; - char *filename; - char *data; - int remove; -} cpio_entry; - -typedef struct cpio_newc_header { - char magic[6]; - char ino[8]; - char mode[8]; - char uid[8]; - char gid[8]; - char nlink[8]; - char mtime[8]; - char filesize[8]; - char devmajor[8]; - char devminor[8]; - char rdevmajor[8]; - char rdevminor[8]; - char namesize[8]; - char check[8]; -} cpio_newc_header; - -typedef enum { - NONE, - RM, - MKDIR, - ADD, - MV, - EXTRACT, - TEST, - PATCH, - BACKUP, - RESTORE, - STOCKSHA1 -} command_t; - -#endif diff --git a/jni/magiskboot/magiskboot.h b/jni/magiskboot/magiskboot.h index 0cc6b116a..4b103c360 100644 --- a/jni/magiskboot/magiskboot.h +++ b/jni/magiskboot/magiskboot.h @@ -32,4 +32,18 @@ size_t lz4_legacy(int mode, int fd, const void *buf, size_t size); long long comp(file_t type, int to, const void *from, size_t size); long long decomp(file_t type, int to, const void *from, size_t size); +typedef enum { + NONE, + RM, + MKDIR, + ADD, + MV, + EXTRACT, + TEST, + PATCH, + BACKUP, + RESTORE, + STOCKSHA1 +} command_t; + #endif diff --git a/jni/magiskboot/ramdisk.c b/jni/magiskboot/ramdisk.c new file mode 100644 index 000000000..a4ce95239 --- /dev/null +++ b/jni/magiskboot/ramdisk.c @@ -0,0 +1,146 @@ +#include +#include +#include + +#include "magiskboot.h" +#include "cpio.h" + +int check_verity_pattern(const char *s) { + int pos = 0; + if (s[0] == ',') ++pos; + if (strncmp(s + pos, "verify", 6) == 0) + pos += 6; + else if (strncmp(s + pos, "avb", 3) == 0) + pos += 3; + else + return -1; + + if (s[pos] == '=') { + while (s[pos] != '\0' && s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos; + } + return pos; +} + +int check_encryption_pattern(const char *s) { + const char *encrypt_list[] = { "forceencrypt", "forcefdeorfbe", NULL }; + for (int i = 0 ; encrypt_list[i]; ++i) { + int len = strlen(encrypt_list[i]); + if (strncmp(s, encrypt_list[i], len) == 0) + return len; + } + return -1; +} + +void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) { + cpio_entry *f; + int skip, write; + vec_for_each(v, f) { + if (!keepverity) { + if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { + write = 0; + for (int read = 0; read < f->filesize; ++write, ++read) { + if ((skip = check_verity_pattern(f->data + read)) > 0) { + fprintf(stderr, "Remove pattern [%.*s] in [%s]\n", skip, f->data + read, f->filename); + read += skip; + } + f->data[write] = f->data[read]; + } + f->filesize = write; + } else if (strcmp(f->filename, "verity_key") == 0) { + fprintf(stderr, "Remove [verity_key]\n"); + f->remove = 1; + } + } + if (!keepforceencrypt) { + if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { + write = 0; + for (int read = 0; read < f->filesize; ++write, ++read) { + if ((skip = check_encryption_pattern(f->data + read)) > 0) { + // assert(skip > 11)! + fprintf(stderr, "Replace pattern [%.*s] with [encryptable] in [%s]\n", skip, f->data + read, f->filename); + memcpy(f->data + write, "encryptable", 11); + write += 11; + read += skip; + } + f->data[write] = f->data[read]; + } + f->filesize = write; + } + } + } +} + +int cpio_commands(const char *command, int argc, char *argv[]) { + int recursive = 0, ret = 0; + command_t cmd; + char *incpio = argv[0]; + ++argv; + --argc; + if (strcmp(command, "test") == 0) { + cmd = TEST; + } else if (strcmp(command, "restore") == 0) { + cmd = RESTORE; + } else if (strcmp(command, "stocksha1") == 0) { + cmd = STOCKSHA1; + } else if (argc >= 1 && strcmp(command, "backup") == 0) { + cmd = BACKUP; + } else if (argc > 0 && strcmp(command, "rm") == 0) { + cmd = RM; + if (argc == 2 && strcmp(argv[0], "-r") == 0) { + recursive = 1; + ++argv; + --argc; + } + } else if (argc == 2 && strcmp(command, "mv") == 0) { + cmd = MV; + } else if (argc == 2 && strcmp(command, "patch") == 0) { + cmd = PATCH; + } else if (argc == 2 && strcmp(command, "extract") == 0) { + cmd = EXTRACT; + } else if (argc == 2 && strcmp(command, "mkdir") == 0) { + cmd = MKDIR; + } else if (argc == 3 && strcmp(command, "add") == 0) { + cmd = ADD; + } else { + cmd = NONE; + } + struct vector v; + vec_init(&v); + parse_cpio(incpio, &v); + switch(cmd) { + case TEST: + cpio_test(&v); + break; + case RESTORE: + ret = cpio_restore(&v); + break; + case STOCKSHA1: + cpio_stocksha1(&v); + return 0; + case BACKUP: + cpio_backup(argv[0], argc > 1 ? argv[1] : NULL, &v); + case RM: + cpio_rm(recursive, argv[0], &v); + break; + case PATCH: + cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0); + break; + case EXTRACT: + cpio_extract(argv[0], argv[1], &v); + break; + case MKDIR: + cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v); + break; + case ADD: + cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v); + break; + case MV: + cpio_mv(&v, argv[0], argv[1]); + break; + case NONE: + return 1; + } + dump_cpio(incpio, &v); + cpio_vec_destroy(&v); + exit(ret); +} diff --git a/jni/magiskboot/cpio.c b/jni/utils/cpio.c similarity index 69% rename from jni/magiskboot/cpio.c rename to jni/utils/cpio.c index bbcc0c2d5..814d26827 100644 --- a/jni/magiskboot/cpio.c +++ b/jni/utils/cpio.c @@ -2,7 +2,6 @@ #include #include -#include "magiskboot.h" #include "cpio.h" #include "logging.h" #include "utils.h" @@ -49,7 +48,7 @@ static int cpio_cmp(const void *a, const void *b) { } // Parse cpio file to a vector of cpio_entry -static void parse_cpio(const char *filename, struct vector *v) { +void parse_cpio(const char *filename, struct vector *v) { fprintf(stderr, "Loading cpio: [%s]\n\n", filename); int fd = xopen(filename, O_RDONLY); cpio_newc_header header; @@ -90,7 +89,7 @@ static void parse_cpio(const char *filename, struct vector *v) { close(fd); } -static void dump_cpio(const char *filename, struct vector *v) { +void dump_cpio(const char *filename, struct vector *v) { fprintf(stderr, "\nDump cpio: [%s]\n\n", filename); int fd = creat(filename, 0644); unsigned inode = 300000; @@ -131,7 +130,7 @@ static void dump_cpio(const char *filename, struct vector *v) { close(fd); } -static void cpio_vec_destroy(struct vector *v) { +void cpio_vec_destroy(struct vector *v) { // Free each cpio_entry cpio_entry *f; vec_for_each(v, f) { @@ -140,7 +139,7 @@ static void cpio_vec_destroy(struct vector *v) { vec_destroy(v); } -static void cpio_rm(int recursive, const char *entry, struct vector *v) { +void cpio_rm(int recursive, const char *entry, struct vector *v) { cpio_entry *f; vec_for_each(v, f) { if (strncmp(f->filename, entry, strlen(entry)) == 0) { @@ -156,7 +155,7 @@ static void cpio_rm(int recursive, const char *entry, struct vector *v) { } } -static void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) { +void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) { cpio_entry *f = xcalloc(sizeof(*f), 1); f->mode = S_IFDIR | mode; f->namesize = strlen(entry) + 1; @@ -165,7 +164,7 @@ static void cpio_mkdir(mode_t mode, const char *entry, struct vector *v) { fprintf(stderr, "Create directory [%s] (%04o)\n",entry, mode); } -static void cpio_add(mode_t mode, const char *entry, const char *filename, struct vector *v) { +void cpio_add(mode_t mode, const char *entry, const char *filename, struct vector *v) { int fd = xopen(filename, O_RDONLY); cpio_entry *f = xcalloc(sizeof(*f), 1); f->mode = S_IFREG | mode; @@ -180,7 +179,28 @@ static void cpio_add(mode_t mode, const char *entry, const char *filename, struc fprintf(stderr, "Add entry [%s] (%04o)\n", entry, mode); } -static void cpio_test(struct vector *v) { +void 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->namesize = strlen(to) + 1; + f->filename = strdup(to); + return; + } + } + fprintf(stderr, "Cannot find entry %s\n", from); + exit(1); +} + +void cpio_test(struct vector *v) { #define STOCK_BOOT 0x0 #define MAGISK_PATCH 0x1 #define OTHER_PATCH 0x2 @@ -205,72 +225,9 @@ static void cpio_test(struct vector *v) { exit(ret); } -int check_verity_pattern(const char *s) { - int pos = 0; - if (s[0] == ',') ++pos; - if (strncmp(s + pos, "verify", 6) == 0) - pos += 6; - else if (strncmp(s + pos, "avb", 3) == 0) - pos += 3; - else - return -1; - if (s[pos] == '=') { - while (s[pos] != '\0' && s[pos] != ' ' && s[pos] != '\n' && s[pos] != ',') ++pos; - } - return pos; -} -int check_encryption_pattern(const char *s) { - const char *encrypt_list[] = { "forceencrypt", "forcefdeorfbe", NULL }; - for (int i = 0 ; encrypt_list[i]; ++i) { - int len = strlen(encrypt_list[i]); - if (strncmp(s, encrypt_list[i], len) == 0) - return len; - } - return -1; -} - -static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) { - cpio_entry *f; - int skip, write; - vec_for_each(v, f) { - if (!keepverity) { - if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { - write = 0; - for (int read = 0; read < f->filesize; ++write, ++read) { - if ((skip = check_verity_pattern(f->data + read)) > 0) { - fprintf(stderr, "Remove pattern [%.*s] in [%s]\n", skip, f->data + read, f->filename); - read += skip; - } - f->data[write] = f->data[read]; - } - f->filesize = write; - } else if (strcmp(f->filename, "verity_key") == 0) { - fprintf(stderr, "Remove [verity_key]\n"); - f->remove = 1; - } - } - if (!keepforceencrypt) { - if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { - write = 0; - for (int read = 0; read < f->filesize; ++write, ++read) { - if ((skip = check_encryption_pattern(f->data + read)) > 0) { - // assert(skip > 11)! - fprintf(stderr, "Replace pattern [%.*s] with [encryptable] in [%s]\n", skip, f->data + read, f->filename); - memcpy(f->data + write, "encryptable", 11); - write += 11; - read += skip; - } - f->data[write] = f->data[read]; - } - f->filesize = write; - } - } - } -} - -static void cpio_extract(const char *entry, const char *filename, struct vector *v) { +void cpio_extract(const char *entry, const char *filename, struct vector *v) { cpio_entry *f; vec_for_each(v, f) { if (strcmp(f->filename, entry) == 0 && S_ISREG(f->mode)) { @@ -286,7 +243,7 @@ static void cpio_extract(const char *entry, const char *filename, struct vector LOGE("Cannot find the file entry [%s]\n", entry); } -static void cpio_backup(const char *orig, const char *sha1, struct vector *v) { +void cpio_backup(const char *orig, const char *sha1, struct vector *v) { struct vector o_body, *o = &o_body, bak; cpio_entry *m, *n, *rem, *cksm; char buf[PATH_MAX]; @@ -394,7 +351,7 @@ static void cpio_backup(const char *orig, const char *sha1, struct vector *v) { cpio_vec_destroy(o); } -static int cpio_restore(struct vector *v) { +int cpio_restore(struct vector *v) { cpio_entry *f, *n; int ret = 1; vec_for_each(v, f) { @@ -428,7 +385,7 @@ static int cpio_restore(struct vector *v) { return ret; } -static void cpio_stocksha1(struct vector *v) { +void cpio_stocksha1(struct vector *v) { cpio_entry *f; char sha1[41]; vec_for_each(v, f) { @@ -448,99 +405,3 @@ static void cpio_stocksha1(struct vector *v) { } } } - -static void 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->namesize = strlen(to) + 1; - f->filename = strdup(to); - return; - } - } - fprintf(stderr, "Cannot find entry %s\n", from); - exit(1); -} - -int cpio_commands(const char *command, int argc, char *argv[]) { - int recursive = 0, ret = 0; - command_t cmd; - char *incpio = argv[0]; - ++argv; - --argc; - if (strcmp(command, "test") == 0) { - cmd = TEST; - } else if (strcmp(command, "restore") == 0) { - cmd = RESTORE; - } else if (strcmp(command, "stocksha1") == 0) { - cmd = STOCKSHA1; - } else if (argc >= 1 && strcmp(command, "backup") == 0) { - cmd = BACKUP; - } else if (argc > 0 && strcmp(command, "rm") == 0) { - cmd = RM; - if (argc == 2 && strcmp(argv[0], "-r") == 0) { - recursive = 1; - ++argv; - --argc; - } - } else if (argc == 2 && strcmp(command, "mv") == 0) { - cmd = MV; - } else if (argc == 2 && strcmp(command, "patch") == 0) { - cmd = PATCH; - } else if (argc == 2 && strcmp(command, "extract") == 0) { - cmd = EXTRACT; - } else if (argc == 2 && strcmp(command, "mkdir") == 0) { - cmd = MKDIR; - } else if (argc == 3 && strcmp(command, "add") == 0) { - cmd = ADD; - } else { - cmd = NONE; - } - struct vector v; - vec_init(&v); - parse_cpio(incpio, &v); - switch(cmd) { - case TEST: - cpio_test(&v); - break; - case RESTORE: - ret = cpio_restore(&v); - break; - case STOCKSHA1: - cpio_stocksha1(&v); - return 0; - case BACKUP: - cpio_backup(argv[0], argc > 1 ? argv[1] : NULL, &v); - case RM: - cpio_rm(recursive, argv[0], &v); - break; - case PATCH: - cpio_patch(&v, strcmp(argv[0], "true") == 0, strcmp(argv[1], "true") == 0); - break; - case EXTRACT: - cpio_extract(argv[0], argv[1], &v); - break; - case MKDIR: - cpio_mkdir(strtoul(argv[0], NULL, 8), argv[1], &v); - break; - case ADD: - cpio_add(strtoul(argv[0], NULL, 8), argv[1], argv[2], &v); - break; - case MV: - cpio_mv(&v, argv[0], argv[1]); - break; - case NONE: - return 1; - } - dump_cpio(incpio, &v); - cpio_vec_destroy(&v); - exit(ret); -}