From bf42fce17e33434e4d9617420527f0cff6c07110 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Sun, 2 Jul 2017 21:36:09 +0800 Subject: [PATCH] Update boot patch method and scripts --- jni/magiskboot/Android.mk | 5 +- jni/magiskboot/{utils.c => boot_utils.c} | 0 jni/magiskboot/cpio.c | 188 +++++++++++++++-------- jni/magiskboot/cpio.h | 8 + jni/magiskboot/magiskboot.h | 3 +- jni/magiskboot/main.c | 5 +- scripts/addon.d.sh | 16 +- scripts/boot_patch.sh | 14 +- scripts/flash_script.sh | 28 +--- scripts/util_functions.sh | 35 ++++- 10 files changed, 183 insertions(+), 119 deletions(-) rename jni/magiskboot/{utils.c => boot_utils.c} (100%) diff --git a/jni/magiskboot/Android.mk b/jni/magiskboot/Android.mk index 6382fa16e..14f4ee7c6 100644 --- a/jni/magiskboot/Android.mk +++ b/jni/magiskboot/Android.mk @@ -17,11 +17,12 @@ LOCAL_SRC_FILES := \ hexpatch.c \ parseimg.c \ compress.c \ - utils.c \ + boot_utils.c \ cpio.c \ sha1.c \ ../utils/xwrap.c \ - ../utils/vector.c + ../utils/vector.c \ + ../utils/list.c LOCAL_CFLAGS += -DZLIB_CONST include $(BUILD_EXECUTABLE) diff --git a/jni/magiskboot/utils.c b/jni/magiskboot/boot_utils.c similarity index 100% rename from jni/magiskboot/utils.c rename to jni/magiskboot/boot_utils.c diff --git a/jni/magiskboot/cpio.c b/jni/magiskboot/cpio.c index 3c9815ba8..be196f3ba 100644 --- a/jni/magiskboot/cpio.c +++ b/jni/magiskboot/cpio.c @@ -1,6 +1,7 @@ #include "magiskboot.h" #include "cpio.h" #include "vector.h" +#include "list.h" static uint32_t x8u(char *hex) { uint32_t val, inpos = 8, outpos; @@ -220,47 +221,109 @@ static int check_verity_pattern(const char *s) { return pos; } -static void cpio_dmverity(struct vector *v) { - cpio_file *f; - size_t read, write; - int skip; - vec_for_each(v, f) { - if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { - for (read = 0, write = 0; read < f->filesize; ++read, ++write) { - skip = check_verity_pattern(f->data + read); - if (skip > 0) { - printf("Remove pattern [%.*s] in [%s]\n", (int) 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) { - f->remove = 1; - break; - } +static struct list_head *block_to_list(char *data) { + struct list_head *head = xmalloc(sizeof(*head)); + line_list *line; + init_list_head(head); + char *tok; + tok = strsep(&data, "\n"); + while (tok) { + line = xcalloc(sizeof(*line), 1); + line->line = tok; + list_insert_end(head, &line->pos); + tok = strsep(&data, "\n"); } + return head; } -static void cpio_forceencrypt(struct vector *v) { +static char *list_to_block(struct list_head *head, uint32_t filesize) { + line_list *line; + char *data = xmalloc(filesize); + uint32_t off = 0; + list_for_each(line, head, line_list, pos) { + strcpy(data + off, line->line); + off += strlen(line->line); + data[off++] = '\n'; + } + return data; +} + +static void free_newline(line_list *line) { + if (line->isNew) + free(line->line); +} + +static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) { + struct list_head *head; + line_list *line; cpio_file *f; + int skip, injected = 0; size_t read, write; const char *ENCRYPT_LIST[] = { "forceencrypt", "forcefdeorfbe", "fileencryptioninline", NULL }; vec_for_each(v, f) { - if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { - for (read = 0, write = 0; read < f->filesize; ++read, ++write) { - for (int i = 0 ; ENCRYPT_LIST[i]; ++i) { - if (strncmp(f->data + read, ENCRYPT_LIST[i], strlen(ENCRYPT_LIST[i])) == 0) { - memcpy(f->data + write, "encryptable", 11); - printf("Replace [%s] with [%s] in [%s]\n", ENCRYPT_LIST[i], "encryptable", f->filename); - write += 11; - read += strlen(ENCRYPT_LIST[i]); - break; - } + if (strcmp(f->filename, "init.rc") == 0) { + head = block_to_list(f->data); + list_for_each(line, head, line_list, pos) { + if (strstr(line->line, "import")) { + if (strstr(line->line, "init.magisk.rc")) + injected = 1; + if (injected) + continue; + // Inject magisk script as import + printf("Inject new line [import /init.magisk.rc] in [init.rc]\n"); + line = xcalloc(sizeof(*line), 1); + line->line = strdup("import /init.magisk.rc"); + line->isNew = 1; + f->filesize += 23; + list_insert(__->prev, &line->pos); + injected = 1; + } else if (strstr(line->line, "selinux.reload_policy")) { + // Remove this line + printf("Remove line [%s] in [init.rc]\n", line->line); + f->filesize -= strlen(line->line) + 1; + __ = list_pop(&line->pos); + free(line); + } + } + char *temp = list_to_block(head, f->filesize); + free(f->data); + f->data = temp; + list_destory(head, list_head, pos, free_newline); + free(head); + } else { + if (!keepverity) { + if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { + for (read = 0, write = 0; read < f->filesize; ++read, ++write) { + skip = check_verity_pattern(f->data + read); + if (skip > 0) { + printf("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) { + printf("Remove [verity_key]\n"); + f->remove = 1; + } + } + if (!keepforceencrypt) { + if (strstr(f->filename, "fstab") != NULL && S_ISREG(f->mode)) { + for (read = 0, write = 0; read < f->filesize; ++read, ++write) { + for (int i = 0 ; ENCRYPT_LIST[i]; ++i) { + if (strncmp(f->data + read, ENCRYPT_LIST[i], strlen(ENCRYPT_LIST[i])) == 0) { + memcpy(f->data + write, "encryptable", 11); + printf("Replace [%s] with [%s] in [%s]\n", ENCRYPT_LIST[i], "encryptable", f->filename); + write += 11; + read += strlen(ENCRYPT_LIST[i]); + break; + } + } + f->data[write] = f->data[read]; + } + f->filesize = write; } - f->data[write] = f->data[read]; } - f->filesize = write; } } } @@ -415,10 +478,6 @@ int cpio_commands(const char *command, int argc, char *argv[]) { --argc; if (strcmp(command, "test") == 0) { cmd = TEST; - } else if (strcmp(command, "patch-dmverity") == 0) { - cmd = DMVERITY; - } else if (strcmp(command, "patch-forceencrypt") == 0) { - cmd = FORCEENCRYPT; } else if (strcmp(command, "restore") == 0) { cmd = RESTORE; } else if (argc == 1 && strcmp(command, "backup") == 0) { @@ -430,6 +489,8 @@ int cpio_commands(const char *command, int argc, char *argv[]) { ++argv; --argc; } + } 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) { @@ -438,41 +499,36 @@ int cpio_commands(const char *command, int argc, char *argv[]) { cmd = ADD; } else { cmd = NONE; - return 1; } struct vector v; vec_init(&v); parse_cpio(incpio, &v); switch(cmd) { - case TEST: - cpio_test(&v); - break; - case DMVERITY: - cpio_dmverity(&v); - break; - case FORCEENCRYPT: - cpio_forceencrypt(&v); - break; - case RESTORE: - ret = cpio_restore(&v); - break; - case BACKUP: - cpio_backup(argv[0], &v); - case RM: - cpio_rm(recursive, argv[0], &v); - 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; - default: - // Never happen - break; + case TEST: + cpio_test(&v); + break; + case RESTORE: + ret = cpio_restore(&v); + break; + case BACKUP: + cpio_backup(argv[0], &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 NONE: + return 1; } dump_cpio(incpio, &v); cpio_vec_destroy(&v); diff --git a/jni/magiskboot/cpio.h b/jni/magiskboot/cpio.h index 6f8cda49b..0573b020f 100644 --- a/jni/magiskboot/cpio.h +++ b/jni/magiskboot/cpio.h @@ -3,6 +3,8 @@ #include +#include "list.h" + typedef struct cpio_file { // uint32_t ino; uint32_t mode; @@ -22,6 +24,12 @@ typedef struct cpio_file { int remove; } cpio_file; +typedef struct line_list { + char *line; + int isNew; + struct list_head pos; +} line_list; + typedef struct cpio_newc_header { char magic[6]; char ino[8]; diff --git a/jni/magiskboot/magiskboot.h b/jni/magiskboot/magiskboot.h index 0e0400873..d63029b04 100644 --- a/jni/magiskboot/magiskboot.h +++ b/jni/magiskboot/magiskboot.h @@ -53,8 +53,7 @@ typedef enum { ADD, EXTRACT, TEST, - DMVERITY, - FORCEENCRYPT, + PATCH, BACKUP, RESTORE } command_t; diff --git a/jni/magiskboot/main.c b/jni/magiskboot/main.c index ed420b18d..ad10188a0 100644 --- a/jni/magiskboot/main.c +++ b/jni/magiskboot/main.c @@ -25,9 +25,8 @@ static void usage(char *arg0) { " --cpio-mkdir \n Create directory as an \n" " --cpio-add \n Add as an ; replaces if already exists\n" " --cpio-extract \n Extract to \n" - " --cpio-test \n Return value: 0/not patched 1/Magisk 2/SuperSU\n" - " --cpio-patch-dmverity \n Remove dm-verity\n" - " --cpio-patch-forceencrypt \n Change forceencrypt flag to encryptable\n" + " --cpio-test \n Return value: 0/not patched 1/Magisk 2/Other (e.g. phh, SuperSU)\n" + " --cpio-patch \n Patch cpio for Magisk. KEEP**** are true/false values\n" " --cpio-backup \n Create ramdisk backups into from \n" " --cpio-restore \n Restore ramdisk from ramdisk backup within \n" "\n" diff --git a/scripts/addon.d.sh b/scripts/addon.d.sh index 6443232fa..8c33f09c9 100644 --- a/scripts/addon.d.sh +++ b/scripts/addon.d.sh @@ -16,6 +16,11 @@ main() { # This script always run in recovery BOOTMODE=false + if [ ! -d $MAGISKBIN ]; then + echo "! Cannot find Magisk binaries!" + exit 1 + fi + # Wait for post addon.d processes to finish sleep 5 @@ -23,11 +28,6 @@ main() { mount -o ro /vendor 2>/dev/null mount /data 2>/dev/null - if [ ! -d $MAGISKBIN ]; then - echo "! Cannot find Magisk binaries!" - exit 1 - fi - # Load all functions . $MAGISKBIN/util_functions.sh @@ -37,6 +37,8 @@ main() { ui_print "* MAGISK_VERSION_STUB" ui_print "************************" + api_level_arch_detect + recovery_actions find_boot_image @@ -61,9 +63,7 @@ main() { cd / - mv /sbin_tmp /sbin - ui_print "- Unmounting partitions" - umount -l /system + recovery_cleanup ui_print "- Done" exit 0 diff --git a/scripts/boot_patch.sh b/scripts/boot_patch.sh index b182e9580..ca974d949 100644 --- a/scripts/boot_patch.sh +++ b/scripts/boot_patch.sh @@ -194,16 +194,8 @@ esac ui_print_wrap "- Patching ramdisk" -# The common patches -$KEEPVERITY || ./magiskboot --cpio-patch-dmverity ramdisk.cpio -$KEEPFORCEENCRYPT || ./magiskboot --cpio-patch-forceencrypt ramdisk.cpio - # Add magisk entrypoint -cpio_extract init.rc init.rc -grep "import /init.magisk.rc" init.rc >/dev/null || sed -i '1,/.*import.*/s/.*import.*/import \/init.magisk.rc\n&/' init.rc -sed -i "/selinux.reload_policy/d" init.rc -cpio_add 750 init.rc init.rc -rm -f init.rc +./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT # sepolicy patches cpio_extract sepolicy sepolicy @@ -237,8 +229,6 @@ rm -f ramdisk.cpio.orig A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054 ui_print_wrap "- Repacking boot image" -./magiskboot --repack "$BOOTIMAGE" - -[ $? -ne 0 ] && abort_wrap "! Unable to repack boot image!" +./magiskboot --repack "$BOOTIMAGE" || abort_wrap "! Unable to repack boot image!" ./magiskboot --cleanup diff --git a/scripts/flash_script.sh b/scripts/flash_script.sh index 02069e0a6..430fa6623 100644 --- a/scripts/flash_script.sh +++ b/scripts/flash_script.sh @@ -67,7 +67,7 @@ ui_print "************************" ui_print "* MAGISK_VERSION_STUB" ui_print "************************" -ui_print "- Mounting /system(ro), /vendor(ro), /cache, /data" +ui_print "- Mounting /system, /vendor, /cache, /data" mount -o ro /system 2>/dev/null mount -o ro /vendor 2>/dev/null mount /cache 2>/dev/null @@ -83,17 +83,8 @@ getvar BOOTIMAGE # Check if system root is installed and remove remove_system_su -API=`grep_prop ro.build.version.sdk` -ABI=`grep_prop ro.product.cpu.abi | cut -c-3` -ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3` -ABILONG=`grep_prop ro.product.cpu.abi` - -ARCH=arm -BBPATH=armeabi-v7a -if [ "$ABI" = "x86" ]; then ARCH=x86; fi; -if [ "$ABI2" = "x86" ]; then ARCH=x86; fi; -if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; fi; -if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; fi; +# Detect version and architecture +api_level_arch_detect [ $API -lt 21 ] && abort "! Magisk is only for Lollipop 5.0+ (SDK 21+)" @@ -110,8 +101,6 @@ find_boot_image ########################################################################################## ui_print "- Constructing environment" - -$BOOTMODE || recovery_actions is_mounted /data && MAGISKBIN=/data/magisk || MAGISKBIN=/cache/data_bin @@ -119,9 +108,7 @@ is_mounted /data && MAGISKBIN=/data/magisk || MAGISKBIN=/cache/data_bin rm -rf $MAGISKBIN 2>/dev/null mkdir -p $MAGISKBIN cp -af $BINDIR/. $COMMONDIR/. $MAGISKBIN - chmod -R 755 $MAGISKBIN -chcon -hR u:object_r:system_file:s0 $MAGISKBIN # addon.d if [ -d /system/addon.d ]; then @@ -135,6 +122,8 @@ fi # Magisk Image ########################################################################################## +$BOOTMODE || recovery_actions + # Fix SuperSU..... $BOOTMODE && $BINDIR/magisk magiskpolicy --live "allow fsck * * *" @@ -206,19 +195,16 @@ ui_print "- Flashing new boot image" if [ -L "$BOOTIMAGE" ]; then dd if=new-boot.img of="$BOOTIMAGE" bs=4096 else - cat new-boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 + cat new-boot.img /dev/zero | dd of="$BOOTIMAGE" bs=4096 >/dev/null 2>&1 fi rm -f new-boot.img cd / if ! $BOOTMODE; then - ui_print "- Unmounting partitions" $BINDIR/magisk --umountimg /magisk $MAGISKLOOP rmdir /magisk - mv /sbin_tmp /sbin - umount -l /system - umount -l /vendor 2>/dev/null + recovery_cleanup fi ui_print "- Done" diff --git a/scripts/util_functions.sh b/scripts/util_functions.sh index 1da1c5c8a..e26d4c3b4 100644 --- a/scripts/util_functions.sh +++ b/scripts/util_functions.sh @@ -32,15 +32,15 @@ getvar() { find_boot_image() { if [ -z "$BOOTIMAGE" ]; then - for PARTITION in kern-a android_boot kernel boot lnx; do - BOOTIMAGE=`find /dev/block -iname "$PARTITION" | head -n 1` + for BLOCK in boot_a BOOT_A kern-a KERN-A android_boot ANDROID_BOOT kernel KERNEL boot BOOT lnx LNX; do + BOOTIMAGE=`ls /dev/block/by-name/$BLOCK || ls /dev/block/platform/*/by-name/$BLOCK || ls /dev/block/platform/*/*/by-name/$BLOCK` 2>/dev/null [ ! -z $BOOTIMAGE ] && break done fi # Recovery fallback if [ -z "$BOOTIMAGE" ]; then for FSTAB in /etc/*fstab*; do - BOOTIMAGE=`grep -E '\b/boot\b' $FSTAB | grep -oE '/dev/[a-zA-Z0-9_./-]*'` + BOOTIMAGE=`grep -E '\b/boot\b' $FSTAB | grep -v "#" | grep -oE '/dev/[a-zA-Z0-9_./-]*'` [ ! -z $BOOTIMAGE ] && break done fi @@ -91,13 +91,38 @@ remove_system_su() { fi } +api_level_arch_detect() { + API=`grep_prop ro.build.version.sdk` + ABI=`grep_prop ro.product.cpu.abi | cut -c-3` + ABI2=`grep_prop ro.product.cpu.abi2 | cut -c-3` + ABILONG=`grep_prop ro.product.cpu.abi` + + ARCH=arm + IS64BIT=false + if [ "$ABI" = "x86" ]; then ARCH=x86; fi; + if [ "$ABI2" = "x86" ]; then ARCH=x86; fi; + if [ "$ABILONG" = "arm64-v8a" ]; then ARCH=arm64; IS64BIT=true; fi; + if [ "$ABILONG" = "x86_64" ]; then ARCH=x64; IS64BIT=true; fi; +} + recovery_actions() { # TWRP bug fix mount -o bind /dev/urandom /dev/random - # Clear out possible lib paths, let the binaries find them itself - export LD_LIBRARY_PATH= # Temporarily block out all custom recovery binaries/libs mv /sbin /sbin_tmp + # Add all possible library paths + OLD_LD_PATH=$LD_LIBRARY_PATH + $IS64BIT && export LD_LIBRARY_PATH=/system/lib64:/system/vendor/lib64 || export LD_LIBRARY_PATH=/system/lib:/system/vendor/lib +} + +recovery_cleanup() { + mv /sbin_tmp /sbin + # Clear LD_LIBRARY_PATH + export LD_LIBRARY_PATH=$OLD_LD_PATH + ui_print "- Unmounting partitions" + umount -l /system + umount -l /vendor 2>/dev/null + umount -l /dev/random } abort() {