diff --git a/build.py b/build.py index abffb0e67..a3ee324e8 100755 --- a/build.py +++ b/build.py @@ -94,12 +94,12 @@ def build_binary(args): 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') + mv(os.path.join('libs', arch, 'magisk'), os.path.join('out', arch, 'magisk')) + with open(os.path.join('out', arch, 'magisk'), 'rb') as bin: + dump.write('const uint8_t magisk_dump[] = "') + 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) @@ -108,7 +108,7 @@ def build_binary(args): print('') for arch in ['arm64-v8a', 'armeabi-v7a', 'x86', 'x86_64']: - for binary in ['monogisk', 'magiskboot', 'b64xz', 'busybox']: + for binary in ['magiskinit', 'magiskboot', 'b64xz', 'busybox']: try: mv(os.path.join('libs', arch, binary), os.path.join('out', arch, binary)) except: @@ -243,7 +243,7 @@ def zip_main(args): # Binaries for lib_dir, zip_dir in [('arm64-v8a', 'arm64'), ('armeabi-v7a', 'arm'), ('x86', 'x86'), ('x86_64', 'x64')]: - for binary in ['monogisk', 'magiskboot']: + for binary in ['magiskinit', 'magiskboot']: source = os.path.join('out', lib_dir, binary) target = os.path.join(zip_dir, binary) zip_with_msg(zipf, source, target) diff --git a/jni/Android.mk b/jni/Android.mk index da30626bf..9de421dce 100644 --- a/jni/Android.mk +++ b/jni/Android.mk @@ -27,11 +27,11 @@ LOCAL_C_INCLUDES := \ $(LIBSELINUX) LOCAL_SRC_FILES := \ - daemon/magisk.c \ - daemon/daemon.c \ - daemon/socket_trans.c \ - daemon/log_monitor.c \ - daemon/bootstages.c \ + core/magisk.c \ + core/daemon.c \ + core/socket_trans.c \ + core/log_monitor.c \ + core/bootstages.c \ utils/misc.c \ utils/vector.c \ utils/xwrap.c \ @@ -55,13 +55,21 @@ LOCAL_CPPFLAGS := -std=c++11 LOCAL_LDLIBS := -llog include $(BUILD_EXECUTABLE) +# precompile +else + # magiskinit include $(CLEAR_VARS) LOCAL_MODULE := magiskinit -LOCAL_STATIC_LIBRARIES := libsepol -LOCAL_C_INCLUDES := jni/include $(LIBSEPOL) +LOCAL_STATIC_LIBRARIES := libsepol liblzma +LOCAL_C_INCLUDES := \ + jni/include \ + out/$(TARGET_ARCH_ABI) \ + $(LIBSEPOL) \ + $(LIBLZMA) + LOCAL_SRC_FILES := \ - init/magiskinit.c \ + core/magiskinit.c \ utils/vector.c \ utils/file.c \ utils/xwrap.c \ @@ -74,18 +82,6 @@ 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 diff --git a/jni/daemon/bootstages.c b/jni/core/bootstages.c similarity index 100% rename from jni/daemon/bootstages.c rename to jni/core/bootstages.c diff --git a/jni/daemon/daemon.c b/jni/core/daemon.c similarity index 100% rename from jni/daemon/daemon.c rename to jni/core/daemon.c diff --git a/jni/daemon/log_monitor.c b/jni/core/log_monitor.c similarity index 100% rename from jni/daemon/log_monitor.c rename to jni/core/log_monitor.c diff --git a/jni/daemon/magisk.c b/jni/core/magisk.c similarity index 100% rename from jni/daemon/magisk.c rename to jni/core/magisk.c diff --git a/jni/init/magiskinit.c b/jni/core/magiskinit.c similarity index 80% rename from jni/init/magiskinit.c rename to jni/core/magiskinit.c index a119c3c41..35df650b6 100644 --- a/jni/init/magiskinit.c +++ b/jni/core/magiskinit.c @@ -2,14 +2,20 @@ * * 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. + * To unify Magisk support for both legacy "normal" devices and new skip_initramfs devices, + * magisk binary compilation is split into two parts - first part only compiles "magisk". + * The python build script will load the magisk main binary and compress with lzma2, dumping + * the results into "dump.h". The "magisk" binary is embedded into this binary, and will + * get extracted to the overlay folder along with init.magisk.rc. + * + * This tool does all pre-init operations to setup a Magisk environment, which pathces rootfs + * on the fly, providing fundamental support such as init, init.rc, and sepolicy patching. + * + * Magiskinit is also responsible for constructing 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 /. + * rootfs files from system. + * * 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) */ @@ -29,11 +35,14 @@ #include #include +#include #include #include "magisk.h" #include "utils.h" #include "magiskpolicy.h" +#include "magiskrc.h" +#include "dump.h" // #define VLOG(fmt, ...) printf(fmt, __VA_ARGS__) /* Enable to debug */ #define VLOG(fmt, ...) @@ -290,6 +299,46 @@ static void patch_sepolicy() { dump_policydb("/sepolicy"); } +#define BUFSIZE (1 << 20) + +static int unxz(const void *buf, size_t size, int fd) { + lzma_stream strm = LZMA_STREAM_INIT; + if (lzma_auto_decoder(&strm, UINT64_MAX, 0) != LZMA_OK) + return 1; + lzma_ret ret = 0; + void *out = malloc(BUFSIZE); + strm.next_in = buf; + strm.avail_in = size; + do { + strm.next_out = out; + strm.avail_out = BUFSIZE; + ret = lzma_code(&strm, LZMA_RUN); + write(fd, out, BUFSIZE - strm.avail_out); + } while (strm.avail_out == 0 && ret == LZMA_OK); + + free(out); + lzma_end(&strm); + + if (ret != LZMA_OK && ret != LZMA_STREAM_END) + return 1; + return 0; +} + +static int dump_magisk(const char *path, mode_t mode) { + unlink(path); + int fd = creat(path, mode); + int ret = unxz(magisk_dump, sizeof(magisk_dump), fd); + close(fd); + return ret; +} + +static int dump_magiskrc(const char *path, mode_t mode) { + int fd = creat(path, mode); + write(fd, magiskrc, sizeof(magiskrc)); + close(fd); + return 0; +} + int main(int argc, char *argv[]) { if (strcmp(basename(argv[0]), "magiskpolicy") == 0 || strcmp(basename(argv[0]), "supolicy") == 0) return magiskpolicy_main(argc, argv); @@ -298,6 +347,23 @@ int main(int argc, char *argv[]) { umask(0); + if (argc > 1) { + if (strcmp(argv[2], "magisk") == 0) + return dump_magisk(argv[3], 0755); + else if (strcmp(argv[2], "magiskrc") == 0) + return dump_magiskrc(argv[3], 0755); + } + + // Extract and link files + mkdir("/overlay", 0000); + 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/magiskinit"); + symlink("/root/magiskinit", "/overlay/root/magiskpolicy"); + symlink("/root/magiskinit", "/overlay/root/supolicy"); + struct cmdline cmd; parse_cmdline(&cmd); diff --git a/jni/daemon/socket_trans.c b/jni/core/socket_trans.c similarity index 100% rename from jni/daemon/socket_trans.c rename to jni/core/socket_trans.c diff --git a/jni/init/monogisk.c b/jni/init/monogisk.c deleted file mode 100644 index 1d587e136..000000000 --- a/jni/init/monogisk.c +++ /dev/null @@ -1,121 +0,0 @@ -/* 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/scripts/boot_patch.sh b/scripts/boot_patch.sh index 52ba16619..9e6d1a971 100644 --- a/scripts/boot_patch.sh +++ b/scripts/boot_patch.sh @@ -68,7 +68,7 @@ BOOTIMAGE="$1" chmod -R 755 . # Extract magisk if doesn't exist -[ -e magisk ] || ./monogisk -x magisk magisk +[ -e magisk ] || ./magiskinit -x magisk magisk ########################################################################################## # Unpack @@ -157,7 +157,7 @@ esac ui_print "- Patching ramdisk" -./magiskboot --cpio-add ramdisk.cpio 750 init monogisk +./magiskboot --cpio-add ramdisk.cpio 750 init magiskinit ./magiskboot --cpio-patch ramdisk.cpio $KEEPVERITY $KEEPFORCEENCRYPT # Create ramdisk backups