From e710848345781c5ba992494b5e6835187a59906e Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Mon, 6 Nov 2017 05:41:03 +0800 Subject: [PATCH] Unify Magisk configuration Introduce monogisk tool --- .gitignore | 1 + build.py | 355 ++++++++++++++++++++--------------- java | 2 +- jni/Android.mk | 66 ++++--- jni/daemon/bootstages.c | 5 +- jni/daemon/daemon.c | 18 -- jni/daemon/magisk.c | 17 +- jni/include/logging.h | 3 + jni/include/magisk.h | 4 +- jni/include/magiskrc.h | 45 +++++ jni/include/utils.h | 2 + jni/init/magiskinit.c | 364 ++++++++++++++++++++++++++++++++++++ jni/init/monogisk.c | 121 ++++++++++++ jni/magiskboot/boot_utils.c | 46 ----- jni/magiskboot/cpio.c | 142 +++++++------- jni/magiskboot/magiskboot.h | 7 +- jni/magiskboot/main.c | 4 +- jni/magiskinit.c | 311 ------------------------------ jni/magiskpolicy | 2 +- jni/utils/file.c | 19 ++ scripts/boot_patch.sh | 55 +----- scripts/flash_script.sh | 10 +- scripts/init.magisk.rc | 41 ---- 23 files changed, 901 insertions(+), 739 deletions(-) create mode 100644 jni/include/magiskrc.h create mode 100644 jni/init/magiskinit.c create mode 100644 jni/init/monogisk.c delete mode 100644 jni/magiskinit.c delete mode 100644 scripts/init.magisk.rc diff --git a/.gitignore b/.gitignore index d692faa0a..7b7d0aa31 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1,4 @@ +out/ obj/ libs/ *.zip diff --git a/build.py b/build.py index c9c3ec10a..abffb0e67 100755 --- a/build.py +++ b/build.py @@ -38,23 +38,36 @@ import shutil import lzma import base64 -def silentremove(file): +def mv(source, target): + print('mv: {} -> {}'.format(source, target)) + shutil.move(source, target) + +def cp(source, target): + print('cp: {} -> {}'.format(source, target)) + shutil.copyfile(source, target) + +def rm(file): try: os.remove(file) except OSError as e: if e.errno != errno.ENOENT: raise +def mkdir(path, mode=0o777): + try: + os.mkdir(path, mode) + except: + pass + +def mkdir_p(path, mode=0o777): + os.makedirs(path, mode, exist_ok=True) + def zip_with_msg(zipfile, source, target): if not os.path.exists(source): error('{} does not exist! Try build \'binary\' and \'apk\' before zipping!'.format(source)) print('zip: {} -> {}'.format(source, target)) zipfile.write(source, target) -def cp(source, target): - print('cp: {} -> {}'.format(source, target)) - shutil.copyfile(source, target) - def build_all(args): build_binary(args) build_apk(args) @@ -67,13 +80,40 @@ def build_binary(args): # Force update Android.mk timestamp to trigger recompilation os.utime(os.path.join('jni', 'Android.mk')) - ndk_build = os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build') debug_flag = '' if args.release else '-DMAGISK_DEBUG' - proc = subprocess.run('{} APP_CFLAGS=\"-DMAGISK_VERSION=\\\"{}\\\" -DMAGISK_VER_CODE={} {}\" -j{}'.format( - ndk_build, args.versionString, args.versionCode, debug_flag, multiprocessing.cpu_count()), shell=True) + cflag = 'APP_CFLAGS=\"-DMAGISK_VERSION=\\\"{}\\\" -DMAGISK_VER_CODE={} {}\"'.format(args.versionString, args.versionCode, debug_flag) + + ndk_build = os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build') + # Prebuild + proc = subprocess.run('PRECOMPILE=true {} {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True) if proc.returncode != 0: error('Build Magisk binary failed!') + print('') + for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']: + mkdir_p(os.path.join('out', arch)) + with open(os.path.join('out', arch, 'dump.h'), 'w') as dump: + dump.write('#include "stdlib.h"\n') + for binary in ['magisk', 'magiskinit']: + mv(os.path.join('libs', arch, binary), os.path.join('out', arch, binary)) + with open(os.path.join('out', arch, binary), 'rb') as bin: + dump.write('const uint8_t {}_dump[] = "'.format(binary)) + dump.write(''.join("\\x{:02X}".format(c) for c in lzma.compress(bin.read(), preset=9))) + dump.write('";\n') + print('') + + proc = subprocess.run('{} {} -j{}'.format(ndk_build, cflag, multiprocessing.cpu_count()), shell=True) + if proc.returncode != 0: + error('Build Magisk binary failed!') + + print('') + for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']: + for binary in ['monogisk', 'magiskboot', 'b64xz', 'busybox']: + try: + mv(os.path.join('libs', arch, binary), os.path.join('out', arch, binary)) + except: + pass + def build_apk(args): header('* Building Magisk Manager') @@ -104,8 +144,8 @@ def build_apk(args): # Find the latest build tools build_tool = sorted(os.listdir(os.path.join(os.environ['ANDROID_HOME'], 'build-tools')))[-1] - silentremove(aligned) - silentremove(release) + rm(aligned) + rm(release) proc = subprocess.run([ os.path.join(os.environ['ANDROID_HOME'], 'build-tools', build_tool, 'zipalign'), @@ -129,13 +169,24 @@ def build_apk(args): if proc.returncode != 0: error('Release sign Magisk Manager failed!') - silentremove(unsigned) - silentremove(aligned) + rm(unsigned) + rm(aligned) + + mkdir(os.path.join('..', 'out')) + target = os.path.join('..', 'out', 'app-release.apk') + print('') + mv(release, target) else: proc = subprocess.run('{} app:assembleDebug'.format(os.path.join('.', 'gradlew')), shell=True) if proc.returncode != 0: error('Build Magisk Manager failed!') + source = os.path.join('app', 'build', 'outputs', 'apk', 'debug', 'app-debug.apk') + mkdir(os.path.join('..', 'out')) + target = os.path.join('..', 'out', 'app-debug.apk') + print('') + mv(source, target) + # Return to upper directory os.chdir('..') @@ -145,11 +196,137 @@ def build_snet(args): if proc.returncode != 0: error('Build snet extention failed!') source = os.path.join('snet', 'build', 'outputs', 'apk', 'release', 'snet-release-unsigned.apk') - target = os.path.join('..', 'snet.apk') + mkdir(os.path.join('..', 'out')) + target = os.path.join('..', 'out', 'snet.apk') print('') - cp(source, target) + mv(source, target) os.chdir('..') +def gen_update_binary(): + update_bin = [] + binary = os.path.join('out', 'armeabi-v7a', 'b64xz') + if not os.path.exists(binary): + error('Please build \'binary\' before zipping!') + with open(binary, 'rb') as b64xz: + update_bin.append('#! /sbin/sh\nEX_ARM=\'') + update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read())) + binary = os.path.join('out', 'x86', 'b64xz') + with open(binary, 'rb') as b64xz: + update_bin.append('\'\nEX_X86=\'') + update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read())) + binary = os.path.join('out', 'armeabi-v7a', 'busybox') + with open(binary, 'rb') as busybox: + update_bin.append('\'\nBB_ARM=') + update_bin.append(base64.b64encode(lzma.compress(busybox.read(), preset=9)).decode('ascii')) + binary = os.path.join('out', 'x86', 'busybox') + with open(binary, 'rb') as busybox: + update_bin.append('\nBB_X86=') + update_bin.append(base64.b64encode(lzma.compress(busybox.read(), preset=9)).decode('ascii')) + update_bin.append('\n') + with open(os.path.join('scripts', 'update_binary.sh'), 'r') as script: + update_bin.append(script.read()) + return ''.join(update_bin) + +def zip_main(args): + header('* Packing Flashable Zip') + + with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf: + # META-INF + # update-binary + target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary') + print('zip: ' + target) + zipf.writestr(target, gen_update_binary()) + # updater-script + source = os.path.join('scripts', 'flash_script.sh') + target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script') + zip_with_msg(zipf, source, target) + + # Binaries + for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]: + for binary in ['monogisk', 'magiskboot']: + source = os.path.join('out', lib_dir, binary) + target = os.path.join(zip_dir, binary) + zip_with_msg(zipf, source, target) + + # APK + source = os.path.join('out', 'app-release.apk' if args.release else 'app-debug.apk') + target = os.path.join('common', 'magisk.apk') + zip_with_msg(zipf, source, target) + + # Scripts + # boot_patch.sh + source = os.path.join('scripts', 'boot_patch.sh') + target = os.path.join('common', 'boot_patch.sh') + zip_with_msg(zipf, source, target) + # util_functions.sh + source = os.path.join('scripts', 'util_functions.sh') + 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)) + target = os.path.join('common', 'util_functions.sh') + print('zip: ' + source + ' -> ' + target) + zipf.writestr(target, util_func) + # addon.d.sh + source = os.path.join('scripts', 'addon.d.sh') + target = os.path.join('addon.d', '99-magisk.sh') + zip_with_msg(zipf, source, target) + + # Prebuilts + for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']: + source = os.path.join('chromeos', chromeos) + zip_with_msg(zipf, source, source) + + # End of zipping + + output = os.path.join('out', 'Magisk-v{}.zip'.format(args.versionString)) + sign_adjust_zip('tmp_unsigned.zip', output) + +def zip_uninstaller(args): + header('* Packing Uninstaller Zip') + + with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf: + # META-INF + # update-binary + target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary') + print('zip: ' + target) + zipf.writestr(target, gen_update_binary()) + # updater-script + source = os.path.join('scripts', 'uninstaller_loader.sh') + target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script') + zip_with_msg(zipf, source, target) + + # Binaries + for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]: + source = os.path.join('out', lib_dir, 'magiskboot') + target = os.path.join(zip_dir, 'magiskboot') + zip_with_msg(zipf, source, target) + + source = os.path.join('scripts', 'magisk_uninstaller.sh') + target = 'magisk_uninstaller.sh' + zip_with_msg(zipf, source, target) + + # Scripts + # util_functions.sh + 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) + + # Prebuilts + for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']: + source = os.path.join('chromeos', chromeos) + zip_with_msg(zipf, source, source) + + # End of zipping + + output = os.path.join('out', 'Magisk-uninstaller-{}.zip'.format(datetime.datetime.now().strftime('%Y%m%d'))) + sign_adjust_zip('tmp_unsigned.zip', output) + def sign_adjust_zip(unsigned, output): signer_name = 'zipsigner-1.0.jar' jarsigner = os.path.join('java', 'crypto', 'build', 'libs', signer_name) @@ -191,142 +368,9 @@ def sign_adjust_zip(unsigned, output): error('Second sign flashable zip failed!') # Cleanup - silentremove(unsigned) - silentremove('tmp_signed.zip') - silentremove('tmp_adjusted.zip') - -def gen_update_binary(): - update_bin = [] - binary = os.path.join('libs', 'armeabi-v7a', 'b64xz') - if not os.path.exists(binary): - error('Please build \'binary\' before zipping!') - with open(binary, 'rb') as b64xz: - update_bin.append('#! /sbin/sh\nEX_ARM=\'') - update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read())) - binary = os.path.join('libs', 'x86', 'b64xz') - with open(binary, 'rb') as b64xz: - update_bin.append('\'\nEX_X86=\'') - update_bin.append(''.join("\\x{:02X}".format(c) for c in b64xz.read())) - binary = os.path.join('libs', 'armeabi-v7a', 'busybox') - with open(binary, 'rb') as busybox: - update_bin.append('\'\nBB_ARM=') - update_bin.append(base64.b64encode(lzma.compress(busybox.read())).decode('ascii')) - binary = os.path.join('libs', 'x86', 'busybox') - with open(binary, 'rb') as busybox: - update_bin.append('\nBB_X86=') - update_bin.append(base64.b64encode(lzma.compress(busybox.read())).decode('ascii')) - update_bin.append('\n') - with open(os.path.join('scripts', 'update_binary.sh'), 'r') as script: - update_bin.append(script.read()) - return ''.join(update_bin) - -def zip_main(args): - header('* Packing Flashable Zip') - - with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf: - # META-INF - # update-binary - target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary') - print('zip: ' + target) - zipf.writestr(target, gen_update_binary()) - # updater-script - source = os.path.join('scripts', 'flash_script.sh') - target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script') - zip_with_msg(zipf, source, target) - - # Binaries - for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]: - for binary in ['magisk', 'magiskboot']: - source = os.path.join('libs', lib_dir, binary) - target = os.path.join(zip_dir, binary) - zip_with_msg(zipf, source, target) - source = os.path.join('libs', 'arm64-v8a', 'magiskinit') - target = os.path.join('arm64', 'magiskinit') - zip_with_msg(zipf, source, target) - - # APK - source = os.path.join('java', 'app', 'build', 'outputs', 'apk', - 'release' if args.release else 'debug', 'app-release.apk' if args.release else 'app-debug.apk') - target = os.path.join('common', 'magisk.apk') - zip_with_msg(zipf, source, target) - - # Scripts - # boot_patch.sh - source = os.path.join('scripts', 'boot_patch.sh') - target = os.path.join('common', 'boot_patch.sh') - zip_with_msg(zipf, source, target) - # util_functions.sh - source = os.path.join('scripts', 'util_functions.sh') - 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)) - target = os.path.join('common', 'util_functions.sh') - print('zip: ' + source + ' -> ' + target) - zipf.writestr(target, util_func) - # addon.d.sh - source = os.path.join('scripts', 'addon.d.sh') - target = os.path.join('addon.d', '99-magisk.sh') - zip_with_msg(zipf, source, target) - # init.magisk.rc - source = os.path.join('scripts', 'init.magisk.rc') - target = os.path.join('common', 'init.magisk.rc') - zip_with_msg(zipf, source, target) - - # Prebuilts - for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']: - source = os.path.join('chromeos', chromeos) - zip_with_msg(zipf, source, source) - - # End of zipping - - output = 'Magisk-v{}.zip'.format(args.versionString) - sign_adjust_zip('tmp_unsigned.zip', output) - -def zip_uninstaller(args): - header('* Packing Uninstaller Zip') - - with zipfile.ZipFile('tmp_unsigned.zip', 'w', compression=zipfile.ZIP_DEFLATED, allowZip64=False) as zipf: - # META-INF - # update-binary - target = os.path.join('META-INF', 'com', 'google', 'android', 'update-binary') - print('zip: ' + target) - zipf.writestr(target, gen_update_binary()) - # updater-script - source = os.path.join('scripts', 'uninstaller_loader.sh') - target = os.path.join('META-INF', 'com', 'google', 'android', 'updater-script') - zip_with_msg(zipf, source, target) - - # Binaries - for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]: - source = os.path.join('libs', lib_dir, 'magiskboot') - target = os.path.join(zip_dir, 'magiskboot') - zip_with_msg(zipf, source, target) - - source = os.path.join('scripts', 'magisk_uninstaller.sh') - target = 'magisk_uninstaller.sh' - zip_with_msg(zipf, source, target) - - # Scripts - # util_functions.sh - 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) - - # Prebuilts - for chromeos in ['futility', 'kernel_data_key.vbprivk', 'kernel.keyblock']: - source = os.path.join('chromeos', chromeos) - zip_with_msg(zipf, source, source) - - # End of zipping - - output = 'Magisk-uninstaller-{}.zip'.format(datetime.datetime.now().strftime('%Y%m%d')) - sign_adjust_zip('tmp_unsigned.zip', output) + rm(unsigned) + rm('tmp_signed.zip') + rm('tmp_adjusted.zip') def cleanup(args): if len(args.target) == 0: @@ -335,20 +379,23 @@ def cleanup(args): if 'binary' in args.target: header('* Cleaning binaries') subprocess.run(os.path.join(os.environ['ANDROID_HOME'], 'ndk-bundle', 'ndk-build') + ' clean', shell=True) + for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']: + shutil.rmtree(os.path.join('out', arch), ignore_errors=True) if 'java' in args.target: header('* Cleaning java') os.chdir('java') subprocess.run('{} clean'.format(os.path.join('.', 'gradlew')), shell=True) os.chdir('..') - silentremove('snet.apk') + for f in os.listdir('out'): + if '.apk' in f: + rm(os.path.join('out', f)) if 'zip' in args.target: header('* Cleaning zip files') - for f in os.listdir('.'): + for f in os.listdir('out'): if '.zip' in f: - print('rm {}'.format(f)) - silentremove(f) + rm(os.path.join('out', f)) parser = argparse.ArgumentParser(description='Magisk build script') parser.add_argument('--release', action='store_true', help='compile Magisk for release') diff --git a/java b/java index fdd700f3e..99c74b31b 160000 --- a/java +++ b/java @@ -1 +1 @@ -Subproject commit fdd700f3e5c2f9d7688d2434d4dbee8c12524411 +Subproject commit 99c74b31be15a239fdffe4a727d2d83feb52b8bb diff --git a/jni/Android.mk b/jni/Android.mk index e09f0c484..da30626bf 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -14,17 +14,17 @@ LIBFDT := $(EXT_PATH)/dtc/libfdt # Binaries ######################## +ifdef PRECOMPILE + # magisk main binary include $(CLEAR_VARS) LOCAL_MODULE := magisk -LOCAL_STATIC_LIBRARIES := libsepol LOCAL_SHARED_LIBRARIES := libsqlite libselinux LOCAL_C_INCLUDES := \ jni/include \ jni/external \ - $(LIBSELINUX) \ - $(LIBSEPOL) + $(LIBSELINUX) LOCAL_SRC_FILES := \ daemon/magisk.c \ @@ -41,10 +41,6 @@ LOCAL_SRC_FILES := \ magiskhide/magiskhide.c \ magiskhide/proc_monitor.c \ magiskhide/hide_utils.c \ - magiskpolicy/magiskpolicy.c \ - magiskpolicy/rules.c \ - magiskpolicy/sepolicy.c \ - magiskpolicy/api.c \ resetprop/resetprop.cpp \ resetprop/system_properties.cpp \ su/su.c \ @@ -59,6 +55,37 @@ LOCAL_CPPFLAGS := -std=c++11 LOCAL_LDLIBS := -llog include $(BUILD_EXECUTABLE) +# magiskinit +include $(CLEAR_VARS) +LOCAL_MODULE := magiskinit +LOCAL_STATIC_LIBRARIES := libsepol +LOCAL_C_INCLUDES := jni/include $(LIBSEPOL) +LOCAL_SRC_FILES := \ + init/magiskinit.c \ + utils/vector.c \ + utils/file.c \ + utils/xwrap.c \ + magiskpolicy/api.c \ + magiskpolicy/magiskpolicy.c \ + magiskpolicy/rules.c \ + magiskpolicy/sepolicy.c + +LOCAL_CFLAGS := -DNO_SELINUX +LOCAL_LDFLAGS := -static +include $(BUILD_EXECUTABLE) + +# precompile +else + +# monogisk +include $(CLEAR_VARS) +LOCAL_MODULE := monogisk +LOCAL_STATIC_LIBRARIES := liblzma +LOCAL_C_INCLUDES := jni/include out/$(TARGET_ARCH_ABI) $(LIBLZMA) +LOCAL_SRC_FILES := init/monogisk.c +LOCAL_LDFLAGS := -static +include $(BUILD_EXECUTABLE) + # magiskboot include $(CLEAR_VARS) LOCAL_MODULE := magiskboot @@ -81,29 +108,13 @@ LOCAL_SRC_FILES := \ magiskboot/types.c \ magiskboot/dtb.c \ utils/xwrap.c \ + utils/file.c \ utils/vector.c + +LOCAL_CFLAGS := -DNO_SELINUX LOCAL_LDLIBS := -lz include $(BUILD_EXECUTABLE) -# magiskinit -ifeq ($(TARGET_ARCH_ABI), arm64-v8a) -include $(CLEAR_VARS) -LOCAL_MODULE := magiskinit -LOCAL_STATIC_LIBRARIES := libsepol -LOCAL_C_INCLUDES := jni/include $(LIBSEPOL) -LOCAL_SRC_FILES := \ - magiskinit.c \ - magiskboot/boot_utils.c \ - utils/file.c \ - utils/xwrap.c \ - magiskpolicy/rules.c \ - magiskpolicy/sepolicy.c \ - magiskpolicy/api.c -LOCAL_CFLAGS := -DNO_SELINUX -LOCAL_LDFLAGS := -static -include $(BUILD_EXECUTABLE) -endif - # 32-bit static binaries ifneq ($(TARGET_ARCH_ABI), x86_64) ifneq ($(TARGET_ARCH_ABI), arm64-v8a) @@ -120,6 +131,9 @@ include jni/external/busybox/Android.mk endif endif +# Precompile +endif + ######################## # Externals ######################## diff --git a/jni/daemon/bootstages.c b/jni/daemon/bootstages.c index ce661bee8..37ebc6234 100644 --- a/jni/daemon/bootstages.c +++ b/jni/daemon/bootstages.c @@ -568,7 +568,7 @@ void fix_filecon() { ****************/ static void unblock_boot_process() { - close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT)); + close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT, 0)); pthread_exit(NULL); } @@ -743,7 +743,8 @@ void late_start(int client) { if (buf2 == NULL) buf2 = xmalloc(PATH_MAX); // Wait till the full patch is done - pthread_join(sepol_patch, NULL); + while (access(PATCHDONE, F_OK) == -1) + usleep(500); /* Wait 0.5ms */ // Run scripts after full patch, most reliable way to run scripts LOGI("* Running service.d scripts\n"); diff --git a/jni/daemon/daemon.c b/jni/daemon/daemon.c index f090e7afe..87b7a53dc 100644 --- a/jni/daemon/daemon.c +++ b/jni/daemon/daemon.c @@ -103,16 +103,6 @@ static int setup_socket(struct sockaddr_un *sun) { return fd; } -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(SELINUX_LOAD); - LOGD("sepol: Large patch done\n"); - destroy_policydb(); - return NULL; -} - static void *start_magisk_hide(void *args) { launch_magiskhide(-1); return NULL; @@ -137,11 +127,6 @@ void start_daemon() { xdup2(fd, STDERR_FILENO); close(fd); - // Patch selinux with medium patch before we do anything - load_policydb(SELINUX_POLICY); - sepol_med_rules(); - dump_policydb(SELINUX_LOAD); - struct sockaddr_un sun; fd = setup_socket(&sun); @@ -159,9 +144,6 @@ void start_daemon() { // Start the log monitor monitor_logs(); - // Continue the larger patch in another thread, we will join later - xpthread_create(&sepol_patch, NULL, large_sepol_patch, NULL); - LOGI("Magisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") daemon started\n"); // Change process name diff --git a/jni/daemon/magisk.c b/jni/daemon/magisk.c index cc78fa218..ab824cbb3 100644 --- a/jni/daemon/magisk.c +++ b/jni/daemon/magisk.c @@ -4,6 +4,7 @@ #include #include #include +#include #include "utils.h" #include "magisk.h" @@ -12,10 +13,10 @@ char *argv0; char *applet[] = - { "su", "resetprop", "magiskpolicy", "supolicy", "magiskhide", NULL }; + { "su", "resetprop", "magiskhide", NULL }; int (*applet_main[]) (int, char *[]) = - { su_client_main, resetprop_main, magiskpolicy_main, magiskpolicy_main, magiskhide_main, NULL }; + { su_client_main, resetprop_main, magiskhide_main, NULL }; int create_links(const char *bin, const char *path) { char self[PATH_MAX], linkpath[PATH_MAX]; @@ -56,7 +57,7 @@ static void usage() { " --clone-attr SRC DEST clone permission, owner, and selinux context\n" "\n" "Supported init services:\n" - " daemon post-fs, post-fs-data, service\n" + " daemon, post-fs, post-fs-data, service\n" "\n" "Supported applets:\n" , argv0, argv0); @@ -69,10 +70,7 @@ static void usage() { int main(int argc, char *argv[]) { argv0 = argv[0]; - char * arg = strrchr(argv[0], '/'); - if (arg) ++arg; - else arg = argv[0]; - if (strcmp(arg, "magisk") == 0) { + if (strcmp(basename(argv[0]), "magisk") == 0) { if (argc < 2) usage(); if (strcmp(argv[1], "-c") == 0) { printf("%s\n", MAGISK_VER_STR); @@ -168,16 +166,15 @@ int main(int argc, char *argv[]) { // It's calling applets --argc; ++argv; - arg = argv[0]; } } // Applets for (int i = 0; applet[i]; ++i) { - if (strcmp(arg, applet[i]) == 0) + if (strcmp(basename(argv[0]), applet[i]) == 0) return (*applet_main[i])(argc, argv); } - fprintf(stderr, "%s: applet not found\n", arg); + fprintf(stderr, "%s: applet not found\n", basename(argv[0])); return 1; } diff --git a/jni/include/logging.h b/jni/include/logging.h index e36b719fd..8ad898942 100644 --- a/jni/include/logging.h +++ b/jni/include/logging.h @@ -8,6 +8,9 @@ #include #include +#define str(a) #a +#define xstr(a) str(a) + #ifdef IS_DAEMON #include diff --git a/jni/include/magisk.h b/jni/include/magisk.h index 4bb9deddb..c1eb645a2 100644 --- a/jni/include/magisk.h +++ b/jni/include/magisk.h @@ -6,9 +6,6 @@ #include "logging.h" -#define str(a) #a -#define xstr(a) str(a) - #define MAGISK_VER_STR xstr(MAGISK_VERSION) ":MAGISK" #define REQUESTOR_DAEMON_PATH "\0MAGISK" @@ -20,6 +17,7 @@ #define LASTLOG "/cache/last_magisk.log" #define DEBUG_LOG "/data/magisk_debug.log" #define UNBLOCKFILE "/dev/.magisk.unblock" +#define PATCHDONE "/dev/.magisk.patch.done" #define DISABLEFILE "/cache/.disable_magisk" #define UNINSTALLER "/cache/magisk_uninstaller.sh" #define CACHEMOUNT "/cache/magisk_mount" diff --git a/jni/include/magiskrc.h b/jni/include/magiskrc.h new file mode 100644 index 000000000..ff7e6ff79 --- /dev/null +++ b/jni/include/magiskrc.h @@ -0,0 +1,45 @@ +const char magiskrc[] = + +// Triggers + +"on post-fs\n" +" start logd\n" +" start magisk_daemon\n" +" wait /dev/.magisk.unblock 5\n" +" rm /dev/.magisk.unblock\n" +" start magisk_pfs\n" +" wait /dev/.magisk.unblock 10\n" +"\n" + +"on post-fs-data\n" +" load_persist_props\n" +" rm /dev/.magisk.unblock\n" +" start magisk_pfsd\n" +" wait /dev/.magisk.unblock 10\n" +"\n" + +// Services + +"service magisk_daemon /sbin/magisk --daemon\n" +" user root\n" +" seclabel u:r:su:s0\n" +"\n" + +"service magisk_pfs /sbin/magisk --post-fs\n" +" user root\n" +" seclabel u:r:su:s0\n" +" oneshot\n" +"\n" + +"service magisk_pfsd /sbin/magisk --post-fs-data\n" +" user root\n" +" seclabel u:r:su:s0\n" +" oneshot\n" +"\n" + +"service magisk_service /sbin/magisk --service\n" +" class late_start\n" +" user root\n" +" seclabel u:r:su:s0\n" +" oneshot\n" +; diff --git a/jni/include/utils.h b/jni/include/utils.h index d979bd622..69963840b 100644 --- a/jni/include/utils.h +++ b/jni/include/utils.h @@ -116,6 +116,8 @@ int fsetattr(int fd, struct file_attr *a); void fclone_attr(const int sourcefd, const int targetfd); void clone_attr(const char *source, const char *target); void restorecon(int dirfd, int force); +void mmap_ro(const char *filename, void **buf, size_t *size); +void mmap_rw(const char *filename, void **buf, size_t *size); // img.c diff --git a/jni/init/magiskinit.c b/jni/init/magiskinit.c new file mode 100644 index 000000000..6e2c11157 --- /dev/null +++ b/jni/init/magiskinit.c @@ -0,0 +1,364 @@ +/* magiskinit.c - Pre-init Magisk support + * + * This code has to be compiled statically to work properly. + * + * This binary will be extracted from monogisk, and dos all pre-init operations to setup + * a Magisk environment. The tool modifies rootfs on the fly, providing fundamental support + * such as init, init.rc, and sepolicy patching. Magiskinit is also responsible to construct + * a proper rootfs on skip_initramfs devices. + * On skip_initramfs devices, it will parse kernel cmdline, mount sysfs, parse through + * uevent files to make the system (or vendor if available) block device node, then copy + * rootfs files from system. The "overlay" folder is constructed by monogisk, + * which contains additional files extracted from the tool. These files will be moved to /. + * This tool will be replaced with the real init to continue the boot process, but hardlinks are + * preserved as it also provides CLI for sepolicy patching (magiskpolicy) + */ + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include + +#include "magisk.h" +#include "utils.h" +#include "magiskpolicy.h" + +struct cmdline { + int skip_initramfs; + char slot[3]; +}; + +struct device { + dev_t major; + dev_t minor; + char devname[32]; + char partname[32]; + char path[64]; +}; + +extern policydb_t *policydb; + +static void parse_cmdline(struct cmdline *cmd) { + char *tok; + char buffer[4096]; + mkdir("/proc", 0555); + mount("proc", "/proc", "proc", 0, NULL); + int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC); + ssize_t size = read(fd, buffer, sizeof(buffer)); + buffer[size] = '\0'; + close(fd); + umount("/proc"); + tok = strtok(buffer, " "); + cmd->skip_initramfs = 0; + cmd->slot[0] = '\0'; + while (tok != NULL) { + if (strncmp(tok, "androidboot.slot_suffix", 23) == 0) { + sscanf(tok, "androidboot.slot_suffix=%s", cmd->slot); + } else if (strcmp(tok, "skip_initramfs") == 0) { + cmd->skip_initramfs = 1; + } + tok = strtok(NULL, " "); + } +} + +static void parse_device(struct device *dev, char *uevent) { + char *tok; + tok = strtok(uevent, "\n"); + while (tok != NULL) { + if (strncmp(tok, "MAJOR", 5) == 0) { + sscanf(tok, "MAJOR=%ld", (long*) &dev->major); + } else if (strncmp(tok, "MINOR", 5) == 0) { + sscanf(tok, "MINOR=%ld", (long*) &dev->minor); + } else if (strncmp(tok, "DEVNAME", 7) == 0) { + sscanf(tok, "DEVNAME=%s", dev->devname); + } else if (strncmp(tok, "PARTNAME", 8) == 0) { + sscanf(tok, "PARTNAME=%s", dev->partname); + } + tok = strtok(NULL, "\n"); + } +} + +static int setup_block(struct device *dev, const char *partname) { + char buffer[1024], path[128]; + struct dirent *entry; + DIR *dir = opendir("/sys/dev/block"); + if (dir == NULL) + return 1; + int found = 0; + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + snprintf(path, sizeof(path), "/sys/dev/block/%s/uevent", entry->d_name); + int fd = open(path, O_RDONLY | O_CLOEXEC); + ssize_t size = read(fd, buffer, sizeof(buffer)); + buffer[size] = '\0'; + close(fd); + parse_device(dev, buffer); + if (strcmp(dev->partname, partname) == 0) { + snprintf(dev->path, sizeof(dev->path), "/dev/block/%s", dev->devname); + found = 1; + break; + } + } + closedir(dir); + + if (!found) + return 1; + + mkdir("/dev", 0755); + mkdir("/dev/block", 0755); + mknod(dev->path, S_IFBLK | 0600, makedev(dev->major, dev->minor)); + return 0; +} + +static void *patch_init_rc(char *data, uint32_t *size) { + int injected = 0; + char *new_data = malloc(*size + 23); + char *old_data = data; + uint32_t pos = 0; + + for (char *tok = strsep(&old_data, "\n"); tok; tok = strsep(&old_data, "\n")) { + if (!injected && strncmp(tok, "import", 6) == 0) { + if (strstr(tok, "init.magisk.rc")) { + injected = 1; + } else { + strcpy(new_data + pos, "import /init.magisk.rc\n"); + pos += 23; + injected = 1; + } + } else if (strstr(tok, "selinux.reload_policy")) { + continue; + } + // Copy the line + strcpy(new_data + pos, tok); + pos += strlen(tok); + new_data[pos++] = '\n'; + } + + *size = pos; + return new_data; +} + +static void patch_ramdisk() { + void *addr; + size_t size; + mmap_rw("/init", &addr, &size); + for (int i = 0; i < size; ++i) { + if (memcmp(addr + i, "/system/etc/selinux/plat_sepolicy.cil", 37) == 0) { + memcpy(addr + i, "/system/etc/selinux/plat_sepolicy.xxx", 37); + break; + } + } + munmap(addr, size); + + mmap_rw("/init.rc", &addr, &size); + uint32_t new_size = size; + void *init_rc = patch_init_rc(addr, &new_size); + munmap(addr, size); + + int fd = open("/init.rc", O_WRONLY | O_TRUNC | O_CLOEXEC); + write(fd, init_rc, new_size); + close(fd); + free(init_rc); +} + +static int strend(const char *s1, const char *s2) { + int l1 = strlen(s1); + int l2 = strlen(s2); + return strcmp(s1 + l1 - l2, s2); +} + +static int compile_cil() { + DIR *dir; + struct dirent *entry; + char path[128]; + + struct cil_db *db = NULL; + sepol_policydb_t *pdb = NULL; + void *addr; + size_t size; + + cil_db_init(&db); + cil_set_mls(db, 1); + cil_set_target_platform(db, SEPOL_TARGET_SELINUX); + cil_set_policy_version(db, POLICYDB_VERSION_XPERMS_IOCTL); + cil_set_attrs_expand_generated(db, 0); + + // plat + mmap_ro("/system/etc/selinux/plat_sepolicy.cil", &addr, &size); + cil_add_file(db, "/system/etc/selinux/plat_sepolicy.cil", addr, size); + munmap(addr, size); + + // mapping + char plat[10]; + int fd = open("/vendor/etc/selinux/plat_sepolicy_vers.txt", O_RDONLY | O_CLOEXEC); + if (fd > 0) { + plat[read(fd, plat, sizeof(plat)) - 1] = '\0'; + snprintf(path, sizeof(path), "/system/etc/selinux/mapping/%s.cil", plat); + mmap_ro(path, &addr, &size); + cil_add_file(db, path, addr, size); + munmap(addr, size); + close(fd); + } + + dir = opendir("/vendor/etc/selinux"); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".cil") == 0) { + snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name); + mmap_ro(path, &addr, &size); + cil_add_file(db, path, addr, size); + munmap(addr, size); + } + } + closedir(dir); + + cil_compile(db); + cil_build_policydb(db, &pdb); + cil_db_destroy(&db); + + policydb = &pdb->p; + + return 0; +} + +static int verify_precompiled() { + DIR *dir; + struct dirent *entry; + int fd; + char sys_sha[70], ven_sha[70]; + + dir = opendir("/vendor/etc/selinux"); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".sha256") == 0) { + fd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_CLOEXEC); + ven_sha[read(fd, ven_sha, sizeof(ven_sha))] = '\0'; + close(fd); + break; + } + } + closedir(dir); + dir = opendir("/system/etc/selinux"); + while ((entry = readdir(dir))) { + if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) + continue; + if (strend(entry->d_name, ".sha256") == 0) { + fd = openat(dirfd(dir), entry->d_name, O_RDONLY | O_CLOEXEC); + sys_sha[read(fd, sys_sha, sizeof(sys_sha))] = '\0'; + close(fd); + break; + } + } + closedir(dir); + return strcmp(sys_sha, ven_sha); +} + +static void patch_sepolicy() { + if (access("/sepolicy", R_OK) == 0) { + load_policydb("/sepolicy"); + } else if (access("/vendor/etc/selinux/precompiled_sepolicy", R_OK) == 0 + && verify_precompiled() == 0) { + load_policydb("/vendor/etc/selinux/precompiled_sepolicy"); + } else if (access("/system/etc/selinux/plat_sepolicy.cil", R_OK) == 0) { + compile_cil(); + } + + sepol_med_rules(); + dump_policydb("/sepolicy"); +} + +int main(int argc, char *argv[]) { + if (strcmp(basename(argv[0]), "magiskpolicy") == 0 || strcmp(basename(argv[0]), "supolicy") == 0) + return magiskpolicy_main(argc, argv); + if (argc > 1 && (strcmp(argv[1], "magiskpolicy") == 0 || strcmp(argv[1], "supolicy") == 0)) + return magiskpolicy_main(argc - 1, argv + 1); + + umask(0); + + struct cmdline cmd; + parse_cmdline(&cmd); + + int root = open("/", O_RDONLY | O_CLOEXEC); + + if (cmd.skip_initramfs) { + // Exclude overlay folder + excl_list = (char *[]) { "overlay", ".backup", NULL }; + // Clear rootfs + frm_rf(root); + + mkdir("/sys", 0755); + mount("sysfs", "/sys", "sysfs", 0, NULL); + + char partname[32]; + snprintf(partname, sizeof(partname), "system%s", cmd.slot); + + struct device dev; + setup_block(&dev, partname); + + mkdir("/system_root", 0755); + mount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL); + int system_root = open("/system_root", O_RDONLY | O_CLOEXEC); + + // Exclude system folder + excl_list = (char *[]) { "system", NULL }; + clone_dir(system_root, root); + mkdir("/system", 0755); + mount("/system_root/system", "/system", NULL, MS_BIND, NULL); + + snprintf(partname, sizeof(partname), "vendor%s", cmd.slot); + + // We need to mount independent vendor partition + if (setup_block(&dev, partname) == 0) + mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL); + + close(system_root); + } else { + // Revert original init binary + unlink("/init"); + link("/.backup/init", "/init"); + } + + int overlay = open("/overlay", O_RDONLY | O_CLOEXEC); + mv_dir(overlay, root); + + patch_ramdisk(); + patch_sepolicy(); + + // Clean up + rmdir("/overlay"); + umount("/vendor"); + close(overlay); + close(root); + + if (fork() == 0) { + // Fork a new process for full patch + setsid(); + sepol_allow("su", ALL, ALL, ALL); + while (access(SELINUX_LOAD, W_OK) == -1) { + usleep(500); /* Wait 0.5ms */ + } + dump_policydb(SELINUX_LOAD); + close(open(PATCHDONE, O_RDONLY | O_CREAT, 0)); + destroy_policydb(); + } else { + // Finally, give control back! + execv("/init", argv); + } + + return 0; +} diff --git a/jni/init/monogisk.c b/jni/init/monogisk.c new file mode 100644 index 000000000..1d587e136 --- /dev/null +++ b/jni/init/monogisk.c @@ -0,0 +1,121 @@ +/* monogisk.c - Monolithic binary hosting Magisk binaries + * + * This code has to be compiled statically to work properly. + * + * To unify Magisk support for both legacy "normal" devices and new skip_initramfs devices, + * this tool is born. Magisk binary compilation is split into two parts - first part contains + * "magisk" and "magiskinit". The python build script will load these 2 binaries and compress + * them with lzma2, dumping the results into "dump.h". Monogisk is simply just a static lzma + * extractor embedded with binary blobs, with a few additional operations to construct an + * environment for "magiskinit" to handle the rest of the work. + */ + + +#include +#include +#include +#include +#include +#include + +#include "dump.h" +#include "magiskrc.h" + +#define str(a) #a +#define xstr(a) str(a) +#define BUFSIZE 0x100000 + +lzma_stream strm = LZMA_STREAM_INIT; + +static void usage() { + const char usage[] = + "Monogisk v" xstr(MAGISK_VERSION) "(" xstr(MAGISK_VER_CODE) ") (by topjohnwu)\n" + "A monolithic binary used as /init to add Magisk support\n" + "\n" + "Usage:\n" + " monogisk -x \n" + " extract \"magisk\", \"magiskinit\", or \"magiskrc\"\n" + " /init\n" + " Startup the system with Magisk support\n" + "\n"; + write(STDERR_FILENO, usage, sizeof(usage)); + exit(1); +} + +static int unxz(lzma_stream *strm, const void *buf, size_t size, int fd) { + lzma_ret ret = 0; + uint8_t out[BUFSIZE]; + strm->next_in = buf; + strm->avail_in = size; + do { + strm->next_out = out; + strm->avail_out = sizeof(out); + ret = lzma_code(strm, LZMA_RUN); + write(fd, out, sizeof(out) - strm->avail_out); + } while (strm->avail_out == 0 && ret == LZMA_OK); + + if (ret != LZMA_OK && ret != LZMA_STREAM_END) + write(STDERR_FILENO, "LZMA error!\n", 13); + return ret; +} + +static int dump_magisk(const char *path, mode_t mode) { + if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK) + return 1; + unlink(path); + int fd = creat(path, mode); + int ret = unxz(&strm, magisk_dump, sizeof(magisk_dump), fd); + close(fd); + return ret; +} + +static int dump_magiskinit(const char *path, mode_t mode) { + if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK) + return 1; + unlink(path); + int fd = creat(path, mode); + int ret = unxz(&strm, magiskinit_dump, sizeof(magiskinit_dump), fd); + close(fd); + return ret; +} + +static int dump_magiskrc(const char *path, mode_t mode) { + unlink(path); + int fd = creat(path, mode); + write(fd, magiskrc, sizeof(magiskrc)); + close(fd); + return 0; +} + +static int init_main(int argc, char *argv[]) { + dump_magiskinit("/init", 0750); + mkdir("/overlay", 0); + dump_magiskrc("/overlay/init.magisk.rc", 0750); + mkdir("/overlay/sbin", 0755); + dump_magisk("/overlay/sbin/magisk", 0755); + mkdir("/overlay/root", 0755); + link("/init", "/overlay/root/magiskpolicy"); + link("/init", "/overlay/root/supolicy"); + execv("/init", argv); + return 1; /* Should not happen */ +} + +int main(int argc, char *argv[]) { + umask(0); + + if (argc == 1) + return init_main(argc, argv); + + if (argc < 4) + usage(); + + if (strcmp(argv[2], "magisk") == 0) + dump_magisk(argv[3], 0755); + else if (strcmp(argv[2], "magiskinit") == 0) + dump_magiskinit(argv[3], 0755); + else + usage(); + + lzma_end(&strm); + return 0; +} diff --git a/jni/magiskboot/boot_utils.c b/jni/magiskboot/boot_utils.c index 62a029adf..f01cb4b64 100644 --- a/jni/magiskboot/boot_utils.c +++ b/jni/magiskboot/boot_utils.c @@ -1,25 +1,8 @@ #include #include -#include #include "utils.h" -void mmap_ro(const char *filename, void **buf, size_t *size) { - int fd = xopen(filename, O_RDONLY); - *size = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); - *buf = *size > 0 ? xmmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0) : NULL; - close(fd); -} - -void mmap_rw(const char *filename, void **buf, size_t *size) { - int fd = xopen(filename, O_RDWR); - *size = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); - *buf = *size > 0 ? xmmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) : NULL; - close(fd); -} - void write_zero(int fd, size_t size) { size_t pos = lseek(fd, 0, SEEK_CUR); ftruncate(fd, pos + size); @@ -51,35 +34,6 @@ int open_new(const char *filename) { return xopen(filename, O_WRONLY | O_CREAT | O_TRUNC, 0644); } -void *patch_init_rc(char *data, uint32_t *size) { - int injected = 0; - char *new_data = xmalloc(*size + 23); - char *old_data = data; - uint32_t pos = 0; - - for (char *tok = strsep(&old_data, "\n"); tok; tok = strsep(&old_data, "\n")) { - if (!injected && strncmp(tok, "import", 6) == 0) { - if (strstr(tok, "init.magisk.rc")) { - injected = 1; - } else { - fprintf(stderr, "Inject [import /init.magisk.rc] to [init.rc]\n"); - strcpy(new_data + pos, "import /init.magisk.rc\n"); - pos += 23; - injected = 1; - } - } else if (strstr(tok, "selinux.reload_policy")) { - continue; - } - // Copy the line - strcpy(new_data + pos, tok); - pos += strlen(tok); - new_data[pos++] = '\n'; - } - - *size = pos; - return new_data; -} - int check_verity_pattern(const char *s) { int pos = 0; if (s[0] == ',') ++pos; diff --git a/jni/magiskboot/cpio.c b/jni/magiskboot/cpio.c index 164d04865..f302ba29b 100644 --- a/jni/magiskboot/cpio.c +++ b/jni/magiskboot/cpio.c @@ -186,7 +186,7 @@ static void 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[] = { "init.magisk.rc", "overlay/init.magisk.rc", 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) { @@ -208,42 +208,36 @@ static void cpio_patch(struct vector *v, int keepverity, int keepforceencrypt) { cpio_entry *f; int skip, write; vec_for_each(v, f) { - if (strcmp(f->filename, "init.rc") == 0) { - void *new_data = patch_init_rc(f->data, &f->filesize); - free(f->data); - f->data = new_data; - } else { - 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]; + 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->filesize = write; - } else if (strcmp(f->filename, "verity_key") == 0) { - fprintf(stderr, "Remove [verity_key]\n"); - f->remove = 1; + 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]; + } + 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->filesize = write; + f->data[write] = f->data[read]; } + f->filesize = write; } } } @@ -265,19 +259,35 @@ 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, struct vector *v) { +static void cpio_backup(const char *orig, const char *sha1, struct vector *v) { struct vector o_body, *o = &o_body, bak; - cpio_entry *m, *n, *dir, *rem; + cpio_entry *m, *n, *rem, *cksm; char buf[PATH_MAX]; int res, doBak; - dir = xcalloc(sizeof(*dir), 1); - rem = xcalloc(sizeof(*rem), 1); + if (sha1) cksm = xcalloc(sizeof(*cksm), 1); vec_init(o); vec_init(&bak); - // First push back the directory and the rmlist - vec_push_back(&bak, dir); + + m = xcalloc(sizeof(*m), 1); + m->filename = strdup(".backup"); + m->namesize = strlen(m->filename) + 1; + m->mode = S_IFDIR; + vec_push_back(&bak, m); + + m = xcalloc(sizeof(*m), 1); + m->filename = strdup(".backup/.magisk"); + m->namesize = strlen(m->filename) + 1; + m->mode = S_IFREG; + vec_push_back(&bak, m); + + rem = xcalloc(sizeof(*rem), 1); + rem->filename = strdup(".backup/.rmlist"); + rem->namesize = strlen(rem->filename) + 1; + rem->mode = S_IFREG; vec_push_back(&bak, rem); + + if (sha1) vec_push_back(&bak, cksm); parse_cpio(orig, o); // Remove possible backups in original ramdisk cpio_rm(1, ".backup", o); @@ -287,13 +297,14 @@ static void cpio_backup(const char *orig, struct vector *v) { vec_sort(v, cpio_cmp); vec_sort(o, cpio_cmp); - // Init the directory and rmlist - dir->filename = strdup(".backup"); - dir->namesize = strlen(dir->filename) + 1; - dir->mode = S_IFDIR; - rem->filename = strdup(".backup/.rmlist"); - rem->namesize = strlen(rem->filename) + 1; - rem->mode = S_IFREG; + if (sha1) { + fprintf(stderr, "Save SHA1: [%s] -> [.backup/.sha1]\n", sha1); + cksm->filename = strdup(".backup/.sha1"); + cksm->namesize = strlen(cksm->filename) + 1; + cksm->mode = S_IFREG; + cksm->data = strdup(sha1); + cksm->filesize = strlen(sha1) + 1; + } // Start comparing size_t i = 0, j = 0; @@ -349,12 +360,8 @@ static void cpio_backup(const char *orig, struct vector *v) { vec_push_back(v, m); } - // Don't include if empty - if (rem->filesize == 0) { + if (rem->filesize == 0) rem->remove = 1; - if (bak.size == 2) - dir->remove = 1; - } // Cleanup cpio_vec_destroy(o); @@ -367,21 +374,24 @@ static int cpio_restore(struct vector *v) { if (strstr(f->filename, ".backup") != NULL) { ret = 0; f->remove = 1; - if (strcmp(f->filename, ".backup") == 0) continue; - if (strcmp(f->filename, ".backup/.rmlist") == 0) { - for (int pos = 0; pos < f->filesize; pos += strlen(f->data + pos) + 1) - cpio_rm(0, f->data + pos, v); + 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(0, f->data + pos, v); + } continue; + } else { + n = xcalloc(sizeof(*n), 1); + memcpy(n, f, sizeof(*f)); + n->namesize -= 8; + 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); } - n = xcalloc(sizeof(*n), 1); - memcpy(n, f, sizeof(*f)); - n->namesize -= 8; - n->filename = strdup(f->filename + 8); - n->data = f->data; - f->data = NULL; - n->remove = 0; - fprintf(stderr, "Restoring [%s] -> [%s]\n", f->filename, n->filename); - cpio_vec_insert(v, n); } } // Some known stuff we can remove @@ -406,6 +416,8 @@ static void cpio_stocksha1(struct vector *v) { return; } } + } else if (strcmp(f->filename, ".backup/.sha1") == 0) { + printf("%s\n", f->data); } } } @@ -443,7 +455,7 @@ int cpio_commands(const char *command, int argc, char *argv[]) { cmd = RESTORE; } else if (strcmp(command, "stocksha1") == 0) { cmd = STOCKSHA1; - } else if (argc == 1 && strcmp(command, "backup") == 0) { + } else if (argc >= 1 && strcmp(command, "backup") == 0) { cmd = BACKUP; } else if (argc > 0 && strcmp(command, "rm") == 0) { cmd = RM; @@ -479,7 +491,7 @@ int cpio_commands(const char *command, int argc, char *argv[]) { cpio_stocksha1(&v); return 0; case BACKUP: - cpio_backup(argv[0], &v); + cpio_backup(argv[0], argc > 1 ? argv[1] : NULL, &v); case RM: cpio_rm(recursive, argv[0], &v); break; diff --git a/jni/magiskboot/magiskboot.h b/jni/magiskboot/magiskboot.h index f13409850..c34aedd6f 100644 --- a/jni/magiskboot/magiskboot.h +++ b/jni/magiskboot/magiskboot.h @@ -3,6 +3,7 @@ #include +#include "logging.h" #include "bootimg.h" #define KERNEL_FILE "kernel" @@ -12,9 +13,6 @@ #define DTB_FILE "dtb" #define NEW_BOOT "new-boot.img" -#define str(a) #a -#define xstr(a) str(a) - // Main entries void unpack(const char *image); void repack(const char* orig_image, const char* out_image); @@ -36,13 +34,10 @@ 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); // Utils -extern void mmap_ro(const char *filename, void **buf, size_t *size); -extern void mmap_rw(const char *filename, void **buf, size_t *size); extern void write_zero(int fd, size_t size); extern void mem_align(size_t *pos, size_t align); extern void file_align(int fd, size_t align, int out); extern int open_new(const char *filename); -extern void *patch_init_rc(char *data, uint32_t *size); extern int check_verity_pattern(const char *s); extern int check_encryption_pattern(const char *s); diff --git a/jni/magiskboot/main.c b/jni/magiskboot/main.c index 5e138f8d7..867a1b04f 100644 --- a/jni/magiskboot/main.c +++ b/jni/magiskboot/main.c @@ -5,6 +5,7 @@ #include #include "magiskboot.h" +#include "utils.h" #include "sha1.h" /******************** @@ -47,8 +48,9 @@ static void usage(char *arg0) { " Return value: 0/stock 1/Magisk 2/other (e.g. phh, SuperSU)\n" " -patch \n" " Patch cpio for Magisk. KEEP**** are true/false values\n" - " -backup \n" + " -backup [SHA1]\n" " Create ramdisk backups into from \n" + " SHA1 of stock boot image is optional\n" " -restore\n" " Restore ramdisk from ramdisk backup within \n" " -stocksha1\n" diff --git a/jni/magiskinit.c b/jni/magiskinit.c deleted file mode 100644 index 8187b2eb8..000000000 --- a/jni/magiskinit.c +++ /dev/null @@ -1,311 +0,0 @@ -/* magiskinit.c - Workaround for skip_initramfs devices - * - * This code has to be compiled statically to work properly. - * - * Magiskinit will mount sysfs, parse through uevent files to make the system block device, - * then it'll mount the system partition and clone rootfs except files under /system. - * Folders placed in "overlay" will then be overlayed to the root. - * Lastly, before giving control back to the real init, it'll patch the root files, - * extract (or compile if needed) sepolicy and patch it to load Magisk. - */ - - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include - -#include "utils.h" -#include "magiskpolicy.h" - -struct cmdline { - int skip_initramfs; - char slot[3]; -}; - -struct device { - dev_t major; - dev_t minor; - char devname[32]; - char partname[32]; - char path[64]; -}; - -extern policydb_t *policydb; - -extern void mmap_ro(const char *filename, void **buf, size_t *size); -extern void mmap_rw(const char *filename, void **buf, size_t *size); -extern void *patch_init_rc(char *data, uint32_t *size); - -static void parse_cmdline(struct cmdline *cmd) { - char *tok; - char buffer[4096]; - mkdir("/proc", 0555); - mount("proc", "/proc", "proc", 0, NULL); - int fd = open("/proc/cmdline", O_RDONLY | O_CLOEXEC); - ssize_t size = read(fd, buffer, sizeof(buffer)); - buffer[size] = '\0'; - close(fd); - umount("/proc"); - tok = strtok(buffer, " "); - cmd->skip_initramfs = 0; - cmd->slot[0] = '\0'; - while (tok != NULL) { - if (strncmp(tok, "androidboot.slot_suffix", 23) == 0) { - sscanf(tok, "androidboot.slot_suffix=%s", cmd->slot); - } else if (strcmp(tok, "skip_initramfs") == 0) { - cmd->skip_initramfs = 1; - } - tok = strtok(NULL, " "); - } -} - -static void parse_device(struct device *dev, char *uevent) { - char *tok; - tok = strtok(uevent, "\n"); - while (tok != NULL) { - if (strncmp(tok, "MAJOR", 5) == 0) { - sscanf(tok, "MAJOR=%ld", (long*) &dev->major); - } else if (strncmp(tok, "MINOR", 5) == 0) { - sscanf(tok, "MINOR=%ld", (long*) &dev->minor); - } else if (strncmp(tok, "DEVNAME", 7) == 0) { - sscanf(tok, "DEVNAME=%s", dev->devname); - } else if (strncmp(tok, "PARTNAME", 8) == 0) { - sscanf(tok, "PARTNAME=%s", dev->partname); - } - tok = strtok(NULL, "\n"); - } -} - -static int setup_block(struct device *dev, const char *partname) { - char buffer[1024], path[128]; - struct dirent *entry; - DIR *dir = opendir("/sys/dev/block"); - if (dir == NULL) - return 1; - int found = 0; - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - snprintf(path, sizeof(path), "/sys/dev/block/%s/uevent", entry->d_name); - int fd = open(path, O_RDONLY | O_CLOEXEC); - ssize_t size = read(fd, buffer, sizeof(buffer)); - buffer[size] = '\0'; - close(fd); - parse_device(dev, buffer); - if (strcmp(dev->partname, partname) == 0) { - snprintf(dev->path, sizeof(dev->path), "/dev/block/%s", dev->devname); - found = 1; - break; - } - } - closedir(dir); - - if (!found) - return 1; - - mkdir("/dev", 0755); - mkdir("/dev/block", 0755); - mknod(dev->path, S_IFBLK | 0600, makedev(dev->major, dev->minor)); - return 0; -} - -static void patch_ramdisk() { - void *addr; - size_t size; - mmap_rw("/init", &addr, &size); - for (int i = 0; i < size; ++i) { - if (memcmp(addr + i, "/system/etc/selinux/plat_sepolicy.cil", 37) == 0) { - memcpy(addr + i, "/system/etc/selinux/plat_sepolicy.xxx", 37); - break; - } - } - munmap(addr, size); - mmap_rw("/init.rc", &addr, &size); - uint32_t new_size = size; - void *init_rc = patch_init_rc(addr, &new_size); - munmap(addr, size); - int fd = open("/init.rc", O_WRONLY | O_TRUNC | O_CLOEXEC); - write(fd, init_rc, new_size); - close(fd); - free(init_rc); -} - -static int strend(const char *s1, const char *s2) { - int l1 = strlen(s1); - int l2 = strlen(s2); - return strcmp(s1 + l1 - l2, s2); -} - -static void patch_sepolicy() { - DIR *dir; - struct dirent *entry; - char *sepolicy = NULL, path[128]; - if (access("/system_root/sepolicy", R_OK) == 0) - sepolicy = "/system_root/sepolicy"; - if (sepolicy == NULL && access("/vendor/etc/selinux/precompiled_sepolicy", R_OK) == 0) { - void *sys_sha = NULL, *ven_sha = NULL; - size_t sys_size = 0, ven_size = 0; - if ((dir = opendir("/vendor/etc/selinux")) == NULL) - goto check_done; - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - if (strend(entry->d_name, ".sha256") == 0) { - snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name); - mmap_ro(path, &ven_sha, &ven_size); - break; - } - } - closedir(dir); - if ((dir = opendir("/system/etc/selinux")) == NULL) - goto check_done; - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - if (strend(entry->d_name, ".sha256") == 0) { - snprintf(path, sizeof(path), "/system/etc/selinux/%s", entry->d_name); - mmap_ro(path, &sys_sha, &sys_size); - break; - } - } - closedir(dir); - if (sys_size == ven_size && memcmp(sys_sha, ven_sha, sys_size) == 0) - sepolicy = "/vendor/etc/selinux/precompiled_sepolicy"; - munmap(sys_sha, sys_size); - munmap(ven_sha, ven_size); - } - -check_done: - - if (sepolicy) { - load_policydb(sepolicy); - } else { - // Compile cil - struct cil_db *db = NULL; - sepol_policydb_t *pdb = NULL; - void *addr; - size_t size; - - cil_db_init(&db); - cil_set_mls(db, 1); - cil_set_target_platform(db, SEPOL_TARGET_SELINUX); - cil_set_policy_version(db, POLICYDB_VERSION_XPERMS_IOCTL); - cil_set_attrs_expand_generated(db, 0); - - mmap_ro("/system/etc/selinux/plat_sepolicy.cil", &addr, &size); - cil_add_file(db, "/system/etc/selinux/plat_sepolicy.cil", addr, size); - munmap(addr, size); - - dir = opendir("/system/etc/selinux/mapping"); - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - if (strend(entry->d_name, ".cil") == 0) { - snprintf(path, sizeof(path), "/system/etc/selinux/mapping/%s", entry->d_name); - mmap_ro(path, &addr, &size); - cil_add_file(db, path, addr, size); - munmap(addr, size); - } - } - closedir(dir); - - dir = opendir("/vendor/etc/selinux"); - while ((entry = readdir(dir))) { - if (strcmp(entry->d_name, ".") == 0 || strcmp(entry->d_name, "..") == 0) - continue; - if (strend(entry->d_name, ".cil") == 0) { - snprintf(path, sizeof(path), "/vendor/etc/selinux/%s", entry->d_name); - mmap_ro(path, &addr, &size); - cil_add_file(db, path, addr, size); - munmap(addr, size); - } - } - closedir(dir); - - cil_compile(db); - cil_build_policydb(db, &pdb); - cil_db_destroy(&db); - - policydb = &pdb->p; - } - - // Magisk patches - sepol_min_rules(); - dump_policydb("/sepolicy"); - destroy_policydb(); -} - -int main(int argc, char *argv[]) { - umask(0); - - struct cmdline cmd; - parse_cmdline(&cmd); - - if (cmd.skip_initramfs) { - // Normal boot mode - // Clear rootfs - int root = open("/", O_RDONLY | O_CLOEXEC); - - // Exclude overlay folder - excl_list = (char *[]) { "overlay", NULL }; - frm_rf(root); - - mkdir("/sys", 0755); - mount("sysfs", "/sys", "sysfs", 0, NULL); - - char partname[32]; - snprintf(partname, sizeof(partname), "system%s", cmd.slot); - - struct device dev; - setup_block(&dev, partname); - - mkdir("/system_root", 0755); - mount(dev.path, "/system_root", "ext4", MS_RDONLY, NULL); - int system_root = open("/system_root", O_RDONLY | O_CLOEXEC); - - // Exclude system folder - excl_list = (char *[]) { "system", NULL }; - clone_dir(system_root, root); - mkdir("/system", 0755); - mount("/system_root/system", "/system", NULL, MS_BIND, NULL); - - int overlay = open("/overlay", O_RDONLY | O_CLOEXEC); - if (overlay > 0) - mv_dir(overlay, root); - - snprintf(partname, sizeof(partname), "vendor%s", cmd.slot); - - // We need to mount independent vendor partition - if (setup_block(&dev, partname) == 0) - mount(dev.path, "/vendor", "ext4", MS_RDONLY, NULL); - - patch_ramdisk(); - patch_sepolicy(); - - close(root); - close(system_root); - close(overlay); - rmdir("/overlay"); - umount("/vendor"); - } else { - // Recovery mode - // Revert original init binary - unlink("/init"); - rename("/.backup/init", "/init"); - } - - execv("/init", argv); - - return 0; -} diff --git a/jni/magiskpolicy b/jni/magiskpolicy index 3c6a17013..9e9682416 160000 --- a/jni/magiskpolicy +++ b/jni/magiskpolicy @@ -1 +1 @@ -Subproject commit 3c6a170138cacb1f817c65181bd6e3ef15cfca9e +Subproject commit 9e96824161ddf1d6af516f44cad4d0e904a7abed diff --git a/jni/utils/file.c b/jni/utils/file.c index 0ce2e881a..7dab09b7c 100644 --- a/jni/utils/file.c +++ b/jni/utils/file.c @@ -5,6 +5,7 @@ #include #include #include +#include #ifndef NO_SELINUX #include @@ -52,6 +53,8 @@ int mkdir_p(const char *pathname, mode_t mode) { void rm_rf(const char *path) { int fd = xopen(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return; frm_rf(fd); close(fd); rmdir(path); @@ -294,6 +297,22 @@ void fclone_attr(const int sourcefd, const int targetfd) { fsetattr(targetfd, &a); } +void mmap_ro(const char *filename, void **buf, size_t *size) { + int fd = xopen(filename, O_RDONLY); + *size = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + *buf = *size > 0 ? xmmap(NULL, *size, PROT_READ, MAP_SHARED, fd, 0) : NULL; + close(fd); +} + +void mmap_rw(const char *filename, void **buf, size_t *size) { + int fd = xopen(filename, O_RDWR); + *size = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + *buf = *size > 0 ? xmmap(NULL, *size, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0) : NULL; + close(fd); +} + #ifndef NO_SELINUX #define UNLABEL_CON "u:object_r:unlabeled:s0" diff --git a/scripts/boot_patch.sh b/scripts/boot_patch.sh index da6d81c32..52ba16619 100644 --- a/scripts/boot_patch.sh +++ b/scripts/boot_patch.sh @@ -11,18 +11,15 @@ # boot_patch.sh script A script to patch boot. Expect path to boot image as parameter. # (this file) The script will use binaries and files in its same directory # to complete the patching process -# magisk binary The main binary for all Magisk operations. -# It is also used to patch the sepolicy in the ramdisk. +# monogisk binary The monolithic binary to replace /init # magiskboot binary A tool to unpack boot image, decompress ramdisk, extract ramdisk # , and patch the ramdisk for Magisk support -# init.magisk.rc script A new line will be added to init.rc to import this script. -# All magisk entrypoints are defined here # chromeos folder This folder should store all the utilities and keys to sign # (optional) a chromeos device, used in the tablet Pixel C # # If the script is not running as root, then the input boot image should be a stock image # or have a backup included in ramdisk internally, since we cannot access the stock boot -# image placed under /data we've created when previously installing +# image placed under /data we've created when previously installed # ########################################################################################## ########################################################################################## @@ -47,21 +44,6 @@ basename_wrap() { echo ${1##*/} } -# --cpio-add -cpio_add() { - ./magiskboot --cpio-add ramdisk.cpio $1 $2 $3 -} - -# --cpio-extract -cpio_extract() { - ./magiskboot --cpio-extract ramdisk.cpio $1 $2 -} - -# --cpio-mkdir -cpio_mkdir() { - ./magiskboot --cpio-mkdir ramdisk.cpio $1 $2 -} - ########################################################################################## # Initialization ########################################################################################## @@ -85,6 +67,9 @@ BOOTIMAGE="$1" chmod -R 755 . +# Extract magisk if doesn't exist +[ -e magisk ] || ./monogisk -x magisk magisk + ########################################################################################## # Unpack ########################################################################################## @@ -172,33 +157,11 @@ esac ui_print "- Patching ramdisk" -if [ ! -z $SHA1 ]; then - cp init.magisk.rc init.magisk.rc.bak - echo "# STOCKSHA1=$SHA1" >> init.magisk.rc -fi - -if $SKIP_INITRAMFS; then - cpio_add 750 init magiskinit - cpio_mkdir 000 overlay - cpio_add 750 overlay/init.magisk.rc init.magisk.rc - cpio_mkdir 750 overlay/sbin - cpio_add 755 overlay/sbin/magisk magisk -else - ./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT - - cpio_extract sepolicy sepolicy - ./magisk magiskpolicy --load sepolicy --save sepolicy --minimal - cpio_add 644 sepolicy sepolicy - rm -f sepolicy - - cpio_add 750 init.magisk.rc init.magisk.rc - cpio_add 755 sbin/magisk magisk -fi - -mv init.magisk.rc.bak init.magisk.rc 2>/dev/null +./magiskboot --cpio-add ramdisk.cpio 750 init monogisk +./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT # Create ramdisk backups -./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig +./magiskboot --cpio-backup ramdisk.cpio ramdisk.cpio.orig $SHA1 if ! $KEEPVERITY && [ -f dtb ]; then ./magiskboot --dtb-patch dtb && ui_print "- Patching fstab in dtb to remove dm-verity" @@ -218,7 +181,7 @@ rm -f ramdisk.cpio.orig A1020054011440B93FA00F7140020054010840B93FA00F71E0010054001840B91FA00F7181010054 # skip_initramfs -> want_initramfs -$SKIP_INITRAMFS && ./magiskboot --hexpatch kernel \ +./magiskboot --hexpatch kernel \ 736B69705F696E697472616D6673 \ 77616E745F696E697472616D6673 diff --git a/scripts/flash_script.sh b/scripts/flash_script.sh index 0bd52fbbc..d01aa9184 100644 --- a/scripts/flash_script.sh +++ b/scripts/flash_script.sh @@ -79,18 +79,12 @@ ui_print "- Constructing environment" is_mounted /data && MAGISKBIN=/data/magisk || MAGISKBIN=/cache/data_bin -if $BOOTMODE; then - # Cleanup binary mirrors - umount -l /dev/magisk/mirror/bin 2>/dev/null - rm -rf /dev/magisk/mirror/bin 2>/dev/null -fi - # Save our stock boot image dump before removing it mv /data/magisk/stock_boot* /data 2>/dev/null # Copy required files -rm -rf $MAGISKBIN 2>/dev/null -mkdir -p $MAGISKBIN +rm -rf $MAGISKBIN/* 2>/dev/null +mkdir -p $MAGISKBIN 2>/dev/null cp -af $BINDIR/. $COMMONDIR/. $CHROMEDIR $TMPDIR/bin/busybox $MAGISKBIN chmod -R 755 $MAGISKBIN diff --git a/scripts/init.magisk.rc b/scripts/init.magisk.rc deleted file mode 100644 index a588b0e54..000000000 --- a/scripts/init.magisk.rc +++ /dev/null @@ -1,41 +0,0 @@ -# Triggers - -on post-fs - start logd - start magisk_daemon - wait /dev/.magisk.unblock 5 - rm /dev/.magisk.unblock - start magisk_pfs - wait /dev/.magisk.unblock 10 - -on post-fs-data - load_persist_props - rm /dev/.magisk.unblock - start magisk_pfsd - wait /dev/.magisk.unblock 10 - -# Services - -# Self recoverable service -service magisk_daemon /sbin/magisk --daemon - user root - seclabel u:r:su:s0 - -# launch post-fs script -service magisk_pfs /sbin/magisk --post-fs - user root - seclabel u:r:su:s0 - oneshot - -# launch post-fs-data script -service magisk_pfsd /sbin/magisk --post-fs-data - user root - seclabel u:r:su:s0 - oneshot - -# launch late_start script -service magisk_service /sbin/magisk --service - class late_start - user root - seclabel u:r:su:s0 - oneshot