From 5a71998b4e8814dd168a6fef163bc780d403cb7d Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Mon, 18 Jan 2021 04:25:26 -0800 Subject: [PATCH] Stop embedding magisk in magiskinit --- .../magisk/core/tasks/MagiskInstaller.kt | 77 ++++++++++++------- app/src/main/res/raw/manager.sh | 2 +- build.py | 62 ++++++++------- native/jni/Android.mk | 15 +--- native/jni/init/init.cpp | 43 +++-------- native/jni/init/init.hpp | 2 +- native/jni/init/mount.cpp | 11 +-- native/jni/init/rootdir.cpp | 27 ++++++- scripts/boot_patch.sh | 17 +++- scripts/emulator.sh | 14 +--- scripts/util_functions.sh | 6 -- 11 files changed, 140 insertions(+), 136 deletions(-) diff --git a/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt b/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt index 23af5e392..e3a31a4bc 100644 --- a/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt +++ b/app/src/main/java/com/topjohnwu/magisk/core/tasks/MagiskInstaller.kt @@ -65,6 +65,16 @@ abstract class MagiskInstallImpl : KoinComponent { logs = NOPList.getInstance() } + companion object { + private val ABI_MAP = TreeMap() + init { + ABI_MAP["armeabi-v7a"] = "arm" + ABI_MAP["arm64-v8a"] = "arm64" + ABI_MAP["x86"] = "x86" + ABI_MAP["x86_64"] = "x64" + } + } + protected constructor(zip: Uri, out: MutableList, err: MutableList) { console = out logs = err @@ -103,44 +113,52 @@ abstract class MagiskInstallImpl : KoinComponent { @Suppress("DEPRECATION") private fun extractZip(): Boolean { - val arch = if (Build.VERSION.SDK_INT >= 21) { - val abis = listOf(*Build.SUPPORTED_ABIS) - if (abis.contains("x86")) "x86" else "arm" + val arch: String + val arch32: String + if (Build.VERSION.SDK_INT >= 21) { + arch = ABI_MAP[Build.SUPPORTED_ABIS[0]]!! + arch32 = ABI_MAP[Build.SUPPORTED_32_BIT_ABIS[0]]!! } else { - if (Build.CPU_ABI == "x86") "x86" else "arm" + arch = ABI_MAP[Build.CPU_ABI]!! + arch32 = arch } - console.add("- Device platform: " + Build.CPU_ABI) + console.add("- Device platform: $arch") console.add("- Magisk Manager: ${BuildConfig.VERSION_NAME} (${BuildConfig.VERSION_CODE})") console.add("- Install target: ${Info.remote.magisk.version} (${Info.remote.magisk.versionCode})") + fun newFile(name: String): File { + return if (installDir is SuFile) + SuFile(installDir, name) + else + File(installDir, name) + } + try { ZipInputStream(zipUri.inputStream().buffered()).use { zi -> lateinit var ze: ZipEntry while (zi.nextEntry?.let { ze = it } != null) { if (ze.isDirectory) continue + var name: String? = null - val names = arrayOf("$arch/", "common/", "META-INF/com/google/android/update-binary") - for (n in names) { - ze.name.run { - if (startsWith(n)) { - name = substring(lastIndexOf('/') + 1) + + if (ze.name.startsWith("chromeos/")) { + name = ze.name + } else { + for (n in listOf("$arch32/", "common/", "META-INF/com/google/android/update-binary")) { + if (ze.name.startsWith(n)) { + name = ze.name.substring(ze.name.lastIndexOf('/') + 1) + break } } - name ?: continue - break } - if (name == null && ze.name.startsWith("chromeos/")) - name = ze.name - name?.also { - val dest = if (installDir is SuFile) - SuFile(installDir, it) - else - File(installDir, it) - dest.parentFile!!.mkdirs() - SuFileOutputStream(dest).use { s -> zi.copyTo(s) } - } ?: continue + + name ?: continue + + val dest = newFile(name) + dest.parentFile!!.mkdirs() + SuFileOutputStream(dest).use { s -> zi.copyTo(s) } } } } catch (e: IOException) { @@ -149,9 +167,9 @@ abstract class MagiskInstallImpl : KoinComponent { return false } - val init64 = SuFile.open(installDir, "magiskinit64") - if (Build.VERSION.SDK_INT >= 21 && Build.SUPPORTED_64_BIT_ABIS.isNotEmpty()) { - init64.renameTo(SuFile.open(installDir, "magiskinit")) + val init64 = newFile("magiskinit64") + if (init64.exists() && arch != arch32) { + init64.renameTo(newFile("magiskinit")) } else { init64.delete() } @@ -324,9 +342,12 @@ abstract class MagiskInstallImpl : KoinComponent { return false } - if (!("KEEPFORCEENCRYPT=${Config.keepEnc} KEEPVERITY=${Config.keepVerity} " + - "RECOVERYMODE=${Config.recovery} sh update-binary " + - "sh boot_patch.sh $srcBoot").sh().isSuccess) { + val FLAGS = + "KEEPFORCEENCRYPT=${Config.keepEnc} " + + "KEEPVERITY=${Config.keepVerity} " + + "RECOVERYMODE=${Config.recovery}" + + if (!("$FLAGS sh update-binary sh boot_patch.sh $srcBoot").sh().isSuccess) { return false } diff --git a/app/src/main/res/raw/manager.sh b/app/src/main/res/raw/manager.sh index aa160d58c..8c7c1927a 100644 --- a/app/src/main/res/raw/manager.sh +++ b/app/src/main/res/raw/manager.sh @@ -7,7 +7,7 @@ run_delay() { } env_check() { - for file in busybox magisk magiskboot magiskinit util_functions.sh boot_patch.sh; do + for file in busybox magiskboot magiskinit util_functions.sh boot_patch.sh; do [ -f $MAGISKBIN/$file ] || return 1 done return 0 diff --git a/build.py b/build.py index 1edd70568..9b1f5233d 100755 --- a/build.py +++ b/build.py @@ -287,18 +287,6 @@ def run_ndk_build(flags): def dump_bin_headers(): - for arch in archs: - bin_file = op.join('native', 'out', arch, 'magisk') - if not op.exists(bin_file): - error('Build "magisk" before building "magiskinit"') - with open(op.join('native', 'out', arch, 'binaries_arch.h'), 'w') as out: - with open(bin_file, 'rb') as src: - binary_dump(src, out, 'magisk_xz') - for arch, arch32 in list(zip(arch64, archs)): - bin_file = op.join('native', 'out', arch, 'magisk') - with open(op.join('native', 'out', arch32, 'binaries_arch64.h'), 'w') as out: - with open(bin_file, 'rb') as src: - binary_dump(src, out, 'magisk_xz') stub = op.join(config['outdir'], 'stub-release.apk') if not op.exists(stub): error('Build stub APK before building "magiskinit"') @@ -347,26 +335,31 @@ def build_binary(args): run_ndk_build('B_MAGISK=1 B_64BIT=1') clean_elf() - if 'magiskinit' in args.target: - dump_bin_headers() - run_ndk_build('B_INIT=1') - run_ndk_build('B_INIT64=1') - - if 'magiskpolicy' in args.target: - run_ndk_build('B_POLICY=1') - - if 'resetprop' in args.target: - run_ndk_build('B_PROP=1') - - if 'magiskboot' in args.target: - run_ndk_build('B_BOOT=1') - - if 'busybox' in args.target: - run_ndk_build('B_BB=1') - if 'test' in args.target: run_ndk_build('B_TEST=1 B_64BIT=1') + # 32-bit only targets can be built in one command + flag = '' + + if 'magiskinit' in args.target: + dump_bin_headers() + flag += ' B_INIT=1' + + if 'magiskpolicy' in args.target: + flag += ' B_POLICY=1' + + if 'resetprop' in args.target: + flag += ' B_PROP=1' + + if 'magiskboot' in args.target: + flag += ' B_BOOT=1' + + if 'busybox' in args.target: + flag += ' B_BB=1' + + if flag: + run_ndk_build(flag) + def build_apk(args, module): build_type = 'Release' if args.release or module == 'stub' else 'Debug' @@ -440,12 +433,17 @@ def zip_main(args): zip_with_msg(zipf, source, target) # Binaries - for lib_dir, zip_dir in [('armeabi-v7a', 'arm'), ('x86', 'x86')]: - for binary in ['magiskinit', 'magiskinit64', 'magiskboot']: + for lib_dir, zip_dir in zip(archs, ('arm', 'x86')): + for binary in ['magiskinit', 'magiskboot', 'magisk']: source = op.join('native', 'out', lib_dir, binary) - target = op.join(zip_dir, binary) + target = op.join(zip_dir, 'magisk32' if binary == 'magisk' else binary) zip_with_msg(zipf, source, target) + for lib_dir, zip_dir in zip(arch64, ('arm', 'x86')): + source = op.join('native', 'out', lib_dir, 'magisk') + target = op.join(zip_dir, 'magisk64') + zip_with_msg(zipf, source, target) + # APK source = op.join( config['outdir'], 'app-release.apk' if args.release else 'app-debug.apk') diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 1caa32d1b..613fea98d 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -54,21 +54,10 @@ endif include $(CLEAR_VARS) ifdef B_INIT + LOCAL_MODULE := magiskinit -BB_INIT := 1 -else ifdef B_INIT64 -LOCAL_MODULE := magiskinit64 -LOCAL_CPPFLAGS += -DUSE_64BIT -BB_INIT := 1 -endif - -ifdef BB_INIT - LOCAL_STATIC_LIBRARIES := libsepol libxz libutils -LOCAL_C_INCLUDES := \ - jni/include \ - out \ - out/$(TARGET_ARCH_ABI) +LOCAL_C_INCLUDES := jni/include out LOCAL_SRC_FILES := \ init/init.cpp \ diff --git a/native/jni/init/init.cpp b/native/jni/init/init.cpp index 33e2283a9..940242d8e 100644 --- a/native/jni/init/init.cpp +++ b/native/jni/init/init.cpp @@ -10,12 +10,6 @@ #include #include "binaries.h" -#ifdef USE_64BIT -#include "binaries_arch64.h" -#else -#include "binaries_arch.h" -#endif - #include "init.hpp" using namespace std; @@ -26,7 +20,7 @@ using namespace std; constexpr int (*init_applet_main[])(int, char *[]) = { magiskpolicy_main, magiskpolicy_main, nullptr }; -static bool unxz(int fd, const uint8_t *buf, size_t size) { +bool unxz(int fd, const uint8_t *buf, size_t size) { uint8_t out[8192]; xz_crc32_init(); struct xz_dec *dec = xz_dec_init(XZ_DYNALLOC, 1 << 26); @@ -49,16 +43,6 @@ static bool unxz(int fd, const uint8_t *buf, size_t size) { return true; } -int dump_magisk(const char *path, mode_t mode) { - int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); - if (fd < 0) - return 1; - if (!unxz(fd, magisk_xz, sizeof(magisk_xz))) - return 1; - close(fd); - return 0; -} - static int dump_manager(const char *path, mode_t mode) { int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); if (fd < 0) @@ -147,10 +131,9 @@ int main(int argc, char *argv[]) { #endif if (argc > 1 && argv[1] == "-x"sv) { - if (argv[2] == "magisk"sv) - return dump_magisk(argv[3], 0755); - else if (argv[2] == "manager"sv) + if (argc > 2 && argv[2] == "manager"sv) return dump_manager(argv[3], 0644); + return 1; } if (getpid() != 1) @@ -166,18 +149,16 @@ int main(int argc, char *argv[]) { // This will also mount /sys and /proc load_kernel_info(&cmd); - if (cmd.skip_initramfs) { + if (cmd.skip_initramfs) init = new SARInit(argv, &cmd); - } else { - if (cmd.force_normal_boot) - init = new FirstStageInit(argv, &cmd); - else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0) - init = new RecoveryInit(argv, &cmd); - else if (check_two_stage()) - init = new FirstStageInit(argv, &cmd); - else - init = new RootFSInit(argv, &cmd); - } + else if (cmd.force_normal_boot) + init = new FirstStageInit(argv, &cmd); + else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0) + init = new RecoveryInit(argv, &cmd); + else if (check_two_stage()) + init = new FirstStageInit(argv, &cmd); + else + init = new RootFSInit(argv, &cmd); } // Run the main routine diff --git a/native/jni/init/init.hpp b/native/jni/init/init.hpp index 3acf1ad55..17c30f684 100644 --- a/native/jni/init/init.hpp +++ b/native/jni/init/init.hpp @@ -31,9 +31,9 @@ struct fstab_entry { extern std::vector mount_list; +bool unxz(int fd, const uint8_t *buf, size_t size); void load_kernel_info(cmdline *cmd); bool check_two_stage(); -int dump_magisk(const char *path, mode_t mode); void setup_klog(); /*************** diff --git a/native/jni/init/mount.cpp b/native/jni/init/mount.cpp index 6d5fc4c95..6303b4f18 100644 --- a/native/jni/init/mount.cpp +++ b/native/jni/init/mount.cpp @@ -378,13 +378,6 @@ void BaseInit::exec_init() { exit(1); } -static void patch_socket_name(const char *path) { - char rstr[16]; - gen_rand_str(rstr, sizeof(rstr)); - auto bin = mmap_data::rw(path); - bin.patch({ make_pair(MAIN_SOCKET, rstr) }); -} - void MagiskInit::setup_tmp(const char *path) { LOGD("Setup Magisk tmp at %s\n", path); xmount("tmpfs", path, "tmpfs", 0, "mode=755"); @@ -401,8 +394,8 @@ void MagiskInit::setup_tmp(const char *path) { fd = xopen("magiskinit", O_WRONLY | O_CREAT, 0755); xwrite(fd, self.buf, self.sz); close(fd); - dump_magisk("magisk", 0755); - patch_socket_name("magisk"); + + // The magisk binary will be handled later // Create applet symlinks for (int i = 0; applet_names[i]; ++i) diff --git a/native/jni/init/rootdir.cpp b/native/jni/init/rootdir.cpp index 87c0a4ced..5078795c9 100644 --- a/native/jni/init/rootdir.cpp +++ b/native/jni/init/rootdir.cpp @@ -174,6 +174,13 @@ static void magic_mount(const string &sdir, const string &ddir = "") { } } +static void patch_socket_name(const char *path) { + char rstr[16]; + gen_rand_str(rstr, sizeof(rstr)); + auto bin = mmap_data::rw(path); + bin.patch({ make_pair(MAIN_SOCKET, rstr) }); +} + #define ROOTMIR MIRRDIR "/system_root" #define MONOPOLICY "/sepolicy" #define NEW_INITRC "/system/etc/init/hw/init.rc" @@ -280,9 +287,19 @@ void SARBase::patch_rootdir() { patch_init_rc(NEW_INITRC, ROOTOVL NEW_INITRC, tmp_dir.data()); } + // Extract magisk + { + auto magisk = mmap_data::ro("magisk.xz"); + unlink("magisk.xz"); + int fd = xopen("magisk", O_WRONLY | O_CREAT, 0755); + unxz(fd, magisk.buf, magisk.sz); + close(fd); + patch_socket_name("magisk"); + } + // Mount rootdir magic_mount(ROOTOVL); - int dest = xopen(ROOTMNT, O_WRONLY | O_CREAT | O_CLOEXEC, 0); + int dest = xopen(ROOTMNT, O_WRONLY | O_CREAT, 0); write(dest, magic_mount_list.data(), magic_mount_list.length()); close(dest); @@ -335,15 +352,23 @@ void MagiskProxy::start() { // Backup stuffs before removing them self = mmap_data::ro("/sbin/magisk"); config = mmap_data::ro("/.backup/.magisk"); + auto magisk = mmap_data::ro("/sbin/magisk.xz"); char custom_rules_dir[64]; custom_rules_dir[0] = '\0'; xreadlink(TMP_RULESDIR, custom_rules_dir, sizeof(custom_rules_dir)); unlink("/sbin/magisk"); + unlink("/sbin/magisk.xz"); rm_rf("/.backup"); setup_tmp("/sbin"); + // Extract magisk + int fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755); + unxz(fd, magisk.buf, magisk.sz); + close(fd); + patch_socket_name("/sbin/magisk"); + // Create symlinks pointing back to /root recreate_sbin("/root", false); diff --git a/scripts/boot_patch.sh b/scripts/boot_patch.sh index 3d1841d7a..4a4f7af0f 100644 --- a/scripts/boot_patch.sh +++ b/scripts/boot_patch.sh @@ -53,6 +53,8 @@ if [ -z $SOURCEDMODE ]; then cd "`getdir "${BASH_SOURCE:-$0}"`" # Load utility functions . ./util_functions.sh + # Detect version and architecture + api_level_arch_detect fi BOOTIMAGE="$1" @@ -67,9 +69,6 @@ export KEEPFORCEENCRYPT chmod -R 755 . -# Extract magisk if doesn't exist -[ -e magisk ] || ./magiskinit -x magisk magisk - ######### # Unpack ######### @@ -135,14 +134,24 @@ echo "KEEPFORCEENCRYPT=$KEEPFORCEENCRYPT" >> config echo "RECOVERYMODE=$RECOVERYMODE" >> config [ ! -z $SHA1 ] && echo "SHA1=$SHA1" >> config +# Compress to save precious ramdisk space +if $IS64BIT; then + ./magiskboot compress=xz magisk64 magisk.xz +else + ./magiskboot compress=xz magisk32 magisk.xz +fi + ./magiskboot cpio ramdisk.cpio \ "add 750 init magiskinit" \ +"mkdir 0750 overlay.d" \ +"mkdir 0750 overlay.d/sbin" \ +"add 750 overlay.d/sbin/magisk.xz magisk.xz" \ "patch" \ "backup ramdisk.cpio.orig" \ "mkdir 000 .backup" \ "add 000 .backup/.magisk config" -rm -f ramdisk.cpio.orig config +rm -f ramdisk.cpio.orig config magisk.xz ################# # Binary Patches diff --git a/scripts/emulator.sh b/scripts/emulator.sh index 80968ccbd..8acece95e 100755 --- a/scripts/emulator.sh +++ b/scripts/emulator.sh @@ -28,14 +28,8 @@ mount_sbin() { if [ ! -f /system/build.prop ]; then # Running on PC - cd "`dirname "$0"`/.." - adb push native/out/x86/busybox scripts/emulator.sh /data/local/tmp - emu_arch=`adb shell uname -m` - if [ "$emu_arch" = "x86_64" ]; then - adb push native/out/x86/magiskinit64 /data/local/tmp/magiskinit - else - adb push native/out/x86/magiskinit /data/local/tmp - fi + cd "$(dirname "$0")/.." + adb push native/out/x86/busybox scripts/emulator.sh native/out/x86/magiskinit native/out/x86_64/magisk /data/local/tmp adb shell sh /data/local/tmp/emulator.sh exit 0 fi @@ -43,7 +37,7 @@ fi cd /data/local/tmp chmod 777 busybox chmod 777 magiskinit -./magiskinit -x magisk magisk +chmod 777 magisk if [ -z "$FIRST_STAGE" ]; then export FIRST_STAGE=1 @@ -113,7 +107,7 @@ else fi # Magisk stuffs -./magiskinit -x magisk $BINDIR/magisk +cp -af ./magisk $BINDIR/magisk chmod 755 $BINDIR/magisk ln -s ./magisk $BINDIR/su ln -s ./magisk $BINDIR/resetprop diff --git a/scripts/util_functions.sh b/scripts/util_functions.sh index f26631639..3866cc2e3 100644 --- a/scripts/util_functions.sh +++ b/scripts/util_functions.sh @@ -445,12 +445,6 @@ install_magisk() { $BOOTSIGNED && ui_print "- Boot image is signed with AVB 1.0" fi - if $IS64BIT; then - mv -f magiskinit64 magiskinit 2>/dev/null - else - rm -f magiskinit64 - fi - # Source the boot patcher SOURCEDMODE=true . ./boot_patch.sh "$BOOTIMAGE"