From dfb1a294ab55374b80bb6f14c2422850610c986d Mon Sep 17 00:00:00 2001 From: nkk71 Date: Fri, 18 Aug 2017 16:34:55 +0300 Subject: [PATCH 01/65] Add 'System Partition Mode' (hybrid) ROMs * Magisk loop mounts the /system by parsing /proc/mounts to get the partition information: https://goo.gl/9PBEHo In MultiROM this has two problems: (1) the /system partition is a bind mount and therefore would fail the mount command and (2) the partition that is listed in /proc/mounts would be the real block device which is just the userdata partition (/dev/block/mmcblk0pNN). * To workaround this we create an img file (for system only) and use loop mount instead of bind mount. * During boot the the fake system img will get loop mounted to /multirom/dev/system which will properly show up in /proc/mounts and being a loop mount will properly work with mount(). * Note: In order to avoid more interference with the existing loop devices, we now create our own loop devices at a higher range (MULTIROM_LOOP_NUM_START). * The accompanying change in MultiROM-TWRP is needed to be able to flash 'System Partition Mode' ROMs. --- lib/util.c | 60 +++++++++++++++++++++++++++++- lib/util.h | 1 + multirom.c | 107 +++++++++++++++++++++++++++++++++-------------------- multirom.h | 28 ++++++++------ 4 files changed, 142 insertions(+), 54 deletions(-) diff --git a/lib/util.c b/lib/util.c index db8312f1..141e8417 100644 --- a/lib/util.c +++ b/lib/util.c @@ -697,7 +697,7 @@ int create_loop_device(const char *dev_path, const char *img_path, int loop_num, return -1; } - INFO("create_loop_device: loop_num = %d", loop_num); + INFO("create_loop_device: loop_num = %d\n", loop_num); if(mknod(dev_path, S_IFBLK | loop_chmod, makedev(7, loop_num)) < 0) { @@ -761,7 +761,7 @@ int mount_image(const char *src, const char *dst, const char *fs, int flags, con if(loop_num == MAX_LOOP_NUM) { - ERROR("mount_image: failed to find suitable loop device number!"); + ERROR("mount_image: failed to find suitable loop device number!\n"); return -1; } @@ -776,6 +776,62 @@ int mount_image(const char *src, const char *dst, const char *fs, int flags, con return res; } +#define MULTIROM_LOOP_NUM_START 231 +#define MULTIROM_DEV_PATH "/multirom/dev" +int multirom_mount_image(const char *src, const char *dst, const char *fs, int flags, const void *data) +{ + static int next_loop_num = MULTIROM_LOOP_NUM_START; + char path[64]; + int device_fd; + int loop_num = 0; + int res = -1; + struct stat info; + struct loop_info64 lo_info; + + for(loop_num = next_loop_num; loop_num < MAX_LOOP_NUM; ++loop_num) + { + sprintf(path, "/dev/block/loop%d", loop_num); + if(stat(path, &info) < 0) + { + if(errno == ENOENT) + break; + } + else if(S_ISBLK(info.st_mode) && (device_fd = open(path, O_RDWR | O_CLOEXEC)) >= 0) + { + int ioctl_res = ioctl(device_fd, LOOP_GET_STATUS64, &lo_info); + close(device_fd); + + if (ioctl_res < 0 && errno == ENXIO) + break; + } + } + + if(loop_num == MAX_LOOP_NUM) + { + ERROR("mount_image: failed to find suitable loop device number!\n"); + return -1; + } + + // now change to /multirom/dev/ + mkdir_recursive_with_perms(MULTIROM_DEV_PATH, 0777, NULL, NULL); + sprintf(path, MULTIROM_DEV_PATH "/%s", dst); + + if(create_loop_device(path, src, loop_num, 0777) < 0) + return -1; + + // never reuse an existing loop + next_loop_num = loop_num + 1; + + if(mount(path, dst, fs, flags, data) < 0) + ERROR("Failed to mount loop (%d: %s)\n", errno, strerror(errno)); + else + res = 0; + + sync(); + + return res; +} + void do_reboot(int type) { sync(); diff --git a/lib/util.h b/lib/util.h index 5e2936eb..5dc19d0d 100644 --- a/lib/util.h +++ b/lib/util.h @@ -57,6 +57,7 @@ inline int64_t timeval_us_diff(struct timeval now, struct timeval prev); void emergency_remount_ro(void); int create_loop_device(const char *dev_path, const char *img_path, int loop_num, int loop_chmod); int mount_image(const char *src, const char *dst, const char *fs, int flags, const void *data); +int multirom_mount_image(const char *src, const char *dst, const char *fs, int flags, const void *data); void do_reboot(int type); int mr_system(const char *shell_fmt, ...); diff --git a/multirom.c b/multirom.c index 456a0884..621eb651 100644 --- a/multirom.c +++ b/multirom.c @@ -1229,12 +1229,19 @@ int multirom_get_rom_type(struct multirom_rom *rom) // Handle android ROMs if(!multirom_path_exists(b, "boot")) { - if (!multirom_path_exists(b, "system") && !multirom_path_exists(b, "data") && + if(!multirom_path_exists(b, "system") && !multirom_path_exists(b, "data") && !multirom_path_exists(b, "cache")) { if(!rom->partition) return ROM_ANDROID_INTERNAL; else return ROM_ANDROID_USB_DIR; } + else if(!multirom_path_exists(b, "system.sparse.img") && + (!multirom_path_exists(b, "data") || !multirom_path_exists(b, "data.sparse.img")) && + (!multirom_path_exists(b, "cache") || !multirom_path_exists(b, "cache.sparse.img"))) + { + if(!rom->partition) return ROM_ANDROID_INTERNAL_HYBRID; + else return ROM_ANDROID_USB_HYBRID; + } else if(!multirom_path_exists(b, "system.img") && !multirom_path_exists(b, "data.img") && !multirom_path_exists(b, "cache.img")) { @@ -1394,6 +1401,8 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to case ROM_ANDROID_USB_IMG: case ROM_ANDROID_USB_DIR: case ROM_ANDROID_INTERNAL: + case ROM_ANDROID_INTERNAL_HYBRID: + case ROM_ANDROID_USB_HYBRID: { if(!(exit & (EXIT_REBOOT | EXIT_KEXEC))) { @@ -1561,59 +1570,75 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom if(has_fw) mkdir_with_perms("/firmware", 0771, "system", "system"); - static const char *folders[2][3] = - { - { "system", "data", "cache" }, - { "system.img", "data.img", "cache.img" }, - }; - - unsigned long flags[2][3] = { - { MS_BIND | MS_RDONLY, MS_BIND, MS_BIND }, - { MS_RDONLY | MS_NOATIME, MS_NOATIME, MS_NOATIME }, - }; + static const char *folders[3] = { "system" , "data" , "cache" }; + unsigned long flags[3] = { MS_RDONLY , MS_NOSUID | MS_NODEV , MS_NOSUID | MS_NODEV }; uint32_t i; char from[256]; char to[256]; - int img = (int)(rom->type == ROM_ANDROID_USB_IMG); - for(i = 0; i < ARRAY_SIZE(folders[0]); ++i) - { - snprintf(from, sizeof(from), "%s/%s", rom->base_path, folders[img][i]); - snprintf(to, sizeof(to), "/%s", folders[0][i]); - if(img == 0) - { - if(mount(from, to, "ext4", flags[img][i], "discard,nomblk_io_submit") < 0) - { + for (i = 0; i < ARRAY_SIZE(folders); ++i) { + snprintf(to, sizeof(to), "/%s", folders[i]); + + snprintf(from, sizeof(from), "%s/%s", rom->base_path, folders[i]); + if (!access(from, R_OK)) { + if(mount(from, to, "ext4", MS_BIND | flags[i], "discard,nomblk_io_submit") < 0) { ERROR("Failed to mount %s to %s (%d: %s)\n", from, to, errno, strerror(errno)); goto exit; - } + } else + INFO("Bind mounted %s on %s\n", from, to); + continue; } - else - { - if(mount_image(from, to, "ext4", flags[img][i], NULL) < 0) + + snprintf(from, sizeof(from), "%s/%s.img", rom->base_path, folders[i]); + if (!access(from, R_OK)) { + if(mount_image(from, to, "ext4", flags[i], NULL) < 0) goto exit; + else + INFO("Loop mounted %s on %s\n", from, to); + continue; } + + snprintf(from, sizeof(from), "%s/%s.sparse.img", rom->base_path, folders[i]); + if (!access(from, R_OK)) { + if(multirom_mount_image(from, to, "ext4", flags[i], NULL) < 0) + goto exit; + else + INFO("MultiROM Loop mounted %s on %s\n", from, to); + continue; + } + + // Neither directory nor .img nor .sparse.img was found, panic + goto exit; } - // make sure /system is ro, otherwise remount it ro - // if it's not ro, then the dir permissions may get changed to disallow 'x' (eg HTC 10) + + // mount() does not necessarily obey the mount options (eg, ro on system or nosuid on data) + // so attempt a remount on the partitions, but don't abort if the remount in unsuccessful, + // unless MR_PANIC_ON_FAILED_REMOUNT is set: eg on the HTC 10 if system is not ro, then the + // dir permissions may get changed to disallow 'x' struct statfs statfs_buf; - snprintf(to, sizeof(to), "/%s", folders[0][0]); // we could just use "/system", but this looks more sophisticated :P - INFO("Checking if system is ro\n"); - if(statfs(to, &statfs_buf) < 0) - { - ERROR("Couldn't statfs %s (%d: %s)\n", to, errno, strerror(errno)); - } - else if(!(statfs_buf.f_flags & ST_RDONLY)) - { - INFO("system seems rw, attempting ro remount\n"); - if(mount(NULL, to, NULL, MS_REMOUNT | MS_RDONLY | flags[img][0], NULL) < 0) // MS_RDONLY is redundant, but just in case it's changed/not in flags[][] - { - ERROR("Failed to remount ro %s (%d: %s)\n", to, errno, strerror(errno)); - goto exit; + for (i = 0; i < ARRAY_SIZE(folders); ++i) { + snprintf(to, sizeof(to), "/%s", folders[i]); + if(statfs(to, &statfs_buf) < 0) + ERROR("Couldn't statfs %s (%d: %s)\n", to, errno, strerror(errno)); + else if((flags[i] & ~statfs_buf.f_flags)) { + INFO("Mount flags of %s are 0x%08lX but should include 0x%08lX, attempting remount\n", + to, (unsigned long) statfs_buf.f_flags, flags[i]); + + if(mount(NULL, to, NULL, MS_REMOUNT | flags[i], NULL) < 0) { + ERROR("Failed to remount %s (%d: %s)\n", to, errno, strerror(errno)); +#ifdef MR_PANIC_ON_FAILED_REMOUNT + goto exit; +#endif + } + else { + if(statfs(to, &statfs_buf) < 0) + INFO("Remounted %s\n", to); + else + INFO("Remounted %s flags=0x%08lX\n", to, (unsigned long) statfs_buf.f_flags); + } } - INFO("Remounted system as ro\n"); } if(has_fw && fw_part) @@ -2080,6 +2105,8 @@ int multirom_load_kexec(struct multirom_status *s, struct multirom_rom *rom) case ROM_ANDROID_INTERNAL: case ROM_ANDROID_USB_DIR: case ROM_ANDROID_USB_IMG: + case ROM_ANDROID_INTERNAL_HYBRID: + case ROM_ANDROID_USB_HYBRID: if(multirom_fill_kexec_android(s, rom, &kexec) != 0) goto exit; break; diff --git a/multirom.h b/multirom.h index 4469ba27..70cab0ac 100644 --- a/multirom.h +++ b/multirom.h @@ -28,24 +28,28 @@ enum { - ROM_DEFAULT = 0, + ROM_DEFAULT = 0, - ROM_ANDROID_INTERNAL = 1, - ROM_ANDROID_USB_IMG = 2, - ROM_ANDROID_USB_DIR = 3, + ROM_ANDROID_INTERNAL = 1, + ROM_ANDROID_USB_IMG = 2, + ROM_ANDROID_USB_DIR = 3, + ROM_ANDROID_INTERNAL_HYBRID = 4, + ROM_ANDROID_USB_HYBRID = 5, - ROM_LINUX_INTERNAL = 4, - ROM_LINUX_USB = 5, + ROM_LINUX_INTERNAL = 6, + ROM_LINUX_USB = 7, - ROM_UNSUPPORTED_INT = 6, - ROM_UNSUPPORTED_USB = 7, - ROM_UNKNOWN = 8 + ROM_UNSUPPORTED_INT = 8, + ROM_UNSUPPORTED_USB = 9, + + ROM_UNKNOWN = 10 }; #define M(x) (1 << x) -#define MASK_INTERNAL (M(ROM_DEFAULT) | M(ROM_ANDROID_INTERNAL) | M(ROM_UNSUPPORTED_INT) | M(ROM_LINUX_INTERNAL)) -#define MASK_USB_ROMS (M(ROM_ANDROID_USB_IMG) | M(ROM_ANDROID_USB_DIR) | M(ROM_UNSUPPORTED_USB) | M(ROM_LINUX_USB)) -#define MASK_ANDROID (M(ROM_ANDROID_USB_DIR) | M(ROM_ANDROID_USB_IMG) | M(ROM_ANDROID_INTERNAL)) +#define MASK_INTERNAL (M(ROM_DEFAULT) | M(ROM_ANDROID_INTERNAL) | M(ROM_ANDROID_INTERNAL_HYBRID) | M(ROM_UNSUPPORTED_INT) | M(ROM_LINUX_INTERNAL)) +#define MASK_USB_ROMS (M(ROM_ANDROID_USB_IMG) | M(ROM_ANDROID_USB_DIR) | M(ROM_ANDROID_USB_HYBRID) | M(ROM_UNSUPPORTED_USB) | M(ROM_LINUX_USB)) +#define MASK_ANDROID (M(ROM_ANDROID_USB_DIR) | M(ROM_ANDROID_USB_HYBRID) | M(ROM_ANDROID_USB_IMG) | M(ROM_ANDROID_INTERNAL) | M(ROM_ANDROID_INTERNAL_HYBRID)) +#define MASK_HYBRID (M(ROM_ANDROID_INTERNAL_HYBRID) | M(ROM_ANDROID_USB_HYBRID)) #define MASK_UNSUPPORTED (M(ROM_UNSUPPORTED_USB) | M(ROM_UNSUPPORTED_INT)) #define MASK_LINUX (M(ROM_LINUX_INTERNAL) | M(ROM_LINUX_USB)) #define MASK_KEXEC (MASK_LINUX) From dc0719c9a90c13564ccb010be1de8bb615089ad5 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Wed, 30 Aug 2017 15:43:40 +0300 Subject: [PATCH 02/65] encmnt: Build required libs * libcryptfslollipop.so is dependent on libstdc++.so * For qcom hardware encryption libcrypfs_hw.so and its other libs (libunwind.so libbase.so libbacktrace.so libutils.so libcryptfs_hw.so) are needed --- trampoline_encmnt/Android.mk | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index 21f22717..5c73fa02 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -8,6 +8,12 @@ LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) LOCAL_SHARED_LIBRARIES := libcryptfslollipop libcutils LOCAL_STATIC_LIBRARIES := libmultirom_static +LOCAL_ADDITIONAL_DEPENDENCIES += libstdc++ + +ifeq ($(TARGET_HW_DISK_ENCRYPTION),true) + LOCAL_ADDITIONAL_DEPENDENCIES += libcryptfs_hw +endif + MR_NO_KEXEC_MK_OPTIONS := true 1 allowed 2 enabled 3 ui_confirm 4 ui_choice 5 forced ifneq (,$(filter $(MR_NO_KEXEC), $(MR_NO_KEXEC_MK_OPTIONS))) LOCAL_STATIC_LIBRARIES +=libbootimg From ad33909dcad922c8f07890be1b71380884de2ef4 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Wed, 30 Aug 2017 15:56:03 +0300 Subject: [PATCH 03/65] Fixup installer/uninstaller mk file --- install_zip/Android.mk | 108 +++++++++++++++++++++++------------------ 1 file changed, 62 insertions(+), 46 deletions(-) diff --git a/install_zip/Android.mk b/install_zip/Android.mk index 4bd60be8..c00b6298 100644 --- a/install_zip/Android.mk +++ b/install_zip/Android.mk @@ -16,14 +16,23 @@ multirom_extra_dep := ifeq ($(MR_ENCRYPTION),true) multirom_extra_dep += trampoline_encmnt linker + multirom_cp_enc_libs := \ + libcryptfslollipop.so libcrypto.so libc.so libcutils.so \ + libdl.so libhardware.so liblog.so libm.so libstdc++.so \ + libc++.so + + ifeq ($(TARGET_HW_DISK_ENCRYPTION),true) + multirom_cp_enc_libs += \ + libunwind.so libbase.so libbacktrace.so \ + libutils.so libcryptfs_hw.so + endif + ifeq ($(MR_ENCRYPTION_FAKE_PROPERTIES),true) multirom_extra_dep += libmultirom_fake_properties - else - MR_ENCRYPTION_FAKE_PROPERTIES := false + multirom_cp_enc_libs += libmultirom_fake_properties.so endif else MR_ENCRYPTION := false - MR_ENCRYPTION_FAKE_PROPERTIES := false endif MR_DEVICES := $(TARGET_DEVICE) @@ -42,46 +51,50 @@ $(MULTIROM_ZIP_TARGET): multirom trampoline signapk bbootimg mrom_kexec_static m @echo @echo ----- Making MultiROM ZIP installer ------ - rm -rf $(MULTIROM_INST_DIR) - mkdir -p $(MULTIROM_INST_DIR) - cp -a $(install_zip_path)/prebuilt-installer/* $(MULTIROM_INST_DIR)/ - cp -a $(TARGET_ROOT_OUT)/multirom $(MULTIROM_INST_DIR)/multirom/ - cp -a $(TARGET_ROOT_OUT)/trampoline $(MULTIROM_INST_DIR)/multirom/ - cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/mrom_kexec_static $(MULTIROM_INST_DIR)/multirom/kexec - cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/mrom_adbd $(MULTIROM_INST_DIR)/multirom/adbd - - if $(MR_ENCRYPTION); then \ + @rm -rf $(MULTIROM_INST_DIR) + @mkdir -p $(MULTIROM_INST_DIR) + @echo Copying primary files + @cp -a $(install_zip_path)/prebuilt-installer/* $(MULTIROM_INST_DIR)/ + @cp -a $(TARGET_ROOT_OUT)/multirom $(MULTIROM_INST_DIR)/multirom/ + @cp -a $(TARGET_ROOT_OUT)/trampoline $(MULTIROM_INST_DIR)/multirom/ + @cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/mrom_kexec_static $(MULTIROM_INST_DIR)/multirom/kexec + @cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/mrom_adbd $(MULTIROM_INST_DIR)/multirom/adbd + + @if $(MR_ENCRYPTION); then \ + echo "Copying decryption files"; \ mkdir -p $(MULTIROM_INST_DIR)/multirom/enc/res; \ cp -a $(TARGET_ROOT_OUT)/trampoline_encmnt $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_EXECUTABLES)/linker $(MULTIROM_INST_DIR)/multirom/enc/; \ + if [ "$(TARGET_IS_64_BIT)" == "true" ]; then \ + cp -a $(TARGET_OUT_EXECUTABLES)/linker64 $(MULTIROM_INST_DIR)/multirom/enc/linker; \ + else \ + cp -a $(TARGET_OUT_EXECUTABLES)/linker $(MULTIROM_INST_DIR)/multirom/enc/; \ + fi; \ cp -a $(install_zip_path)/prebuilt-installer/multirom/res/Roboto-Regular.ttf $(MULTIROM_INST_DIR)/multirom/enc/res/; \ \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libcryptfslollipop.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libcrypto.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libc.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libcutils.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libdl.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libhardware.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/liblog.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libm.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libstdc++.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libc++.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - if $(MR_ENCRYPTION_FAKE_PROPERTIES); then \ - cp -a $(TARGET_OUT_SHARED_LIBRARIES)/libmultirom_fake_properties.so $(MULTIROM_INST_DIR)/multirom/enc/; \ - fi; \ + for f in $(multirom_cp_enc_libs); do \ + if [ -f "$(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/$$f" ]; then \ + cp -a $(TARGET_OUT_VENDOR_SHARED_LIBRARIES)/$$f $(MULTIROM_INST_DIR)/multirom/enc/; \ + else \ + cp -a $(TARGET_OUT_SHARED_LIBRARIES)/$$f $(MULTIROM_INST_DIR)/multirom/enc/; \ + fi; \ + done; \ if [ -n "$(MR_ENCRYPTION_SETUP_SCRIPT)" ]; then sh "$(ANDROID_BUILD_TOP)/$(MR_ENCRYPTION_SETUP_SCRIPT)" "$(ANDROID_BUILD_TOP)" "$(MULTIROM_INST_DIR)/multirom/enc"; fi; \ fi - mkdir $(MULTIROM_INST_DIR)/multirom/infos - if [ -n "$(MR_INFOS)" ]; then cp -r $(PWD)/$(MR_INFOS)/* $(MULTIROM_INST_DIR)/multirom/infos/; fi - cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/bbootimg $(MULTIROM_INST_DIR)/scripts/ - cp $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/multirom/mrom.fstab - $(install_zip_path)/extract_boot_dev.sh $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/scripts/bootdev - $(install_zip_path)/make_updater_script.sh "$(MR_DEVICES)" $(MULTIROM_INST_DIR)/META-INF/com/google/android "Installing MultiROM for" - rm -f $(MULTIROM_ZIP_TARGET).zip $(MULTIROM_ZIP_TARGET)-unsigned.zip - cd $(MULTIROM_INST_DIR) && zip -qr ../$(notdir $@)-unsigned.zip * - java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_ZIP_TARGET)-unsigned.zip $(MULTIROM_ZIP_TARGET).zip - $(install_zip_path)/rename_zip.sh $(MULTIROM_ZIP_TARGET) $(TARGET_DEVICE) $(PWD)/$(multirom_local_path)/version.h $(MR_DEVICE_SPECIFIC_VERSION) + @echo Copying info files + @mkdir $(MULTIROM_INST_DIR)/multirom/infos + @if [ -n "$(MR_INFOS)" ]; then cp -vr $(PWD)/$(MR_INFOS)/* $(MULTIROM_INST_DIR)/multirom/infos/; fi + @echo Copying scripts + @cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/bbootimg $(MULTIROM_INST_DIR)/scripts/ + @cp $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/multirom/mrom.fstab + @echo Preparing installer script + @$(install_zip_path)/extract_boot_dev.sh $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/scripts/bootdev + @$(install_zip_path)/make_updater_script.sh "$(MR_DEVICES)" $(MULTIROM_INST_DIR)/META-INF/com/google/android "Installing MultiROM for" + @echo Signing flashable zip + @rm -f $(MULTIROM_ZIP_TARGET).zip $(MULTIROM_ZIP_TARGET)-unsigned.zip + @cd $(MULTIROM_INST_DIR) && zip -qr ../$(notdir $@)-unsigned.zip * + @java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_ZIP_TARGET)-unsigned.zip $(MULTIROM_ZIP_TARGET).zip + @$(install_zip_path)/rename_zip.sh $(MULTIROM_ZIP_TARGET) $(TARGET_DEVICE) $(PWD)/$(multirom_local_path)/version.h $(MR_DEVICE_SPECIFIC_VERSION) @echo ----- Made MultiROM ZIP installer -------- $@.zip .PHONY: multirom_zip @@ -94,16 +107,19 @@ MULTIROM_UNINST_DIR := $(PRODUCT_OUT)/multirom_uninstaller $(MULTIROM_UNINST_TARGET): signapk bbootimg @echo ----- Making MultiROM uninstaller ------ - rm -rf $(MULTIROM_UNINST_DIR) - mkdir -p $(MULTIROM_UNINST_DIR) - cp -a $(install_zip_path)/prebuilt-uninstaller/* $(MULTIROM_UNINST_DIR)/ - cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/bbootimg $(MULTIROM_UNINST_DIR)/scripts/ - $(install_zip_path)/extract_boot_dev.sh $(PWD)/$(MR_FSTAB) $(MULTIROM_UNINST_DIR)/scripts/bootdev - echo $(MR_RD_ADDR) > $(MULTIROM_UNINST_DIR)/scripts/rd_addr - $(install_zip_path)/make_updater_script.sh "$(MR_DEVICES)" $(MULTIROM_UNINST_DIR)/META-INF/com/google/android "MultiROM uninstaller -" - rm -f $(MULTIROM_UNINST_TARGET).zip $(MULTIROM_UNINST_TARGET)-unsigned.zip - cd $(MULTIROM_UNINST_DIR) && zip -qr ../$(notdir $@)-unsigned.zip * - java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_UNINST_TARGET)-unsigned.zip $(MULTIROM_UNINST_TARGET).zip + @rm -rf $(MULTIROM_UNINST_DIR) + @mkdir -p $(MULTIROM_UNINST_DIR) + @echo Copying files + @cp -a $(install_zip_path)/prebuilt-uninstaller/* $(MULTIROM_UNINST_DIR)/ + @cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/bbootimg $(MULTIROM_UNINST_DIR)/scripts/ + @echo Preparing installer script + @$(install_zip_path)/extract_boot_dev.sh $(PWD)/$(MR_FSTAB) $(MULTIROM_UNINST_DIR)/scripts/bootdev + @echo $(MR_RD_ADDR) > $(MULTIROM_UNINST_DIR)/scripts/rd_addr + @$(install_zip_path)/make_updater_script.sh "$(MR_DEVICES)" $(MULTIROM_UNINST_DIR)/META-INF/com/google/android "MultiROM uninstaller -" + @echo Signing flashable zip + @rm -f $(MULTIROM_UNINST_TARGET).zip $(MULTIROM_UNINST_TARGET)-unsigned.zip + @cd $(MULTIROM_UNINST_DIR) && zip -qr ../$(notdir $@)-unsigned.zip * + @java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_UNINST_TARGET)-unsigned.zip $(MULTIROM_UNINST_TARGET).zip @echo ----- Made MultiROM uninstaller -------- $@.zip .PHONY: multirom_uninstaller From 87f97da138438ba043c820484ffd9467a6548333 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Wed, 30 Aug 2017 16:04:03 +0300 Subject: [PATCH 04/65] encmnt: Use linker[64] from /mrom_enc directory * It's easier to relink trampoline_encmnt and qseecomd to use /mrom_enc/linker[64] instead of symlinking it in /system. * This needs to be done after all the copies and other scripts have run and the files are in the final output dir $(MULTIROM_INST_DIR)/multirom/enc/. --- install_zip/Android.mk | 25 ++++++++++++++++++++----- trampoline/encryption.c | 17 ++++------------- 2 files changed, 24 insertions(+), 18 deletions(-) diff --git a/install_zip/Android.mk b/install_zip/Android.mk index c00b6298..25e6c978 100644 --- a/install_zip/Android.mk +++ b/install_zip/Android.mk @@ -64,11 +64,7 @@ $(MULTIROM_ZIP_TARGET): multirom trampoline signapk bbootimg mrom_kexec_static m echo "Copying decryption files"; \ mkdir -p $(MULTIROM_INST_DIR)/multirom/enc/res; \ cp -a $(TARGET_ROOT_OUT)/trampoline_encmnt $(MULTIROM_INST_DIR)/multirom/enc/; \ - if [ "$(TARGET_IS_64_BIT)" == "true" ]; then \ - cp -a $(TARGET_OUT_EXECUTABLES)/linker64 $(MULTIROM_INST_DIR)/multirom/enc/linker; \ - else \ - cp -a $(TARGET_OUT_EXECUTABLES)/linker $(MULTIROM_INST_DIR)/multirom/enc/; \ - fi; \ + \ cp -a $(install_zip_path)/prebuilt-installer/multirom/res/Roboto-Regular.ttf $(MULTIROM_INST_DIR)/multirom/enc/res/; \ \ for f in $(multirom_cp_enc_libs); do \ @@ -79,6 +75,25 @@ $(MULTIROM_ZIP_TARGET): multirom trampoline signapk bbootimg mrom_kexec_static m fi; \ done; \ if [ -n "$(MR_ENCRYPTION_SETUP_SCRIPT)" ]; then sh "$(ANDROID_BUILD_TOP)/$(MR_ENCRYPTION_SETUP_SCRIPT)" "$(ANDROID_BUILD_TOP)" "$(MULTIROM_INST_DIR)/multirom/enc"; fi; \ + \ + if [ "$(TARGET_IS_64_BIT)" == "true" ]; then \ + cp -a $(TARGET_OUT_EXECUTABLES)/linker64 $(MULTIROM_INST_DIR)/multirom/enc/; \ + echo "Relinking trampoline_encmnt /system/bin/linker64 to /mrom_enc/linker64"; \ + sed -i "s|/system/bin/linker64\x0|/mrom_enc/linker64\x0\x0\x0|g" $(MULTIROM_INST_DIR)/multirom/enc/trampoline_encmnt; \ + if [ -f "$(MULTIROM_INST_DIR)/multirom/enc/qseecomd" ]; then \ + echo "Relinking qseecomd /system/bin/linker64 to /mrom_enc/linker64"; \ + sed -i "s|/system/bin/linker64\x0|/mrom_enc/linker64\x0\x0\x0|g" $(MULTIROM_INST_DIR)/multirom/enc/qseecomd; \ + fi; \ + else \ + cp -a $(TARGET_OUT_EXECUTABLES)/linker $(MULTIROM_INST_DIR)/multirom/enc/; \ + echo "Relinking trampoline_encmnt /system/bin/linker to /mrom_enc/linker"; \ + sed -i "s|/system/bin/linker\x0|/mrom_enc/linker\x0\x0\x0|g" $(MULTIROM_INST_DIR)/multirom/enc/trampoline_encmnt; \ + if [ -f "$(MULTIROM_INST_DIR)/multirom/enc/qseecomd" ]; then \ + echo "Relinking qseecomd /system/bin/linker to /mrom_enc/linker"; \ + sed -i "s|/system/bin/linker\x0|/mrom_enc/linker\x0\x0\x0|g" $(MULTIROM_INST_DIR)/multirom/enc/qseecomd; \ + fi; \ + fi; \ + \ fi @echo Copying info files diff --git a/trampoline/encryption.c b/trampoline/encryption.c index e1d7e020..344f13fd 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -41,22 +41,17 @@ static char *const encmnt_envp[] = { "LD_LIBRARY_PATH=/mrom_enc/", NULL }; #endif static int g_decrypted = 0; -#ifdef __LP64__ -#define LINKER_PATH "/system/bin/linker64" -#else -#define LINKER_PATH "/system/bin/linker" -#endif - int encryption_before_mount(struct fstab *fstab) { int exit_code = -1; char *output = NULL, *itr; int res = ENC_RES_ERR; - mkdir_recursive("/system/bin", 0755); - remove(LINKER_PATH); - symlink("/mrom_enc/linker", LINKER_PATH); +#ifdef __LP64__ + chmod("/mrom_enc/linker64", 0775); +#else chmod("/mrom_enc/linker", 0775); +#endif chmod("/mrom_enc/trampoline_encmnt", 0775); // some fonts not in ramdisk to save space, so use regular instead symlink("/mrom_enc/res/Roboto-Regular.ttf", "/mrom_enc/res/Roboto-Italic.ttf"); @@ -147,10 +142,6 @@ void encryption_destroy(void) g_decrypted = 0; free(output); } - - // Make sure we're removing our symlink and not ROM's linker - if(lstat(LINKER_PATH, &info) >= 0 && S_ISLNK(info.st_mode)) - remove(LINKER_PATH); } int encryption_cleanup(void) From dd1918f3b2aa2fe3499438531494579e8a451b24 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Fri, 8 Sep 2017 17:39:43 +0300 Subject: [PATCH 05/65] Don't build MultiROM when building TWRP --- Android.mk | 2 +- lib/Android.mk | 4 ++-- trampoline/Android.mk | 2 +- trampoline_encmnt/Android.mk | 4 ++-- 4 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Android.mk b/Android.mk index 7a0b6cf7..ed787ec0 100644 --- a/Android.mk +++ b/Android.mk @@ -30,7 +30,7 @@ LOCAL_CFLAGS += -O3 -funsafe-math-optimizations #LOCAL_CFLAGS += -D_FORTIFY_SOURCE=2 -fstack-protector-all -O0 -g -fno-omit-frame-pointer -Wall LOCAL_MODULE:= multirom -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) diff --git a/lib/Android.mk b/lib/Android.mk index 3c5be35c..eef72b40 100644 --- a/lib/Android.mk +++ b/lib/Android.mk @@ -58,7 +58,7 @@ endif include $(CLEAR_VARS) LOCAL_MODULE := libmultirom_static -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) LOCAL_CFLAGS += $(common_C_FLAGS) @@ -83,7 +83,7 @@ include $(BUILD_STATIC_LIBRARY) include $(CLEAR_VARS) LOCAL_MODULE := libmultirom -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libcutils libc libm libpng libz libft2 LOCAL_CFLAGS += $(common_C_FLAGS) LOCAL_SRC_FILES := $(common_SRC_FILES) diff --git a/trampoline/Android.mk b/trampoline/Android.mk index 8e5cab14..adf13578 100644 --- a/trampoline/Android.mk +++ b/trampoline/Android.mk @@ -8,7 +8,7 @@ LOCAL_SRC_FILES:= \ adb.c \ LOCAL_MODULE:= trampoline -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index 5c73fa02..4c336da4 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -2,7 +2,7 @@ LOCAL_PATH:= $(call my-dir) include $(CLEAR_VARS) LOCAL_MODULE:= trampoline_encmnt -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) LOCAL_SHARED_LIBRARIES := libcryptfslollipop libcutils @@ -45,7 +45,7 @@ ifeq ($(MR_ENCRYPTION_FAKE_PROPERTIES),true) include $(CLEAR_VARS) LOCAL_MODULE := libmultirom_fake_properties - LOCAL_MODULE_TAGS := eng + LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES += $(multirom_local_path) LOCAL_SRC_FILES := fake_properties.c From da0485ceba63f5cae34b8c594f54979f924f9906 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Fri, 15 Sep 2017 18:06:52 +0300 Subject: [PATCH 06/65] rom_quirks: Add Android 8.0 plat_file_contexts exclusions * Android 8 uses plat_file_contexts and nonplat_file_contexts * Android 8 also uses 'restorecon --recursive --skip-ce /data' --- rom_quirks.c | 26 ++++++++++++++++++++------ 1 file changed, 20 insertions(+), 6 deletions(-) diff --git a/rom_quirks.c b/rom_quirks.c index 9b94b697..bd7554c1 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -148,8 +148,11 @@ static void disable_restorecon_recursive(void) while(fgets(line, sizeof(line), f_in)) { - if(strstr(line, "restorecon_recursive ") && (strstr(line, "/data") || strstr(line, "/system") || strstr(line, "/cache") || strstr(line, "/mnt"))) - fputc('#', f_out); + if (strstr(line, "restorecon_recursive ") || (strstr(line, "restorecon ") && strstr(line, "--recursive"))) { + if (strstr(line, "/data") || strstr(line, "/system") || strstr(line, "/cache") || strstr(line, "/mnt")) { + fputc('#', f_out); + } + } fputs(line, f_out); } @@ -680,6 +683,8 @@ static int inject_file_contexts_bin(const char *path) void rom_quirks_on_initrd_finalized(void) { + int file_contexts_injected = 0; + // walk over all _regular_ files in / DIR *d = opendir("/"); if(d) @@ -702,8 +707,14 @@ void rom_quirks_on_initrd_finalized(void) // Android N is using the binary format of file_contexts, try to inject it // with MultiROM exclusions, if that fails go back to the old method and remove // 'restorecon_recursive' from init.rc scripts - if((strcmp(dt->d_name, "file_contexts") == 0) || (strcmp(dt->d_name, "file_contexts.bin") == 0)) - { + // + // Android 8.0 is using text format contexts again, but now has two separate files + // 'nonplat_file_contexts' and 'plat_file_contexts', we need to patch the latter + // https://source.android.com/security/selinux/images/SELinux_Treble.pdf + if( (strcmp(dt->d_name, "file_contexts") == 0) + || (strcmp(dt->d_name, "file_contexts.bin") == 0) + || (strcmp(dt->d_name, "plat_file_contexts") == 0) + ) { FILE *f; uint32_t magic = 0; int res = 1; @@ -723,8 +734,8 @@ void rom_quirks_on_initrd_finalized(void) res = inject_file_contexts(buff); } - if(res != 0) - disable_restorecon_recursive(); + if(res == 0) + file_contexts_injected = 1; } // franco.Kernel includes script init.fk.sh which remounts /system as read only @@ -737,4 +748,7 @@ void rom_quirks_on_initrd_finalized(void) } closedir(d); } + + if (!file_contexts_injected) + disable_restorecon_recursive(); } From d2e61ff6c35bf5813fb1b2dd33c42805b489f944 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Thu, 28 Sep 2017 15:50:26 +0300 Subject: [PATCH 07/65] For Android ROMs use default icon if no custom icon is set --- .../multirom/icons/romic_android_default.png | Bin 0 -> 12503 bytes multirom.c | 15 ++++++++++++--- 2 files changed, 12 insertions(+), 3 deletions(-) create mode 100644 install_zip/prebuilt-installer/multirom/icons/romic_android_default.png diff --git a/install_zip/prebuilt-installer/multirom/icons/romic_android_default.png b/install_zip/prebuilt-installer/multirom/icons/romic_android_default.png new file mode 100644 index 0000000000000000000000000000000000000000..3cbaea1e90799a9282a6bb06cd6d4104560f46f5 GIT binary patch literal 12503 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 literal 0 HcmV?d00001 diff --git a/multirom.c b/multirom.c index 621eb651..27a64de6 100644 --- a/multirom.c +++ b/multirom.c @@ -3074,6 +3074,8 @@ int multirom_run_scripts(const char *type, struct multirom_rom *rom) #define USER_IC_PATH_LEN 46 #define DEFAULT_ICON "/icons/romic_default.png" #define DEFAULT_ICON_LEN 24 +#define DEFAULT_ANDROID_ICON "/icons/romic_android_default.png" +#define DEFAULT_ANDROID_ICON_LEN 32 void multirom_find_rom_icon(struct multirom_rom *rom) { @@ -3138,7 +3140,14 @@ void multirom_find_rom_icon(struct multirom_rom *rom) if(f) fclose(f); - len = strlen(mrom_dir()) + DEFAULT_ICON_LEN + 1; - rom->icon_path = realloc(rom->icon_path, len); - snprintf(rom->icon_path, len, "%s%s", mrom_dir(), DEFAULT_ICON); + if (rom->type & MASK_ANDROID) { + len = strlen(mrom_dir()) + DEFAULT_ANDROID_ICON_LEN + 1; + rom->icon_path = realloc(rom->icon_path, len); + snprintf(rom->icon_path, len, "%s%s", mrom_dir(), DEFAULT_ANDROID_ICON); + } + else { + len = strlen(mrom_dir()) + DEFAULT_ICON_LEN + 1; + rom->icon_path = realloc(rom->icon_path, len); + snprintf(rom->icon_path, len, "%s%s", mrom_dir(), DEFAULT_ICON); + } } From 6e70beacd6845565174bb20f40cf7008de28e015 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Tue, 3 Oct 2017 14:01:46 +0300 Subject: [PATCH 08/65] Update default android rom icon --- .../multirom/icons/romic_android.png | Bin 4056 -> 13181 bytes .../multirom/icons/romic_android_old.png | Bin 0 -> 4056 bytes 2 files changed, 0 insertions(+), 0 deletions(-) create mode 100644 install_zip/prebuilt-installer/multirom/icons/romic_android_old.png diff --git a/install_zip/prebuilt-installer/multirom/icons/romic_android.png b/install_zip/prebuilt-installer/multirom/icons/romic_android.png index 0b55c4bc67323bd51f7c97cedcee2f9312e28229..ce6d4ba2791d71447cd335ad9f3057f149a0736d 100644 GIT binary patch literal 13181 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 E1F2)AQ2+n{ diff --git a/install_zip/prebuilt-installer/multirom/icons/romic_android_old.png b/install_zip/prebuilt-installer/multirom/icons/romic_android_old.png new file mode 100644 index 0000000000000000000000000000000000000000..0b55c4bc67323bd51f7c97cedcee2f9312e28229 GIT binary patch literal 4056 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 E1F2)AQ2+n{ literal 0 HcmV?d00001 From 5326d9188150ebeb7fffa822a16fb542df3eac96 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Sat, 7 Oct 2017 15:51:00 +0300 Subject: [PATCH 09/65] rom_quirks: Separate file_contexts injection code * Use a separate .c file for the 'inject_file_contexts()' function which will handle both text and binary format file_contexts. * Only rely on the 'multirom_exclusion_path' string array to add the needed exclusions. This will become useful once the multirom directory changes. * This also allows us to use the same file for exclusions in TWRP. --- Android.mk | 1 + rom_quirks.c | 577 +------------------------------- rq_inject_file_contexts.c | 617 +++++++++++++++++++++++++++++++++++ rq_inject_file_contexts.h | 28 ++ trampoline_encmnt/Android.mk | 1 + 5 files changed, 649 insertions(+), 575 deletions(-) create mode 100644 rq_inject_file_contexts.c create mode 100644 rq_inject_file_contexts.h diff --git a/Android.mk b/Android.mk index ed787ec0..f3ee86cc 100644 --- a/Android.mk +++ b/Android.mk @@ -22,6 +22,7 @@ LOCAL_SRC_FILES:= \ pong.c \ rcadditions.c \ rom_quirks.c \ + rq_inject_file_contexts.c \ # With these, GCC optimizes aggressively enough so full-screen alpha blending # is quick enough to be done in an animation diff --git a/rom_quirks.c b/rom_quirks.c index bd7554c1..ce805aec 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -24,6 +24,7 @@ #include #include "rom_quirks.h" +#include "rq_inject_file_contexts.h" #include "lib/log.h" #include "lib/util.h" @@ -66,51 +67,6 @@ static void workaround_mount_in_sh(const char *path) free(tmp_name); } -static int inject_file_contexts(const char *path) -{ - FILE *f; - char line[512]; - - f = fopen(path, "re"); - if(!f) - { - ERROR("Failed to open /file_contexts!\n"); - return -1; - } - - while(fgets(line, sizeof(line), f)) - { - if(strstartswith(line, "/data/media/multirom")) - { - INFO("/file_contexts has been already injected.\n"); - fclose(f); - return 0; - } - } - - fclose(f); - - INFO("Injecting /file_contexts\n"); - f = fopen(path, "ae"); - if(!f) - { - ERROR("Failed to open /file_contexts for appending!\n"); - return -1; - } - - fputs("\n" - "# MultiROM folders\n" - "/data/media/multirom(/.*)? <>\n" - "/data/media/0/multirom(/.*)? <>\n" - "/realdata/media/multirom(/.*)? <>\n" - "/realdata/media/0/multirom(/.*)? <>\n" - "/mnt/mrom(/.*)? <>\n", - f); - fclose(f); - - return 0; -} - // Keep this as a backup function in case the file_contexts binary injection doesn't work static void disable_restorecon_recursive(void) { @@ -168,519 +124,6 @@ static void disable_restorecon_recursive(void) } } -/* ************************************************************************************************************************************************ */ -/* - * Functions to deal with bin formatted file_contexts (ie compiled regex) - * - */ - -#define NUM_OF_REGEXS_EXCLUSIONS 5 - -const char *multirom_exclusion_path[NUM_OF_REGEXS_EXCLUSIONS] = { - "/data/media/multirom", - "/data/media/0/multirom", - "/realdata/media/multirom", - "/realdata/media/0/multirom", - "/mnt/mrom", -}; - -// The structure and content of the compiled regex_info and study_data -// was extrapolated from '/data/media(/.*)?' compiled regex, and then -// hardcoded here, which seems to work fine for now. -// -// Alternatively, we can decompile the existing file_contexts.bin and -// find the '/data/media(/.*)?' compiled regex, and use it to build -// the multirom exclusion regexs; this may actually be a better (if possible) -// solution than hardcoding, but for the time being all the file_contexts.bin -// I've seen are all version 4, and have the same structure: -// -// Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F -// -// 00000000 21 00 00 00 75 3A 6F 62 6A 65 63 74 5F 72 3A 6D !...u:object_r:m -// 00000010 65 64 69 61 5F 72 77 5F 64 61 74 61 5F 66 69 6C edia_rw_data_fil -// 00000020 65 3A 73 30 00 12 00 00 00 2F 64 61 74 61 2F 6D e:s0...../data/m -// 00000030 65 64 69 61 28 2F 2E 2A 29 3F 00 00 00 00 00 03 edia(/.*)?...... -// 00000040 00 00 00 01 00 00 00 0B 00 00 00 62 00 00 00 45 ...........b...E -// 00000050 52 43 50 62 00 00 00 14 00 00 00 01 00 00 00 FF RCPb...........ÿ -// 00000060 FF FF FF FF FF FF FF 00 00 00 00 00 00 01 00 00 ÿÿÿÿÿÿÿ......... -// 00000070 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .@.............. -// 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 83 ...............Æ’ -// 00000090 00 1E 1B 1D 2F 1D 6D 1D 65 1D 64 1D 69 1D 61 92 ..../.m.e.d.i.a’ -// 000000A0 85 00 09 00 01 1D 2F 55 0D 78 00 09 19 78 00 1E …...../U.x...x.. -// 000000B0 00 2C 00 00 00 2C 00 00 00 02 00 00 00 00 00 00 .,...,.......... -// 000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ -// 000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00 ................ -// 000000E0 00 . - -#define COMPILED_ERCP_P1 (char[]) { \ - 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \ - 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, \ - 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ - 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00 \ - } - -#define COMPILED_ERCP_P2 (char[]) { 0x92, 0x85, 0x00, 0x09, 0x00, 0x01, 0x1D, 0x2F, 0x55, 0x0D, 0x78, 0x00, 0x09, 0x19, 0x78, 0x00 } - - -#define SELINUX_MAGIC_COMPILED_FCONTEXT 0xf97cff8a - -/* Version specific changes */ -#define SELINUX_COMPILED_FCONTEXT_NOPCRE_VERS 1 -#define SELINUX_COMPILED_FCONTEXT_PCRE_VERS 2 -#define SELINUX_COMPILED_FCONTEXT_MODE 3 -#define SELINUX_COMPILED_FCONTEXT_PREFIX_LEN 4 -#define SELINUX_COMPILED_FCONTEXT_REGEX_ARCH 5 - -#define SELINUX_COMPILED_FCONTEXT_MAX_VERS \ - SELINUX_COMPILED_FCONTEXT_REGEX_ARCH - -/* A regular expression stem */ -typedef struct { - uint32_t stem_len; - char *stem_string; -} stem_s; - -typedef struct { - uint32_t len_context_string; - char * str_context_string; - - uint32_t len_regex_string; - char * str_regex_string; - - uint32_t mode_bits; - int32_t stem_id; - uint32_t spec_has_meta_chars; - - uint32_t prefix_len; - - uint32_t len_raw_pcre_regex_info; - char * buf_raw_pcre_regex_info; - - uint32_t len_raw_pcre_regex_study_data; - char * buf_raw_pcre_regex_study_data; -} regex_s; - - -uint8_t calc_len_raw_pcre_regex_subpart(const char *exclusion_path) -{ - char *path_less_stem = strchr(exclusion_path + 1, '/'); - return (sizeof(uint8_t) + (strlen(path_less_stem) * 2) + sizeof(COMPILED_ERCP_P2) + sizeof(uint8_t)); -} - -uint32_t calc_len_raw_pcre_regex_info(const char *exclusion_path) -{ - uint32_t r = 0; - char *path_less_stem = strchr(exclusion_path + 1, '/'); - - r += sizeof(uint32_t); // MAGIC - r += sizeof(uint32_t); // len_raw_pcre_regex_info - r += sizeof(COMPILED_ERCP_P1); // - r += sizeof(uint8_t); // len_raw_pcre_regex_subpart - r += sizeof(char); // - r += strlen(path_less_stem) * 2; // length of the unicode string - r += sizeof(COMPILED_ERCP_P2); // - r += sizeof(uint8_t); // len_raw_pcre_regex_subpart - r += sizeof(uint8_t); // null - - return r; -} - -char *construct_raw_pcre_regex_info(char *dest, const char *exclusion_path) -{ - char *buf = dest; - size_t off = 0; - char *path_less_stem = strchr(exclusion_path + 1, '/'); - - uint32_t len_raw_pcre_regex_info = calc_len_raw_pcre_regex_info(exclusion_path); - uint8_t len_raw_pcre_regex_subpart = calc_len_raw_pcre_regex_subpart(exclusion_path); - - memcpy(buf + off, "ERCP", 4); - off += 4; - - memcpy(buf + off, &len_raw_pcre_regex_info, sizeof(uint32_t)); - off += sizeof(uint32_t); - - memcpy(buf + off, COMPILED_ERCP_P1, sizeof(COMPILED_ERCP_P1)); - off += sizeof(COMPILED_ERCP_P1); - - memcpy(buf + off, &len_raw_pcre_regex_subpart, sizeof(uint8_t)); - off += sizeof(uint8_t); - - memcpy(buf + off, (char[]){ 0x1B }, 1); - off += 1; - - // copy as unicode string, without trailing null - while (path_less_stem[0]) - { - buf[off++] = 0x1D; - buf[off++] = path_less_stem[0]; - path_less_stem++; - } - - memcpy(buf + off, COMPILED_ERCP_P2, sizeof(COMPILED_ERCP_P2)); - off += sizeof(COMPILED_ERCP_P2); - - memcpy(buf + off, &len_raw_pcre_regex_subpart, sizeof(uint8_t)); - off += sizeof(uint8_t); - - memcpy(buf + off, (char[]){ 0x00 }, 1); - off += 1; - - return dest; -} - - -typedef struct { - uint32_t len_raw_pcre_regex_study_data; - uint32_t unknown02; - uint32_t null_1; - uint32_t null_2; - uint32_t null_3; - uint32_t null_4; - uint32_t null_5; - uint32_t null_6; - uint32_t null_7; - uint32_t null_9; - uint32_t len_path_less_stem; -} raw_pcre_regex_study_data_s; - -uint32_t calc_len_raw_pcre_regex_study_data(UNUSED const char *exclusion_path) -{ - return sizeof(raw_pcre_regex_study_data_s); -} - -uint32_t calc_len_path_less_stem(const char *exclusion_path) -{ - return strlen(strchr(exclusion_path + 1, '/')); -} - -char *construct_raw_pcre_regex_study_data(char *dest, const char *exclusion_path) -{ - uint32_t len_raw_pcre_regex_study_data = calc_len_raw_pcre_regex_study_data(exclusion_path); - uint32_t len_path_less_stem = calc_len_path_less_stem(exclusion_path); - - memset(dest, 0, sizeof(raw_pcre_regex_study_data_s)); - - ((raw_pcre_regex_study_data_s *)dest)->len_raw_pcre_regex_study_data = len_raw_pcre_regex_study_data; - ((raw_pcre_regex_study_data_s *)dest)->unknown02 = 2; - ((raw_pcre_regex_study_data_s *)dest)->len_path_less_stem = len_path_less_stem; - - return dest; -} - - -// TODO: add error handling -static int inject_file_contexts_bin(const char *path) -{ - /* - * File Format - * - * u32 - magic number - * u32 - version - * u32 - length of pcre version EXCLUDING nul - * char - pcre version string EXCLUDING nul - * u32 - number of stems - * ** Stems - * u32 - length of stem EXCLUDING nul - * char - stem char array INCLUDING nul - * u32 - number of regexs - * ** Regexes - * u32 - length of upcoming context INCLUDING nul - * char - char array of the raw context - * u32 - length of the upcoming regex_str - * char - char array of the original regex string including the stem. - * u32 - mode bits for >= SELINUX_COMPILED_FCONTEXT_MODE - * mode_t for <= SELINUX_COMPILED_FCONTEXT_PCRE_VERS - * s32 - stemid associated with the regex - * u32 - spec has meta characters - * u32 - The specs prefix_len if >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN - * u32 - data length of the pcre regex - * char - a bufer holding the raw pcre regex info - * u32 - data length of the pcre regex study daya - * char - a buffer holding the raw pcre regex study data - */ - - FILE *bin_file_in; - FILE *bin_file_out; - size_t len; - - // header - uint32_t magic; - uint32_t version; - uint32_t reg_version_len; - char *reg_version_string; - uint32_t regex_arch_len; - char *regex_arch_string; - - bin_file_in = fopen(path, "rb"); - if (!bin_file_in) { - ERROR("Failed to open '%s' for reading!\n", path); - return -1; - } - - /* check if this looks like an fcontext file */ - len = fread(&magic, sizeof(uint32_t), 1, bin_file_in); - if (len != 1 || magic != SELINUX_MAGIC_COMPILED_FCONTEXT) - { - fclose(bin_file_in); - return -1; - } - - /* check if this version is higher than we understand */ - len = fread(&version, sizeof(uint32_t), 1, bin_file_in); - if (len != 1 || version != 4) // if (len != 1 || version > SELINUX_COMPILED_FCONTEXT_MAX_VERS) - { - // we currently only support version 4, all the ones i have seen are version 4 at the moment - ERROR("Unsupported /file_contexts.bin version %d\n", version); - fclose(bin_file_in); - return -1; - } - - - // we can process this, let's open the output file and start - char *tmp_name = NULL; - const int size = strlen(path) + 5; - tmp_name = malloc(size); - snprintf(tmp_name, size, "%s-new", path); - - bin_file_out = fopen(tmp_name, "w"); - if (!bin_file_out) { - ERROR("Failed to open '%s' for writing!\n", tmp_name); - fclose(bin_file_in); - free(tmp_name); - return -1; - } - - /* write some magic number */ - len = fwrite(&magic, sizeof(uint32_t), 1, bin_file_out); - - /* write the version */ - len = fwrite(&version, sizeof(uint32_t), 1, bin_file_out); - - - if (version >= SELINUX_COMPILED_FCONTEXT_PCRE_VERS) { - /* read version of the regex back-end */ - len = fread(®_version_len, sizeof(uint32_t), 1, bin_file_in); - - reg_version_string = malloc(reg_version_len + 1); - len = fread(reg_version_string, sizeof(char), reg_version_len, bin_file_in); - reg_version_string[reg_version_len] = '\0'; - - /* write version of the regex back-end */ - len = fwrite(®_version_len, sizeof(uint32_t), 1, bin_file_out); - len = fwrite(reg_version_string, sizeof(char), reg_version_len, bin_file_out); - - free(reg_version_string); - - if (version >= SELINUX_COMPILED_FCONTEXT_REGEX_ARCH) { - /* read regex arch string */ - len = fread(®ex_arch_len, sizeof(uint32_t), 1, bin_file_in); - regex_arch_string = malloc(regex_arch_len + 1); - len = fread(regex_arch_string, sizeof(char), regex_arch_len, bin_file_in); - regex_arch_string[regex_arch_len] = '\0'; - - /* write regex arch string */ - len = fwrite(®ex_arch_len, sizeof(uint32_t), 1, bin_file_out); - len = fwrite(regex_arch_string, sizeof(char), regex_arch_len, bin_file_out); - - free(regex_arch_string); - } - } - - - // read in the stems, check for missing and add - uint32_t i; - uint32_t number_of_stems; - int32_t data_stem_id = -1; - int32_t realdata_stem_id = -1; - int32_t mnt_stem_id = -1; - - /* read the number of stems coming */ - len = fread(&number_of_stems, sizeof(uint32_t), 1, bin_file_in); - stem_s *stem_array; - stem_array = malloc((number_of_stems + 3) * sizeof(stem_s)); // add 3 since mrom additions could use them - - for (i = 0; i < number_of_stems; i++) - { - /* read the strlen (aka no nul) */ - len = fread(&stem_array[i].stem_len, sizeof(uint32_t), 1, bin_file_in); - - /* include the nul in the file */ - stem_array[i].stem_string = malloc(stem_array[i].stem_len + 1); - len = fread(stem_array[i].stem_string, sizeof(char), stem_array[i].stem_len + 1, bin_file_in); - - if (strcmp(stem_array[i].stem_string, "/data") == 0) - data_stem_id = i; - else if (strcmp(stem_array[i].stem_string, "/realdata") == 0) - realdata_stem_id = i; - else if (strcmp(stem_array[i].stem_string, "/mnt") == 0) - mnt_stem_id = i; - } - - // if 'realdata' already exists assume multirom exclusions are present - // this should be faster than finding 'multirom' in the regexs - if (realdata_stem_id != -1) - { - INFO("/file_contexts.bin has been already injected.\n"); - for (i = 0; i < number_of_stems; i++) - free(stem_array[i].stem_string); - free(stem_array); - goto noerr; - } - - INFO("Injecting /file_contexts.bin\n"); - - // add new stems here - if (data_stem_id == -1) - { - stem_array[i].stem_string = strdup("/data"); - stem_array[number_of_stems].stem_len = strlen(stem_array[i].stem_string); - data_stem_id = number_of_stems; - number_of_stems += 1; - } - if (realdata_stem_id == -1) - { - stem_array[i].stem_string = strdup("/realdata"); - stem_array[number_of_stems].stem_len = strlen(stem_array[i].stem_string); - realdata_stem_id = number_of_stems; - number_of_stems += 1; - } - if (mnt_stem_id == -1) - { - stem_array[i].stem_string = strdup("/mnt"); - stem_array[number_of_stems].stem_len = strlen(stem_array[i].stem_string); - mnt_stem_id = number_of_stems; - number_of_stems += 1; - } - - /* write the number of stems coming */ - len = fwrite(&number_of_stems, sizeof(uint32_t), 1, bin_file_out); - - for (i = 0; i < number_of_stems; i++) - { - /* write the strlen (aka no nul) */ - len = fwrite(&stem_array[i].stem_len, sizeof(uint32_t), 1, bin_file_out); - - /* include the nul in the file */ - len = fwrite(stem_array[i].stem_string, sizeof(char), stem_array[i].stem_len + 1, bin_file_out); - - free(stem_array[i].stem_string); - } - free(stem_array); - - - uint32_t number_of_regexs; - /* read the number of regexes coming */ - len = fread(&number_of_regexs, sizeof(uint32_t), 1, bin_file_in); - - /* write the number of regexes coming */ - number_of_regexs += NUM_OF_REGEXS_EXCLUSIONS; // add mrom exclusions count - len = fwrite(&number_of_regexs, sizeof(uint32_t), 1, bin_file_out); - - - //// now write (actually copy/paste) the normal regexs back since we don't want to - //// read and parse them in, do nothing and write them back - #define BUFFER_SIZE 1024*1024 - char *buf = malloc(BUFFER_SIZE); - while ((len = fread(buf, 1, BUFFER_SIZE, bin_file_in)) > 0) - { - len = fwrite(buf, 1, len, bin_file_out); - } - free(buf); - - - // now adjust the stem_id and write the multirom exclusions - for (i = 0; i < NUM_OF_REGEXS_EXCLUSIONS; i++) - { - regex_s regex; - - // build the compiled regex - regex.str_context_string = "<>", - regex.len_context_string = strlen(regex.str_context_string) + 1; - - regex.str_regex_string = malloc(strlen(multirom_exclusion_path[i]) + 7); - strcpy(regex.str_regex_string, multirom_exclusion_path[i]); - strcat(regex.str_regex_string, "(/.*)?"); - - regex.len_regex_string = strlen(regex.str_regex_string) + 1; - regex.prefix_len = strlen(multirom_exclusion_path[i]); - - regex.mode_bits = 0x00000000; - regex.spec_has_meta_chars = 0x00000001; - - if (strncmp(regex.str_regex_string, "/data", sizeof("/data") - 1) == 0) - regex.stem_id = data_stem_id; - else if (strncmp(regex.str_regex_string, "/realdata", sizeof("/realdata") - 1) == 0) - regex.stem_id = realdata_stem_id; - else if (strncmp(regex.str_regex_string, "/mnt", sizeof("/mnt") - 1) == 0) - regex.stem_id = mnt_stem_id; - // else error - - - // now write the compiled regex - len = fwrite(®ex.len_context_string, sizeof(uint32_t), 1, bin_file_out); - len = fwrite(regex.str_context_string, sizeof(char), regex.len_context_string, bin_file_out); - - len = fwrite(®ex.len_regex_string, sizeof(uint32_t), 1, bin_file_out); - len = fwrite(regex.str_regex_string, sizeof(char), regex.len_regex_string, bin_file_out); - - len = fwrite(®ex.mode_bits, sizeof(uint32_t), 1, bin_file_out); - len = fwrite(®ex.stem_id, sizeof(int32_t), 1, bin_file_out); - len = fwrite(®ex.spec_has_meta_chars, sizeof(uint32_t), 1, bin_file_out); - - len = fwrite(®ex.prefix_len, sizeof(uint32_t), 1, bin_file_out); - free(regex.str_regex_string); - - - // construct here (ie we're constructing it from extrapolating from '/data/media(/.*)?', not generating a compiled version) - regex.len_raw_pcre_regex_info = (uint32_t)calc_len_raw_pcre_regex_info(multirom_exclusion_path[i]); - regex.buf_raw_pcre_regex_info = malloc(regex.len_raw_pcre_regex_info); - if(regex.buf_raw_pcre_regex_info) - { - construct_raw_pcre_regex_info(regex.buf_raw_pcre_regex_info, multirom_exclusion_path[i]); - len = fwrite(®ex.len_raw_pcre_regex_info, sizeof(uint32_t), 1, bin_file_out); - len = fwrite(regex.buf_raw_pcre_regex_info, sizeof(char), regex.len_raw_pcre_regex_info, bin_file_out); - free(regex.buf_raw_pcre_regex_info); - } - //else error - - regex.len_raw_pcre_regex_study_data = (uint32_t)calc_len_raw_pcre_regex_study_data(multirom_exclusion_path[i]); - regex.buf_raw_pcre_regex_study_data = malloc(regex.len_raw_pcre_regex_study_data); - if(regex.buf_raw_pcre_regex_study_data) - { - construct_raw_pcre_regex_study_data(regex.buf_raw_pcre_regex_study_data, multirom_exclusion_path[i]); - len = fwrite(®ex.len_raw_pcre_regex_study_data, sizeof(uint32_t), 1, bin_file_out); - len = fwrite(regex.buf_raw_pcre_regex_study_data, sizeof(char), regex.len_raw_pcre_regex_study_data, bin_file_out); - free(regex.buf_raw_pcre_regex_study_data); - } - //else error - } - -out: - fclose(bin_file_out); - fclose(bin_file_in); - rename(tmp_name, path); - chmod(path, 0644); - //copy_file(path, "/cache/file_contexts.bin-new"); // in case we need to debug - free(tmp_name); - return 0; -noerr: - fclose(bin_file_out); - fclose(bin_file_in); - remove(tmp_name); - free(tmp_name); - return 0; -err: - fclose(bin_file_out); - fclose(bin_file_in); - remove(tmp_name); - free(tmp_name); - return -2; -} -/* ************************************************************************************************************************************************ */ - - void rom_quirks_on_initrd_finalized(void) { int file_contexts_injected = 0; @@ -715,26 +158,10 @@ void rom_quirks_on_initrd_finalized(void) || (strcmp(dt->d_name, "file_contexts.bin") == 0) || (strcmp(dt->d_name, "plat_file_contexts") == 0) ) { - FILE *f; - uint32_t magic = 0; - int res = 1; snprintf(buff, sizeof(buff), "/%s", dt->d_name); - f = fopen(buff, "rb"); - if (f) - { - if (fread(&magic, sizeof magic, 1, f) != 1) - ERROR("Could not read magic in '%s'\n", buff); - fclose(f); - - if (magic == SELINUX_MAGIC_COMPILED_FCONTEXT) - res = inject_file_contexts_bin(buff); - else - res = inject_file_contexts(buff); - } - - if(res == 0) + if(inject_file_contexts(buff) == 0) file_contexts_injected = 1; } diff --git a/rq_inject_file_contexts.c b/rq_inject_file_contexts.c new file mode 100644 index 00000000..73bb81cc --- /dev/null +++ b/rq_inject_file_contexts.c @@ -0,0 +1,617 @@ +/* + * This file is part of MultiROM. + * + * MultiROM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MultiROM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MultiROM. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include + +#include "rq_inject_file_contexts.h" +#include "lib/log.h" +#include "lib/util.h" + + +// NOTE: stems are still hardcoded to 3 possibilities: +// "/data", "/realdata" and "/mnt" + +const char *multirom_exclusion_path[] = { + "/data/media/multirom", + "/data/media/0/multirom", + "/realdata/media/multirom", + "/realdata/media/0/multirom", + "/mnt/mrom", +}; + +#define REGEX_PATTERN "(/.*)?" +#define CONTEXT_STRING "<>" + + +/* Inject text format file_contexts */ +static int inject_file_contexts_text(const char *path) +{ + FILE *f; + char line[512]; + unsigned int i; + + f = fopen(path, "re"); + if (!f) { + ERROR("Failed to open /file_contexts!\n"); + return -1; + } + + while (fgets(line, sizeof(line), f)) { + if (strstartswith(line, multirom_exclusion_path[0])) { + INFO("/file_contexts has been already injected.\n"); + fclose(f); + return 0; + } + } + + fclose(f); + + INFO("Injecting /file_contexts\n"); + f = fopen(path, "ae"); + if (!f) { + ERROR("Failed to open /file_contexts for appending!\n"); + return -1; + } + + fputs("\n" + "# MultiROM folders\n", f); + + for (i = 0; i < ARRAY_SIZE(multirom_exclusion_path); ++i) { + fprintf(f, "%s%s %s\n", multirom_exclusion_path[i], REGEX_PATTERN, CONTEXT_STRING); + } + fclose(f); + + return 0; +} + + +/* ************************************************************************************************************************************************ */ +/* + * Functions to deal with bin formatted file_contexts (ie compiled regex) + * + */ + +// The structure and content of the compiled regex_info and study_data +// was extrapolated from '/data/media(/.*)?' compiled regex, and then +// hardcoded here, which seems to work fine for now. +// +// Alternatively, we can decompile the existing file_contexts.bin and +// find the '/data/media(/.*)?' compiled regex, and use it to build +// the multirom exclusion regexs; this may actually be a better (if possible) +// solution than hardcoding, but for the time being all the file_contexts.bin +// I've seen are all version 4, and have the same structure: +// +// Offset(h) 00 01 02 03 04 05 06 07 08 09 0A 0B 0C 0D 0E 0F +// +// 00000000 21 00 00 00 75 3A 6F 62 6A 65 63 74 5F 72 3A 6D !...u:object_r:m +// 00000010 65 64 69 61 5F 72 77 5F 64 61 74 61 5F 66 69 6C edia_rw_data_fil +// 00000020 65 3A 73 30 00 12 00 00 00 2F 64 61 74 61 2F 6D e:s0...../data/m +// 00000030 65 64 69 61 28 2F 2E 2A 29 3F 00 00 00 00 00 03 edia(/.*)?...... +// 00000040 00 00 00 01 00 00 00 0B 00 00 00 62 00 00 00 45 ...........b...E +// 00000050 52 43 50 62 00 00 00 14 00 00 00 01 00 00 00 FF RCPb...........ÿ +// 00000060 FF FF FF FF FF FF FF 00 00 00 00 00 00 01 00 00 ÿÿÿÿÿÿÿ......... +// 00000070 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 .@.............. +// 00000080 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 83 ...............Æ’ +// 00000090 00 1E 1B 1D 2F 1D 6D 1D 65 1D 64 1D 69 1D 61 92 ..../.m.e.d.i.a’ +// 000000A0 85 00 09 00 01 1D 2F 55 0D 78 00 09 19 78 00 1E …...../U.x...x.. +// 000000B0 00 2C 00 00 00 2C 00 00 00 02 00 00 00 00 00 00 .,...,.......... +// 000000C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................ +// 000000D0 00 00 00 00 00 00 00 00 00 00 00 00 00 06 00 00 ................ +// 000000E0 00 . + +#define COMPILED_ERCP_P1 (char[]) { \ + 0x14, 0x00, 0x00, 0x00, 0x01, 0x00, 0x00, 0x00, 0xFF, 0xFF, 0xFF, 0xFF, \ + 0xFF, 0xFF, 0xFF, 0xFF, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x00, \ + 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, \ + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x00 \ + } + +#define COMPILED_ERCP_P2 (char[]) { 0x92, 0x85, 0x00, 0x09, 0x00, 0x01, 0x1D, 0x2F, 0x55, 0x0D, 0x78, 0x00, 0x09, 0x19, 0x78, 0x00 } + + +#define SELINUX_MAGIC_COMPILED_FCONTEXT 0xf97cff8a + +/* Version specific changes */ +#define SELINUX_COMPILED_FCONTEXT_NOPCRE_VERS 1 +#define SELINUX_COMPILED_FCONTEXT_PCRE_VERS 2 +#define SELINUX_COMPILED_FCONTEXT_MODE 3 +#define SELINUX_COMPILED_FCONTEXT_PREFIX_LEN 4 +#define SELINUX_COMPILED_FCONTEXT_REGEX_ARCH 5 + +#define SELINUX_COMPILED_FCONTEXT_MAX_VERS \ + SELINUX_COMPILED_FCONTEXT_REGEX_ARCH + +/* A regular expression stem */ +typedef struct { + uint32_t stem_len; + char *stem_string; +} stem_s; + +typedef struct { + uint32_t len_context_string; + char * str_context_string; + + uint32_t len_regex_string; + char * str_regex_string; + + uint32_t mode_bits; + int32_t stem_id; + uint32_t spec_has_meta_chars; + + uint32_t prefix_len; + + uint32_t len_raw_pcre_regex_info; + char * buf_raw_pcre_regex_info; + + uint32_t len_raw_pcre_regex_study_data; + char * buf_raw_pcre_regex_study_data; +} regex_s; + + +static uint8_t calc_len_raw_pcre_regex_subpart(const char *exclusion_path) +{ + char *path_less_stem = strchr(exclusion_path + 1, '/'); + return (sizeof(uint8_t) + (strlen(path_less_stem) * 2) + sizeof(COMPILED_ERCP_P2) + sizeof(uint8_t)); +} + +static uint32_t calc_len_raw_pcre_regex_info(const char *exclusion_path) +{ + uint32_t r = 0; + char *path_less_stem = strchr(exclusion_path + 1, '/'); + + r += sizeof(uint32_t); // MAGIC + r += sizeof(uint32_t); // len_raw_pcre_regex_info + r += sizeof(COMPILED_ERCP_P1); // + r += sizeof(uint8_t); // len_raw_pcre_regex_subpart + r += sizeof(char); // + r += strlen(path_less_stem) * 2; // length of the unicode string + r += sizeof(COMPILED_ERCP_P2); // + r += sizeof(uint8_t); // len_raw_pcre_regex_subpart + r += sizeof(uint8_t); // null + + return r; +} + +static char *construct_raw_pcre_regex_info(char *dest, const char *exclusion_path) +{ + char *buf = dest; + size_t off = 0; + char *path_less_stem = strchr(exclusion_path + 1, '/'); + + uint32_t len_raw_pcre_regex_info = calc_len_raw_pcre_regex_info(exclusion_path); + uint8_t len_raw_pcre_regex_subpart = calc_len_raw_pcre_regex_subpart(exclusion_path); + + memcpy(buf + off, "ERCP", 4); + off += 4; + + memcpy(buf + off, &len_raw_pcre_regex_info, sizeof(uint32_t)); + off += sizeof(uint32_t); + + memcpy(buf + off, COMPILED_ERCP_P1, sizeof(COMPILED_ERCP_P1)); + off += sizeof(COMPILED_ERCP_P1); + + memcpy(buf + off, &len_raw_pcre_regex_subpart, sizeof(uint8_t)); + off += sizeof(uint8_t); + + memcpy(buf + off, (char[]){ 0x1B }, 1); + off += 1; + + // copy as unicode string, without trailing null + while (path_less_stem[0]) + { + buf[off++] = 0x1D; + buf[off++] = path_less_stem[0]; + path_less_stem++; + } + + memcpy(buf + off, COMPILED_ERCP_P2, sizeof(COMPILED_ERCP_P2)); + off += sizeof(COMPILED_ERCP_P2); + + memcpy(buf + off, &len_raw_pcre_regex_subpart, sizeof(uint8_t)); + off += sizeof(uint8_t); + + memcpy(buf + off, (char[]){ 0x00 }, 1); + off += 1; + + return dest; +} + + +typedef struct { + uint32_t len_raw_pcre_regex_study_data; + uint32_t unknown02; + uint32_t null_1; + uint32_t null_2; + uint32_t null_3; + uint32_t null_4; + uint32_t null_5; + uint32_t null_6; + uint32_t null_7; + uint32_t null_9; + uint32_t len_path_less_stem; +} raw_pcre_regex_study_data_s; + +static uint32_t calc_len_raw_pcre_regex_study_data(UNUSED const char *exclusion_path) +{ + return sizeof(raw_pcre_regex_study_data_s); +} + +static uint32_t calc_len_path_less_stem(const char *exclusion_path) +{ + return strlen(strchr(exclusion_path + 1, '/')); +} + +static char *construct_raw_pcre_regex_study_data(char *dest, const char *exclusion_path) +{ + uint32_t len_raw_pcre_regex_study_data = calc_len_raw_pcre_regex_study_data(exclusion_path); + uint32_t len_path_less_stem = calc_len_path_less_stem(exclusion_path); + + memset(dest, 0, sizeof(raw_pcre_regex_study_data_s)); + + ((raw_pcre_regex_study_data_s *)dest)->len_raw_pcre_regex_study_data = len_raw_pcre_regex_study_data; + ((raw_pcre_regex_study_data_s *)dest)->unknown02 = 2; + ((raw_pcre_regex_study_data_s *)dest)->len_path_less_stem = len_path_less_stem; + + return dest; +} + + +/* Inject binary format file_contexts */ +// TODO: add error handling +static int inject_file_contexts_bin(const char *path) +{ + /* + * File Format + * + * u32 - magic number + * u32 - version + * u32 - length of pcre version EXCLUDING nul + * char - pcre version string EXCLUDING nul + * u32 - number of stems + * ** Stems + * u32 - length of stem EXCLUDING nul + * char - stem char array INCLUDING nul + * u32 - number of regexs + * ** Regexes + * u32 - length of upcoming context INCLUDING nul + * char - char array of the raw context + * u32 - length of the upcoming regex_str + * char - char array of the original regex string including the stem. + * u32 - mode bits for >= SELINUX_COMPILED_FCONTEXT_MODE + * mode_t for <= SELINUX_COMPILED_FCONTEXT_PCRE_VERS + * s32 - stemid associated with the regex + * u32 - spec has meta characters + * u32 - The specs prefix_len if >= SELINUX_COMPILED_FCONTEXT_PREFIX_LEN + * u32 - data length of the pcre regex + * char - a bufer holding the raw pcre regex info + * u32 - data length of the pcre regex study daya + * char - a buffer holding the raw pcre regex study data + */ + + FILE *bin_file_in; + FILE *bin_file_out; + size_t len; + + // header + uint32_t magic; + uint32_t version; + uint32_t reg_version_len; + char *reg_version_string; + uint32_t regex_arch_len; + char *regex_arch_string; + + bin_file_in = fopen(path, "rb"); + if (!bin_file_in) { + ERROR("Failed to open '%s' for reading!\n", path); + return -1; + } + + /* check if this looks like an fcontext file */ + len = fread(&magic, sizeof(uint32_t), 1, bin_file_in); + if (len != 1 || magic != SELINUX_MAGIC_COMPILED_FCONTEXT) + { + fclose(bin_file_in); + return -1; + } + + /* check if this version is higher than we understand */ + len = fread(&version, sizeof(uint32_t), 1, bin_file_in); + if (len != 1 || version != 4) // if (len != 1 || version > SELINUX_COMPILED_FCONTEXT_MAX_VERS) + { + // we currently only support version 4, all the ones i have seen are version 4 at the moment + ERROR("Unsupported /file_contexts.bin version %d\n", version); + fclose(bin_file_in); + return -1; + } + + + // we can process this, let's open the output file and start + char *tmp_name = NULL; + const int size = strlen(path) + 5; + tmp_name = malloc(size); + snprintf(tmp_name, size, "%s-new", path); + + bin_file_out = fopen(tmp_name, "w"); + if (!bin_file_out) { + ERROR("Failed to open '%s' for writing!\n", tmp_name); + fclose(bin_file_in); + free(tmp_name); + return -1; + } + + /* write some magic number */ + len = fwrite(&magic, sizeof(uint32_t), 1, bin_file_out); + + /* write the version */ + len = fwrite(&version, sizeof(uint32_t), 1, bin_file_out); + + + if (version >= SELINUX_COMPILED_FCONTEXT_PCRE_VERS) { + /* read version of the regex back-end */ + len = fread(®_version_len, sizeof(uint32_t), 1, bin_file_in); + + reg_version_string = malloc(reg_version_len + 1); + len = fread(reg_version_string, sizeof(char), reg_version_len, bin_file_in); + reg_version_string[reg_version_len] = '\0'; + + /* write version of the regex back-end */ + len = fwrite(®_version_len, sizeof(uint32_t), 1, bin_file_out); + len = fwrite(reg_version_string, sizeof(char), reg_version_len, bin_file_out); + + free(reg_version_string); + + if (version >= SELINUX_COMPILED_FCONTEXT_REGEX_ARCH) { + /* read regex arch string */ + len = fread(®ex_arch_len, sizeof(uint32_t), 1, bin_file_in); + regex_arch_string = malloc(regex_arch_len + 1); + len = fread(regex_arch_string, sizeof(char), regex_arch_len, bin_file_in); + regex_arch_string[regex_arch_len] = '\0'; + + /* write regex arch string */ + len = fwrite(®ex_arch_len, sizeof(uint32_t), 1, bin_file_out); + len = fwrite(regex_arch_string, sizeof(char), regex_arch_len, bin_file_out); + + free(regex_arch_string); + } + } + + + // read in the stems, check for missing and add + uint32_t i; + uint32_t number_of_stems; + int32_t data_stem_id = -1; + int32_t realdata_stem_id = -1; + int32_t mnt_stem_id = -1; + + /* read the number of stems coming */ + len = fread(&number_of_stems, sizeof(uint32_t), 1, bin_file_in); + stem_s *stem_array; + stem_array = malloc((number_of_stems + 3) * sizeof(stem_s)); // add 3 since mrom additions could use them + + for (i = 0; i < number_of_stems; i++) + { + /* read the strlen (aka no nul) */ + len = fread(&stem_array[i].stem_len, sizeof(uint32_t), 1, bin_file_in); + + /* include the nul in the file */ + stem_array[i].stem_string = malloc(stem_array[i].stem_len + 1); + len = fread(stem_array[i].stem_string, sizeof(char), stem_array[i].stem_len + 1, bin_file_in); + + if (strcmp(stem_array[i].stem_string, "/data") == 0) + data_stem_id = i; + else if (strcmp(stem_array[i].stem_string, "/realdata") == 0) + realdata_stem_id = i; + else if (strcmp(stem_array[i].stem_string, "/mnt") == 0) + mnt_stem_id = i; + } + + // if 'realdata' already exists assume multirom exclusions are present + // this should be faster than finding 'multirom' in the regexs + if (realdata_stem_id != -1) + { + INFO("/file_contexts.bin has been already injected.\n"); + for (i = 0; i < number_of_stems; i++) + free(stem_array[i].stem_string); + free(stem_array); + goto noerr; + } + + INFO("Injecting /file_contexts.bin\n"); + + // add new stems here + if (data_stem_id == -1) + { + stem_array[i].stem_string = strdup("/data"); + stem_array[number_of_stems].stem_len = strlen(stem_array[i].stem_string); + data_stem_id = number_of_stems; + number_of_stems += 1; + } + if (realdata_stem_id == -1) + { + stem_array[i].stem_string = strdup("/realdata"); + stem_array[number_of_stems].stem_len = strlen(stem_array[i].stem_string); + realdata_stem_id = number_of_stems; + number_of_stems += 1; + } + if (mnt_stem_id == -1) + { + stem_array[i].stem_string = strdup("/mnt"); + stem_array[number_of_stems].stem_len = strlen(stem_array[i].stem_string); + mnt_stem_id = number_of_stems; + number_of_stems += 1; + } + + /* write the number of stems coming */ + len = fwrite(&number_of_stems, sizeof(uint32_t), 1, bin_file_out); + + for (i = 0; i < number_of_stems; i++) + { + /* write the strlen (aka no nul) */ + len = fwrite(&stem_array[i].stem_len, sizeof(uint32_t), 1, bin_file_out); + + /* include the nul in the file */ + len = fwrite(stem_array[i].stem_string, sizeof(char), stem_array[i].stem_len + 1, bin_file_out); + + free(stem_array[i].stem_string); + } + free(stem_array); + + + uint32_t number_of_regexs; + /* read the number of regexes coming */ + len = fread(&number_of_regexs, sizeof(uint32_t), 1, bin_file_in); + + /* write the number of regexes coming */ + number_of_regexs += ARRAY_SIZE(multirom_exclusion_path); // add mrom exclusions count + len = fwrite(&number_of_regexs, sizeof(uint32_t), 1, bin_file_out); + + + //// now write (actually copy/paste) the normal regexs back since we don't want to + //// read and parse them in, do nothing and write them back + #define BUFFER_SIZE 1024*1024 + char *buf = malloc(BUFFER_SIZE); + while ((len = fread(buf, 1, BUFFER_SIZE, bin_file_in)) > 0) + { + len = fwrite(buf, 1, len, bin_file_out); + } + free(buf); + + + // now adjust the stem_id and write the multirom exclusions + for (i = 0; i < ARRAY_SIZE(multirom_exclusion_path); ++i) + { + regex_s regex; + + // build the compiled regex + regex.str_context_string = CONTEXT_STRING, + regex.len_context_string = strlen(regex.str_context_string) + 1; + + regex.str_regex_string = malloc(strlen(multirom_exclusion_path[i]) + strlen(REGEX_PATTERN) + 1); + strcpy(regex.str_regex_string, multirom_exclusion_path[i]); + strcat(regex.str_regex_string, REGEX_PATTERN); + + regex.len_regex_string = strlen(regex.str_regex_string) + 1; + regex.prefix_len = strlen(multirom_exclusion_path[i]); + + regex.mode_bits = 0x00000000; + regex.spec_has_meta_chars = 0x00000001; + + if (strncmp(regex.str_regex_string, "/data", sizeof("/data") - 1) == 0) + regex.stem_id = data_stem_id; + else if (strncmp(regex.str_regex_string, "/realdata", sizeof("/realdata") - 1) == 0) + regex.stem_id = realdata_stem_id; + else if (strncmp(regex.str_regex_string, "/mnt", sizeof("/mnt") - 1) == 0) + regex.stem_id = mnt_stem_id; + // else error + + + // now write the compiled regex + len = fwrite(®ex.len_context_string, sizeof(uint32_t), 1, bin_file_out); + len = fwrite(regex.str_context_string, sizeof(char), regex.len_context_string, bin_file_out); + + len = fwrite(®ex.len_regex_string, sizeof(uint32_t), 1, bin_file_out); + len = fwrite(regex.str_regex_string, sizeof(char), regex.len_regex_string, bin_file_out); + + len = fwrite(®ex.mode_bits, sizeof(uint32_t), 1, bin_file_out); + len = fwrite(®ex.stem_id, sizeof(int32_t), 1, bin_file_out); + len = fwrite(®ex.spec_has_meta_chars, sizeof(uint32_t), 1, bin_file_out); + + len = fwrite(®ex.prefix_len, sizeof(uint32_t), 1, bin_file_out); + free(regex.str_regex_string); + + + // construct here (ie we're constructing it from extrapolating from '/data/media(/.*)?', not generating a compiled version) + regex.len_raw_pcre_regex_info = (uint32_t)calc_len_raw_pcre_regex_info(multirom_exclusion_path[i]); + regex.buf_raw_pcre_regex_info = malloc(regex.len_raw_pcre_regex_info); + if(regex.buf_raw_pcre_regex_info) + { + construct_raw_pcre_regex_info(regex.buf_raw_pcre_regex_info, multirom_exclusion_path[i]); + len = fwrite(®ex.len_raw_pcre_regex_info, sizeof(uint32_t), 1, bin_file_out); + len = fwrite(regex.buf_raw_pcre_regex_info, sizeof(char), regex.len_raw_pcre_regex_info, bin_file_out); + free(regex.buf_raw_pcre_regex_info); + } + //else error + + regex.len_raw_pcre_regex_study_data = (uint32_t)calc_len_raw_pcre_regex_study_data(multirom_exclusion_path[i]); + regex.buf_raw_pcre_regex_study_data = malloc(regex.len_raw_pcre_regex_study_data); + if(regex.buf_raw_pcre_regex_study_data) + { + construct_raw_pcre_regex_study_data(regex.buf_raw_pcre_regex_study_data, multirom_exclusion_path[i]); + len = fwrite(®ex.len_raw_pcre_regex_study_data, sizeof(uint32_t), 1, bin_file_out); + len = fwrite(regex.buf_raw_pcre_regex_study_data, sizeof(char), regex.len_raw_pcre_regex_study_data, bin_file_out); + free(regex.buf_raw_pcre_regex_study_data); + } + //else error + } + +out: + fclose(bin_file_out); + fclose(bin_file_in); + rename(tmp_name, path); + chmod(path, 0644); +#if 0 + // in case we need to debug + copy_file(path, "/cache/file_contexts.bin-new"); +#endif + free(tmp_name); + return 0; +noerr: + fclose(bin_file_out); + fclose(bin_file_in); + remove(tmp_name); + free(tmp_name); + return 0; +err: + fclose(bin_file_out); + fclose(bin_file_in); + remove(tmp_name); + free(tmp_name); + return -2; +} +/* ************************************************************************************************************************************************ */ + +/* + * Main inject_file_contexts() function will determine + * if the file is a compiled binary format or text format + * and act accordingly. + */ +int inject_file_contexts(const char *path) +{ + FILE *f; + uint32_t magic = 0; + int res = 1; + + f = fopen(path, "rb"); + if (f) { + if (fread(&magic, sizeof magic, 1, f) != 1) + ERROR("Could not read magic in '%s'\n", path); + fclose(f); + + if (magic == SELINUX_MAGIC_COMPILED_FCONTEXT) + res = inject_file_contexts_bin(path); + else + res = inject_file_contexts_text(path); + } + return res; +} diff --git a/rq_inject_file_contexts.h b/rq_inject_file_contexts.h new file mode 100644 index 00000000..88183ca2 --- /dev/null +++ b/rq_inject_file_contexts.h @@ -0,0 +1,28 @@ +/* + * This file is part of MultiROM. + * + * MultiROM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MultiROM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MultiROM. If not, see . + */ + +#ifndef _RQ_INJECT_FILE_CONTEXTS_H +#define _RQ_INJECT_FILE_CONTEXTS_H + +/* + * Main inject_file_contexts() function will determine + * if the file is a compiled binary format or text format + * and act accordingly. + */ +int inject_file_contexts(const char *path); + +#endif //_RQ_INJECT_FILE_CONTEXTS_H diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index 4c336da4..b764ac98 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -35,6 +35,7 @@ LOCAL_SRC_FILES := \ encmnt.c \ pw_ui.c \ ../rom_quirks.c \ + ../rq_inject_file_contexts.c \ include $(multirom_local_path)/device_defines.mk From 67c144ee40162ed059f7969b222e24deded0e4b0 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Sat, 7 Oct 2017 22:37:00 +0300 Subject: [PATCH 10/65] All MultiROM tags should be optional * ref: https://github.com/nkk71/multirom/commit/c732106eacb39cf843a513498b32a23a535d6039 --- kernel_inject/Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/kernel_inject/Android.mk b/kernel_inject/Android.mk index ad443940..b8084b74 100644 --- a/kernel_inject/Android.mk +++ b/kernel_inject/Android.mk @@ -10,7 +10,7 @@ LOCAL_SRC_FILES:= \ kernel_inject.c \ LOCAL_MODULE:= kernel_inject -LOCAL_MODULE_TAGS := eng +LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) From b85bb36e82c98f8143cfda6dbc2d51026ae2e2d2 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Mon, 9 Oct 2017 15:08:56 +0300 Subject: [PATCH 11/65] inject_file_contexts: Remove lib/util dependency and make buildable in TWRP --- rq_inject_file_contexts.c | 20 +++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/rq_inject_file_contexts.c b/rq_inject_file_contexts.c index 73bb81cc..e4d9099b 100644 --- a/rq_inject_file_contexts.c +++ b/rq_inject_file_contexts.c @@ -24,8 +24,22 @@ #include #include "rq_inject_file_contexts.h" -#include "lib/log.h" -#include "lib/util.h" + +#ifndef TARGET_RECOVERY_IS_MULTIROM + #include "lib/log.h" +#else + #include "twcommon.h" + #define INFO(...) LOGINFO("MultiROM " __VA_ARGS__) + #define ERROR(...) LOGINFO("MultiROM " __VA_ARGS__) +#endif + +#ifndef UNUSED +#define UNUSED __attribute__((unused)) +#endif + +#ifndef ARRAY_SIZE +#define ARRAY_SIZE(x) (sizeof(x)/sizeof(x[0])) +#endif // NOTE: stems are still hardcoded to 3 possibilities: @@ -57,7 +71,7 @@ static int inject_file_contexts_text(const char *path) } while (fgets(line, sizeof(line), f)) { - if (strstartswith(line, multirom_exclusion_path[0])) { + if (strncmp(line, multirom_exclusion_path[0], strlen(multirom_exclusion_path[0])) == 0) { INFO("/file_contexts has been already injected.\n"); fclose(f); return 0; From e1d6742ec05608ef42a467f168bb21af5ea7445d Mon Sep 17 00:00:00 2001 From: nkk71 Date: Mon, 16 Oct 2017 23:02:15 +0300 Subject: [PATCH 12/65] inject_file_contexts: Check all injections are successful --- rom_quirks.c | 11 +++++++---- 1 file changed, 7 insertions(+), 4 deletions(-) diff --git a/rom_quirks.c b/rom_quirks.c index ce805aec..447609dc 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -126,7 +126,7 @@ static void disable_restorecon_recursive(void) void rom_quirks_on_initrd_finalized(void) { - int file_contexts_injected = 0; + int failed_file_contexts_injections = 0; // walk over all _regular_ files in / DIR *d = opendir("/"); @@ -154,6 +154,9 @@ void rom_quirks_on_initrd_finalized(void) // Android 8.0 is using text format contexts again, but now has two separate files // 'nonplat_file_contexts' and 'plat_file_contexts', we need to patch the latter // https://source.android.com/security/selinux/images/SELinux_Treble.pdf + // + // The possibility of several combinations of file_contexts, file_contexts.bin and + // plat_file_contexts seems to exist, so use a fail counter instead. if( (strcmp(dt->d_name, "file_contexts") == 0) || (strcmp(dt->d_name, "file_contexts.bin") == 0) || (strcmp(dt->d_name, "plat_file_contexts") == 0) @@ -161,8 +164,8 @@ void rom_quirks_on_initrd_finalized(void) snprintf(buff, sizeof(buff), "/%s", dt->d_name); - if(inject_file_contexts(buff) == 0) - file_contexts_injected = 1; + if (inject_file_contexts(buff) != 0) + failed_file_contexts_injections++; } // franco.Kernel includes script init.fk.sh which remounts /system as read only @@ -176,6 +179,6 @@ void rom_quirks_on_initrd_finalized(void) closedir(d); } - if (!file_contexts_injected) + if (failed_file_contexts_injections) disable_restorecon_recursive(); } From 8c43dc03ceb3114c48fc818537184420f87a8744 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Sun, 15 Oct 2017 19:19:55 +0300 Subject: [PATCH 13/65] Block sdcardfs uid/gid/mode derivation on MultiROM * sdcardfs (re)sets uid+gid+mode on /data/media and it's subdirectories to media_rw:media_rw or to the appropriate settings for a per app directory. Refer to https://goo.gl/frxVpi for more details. * This will effectively break all secondary ROMs since they are stored in /data/media/0/multirom. * To block this from happening move multirom to a subdirectory within a 'container' directory in /data/media/0 and set this 'container' directory to be immutable. Doing so will result in /data/media/0/MultiROM not being affected by any changes (nor can it be manipulated), it's subdirectories however '/data/media/0/MultiROM/multirom/...' can be used normally. * The directory is set immutable during MultiROM installation, in trampoline, as well as MultiROM-TWRP to avoid potential problems if someone decides to flash a ROM/kernel with the sdcardfs issue to primary without injection or using normal TWRP. This would break any secondaries currently existing in Internal Storage. * However, setting/keeping the container immutable will interfere with 'Wipe Internal Storage' in MultiROM-TWRP, as well as regular TWRP, though maybe that is a good thing. TODO: set -i during 'Wipe Internal Storage' and/or add a new 'Wipe MultiROM' option in MultiROM-TWRP. Other options that were considered and tested successfully: (1) Use /data/multirom Move multirom to /data/multirom (don't forget to adjust TWRP to exclude /data/multirom from wipe and backups, as well as take into account that some installers will actually wipe data excluding media as part of their installation). This was my initial attempt, but was reconsidered due to the current change being effective, while minimizing code changes and maintaining the current directory in Internal Storage. At some point it may need to be reconsidered if this would make the most sense. Perhaps once we see devices with FBE this may become the most logical step. (2) Use .img files Similar to System Partition Mode, use .img files and loop mount them during boot. Since the secondary ROMs directories become actual files in /data/media/[0/]multirom/roms... these are unaffected by any change to /data/media/... The problem is that the data partition will become constrained and/or susceptible to 'overflow' crashes both while booted and in TWRP, since the actual free space is not properly reflected since it will show the free space within the .img file as opposed to the device's free space. (3) Use one of the already excluded 'names' 'autorun.inf', '.android_secure' and 'android_secure' are excluded by default from uid/gid derivation, and are hardcoded here https://goo.gl/dRQpYn so renaming /data/media/0/multirom to /data/media/0/autorun.inf (for example) will not let sdcardfs perform a chown on it and it's subdirectories. Not very intuitive though to have something called 'autorun.inf' in the root directory of Internal Storage which in fact is multirom. (Even if there's a multirom symlink to it, and the symlink will be affected by the uid/gid derivation) --- .../scripts/extract_multirom.sh | 49 +++++++++++++++---- .../scripts/erase_multirom.sh | 6 ++- multirom.c | 26 ++++++---- rq_inject_file_contexts.c | 4 ++ trampoline/trampoline.c | 32 +++++++++++- 5 files changed, 96 insertions(+), 21 deletions(-) diff --git a/install_zip/prebuilt-installer/scripts/extract_multirom.sh b/install_zip/prebuilt-installer/scripts/extract_multirom.sh index 6cd08071..dee6faac 100644 --- a/install_zip/prebuilt-installer/scripts/extract_multirom.sh +++ b/install_zip/prebuilt-installer/scripts/extract_multirom.sh @@ -1,16 +1,36 @@ #!/sbin/sh +cont="" base="" -if [ -d "/data/media/multirom" ] ; then - base="/data/media/multirom" -elif [ -d "/data/media/0/multirom" ] ; then - base="/data/media/0/multirom" + +# Move old installation of multirom to MultiROM/multirom +if [ -d "/data/media/multirom" ] && [ ! -d "/data/media/MultiROM/multirom" ]; then + mkdir "/data/media/MultiROM" + mv "/data/media/multirom" "/data/media/MultiROM/multirom" +elif [ -d "/data/media/0/multirom" ] && [ ! -d "/data/media/0/MultiROM/multirom" ]; then + mkdir "/data/media/0/MultiROM" + mv "/data/media/0/multirom" "/data/media/0/MultiROM/multirom" +fi + +# Check for existing dirs otherwise create them +if [ -d "/data/media/MultiROM/multirom" ] ; then + cont="/data/media/MultiROM" + base="/data/media/MultiROM/multirom" +elif [ -d "/data/media/0/MultiROM/multirom" ] ; then + cont="/data/media/0/MultiROM" + base="/data/media/0/MultiROM/multirom" else if [ -d "/data/media/0" ] ; then - base="/data/media/0/multirom" + cont="/data/media/0/MultiROM" + base="/data/media/0/MultiROM/multirom" else - base="/data/media/multirom" + cont="/data/media/MultiROM" + base="/data/media/MultiROM/multirom" fi + mkdir "$cont" + chown root:root "$cont" + chmod 770 "$cont" + mkdir "$base" chown root:root "$base" chmod 770 "$base" @@ -18,11 +38,9 @@ else mkdir "$base/roms" chown media_rw:media_rw "$base/roms" chmod 777 "$base/roms" - - touch "$base/.nomedia" - chown media_rw:media_rw "$base/.nomedia" fi +# Main installation rm "$base/boot.img-ubuntu"* rm "$base/infos/"* rm "$base/res/"* @@ -41,7 +59,20 @@ chmod 644 "$base/ubuntu-touch-init/scripts/touch" chmod 755 "$base/ubuntu-touch-sysimage-init/init" chmod 644 "$base/ubuntu-touch-sysimage-init/scripts/touch" +# Remove immutable flag so we can chmod and chown +chattr -i "$cont" + # This makes does not allows access for media scanner on android, but # still is enough for ubuntu +chmod 770 "$cont" +chown root:root "$cont" +touch "$cont/.nomedia" +chown media_rw:media_rw "$cont/.nomedia" + chmod 770 "$base" chown root:root "$base" +touch "$base/.nomedia" +chown media_rw:media_rw "$base/.nomedia" + +# Make the parent/container folder immutable to prevent sdcardfs uid/gid derivation +chattr +i "$cont" diff --git a/install_zip/prebuilt-uninstaller/scripts/erase_multirom.sh b/install_zip/prebuilt-uninstaller/scripts/erase_multirom.sh index 7ef0aad5..8348f673 100644 --- a/install_zip/prebuilt-uninstaller/scripts/erase_multirom.sh +++ b/install_zip/prebuilt-uninstaller/scripts/erase_multirom.sh @@ -1,6 +1,10 @@ #!/sbin/sh base="" -if [ -d "/data/media/multirom" ] ; then +if [ -d "/data/media/MultiROM" ] ; then + base="/data/media/MultiROM" +elif [ -d "/data/media/0/MultiROM" ] ; then + base="/data/media/0/MultiROM" +elif [ -d "/data/media/multirom" ] ; then base="/data/media/multirom" elif [ -d "/data/media/0/multirom" ] ; then base="/data/media/0/multirom" diff --git a/multirom.c b/multirom.c index 27a64de6..00c4075d 100644 --- a/multirom.c +++ b/multirom.c @@ -88,6 +88,10 @@ int multirom_find_base_dir(void) struct stat info; static const char *paths[] = { + REALDATA"/media/0/MultiROM/multirom", + REALDATA"/media/MultiROM/multirom", + "/data/media/0/MultiROM/multirom", + "/data/media/MultiROM/multirom", REALDATA"/media/0/multirom", // 4.2 REALDATA"/media/multirom", "/data/media/0/multirom", @@ -3070,12 +3074,9 @@ int multirom_run_scripts(const char *type, struct multirom_rom *rom) #define IC_TYPE_PREDEF 0 #define IC_TYPE_USER 1 -#define USER_IC_PATH "../Android/data/com.tassadar.multirommgr/files" -#define USER_IC_PATH_LEN 46 +#define USER_IC_PATH "../Android/data/com.tassadar.multirommgr/files" // TODO: just use /realdata/media/[0] #define DEFAULT_ICON "/icons/romic_default.png" -#define DEFAULT_ICON_LEN 24 #define DEFAULT_ANDROID_ICON "/icons/romic_android_default.png" -#define DEFAULT_ANDROID_ICON_LEN 32 void multirom_find_rom_icon(struct multirom_rom *rom) { @@ -3125,9 +3126,16 @@ void multirom_find_rom_icon(struct multirom_rom *rom) } case IC_TYPE_USER: { - len = strlen(mrom_dir()) + 1 + USER_IC_PATH_LEN + 1 + len + 4 + 1; // + / + / + .png + \0 - rom->icon_path = malloc(len); - snprintf(rom->icon_path, len, "%s/%s/%s.png", mrom_dir(), USER_IC_PATH, buff); + if (strstr(mrom_dir(), "MultiROM")) { + len = strlen(mrom_dir()) + 1 + 3 + sizeof(USER_IC_PATH) + 1 + len + 4; // + / + / + .png + \0 (sizeof() includes trailing null) + rom->icon_path = malloc(len); + snprintf(rom->icon_path, len, "%s/../%s/%s.png", mrom_dir(), USER_IC_PATH, buff); + } + else { + len = strlen(mrom_dir()) + 1 + sizeof(USER_IC_PATH) + 1 + len + 4; // + / + / + .png + \0 (sizeof() includes trailing null) + rom->icon_path = malloc(len); + snprintf(rom->icon_path, len, "%s/%s/%s.png", mrom_dir(), USER_IC_PATH, buff); + } break; } } @@ -3141,12 +3149,12 @@ void multirom_find_rom_icon(struct multirom_rom *rom) fclose(f); if (rom->type & MASK_ANDROID) { - len = strlen(mrom_dir()) + DEFAULT_ANDROID_ICON_LEN + 1; + len = strlen(mrom_dir()) + sizeof(DEFAULT_ANDROID_ICON); // sizeof() includes trailing null rom->icon_path = realloc(rom->icon_path, len); snprintf(rom->icon_path, len, "%s%s", mrom_dir(), DEFAULT_ANDROID_ICON); } else { - len = strlen(mrom_dir()) + DEFAULT_ICON_LEN + 1; + len = strlen(mrom_dir()) + sizeof(DEFAULT_ICON); // sizeof() includes trailing null rom->icon_path = realloc(rom->icon_path, len); snprintf(rom->icon_path, len, "%s%s", mrom_dir(), DEFAULT_ICON); } diff --git a/rq_inject_file_contexts.c b/rq_inject_file_contexts.c index e4d9099b..7a465981 100644 --- a/rq_inject_file_contexts.c +++ b/rq_inject_file_contexts.c @@ -50,6 +50,10 @@ const char *multirom_exclusion_path[] = { "/data/media/0/multirom", "/realdata/media/multirom", "/realdata/media/0/multirom", + "/data/media/MultiROM", + "/data/media/0/MultiROM", + "/realdata/media/MultiROM", + "/realdata/media/0/MultiROM", "/mnt/mrom", }; diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index 90507535..f93fb5e3 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -24,6 +24,9 @@ #include #include #include +#include +#include +#include #include #include "devices.h" @@ -57,17 +60,42 @@ static int find_multirom(void) struct stat info; static const char *paths[] = { + REALDATA"/media/0/MultiROM/multirom", + REALDATA"/media/MultiROM/multirom", REALDATA"/media/0/multirom", // 4.2 REALDATA"/media/multirom", NULL, }; - for(i = 0; paths[i]; ++i) - { + for(i = 0; paths[i]; ++i) { if(stat(paths[i], &info) < 0) continue; strcpy(path_multirom, paths[i]); + + if (i < 2) { + // Make sure to set the container dir to immutable + char main_path[64]; + strncpy(main_path, path_multirom, strlen(path_multirom) - (sizeof("/multirom") - 1)); + main_path[strlen(path_multirom) - (sizeof("/multirom") - 1)] = '\0'; + + int fd = open(main_path, O_RDONLY | O_NONBLOCK); + if (fd >= 0) { + long flags; + if (ioctl(fd, FS_IOC_GETFLAGS, &flags) >= 0) { + flags |= FS_IMMUTABLE_FL; + if (ioctl(fd, FS_IOC_SETFLAGS, &flags) < 0) + ERROR("Failed FS_IOC_SETFLAGS: %s!\n", strerror(errno)); + else + INFO("Set FS_IMMUTABLE_FL on %s.\n", main_path); + } + else + ERROR("Failed FS_IOC_GETFLAGS: %s!\n", strerror(errno)); + close(fd); + } + else + ERROR("Failed to open %s: %s!\n", main_path, strerror(errno)); + } return 0; } return -1; From c2101778fb0bfa48870f1d3b3ef5aa1cbe95baaa Mon Sep 17 00:00:00 2001 From: nkk71 Date: Sat, 28 Oct 2017 15:53:52 +0300 Subject: [PATCH 14/65] trampoline: Rearrange the code a bit * Doesn't affect the code execution, it's only needed to make future changes (the addition of trampoline511) easier. --- trampoline/trampoline.c | 120 +++++++++++++++++++++++----------------- trampoline/trampoline.h | 34 ++++++++++++ 2 files changed, 102 insertions(+), 52 deletions(-) create mode 100644 trampoline/trampoline.h diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index f93fb5e3..5285cb8f 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -43,14 +43,7 @@ #include "Populate_ByName_using_emmc.c" #endif -#define EXEC_MASK (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) -#define REALDATA "/realdata" -#define MULTIROM_BIN "multirom" -#define BUSYBOX_BIN "busybox" -#define KEEP_REALDATA "/dev/.keep_realdata" - -// Not defined in android includes? -#define MS_RELATIME (1<<21) +#include "trampoline.h" static char path_multirom[64] = { 0 }; @@ -302,11 +295,9 @@ static void fixup_symlinks(void) } } -int main(int argc, char *argv[]) +static int do_cmdline(int argc, char *argv[]) { - int i, res; - static char *const cmd[] = { "/init", NULL }; - struct fstab *fstab = NULL; + int i; char *inject_path = NULL; char *mrom_dir = NULL; int force_inject = 0; @@ -341,6 +332,69 @@ int main(int argc, char *argv[]) return inject_bootimg(inject_path, force_inject); } + printf("Usage: trampoline -v\n"); + printf(" trampoline --inject= --mrom_dir= [-f]\n"); + return 1; +} + +static int run_core(void) +{ + int res = -1; + struct fstab *fstab = NULL; + + if(wait_for_file("/dev/graphics/fb0", 5) < 0) + { + ERROR("Waiting too long for fb0"); + goto exit; + } + +#ifdef MR_POPULATE_BY_NAME_PATH + Populate_ByName_using_emmc(); +#endif + + fstab = fstab_auto_load(); + if(!fstab) + goto exit; + +#if 0 + fstab_dump(fstab); //debug +#endif + + // mount and run multirom from sdcard + res = mount_and_run(fstab); + if(res < 0 && mrom_is_second_boot()) + { + ERROR("This is second boot and we couldn't mount /data, reboot!\n"); + sync(); + //android_reboot(ANDROID_RB_RESTART, 0, 0); + android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); // favour reboot to recovery, to avoid possible bootlooping + while(1) + sleep(1); + } + + if(access(KEEP_REALDATA, F_OK) < 0) { + umount(REALDATA); + rmdir(REALDATA); + encryption_destroy(); + } + + encryption_cleanup(); + +exit: + if(fstab) + fstab_destroy(fstab); + + return res; +} + +int main(int argc, char *argv[]) +{ + if (argc > 1) + return do_cmdline(argc, argv); + + int res; + static char *const cmd[] = { "/init", NULL }; + umask(000); // Init only the little we need, leave the rest for real init @@ -384,39 +438,7 @@ int main(int argc, char *argv[]) devices_init(); INFO("Done initializing\n"); - if(wait_for_file("/dev/graphics/fb0", 5) < 0) - { - ERROR("Waiting too long for fb0"); - goto exit; - } - -#ifdef MR_POPULATE_BY_NAME_PATH - //nkk71 M7 hack - Populate_ByName_using_emmc(); -#endif - - fstab = fstab_auto_load(); - if(!fstab) - goto exit; - -#if 0 - fstab_dump(fstab); //debug -#endif - - // mount and run multirom from sdcard - if(mount_and_run(fstab) < 0 && mrom_is_second_boot()) - { - ERROR("This is second boot and we couldn't mount /data, reboot!\n"); - sync(); - //android_reboot(ANDROID_RB_RESTART, 0, 0); - android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); // favour reboot to recovery, to avoid possible bootlooping - while(1) - sleep(1); - } - -exit: - if(fstab) - fstab_destroy(fstab); + run_core(); // close and destroy everything devices_close(); @@ -426,16 +448,10 @@ int main(int argc, char *argv[]) rmdir("/dev/pts"); rmdir("/dev/socket"); - if(access(KEEP_REALDATA, F_OK) < 0) - { - umount(REALDATA); + if(access(KEEP_REALDATA, F_OK) < 0) { umount("/dev"); - rmdir(REALDATA); - encryption_destroy(); } - encryption_cleanup(); - #if MR_USE_DEBUGFS_MOUNT umount("/sys/kernel/debug"); #endif diff --git a/trampoline/trampoline.h b/trampoline/trampoline.h new file mode 100644 index 00000000..ed007e2d --- /dev/null +++ b/trampoline/trampoline.h @@ -0,0 +1,34 @@ +/* + * This file is part of MultiROM. + * + * MultiROM is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * MultiROM is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with MultiROM. If not, see . + */ + +#ifndef _TRAMPOLINE_H +#define _TRAMPOLINE_H + +#include + +#define EXEC_MASK (S_IRWXU | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) +#define REALDATA "/realdata" +#define MULTIROM_BIN "multirom" +#define BUSYBOX_BIN "busybox" +#define KEEP_REALDATA "/dev/.keep_realdata" + +// Not defined in android includes? +#ifndef MS_RELATIME +#define MS_RELATIME (1<<21) +#endif + +#endif // _TRAMPOLINE_H From 64a4ac664ac3563d9c13fe23797f807d0e8cdc04 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Sun, 12 Nov 2017 14:04:03 +0200 Subject: [PATCH 15/65] multirom: trampoline: Preserve /firmware in encryption.c * If /firmware exists in the bootimage, keep its content by renaming it during the encrypted work and restoring it after the decrypt process. * This is evident on the HTC U11, where if the /firmware directory is not present during boot (due to it's deletion in encryption.c) all the firmware files are not mounted at all since the /firmware directory is not created in the .rc files. --- trampoline/encryption.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/trampoline/encryption.c b/trampoline/encryption.c index 344f13fd..dc634fcc 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -62,6 +62,9 @@ int encryption_before_mount(struct fstab *fstab) } symlink("/mrom_enc/vendor", "/vendor"); + if (access("/firmware", F_OK) >= 0) { + rename("/firmware", "/firmware_boot"); + } mkdir("/firmware", 0775); struct fstab_part *fwpart = fstab_find_first_by_path(fstab, "/firmware"); if(fwpart && (strcmp(fwpart->type, "emmc") != 0 || strcmp(fwpart->type, "vfat") != 0)) @@ -158,5 +161,8 @@ int encryption_cleanup(void) ERROR("encryption_cleanup: failed to unmount /firmware: %s\n", strerror(errno)); rmdir("/firmware"); + if (access("/firmware_boot", F_OK) >= 0) { + rename("/firmware_boot", "/firmware"); + } return 0; } From 2894780a9566bb20694012b8bc195f7f8be23121 Mon Sep 17 00:00:00 2001 From: nkk71 Date: Tue, 14 Nov 2017 17:41:12 +0200 Subject: [PATCH 16/65] Update multirom path to account for the new dir * Fixes 'Advanced Kernel Logging'. * Set permissions and ownership on the directory and files to make them world visible. * Change multirom_log and icon files to also use datamedia_dir. --- multirom.c | 130 ++++++++++++++++++++++++++--------------------------- 1 file changed, 65 insertions(+), 65 deletions(-) diff --git a/multirom.c b/multirom.c index 00c4075d..bbdf848e 100644 --- a/multirom.c +++ b/multirom.c @@ -76,6 +76,7 @@ static char kexec_path[64] = { 0 }; static char ntfs_path[64] = { 0 }; static char exfat_path[64] = { 0 }; static char partition_dir[64] = { 0 }; +static char datamedia_dir[64] = { 0 }; static volatile int run_usb_refresh = 0; static pthread_t usb_refresh_thread; @@ -84,39 +85,45 @@ static void (*usb_refresh_handler)(void) = NULL; int multirom_find_base_dir(void) { - int i; + int i, j; + char path[64]; struct stat info; - static const char *paths[] = { - REALDATA"/media/0/MultiROM/multirom", - REALDATA"/media/MultiROM/multirom", - "/data/media/0/MultiROM/multirom", - "/data/media/MultiROM/multirom", - REALDATA"/media/0/multirom", // 4.2 - REALDATA"/media/multirom", - "/data/media/0/multirom", - "/data/media/multirom", + static const char *base_dirs[] = { + REALDATA"/media/0", + REALDATA"/media", + "/data/media/0", + "/data/media", + NULL, + }; + static const char *mrom_dirs[] = { + "MultiROM/multirom", + "multirom", NULL, }; - for(i = 0; paths[i]; ++i) - { - if(stat(paths[i], &info) < 0) - continue; + for(i = 0; base_dirs[i]; ++i) { + for (j = 0; mrom_dirs[j]; ++j) { + sprintf(path, "%s/%s", base_dirs[i], mrom_dirs[j]); + if(stat(path, &info) < 0) + continue; - mrom_set_dir(paths[i]); + mrom_set_dir(path); - strncpy(partition_dir, paths[i], strchr(paths[i]+1, '/') - paths[i]); + strcpy(datamedia_dir, path); - sprintf(busybox_path, "%s/%s", paths[i], BUSYBOX_BIN); - sprintf(kexec_path, "%s/%s", paths[i], KEXEC_BIN); - sprintf(ntfs_path, "%s/%s", paths[i], NTFS_BIN); - sprintf(exfat_path, "%s/%s", paths[i], EXFAT_BIN); + strncpy(partition_dir, path, strchr(path, '/') - path); - chmod(kexec_path, 0755); - chmod(ntfs_path, 0755); - chmod(exfat_path, 0755); - return 0; + sprintf(busybox_path, "%s/%s", path, BUSYBOX_BIN); + sprintf(kexec_path, "%s/%s", path, KEXEC_BIN); + sprintf(ntfs_path, "%s/%s", path, NTFS_BIN); + sprintf(exfat_path, "%s/%s", path, EXFAT_BIN); + + chmod(kexec_path, 0755); + chmod(ntfs_path, 0755); + chmod(exfat_path, 0755); + return 0; + } } return -1; } @@ -131,6 +138,15 @@ enum BACKUP_LAST_KEXEC = 3 }; +static void set_mediarw_perms(const char *path) +{ + chmod(path, 0666); + + unsigned int media_rw_id = decode_uid("media_rw"); + if(media_rw_id != -1U) + chown(path, (uid_t)media_rw_id, (gid_t)media_rw_id); +} + void multirom_kmsg_rename_logs(const char *path_logs_dir, const char *base_name, const int max_count) { DIR *dp = opendir(path_logs_dir); @@ -188,7 +204,7 @@ void multirom_kmsg_logging(int kmsg_backup_type) }; // make the logs folder visible outside multirom folder - static const char log_dir_name[] = "../multirom-klogs"; + static const char log_dir_name[] = "multirom-klogs"; static const char ext[] = "txt"; // current date time @@ -214,36 +230,29 @@ void multirom_kmsg_logging(int kmsg_backup_type) else return; + sprintf(path_logs_dir, "%s/%s", datamedia_dir, log_dir_name); - // set path and create if needed - sprintf(path_logs_dir, "%s/%s", mrom_dir(), log_dir_name); - mkdir(path_logs_dir, 0777); + if (access(path_logs_dir, F_OK) < 0) + mkdir(path_logs_dir, 0666); + set_mediarw_perms(path_logs_dir); - if (kmsg_backup_type == BACKUP_LAST_KMSG) - { + if (kmsg_backup_type == BACKUP_LAST_KMSG) { int i; - multirom_kmsg_rename_logs(path_logs_dir, base_name, MAX_LASTKMSG_LOGS); - - // now copy the last kernel msg sprintf(path_log_file, "%s/%s_%i_%s.%s", path_logs_dir, base_name, 0, datetime, ext); - for(i = 0; kmsg_paths[i]; ++i) - { - if (access(kmsg_paths[i], R_OK) == 0) - { + for(i = 0; kmsg_paths[i]; ++i) { + if (access(kmsg_paths[i], R_OK) == 0) { INFO("Backing up last kmsg '%s' to '%s' res=%d\n", kmsg_paths[i], path_log_file, copy_file(kmsg_paths[i], path_log_file)); break; } } } - else - { + else { multirom_kmsg_rename_logs(path_logs_dir, base_name, (kmsg_backup_type == BACKUP_LATE_KLOG) ? MAX_MROMKMSG_LOGS : 0); - - // now copy current klog sprintf(path_log_file, "%s/%s_%i_%s.%s", log_dir_name, base_name, 0, datetime, ext); INFO("Backing up current klog to '%s' res=%d\n", path_log_file, multirom_copy_log(NULL, path_log_file)); } + set_mediarw_perms(path_log_file); } int multirom(const char *rom_to_boot) @@ -500,7 +509,7 @@ void multirom_emergency_reboot(void) char *tail; char *last_end; int cur_y; - unsigned int media_rw_id; + char path_log_file[64]; if(multirom_init_fb(0) < 0) { @@ -549,13 +558,11 @@ void multirom_emergency_reboot(void) fb_force_draw(); - multirom_copy_log(klog, "../multirom_log.txt"); + sprintf(path_log_file, "%s/multirom_log.txt", datamedia_dir); + multirom_copy_log(klog, path_log_file); free(klog); - media_rw_id = decode_uid("media_rw"); - if(media_rw_id != -1U) - chown("../multirom_log.txt", (uid_t)media_rw_id, (gid_t)media_rw_id); - chmod("../multirom_log.txt", 0666); + set_mediarw_perms(path_log_file); // Wait for power key start_input_thread(); @@ -3074,9 +3081,9 @@ int multirom_run_scripts(const char *type, struct multirom_rom *rom) #define IC_TYPE_PREDEF 0 #define IC_TYPE_USER 1 -#define USER_IC_PATH "../Android/data/com.tassadar.multirommgr/files" // TODO: just use /realdata/media/[0] -#define DEFAULT_ICON "/icons/romic_default.png" -#define DEFAULT_ANDROID_ICON "/icons/romic_android_default.png" +#define USER_IC_PATH "Android/data/com.tassadar.multirommgr/files" +#define DEFAULT_ICON "icons/romic_default.png" +#define DEFAULT_ANDROID_ICON "icons/romic_android_default.png" void multirom_find_rom_icon(struct multirom_rom *rom) { @@ -3119,23 +3126,16 @@ void multirom_find_rom_icon(struct multirom_rom *rom) if(!ic_name) goto fail; - len = strlen(mrom_dir()) + 6 + strlen(ic_name)+4+1; // + /icons + .png + \0 + len = strlen(mrom_dir()) + 6 + strlen(ic_name) + 4 + 1; // + /icons + .png + \0 rom->icon_path = malloc(len); snprintf(rom->icon_path, len, "%s/icons%s.png", mrom_dir(), ic_name); break; } case IC_TYPE_USER: { - if (strstr(mrom_dir(), "MultiROM")) { - len = strlen(mrom_dir()) + 1 + 3 + sizeof(USER_IC_PATH) + 1 + len + 4; // + / + / + .png + \0 (sizeof() includes trailing null) - rom->icon_path = malloc(len); - snprintf(rom->icon_path, len, "%s/../%s/%s.png", mrom_dir(), USER_IC_PATH, buff); - } - else { - len = strlen(mrom_dir()) + 1 + sizeof(USER_IC_PATH) + 1 + len + 4; // + / + / + .png + \0 (sizeof() includes trailing null) - rom->icon_path = malloc(len); - snprintf(rom->icon_path, len, "%s/%s/%s.png", mrom_dir(), USER_IC_PATH, buff); - } + len = strlen(datamedia_dir) + 1 + sizeof(USER_IC_PATH) + 1 + len + 4; // + / + / + .png + \0 (sizeof() includes trailing null) + rom->icon_path = malloc(len); + snprintf(rom->icon_path, len, "%s/%s/%s.png", datamedia_dir, USER_IC_PATH, buff); break; } } @@ -3149,13 +3149,13 @@ void multirom_find_rom_icon(struct multirom_rom *rom) fclose(f); if (rom->type & MASK_ANDROID) { - len = strlen(mrom_dir()) + sizeof(DEFAULT_ANDROID_ICON); // sizeof() includes trailing null + len = strlen(mrom_dir()) + 1 + sizeof(DEFAULT_ANDROID_ICON); // sizeof() includes trailing null rom->icon_path = realloc(rom->icon_path, len); - snprintf(rom->icon_path, len, "%s%s", mrom_dir(), DEFAULT_ANDROID_ICON); + snprintf(rom->icon_path, len, "%s/%s", mrom_dir(), DEFAULT_ANDROID_ICON); } else { - len = strlen(mrom_dir()) + sizeof(DEFAULT_ICON); // sizeof() includes trailing null + len = strlen(mrom_dir()) + 1 + sizeof(DEFAULT_ICON); // sizeof() includes trailing null rom->icon_path = realloc(rom->icon_path, len); - snprintf(rom->icon_path, len, "%s%s", mrom_dir(), DEFAULT_ICON); + snprintf(rom->icon_path, len, "%s/%s", mrom_dir(), DEFAULT_ICON); } } From 0507c11557e4ffafd1f6f9405ec3a1fc81b490f6 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Tue, 13 Mar 2018 20:54:17 +0530 Subject: [PATCH 17/65] Use lstat instead of access to check file existence Some devices have a permanent /vendor symlink to /system/vendor in ramdisk. As during multirom bootup neither system nor vendor partition is mounted, so /vendor points to a non-existent target. Running access() on this symlink results in error with NOENT (no such file or directory) as it tries to dereference the target of symlink. Thus, the symlinking of /mrom_enc/vendor to /vendor also fails since the link with same name already exists. Fix this by using lstat() which reports the existence of symlink (broken or working) and real file properly. --- trampoline/encryption.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/trampoline/encryption.c b/trampoline/encryption.c index dc634fcc..71a3d46e 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -46,6 +46,7 @@ int encryption_before_mount(struct fstab *fstab) int exit_code = -1; char *output = NULL, *itr; int res = ENC_RES_ERR; + struct stat stat; #ifdef __LP64__ chmod("/mrom_enc/linker64", 0775); @@ -57,7 +58,7 @@ int encryption_before_mount(struct fstab *fstab) symlink("/mrom_enc/res/Roboto-Regular.ttf", "/mrom_enc/res/Roboto-Italic.ttf"); symlink("/mrom_enc/res/Roboto-Regular.ttf", "/mrom_enc/res/Roboto-Medium.ttf"); - if (access("/vendor", F_OK) >= 0) { + if (lstat("/vendor", &stat) == 0) { rename("/vendor", "/vendor_boot"); } symlink("/mrom_enc/vendor", "/vendor"); @@ -149,11 +150,12 @@ void encryption_destroy(void) int encryption_cleanup(void) { + struct stat stat; #if MR_DEVICE_HOOKS >= 6 tramp_hook_encryption_cleanup(); #endif remove("/vendor"); - if (access("/vendor_boot", F_OK) >= 0) { + if (lstat("/vendor_boot", &stat) == 0) { rename("/vendor_boot", "/vendor"); } From 55c2d868f9726915803ae7a6dd953415681a3a8d Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Tue, 13 Mar 2018 21:04:47 +0530 Subject: [PATCH 18/65] Allow users to manually add a firmware scan directory Some devices have certain drivers which probe and request for a firmware before multirom has symlinked /mrom_enc/vendor. Add a new flag to allow users to specify manual scan directories where users can put their own needed firmwares. --- trampoline/Android.mk | 4 ++++ trampoline/devices.c | 3 +++ 2 files changed, 7 insertions(+) diff --git a/trampoline/Android.mk b/trampoline/Android.mk index adf13578..b1c7fa1e 100644 --- a/trampoline/Android.mk +++ b/trampoline/Android.mk @@ -20,6 +20,10 @@ ifeq ($(MR_INIT_DEVICES),) endif LOCAL_SRC_FILES += ../../../../$(MR_INIT_DEVICES) +ifneq ($(MR_EXTRA_FIRMWARE_DIR),) + LOCAL_CFLAGS += -DMR_EXTRA_FIRMWARE_DIR="\"$(MR_EXTRA_FIRMWARE_DIR)\"" +endif + # for adb LOCAL_CFLAGS += -DPRODUCT_MODEL="\"$(PRODUCT_MODEL)\"" -DPRODUCT_MANUFACTURER="\"$(PRODUCT_MANUFACTURER)\"" diff --git a/trampoline/devices.c b/trampoline/devices.c index 066ec79c..114c5857 100644 --- a/trampoline/devices.c +++ b/trampoline/devices.c @@ -66,6 +66,9 @@ static const char *firmware_dirs[] = { "/etc/firmware", "/vendor/firmware", +#ifdef MR_EXTRA_FIRMWARE_DIR + MR_EXTRA_FIRMWARE_DIR, +#endif "/firmware/image" }; #ifdef HAVE_SELINUX From e7cf49ff75a031f9e6fe9f27721c4eeca4552503 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Tue, 27 Mar 2018 20:55:53 +0530 Subject: [PATCH 19/65] Add support for treble and GSI (Generic System Image) oreo roms Mount system and/or vendor partition from dtb. Scan for fstab in vendor as well. Modify the fstab using bind mounts. Mark the dtb partitions as disabled in procfs to prevent fs_mgr from mounting it. Also inject file_contexts in system partition using bind mounting. Tested working AOSP GSI rom on Redmi Note 5 pro running oreo as primary rom. Retains compatibility with pre-oreo roms. --- multirom.c | 127 +++++++++++++++++++++++++++++++++++++--- multirom.h | 2 +- rom_quirks.c | 28 ++++++++- trampoline/encryption.c | 2 +- 4 files changed, 147 insertions(+), 12 deletions(-) diff --git a/multirom.c b/multirom.c index bbdf848e..407c26f6 100644 --- a/multirom.c +++ b/multirom.c @@ -70,6 +70,7 @@ #define LAYOUT_VERSION "/data/.layout_version" #define BATTERY_CAP "/sys/class/power_supply/battery/capacity" +#define DT_FSTAB_PATH "/proc/device-tree/firmware/android/fstab/" static char busybox_path[64] = { 0 }; static char kexec_path[64] = { 0 }; @@ -83,6 +84,56 @@ static pthread_t usb_refresh_thread; static pthread_mutex_t parts_mutex = PTHREAD_MUTEX_INITIALIZER; static void (*usb_refresh_handler)(void) = NULL; +char* read_file(char* file) { + char* buf = calloc(1, 256); + FILE* fp = fopen(file, "r"); + if (fp) { + fread(buf, 1, 256, fp); + fclose(fp); + } else { + ERROR("cannot open %s %s\n", file, strerror(errno)); + } + return buf; +} + +void disable_dtb_fstab(char* partition) { + if (access("status", F_OK)) { + FILE* fp = fopen("status", "w"); + fprintf(fp, "disabled"); + fclose(fp); + } + char mnt_pt[strlen(DT_FSTAB_PATH) + strlen(partition) + 1]; + sprintf(mnt_pt, "%s%s/status", DT_FSTAB_PATH, partition); + if (!mount("/status", mnt_pt, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + INFO("status node bind mounted in procfs\n"); + } else { + ERROR("status node bind mount failed! %s\n", strerror(errno)); + } +} + +int mount_dtb_fstab(char* partition) { + int rc = -1; + + char root_path [strlen(DT_FSTAB_PATH) + 20] = {'\0'}; + char device[sizeof(root_path) + strlen("dev")] = {'\0'}; + char type[sizeof(root_path) + strlen("type")] = {'\0'}; + char mnt_flags[sizeof(root_path) + strlen("mnt_flags")] = {'\0'}; + + sprintf(root_path, "%s%s", DT_FSTAB_PATH, partition); + sprintf(device, "%s%s", root_path, "/dev"); + sprintf(type, "%s%s", root_path, "/type"); + sprintf(mnt_flags, "%s%s", root_path, "/mnt_flags"); + + if (!(rc = mount(read_file(device), partition, read_file(type), MS_RDONLY, "barrier=1,discard"))) { + INFO("dtb %s mount successful\n", partition); + disable_dtb_fstab(partition); + } else { + INFO("dtb %s mount failed %s\n", partition, strerror(errno)); + } + + return rc; +} + int multirom_find_base_dir(void) { int i, j; @@ -1403,6 +1454,9 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to { case ROM_DEFAULT: { + if (!access(DT_FSTAB_PATH, F_OK)) { + mount_dtb_fstab("system"); + } rom_quirks_on_initrd_finalized(); break; } @@ -1531,7 +1585,9 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom char out[128]; char path[256]; char *fstab_name = NULL; + struct stat stat; int has_fw = 0; + int found_fstab = 0; struct fstab_part *fw_part = NULL; int res = -1; @@ -1570,19 +1626,31 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom } closedir(d); - if(multirom_process_android_fstab(fstab_name, has_fw, &fw_part) != 0) - goto exit; + if(multirom_process_android_fstab(fstab_name, has_fw, &fw_part, 0) != 0) { + INFO("fstab couldnt be found in ramdisk. Rom maybe treble. Retry after vendor mount\n"); + } else { + found_fstab = 1; + } unlink("/cache"); mkdir_with_perms("/system", 0755, NULL, NULL); mkdir_with_perms("/data", 0771, "system", "system"); mkdir_with_perms("/cache", 0770, "system", "cache"); + mkdir_with_perms("/vendor", 0755, NULL, NULL); if(has_fw) mkdir_with_perms("/firmware", 0771, "system", "system"); - static const char *folders[3] = { "system" , "data" , "cache" }; - unsigned long flags[3] = { MS_RDONLY , MS_NOSUID | MS_NODEV , MS_NOSUID | MS_NODEV }; + /* In case device is encrypted, vendor is renamed to vendor_boot + * Now that decryption is done and partition is mounted, we dont need multirom's vendor folder. + * So we can safely remove it */ + + if (lstat("/vendor_boot", &stat) == 0) { + remove("/vendor"); + rename("/vendor_boot", "/vendor"); + } + static const char *folders[4] = { "system" , "data" , "cache" , "vendor"}; + unsigned long flags[4] = { MS_RDONLY , MS_NOSUID | MS_NODEV , MS_NOSUID | MS_NODEV, MS_RDONLY }; uint32_t i; char from[256]; @@ -1590,7 +1658,6 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom for (i = 0; i < ARRAY_SIZE(folders); ++i) { snprintf(to, sizeof(to), "/%s", folders[i]); - snprintf(from, sizeof(from), "%s/%s", rom->base_path, folders[i]); if (!access(from, R_OK)) { if(mount(from, to, "ext4", MS_BIND | flags[i], "discard,nomblk_io_submit") < 0) { @@ -1599,6 +1666,9 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom } else INFO("Bind mounted %s on %s\n", from, to); continue; + } else if (strstr(from, "vendor")) { + INFO("vendor not found, skipping\n"); + continue; } snprintf(from, sizeof(from), "%s/%s.img", rom->base_path, folders[i]); @@ -1623,6 +1693,19 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom goto exit; } + if((multirom_path_exists("/", "system/vendor/etc")) != 0 && + (multirom_path_exists(rom->base_path, "vendor")) != 0) { + if (!access(DT_FSTAB_PATH, F_OK)) { + mount_dtb_fstab("vendor"); + } + } + if (!access(DT_FSTAB_PATH, F_OK)) { + disable_dtb_fstab("system"); + } + if(!found_fstab && multirom_process_android_fstab(NULL, has_fw, &fw_part, 1) != 0) { + INFO("fstab not found even in vendor!\n"); + goto exit; + } // mount() does not necessarily obey the mount options (eg, ro on system or nosuid on data) // so attempt a remount on the partitions, but don't abort if the remount in unsuccessful, @@ -1677,15 +1760,23 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom return res; } -int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_part **fw_part) +int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_part **fw_part, int treble_fstab) { int res = -1; + char* dirname; if(fstab_name != NULL) INFO("Using fstab %s from rc files\n", fstab_name); else { - DIR *d = opendir("/"); + DIR *d; + if (treble_fstab) { + dirname = "/vendor/etc/"; + d = opendir(dirname); + } else { + d = opendir("/"); + } + if(!d) { ERROR("Failed to open root folder!\n"); @@ -1713,6 +1804,12 @@ int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_pa } } + if (treble_fstab) { + char name[strlen(fstab_name) + 1]; + strcpy(name, fstab_name); + fstab_name = realloc(fstab_name, strlen(name) + strlen(dirname) + 1); + sprintf(fstab_name, "%s%s", dirname, name); + } ERROR("Modifying fstab: %s\n", fstab_name); struct fstab *tab = fstab_load(fstab_name, 0); if(!tab) @@ -1721,8 +1818,9 @@ int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_pa int disable_sys = fstab_disable_parts(tab, "/system"); int disable_data = fstab_disable_parts(tab, "/data"); int disable_cache = fstab_disable_parts(tab, "/cache"); + int disable_vendor = fstab_disable_parts(tab, "/vendor"); - if(disable_sys < 0 || disable_data < 0 || disable_cache < 0) + if((!treble_fstab) && disable_sys < 0 || disable_data < 0 || disable_cache < 0) { #if MR_DEVICE_HOOKS >= 4 if(!mrom_hook_allow_incomplete_fstab()) @@ -1770,9 +1868,20 @@ int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_pa mkdir("/dummy_tmpfs", 0644); } - if(fstab_save(tab, fstab_name) == 0) + char* fstab_save_path = strstr(fstab_name, "fstab"); + if(fstab_save(tab, fstab_save_path) == 0) res = 0; + if (treble_fstab) { + if(!mount(fstab_save_path, fstab_name, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + INFO("fstab bind mounted in vendor\n"); + } else { + ERROR("fstab bind mount failed on %s! %s\n", fstab_name, strerror(errno)); + res = -1; + goto exit; + } + } + exit: if(tab) fstab_destroy(tab); diff --git a/multirom.h b/multirom.h index 70cab0ac..310f6554 100644 --- a/multirom.h +++ b/multirom.h @@ -146,7 +146,7 @@ void multirom_free_rom(void *rom); int multirom_init_fb(int rotation); int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom *rom); int multirom_create_media_link(struct multirom_status *s); -int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_part **fw_part); +int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_part **fw_part, int treble_fstab); int multirom_get_api_level(const char *path); int multirom_get_rom_type(struct multirom_rom *rom); int multirom_get_trampoline_ver(void); diff --git a/rom_quirks.c b/rom_quirks.c index 447609dc..25df92bc 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -22,6 +22,10 @@ #include #include #include +#include +#include +#include +#include #include "rom_quirks.h" #include "rq_inject_file_contexts.h" @@ -105,7 +109,8 @@ static void disable_restorecon_recursive(void) while(fgets(line, sizeof(line), f_in)) { if (strstr(line, "restorecon_recursive ") || (strstr(line, "restorecon ") && strstr(line, "--recursive"))) { - if (strstr(line, "/data") || strstr(line, "/system") || strstr(line, "/cache") || strstr(line, "/mnt")) { + if (strstr(line, "/data") || strstr(line, "/system") || strstr(line, "/cache") || strstr(line, "/mnt") || + strstr(line, "/vendor")) { fputc('#', f_out); } } @@ -129,6 +134,19 @@ void rom_quirks_on_initrd_finalized(void) int failed_file_contexts_injections = 0; // walk over all _regular_ files in / + char* path = "/system/etc/selinux/plat_file_contexts"; + if (!access(path, F_OK)) { + char buf; + int sourcefile, destfile, n; + sourcefile = open(path, O_RDONLY); + destfile = open("/plat_file_contexts", O_WRONLY | O_CREAT, 0644); + while((n = read(sourcefile, &buf, 1))) + { + write(destfile, &buf, 1 ); + } + close(sourcefile); + close(destfile); + } DIR *d = opendir("/"); if(d) { @@ -179,6 +197,14 @@ void rom_quirks_on_initrd_finalized(void) closedir(d); } + if (!access(path, F_OK)) { + if(!mount("/plat_file_contexts", path, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + INFO("file_contexts bind mounted in system\n"); + } else { + ERROR("file_contexts bind mount failed! %s\n", strerror(errno)); + } + } + if (failed_file_contexts_injections) disable_restorecon_recursive(); } diff --git a/trampoline/encryption.c b/trampoline/encryption.c index 71a3d46e..d7388297 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -154,8 +154,8 @@ int encryption_cleanup(void) #if MR_DEVICE_HOOKS >= 6 tramp_hook_encryption_cleanup(); #endif - remove("/vendor"); if (lstat("/vendor_boot", &stat) == 0) { + remove("/vendor"); rename("/vendor_boot", "/vendor"); } From 4535404c7e60cc2ad136908677409eaff649d766 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 14 Mar 2018 15:27:19 +0530 Subject: [PATCH 20/65] Remove old adbd --- adbd | 1 - 1 file changed, 1 deletion(-) delete mode 160000 adbd diff --git a/adbd b/adbd deleted file mode 160000 index 9c842501..00000000 --- a/adbd +++ /dev/null @@ -1 +0,0 @@ -Subproject commit 9c842501f8255a7e531466d9b831295ee094ce88 From 482c76cab9ef3f514e806ba8e80e131692e4212e Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 14 Mar 2018 15:59:39 +0530 Subject: [PATCH 21/65] klog_init has been removed in android 8.x --- main.c | 2 -- trampoline/trampoline.c | 1 - trampoline_encmnt/encmnt.c | 2 -- 3 files changed, 5 deletions(-) diff --git a/main.c b/main.c index 6c38184a..9086c545 100644 --- a/main.c +++ b/main.c @@ -108,8 +108,6 @@ int main(int argc, const char *argv[]) } srand(time(0)); - klog_init(); - // output all messages to dmesg, // but it is possible to filter out INFO messages klog_set_level(6); diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index 5285cb8f..c9b3861a 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -416,7 +416,6 @@ int main(int argc, char *argv[]) mount("debugfs", "/sys/kernel/debug", "debugfs", 0, NULL); #endif - klog_init(); // output all messages to dmesg, // but it is possible to filter out INFO messages klog_set_level(6); diff --git a/trampoline_encmnt/encmnt.c b/trampoline_encmnt/encmnt.c index d841afea..70be9316 100644 --- a/trampoline_encmnt/encmnt.c +++ b/trampoline_encmnt/encmnt.c @@ -214,8 +214,6 @@ int main(int argc, char *argv[]) struct fstab_part *p; char *argument = NULL; - klog_init(); - // output all messages to dmesg, // but it is possible to filter out INFO messages klog_set_level(6); From 4e3bab96a6ad621bd906895f4c7a784154524443 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 14 Mar 2018 16:01:08 +0530 Subject: [PATCH 22/65] Fix compile error on android 8.x --- trampoline/devices.c | 1 + 1 file changed, 1 insertion(+) diff --git a/trampoline/devices.c b/trampoline/devices.c index 114c5857..79047cd4 100644 --- a/trampoline/devices.c +++ b/trampoline/devices.c @@ -20,6 +20,7 @@ #include #include #include +#include #include #include From a41d886dd747b6fa685ef70c089f173af23d56a2 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 14 Mar 2018 16:01:37 +0530 Subject: [PATCH 23/65] Switch to getpwuname from pwd.h As recommended by google --- lib/util.c | 39 +++++++++++++++++++++++++++++---------- 1 file changed, 29 insertions(+), 10 deletions(-) diff --git a/lib/util.c b/lib/util.c index 141e8417..1e1d1670 100644 --- a/lib/util.c +++ b/lib/util.c @@ -26,6 +26,7 @@ #include #include #include +#include #ifdef HAVE_SELINUX #include @@ -37,6 +38,7 @@ #include #include #include +#include #include #include @@ -67,6 +69,7 @@ time_t gettime(void) * android_name_to_id - returns the integer uid/gid associated with the given * name, or -1U on error. */ +#if 0 static unsigned int android_name_to_id(const char *name) { struct android_id_info const *info = android_ids; @@ -79,6 +82,7 @@ static unsigned int android_name_to_id(const char *name) return -1U; } +#endif /* * decode_uid - decodes and returns the given string, which can be either the @@ -88,16 +92,28 @@ static unsigned int android_name_to_id(const char *name) unsigned int decode_uid(const char *s) { unsigned int v; + uid_t uid; + struct passwd *pwd = malloc(sizeof(struct passwd)); - if (!s || *s == '\0') + if (!s || *s == '\0') { + free(pwd); return -1U; - if (isalpha(s[0])) - return android_name_to_id(s); + } + if (isalpha(s[0])) { + + pwd = getpwnam(s); + uid_t uid = pwd->pw_uid; + free(pwd); + return uid; + } errno = 0; v = (unsigned int) strtoul(s, 0, 0); - if (errno) + if (errno) { + free(pwd); return -1U; + } + free(pwd); return v; } @@ -143,6 +159,7 @@ int mkdir_recursive_with_perms(const char *pathname, mode_t mode, const char *ow int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const char *group) { int ret; + struct passwd *pwd = malloc(sizeof(struct passwd)); ret = mkdir(path, mode); /* chmod in case the directory already exists */ @@ -150,20 +167,22 @@ int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const cha ret = chmod(path, mode); } if (ret == -1) { + free(pwd); return -errno; } if(owner) { - uid_t uid = decode_uid(owner); - gid_t gid = -1; - - if(group) - gid = decode_uid(group); + pwd = getpwnam(owner); + uid_t uid = pwd->pw_uid; + gid_t gid = pwd->pw_gid; - if(chown(path, uid, gid) < 0) + if(chown(path, uid, gid) < 0) { + free(pwd); return -errno; + } } + free(pwd); return 0; } From 023b773ae1ce68137472aa53c0b274e36d71d0ce Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 14 Mar 2018 16:02:17 +0530 Subject: [PATCH 24/65] Fix signed zip generation --- install_zip/Android.mk | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/install_zip/Android.mk b/install_zip/Android.mk index 25e6c978..98b79e58 100644 --- a/install_zip/Android.mk +++ b/install_zip/Android.mk @@ -108,7 +108,7 @@ $(MULTIROM_ZIP_TARGET): multirom trampoline signapk bbootimg mrom_kexec_static m @echo Signing flashable zip @rm -f $(MULTIROM_ZIP_TARGET).zip $(MULTIROM_ZIP_TARGET)-unsigned.zip @cd $(MULTIROM_INST_DIR) && zip -qr ../$(notdir $@)-unsigned.zip * - @java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_ZIP_TARGET)-unsigned.zip $(MULTIROM_ZIP_TARGET).zip + @java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar --min-sdk-version 26 $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_ZIP_TARGET)-unsigned.zip $(MULTIROM_ZIP_TARGET).zip @$(install_zip_path)/rename_zip.sh $(MULTIROM_ZIP_TARGET) $(TARGET_DEVICE) $(PWD)/$(multirom_local_path)/version.h $(MR_DEVICE_SPECIFIC_VERSION) @echo ----- Made MultiROM ZIP installer -------- $@.zip @@ -134,7 +134,7 @@ $(MULTIROM_UNINST_TARGET): signapk bbootimg @echo Signing flashable zip @rm -f $(MULTIROM_UNINST_TARGET).zip $(MULTIROM_UNINST_TARGET)-unsigned.zip @cd $(MULTIROM_UNINST_DIR) && zip -qr ../$(notdir $@)-unsigned.zip * - @java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_UNINST_TARGET)-unsigned.zip $(MULTIROM_UNINST_TARGET).zip + @java -Djava.library.path=$(SIGNAPK_JNI_LIBRARY_PATH) -jar $(HOST_OUT_JAVA_LIBRARIES)/signapk.jar --min-sdk-version 26 $(DEFAULT_SYSTEM_DEV_CERTIFICATE).x509.pem $(DEFAULT_SYSTEM_DEV_CERTIFICATE).pk8 $(MULTIROM_UNINST_TARGET)-unsigned.zip $(MULTIROM_UNINST_TARGET).zip @echo ----- Made MultiROM uninstaller -------- $@.zip .PHONY: multirom_uninstaller From 65783567676de062587420127957f0187fa65f76 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 14 Mar 2018 16:15:14 +0530 Subject: [PATCH 25/65] Remove old adbd --- .gitmodules | 3 --- 1 file changed, 3 deletions(-) diff --git a/.gitmodules b/.gitmodules index 30599bb5..14d1047b 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,6 +1,3 @@ [submodule "kexec-tools"] path = kexec-tools url = https://github.com/Tasssadar/kexec-tools -[submodule "adbd"] - path = adbd - url = https://github.com/multirom-dev/multirom_adbd.git From 98ebf5c18e4412e99e95d40f3f7090aa6f517628 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 14 Mar 2018 16:17:57 +0530 Subject: [PATCH 26/65] Add updated adbd for android-8.1 --- .gitmodules | 3 +++ adbd | 1 + 2 files changed, 4 insertions(+) create mode 160000 adbd diff --git a/.gitmodules b/.gitmodules index 14d1047b..e585ac40 100644 --- a/.gitmodules +++ b/.gitmodules @@ -1,3 +1,6 @@ [submodule "kexec-tools"] path = kexec-tools url = https://github.com/Tasssadar/kexec-tools +[submodule "adbd"] + path = adbd + url = https://github.com/vasishath/adbd diff --git a/adbd b/adbd new file mode 160000 index 00000000..402203d5 --- /dev/null +++ b/adbd @@ -0,0 +1 @@ +Subproject commit 402203d54640cf18d51d18e4aa55729ab460c2c2 From fc85b999bee23d18c72794e0c8dc16b76beb51b1 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 28 Mar 2018 15:49:21 +0530 Subject: [PATCH 27/65] Create own kernel logger The one in libcutils is crashing the kernel for some reason --- lib/Android.mk | 1 + lib/klog.c | 79 ++++++++++++++++++++++++++++++++++++++++++++++++++ lib/log.h | 9 ++++-- 3 files changed, 86 insertions(+), 3 deletions(-) create mode 100644 lib/klog.c diff --git a/lib/Android.mk b/lib/Android.mk index eef72b40..4138c453 100644 --- a/lib/Android.mk +++ b/lib/Android.mk @@ -21,6 +21,7 @@ common_SRC_FILES := \ touch_tracker.c \ util.c \ workers.c \ + klog.c \ common_C_INCLUDES := $(multirom_local_path)/lib \ external/libpng \ diff --git a/lib/klog.c b/lib/klog.c new file mode 100644 index 00000000..51dcce5e --- /dev/null +++ b/lib/klog.c @@ -0,0 +1,79 @@ +/* + * Copyright (C) 2008 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "log.h" + +static int klog_fd = -1; +static int klog_level = 6; + +int multirom_klog_get_level(void) { + return klog_level; +} + +void multirom_klog_set_level(int level) { + klog_level = level; +} + +void multirom_klog_init(void) { + if (klog_fd >= 0) return; /* Already initialized */ + + klog_fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); + if (klog_fd >= 0) { + return; + } + + static const char* name = "/dev/__kmsg__"; + if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) { + klog_fd = open(name, O_WRONLY | O_CLOEXEC); + unlink(name); + } +} + +#define LOG_BUF_MAX 512 + +void multirom_klog_writev(int level, const struct iovec* iov, int iov_count) { + if (level > klog_level) return; + if (klog_fd < 0) multirom_klog_init(); + if (klog_fd < 0) return; + TEMP_FAILURE_RETRY(writev(klog_fd, iov, iov_count)); +} + +void multirom_klog_write(int level, const char* fmt, ...) { + if (level > klog_level) return; + char buf[LOG_BUF_MAX]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + + buf[LOG_BUF_MAX - 1] = 0; + + struct iovec iov[1]; + iov[0].iov_base = buf; + iov[0].iov_len = strlen(buf); + multirom_klog_writev(level, iov, 1); +} diff --git a/lib/log.h b/lib/log.h index 3686b37a..8a509f94 100644 --- a/lib/log.h +++ b/lib/log.h @@ -24,10 +24,13 @@ #define ERROR(fmt, ...) fprintf(stderr, "%s: " fmt "\n", mrom_log_tag(), ##__VA_ARGS__) #define INFO(fmt, ...) printf("%s: " fmt "\n", mrom_log_tag(), ##__VA_ARGS__) #else - #include - #define ERROR(fmt, ...) klog_write(3, "<3>%s: " fmt, mrom_log_tag(), ##__VA_ARGS__) - #define INFO(fmt, ...) klog_write(6, "<6>%s: " fmt, mrom_log_tag(), ##__VA_ARGS__) +void multirom_klog_write(int level, const char* fmt, ...); +void multirom_klog_set_level(int level); + + #define klog_set_level(n) multirom_klog_set_level(n) + #define ERROR(fmt, ...) multirom_klog_write(3, "<3>%s: " fmt, mrom_log_tag(), ##__VA_ARGS__) + #define INFO(fmt, ...) multirom_klog_write(6, "<6>%s: " fmt, mrom_log_tag(), ##__VA_ARGS__) #endif #endif From 2fab8c3ff246e2a2851f3a3992a6489505fb368b Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Mon, 15 Oct 2018 12:15:09 +0530 Subject: [PATCH 28/65] Fix compile with 8.0 --- multirom.c | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/multirom.c b/multirom.c index 407c26f6..50827ce6 100644 --- a/multirom.c +++ b/multirom.c @@ -102,7 +102,7 @@ void disable_dtb_fstab(char* partition) { fprintf(fp, "disabled"); fclose(fp); } - char mnt_pt[strlen(DT_FSTAB_PATH) + strlen(partition) + 1]; + char mnt_pt[100]; sprintf(mnt_pt, "%s%s/status", DT_FSTAB_PATH, partition); if (!mount("/status", mnt_pt, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { INFO("status node bind mounted in procfs\n"); @@ -114,10 +114,10 @@ void disable_dtb_fstab(char* partition) { int mount_dtb_fstab(char* partition) { int rc = -1; - char root_path [strlen(DT_FSTAB_PATH) + 20] = {'\0'}; - char device[sizeof(root_path) + strlen("dev")] = {'\0'}; - char type[sizeof(root_path) + strlen("type")] = {'\0'}; - char mnt_flags[sizeof(root_path) + strlen("mnt_flags")] = {'\0'}; + char root_path [100] = {'\0'}; + char device[100] = {'\0'}; + char type[100] = {'\0'}; + char mnt_flags[100] = {'\0'}; sprintf(root_path, "%s%s", DT_FSTAB_PATH, partition); sprintf(device, "%s%s", root_path, "/dev"); From 1fcf3f707f9b4e448e0f42cbfc226fddcfc5ad01 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Fri, 30 Mar 2018 20:16:41 +0530 Subject: [PATCH 29/65] Fix data mount as read only for roms with vendor --- multirom.c | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/multirom.c b/multirom.c index 50827ce6..079be683 100644 --- a/multirom.c +++ b/multirom.c @@ -126,7 +126,6 @@ int mount_dtb_fstab(char* partition) { if (!(rc = mount(read_file(device), partition, read_file(type), MS_RDONLY, "barrier=1,discard"))) { INFO("dtb %s mount successful\n", partition); - disable_dtb_fstab(partition); } else { INFO("dtb %s mount failed %s\n", partition, strerror(errno)); } @@ -1456,6 +1455,7 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to { if (!access(DT_FSTAB_PATH, F_OK)) { mount_dtb_fstab("system"); + disable_dtb_fstab("system"); } rom_quirks_on_initrd_finalized(); break; @@ -1660,15 +1660,15 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom snprintf(to, sizeof(to), "/%s", folders[i]); snprintf(from, sizeof(from), "%s/%s", rom->base_path, folders[i]); if (!access(from, R_OK)) { + if (strstr(from, "vendor") && multirom_path_exists(rom->base_path, "vendor/etc")) { + continue; + } if(mount(from, to, "ext4", MS_BIND | flags[i], "discard,nomblk_io_submit") < 0) { ERROR("Failed to mount %s to %s (%d: %s)\n", from, to, errno, strerror(errno)); goto exit; } else INFO("Bind mounted %s on %s\n", from, to); continue; - } else if (strstr(from, "vendor")) { - INFO("vendor not found, skipping\n"); - continue; } snprintf(from, sizeof(from), "%s/%s.img", rom->base_path, folders[i]); @@ -1689,18 +1689,23 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom continue; } + if (strstr(from, "vendor")) { + INFO("vendor not found, skipping\n"); + continue; + } // Neither directory nor .img nor .sparse.img was found, panic goto exit; } - if((multirom_path_exists("/", "system/vendor/etc")) != 0 && - (multirom_path_exists(rom->base_path, "vendor")) != 0) { + if((multirom_path_exists("/system", "vendor/etc") == -1) && + (multirom_path_exists(rom->base_path, "vendor/etc") == -1)) { if (!access(DT_FSTAB_PATH, F_OK)) { mount_dtb_fstab("vendor"); } } if (!access(DT_FSTAB_PATH, F_OK)) { disable_dtb_fstab("system"); + disable_dtb_fstab("vendor"); } if(!found_fstab && multirom_process_android_fstab(NULL, has_fw, &fw_part, 1) != 0) { INFO("fstab not found even in vendor!\n"); @@ -1873,7 +1878,7 @@ int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_pa res = 0; if (treble_fstab) { - if(!mount(fstab_save_path, fstab_name, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + if(!mount(fstab_save_path, fstab_name, "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("fstab bind mounted in vendor\n"); } else { ERROR("fstab bind mount failed on %s! %s\n", fstab_name, strerror(errno)); @@ -1926,7 +1931,7 @@ int multirom_create_media_link(struct multirom_status *s) ERROR("Making media dir: api %d, media_new %d, %s to %s\n", api_level, media_new, paths[from], paths[to]); if(mkdir_recursive(paths[to], 0775) == -1) { - ERROR("Failed to make media dir\n"); + ERROR("Failed to make media dir on %s\n", paths[to]); return -1; } From 2e5e8e98de9b70cca6123798a600c2e78f86dbae Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 28 Jul 2018 22:42:14 +0530 Subject: [PATCH 30/65] Add support for android P Android P doesnt allow all dtb partitions to be disabled. So, now we make the partitions undetectable. --- multirom.c | 18 ++++++++++++++++-- 1 file changed, 16 insertions(+), 2 deletions(-) diff --git a/multirom.c b/multirom.c index 079be683..8280e152 100644 --- a/multirom.c +++ b/multirom.c @@ -111,6 +111,21 @@ void disable_dtb_fstab(char* partition) { } } +void remove_dtb_fstab() { + if (access("compatible", F_OK)) { + FILE* fp = fopen("compatible", "w"); + fprintf(fp, "android"); + fclose(fp); + } + char mnt_pt[strlen(DT_FSTAB_PATH) + strlen("/compatible") + 1]; + sprintf(mnt_pt, "%s/compatible", DT_FSTAB_PATH); + if (!mount("/compatible", mnt_pt, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + INFO("compatible node bind mounted in procfs\n"); + } else { + ERROR("compatible node bind mount failed! %s\n", strerror(errno)); + } +} + int mount_dtb_fstab(char* partition) { int rc = -1; @@ -1704,8 +1719,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom } } if (!access(DT_FSTAB_PATH, F_OK)) { - disable_dtb_fstab("system"); - disable_dtb_fstab("vendor"); + remove_dtb_fstab(); } if(!found_fstab && multirom_process_android_fstab(NULL, has_fw, &fw_part, 1) != 0) { INFO("fstab not found even in vendor!\n"); From 57795dfcfc900b230de0cc62e221b75143d577bf Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 27 Oct 2018 13:18:01 +0530 Subject: [PATCH 31/65] Fix usage of getpwnam and switch to _NR_REBOOT syscalls Changes for android-8+ --- lib/util.c | 40 +++++++++++++++++++++++++++------------- 1 file changed, 27 insertions(+), 13 deletions(-) diff --git a/lib/util.c b/lib/util.c index 1e1d1670..da31373f 100644 --- a/lib/util.c +++ b/lib/util.c @@ -39,6 +39,8 @@ #include #include #include +#include +#include #include #include @@ -93,27 +95,26 @@ unsigned int decode_uid(const char *s) { unsigned int v; uid_t uid; - struct passwd *pwd = malloc(sizeof(struct passwd)); + struct passwd *pwd = NULL; if (!s || *s == '\0') { - free(pwd); return -1U; } if (isalpha(s[0])) { pwd = getpwnam(s); + if (!pwd) { + return -errno; + } uid_t uid = pwd->pw_uid; - free(pwd); return uid; } errno = 0; v = (unsigned int) strtoul(s, 0, 0); if (errno) { - free(pwd); return -1U; } - free(pwd); return v; } @@ -159,7 +160,7 @@ int mkdir_recursive_with_perms(const char *pathname, mode_t mode, const char *ow int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const char *group) { int ret; - struct passwd *pwd = malloc(sizeof(struct passwd)); + struct passwd *pwd = NULL; ret = mkdir(path, mode); /* chmod in case the directory already exists */ @@ -167,22 +168,24 @@ int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const cha ret = chmod(path, mode); } if (ret == -1) { - free(pwd); return -errno; } if(owner) { pwd = getpwnam(owner); + + if (!pwd) { + return -errno; + } + uid_t uid = pwd->pw_uid; gid_t gid = pwd->pw_gid; if(chown(path, uid, gid) < 0) { - free(pwd); return -errno; } } - free(pwd); return 0; } @@ -453,6 +456,11 @@ char *run_get_stdout_with_exit_with_env(char **cmd, int *exit_code, char *const waitpid(pid, exit_code, 0); + if (WIFEXITED(*exit_code)) { + INFO("exit code %d", WEXITSTATUS(*exit_code)); + } + + if(written == 0) { free(res); @@ -860,16 +868,22 @@ void do_reboot(int type) { default: case REBOOT_SYSTEM: - android_reboot(ANDROID_RB_RESTART, 0, 0); + //android_reboot(ANDROID_RB_RESTART, 0, 0); + syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, ""); break; case REBOOT_RECOVERY: - android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); + //android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); + syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, "recovery"); break; case REBOOT_BOOTLOADER: - android_reboot(ANDROID_RB_RESTART2, 0, "bootloader"); + //android_reboot(ANDROID_RB_RESTART2, 0, "bootloader"); + syscall(__NR_reboot, LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, + LINUX_REBOOT_CMD_RESTART2, "bootloader"); break; case REBOOT_SHUTDOWN: - android_reboot(ANDROID_RB_POWEROFF, 0, 0); + reboot(RB_POWER_OFF); break; } From b30660738370c6ccab2b5b93fe45e1ee88b513f2 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 27 Oct 2018 13:27:01 +0530 Subject: [PATCH 32/65] trampoline_encmt: Convert to cpp to support HIDL architecture Additionally, add fake library for PropertyWait function (Used by HIDL HALs to check for hwservicemanager) Also add support for specifying security patch and osversion at runtime --- install_zip/Android.mk | 2 + trampoline/encryption.c | 2 +- trampoline_encmnt/Android.mk | 16 +++++++- trampoline_encmnt/{encmnt.c => encmnt.cpp} | 26 ++++++++++-- trampoline_encmnt/fake_properties.c | 24 ++++++++++- trampoline_encmnt/property_wait.cpp | 13 ++++++ trampoline_encmnt/{pw_ui.c => pw_ui.cpp} | 46 +++++++++++----------- 7 files changed, 98 insertions(+), 31 deletions(-) rename trampoline_encmnt/{encmnt.c => encmnt.cpp} (90%) create mode 100644 trampoline_encmnt/property_wait.cpp rename trampoline_encmnt/{pw_ui.c => pw_ui.cpp} (91%) diff --git a/install_zip/Android.mk b/install_zip/Android.mk index 98b79e58..527a12e5 100644 --- a/install_zip/Android.mk +++ b/install_zip/Android.mk @@ -30,6 +30,8 @@ ifeq ($(MR_ENCRYPTION),true) ifeq ($(MR_ENCRYPTION_FAKE_PROPERTIES),true) multirom_extra_dep += libmultirom_fake_properties multirom_cp_enc_libs += libmultirom_fake_properties.so + multirom_extra_dep += libmultirom_fake_propertywait + multirom_cp_enc_libs += libmultirom_fake_propertywait.so endif else MR_ENCRYPTION := false diff --git a/trampoline/encryption.c b/trampoline/encryption.c index d7388297..30a4ae0d 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -35,7 +35,7 @@ static char encmnt_cmd_arg[64] = { 0 }; static char *const encmnt_cmd[] = { "/mrom_enc/trampoline_encmnt", encmnt_cmd_arg, NULL }; #ifdef MR_ENCRYPTION_FAKE_PROPERTIES -static char *const encmnt_envp[] = { "LD_LIBRARY_PATH=/mrom_enc/", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so", NULL }; +static char *const encmnt_envp[] = { "LD_LIBRARY_PATH=/mrom_enc/", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", NULL }; #else static char *const encmnt_envp[] = { "LD_LIBRARY_PATH=/mrom_enc/", NULL }; #endif diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index b764ac98..61e50f72 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -32,8 +32,8 @@ endif LOCAL_C_INCLUDES += $(multirom_local_path) $(mr_twrp_path) $(mr_twrp_path)/crypto/scrypt/lib/crypto external/openssl/include external/boringssl/include LOCAL_SRC_FILES := \ - encmnt.c \ - pw_ui.c \ + encmnt.cpp \ + pw_ui.cpp \ ../rom_quirks.c \ ../rq_inject_file_contexts.c \ @@ -59,4 +59,16 @@ ifeq ($(MR_ENCRYPTION_FAKE_PROPERTIES),true) include $(multirom_local_path)/device_defines.mk include $(BUILD_SHARED_LIBRARY) + + include $(CLEAR_VARS) + + LOCAL_MODULE := libmultirom_fake_propertywait + LOCAL_MODULE_TAGS := optional + LOCAL_C_INCLUDES += $(multirom_local_path) + + LOCAL_SRC_FILES := property_wait.cpp + + include $(multirom_local_path)/device_defines.mk + + include $(BUILD_SHARED_LIBRARY) endif diff --git a/trampoline_encmnt/encmnt.c b/trampoline_encmnt/encmnt.cpp similarity index 90% rename from trampoline_encmnt/encmnt.c rename to trampoline_encmnt/encmnt.cpp index 70be9316..2cf08433 100644 --- a/trampoline_encmnt/encmnt.c +++ b/trampoline_encmnt/encmnt.cpp @@ -22,10 +22,12 @@ #include #include +extern "C" { #include "../lib/log.h" #include "../lib/fstab.h" #include "../lib/framebuffer.h" #include "../lib/util.h" +} #include "crypto/lollipop/cryptfs.h" @@ -113,7 +115,7 @@ static int handle_pwtype(int stdout_fd) return 0; } -static int handle_decrypt(int stdout_fd, const char *password) +static int handle_decrypt(int stdout_fd, char *password) { DIR *d; struct dirent *de; @@ -134,7 +136,7 @@ static int handle_decrypt(int stdout_fd, const char *password) return -1; } else if (pwtype == CRYPT_TYPE_DEFAULT) - password = default_password; + password = (char*)default_password; if(password) { @@ -167,6 +169,7 @@ static int handle_decrypt(int stdout_fd, const char *password) } } + INFO("open block device\n"); d = opendir("/dev/block/"); if(!d) { @@ -174,19 +177,33 @@ static int handle_decrypt(int stdout_fd, const char *password) return -1; } + INFO("finding block device\n"); + if (access("/dev/block/dm-0", R_OK)) { + INFO("/dev/block/dm-0 nhi hai\n"); + } else { + INFO("/dev/block/dm-0 hai\n"); + } // find the block device while((de = readdir(d))) { - if(de->d_type == DT_BLK && strncmp(de->d_name, "dm-", 3) == 0) + INFO("finding block device %d %s\n", de->d_type, de->d_name); + if(de->d_type == DT_BLK && !strncmp(de->d_name, "dm-", 3)) { snprintf(buff, sizeof(buff), "/dev/block/%s\n", de->d_name); INFO("Found block device %s\n", buff); + char temp[512]; + read(stdout_fd, temp, 512); + INFO("ye tha stdout me %s\n", temp); write(stdout_fd, buff, strlen(buff)); fsync(stdout_fd); res = 0; break; } } + /*snprintf(buff, sizeof(buff), "/dev/block/dm-0\n"); + write(stdout_fd, buff, strlen(buff)); + fsync(stdout_fd); + res = 0;*/ closedir(d); return res; @@ -280,9 +297,10 @@ int main(int argc, char *argv[]) INFO("Setting encrypted partition data to %s %s %s\n", p->device, footer_location, p->type); set_partition_data(p->device, footer_location, p->type); - // cryptfs prints informations, we don't want that + //cryptfs prints informations, we don't want that stdout_fd = dup(1); freopen("/dev/null", "ae", stdout); + freopen("/dev/null", "ae", stderr); switch(cmd) { diff --git a/trampoline_encmnt/fake_properties.c b/trampoline_encmnt/fake_properties.c index 1ea8f0a9..012c2572 100644 --- a/trampoline_encmnt/fake_properties.c +++ b/trampoline_encmnt/fake_properties.c @@ -32,13 +32,33 @@ int property_get(const char *key, char *value, const char *default_value) if (!strcmp(key, "sys.listeners.registered")) default_value = "true"; + /* For Keymaster 3 HAL, we need security patch and build version + * to match with the one in bootimg header. Pass the OS version + * and security patch version as environment variable OSVER and OSPATCH + * respectively to keymaster and qseecom (Make sure they LD_PRELOAD this lib) + * process after reading from bootimg in tramp_hook_encryption_setup() function */ + + if (!strcmp(key, "ro.build.version.release")) { + if (getenv("OSVER")) { + strcpy(value, getenv("OSVER")); + return strlen(value); + } + } + + if (!strcmp(key, "ro.build.version.security_patch")) { + if (getenv("OSPATCH")) { + strcpy(value, getenv("OSPATCH")); + return strlen(value); + } + } + #ifdef MR_ENCRYPTION_FAKE_PROPERTIES_EXTRAS int i; for(i = 0; mr_fake_properties[i][0]; ++i) { if (!strcmp(key, mr_fake_properties[i][0])) { - default_value = mr_fake_properties[i][1]; - break; + strncpy(value, mr_fake_properties[i][1], PROP_VALUE_MAX); + return strlen(value); } } #endif diff --git a/trampoline_encmnt/property_wait.cpp b/trampoline_encmnt/property_wait.cpp new file mode 100644 index 00000000..49304d2a --- /dev/null +++ b/trampoline_encmnt/property_wait.cpp @@ -0,0 +1,13 @@ +#include +#include + +namespace android { +namespace base { + + bool WaitForProperty(const std::string& key, const std::string& expected_value, + std::chrono::milliseconds relative_timeout) { + return true; + } + +} +} diff --git a/trampoline_encmnt/pw_ui.c b/trampoline_encmnt/pw_ui.cpp similarity index 91% rename from trampoline_encmnt/pw_ui.c rename to trampoline_encmnt/pw_ui.cpp index c67ef7c1..dd9f3633 100644 --- a/trampoline_encmnt/pw_ui.c +++ b/trampoline_encmnt/pw_ui.cpp @@ -23,6 +23,7 @@ #include "pw_ui.h" #include "encmnt_defines.h" +extern "C" { #include "../lib/framebuffer.h" #include "../lib/colors.h" #include "../lib/log.h" @@ -34,6 +35,7 @@ #include "../lib/workers.h" #include "../lib/containers.h" #include "../rom_quirks.h" +} #include "crypto/lollipop/cryptfs.h" @@ -105,20 +107,20 @@ static void boot_reboot_to_recovery(UNUSED void *data) static void fade_rect_alpha_step(void *data, float interpolated) { - fb_rect *r = data; + fb_rect *r = (fb_rect*)data; r->color = (((int)(0xFF*interpolated)) << 24); fb_request_draw(); } static void reveal_rect_alpha_step(void *data, float interpolated) { - fb_rect *r = data; + fb_rect *r = (fb_rect*)data; interpolated = 1.f - interpolated; r->color = (r->color & ~(0xFF << 24)) | (((int)(0xFF*interpolated)) << 24); fb_request_draw(); } -static int try_password(const char *pass) +static int try_password(char *pass) { fb_text_set_content(invalid_pass_text, ""); @@ -154,7 +156,7 @@ static int try_password(const char *pass) static void type_pass_key_pressed(void *data, uint8_t code) { - struct pwui_type_pass_data *d = data; + struct pwui_type_pass_data *d = (pwui_type_pass_data*)data; if(code < 128) { @@ -162,8 +164,8 @@ static void type_pass_key_pressed(void *data, uint8_t code) while(d->pass_buf_cap < pass_len + 2) { d->pass_buf_cap *= 2; - d->pass_buf = realloc(d->pass_buf, d->pass_buf_cap); - d->pass_buf_stars = realloc(d->pass_buf_stars, d->pass_buf_cap); + d->pass_buf = (char*)realloc(d->pass_buf, d->pass_buf_cap); + d->pass_buf_stars = (char*)realloc(d->pass_buf_stars, d->pass_buf_cap); } if(pass_len > 0) @@ -211,7 +213,7 @@ static void type_pass_key_pressed(void *data, uint8_t code) static void type_pass_init(int pwtype) { - struct pwui_type_pass_data *d = mzalloc(sizeof(struct pwui_type_pass_data)); + struct pwui_type_pass_data *d = (pwui_type_pass_data*)mzalloc(sizeof(struct pwui_type_pass_data)); d->keyboard = keyboard_create(pwtype == CRYPT_TYPE_PIN ? KEYBOARD_PIN : KEYBOARD_NORMAL, 0, fb_height*0.65, fb_width, fb_height*0.35); keyboard_set_callback(d->keyboard, type_pass_key_pressed, d); @@ -220,15 +222,15 @@ static void type_pass_init(int pwtype) center_text(d->passwd_text, 0, 0, fb_width, fb_height); d->pass_buf_cap = 12; - d->pass_buf = mzalloc(d->pass_buf_cap); - d->pass_buf_stars = mzalloc(d->pass_buf_cap); + d->pass_buf = (char*)mzalloc(d->pass_buf_cap); + d->pass_buf_stars = (char*)mzalloc(d->pass_buf_cap); pwui_type_data = d; } static void type_pass_destroy(void) { - struct pwui_type_pass_data *d = pwui_type_data; + struct pwui_type_pass_data *d = (pwui_type_pass_data*)pwui_type_data; keyboard_destroy(d->keyboard); free(d->pass_buf); @@ -276,7 +278,7 @@ static inline void type_pattern_connect_dot(struct pwui_type_pattern_data *d, i static int type_pattern_touch_handler(touch_event *ev, void *data) { - struct pwui_type_pattern_data *d = data; + struct pwui_type_pattern_data *d = (pwui_type_pattern_data*)data; if(d->touch_id == -1 && (ev->changed & TCHNG_ADDED) && !ev->consumed) { @@ -343,7 +345,7 @@ static int type_pattern_touch_handler(touch_event *ev, void *data) d->cur_line = NULL; fb_request_draw(); - char *passwd = malloc(d->connected_dots_len+1); + char *passwd = (char*)malloc(d->connected_dots_len+1); size_t i; for(i = 0; i < d->connected_dots_len; ++i) passwd[i] = '1' + d->connected_dots[i]; @@ -351,8 +353,8 @@ static int type_pattern_touch_handler(touch_event *ev, void *data) if(try_password(passwd) < 0) { - list_clear(&d->active_dots, fb_remove_item); - list_clear(&d->complete_lines, fb_remove_item); + list_clear(&d->active_dots, (callback)fb_remove_item); + list_clear(&d->complete_lines, (callback)fb_remove_item); fb_request_draw(); } @@ -364,7 +366,7 @@ static int type_pattern_touch_handler(touch_event *ev, void *data) static void type_pattern_init(void) { - struct pwui_type_pattern_data *d = mzalloc(sizeof(struct pwui_type_pattern_data)); + struct pwui_type_pattern_data *d = (pwui_type_pattern_data*)mzalloc(sizeof(struct pwui_type_pattern_data)); int cx, cy; const int start_x = fb_width*0.2; @@ -393,10 +395,10 @@ static void type_pattern_init(void) static void type_pattern_destroy(void) { - struct pwui_type_pattern_data *d = pwui_type_data; - list_clear(&d->dots, fb_remove_item); - list_clear(&d->active_dots, fb_remove_item); - list_clear(&d->complete_lines, fb_remove_item); + struct pwui_type_pattern_data *d = (pwui_type_pattern_data*)pwui_type_data; + list_clear(&d->dots, (callback)fb_remove_item); + list_clear(&d->active_dots, (callback)fb_remove_item); + list_clear(&d->complete_lines, (callback)fb_remove_item); fb_rm_line(d->cur_line); free(d); @@ -423,7 +425,7 @@ static void init_ui(int pwtype) if(!mrom_is_second_boot()) { - boot_primary_btn = mzalloc(sizeof(button)); + boot_primary_btn = (button*)mzalloc(sizeof(button)); boot_primary_btn->w = fb_width*0.30; boot_primary_btn->h = HEADER_HEIGHT; boot_primary_btn->x = fb_width - boot_primary_btn->w; @@ -434,7 +436,7 @@ static void init_ui(int pwtype) } else { - boot_primary_btn = mzalloc(sizeof(button)); + boot_primary_btn = (button*)mzalloc(sizeof(button)); boot_primary_btn->w = fb_width*0.30; boot_primary_btn->h = HEADER_HEIGHT; boot_primary_btn->x = fb_width - boot_primary_btn->w; @@ -479,7 +481,7 @@ static void destroy_ui(int pwtype) static int pw_ui_shutdown_counter_touch_handler(UNUSED touch_event *ev, void *data) { - int *shutdown_counter = data; + int *shutdown_counter = (int*)data; if(*shutdown_counter == 0) return -1; From 6d54bbf08becf067715d6c961fda168e58c43f0a Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 27 Oct 2018 13:30:17 +0530 Subject: [PATCH 33/65] Actually fix data partition being mounted readonly --- multirom.c | 17 ++++++++++------- rom_quirks.c | 2 +- 2 files changed, 11 insertions(+), 8 deletions(-) diff --git a/multirom.c b/multirom.c index 8280e152..ed7c896d 100644 --- a/multirom.c +++ b/multirom.c @@ -104,7 +104,7 @@ void disable_dtb_fstab(char* partition) { } char mnt_pt[100]; sprintf(mnt_pt, "%s%s/status", DT_FSTAB_PATH, partition); - if (!mount("/status", mnt_pt, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + if (!mount("/status", mnt_pt, "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("status node bind mounted in procfs\n"); } else { ERROR("status node bind mount failed! %s\n", strerror(errno)); @@ -119,7 +119,7 @@ void remove_dtb_fstab() { } char mnt_pt[strlen(DT_FSTAB_PATH) + strlen("/compatible") + 1]; sprintf(mnt_pt, "%s/compatible", DT_FSTAB_PATH); - if (!mount("/compatible", mnt_pt, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + if (!mount("/compatible", mnt_pt, "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("compatible node bind mounted in procfs\n"); } else { ERROR("compatible node bind mount failed! %s\n", strerror(errno)); @@ -507,10 +507,12 @@ int multirom(const char *rom_to_boot) multirom_run_scripts("run-on-boot", to_boot); exit = multirom_prepare_for_boot(&s, to_boot); + INFO("prepare for boot returned %d\n", exit); // Something went wrong, exit/reboot if(exit == -1) { + INFO("SOMETHING HAS GONE WRONG !!"); if(rom_to_boot == NULL) { multirom_emergency_reboot(); @@ -1469,8 +1471,9 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to case ROM_DEFAULT: { if (!access(DT_FSTAB_PATH, F_OK)) { - mount_dtb_fstab("system"); - disable_dtb_fstab("system"); + if (mount_dtb_fstab("system") == 0) { + disable_dtb_fstab("system"); + } } rom_quirks_on_initrd_finalized(); break; @@ -1664,8 +1667,8 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom remove("/vendor"); rename("/vendor_boot", "/vendor"); } - static const char *folders[4] = { "system" , "data" , "cache" , "vendor"}; - unsigned long flags[4] = { MS_RDONLY , MS_NOSUID | MS_NODEV , MS_NOSUID | MS_NODEV, MS_RDONLY }; + static const char *folders[4] = { "system" , "vendor" , "data" , "cache"}; + unsigned long flags[4] = { MS_RDONLY , MS_RDONLY, MS_NOSUID | MS_NODEV , MS_NOSUID | MS_NODEV}; uint32_t i; char from[256]; @@ -2865,7 +2868,7 @@ int multirom_update_partitions(struct multirom_status *s) tok = strrchr(line, '/')+1; name = strndup(tok, strchr(tok, ':') - tok); - if(strncmp(name, "mmcblk0", 7) == 0 || strncmp(name, "dm-", 3) == 0) // ignore internal nand + if(strncmp(name, "mmcblk0", 7) == 0 || strncmp(name, "dm-", 3) == 0 || strncmp(name, "sd", 2) == 0) // ignore internal nand { free(name); goto next_itr; diff --git a/rom_quirks.c b/rom_quirks.c index 25df92bc..63f0a812 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -198,7 +198,7 @@ void rom_quirks_on_initrd_finalized(void) } if (!access(path, F_OK)) { - if(!mount("/plat_file_contexts", path, "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit")) { + if(!mount("/plat_file_contexts", path, "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("file_contexts bind mounted in system\n"); } else { ERROR("file_contexts bind mount failed! %s\n", strerror(errno)); From 6811aacd2333233dbe3c378708965169bb5e48d5 Mon Sep 17 00:00:00 2001 From: shahan-mik3 Date: Sat, 27 Oct 2018 13:31:47 +0530 Subject: [PATCH 34/65] Use do_reboot functionality from lib --- no_kexec.c | 1 + trampoline/Android.mk | 1 + trampoline/trampoline.c | 6 +++--- 3 files changed, 5 insertions(+), 3 deletions(-) diff --git a/no_kexec.c b/no_kexec.c index 10651452..ee82dd2f 100644 --- a/no_kexec.c +++ b/no_kexec.c @@ -34,6 +34,7 @@ #include "lib/inject.h" #include "lib/log.h" #include "lib/util.h" +#include "lib/mrom_data.h" #include "multirom.h" #include "version.h" diff --git a/trampoline/Android.mk b/trampoline/Android.mk index b1c7fa1e..7ec46c5e 100644 --- a/trampoline/Android.mk +++ b/trampoline/Android.mk @@ -13,6 +13,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static libbootimg +LOCAL_C_INCLUDES += system/extras/libbootimg/include LOCAL_FORCE_STATIC_EXECUTABLE := true ifeq ($(MR_INIT_DEVICES),) diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index c9b3861a..e78c91e8 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -183,7 +183,7 @@ static int mount_and_run(struct fstab *fstab) if(access(datap->device, R_OK) < 0) { - INFO("Waiting for %s\n", datap->device); + INFO("Waiting for %s because error %s\n", datap->device, strerror(errno)); if(wait_for_file(datap->device, 5) < 0) { ERROR("Waiting too long for dev %s\n", datap->device); @@ -209,7 +209,7 @@ static int mount_and_run(struct fstab *fstab) return 0; case ENC_RES_BOOT_RECOVERY: sync(); - android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); // REBOOT_RECOVERY + do_reboot(REBOOT_RECOVERY); // REBOOT_RECOVERY while (1) sleep(1); // we're never returning @@ -367,7 +367,7 @@ static int run_core(void) ERROR("This is second boot and we couldn't mount /data, reboot!\n"); sync(); //android_reboot(ANDROID_RB_RESTART, 0, 0); - android_reboot(ANDROID_RB_RESTART2, 0, "recovery"); // favour reboot to recovery, to avoid possible bootlooping + do_reboot(REBOOT_RECOVERY); // favour reboot to recovery, to avoid possible bootlooping while(1) sleep(1); } From 23a6b5e863d61d7f5174f45e2047af47f5ecab45 Mon Sep 17 00:00:00 2001 From: shahan-mik3 Date: Sat, 27 Oct 2018 13:32:33 +0530 Subject: [PATCH 35/65] Add hwservice selinux contexts Needed by hwservicemanager during startup --- lib/inject.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/lib/inject.c b/lib/inject.c index 25523222..73189c78 100644 --- a/lib/inject.c +++ b/lib/inject.c @@ -58,6 +58,8 @@ static int copy_rd_files(UNUSED const char *path, UNUSED const char *busybox_pat char path_main[64]; char path_mrom_enc[64]; char path_mrom_fstab[64]; + char path_hwservice_contexts[64]; + char path_nonplat_hwservice_contexts[64]; char path_ueventd[64]; char path_watchdog[64]; @@ -68,6 +70,8 @@ static int copy_rd_files(UNUSED const char *path, UNUSED const char *busybox_pat snprintf(path_main, sizeof(path_main), TMP_RD2_UNPACKED_DIR "/main_init"); snprintf(path_mrom_enc, sizeof(path_mrom_enc), TMP_RD2_UNPACKED_DIR "/mrom_enc"); snprintf(path_mrom_fstab, sizeof(path_mrom_fstab), TMP_RD2_UNPACKED_DIR "/mrom.fstab"); + snprintf(path_hwservice_contexts, sizeof(path_hwservice_contexts), TMP_RD2_UNPACKED_DIR "/plat_hwservice_contexts"); + snprintf(path_nonplat_hwservice_contexts, sizeof(path_nonplat_hwservice_contexts), TMP_RD2_UNPACKED_DIR "/nonplat_hwservice_contexts"); snprintf(path_ueventd, sizeof(path_ueventd), TMP_RD2_UNPACKED_DIR "/sbin/ueventd"); snprintf(path_watchdog, sizeof(path_watchdog), TMP_RD2_UNPACKED_DIR "/sbin/watchdogd"); } @@ -82,6 +86,8 @@ static int copy_rd_files(UNUSED const char *path, UNUSED const char *busybox_pat snprintf(path_main, sizeof(path_main), TMP_RD_UNPACKED_DIR "/main_init"); snprintf(path_mrom_enc, sizeof(path_mrom_enc), TMP_RD_UNPACKED_DIR "/mrom_enc"); snprintf(path_mrom_fstab, sizeof(path_mrom_fstab), TMP_RD_UNPACKED_DIR "/mrom.fstab"); + snprintf(path_hwservice_contexts, sizeof(path_hwservice_contexts), TMP_RD_UNPACKED_DIR "/plat_hwservice_contexts"); + snprintf(path_nonplat_hwservice_contexts, sizeof(path_nonplat_hwservice_contexts), TMP_RD_UNPACKED_DIR "/nonplat_hwservice_contexts"); snprintf(path_ueventd, sizeof(path_ueventd), TMP_RD_UNPACKED_DIR "/sbin/ueventd"); snprintf(path_watchdog, sizeof(path_watchdog), TMP_RD_UNPACKED_DIR "/sbin/watchdogd"); } @@ -111,6 +117,10 @@ static int copy_rd_files(UNUSED const char *path, UNUSED const char *busybox_pat #else remove(path_mrom_fstab); #endif + snprintf(buf, sizeof(buf), "%s/plat_hwservice_contexts", mrom_dir()); + copy_file(buf, path_hwservice_contexts); + snprintf(buf, sizeof(buf), "%s/nonplat_hwservice_contexts", mrom_dir()); + copy_file(buf, path_nonplat_hwservice_contexts); #ifdef MR_ENCRYPTION remove_dir(path_mrom_enc); From 0830f5f780a83cfacea41de3a894df5faf231643 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Fri, 2 Nov 2018 01:01:10 +0530 Subject: [PATCH 36/65] devices: Add support for drm devices --- trampoline/devices.c | 3 +++ 1 file changed, 3 insertions(+) diff --git a/trampoline/devices.c b/trampoline/devices.c index 79047cd4..64e970c3 100644 --- a/trampoline/devices.c +++ b/trampoline/devices.c @@ -803,6 +803,9 @@ static void handle_generic_device_event(struct uevent *uevent) } else if (!strncmp(uevent->subsystem, "graphics", 8)) { base = "/dev/graphics/"; make_dir(base, 0755); + } else if (!strncmp(uevent->subsystem, "drm", 3)) { + base = "/dev/dri/"; + make_dir(base, 0755); } else if (!strncmp(uevent->subsystem, "oncrpc", 6)) { base = "/dev/oncrpc/"; make_dir(base, 0755); From f77dc98fcb0beca7267751255a83063fc41f02ef Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 3 Nov 2018 17:13:30 +0530 Subject: [PATCH 37/65] Add support for DRM graphics --- lib/Android.mk | 14 ++ lib/drm.c | 607 ++++++++++++++++++++++++++++++++++++++++++++++ lib/framebuffer.c | 21 +- lib/framebuffer.h | 3 + 4 files changed, 636 insertions(+), 9 deletions(-) create mode 100644 lib/drm.c diff --git a/lib/Android.mk b/lib/Android.mk index 4138c453..c7d56d27 100644 --- a/lib/Android.mk +++ b/lib/Android.mk @@ -55,6 +55,14 @@ endif endif +ifeq ($(MR_DEVICE_HAS_DRM_GRAPHICS),true) + common_C_FLAGS += -DMR_DEVICE_HAS_DRM_GRAPHICS + common_C_INCLUDES += \ + external/libdrm \ + external/libdrm/include/drm + common_SRC_FILES += \ + drm.c +endif include $(CLEAR_VARS) @@ -64,6 +72,9 @@ LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) LOCAL_CFLAGS += $(common_C_FLAGS) LOCAL_C_INCLUDES += $(common_C_INCLUDES) +ifeq ($(MR_DEVICE_HAS_DRM_GRAPHICS),true) +LOCAL_WHOLE_STATIC_LIBRARIES := libdrm_platform +endif LOCAL_SRC_FILES := $(common_SRC_FILES) MR_NO_KEXEC_MK_OPTIONS := true 1 allowed 2 enabled 3 ui_confirm 4 ui_choice 5 forced @@ -86,6 +97,9 @@ include $(CLEAR_VARS) LOCAL_MODULE := libmultirom LOCAL_MODULE_TAGS := optional LOCAL_SHARED_LIBRARIES := libcutils libc libm libpng libz libft2 +ifeq ($(MR_DEVICE_HAS_DRM_GRAPHICS),true) +LOCAL_WHOLE_STATIC_LIBRARIES := libdrm_platform +endif LOCAL_CFLAGS += $(common_C_FLAGS) LOCAL_SRC_FILES := $(common_SRC_FILES) LOCAL_C_INCLUDES += $(common_C_INCLUDES) diff --git a/lib/drm.c b/lib/drm.c new file mode 100644 index 00000000..aa35baff --- /dev/null +++ b/lib/drm.c @@ -0,0 +1,607 @@ +/* + * Copyright (C) 2015 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "framebuffer.h" +#include "log.h" +#include "util.h" + +#define ARRAY_SIZE(A) (sizeof(A)/sizeof(*(A))) + +typedef struct GRSurface { + int width; + int height; + int row_bytes; + int pixel_bytes; + unsigned char* data; //This is the actual FB +} GRSurface; + +typedef struct drm_surface { + GRSurface base; + uint32_t fb_id; + uint32_t handle; +}drm_surface; + +static drm_surface *drm_surfaces[2]; +static int current_buffer; +static GRSurface *draw_buf = NULL; + +static drmModeCrtc *main_monitor_crtc; +static drmModeConnector *main_monitor_connector; + +static int drm_fd = -1; + +static void drm_disable_crtc(int drm_fd, drmModeCrtc *crtc) { + if (crtc) { + drmModeSetCrtc(drm_fd, crtc->crtc_id, + 0, // fb_id + 0, 0, // x,y + NULL, // connectors + 0, // connector_count + NULL); // mode + } +} + +static void drm_enable_crtc(int drm_fd, drmModeCrtc *crtc, + struct drm_surface *surface) { + int32_t ret; + + ret = drmModeSetCrtc(drm_fd, crtc->crtc_id, + surface->fb_id, + 0, 0, // x,y + &main_monitor_connector->connector_id, + 1, // connector_count + &main_monitor_crtc->mode); + + if (ret) + INFO("drmModeSetCrtc failed ret=%d\n", ret); +} + +static void drm_blank(bool blank, int buffer) { + if (blank) + drm_disable_crtc(drm_fd, main_monitor_crtc); + else + drm_enable_crtc(drm_fd, main_monitor_crtc, + drm_surfaces[buffer]); +} + +static void drm_destroy_surface(struct drm_surface *surface) { + struct drm_gem_close gem_close; + int ret; + + if(!surface) + return; + + if (surface->base.data) + munmap(surface->base.data, + surface->base.row_bytes * surface->base.height); + + if (surface->fb_id) { + ret = drmModeRmFB(drm_fd, surface->fb_id); + if (ret) + INFO("drmModeRmFB failed ret=%d\n", ret); + } + + if (surface->handle) { + memset(&gem_close, 0, sizeof(gem_close)); + gem_close.handle = surface->handle; + + ret = drmIoctl(drm_fd, DRM_IOCTL_GEM_CLOSE, &gem_close); + if (ret) + INFO("DRM_IOCTL_GEM_CLOSE failed ret=%d\n", ret); + } + + free(surface); +} + +static int drm_format_to_bpp(uint32_t format) { + switch(format) { + case DRM_FORMAT_ABGR8888: + case DRM_FORMAT_BGRA8888: + case DRM_FORMAT_RGBX8888: + case DRM_FORMAT_BGRX8888: + case DRM_FORMAT_XBGR8888: + case DRM_FORMAT_ARGB8888: + case DRM_FORMAT_XRGB8888: + return 32; + case DRM_FORMAT_RGB565: + return 16; + default: + INFO("Unknown format %d\n", format); + return 32; + } +} + +static drm_surface *drm_create_surface(int width, int height) { + struct drm_surface *surface; + struct drm_mode_create_dumb create_dumb; + uint32_t format; + int ret; + + surface = (struct drm_surface*)calloc(1, sizeof(*surface)); + if (!surface) { + INFO("Can't allocate memory\n"); + return NULL; + } + +#if defined(RECOVERY_ABGR) + format = DRM_FORMAT_RGBA8888; + INFO("setting DRM_FORMAT_RGBA8888 and GGL_PIXEL_FORMAT_RGBA_8888\n"); +#elif defined(RECOVERY_BGRA) + format = DRM_FORMAT_ARGB8888; + INFO("setting DRM_FORMAT_ARGB8888 and GGL_PIXEL_FORMAT_RGBA_8888\n"); +#elif defined(RECOVERY_RGBA) + format = DRM_FORMAT_ABGR8888; + INFO("setting DRM_FORMAT_ABGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n"); +#elif defined(RECOVERY_RGBX) + format = DRM_FORMAT_XBGR8888; + INFO("setting DRM_FORMAT_XBGR8888 and GGL_PIXEL_FORMAT_BGRA_8888, GGL_PIXEL_FORMAT may not match!\n"); +#else + format = DRM_FORMAT_RGB565; + INFO("setting DRM_FORMAT_RGB565 and GGL_PIXEL_FORMAT_RGB_565\n"); +#endif + + memset(&create_dumb, 0, sizeof(create_dumb)); + create_dumb.height = height; + create_dumb.width = width; + create_dumb.bpp = drm_format_to_bpp(format); + create_dumb.flags = 0; + + ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_CREATE_DUMB, &create_dumb); + if (ret) { + INFO("DRM_IOCTL_MODE_CREATE_DUMB failed ret=%d\n",ret); + drm_destroy_surface(surface); + return NULL; + } + surface->handle = create_dumb.handle; + + uint32_t handles[4], pitches[4], offsets[4]; + + handles[0] = surface->handle; + pitches[0] = create_dumb.pitch; + offsets[0] = 0; + + ret = drmModeAddFB2(drm_fd, width, height, + format, handles, pitches, offsets, + &(surface->fb_id), 0); + if (ret) { + INFO("drmModeAddFB2 failed ret=%d\n", ret); + drm_destroy_surface(surface); + return NULL; + } + + struct drm_mode_map_dumb map_dumb; + memset(&map_dumb, 0, sizeof(map_dumb)); + map_dumb.handle = create_dumb.handle; + ret = drmIoctl(drm_fd, DRM_IOCTL_MODE_MAP_DUMB, &map_dumb); + if (ret) { + INFO("DRM_IOCTL_MODE_MAP_DUMB failed ret=%d\n",ret); + drm_destroy_surface(surface); + return NULL;; + } + + surface->base.height = height; + surface->base.width = width; + surface->base.row_bytes = create_dumb.pitch; + surface->base.pixel_bytes = create_dumb.bpp / 8; + surface->base.data = (unsigned char*) + mmap(NULL, + surface->base.height * surface->base.row_bytes, + PROT_READ | PROT_WRITE, MAP_SHARED, + drm_fd, map_dumb.offset); + if (surface->base.data == MAP_FAILED) { + perror("mmap() failed"); + drm_destroy_surface(surface); + return NULL; + } + + return surface; +} + +static drmModeCrtc *find_crtc_for_connector(int fd, + drmModeRes *resources, + drmModeConnector *connector) { + int i, j; + drmModeEncoder *encoder; + int32_t crtc; + + /* + * Find the encoder. If we already have one, just use it. + */ + if (connector->encoder_id) + encoder = drmModeGetEncoder(fd, connector->encoder_id); + else + encoder = NULL; + + if (encoder && encoder->crtc_id) { + crtc = encoder->crtc_id; + drmModeFreeEncoder(encoder); + return drmModeGetCrtc(fd, crtc); + } + + /* + * Didn't find anything, try to find a crtc and encoder combo. + */ + crtc = -1; + for (i = 0; i < connector->count_encoders; i++) { + encoder = drmModeGetEncoder(fd, connector->encoders[i]); + + if (encoder) { + for (j = 0; j < resources->count_crtcs; j++) { + if (!(encoder->possible_crtcs & (1 << j))) + continue; + crtc = resources->crtcs[j]; + break; + } + if (crtc >= 0) { + drmModeFreeEncoder(encoder); + return drmModeGetCrtc(fd, crtc); + } + } + } + + return NULL; +} + +static drmModeConnector *find_used_connector_by_type(int fd, + drmModeRes *resources, + unsigned type) { + int i; + for (i = 0; i < resources->count_connectors; i++) { + drmModeConnector *connector; + + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector) { + if ((connector->connector_type == type) && + (connector->connection == DRM_MODE_CONNECTED) && + (connector->count_modes > 0)) + return connector; + + drmModeFreeConnector(connector); + } + } + return NULL; +} + +static drmModeConnector *find_first_connected_connector(int fd, + drmModeRes *resources) { + int i; + for (i = 0; i < resources->count_connectors; i++) { + drmModeConnector *connector; + + connector = drmModeGetConnector(fd, resources->connectors[i]); + if (connector) { + if ((connector->count_modes > 0) && + (connector->connection == DRM_MODE_CONNECTED)) + return connector; + + drmModeFreeConnector(connector); + } + } + return NULL; +} + +static drmModeConnector *find_main_monitor(int fd, drmModeRes *resources, + uint32_t *mode_index) { + unsigned i = 0; + int modes; + /* Look for LVDS/eDP/DSI connectors. Those are the main screens. */ + unsigned kConnectorPriority[] = { + DRM_MODE_CONNECTOR_LVDS, + DRM_MODE_CONNECTOR_eDP, + DRM_MODE_CONNECTOR_DSI, + }; + + drmModeConnector *main_monitor_connector = NULL; + do { + main_monitor_connector = find_used_connector_by_type(fd, + resources, + kConnectorPriority[i]); + i++; + } while (!main_monitor_connector && i < ARRAY_SIZE(kConnectorPriority)); + + /* If we didn't find a connector, grab the first one that is connected. */ + if (!main_monitor_connector) + main_monitor_connector = + find_first_connected_connector(fd, resources); + + /* If we still didn't find a connector, give up and return. */ + if (!main_monitor_connector) + return NULL; + + *mode_index = 0; + for (modes = 0; modes < main_monitor_connector->count_modes; modes++) { + if (main_monitor_connector->modes[modes].type & + DRM_MODE_TYPE_PREFERRED) { + *mode_index = modes; + break; + } + } + + return main_monitor_connector; +} + +static void disable_non_main_crtcs(int fd, + drmModeRes *resources, + drmModeCrtc* main_crtc) { + int i; + drmModeCrtc* crtc; + + for (i = 0; i < resources->count_connectors; i++) { + drmModeConnector *connector; + + connector = drmModeGetConnector(fd, resources->connectors[i]); + crtc = find_crtc_for_connector(fd, resources, connector); + if (crtc->crtc_id != main_crtc->crtc_id) + drm_disable_crtc(fd, crtc); + drmModeFreeCrtc(crtc); + } +} + +static int drm_init(struct framebuffer *fb) { + drmModeRes *res = NULL; + uint32_t selected_mode; + char *dev_name; + int width, height; + int ret, i; + + /* Consider DRM devices in order. */ + for (i = 0; i < DRM_MAX_MINOR; i++) { + uint64_t cap = 0; + + ret = asprintf(&dev_name, DRM_DEV_NAME, DRM_DIR_NAME, i); + INFO("trying %s\n", dev_name); + if (ret < 0) + continue; + + drm_fd = open(dev_name, O_RDWR, 0); + free(dev_name); + if (drm_fd < 0) { + INFO("open failed with error %s", strerror(errno)); + continue; + } + + /* We need dumb buffers. */ + ret = drmGetCap(drm_fd, DRM_CAP_DUMB_BUFFER, &cap); + if (ret || cap == 0) { + close(drm_fd); + continue; + } + + res = drmModeGetResources(drm_fd); + if (!res) { + close(drm_fd); + continue; + } + + /* Use this device if it has at least one connected monitor. */ + if (res->count_crtcs > 0 && res->count_connectors > 0) + if (find_first_connected_connector(drm_fd, res)) + break; + + drmModeFreeResources(res); + close(drm_fd); + res = NULL; + } + + if (drm_fd < 0 || res == NULL) { + perror("cannot find/open a drm device"); + return -1; + } + + main_monitor_connector = find_main_monitor(drm_fd, + res, &selected_mode); + + if (!main_monitor_connector) { + INFO("main_monitor_connector not found\n"); + drmModeFreeResources(res); + close(drm_fd); + return -1; + } + + main_monitor_crtc = find_crtc_for_connector(drm_fd, res, + main_monitor_connector); + + if (!main_monitor_crtc) { + INFO("main_monitor_crtc not found\n"); + drmModeFreeResources(res); + close(drm_fd); + return -1; + } + + disable_non_main_crtcs(drm_fd, + res, main_monitor_crtc); + + INFO("selected mode %d\n", selected_mode); + main_monitor_crtc->mode = main_monitor_connector->modes[selected_mode]; + + width = main_monitor_crtc->mode.hdisplay; + height = main_monitor_crtc->mode.vdisplay; + + drmModeFreeResources(res); + + drm_surfaces[0] = drm_create_surface(width, height); + drm_surfaces[1] = drm_create_surface(width, height); + if (!drm_surfaces[0] || !drm_surfaces[1]) { + drm_destroy_surface(drm_surfaces[0]); + drm_destroy_surface(drm_surfaces[1]); + drmModeFreeResources(res); + close(drm_fd); + return -1; + } + + draw_buf = (GRSurface *)malloc(sizeof(GRSurface)); + if (!draw_buf) { + INFO("failed to alloc draw_buf\n"); + drm_destroy_surface(drm_surfaces[0]); + drm_destroy_surface(drm_surfaces[1]); + drmModeFreeResources(res); + close(drm_fd); + return -1; + } + + memcpy(draw_buf, &drm_surfaces[0]->base, sizeof(GRSurface)); + + /*Assign framebuffer properties here to maintain compatibility*/ + + fb_width = draw_buf->width; + fb_height = draw_buf->height; + fb->stride = draw_buf->row_bytes / draw_buf->pixel_bytes; + fb->size = draw_buf->height * draw_buf->row_bytes * draw_buf->pixel_bytes; + fb->vi.bits_per_pixel = draw_buf->pixel_bytes * 8; + fb->vi.xres = fb_width; + fb->vi.yres = fb_height; + fb->vi.xres_virtual = fb_width; + fb->vi.yres_virtual = fb_height; + INFO("Pixel format: %dx%d @ %dbpp\n", fb->vi.xres, fb->vi.yres, fb->vi.bits_per_pixel); + +#ifdef RECOVERY_BGRA + INFO("Pixel format: BGRA_8888\n"); + fb->vi.red.offset = 8; + fb->vi.red.length = 8; + fb->vi.green.offset = 16; + fb->vi.green.length = 8; + fb->vi.blue.offset = 24; + fb->vi.blue.length = 8; + fb->vi.transp.offset = 0; + fb->vi.transp.length = 8; +#elif defined(RECOVERY_RGBX) + INFO("Pixel format: RGBX_8888\n"); + fb->vi.red.offset = 24; + fb->vi.red.length = 8; + fb->vi.green.offset = 16; + fb->vi.green.length = 8; + fb->vi.blue.offset = 8; + fb->vi.blue.length = 8; + fb->vi.transp.offset = 0; + fb->vi.transp.length = 8; +#elif defined(RECOVERY_RGBA) + INFO("Pixel format: RGBA_8888\n"); + fb->vi.red.offset = 0; + fb->vi.red.length = 8; + fb->vi.green.offset = 8; + fb->vi.green.length = 8; + fb->vi.blue.offset = 16; + fb->vi.blue.length = 8; + fb->vi.transp.offset = 24; + fb->vi.transp.length = 8; +#elif defined(RECOVERY_RGB_565) + INFO("Pixel format: RGB_565\n"); + fb->vi.blue.offset = 0; + fb->vi.green.offset = 5; + fb->vi.red.offset = 11; + fb->vi.blue.length = 5; + fb->vi.green.length = 6; + fb->vi.red.length = 5; + fb->vi.blue.msb_right = 0; + fb->vi.green.msb_right = 0; + fb->vi.red.msb_right = 0; + fb->vi.transp.offset = 0; + fb->vi.transp.length = 0; +#elif defined(RECOVERY_ABGR) + INFO("Pixel format: ABGR_8888\n"); + fb->vi.red.offset = 0; + fb->vi.red.length = 8; + fb->vi.green.offset = 8; + fb->vi.green.length = 8; + fb->vi.blue.offset = 16; + fb->vi.blue.length = 8; + fb->vi.transp.offset = 24; + fb->vi.transp.length = 8; +#else +#error "Unknown pixel format" +#endif + + + draw_buf->data = (unsigned char *)calloc(draw_buf->height * draw_buf->row_bytes, 1); + if (!draw_buf->data) { + INFO("failed to alloc draw_buf surface\n"); + free(draw_buf); + drm_destroy_surface(drm_surfaces[0]); + drm_destroy_surface(drm_surfaces[1]); + drmModeFreeResources(res); + close(drm_fd); + return -1; + } + + drm_enable_crtc(drm_fd, main_monitor_crtc, drm_surfaces[1]); + +#ifdef TW_SCREEN_BLANK_ON_BOOT + drm_blank(true, 1); + drm_blank(false, 1); +#endif + current_buffer = 0; + + return 0; +} + +static int drm_update(struct framebuffer *fb) { + int ret; + + memcpy(drm_surfaces[current_buffer]->base.data, + draw_buf->data, draw_buf->height * draw_buf->row_bytes); + + + ret = drmModePageFlip(drm_fd, main_monitor_crtc->crtc_id, + drm_surfaces[current_buffer]->fb_id, 0, NULL); + + if (ret < 0) { + ERROR("drmModePageFlip failed ret=%d\n", ret); + return -1; + } + + current_buffer = 1 - current_buffer; + + return 0; +} + +static void* drm_get_frame_dest(struct framebuffer *fb) { + + return draw_buf->data; +} + +static void drm_exit(struct framebuffer *fb) { + drm_disable_crtc(drm_fd, main_monitor_crtc); + drm_destroy_surface(drm_surfaces[0]); + drm_destroy_surface(drm_surfaces[1]); + drmModeFreeCrtc(main_monitor_crtc); + drmModeFreeConnector(main_monitor_connector); + close(drm_fd); + drm_fd = -1; +} + +const struct fb_impl fb_impl_drm = { + .name = "Drm", + .impl_id = FB_IMPL_DRM, + .open = drm_init, + .close = drm_exit, + .update = drm_update, + .get_frame_dest = drm_get_frame_dest, +}; diff --git a/lib/framebuffer.c b/lib/framebuffer.c index b0123502..5d54b4be 100644 --- a/lib/framebuffer.c +++ b/lib/framebuffer.c @@ -95,9 +95,13 @@ int fb_open_impl(void) extern struct fb_impl fb_impl_ ## N; \ impls[ID] = &fb_impl_ ## N; +#ifdef MR_DEVICE_HAS_DRM_GRAPHICS + ADD_IMPL(FB_IMPL_DRM, drm); +#else ADD_IMPL(FB_IMPL_GENERIC, generic); #ifdef MR_USE_QCOM_OVERLAY ADD_IMPL(FB_IMPL_QCOM_OVERLAY, qcom_overlay); +#endif #endif if(fb_force_generic) @@ -123,6 +127,7 @@ int fb_open(int rotation) { memset(&fb, 0, sizeof(struct framebuffer)); +#ifndef MR_DEVICE_HAS_DRM_GRAPHICS fb.fd = open("/dev/graphics/fb0", O_RDWR | O_CLOEXEC); if (fb.fd < 0) return -1; @@ -174,6 +179,11 @@ int fb_open(int rotation) fb.stride = (fb_rotation%180 == 0) ? fb.vi.xres_virtual : fb.vi.yres; fb.size = fb.vi.xres_virtual*fb.vi.yres*PIXEL_SIZE; +#else + if(fb_open_impl() < 0) + goto fail; +#endif + fb.buffer = malloc(fb.size); fb_memset(fb.buffer, fb_convert_color(BLACK), fb.size); @@ -615,12 +625,9 @@ void fb_draw_rect(fb_rect *r) if(alpha == 0) return; -#if defined(RECOVERY_RGBX) || (RECOVERY_RGBA) || defined(RECOVERY_ABGR) +#if defined(RECOVERY_RGBX) || (RECOVERY_RGBA) || defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) const uint32_t premult_color_rb = ((color & 0xFF00FF) * (alpha)) >> 8; const uint32_t premult_color_g = ((color & 0x00FF00) * (alpha)) >> 8; -#elif defined(RECOVERY_BGRA) - const uint32_t premult_color_rb = (((color >> 8) & 0xFF00FF) * (alpha)) >> 8; - const uint32_t premult_color_g = (((color >> 8) & 0x00FF00) * (alpha)) >> 8; #elif defined(RECOVERY_RGB_565) const uint8_t alpha5b = (alpha >> 3) + 1; const uint8_t alpha6b = (alpha >> 2) + 1; @@ -660,14 +667,10 @@ void fb_draw_rect(fb_rect *r) #else for(x = 0; x < rendered_w; ++x) { - #if defined(RECOVERY_RGBX) || defined(RECOVERY_RGBA) || defined(RECOVERY_ABGR) + #if defined(RECOVERY_RGBX) || defined(RECOVERY_RGBA) || defined(RECOVERY_ABGR) || defined(RECOVERY_BGRA) const uint32_t rb = (premult_color_rb & 0xFF00FF) + ((inv_alpha * (*bits & 0xFF00FF)) >> 8); const uint32_t g = (premult_color_g & 0x00FF00) + ((inv_alpha * (*bits & 0x00FF00)) >> 8); *bits = 0xFF000000 | (rb & 0xFF00FF) | (g & 0x00FF00); - #elif defined(RECOVERY_BGRA) - const uint32_t rb = (premult_color_rb & 0xFF00FF) + ((inv_alpha * ((*bits >> 8) & 0xFF00FF)) >> 8); - const uint32_t g = (premult_color_g & 0x00FF00) + ((inv_alpha * ((*bits >> 8) & 0x00FF00)) >> 8); - *bits = 0xFF000000 | (rb & 0xFF00FF) | (g & 0x00FF00); #elif defined(RECOVERY_RGB_565) const uint16_t rb = (premult_color_rb & 0xF81F) + ((inv_alpha5b * (*bits & 0xF81F)) >> 5); const uint16_t g = (premult_color_g & 0x7E0) + ((inv_alpha6b * (*bits & 0x7E0)) >> 6); diff --git a/lib/framebuffer.h b/lib/framebuffer.h index f96e5bb6..544f482e 100644 --- a/lib/framebuffer.h +++ b/lib/framebuffer.h @@ -102,6 +102,9 @@ enum #ifdef MR_USE_QCOM_OVERLAY FB_IMPL_QCOM_OVERLAY, #endif +#ifdef MR_DEVICE_HAS_DRM_GRAPHICS + FB_IMPL_DRM, +#endif FB_IMPL_GENERIC, // must be last From f03df6b6f2319b947c478572bb828848cce63629 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 3 Nov 2018 17:20:39 +0530 Subject: [PATCH 38/65] Fixes to get magisk root working on secondary rom --- multirom.c | 36 ++++++++++++++++++++++-------------- 1 file changed, 22 insertions(+), 14 deletions(-) diff --git a/multirom.c b/multirom.c index ed7c896d..359242c5 100644 --- a/multirom.c +++ b/multirom.c @@ -112,17 +112,11 @@ void disable_dtb_fstab(char* partition) { } void remove_dtb_fstab() { - if (access("compatible", F_OK)) { - FILE* fp = fopen("compatible", "w"); - fprintf(fp, "android"); - fclose(fp); - } - char mnt_pt[strlen(DT_FSTAB_PATH) + strlen("/compatible") + 1]; - sprintf(mnt_pt, "%s/compatible", DT_FSTAB_PATH); - if (!mount("/compatible", mnt_pt, "ext4", MS_BIND, "discard,nomblk_io_submit")) { - INFO("compatible node bind mounted in procfs\n"); + mkdir("/dummy_fw", S_IFDIR); + if (!mount("/dummy_fw", "/proc/device-tree/firmware", "ext4", MS_BIND, "discard,nomblk_io_submit")) { + INFO("dummy dtb node bind mounted in procfs\n"); } else { - ERROR("compatible node bind mount failed! %s\n", strerror(errno)); + ERROR("dummy dtb node bind mount failed! %s\n", strerror(errno)); } } @@ -1615,6 +1609,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom sprintf(path, "%s/boot", rom->base_path); DIR *d = opendir(path); + char* prefix = NULL; if(!d) { ERROR("Failed to open rom path %s\n", path); @@ -1625,11 +1620,23 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom while((dp = readdir(d))) { - if(dp->d_name[0] == '.' && (dp->d_name[1] == '.' || dp->d_name[1] == 0)) + if((dp->d_name[0] == '.' && strlen(dp->d_name) == 1) || (dp->d_name[0] == '.' && (dp->d_name[1] == '.') || dp->d_name[1] == 0)) continue; - sprintf(in, "%s/%s", path, dp->d_name); - sprintf(out, "/%s", dp->d_name); + if (dp->d_type == DT_DIR) { + sprintf(in, "%s/%s", path, dp->d_name); + d = opendir(in); + prefix = dp->d_name; + continue; + } + + if (prefix) { + sprintf(out, "/%s/%s", prefix, dp->d_name); + sprintf(in, "%s/%s/%s", path, prefix, dp->d_name); + } else { + sprintf(in, "%s/%s", path, dp->d_name); + sprintf(out, "/%s", dp->d_name); + } copy_file(in, out); @@ -1716,7 +1723,8 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom } if((multirom_path_exists("/system", "vendor/etc") == -1) && - (multirom_path_exists(rom->base_path, "vendor/etc") == -1)) { + (multirom_path_exists(rom->base_path, "vendor/etc") == -1) && + (multirom_path_exists("/", "vendor/etc") == -1)) { if (!access(DT_FSTAB_PATH, F_OK)) { mount_dtb_fstab("vendor"); } From fd84b407d114f30fe29d0e0f171ddae86af11827 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Mon, 5 Nov 2018 00:25:11 +0530 Subject: [PATCH 39/65] Add fake property_set function Devices which want to use it can setup a socket named "/property_socket" and poll for their desired property --- trampoline_encmnt/Android.mk | 1 + trampoline_encmnt/fake_properties.c | 42 +++++++++++++++++++++++++++++ 2 files changed, 43 insertions(+) diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index 61e50f72..ed06c516 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -50,6 +50,7 @@ ifeq ($(MR_ENCRYPTION_FAKE_PROPERTIES),true) LOCAL_C_INCLUDES += $(multirom_local_path) LOCAL_SRC_FILES := fake_properties.c + LOCAL_SHARED_LIBRARIES := liblog ifneq ($(MR_ENCRYPTION_FAKE_PROPERTIES_EXTRAS),) LOCAL_CFLAGS += -DMR_ENCRYPTION_FAKE_PROPERTIES_EXTRAS diff --git a/trampoline_encmnt/fake_properties.c b/trampoline_encmnt/fake_properties.c index 012c2572..a55fa92a 100644 --- a/trampoline_encmnt/fake_properties.c +++ b/trampoline_encmnt/fake_properties.c @@ -17,7 +17,13 @@ #include #include #include +#include +#include +#include +#include +#include +#define PROPERTY_SOCKET "/property_socket" /* MultiROM doesn't initialize the property service, * but decryption on Nexus 6P waits for one property to become true * so we hardcode it here @@ -67,3 +73,39 @@ int property_get(const char *key, char *value, const char *default_value) strncpy(value, default_value, PROP_VALUE_MAX); return strlen(value); } + +int property_set(char* property, char* value) { + + char* property_value; + int i, s, len; + struct sockaddr_un saun; + + ALOGE("property_set called for %s:%s\n", property, value); + property_value = calloc(strlen(property) + strlen(value) + 1, 1); + + sprintf(property_value, "%s:%s", property, value); + /* + * Get a socket to work with. This socket will + * be in the UNIX domain, and will be a + * datagram socket. + */ + if ((s = socket(AF_UNIX, SOCK_DGRAM, 0)) < 0) { + ALOGE("client: socket"); + } + + /* + * Create the address we will be connecting to. + */ + saun.sun_family = AF_UNIX; + strcpy(saun.sun_path, PROPERTY_SOCKET); + len = sizeof(saun.sun_family) + strlen(saun.sun_path); + + if (sendto(s, property_value, strlen(property_value), 0, &saun, sizeof(struct sockaddr_un)) < 0) { + ALOGE("sendto failed %s\n", strerror(errno)); + } + + free(property_value); + + close(s); + return 0; +} From d39ae6e2bc0ad6c2bc95bdb09309de596e766fab Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Mon, 5 Nov 2018 00:28:51 +0530 Subject: [PATCH 40/65] Dont make permanent injection to secondary boot image Makes magisk flashing a breeze --- no_kexec.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/no_kexec.c b/no_kexec.c index ee82dd2f..6aa684d6 100644 --- a/no_kexec.c +++ b/no_kexec.c @@ -197,11 +197,13 @@ int nokexec_backup_primary(void) int nokexec_flash_to_primary(const char * source) { int res = 0; + char* temp_boot = "/secondary_boot.img"; // check trampoline no_kexec version and update if needed + copy_file(source, temp_boot); struct boot_img_hdr hdr; - if (libbootimg_load_header(&hdr, source) < 0) + if (libbootimg_load_header(&hdr, temp_boot) < 0) { ERROR(NO_KEXEC_LOG_TEXT ": Could not open boot image (%s)!\n", nokexec_s.path_boot_mmcblk); res = -1; @@ -216,7 +218,7 @@ int nokexec_flash_to_primary(const char * source) { // Trampolines in ROM boot images may get out of sync, so we need to check it and // update if needed. I can't do that during ZIP installation because of USB drives. - if(inject_bootimg(source, 1) < 0) + if(inject_bootimg(temp_boot, 1) < 0) { ERROR(NO_KEXEC_LOG_TEXT ": Failed to inject bootimg!\n"); res = -1; @@ -227,7 +229,7 @@ int nokexec_flash_to_primary(const char * source) } if (res == 0) - INFO(NO_KEXEC_LOG_TEXT ": flashing '%s' to boot partition; res=%d\n", source, res = copy_file(source, nokexec_s.path_boot_mmcblk)); + INFO(NO_KEXEC_LOG_TEXT ": flashing '%s' to boot partition; res=%d\n", temp_boot, res = copy_file(temp_boot, nokexec_s.path_boot_mmcblk)); return res; } From 8589905b3579d4632ff6fb1716a8c85da4d9b623 Mon Sep 17 00:00:00 2001 From: shahan-mik3 Date: Thu, 8 Nov 2018 13:53:35 +0530 Subject: [PATCH 41/65] Use scaled brightness --- device_defines.mk | 6 ++++++ lib/framebuffer.c | 1 + 2 files changed, 7 insertions(+) diff --git a/device_defines.mk b/device_defines.mk index 77e8596b..c29157b5 100644 --- a/device_defines.mk +++ b/device_defines.mk @@ -87,6 +87,12 @@ else LOCAL_CFLAGS += -DMULTIROM_DEFAULT_BRIGHTNESS=40 endif +ifneq ($(TW_MAX_BRIGHTNESS),) + LOCAL_CFLAGS += -DTW_MAX_BRIGHTNESS=\"$(TW_MAX_BRIGHTNESS)\" +else + LOCAL_CFLAGS += -DTW_MAX_BRIGHTNESS=255 +endif + ifneq ($(MR_INPUT_ROTATION),) LOCAL_CFLAGS += -DMR_INPUT_ROTATION=$(MR_INPUT_ROTATION) endif diff --git a/lib/framebuffer.c b/lib/framebuffer.c index 5d54b4be..48215499 100644 --- a/lib/framebuffer.c +++ b/lib/framebuffer.c @@ -258,6 +258,7 @@ void fb_dump_info(void) void fb_set_brightness(int val) { + val = (val/255) * atoi(TW_MAX_BRIGHTNESS); #ifdef TW_BRIGHTNESS_PATH FILE *f = fopen(TW_BRIGHTNESS_PATH, "we"); if(!f) From 820621ae05ce4f0070d0c162e386dd9f8b6f680e Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Tue, 13 Nov 2018 22:18:59 +0530 Subject: [PATCH 42/65] Use existing loop nodes if kernel can't create new --- lib/util.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/lib/util.c b/lib/util.c index da31373f..4dfa3b6d 100644 --- a/lib/util.c +++ b/lib/util.c @@ -843,8 +843,9 @@ int multirom_mount_image(const char *src, const char *dst, const char *fs, int f mkdir_recursive_with_perms(MULTIROM_DEV_PATH, 0777, NULL, NULL); sprintf(path, MULTIROM_DEV_PATH "/%s", dst); +create_loop: if(create_loop_device(path, src, loop_num, 0777) < 0) - return -1; + res = -1; // never reuse an existing loop next_loop_num = loop_num + 1; @@ -854,6 +855,13 @@ int multirom_mount_image(const char *src, const char *dst, const char *fs, int f else res = 0; + if(res) { + if (loop_num == MULTIROM_LOOP_NUM_START) + loop_num = 0; + sprintf(path, "/dev/block/loop%d", loop_num); + goto create_loop; + } + sync(); return res; From 8ba28ad8f39ac97ba2cf3d177ab5fadb8e0a6925 Mon Sep 17 00:00:00 2001 From: shahan-mik3 Date: Tue, 13 Nov 2018 22:26:22 +0530 Subject: [PATCH 43/65] Add custom firmware mount point Set MR_FIRMWARE_DIR in BoardConfig. Set to /firmware by default --- Android.mk | 6 ++++++ multirom.c | 2 +- 2 files changed, 7 insertions(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index f3ee86cc..eb75ffdb 100644 --- a/Android.mk +++ b/Android.mk @@ -40,6 +40,12 @@ LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static LOCAL_WHOLE_STATIC_LIBRARIES := libm libcutils libpng libz libft2_mrom_static +ifeq ($(MR_FIRMWARE_DIR),) + LOCAL_CFLAGS += -DMR_FIRMWARE_DIR="/firmware" +else + LOCAL_CFLAGS += -DMR_FIRMWARE_DIR=$(MR_FIRMWARE_DIR) +endif + # clone libbootimg to /system/extras/ from # https://github.com/Tasssadar/libbootimg.git LOCAL_STATIC_LIBRARIES += libbootimg diff --git a/multirom.c b/multirom.c index 359242c5..21c93ab9 100644 --- a/multirom.c +++ b/multirom.c @@ -1862,7 +1862,7 @@ int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_pa if(has_fw) { - struct fstab_part *p = fstab_find_first_by_path(tab, "/firmware"); + struct fstab_part *p = fstab_find_first_by_path(tab, MR_FIRMWARE_DIR); if(p) { *fw_part = fstab_clone_part(p); From 72c747b0389bd9cf0a627fbed375431f59aa9027 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 5 Dec 2018 05:47:27 +0000 Subject: [PATCH 44/65] Fix compile error --- Android.mk | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Android.mk b/Android.mk index eb75ffdb..17de220b 100644 --- a/Android.mk +++ b/Android.mk @@ -43,7 +43,7 @@ LOCAL_WHOLE_STATIC_LIBRARIES := libm libcutils libpng libz libft2_mrom_static ifeq ($(MR_FIRMWARE_DIR),) LOCAL_CFLAGS += -DMR_FIRMWARE_DIR="/firmware" else - LOCAL_CFLAGS += -DMR_FIRMWARE_DIR=$(MR_FIRMWARE_DIR) + LOCAL_CFLAGS += -DMR_FIRMWARE_DIR="\"$(MR_FIRMWARE_DIR)\"" endif # clone libbootimg to /system/extras/ from From 035ab9517b183121cef3f65a6559658e7e61706f Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 5 Dec 2018 05:47:47 +0000 Subject: [PATCH 45/65] drm: Remove screen blanking code --- lib/drm.c | 4 ---- 1 file changed, 4 deletions(-) diff --git a/lib/drm.c b/lib/drm.c index aa35baff..9a062b2e 100644 --- a/lib/drm.c +++ b/lib/drm.c @@ -553,10 +553,6 @@ static int drm_init(struct framebuffer *fb) { drm_enable_crtc(drm_fd, main_monitor_crtc, drm_surfaces[1]); -#ifdef TW_SCREEN_BLANK_ON_BOOT - drm_blank(true, 1); - drm_blank(false, 1); -#endif current_buffer = 0; return 0; From 49d010ecd84d087057244f6d20f11ec4f4abf0cf Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Tue, 11 Dec 2018 12:00:06 +0000 Subject: [PATCH 46/65] Add support for flashing older version secondary ROM Patch secondary ROM bootimg and build.prop systemless-ly to allow secondary ROM to boot even when it is using older android version and/or security patch with encryption enabled. --- multirom.c | 2 + no_kexec.c | 46 +++++++++++++ rom_quirks.c | 122 +++++++++++++++++++++++++++++++++++ rom_quirks.h | 1 + trampoline_encmnt/Android.mk | 1 + 5 files changed, 172 insertions(+) diff --git a/multirom.c b/multirom.c index 21c93ab9..199a60dd 100644 --- a/multirom.c +++ b/multirom.c @@ -1493,6 +1493,8 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to rom_quirks_on_initrd_finalized(); + rom_quirks_change_patch_and_osver(); + rcadditions_write_to_files(&s->rc); rcadditions_free(&s->rc); } diff --git a/no_kexec.c b/no_kexec.c index 6aa684d6..a2153c58 100644 --- a/no_kexec.c +++ b/no_kexec.c @@ -185,6 +185,48 @@ int nokexec_set_secondary_flag(void) return res; } +int nokexec_set_oslevel(char *secondary_path) +{ + int res = -1; + struct bootimg primary_img, secondary_img; + + INFO(NO_KEXEC_LOG_TEXT ": Going to check the bootimg in primary slot for slevel\n"); + + if (libbootimg_init_load(&primary_img, nokexec_s.path_boot_mmcblk, LIBBOOTIMG_LOAD_ALL) < 0) + { + ERROR(NO_KEXEC_LOG_TEXT ": Could not open boot image (%s)!\n", nokexec_s.path_boot_mmcblk); + return -1; + } + + if (libbootimg_init_load(&secondary_img, secondary_path, LIBBOOTIMG_LOAD_ALL) < 0) + { + ERROR(NO_KEXEC_LOG_TEXT ": Could not open boot image (%s)!\n", nokexec_s.path_boot_mmcblk); + return -1; + } + + char* primary_os_version = libbootimg_get_osversion(&primary_img.hdr, true); + char* primary_os_level = libbootimg_get_oslevel(&primary_img.hdr, true); + + char* secondary_os_version = libbootimg_get_osversion(&secondary_img.hdr, true); + char* secondary_os_level = libbootimg_get_oslevel(&secondary_img.hdr, true); + + if (strtol(primary_os_level, NULL, 10) > strtol(secondary_os_level, NULL, 10) || strtol(primary_os_version, NULL, 10) > strtol(secondary_os_version, NULL, 10)) { + secondary_img.hdr.oslevel = primary_img.hdr.oslevel; + } + + INFO(NO_KEXEC_LOG_TEXT ": Writing boot.img updated with new security patch\n"); + if (libbootimg_write_img(&secondary_img, secondary_path) < 0) + { + ERROR("Failed to libbootimg_write_img!\n"); + } + else + res = 0; + + libbootimg_destroy(&primary_img); + libbootimg_destroy(&secondary_img); + return res; +} + int nokexec_backup_primary(void) { int res; @@ -323,6 +365,10 @@ int nokexec_flash_secondary_bootimg(struct multirom_rom *secondary_rom) // now flash the secondary boot.img to primary slot char path_bootimg[256]; sprintf(path_bootimg, "%s/%s", secondary_rom->base_path, "boot.img"); + + if (nokexec_set_oslevel(path_bootimg)) + return -3; + if (nokexec_flash_to_primary(path_bootimg)) return -3; diff --git a/rom_quirks.c b/rom_quirks.c index 63f0a812..c0f0bf8a 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -20,6 +20,8 @@ #include #include #include +#include +#include #include #include #include @@ -31,6 +33,7 @@ #include "rq_inject_file_contexts.h" #include "lib/log.h" #include "lib/util.h" +#include "libbootimg.h" static void workaround_mount_in_sh(const char *path) { @@ -208,3 +211,122 @@ void rom_quirks_on_initrd_finalized(void) if (failed_file_contexts_injections) disable_restorecon_recursive(); } + +char* convert_to_raw(char* str) { + char* temp = malloc(strlen(str)); + char* temp2 = temp; + char* out = calloc(1, strlen(str)); + int i = 0, j = 0; + + while (str[j] != '\n') { + j++; + } + + char* token; + strcpy(temp, str); + temp[j] = '\0'; + if (strstr(temp, ".")) { + while (token = strsep(&temp, ".")) { + strcpy(out + i, token); + i += strlen(token); + } + } else if(strstr(temp, "-")) { + while (token = strsep(&temp, "-")) { + strcpy(out + i, token); + i += strlen(token); + } + } else { + strcpy(out, temp); + } + free(temp2); + return out; +} + +void rom_quirks_change_patch_and_osver() { + + char* path = "/system/build.prop"; + struct bootimg primary_img; + char* patchstring = NULL, *stringtoappend = NULL; + char* existing_ver = NULL; + char* existing_level = NULL; + int sourcefile, destfile, n; + + if (libbootimg_init_load(&primary_img, "/dev/block/bootdevice/by-name/boot", LIBBOOTIMG_LOAD_ALL) < 0) + { + return; + } + libbootimg_destroy(&primary_img); + + char* primary_os_version = libbootimg_get_osversion(&primary_img.hdr, false); + char* primary_os_level = libbootimg_get_oslevel(&primary_img.hdr, false); + + char* primary_os_ver_raw = libbootimg_get_osversion(&primary_img.hdr, true); + char* primary_os_level_raw = libbootimg_get_oslevel(&primary_img.hdr, true); + + sourcefile = open(path, O_RDONLY, 0644); + + if (sourcefile == -1) { + ERROR("open failed! %s\n", strerror(errno)); + } + + struct stat stats; + int status; + int size; + + status = stat(path, &stats); + if(status == 0) { + size = stats.st_size; + } + + asprintf(&patchstring, "%s=%s\n%s=%s", "ro.build.version.security_patch", primary_os_level, "ro.build.version.release", primary_os_version); + char* filebuf = calloc(1, size + strlen(patchstring)); + + + n = read(sourcefile, filebuf, size); + if (n == -1) { + ERROR("read failed! %s\n", strerror(errno)); + } + close(sourcefile); + + existing_level = strstr(filebuf, "ro.build.version.security_patch"); + existing_level += strlen("ro.build.version.security_patch="); + + existing_ver = strstr(filebuf, "ro.build.version.release"); + existing_ver += strlen("ro.build.version.release="); + + char* existing_level_raw = convert_to_raw(existing_level); + char* existing_ver_raw = convert_to_raw(existing_ver); + + if (strtol(primary_os_ver_raw, NULL, 10) > strtol(existing_ver_raw, NULL, 10) || strtol(primary_os_level_raw, NULL, 10) > strtol(existing_level_raw, NULL, 10)) { + + existing_level = strstr(filebuf, "ro.build.version.security_patch"); + + int i = 0; + while (existing_level[i] != '\n') { + i++; + } + existing_level += i; + asprintf(&stringtoappend, "%s%s", patchstring, existing_level); + + existing_ver = strstr(filebuf, "ro.build.version.release"); + memcpy(existing_ver, stringtoappend, strlen(stringtoappend)); + + destfile = open("/build.prop", O_RDWR | O_CREAT, 0644); + write(destfile, filebuf, strlen(filebuf)); + close(destfile); + + + if (!access(path, F_OK)) { + if(!mount("/build.prop", path, "ext4", MS_BIND, "discard,nomblk_io_submit")) { + INFO("build.prop bind mounted in system\n"); + } else { + ERROR("build.prop bind mount failed! %s\n", strerror(errno)); + } + } + } + free(existing_level_raw); + free(existing_ver_raw); + free(patchstring); + free(stringtoappend); + free(filebuf); +} diff --git a/rom_quirks.h b/rom_quirks.h index 820e6290..5e311490 100644 --- a/rom_quirks.h +++ b/rom_quirks.h @@ -20,5 +20,6 @@ struct multirom_rom; void rom_quirks_on_initrd_finalized(void); +void rom_quirks_change_patch_and_osver(); #endif diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index ed06c516..3d85a612 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -30,6 +30,7 @@ else endif LOCAL_C_INCLUDES += $(multirom_local_path) $(mr_twrp_path) $(mr_twrp_path)/crypto/scrypt/lib/crypto external/openssl/include external/boringssl/include +LOCAL_C_INCLUDES += system/extras/libbootimg/include LOCAL_SRC_FILES := \ encmnt.cpp \ From 41e8156c988c8de9e6e81661e42fe47bccf81540 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Tue, 11 Dec 2018 18:22:27 +0000 Subject: [PATCH 47/65] Fix derp that caused bootloops --- rom_quirks.c | 9 ++++++--- 1 file changed, 6 insertions(+), 3 deletions(-) diff --git a/rom_quirks.c b/rom_quirks.c index c0f0bf8a..1ce2e6c0 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -215,7 +215,7 @@ void rom_quirks_on_initrd_finalized(void) char* convert_to_raw(char* str) { char* temp = malloc(strlen(str)); char* temp2 = temp; - char* out = calloc(1, strlen(str)); + char* out = calloc(1, strlen(str) + 2); int i = 0, j = 0; while (str[j] != '\n') { @@ -236,6 +236,7 @@ char* convert_to_raw(char* str) { i += strlen(token); } } else { + strcat(temp, "00"); strcpy(out, temp); } free(temp2); @@ -255,13 +256,13 @@ void rom_quirks_change_patch_and_osver() { { return; } - libbootimg_destroy(&primary_img); char* primary_os_version = libbootimg_get_osversion(&primary_img.hdr, false); char* primary_os_level = libbootimg_get_oslevel(&primary_img.hdr, false); char* primary_os_ver_raw = libbootimg_get_osversion(&primary_img.hdr, true); char* primary_os_level_raw = libbootimg_get_oslevel(&primary_img.hdr, true); + libbootimg_destroy(&primary_img); sourcefile = open(path, O_RDONLY, 0644); @@ -327,6 +328,8 @@ void rom_quirks_change_patch_and_osver() { free(existing_level_raw); free(existing_ver_raw); free(patchstring); - free(stringtoappend); + if (stringtoappend) { + free(stringtoappend); + } free(filebuf); } From 1bd7f331c99a6db54a9e8a0129fe8fcb321d6e67 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 5 May 2019 15:53:36 +0000 Subject: [PATCH 48/65] Add a couple of new features:- * System as root support * Android Q support * Support selinux * Support booting into second rom without a second reboot --- Android.mk | 3 +- lib/Android.mk | 1 + lib/inject.c | 201 ++++++++++++++++---------- lib/inject.h | 4 + lib/util.c | 161 +++++++++++++++++++++ lib/util.h | 12 ++ multirom.c | 303 ++++++++++++++++++++++++++++++---------- multirom.h | 1 + no_kexec.c | 29 ++++ trampoline/Android.mk | 2 +- trampoline/trampoline.c | 169 +++++++++++++++++++++- 11 files changed, 737 insertions(+), 149 deletions(-) diff --git a/Android.mk b/Android.mk index 17de220b..3c3382de 100644 --- a/Android.mk +++ b/Android.mk @@ -9,6 +9,7 @@ LOCAL_C_INCLUDES += $(multirom_local_path) \ external/libpng \ external/zlib \ external/freetype/include \ + external/selinux/libselinux/include \ $(multirom_local_path)/lib LOCAL_SRC_FILES:= \ @@ -37,7 +38,7 @@ LOCAL_FORCE_STATIC_EXECUTABLE := true LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) -LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static +LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static libselinux LOCAL_WHOLE_STATIC_LIBRARIES := libm libcutils libpng libz libft2_mrom_static ifeq ($(MR_FIRMWARE_DIR),) diff --git a/lib/Android.mk b/lib/Android.mk index c7d56d27..532fc400 100644 --- a/lib/Android.mk +++ b/lib/Android.mk @@ -27,6 +27,7 @@ common_C_INCLUDES := $(multirom_local_path)/lib \ external/libpng \ external/zlib \ external/freetype/include \ + external/selinux/libselinux/include \ system/extras/libbootimg/include \ # With these, GCC optimizes aggressively enough so full-screen alpha blending diff --git a/lib/inject.c b/lib/inject.c index 73189c78..7c4c0a7d 100644 --- a/lib/inject.c +++ b/lib/inject.c @@ -50,7 +50,7 @@ static int get_img_trampoline_ver(struct bootimg *img) return ver; } -static int copy_rd_files(UNUSED const char *path, UNUSED const char *busybox_path) +static int copy_rd_files(UNUSED const char *path, const char *target) { char buf[256]; char path_dir[64]; @@ -63,34 +63,21 @@ static int copy_rd_files(UNUSED const char *path, UNUSED const char *busybox_pat char path_ueventd[64]; char path_watchdog[64]; - if (access(TMP_RD2, F_OK) != -1) - { - snprintf(path_dir, sizeof(path_dir), TMP_RD2_UNPACKED_DIR); - snprintf(path_init, sizeof(path_init), TMP_RD2_UNPACKED_DIR "/init"); - snprintf(path_main, sizeof(path_main), TMP_RD2_UNPACKED_DIR "/main_init"); - snprintf(path_mrom_enc, sizeof(path_mrom_enc), TMP_RD2_UNPACKED_DIR "/mrom_enc"); - snprintf(path_mrom_fstab, sizeof(path_mrom_fstab), TMP_RD2_UNPACKED_DIR "/mrom.fstab"); - snprintf(path_hwservice_contexts, sizeof(path_hwservice_contexts), TMP_RD2_UNPACKED_DIR "/plat_hwservice_contexts"); - snprintf(path_nonplat_hwservice_contexts, sizeof(path_nonplat_hwservice_contexts), TMP_RD2_UNPACKED_DIR "/nonplat_hwservice_contexts"); - snprintf(path_ueventd, sizeof(path_ueventd), TMP_RD2_UNPACKED_DIR "/sbin/ueventd"); - snprintf(path_watchdog, sizeof(path_watchdog), TMP_RD2_UNPACKED_DIR "/sbin/watchdogd"); - } - else - { - snprintf(path_dir, sizeof(path_dir), TMP_RD_UNPACKED_DIR); - if (access(TMP_RD_UNPACKED_DIR "/init.real", F_OK) != -1) { - snprintf(path_init, sizeof(path_init), TMP_RD_UNPACKED_DIR "/init.real"); - } else { - snprintf(path_init, sizeof(path_init), TMP_RD_UNPACKED_DIR "/init"); - } - snprintf(path_main, sizeof(path_main), TMP_RD_UNPACKED_DIR "/main_init"); - snprintf(path_mrom_enc, sizeof(path_mrom_enc), TMP_RD_UNPACKED_DIR "/mrom_enc"); - snprintf(path_mrom_fstab, sizeof(path_mrom_fstab), TMP_RD_UNPACKED_DIR "/mrom.fstab"); - snprintf(path_hwservice_contexts, sizeof(path_hwservice_contexts), TMP_RD_UNPACKED_DIR "/plat_hwservice_contexts"); - snprintf(path_nonplat_hwservice_contexts, sizeof(path_nonplat_hwservice_contexts), TMP_RD_UNPACKED_DIR "/nonplat_hwservice_contexts"); - snprintf(path_ueventd, sizeof(path_ueventd), TMP_RD_UNPACKED_DIR "/sbin/ueventd"); - snprintf(path_watchdog, sizeof(path_watchdog), TMP_RD_UNPACKED_DIR "/sbin/watchdogd"); + + snprintf(path_dir, sizeof(path_dir), "%s", target); + snprintf(path_init, sizeof(path_init), "%s%s", target, "/init.real"); + if (access(path_init, F_OK) != -1) { + snprintf(path_init, sizeof(path_init), "%s%s", target, "/init.real"); + } else { + snprintf(path_init, sizeof(path_init), "%s%s", target, "/init"); } + snprintf(path_main, sizeof(path_main), "%s%s", target, "/main_init"); + snprintf(path_mrom_enc, sizeof(path_mrom_enc), "%s%s", target, "/mrom_enc"); + snprintf(path_mrom_fstab, sizeof(path_mrom_fstab), "%s%s", target, "/mrom.fstab"); + snprintf(path_hwservice_contexts, sizeof(path_hwservice_contexts), "%s%s", target, "/plat_hwservice_contexts"); + snprintf(path_nonplat_hwservice_contexts, sizeof(path_nonplat_hwservice_contexts), "%s%s", target, "/nonplat_hwservice_contexts"); + snprintf(path_ueventd, sizeof(path_ueventd), "%s%s", target, "/sbin/ueventd"); + snprintf(path_watchdog, sizeof(path_watchdog), "%s%s", target, "/sbin/watchdogd"); if (access(path_main, F_OK) < 0 && rename(path_init, path_main)) @@ -136,21 +123,13 @@ static int copy_rd_files(UNUSED const char *path, UNUSED const char *busybox_pat #define RD_GZIP 1 #define RD_LZ4 2 -static int inject_second_rd(const char *path, const char *second_path) -{ - int result = -1; - uint32_t magic = 0; - FILE *f = fopen(path, "re"); - if(!f) - { - ERROR("Couldn't open %s!\n", path); - return -1; - } - fread(&magic, sizeof(magic), 1, f); - fclose(f); +int decompress_second_rd(const char* target, const char *second_path) { + int result = -1; - mkdir(TMP_RD2_UNPACKED_DIR, 0755); + char second_unpacked_dir[256]; + sprintf(second_unpacked_dir, "%s/%s", target, "second"); + mkdir(second_unpacked_dir, 0755); // Decompress initrd int type; @@ -158,10 +137,10 @@ static int inject_second_rd(const char *path, const char *second_path) char busybox_path[256]; snprintf(busybox_path, sizeof(busybox_path), "%s/busybox", mrom_dir()); - char *cmd[] = { busybox_path, "sh", "-c", buff, NULL }; - snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" cat \"%s\" | \"$B\" cpio -i", busybox_path, TMP_RD2_UNPACKED_DIR, second_path); + snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" cat \"%s\" | \"$B\" cpio -i", busybox_path, second_unpacked_dir, second_path); + char *cmd[] = { busybox_path, "sh", "-c", buff, NULL }; int r; char *out = run_get_stdout_with_exit(cmd, &r); if (r != 0) @@ -169,33 +148,48 @@ static int inject_second_rd(const char *path, const char *second_path) ERROR("Output: %s\n", out); ERROR("Failed to unpack second ramdisk!%s\n", buff); goto fail; + } else { + return 0; } +fail: + remove_dir(second_unpacked_dir); + return result; +} - // Update files - if (copy_rd_files(second_path, busybox_path) < 0) - { - goto fail; - } +int pack_second_rd(const char *second_path, const char* unpacked_dir) { + int result = -1; + char second_unpacked_dir[256]; + sprintf(second_unpacked_dir, "%s/%s", unpacked_dir, "second"); // Pack initrd again - snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc > \"%s\"", busybox_path, TMP_RD2_UNPACKED_DIR, second_path); + char buff[256]; + char busybox_path[256]; + snprintf(busybox_path, sizeof(busybox_path), "%s/busybox", mrom_dir()); + snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc > \"%s\"", busybox_path, second_unpacked_dir, second_path); - out = run_get_stdout_with_exit(cmd, &r); + char *cmd[] = { busybox_path, "sh", "-c", buff, NULL }; + int r; + char *out = run_get_stdout_with_exit(cmd, &r); if (r != 0) { ERROR("Output: %s\n", out); ERROR("Failed to pack ramdisk.cpio!\n"); goto fail; + } else { + return 0; } success: result = 0; fail: - remove_dir(TMP_RD2_UNPACKED_DIR); + remove_dir(second_unpacked_dir); return result; + } -static int inject_rd(const char *path, const char *second_path) -{ + + +int decompress_rd(const char *path, const char* target, int* type) { + int result = -1; uint32_t magic = 0; @@ -208,26 +202,24 @@ static int inject_rd(const char *path, const char *second_path) fread(&magic, sizeof(magic), 1, f); fclose(f); - remove_dir(TMP_RD_UNPACKED_DIR); - mkdir(TMP_RD_UNPACKED_DIR, 0755); + remove_dir(target); + mkdir(target, 0755); // Decompress initrd - int type; char buff[256]; char busybox_path[256]; snprintf(busybox_path, sizeof(busybox_path), "%s/busybox", mrom_dir()); - char *cmd[] = { busybox_path, "sh", "-c", buff, NULL }; if((magic & 0xFFFF) == 0x8B1F) { - type = RD_GZIP; - snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" gzip -d -c \"%s\" | \"$B\" cpio -i", busybox_path, TMP_RD_UNPACKED_DIR, path); + *type = RD_GZIP; + snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" gzip -d -c \"%s\" | \"$B\" cpio -i", busybox_path, target, path); } else if(magic == 0x184C2102) { - type = RD_LZ4; - snprintf(buff, sizeof(buff), "cd \"%s\"; \"%s/lz4\" -d \"%s\" stdout | \"%s\" cpio -i", TMP_RD_UNPACKED_DIR, mrom_dir(), path, busybox_path); + *type = RD_LZ4; + snprintf(buff, sizeof(buff), "cd \"%s\"; \"%s/lz4\" -d \"%s\" stdout | \"%s\" cpio -i", target, mrom_dir(), path, busybox_path); } else { @@ -235,6 +227,7 @@ static int inject_rd(const char *path, const char *second_path) goto success; } + char *cmd[] = { busybox_path, "sh", "-c", buff, NULL }; int r = run_cmd(cmd); if(r != 0) { @@ -242,43 +235,111 @@ static int inject_rd(const char *path, const char *second_path) goto fail; } - if (access(TMP_RD2, F_OK) != -1) + char second_path[256]; + sprintf(second_path, "%s/%s", target, "sbin/ramdisk.cpio"); + if (access(second_path, F_OK) != -1) { - if (inject_second_rd(path, second_path) < 0) + if (decompress_second_rd(target, second_path) < 0) { goto fail; + } else { + return 0; } + } else { + return 0; } - else if (copy_rd_files(path, busybox_path) < 0) +success: + result = 0; +fail: + remove_dir(target); + return result; +} + +int pack_rd(const char *path, const char *target, int type) { + + // Pack ramdisk + char second_path[256]; + sprintf(second_path, "%s/%s", target, "sbin/ramdisk.cpio"); + if (access(second_path, F_OK) != -1) { - goto fail; + pack_second_rd(second_path, target); } - // Pack ramdisk + char buff[256]; + char busybox_path[256]; + snprintf(busybox_path, sizeof(busybox_path), "%s/busybox", mrom_dir()); switch (type) { case RD_GZIP: - snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc | \"$B\" gzip > \"%s\"", busybox_path, TMP_RD_UNPACKED_DIR, path); + snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc | \"$B\" gzip > \"%s\"", busybox_path, target, path); break; case RD_LZ4: - snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc | \"%s/lz4\" stdin \"%s\"", busybox_path, TMP_RD_UNPACKED_DIR, mrom_dir(), path); + snprintf(buff, sizeof(buff), "B=\"%s\"; cd \"%s\"; \"$B\" find . | \"$B\" cpio -o -H newc | \"%s/lz4\" stdin \"%s\"", busybox_path, target, mrom_dir(), path); break; } + char *cmd[] = { busybox_path, "sh", "-c", buff, NULL }; + int r; r = run_cmd(cmd); if(r != 0) { ERROR("Failed to pack ramdisk!\n"); + return -1; + } else { + return 0; + } +} + + +static int inject_rd(const char *path) +{ + int result = -1; + int type; + + char *copy_target; + if (decompress_rd(path, TMP_RD_UNPACKED_DIR, &type)) { goto fail; } + if (!access(TMP_RD2_UNPACKED_DIR, F_OK)) { + copy_target = TMP_RD2_UNPACKED_DIR; + } else { + copy_target = TMP_RD_UNPACKED_DIR; + } + + if (copy_rd_files(path, copy_target) < 0) + { + goto fail; + } + + if (pack_rd(path, TMP_RD_UNPACKED_DIR, type) < 0) { + goto fail; + } + + success: result = 0; fail: - remove_dir(TMP_RD_UNPACKED_DIR); return result; } +int inject_cmdline(struct bootimg *image) +{ + int res = 0; + char* custom_cmdline = "printk.devkmsg=on androidboot.android_dt_dir=/fakefstab/"; + + char* cmdline = libbootimg_get_cmdline(&image->hdr); + char* newcmdline = NULL; + if (!strstr(cmdline, custom_cmdline)) { + asprintf(&newcmdline, "%s %s", cmdline, custom_cmdline); + + libbootimg_set_cmdline(&image->hdr, newcmdline); + free(newcmdline); + } + + return res; +} + int inject_bootimg(const char *img_path, int force) { int res = -1; @@ -322,7 +383,7 @@ int inject_bootimg(const char *img_path, int force) goto exit; } - if(inject_rd(initrd_tmp_name, initrd2_tmp_name) >= 0) + if(inject_rd(initrd_tmp_name) >= 0 && inject_cmdline(&img) == 0) { // Update the boot.img snprintf((char*)img.hdr.name, BOOT_NAME_SIZE, "tr_ver%d", VERSION_TRAMPOLINE); diff --git a/lib/inject.h b/lib/inject.h index 6b2f6c49..7313be98 100644 --- a/lib/inject.h +++ b/lib/inject.h @@ -19,5 +19,9 @@ #define INJECT_H int inject_bootimg(const char *img_path, int force); +int decompress_second_rd(const char* target, const char *second_path); +int pack_second_rd(const char *second_path, const char* unpacked_dir); +int decompress_rd(const char *path, const char* target, int* type); +int pack_rd(const char *path, const char *target, int type); #endif diff --git a/lib/util.c b/lib/util.c index 4dfa3b6d..a35e43b4 100644 --- a/lib/util.c +++ b/lib/util.c @@ -31,6 +31,7 @@ #ifdef HAVE_SELINUX #include #endif +#include #include #include @@ -189,6 +190,39 @@ int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const cha return 0; } +int mkdir_with_perms_context(const char *path, mode_t mode, const char *owner, const char *group, char* context) +{ + int ret; + struct passwd *pwd = NULL; + + ret = mkdir(path, mode); + /* chmod in case the directory already exists */ + if (ret == -1 && errno == EEXIST) { + ret = chmod(path, mode); + } + if (ret == -1) { + return -errno; + } + + if(owner) + { + pwd = getpwnam(owner); + + if (!pwd) { + return -errno; + } + + uid_t uid = pwd->pw_uid; + gid_t gid = pwd->pw_gid; + + if(chown(path, uid, gid) < 0) { + return -errno; + } + } + setfilecon(path, context); + return 0; +} + /* * replaces any unacceptable characters with '_', the * length of the resulting string is equal to the input string @@ -294,6 +328,120 @@ int copy_file(const char *from, const char *to) return 0; } +int copy_file_with_context(const char *from, const char *to, char* context) +{ + FILE *in = fopen(from, "re"); + if(!in) + return -1; + + FILE *out = fopen(to, "we"); + if(!out) + { + fclose(in); + return -1; + } + + fseek(in, 0, SEEK_END); + int size = ftell(in); + rewind(in); + + char *buff = malloc(size); + fread(buff, 1, size, in); + fwrite(buff, 1, size, out); + + fclose(in); + fclose(out); + free(buff); + setfilecon(out, context); + return 0; +} + +int getattr(const char *path, struct file_attr *a) { + if (lstat(path, &a->st) == -1) + return -1; + char con[256]; + if (getfilecon(path, &con) == -1) + return -1; + strcpy(a->con, con); + //freecon(con); + return 0; +} + +int setattr(const char *path, struct file_attr *a) { + if (chmod(path, a->st.st_mode & 0777) < 0) + return -1; + if (chown(path, a->st.st_uid, a->st.st_gid) < 0) + return -1; + if (a->con[0] && setfilecon(path, a->con) < 0) + return -1; + return 0; +} + +void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context) { + + char in[256]; + char out[256]; + memset(in, 0, 256); + memset(out, 0, 256); + struct dirent *dp = NULL; + char *fstab_name = NULL; + DIR* dir = NULL; + if (access(target, F_OK)) { + mkdir_with_perms(target, 0755, NULL, NULL); + } + ERROR("copying dir %s to %s\n", dirpath, target); + while((dp = readdir(d))) + { + if((dp->d_name[0] == '.' && strlen(dp->d_name) == 1) || (dp->d_name[0] == '.' && dp->d_name[1] == '.') || (!strcmp(dp->d_name, "system"))) + continue; + + sprintf(in, "%s/%s", dirpath, dp->d_name); + if (!strcmp(dp->d_name, "init")) { + sprintf(out, "%s/%s", target, "main_init"); + } else { + sprintf(out, "%s/%s", target, dp->d_name); + } + + struct file_attr a; + getattr(in, &a); + + if (dp->d_type == DT_DIR) { + dir = opendir(in); + if (preserve_context) { + char* context = calloc(1, 50); + getfilecon(in, &context); + mkdir_with_perms_context(out, 0755, NULL, NULL, context); + } else { + mkdir_with_perms(out, 0755, NULL, NULL); + } + setattr(out, &a); + copy_dir_contents(dir, in, out); + continue; + } else if (dp->d_type == DT_LNK) { + char target[256]; + readlink(in, target, sizeof(target)); + symlink(target, out); + setattr(out, &a); + } else if (dp->d_type == DT_REG) { + if (preserve_context) { + char* context = calloc(1, 50); + getfilecon(in, &context); + copy_file_with_context(in, out, context); + } else { + copy_file(in, out); + } + setattr(out, &a); + } + + } + closedir(d); +} + + +void copy_dir_contents(DIR* d, char* dirpath, char* target) { + clone_dir(d, dirpath, target, false); +} + int write_file(const char *path, const char *value) { int fd, ret, len; @@ -314,6 +462,7 @@ int write_file(const char *path, const char *value) close(fd); if (ret < 0) { + ERROR("Failed to open file %s (%d: %s)\n", path, errno, strerror(errno)); return -errno; } else { return 0; @@ -398,6 +547,18 @@ int run_cmd_with_env(char **cmd, char *const *envp) } +char* read_file(char* file) { + char* buf = calloc(1, 256); + FILE* fp = fopen(file, "r"); + if (fp) { + fread(buf, 1, 256, fp); + fclose(fp); + } else { + ERROR("cannot open %s %s\n", file, strerror(errno)); + } + return buf; +} + char *run_get_stdout(char **cmd) { int exit_code; diff --git a/lib/util.h b/lib/util.h index 5dc19d0d..65d3d718 100644 --- a/lib/util.h +++ b/lib/util.h @@ -17,10 +17,12 @@ #ifndef _INIT_UTIL_H_ #define _INIT_UTIL_H_ +#include #include #include #include #include +#include #define UNUSED __attribute__((unused)) @@ -31,6 +33,11 @@ #define REBOOT_BOOTLOADER 2 #define REBOOT_SHUTDOWN 3 +struct file_attr { + struct stat st; + char con[128]; +}; + time_t gettime(void); unsigned int decode_uid(const char *s); int mkdir_recursive(const char *pathname, mode_t mode); @@ -40,8 +47,12 @@ int make_link(const char *oldpath, const char *newpath); void remove_link(const char *oldpath, const char *newpath); int wait_for_file(const char *filename, int timeout); int copy_file(const char *from, const char *to); +int copy_file_with_context(const char *from, const char *to, char* context); +void copy_dir_contents(DIR* d, char* dirpath, char* target); +void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context); int copy_dir(const char *from, const char *to); int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const char *group); +int mkdir_with_perms_context(const char *path, mode_t mode, const char *owner, const char *group, char* context); int write_file(const char *path, const char *value); int remove_dir(const char *dir); int run_cmd(char **cmd); @@ -60,6 +71,7 @@ int mount_image(const char *src, const char *dst, const char *fs, int flags, con int multirom_mount_image(const char *src, const char *dst, const char *fs, int flags, const void *data); void do_reboot(int type); int mr_system(const char *shell_fmt, ...); +char* read_file(char* file); inline int imin(int a, int b); inline int imax(int a, int b); diff --git a/multirom.c b/multirom.c index 199a60dd..42707428 100644 --- a/multirom.c +++ b/multirom.c @@ -32,6 +32,8 @@ #include #include #include +#include +#include // clone libbootimg to /system/extras/ from // https://github.com/Tasssadar/libbootimg.git @@ -83,37 +85,30 @@ static volatile int run_usb_refresh = 0; static pthread_t usb_refresh_thread; static pthread_mutex_t parts_mutex = PTHREAD_MUTEX_INITIALIZER; static void (*usb_refresh_handler)(void) = NULL; +void copy_dir_contents(DIR* d, char* dirpath, char* target); +void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts); +bool LoadSplitPolicy(); -char* read_file(char* file) { - char* buf = calloc(1, 256); - FILE* fp = fopen(file, "r"); - if (fp) { - fread(buf, 1, 256, fp); - fclose(fp); - } else { - ERROR("cannot open %s %s\n", file, strerror(errno)); - } - return buf; -} void disable_dtb_fstab(char* partition) { + //return; if (access("status", F_OK)) { + DIR* dir = opendir("/proc/device-tree/firmware/android"); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab"); FILE* fp = fopen("status", "w"); fprintf(fp, "disabled"); fclose(fp); } - char mnt_pt[100]; - sprintf(mnt_pt, "%s%s/status", DT_FSTAB_PATH, partition); - if (!mount("/status", mnt_pt, "ext4", MS_BIND, "discard,nomblk_io_submit")) { - INFO("status node bind mounted in procfs\n"); - } else { - ERROR("status node bind mount failed! %s\n", strerror(errno)); - } + char path[256]; + sprintf(path, "/fakefstab/fstab/%s/status", partition); + copy_file("/status", path); } void remove_dtb_fstab() { mkdir("/dummy_fw", S_IFDIR); - if (!mount("/dummy_fw", "/proc/device-tree/firmware", "ext4", MS_BIND, "discard,nomblk_io_submit")) { + DIR* dir = opendir("/proc/device-tree/firmware/android"); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab"); + if (!mount("/dummy_fw", "/fakefstab", "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("dummy dtb node bind mounted in procfs\n"); } else { ERROR("dummy dtb node bind mount failed! %s\n", strerror(errno)); @@ -123,10 +118,10 @@ void remove_dtb_fstab() { int mount_dtb_fstab(char* partition) { int rc = -1; - char root_path [100] = {'\0'}; - char device[100] = {'\0'}; - char type[100] = {'\0'}; - char mnt_flags[100] = {'\0'}; + char root_path [256] = {'\0'}; + char device[256] = {'\0'}; + char type[256] = {'\0'}; + char mnt_flags[256] = {'\0'}; sprintf(root_path, "%s%s", DT_FSTAB_PATH, partition); sprintf(device, "%s%s", root_path, "/dev"); @@ -475,7 +470,7 @@ int multirom(const char *rom_to_boot) } else { - if ((to_boot->type != ROM_DEFAULT) && to_boot->has_bootimg) + if ((to_boot->type != ROM_DEFAULT) && to_boot->has_bootimg && !s.use_primary_kernel) { // Flash secondary boot.img, and reboot // note: a secondary boot.img in primary slot will trigger second_boot=1 @@ -493,6 +488,8 @@ int multirom(const char *rom_to_boot) exit = (EXIT_REBOOT | EXIT_UMOUNT); goto finish; + } else if (s.use_primary_kernel) { + exit = 0; } } #endif @@ -847,6 +844,7 @@ int multirom_default_status(struct multirom_status *s) s->enable_kmsg_logging = 0; s->rotation = MULTIROM_DEFAULT_ROTATION; s->anim_duration_coef = 1.f; + s->use_primary_kernel = 0; s->fstab = fstab_auto_load(); if(!s->fstab) @@ -1005,6 +1003,8 @@ int multirom_load_status(struct multirom_status *s) s->force_generic_fb = atoi(arg); else if(strstr(name, "anim_duration_coef_pct")) s->anim_duration_coef = ((float)atoi(arg)) / 100; + else if(strstr(name, "use_primary_kernel")) + s->use_primary_kernel = atoi(arg); } fclose(f); @@ -1092,6 +1092,7 @@ int multirom_save_status(struct multirom_status *s) fprintf(f, "rotation=%d\n", s->rotation); fprintf(f, "force_generic_fb=%d\n", s->force_generic_fb); fprintf(f, "anim_duration_coef_pct=%d\n", (int)(s->anim_duration_coef*100)); + fprintf(f, "use_primary_kernel=%d\n", (int)(s->use_primary_kernel)); fclose(f); return 0; @@ -1134,6 +1135,7 @@ void multirom_dump_status(struct multirom_status *s) INFO(" auto_boot_rom=%s\n", s->auto_boot_rom ? s->auto_boot_rom->name : "NULL"); INFO(" auto_boot_type=%d\n", s->auto_boot_type); INFO(" curr_rom_part=%s\n", s->curr_rom_part ? s->curr_rom_part : "NULL"); + INFO(" use_primary_kernel=%d\n", s->use_primary_kernel); INFO("\n"); int i; @@ -1468,8 +1470,13 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to if (mount_dtb_fstab("system") == 0) { disable_dtb_fstab("system"); } + //if (mount_dtb_fstab("vendor") == 0) { + //disable_dtb_fstab("vendor"); + // } + // remove_dtb_fstab(); } rom_quirks_on_initrd_finalized(); + LoadSplitPolicy(); break; } case ROM_LINUX_INTERNAL: @@ -1483,7 +1490,25 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to { if(!(exit & (EXIT_REBOOT | EXIT_KEXEC))) { - exit &= ~(EXIT_UMOUNT); + if (!s->use_primary_kernel) { + exit &= ~(EXIT_UMOUNT); + } else { + exit = 0; + struct bootimg img; + char bootimg_path[256]; + sprintf(bootimg_path, "%s/%s", to_boot->base_path, "boot.img"); + libbootimg_init_load(&img, bootimg_path, LIBBOOTIMG_LOAD_ALL); + libbootimg_dump_ramdisk(&img, "/.temprd"); + int type = 0; + decompress_rd("/.temprd", "/.newrd", &type); + if (!access("/.newrd/second", F_OK)) { + DIR* dir = opendir("/.newrd/second"); + copy_init_contents(dir, "/.newrd/second", "/", true); + } else { + DIR* dir = opendir("/.newrd"); + copy_init_contents(dir, "/.newrd", "/", true); + } + } if(multirom_prep_android_mounts(s, to_boot) == -1) return -1; @@ -1512,6 +1537,8 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to } #define EXEC_MASK (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) +#define EXEC_MASK_NEW (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) +#define EXEC_MASK_RW (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) char *multirom_find_fstab_in_rc(const char *rcfile) { @@ -1593,6 +1620,140 @@ static int multirom_inject_fw_mounter(struct multirom_status *s, struct fstab_pa return 0; } + + +bool is_symlink(const char *filename) +{ + struct stat p_statbuf; + + if (lstat(filename, &p_statbuf) < 0) { /* if error occured */ + ERROR("calling stat()"); + return false; + } + + if (S_ISLNK(p_statbuf.st_mode) == 1) { + INFO("%s is a symbolic link\n", filename); + return true; + } else { + INFO("%s is NOT a symbolic link\n", filename); + return false; + } +} + +void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts) { + + char in[256]; + char out[256]; + memset(in, 0, 256); + memset(out, 0, 256); + struct dirent *dp = NULL; + char *fstab_name = NULL; + DIR* dir = NULL; + ERROR("copying dir %s\n", dirpath); + clone_dir(d, dirpath, target, preserve_contexts); +} + +bool GetVendorMappingVersion(char** plat_vers) { + if (!(*plat_vers = read_file("/vendor/etc/selinux/plat_sepolicy_vers.txt"))) { + //PLOG(ERROR) << "Failed to read /vendor/etc/selinux/plat_sepolicy_vers.txt"; + return false; + } + if (!plat_vers) { + //LOG(ERROR) << "No version present in plat_sepolicy_vers.txt"; + return false; + } + return true; +} + +bool LoadSplitPolicy() { + // IMPLEMENTATION NOTE: Split policy consists of three CIL files: + // * platform -- policy needed due to logic contained in the system image, + // * non-platform -- policy needed due to logic contained in the vendor image, + // * mapping -- mapping policy which helps preserve forward-compatibility of non-platform policy + // with newer versions of platform policy. + // + // secilc is invoked to compile the above three policy files into a single monolithic policy + // file. This file is then loaded into the kernel. + // Load precompiled policy from vendor image, if a matching policy is found there. The policy + // must match the platform policy on the system image. + // No suitable precompiled policy could be loaded + INFO( "Compiling SELinux policy"); + // Determine the highest policy language version supported by the kernel + set_selinuxmnt("/sys/fs/selinux"); + int max_policy_version = security_policyvers(); + if (max_policy_version == -1) { + //PLOG(ERROR) << "Failed to determine highest policy version supported by kernel"; + return false; + } + // We store the output of the compilation on /dev because this is the most convenient tmpfs + // storage mount available this early in the boot sequence. + char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX"; + int compiled_sepolicy_fd = mkostemp(compiled_sepolicy, O_CLOEXEC); + if (compiled_sepolicy_fd < 0) { + //PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy; + return false; + } + // Determine which mapping file to include + char* vend_plat_vers; + if (!GetVendorMappingVersion(&vend_plat_vers)) { + return false; + } + char* mapping_file = NULL; + asprintf(&mapping_file, "/system/etc/selinux/mapping/%s.cil","28.0"); + // vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace + // nonplat_sepolicy.cil. + char* plat_pub_versioned_cil_file = "/vendor/etc/selinux/plat_pub_versioned.cil"; + char* vendor_policy_cil_file = "/vendor/etc/selinux/vendor_sepolicy.cil"; + if (access(vendor_policy_cil_file, F_OK) == -1) { + // For backward compatibility. + // TODO: remove this after no device is using nonplat_sepolicy.cil. + vendor_policy_cil_file = "/vendor/etc/selinux/nonplat_sepolicy.cil"; + plat_pub_versioned_cil_file = NULL; + } else if (access(plat_pub_versioned_cil_file, F_OK) == -1) { + //LOG(ERROR) << "Missing " << plat_pub_versioned_cil_file; + return false; + } + // odm_sepolicy.cil is default but optional. + const char* version_as_string = NULL; + asprintf(&version_as_string, "%d", max_policy_version); + const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil"; + // clang-format off + char* compile_args[] = { + "/system/bin/secilc", + plat_policy_cil_file, + "-m", "-M", "true", "-G", "-N", + // Target the highest policy language version supported by the kernel + "-c", version_as_string, + mapping_file, + "-o", compiled_sepolicy, + // We don't care about file_contexts output by the compiler + "-f", "/sys/fs/selinux/null", "", "", NULL // /dev/null is not yet available + }; + // clang-format on + if (plat_pub_versioned_cil_file) { + compile_args[14] = plat_pub_versioned_cil_file; + } + if (vendor_policy_cil_file) { + compile_args[15] = vendor_policy_cil_file; + } + int exit_code = 0; + for (int i = 0; i < 17; i++) { + INFO("args %s", compile_args[i]); + } + INFO("%s", run_get_stdout_with_exit(compile_args, &exit_code)); + //unlink(compiled_sepolicy); + //return false; + unlink(compiled_sepolicy); + INFO( "Loading compiled SELinux policy"); + if (selinux_android_load_policy_from_fd(compiled_sepolicy_fd, compiled_sepolicy) < 0) { + //LOG(ERROR) << "Failed to load SELinux policy from " << compiled_sepolicy; + return false; + } + INFO( "sepolicy loaded successfuly"); + write_file("/sys/fs/selinux/checkreqprot", "0"); + return true; +} + int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom *rom) { char in[128]; @@ -1608,57 +1769,6 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom sprintf(path, "%s/firmware.img", rom->base_path); has_fw = (access(path, R_OK) >= 0); - sprintf(path, "%s/boot", rom->base_path); - - DIR *d = opendir(path); - char* prefix = NULL; - if(!d) - { - ERROR("Failed to open rom path %s\n", path); - return -1; - } - - struct dirent *dp = NULL; - - while((dp = readdir(d))) - { - if((dp->d_name[0] == '.' && strlen(dp->d_name) == 1) || (dp->d_name[0] == '.' && (dp->d_name[1] == '.') || dp->d_name[1] == 0)) - continue; - - if (dp->d_type == DT_DIR) { - sprintf(in, "%s/%s", path, dp->d_name); - d = opendir(in); - prefix = dp->d_name; - continue; - } - - if (prefix) { - sprintf(out, "/%s/%s", prefix, dp->d_name); - sprintf(in, "%s/%s/%s", path, prefix, dp->d_name); - } else { - sprintf(in, "%s/%s", path, dp->d_name); - sprintf(out, "/%s", dp->d_name); - } - - copy_file(in, out); - - if(strstr(dp->d_name, ".rc")) - { - // set permissions for .rc files - chmod(out, EXEC_MASK); - - if(!fstab_name && strcmp(dp->d_name, "init."TARGET_DEVICE".rc") == 0) - fstab_name = multirom_find_fstab_in_rc(out); - } - } - closedir(d); - - if(multirom_process_android_fstab(fstab_name, has_fw, &fw_part, 0) != 0) { - INFO("fstab couldnt be found in ramdisk. Rom maybe treble. Retry after vendor mount\n"); - } else { - found_fstab = 1; - } - unlink("/cache"); mkdir_with_perms("/system", 0755, NULL, NULL); @@ -1734,11 +1844,52 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom if (!access(DT_FSTAB_PATH, F_OK)) { remove_dtb_fstab(); } + + //System as root detection + char* system_path = NULL; + bool system_as_root = false; + asprintf(&system_path, "%s/system.sparse.img", rom->base_path); + + if (!multirom_path_exists("/system", "init.rc")) { + umount("/system"); + mkdir_with_perms("/system_root", 0755, NULL, NULL); + multirom_mount_image(system_path, "/system_root", "ext4", MS_RDONLY, NULL); + system_as_root = true; + if(mount("/system_root/system", "/system", "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit") < 0) { + INFO("mount error\n"); + } else { + INFO("Bind mounted /system_root/system on /system\n"); + } + + LoadSplitPolicy(); + DIR* dir = opendir("/system_root"); + copy_init_contents(dir, "/system_root", "/", true); + } + + sprintf(path, "%s/boot", rom->base_path); + DIR* dir = opendir(path); + if (!system_as_root) { + LoadSplitPolicy(); + } + copy_init_contents(dir, path, "/", false); + if (!access("/system/bin/init", F_OK) && is_symlink("/main_init")) { + char* context = calloc(1, 50); + getfilecon("/system/bin/init", &context); + copy_file_with_context("/system/bin/init", "/main_init", context); + chmod("/main_init", EXEC_MASK_NEW); + } + + if(multirom_process_android_fstab(fstab_name, has_fw, &fw_part, 0) != 0) { + INFO("fstab couldnt be found in ramdisk. Rom maybe treble. Retry after vendor mount\n"); + } else { + found_fstab = 1; + } if(!found_fstab && multirom_process_android_fstab(NULL, has_fw, &fw_part, 1) != 0) { INFO("fstab not found even in vendor!\n"); goto exit; } + // mount() does not necessarily obey the mount options (eg, ro on system or nosuid on data) // so attempt a remount on the partitions, but don't abort if the remount in unsuccessful, // unless MR_PANIC_ON_FAILED_REMOUNT is set: eg on the HTC 10 if system is not ro, then the diff --git a/multirom.h b/multirom.h index 310f6554..00f46da5 100644 --- a/multirom.h +++ b/multirom.h @@ -116,6 +116,7 @@ struct multirom_status char *int_display_name; int rotation; int force_generic_fb; + int use_primary_kernel; float anim_duration_coef; struct multirom_rom *auto_boot_rom; struct multirom_rom *current_rom; diff --git a/no_kexec.c b/no_kexec.c index a2153c58..e8076398 100644 --- a/no_kexec.c +++ b/no_kexec.c @@ -227,6 +227,32 @@ int nokexec_set_oslevel(char *secondary_path) return res; } +int nokexec_set_cmdline(char *secondary_path) +{ + int res = 0; + struct bootimg image; + char* custom_cmdline = "androidboot.selinux=permissive printk.devkmsg=on androidboot.android_dt_dir=/fakefstab/"; + + INFO(NO_KEXEC_LOG_TEXT ": Going to check the bootimg in primary slot for slevel\n"); + + if (libbootimg_init_load(&image, secondary_path, LIBBOOTIMG_LOAD_ALL) < 0) + { + ERROR(NO_KEXEC_LOG_TEXT ": Could not open boot image (%s)!\n", nokexec_s.path_boot_mmcblk); + return -1; + } + + char* cmdline = libbootimg_get_cmdline(&image.hdr); + char* newcmdline = NULL; + asprintf(&newcmdline, "%s %s", cmdline, custom_cmdline); + + libbootimg_set_cmdline(&image.hdr, newcmdline); + free(newcmdline); + + libbootimg_destroy(&image); + return res; +} + + int nokexec_backup_primary(void) { int res; @@ -369,6 +395,9 @@ int nokexec_flash_secondary_bootimg(struct multirom_rom *secondary_rom) if (nokexec_set_oslevel(path_bootimg)) return -3; + if (nokexec_set_cmdline(path_bootimg)) + return -3; + if (nokexec_flash_to_primary(path_bootimg)) return -3; diff --git a/trampoline/Android.mk b/trampoline/Android.mk index 7ec46c5e..24553bab 100644 --- a/trampoline/Android.mk +++ b/trampoline/Android.mk @@ -12,7 +12,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) -LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static libbootimg +LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static libbootimg libselinux LOCAL_C_INCLUDES += system/extras/libbootimg/include LOCAL_FORCE_STATIC_EXECUTABLE := true diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index e78c91e8..8dd3c93f 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -15,6 +15,7 @@ * along with MultiROM. If not, see . */ +#define _GNU_SOURCE #include #include #include @@ -27,7 +28,11 @@ #include #include #include +#include +#include +#include #include +#include #include "devices.h" #include "../lib/log.h" @@ -47,6 +52,88 @@ static char path_multirom[64] = { 0 }; +int fork_and_exec_with_stdout(char *cmd, char *const *envp) +{ + int fd[2]; + int exit_code = -1; + char* command[] = {cmd, NULL}; + if(pipe2(fd, O_CLOEXEC) < 0) + return -1; + + pid_t pid = fork(); + if (pid < 0) + { + close(fd[0]); + close(fd[1]); + return pid; + } + + if(pid == 0) // child + { + close(fd[0]); + dup2(fd[1], 1); // send stdout to the pipe + dup2(fd[1], 2); // send stderr to the pipe + close(fd[1]); + + if (execve(command[0], command, envp) == -1) { + ERROR("execve failed %s\n", strerror(errno)); + } + _exit(127); + } + else + { + close(fd[1]); + + char *res = malloc(512); + char buffer[512]; + int size = 512, written = 0, len; + while ((len = read(fd[0], buffer, sizeof(buffer))) > 0) + { + if(written + len + 1 > size) + { + size = written + len + 256; + res = realloc(res, size); + } + memcpy(res+written, buffer, len); + written += len; + } + res[written] = 0; + + close(fd[0]); + + waitpid(pid, &exit_code, 0); + ERROR("%s\n", res); + + if(written == 0) + { + free(res); + return pid; + } + return pid; + } + return pid; +} + +static int fork_and_exec_with_strace(char *cmd, char** env) +{ + pid_t pID = fork(); + if(pID == 0) + { + char* args[] = {"/mrom_enc/strace", "-o", NULL, "-f", NULL, NULL}; + char strace_arg1[100]; + sprintf(strace_arg1, "strace-%s", (cmd + 10)); + args[2] = strace_arg1; + args[4] = cmd; + INFO("running %s %s %s %s %s\n", args[0], args[1], args[2], args[3], args[4]); + stdio_to_null(); + setpgid(0, getpid()); + execve(args[0], args, env); + ERROR("Failed to exec %s: %s\n", args[0], strerror(errno)); + _exit(127); + } + return pID; +} + static int find_multirom(void) { int i; @@ -387,6 +474,68 @@ static int run_core(void) return res; } +char *trampoline_get_klog(void) +{ + int len = klogctl(10, NULL, 0); + if (len < 16*1024) len = 16*1024; + else if (len > 16*1024*1024) len = 16*1024*1024; + + char *buff = malloc(len + 1); + len = klogctl(3, buff, len); + if(len <= 0) + { + ERROR("Could not get klog!\n"); + free(buff); + return NULL; + } + buff[len] = 0; + return buff; +} + +int trampoline_copy_log(char *klog, const char *dest_path_relative) +{ + int res = 0; + int freeLog = (klog == NULL); + + if(!klog) + klog = trampoline_get_klog(); + + if(klog) + { + char path[256]; + snprintf(path, sizeof(path), "%s", dest_path_relative); + FILE *f = fopen(path, "we"); + + if(f) + { + fwrite(klog, 1, strlen(klog), f); + fclose(f); + chmod(path, 0777); + } + else + { + ERROR("Failed to open %s!\n", path); + res = -1; + } + } + else + { + ERROR("Could not get klog!\n"); + res = -1; + } + + if(freeLog) + free(klog); + return res; +} + +void klog_periodic(void* ptr) { + while(1) { + usleep(2000000); + trampoline_copy_log(NULL, "/data/last_kmsg"); + } +} + int main(int argc, char *argv[]) { if (argc > 1) @@ -409,6 +558,7 @@ int main(int argc, char *argv[]) mount("proc", "/proc", "proc", 0, NULL); mount("sysfs", "/sys", "sysfs", 0, NULL); mount("pstore", "/sys/fs/pstore", "pstore", 0, NULL); + mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL); #if MR_USE_DEBUGFS_MOUNT // Mount the debugfs kernel sysfs @@ -455,9 +605,16 @@ int main(int argc, char *argv[]) umount("/sys/kernel/debug"); #endif + if (access("/fakefstab/", F_OK)) { + DIR* dir = opendir("/proc/device-tree/firmware/android"); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab"); + } umount("/proc"); umount("/sys/fs/pstore"); - umount("/sys"); + umount("/sys/fs/selinux"); + if(umount("/sys")) { + ERROR("sysfs unmount failed :%s\n", strerror(errno)); + } INFO("Running main_init\n"); @@ -466,7 +623,17 @@ int main(int argc, char *argv[]) chmod("/main_init", EXEC_MASK); rename("/main_init", "/init"); + pthread_t klog_thread; + if(pthread_create(&klog_thread, NULL, klog_periodic, NULL)) { + + fprintf(stderr, "Error creating thread\n"); + return 1; + + } + + //trampoline_copy_log(NULL, "/data/last_kmsg"); res = execve(cmd[0], cmd, NULL); + //trampoline_copy_log(NULL, "/data/last_kmsg"); ERROR("execve returned %d %d %s\n", res, errno, strerror(errno)); return 0; } From b2d560fd5f70017fcd358a77efbdc97775ac2955 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Thu, 16 May 2019 14:53:26 +0530 Subject: [PATCH 49/65] Add support for booting google's android P GSI --- lib/util.c | 5 ++- multirom.c | 68 +++++++++++++++++++++++++++++++++-------- multirom.h | 1 + rom_quirks.c | 6 ++-- rom_quirks.h | 4 ++- trampoline/trampoline.c | 27 ++++++++++++++++ 6 files changed, 95 insertions(+), 16 deletions(-) diff --git a/lib/util.c b/lib/util.c index a35e43b4..da07641f 100644 --- a/lib/util.c +++ b/lib/util.c @@ -349,10 +349,13 @@ int copy_file_with_context(const char *from, const char *to, char* context) fread(buff, 1, size, in); fwrite(buff, 1, size, out); + if(setfilecon(to, context)) { + ERROR("couldnt set %s context to %s because %s", to, context, strerror(errno)); + } + fclose(in); fclose(out); free(buff); - setfilecon(out, context); return 0; } diff --git a/multirom.c b/multirom.c index 42707428..baadfb04 100644 --- a/multirom.c +++ b/multirom.c @@ -309,6 +309,27 @@ void multirom_kmsg_logging(int kmsg_backup_type) set_mediarw_perms(path_log_file); } +int multirom_get_current_oslevel(struct multirom_status *s) +{ + int res = -1; + struct bootimg primary_img, secondary_img; + + char* secondary_path = "/dev/block/bootdevice/by-name/boot"; + + INFO(NO_KEXEC_LOG_TEXT ": Going to check the bootimg in primary slot for slevel\n"); + + if (libbootimg_init_load(&secondary_img, secondary_path, LIBBOOTIMG_LOAD_ALL) < 0) + { + return -1; + } + + char* secondary_os_version = libbootimg_get_osversion(&secondary_img.hdr, true); + char* secondary_os_level = libbootimg_get_oslevel(&secondary_img.hdr, true); + + memcpy(s->os_version, secondary_os_version, 6); + return 0; +} + int multirom(const char *rom_to_boot) { if(multirom_find_base_dir() == -1) @@ -464,6 +485,7 @@ int multirom(const char *rom_to_boot) if (s.is_second_boot != 0) { + multirom_get_current_oslevel(&s); // Restore primary boot.img, and continue if (nokexec_restore_primary_and_cleanup() < 0) MR_NO_KEXEC_ABORT; @@ -691,7 +713,7 @@ int multirom_apk_get_roms(struct multirom_status *s) { if(multirom_find_base_dir() == -1) { - printf("Could not find multirom dir\n"); + INFO("Could not find multirom dir\n"); return -1; } @@ -725,13 +747,13 @@ int multirom_apk_get_roms(struct multirom_status *s) s->curr_rom_part = strdup(arg); } - printf("current_rom='%s' curr_rom_part='%s'\n", current_rom, (s->curr_rom_part ? s->curr_rom_part : "")); + INFO("current_rom='%s' curr_rom_part='%s'\n", current_rom, (s->curr_rom_part ? s->curr_rom_part : "")); fclose(f); } else { - printf("Failed to open config file, setting current_rom to null!\n"); + INFO("Failed to open config file, setting current_rom to null!\n"); } /* Get Internal ROM */ @@ -740,7 +762,7 @@ int multirom_apk_get_roms(struct multirom_status *s) DIR *d = opendir(roms_path); if(!d) { - printf("Failed to open Internal ROM's folder, creating one with ROM from internal memory...\n"); + INFO("Failed to open Internal ROM's folder, creating one with ROM from internal memory...\n"); multirom_import_internal(); } else @@ -751,7 +773,7 @@ int multirom_apk_get_roms(struct multirom_status *s) d = opendir(roms_path); if(!d) { - printf("Failed to open roms dir!\n"); + INFO("Failed to open roms dir!\n"); //return -1; } else @@ -769,11 +791,11 @@ int multirom_apk_get_roms(struct multirom_status *s) if(strlen(dr->d_name) > MAX_ROM_NAME_LEN) { - printf("Skipping ROM %s, name is too long (max %d chars allowed)\n", dr->d_name, MAX_ROM_NAME_LEN); + INFO("Skipping ROM %s, name is too long (max %d chars allowed)\n", dr->d_name, MAX_ROM_NAME_LEN); continue; } - //printf("Adding ROM %s\n", dr->d_name); + //INFO("Adding ROM %s\n", dr->d_name); struct multirom_rom *rom = malloc(sizeof(struct multirom_rom)); memset(rom, 0, sizeof(struct multirom_rom)); @@ -822,7 +844,7 @@ int multirom_apk_get_roms(struct multirom_status *s) s->current_rom = multirom_get_rom(s, current_rom, s->curr_rom_part); if(!s->current_rom) { - printf("Failed to find current rom (%s, part %s)!\n", current_rom, (s->curr_rom_part) ? s->curr_rom_part : ""); + INFO("Failed to find current rom (%s, part %s)!\n", current_rom, (s->curr_rom_part) ? s->curr_rom_part : ""); free(s->curr_rom_part); s->curr_rom_part = NULL; } @@ -1516,9 +1538,8 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to if(multirom_create_media_link(s) == -1) return -1; - rom_quirks_on_initrd_finalized(); - rom_quirks_change_patch_and_osver(); + rom_quirks_change_patch_and_osver(s, to_boot); rcadditions_write_to_files(&s->rc); rcadditions_free(&s->rc); @@ -1751,6 +1772,22 @@ bool LoadSplitPolicy() { } INFO( "sepolicy loaded successfuly"); write_file("/sys/fs/selinux/checkreqprot", "0"); + struct stat fileStat; + if(stat("/sys/fs/selinux/checkreqprot",&fileStat) < 0) + return false; + + INFO("File Permissions: \t"); + INFO("read %d\n", fileStat.st_mode & S_IRUSR); + INFO("write %d\n", fileStat.st_mode & S_IWUSR); + INFO("exec %d\n", fileStat.st_mode & S_IXUSR); + INFO("%d\n", fileStat.st_mode & S_IRGRP); + INFO("%d\n", fileStat.st_mode & S_IWGRP); + INFO("%d\n", fileStat.st_mode & S_IXGRP); + INFO("%d\n", fileStat.st_mode & S_IROTH); + INFO("%d\n", fileStat.st_mode & S_IWOTH); + INFO("%d\n", fileStat.st_mode & S_IXOTH); + INFO("\n\n"); + return true; } @@ -1861,6 +1898,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom INFO("Bind mounted /system_root/system on /system\n"); } + rom_quirks_on_initrd_finalized(); LoadSplitPolicy(); DIR* dir = opendir("/system_root"); copy_init_contents(dir, "/system_root", "/", true); @@ -1869,13 +1907,19 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom sprintf(path, "%s/boot", rom->base_path); DIR* dir = opendir(path); if (!system_as_root) { + rom_quirks_on_initrd_finalized(); LoadSplitPolicy(); } copy_init_contents(dir, path, "/", false); - if (!access("/system/bin/init", F_OK) && is_symlink("/main_init")) { + if (!access("/system/bin/init", F_OK) && is_symlink("/system_root/init")) { char* context = calloc(1, 50); getfilecon("/system/bin/init", &context); - copy_file_with_context("/system/bin/init", "/main_init", context); + copy_file_with_context("/system/bin/init", "/main_init", "u:object_r:rootfs:s0"); + chmod("/main_init", EXEC_MASK_NEW); + } else if (!is_symlink("/system_root/init") && !access("/system_root/init", F_OK)) { + char* context = calloc(1, 50); + getfilecon("/system_root/init", &context); + copy_file_with_context("/system_root/init", "/main_init", context); chmod("/main_init", EXEC_MASK_NEW); } diff --git a/multirom.h b/multirom.h index 00f46da5..26cd6951 100644 --- a/multirom.h +++ b/multirom.h @@ -114,6 +114,7 @@ struct multirom_status int enable_kmsg_logging; int hide_internal; char *int_display_name; + char os_version[6]; int rotation; int force_generic_fb; int use_primary_kernel; diff --git a/rom_quirks.c b/rom_quirks.c index 1ce2e6c0..63608a6f 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -243,7 +243,7 @@ char* convert_to_raw(char* str) { return out; } -void rom_quirks_change_patch_and_osver() { +void rom_quirks_change_patch_and_osver(struct multirom_status *s, struct multirom_rom *to_boot) { char* path = "/system/build.prop"; struct bootimg primary_img; @@ -254,6 +254,7 @@ void rom_quirks_change_patch_and_osver() { if (libbootimg_init_load(&primary_img, "/dev/block/bootdevice/by-name/boot", LIBBOOTIMG_LOAD_ALL) < 0) { + ERROR("cant open /dev/block/bootdevice/by-name/boot\n"); return; } @@ -298,7 +299,7 @@ void rom_quirks_change_patch_and_osver() { char* existing_level_raw = convert_to_raw(existing_level); char* existing_ver_raw = convert_to_raw(existing_ver); - if (strtol(primary_os_ver_raw, NULL, 10) > strtol(existing_ver_raw, NULL, 10) || strtol(primary_os_level_raw, NULL, 10) > strtol(existing_level_raw, NULL, 10)) { + if (strtol(primary_os_ver_raw, NULL, 10) > strtol(existing_ver_raw, NULL, 10) || strtol(primary_os_level_raw, NULL, 10) > strtol(existing_level_raw, NULL, 10) || s->use_primary_kernel || !to_boot->has_bootimg) { existing_level = strstr(filebuf, "ro.build.version.security_patch"); @@ -314,6 +315,7 @@ void rom_quirks_change_patch_and_osver() { destfile = open("/build.prop", O_RDWR | O_CREAT, 0644); write(destfile, filebuf, strlen(filebuf)); + INFO("build.prop %s\n", filebuf); close(destfile); diff --git a/rom_quirks.h b/rom_quirks.h index 5e311490..5b493548 100644 --- a/rom_quirks.h +++ b/rom_quirks.h @@ -17,9 +17,11 @@ #ifndef ROM_QUIRKS_H #define ROM_QUIRKS_H +#include + struct multirom_rom; void rom_quirks_on_initrd_finalized(void); -void rom_quirks_change_patch_and_osver(); +void rom_quirks_change_patch_and_osver(struct multirom_status *s, struct multirom_rom *to_boot); #endif diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index 8dd3c93f..b976b7d1 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -22,6 +22,8 @@ #include #include #include +#include +#include #include #include #include @@ -33,6 +35,7 @@ #include #include #include +#include #include "devices.h" #include "../lib/log.h" @@ -620,8 +623,13 @@ int main(int argc, char *argv[]) fixup_symlinks(); + char* context = calloc(1, 50); + getfilecon("/main_init", &context); + INFO("context of main_init is %s", context); chmod("/main_init", EXEC_MASK); rename("/main_init", "/init"); + getfilecon("/init", &context); + INFO("context of init is %s", context); pthread_t klog_thread; if(pthread_create(&klog_thread, NULL, klog_periodic, NULL)) { @@ -631,6 +639,25 @@ int main(int argc, char *argv[]) } + char *addr; + int initfd = open("/init", O_RDWR); + struct stat st; + stat("/init", &st); + size_t size = st.st_size; + addr = mmap(NULL, size, PROT_WRITE, MAP_SHARED, initfd, 0); + for (char *p = addr; p < addr + size; ++p) { + if (memcmp(p, "/system/bin/init", sizeof("/system/bin/init")) == 0) { + // Force execute /init instead of /system/bin/init + INFO("Patch init: [/system/bin/init] -> [/init]\n"); + strcpy(p, "/init"); + p += sizeof("/system/bin/init") - 1; + } + } + munmap(addr, size); + close(initfd); + + //setexeccon("u:object_r:kernel:s0"); + //trampoline_copy_log(NULL, "/data/last_kmsg"); res = execve(cmd[0], cmd, NULL); //trampoline_copy_log(NULL, "/data/last_kmsg"); From 193d39b801282f1740e2523878d81bca066e6aad Mon Sep 17 00:00:00 2001 From: Shahan Rai Date: Sat, 20 Jul 2019 20:26:55 +0530 Subject: [PATCH 50/65] Fix derp where whole system dir was being copied --- lib/util.c | 10 +++++----- lib/util.h | 4 ++-- 2 files changed, 7 insertions(+), 7 deletions(-) diff --git a/lib/util.c b/lib/util.c index da07641f..c3ce6faf 100644 --- a/lib/util.c +++ b/lib/util.c @@ -380,7 +380,7 @@ int setattr(const char *path, struct file_attr *a) { return 0; } -void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context) { +void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char* exclude_dir) { char in[256]; char out[256]; @@ -395,7 +395,7 @@ void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context) { ERROR("copying dir %s to %s\n", dirpath, target); while((dp = readdir(d))) { - if((dp->d_name[0] == '.' && strlen(dp->d_name) == 1) || (dp->d_name[0] == '.' && dp->d_name[1] == '.') || (!strcmp(dp->d_name, "system"))) + if((dp->d_name[0] == '.' && strlen(dp->d_name) == 1) || (dp->d_name[0] == '.' && dp->d_name[1] == '.') || (exclude_dir && !strcmp(dp->d_name, exclude_dir))) continue; sprintf(in, "%s/%s", dirpath, dp->d_name); @@ -418,7 +418,7 @@ void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context) { mkdir_with_perms(out, 0755, NULL, NULL); } setattr(out, &a); - copy_dir_contents(dir, in, out); + copy_dir_contents(dir, in, out, exclude_dir); continue; } else if (dp->d_type == DT_LNK) { char target[256]; @@ -441,8 +441,8 @@ void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context) { } -void copy_dir_contents(DIR* d, char* dirpath, char* target) { - clone_dir(d, dirpath, target, false); +void copy_dir_contents(DIR* d, char* dirpath, char* target, char* exclude_dir) { + clone_dir(d, dirpath, target, false, exclude_dir); } int write_file(const char *path, const char *value) diff --git a/lib/util.h b/lib/util.h index 65d3d718..79159535 100644 --- a/lib/util.h +++ b/lib/util.h @@ -48,8 +48,8 @@ void remove_link(const char *oldpath, const char *newpath); int wait_for_file(const char *filename, int timeout); int copy_file(const char *from, const char *to); int copy_file_with_context(const char *from, const char *to, char* context); -void copy_dir_contents(DIR* d, char* dirpath, char* target); -void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context); +void copy_dir_contents(DIR* d, char* dirpath, char* target, char* exclude_dir); +void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char* exclude_dir); int copy_dir(const char *from, const char *to); int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const char *group); int mkdir_with_perms_context(const char *path, mode_t mode, const char *owner, const char *group, char* context); From 271667d65b90be4eab8ff6d18d903519a39e9bff Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 20 Jul 2019 20:28:32 +0530 Subject: [PATCH 51/65] Patch init to support selinux enforcing on android Q Patch borrowed from magisk --- multirom.c | 66 +++++++++++++++++++++++++++++++++++++++++------------- multirom.h | 5 ++++- 2 files changed, 54 insertions(+), 17 deletions(-) diff --git a/multirom.c b/multirom.c index baadfb04..a3f5d38f 100644 --- a/multirom.c +++ b/multirom.c @@ -22,9 +22,11 @@ #include #include #include +#include #include #include #include +#include #include #include #include @@ -85,8 +87,7 @@ static volatile int run_usb_refresh = 0; static pthread_t usb_refresh_thread; static pthread_mutex_t parts_mutex = PTHREAD_MUTEX_INITIALIZER; static void (*usb_refresh_handler)(void) = NULL; -void copy_dir_contents(DIR* d, char* dirpath, char* target); -void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts); +void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts, char* exclude_dirs); bool LoadSplitPolicy(); @@ -94,7 +95,7 @@ void disable_dtb_fstab(char* partition) { //return; if (access("status", F_OK)) { DIR* dir = opendir("/proc/device-tree/firmware/android"); - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab"); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); FILE* fp = fopen("status", "w"); fprintf(fp, "disabled"); fclose(fp); @@ -107,7 +108,7 @@ void disable_dtb_fstab(char* partition) { void remove_dtb_fstab() { mkdir("/dummy_fw", S_IFDIR); DIR* dir = opendir("/proc/device-tree/firmware/android"); - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab"); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); if (!mount("/dummy_fw", "/fakefstab", "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("dummy dtb node bind mounted in procfs\n"); } else { @@ -323,10 +324,20 @@ int multirom_get_current_oslevel(struct multirom_status *s) return -1; } - char* secondary_os_version = libbootimg_get_osversion(&secondary_img.hdr, true); - char* secondary_os_level = libbootimg_get_oslevel(&secondary_img.hdr, true); + char* secondary_os_version = libbootimg_get_osversion(&secondary_img.hdr, false); + char* secondary_os_level = libbootimg_get_oslevel(&secondary_img.hdr, false); + char* secondary_os_version_raw = libbootimg_get_osversion(&secondary_img.hdr, true); + char* secondary_os_level_raw = libbootimg_get_oslevel(&secondary_img.hdr, true); + + memset(s->os_version, 0, sizeof(s->os_version)); + memset(s->os_level, 0, sizeof(s->os_level)); + memset(s->os_version_raw, 0, sizeof(s->os_version_raw)); + memset(s->os_level_raw, 0, sizeof(s->os_level_raw)); - memcpy(s->os_version, secondary_os_version, 6); + memcpy(s->os_version, secondary_os_version, strlen(secondary_os_version)); + memcpy(s->os_level, secondary_os_level, strlen(secondary_os_level)); + memcpy(s->os_version_raw, secondary_os_version_raw, strlen(secondary_os_version_raw)); + memcpy(s->os_level_raw, secondary_os_level_raw, strlen(secondary_os_level_raw)); return 0; } @@ -1525,10 +1536,10 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to decompress_rd("/.temprd", "/.newrd", &type); if (!access("/.newrd/second", F_OK)) { DIR* dir = opendir("/.newrd/second"); - copy_init_contents(dir, "/.newrd/second", "/", true); + copy_init_contents(dir, "/.newrd/second", "/", true, "system"); } else { DIR* dir = opendir("/.newrd"); - copy_init_contents(dir, "/.newrd", "/", true); + copy_init_contents(dir, "/.newrd", "/", true, "system"); } } @@ -1661,7 +1672,7 @@ bool is_symlink(const char *filename) } } -void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts) { +void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts, char* exclude_dir) { char in[256]; char out[256]; @@ -1671,7 +1682,7 @@ void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_conte char *fstab_name = NULL; DIR* dir = NULL; ERROR("copying dir %s\n", dirpath); - clone_dir(d, dirpath, target, preserve_contexts); + clone_dir(d, dirpath, target, preserve_contexts, exclude_dir); } bool GetVendorMappingVersion(char** plat_vers) { @@ -1901,7 +1912,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom rom_quirks_on_initrd_finalized(); LoadSplitPolicy(); DIR* dir = opendir("/system_root"); - copy_init_contents(dir, "/system_root", "/", true); + copy_init_contents(dir, "/system_root", "/", true, "system"); } sprintf(path, "%s/boot", rom->base_path); @@ -1910,13 +1921,36 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom rom_quirks_on_initrd_finalized(); LoadSplitPolicy(); } - copy_init_contents(dir, path, "/", false); - if (!access("/system/bin/init", F_OK) && is_symlink("/system_root/init")) { + copy_init_contents(dir, path, "/", false, "system"); + if (system_as_root && !access("/system/bin/init", F_OK) && is_symlink("/system_root/init")) { char* context = calloc(1, 50); + char* initPath = "/main_init"; getfilecon("/system/bin/init", &context); - copy_file_with_context("/system/bin/init", "/main_init", "u:object_r:rootfs:s0"); + if (multirom_path_exists("/", "/.backup/init")) { + copy_file_with_context("/system/bin/init", "/main_init", "u:object_r:rootfs:s0"); + } else { + copy_file_with_context("/system/bin/init", "/.backup/init", "u:object_r:rootfs:s0"); + initPath = "/.backup/init"; + } + + char *addr; + int initfd = open(initPath, O_RDWR); + struct stat st; + lstat(initPath, &st); + size_t size = st.st_size; + addr = mmap(NULL, size, PROT_WRITE, MAP_SHARED, initfd, 0); + for (char *p = addr; p < addr + size; ++p) { + if (memcmp(p, "/system/bin/init", sizeof("/system/bin/init")) == 0) { + // Force execute /init instead of /system/bin/init + INFO("Patch init: [/system/bin/init] -> [/init]\n"); + strcpy(p, "/init"); + p += sizeof("/system/bin/init") - 1; + } + } + munmap(addr, size); + close(initfd); chmod("/main_init", EXEC_MASK_NEW); - } else if (!is_symlink("/system_root/init") && !access("/system_root/init", F_OK)) { + } else if (system_as_root && !is_symlink("/system_root/init") && !access("/system_root/init", F_OK)) { char* context = calloc(1, 50); getfilecon("/system_root/init", &context); copy_file_with_context("/system_root/init", "/main_init", context); diff --git a/multirom.h b/multirom.h index 26cd6951..544060eb 100644 --- a/multirom.h +++ b/multirom.h @@ -114,7 +114,10 @@ struct multirom_status int enable_kmsg_logging; int hide_internal; char *int_display_name; - char os_version[6]; + char os_version[20]; + char os_level[20]; + char os_version_raw[20]; + char os_level_raw[20]; int rotation; int force_generic_fb; int use_primary_kernel; From dc2f2ef87c3b09974c364befc7b569cf685c47ee Mon Sep 17 00:00:00 2001 From: Shahan Rai Date: Sat, 20 Jul 2019 20:29:52 +0530 Subject: [PATCH 52/65] Allow mix and match of security patch and os version --- rom_quirks.c | 20 +++++++------------- 1 file changed, 7 insertions(+), 13 deletions(-) diff --git a/rom_quirks.c b/rom_quirks.c index 63608a6f..33b88089 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -246,24 +246,16 @@ char* convert_to_raw(char* str) { void rom_quirks_change_patch_and_osver(struct multirom_status *s, struct multirom_rom *to_boot) { char* path = "/system/build.prop"; - struct bootimg primary_img; char* patchstring = NULL, *stringtoappend = NULL; char* existing_ver = NULL; char* existing_level = NULL; int sourcefile, destfile, n; - if (libbootimg_init_load(&primary_img, "/dev/block/bootdevice/by-name/boot", LIBBOOTIMG_LOAD_ALL) < 0) - { - ERROR("cant open /dev/block/bootdevice/by-name/boot\n"); - return; - } + char* primary_os_version = s->os_version; + char* primary_os_level = s->os_level; - char* primary_os_version = libbootimg_get_osversion(&primary_img.hdr, false); - char* primary_os_level = libbootimg_get_oslevel(&primary_img.hdr, false); - - char* primary_os_ver_raw = libbootimg_get_osversion(&primary_img.hdr, true); - char* primary_os_level_raw = libbootimg_get_oslevel(&primary_img.hdr, true); - libbootimg_destroy(&primary_img); + char* primary_os_ver_raw = s->os_version_raw; + char* primary_os_level_raw = s->os_level_raw; sourcefile = open(path, O_RDONLY, 0644); @@ -299,7 +291,9 @@ void rom_quirks_change_patch_and_osver(struct multirom_status *s, struct multiro char* existing_level_raw = convert_to_raw(existing_level); char* existing_ver_raw = convert_to_raw(existing_ver); - if (strtol(primary_os_ver_raw, NULL, 10) > strtol(existing_ver_raw, NULL, 10) || strtol(primary_os_level_raw, NULL, 10) > strtol(existing_level_raw, NULL, 10) || s->use_primary_kernel || !to_boot->has_bootimg) { + INFO("primary %s existing %s", primary_os_level_raw, existing_level_raw); + + if (strtol(primary_os_ver_raw, NULL, 10) != strtol(existing_ver_raw, NULL, 10) || strtol(primary_os_level_raw, NULL, 10) != strtol(existing_level_raw, NULL, 10) || s->use_primary_kernel || !to_boot->has_bootimg) { existing_level = strstr(filebuf, "ro.build.version.security_patch"); From 53201f0f4fcd582585c592c8743fb13909fcf1cf Mon Sep 17 00:00:00 2001 From: Shahan Rai Date: Sat, 20 Jul 2019 20:31:11 +0530 Subject: [PATCH 53/65] Fix no multirom menu on arter kernel --- trampoline/Android.mk | 4 ++++ trampoline/trampoline.c | 22 +++------------------- 2 files changed, 7 insertions(+), 19 deletions(-) diff --git a/trampoline/Android.mk b/trampoline/Android.mk index 24553bab..84933873 100644 --- a/trampoline/Android.mk +++ b/trampoline/Android.mk @@ -68,4 +68,8 @@ ifeq ($(MR_USE_DEBUGFS_MOUNT),true) LOCAL_CFLAGS += -DMR_USE_DEBUGFS_MOUNT endif +ifeq ($(MR_DEVICE_HAS_DRM_GRAPHICS),true) + LOCAL_CFLAGS += -DMR_DEVICE_HAS_DRM_GRAPHICS +endif + include $(BUILD_EXECUTABLE) diff --git a/trampoline/trampoline.c b/trampoline/trampoline.c index b976b7d1..6a9a181c 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.c @@ -22,7 +22,6 @@ #include #include #include -#include #include #include #include @@ -432,11 +431,13 @@ static int run_core(void) int res = -1; struct fstab *fstab = NULL; +#ifndef MR_DEVICE_HAS_DRM_GRAPHICS if(wait_for_file("/dev/graphics/fb0", 5) < 0) { ERROR("Waiting too long for fb0"); goto exit; } +#endif #ifdef MR_POPULATE_BY_NAME_PATH Populate_ByName_using_emmc(); @@ -610,7 +611,7 @@ int main(int argc, char *argv[]) if (access("/fakefstab/", F_OK)) { DIR* dir = opendir("/proc/device-tree/firmware/android"); - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab"); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); } umount("/proc"); umount("/sys/fs/pstore"); @@ -639,23 +640,6 @@ int main(int argc, char *argv[]) } - char *addr; - int initfd = open("/init", O_RDWR); - struct stat st; - stat("/init", &st); - size_t size = st.st_size; - addr = mmap(NULL, size, PROT_WRITE, MAP_SHARED, initfd, 0); - for (char *p = addr; p < addr + size; ++p) { - if (memcmp(p, "/system/bin/init", sizeof("/system/bin/init")) == 0) { - // Force execute /init instead of /system/bin/init - INFO("Patch init: [/system/bin/init] -> [/init]\n"); - strcpy(p, "/init"); - p += sizeof("/system/bin/init") - 1; - } - } - munmap(addr, size); - close(initfd); - //setexeccon("u:object_r:kernel:s0"); //trampoline_copy_log(NULL, "/data/last_kmsg"); From 0c11f75968d6ee7f86da43768975d86ba581a998 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 28 Sep 2019 14:45:35 +0530 Subject: [PATCH 54/65] Update to support android 10 --- lib/klog.c | 2 +- lib/util.c | 17 ++- lib/util.h | 4 +- multirom.c | 129 ++++++++++++++++---- rom_quirks.c | 26 +++- trampoline/Android.mk | 4 +- trampoline/encryption.c | 2 +- trampoline/{trampoline.c => trampoline.cpp} | 95 ++++++++++++-- 8 files changed, 229 insertions(+), 50 deletions(-) rename trampoline/{trampoline.c => trampoline.cpp} (86%) diff --git a/lib/klog.c b/lib/klog.c index 51dcce5e..379a36db 100644 --- a/lib/klog.c +++ b/lib/klog.c @@ -53,7 +53,7 @@ void multirom_klog_init(void) { } } -#define LOG_BUF_MAX 512 +#define LOG_BUF_MAX 51200 void multirom_klog_writev(int level, const struct iovec* iov, int iov_count) { if (level > klog_level) return; diff --git a/lib/util.c b/lib/util.c index c3ce6faf..27304721 100644 --- a/lib/util.c +++ b/lib/util.c @@ -380,7 +380,18 @@ int setattr(const char *path, struct file_attr *a) { return 0; } -void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char* exclude_dir) { +bool is_in_list(char** stack, char* needle) { + int i = 0; + while (stack[i] != NULL) { + if (!strcmp(stack[i], needle)) { + return true; + } + i++; + } + return false; +} + +void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char** exclude_dir) { char in[256]; char out[256]; @@ -395,7 +406,7 @@ void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char* ERROR("copying dir %s to %s\n", dirpath, target); while((dp = readdir(d))) { - if((dp->d_name[0] == '.' && strlen(dp->d_name) == 1) || (dp->d_name[0] == '.' && dp->d_name[1] == '.') || (exclude_dir && !strcmp(dp->d_name, exclude_dir))) + if((dp->d_name[0] == '.' && strlen(dp->d_name) == 1) || (dp->d_name[0] == '.' && dp->d_name[1] == '.') || (exclude_dir && exclude_dir[0] && is_in_list(exclude_dir, dp->d_name))) continue; sprintf(in, "%s/%s", dirpath, dp->d_name); @@ -441,7 +452,7 @@ void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char* } -void copy_dir_contents(DIR* d, char* dirpath, char* target, char* exclude_dir) { +void copy_dir_contents(DIR* d, char* dirpath, char* target, char** exclude_dir) { clone_dir(d, dirpath, target, false, exclude_dir); } diff --git a/lib/util.h b/lib/util.h index 79159535..4950f0e7 100644 --- a/lib/util.h +++ b/lib/util.h @@ -48,8 +48,8 @@ void remove_link(const char *oldpath, const char *newpath); int wait_for_file(const char *filename, int timeout); int copy_file(const char *from, const char *to); int copy_file_with_context(const char *from, const char *to, char* context); -void copy_dir_contents(DIR* d, char* dirpath, char* target, char* exclude_dir); -void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char* exclude_dir); +void copy_dir_contents(DIR* d, char* dirpath, char* target, char** exclude_dir); +void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char** exclude_dir); int copy_dir(const char *from, const char *to); int mkdir_with_perms(const char *path, mode_t mode, const char *owner, const char *group); int mkdir_with_perms_context(const char *path, mode_t mode, const char *owner, const char *group, char* context); diff --git a/multirom.c b/multirom.c index a3f5d38f..d62b9e47 100644 --- a/multirom.c +++ b/multirom.c @@ -76,6 +76,10 @@ #define BATTERY_CAP "/sys/class/power_supply/battery/capacity" #define DT_FSTAB_PATH "/proc/device-tree/firmware/android/fstab/" +#define EXEC_MASK (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) +#define EXEC_MASK_NEW (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) +#define EXEC_MASK_RW (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) + static char busybox_path[64] = { 0 }; static char kexec_path[64] = { 0 }; static char ntfs_path[64] = { 0 }; @@ -87,7 +91,7 @@ static volatile int run_usb_refresh = 0; static pthread_t usb_refresh_thread; static pthread_mutex_t parts_mutex = PTHREAD_MUTEX_INITIALIZER; static void (*usb_refresh_handler)(void) = NULL; -void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts, char* exclude_dirs); +void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts, char** exclude_dirs); bool LoadSplitPolicy(); @@ -95,7 +99,8 @@ void disable_dtb_fstab(char* partition) { //return; if (access("status", F_OK)) { DIR* dir = opendir("/proc/device-tree/firmware/android"); - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); + char** exclude_dirs = NULL; + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", exclude_dirs); FILE* fp = fopen("status", "w"); fprintf(fp, "disabled"); fclose(fp); @@ -108,7 +113,8 @@ void disable_dtb_fstab(char* partition) { void remove_dtb_fstab() { mkdir("/dummy_fw", S_IFDIR); DIR* dir = opendir("/proc/device-tree/firmware/android"); - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); + char** exclude_dirs = NULL; + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", exclude_dirs); if (!mount("/dummy_fw", "/fakefstab", "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("dummy dtb node bind mounted in procfs\n"); } else { @@ -129,6 +135,15 @@ int mount_dtb_fstab(char* partition) { sprintf(type, "%s%s", root_path, "/type"); sprintf(mnt_flags, "%s%s", root_path, "/mnt_flags"); + if (!strcmp(partition, "system") && !multirom_path_exists("/", "apex")) { + partition = "system_root"; + mkdir_with_perms("/system_root", 0755, NULL, NULL); + if (access("/system/bin/init", F_OK)) { + mkdir_with_perms("/system/bin", 0755, NULL, NULL); + copy_file("/init", "/system/bin/init"); + chmod("/system/bin/init", EXEC_MASK_NEW); + } + } if (!(rc = mount(read_file(device), partition, read_file(type), MS_RDONLY, "barrier=1,discard"))) { INFO("dtb %s mount successful\n", partition); } else { @@ -1509,7 +1524,7 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to // remove_dtb_fstab(); } rom_quirks_on_initrd_finalized(); - LoadSplitPolicy(); + //LoadSplitPolicy(); break; } case ROM_LINUX_INTERNAL: @@ -1536,10 +1551,12 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to decompress_rd("/.temprd", "/.newrd", &type); if (!access("/.newrd/second", F_OK)) { DIR* dir = opendir("/.newrd/second"); - copy_init_contents(dir, "/.newrd/second", "/", true, "system"); + char* exclude_dirs[] = {"system", "vendor", "product", NULL}; + copy_init_contents(dir, "/.newrd/second", "/", true, exclude_dirs); } else { DIR* dir = opendir("/.newrd"); - copy_init_contents(dir, "/.newrd", "/", true, "system"); + char* exclude_dirs[] = {"system", "vendor", "product", NULL}; + copy_init_contents(dir, "/.newrd", "/", true, exclude_dirs); } } @@ -1568,9 +1585,6 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to return exit; } -#define EXEC_MASK (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP) -#define EXEC_MASK_NEW (S_IRUSR | S_IWUSR | S_IXUSR | S_IRGRP | S_IXGRP | S_IROTH | S_IXOTH) -#define EXEC_MASK_RW (S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH) char *multirom_find_fstab_in_rc(const char *rcfile) { @@ -1672,7 +1686,7 @@ bool is_symlink(const char *filename) } } -void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts, char* exclude_dir) { +void copy_init_contents(DIR* d, char* dirpath, char* target, bool preserve_contexts, char** exclude_dir) { char in[256]; char out[256]; @@ -1726,12 +1740,12 @@ bool LoadSplitPolicy() { return false; } // Determine which mapping file to include - char* vend_plat_vers; - if (!GetVendorMappingVersion(&vend_plat_vers)) { + char* vend_plat_vers = read_file("/vendor/etc/selinux/plat_sepolicy_vers.txt"); + if (!vend_plat_vers) { return false; } char* mapping_file = NULL; - asprintf(&mapping_file, "/system/etc/selinux/mapping/%s.cil","28.0"); + asprintf(&mapping_file, "/system/etc/selinux/mapping/%s.cil",vend_plat_vers); // vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace // nonplat_sepolicy.cil. char* plat_pub_versioned_cil_file = "/vendor/etc/selinux/plat_pub_versioned.cil"; @@ -1748,10 +1762,24 @@ bool LoadSplitPolicy() { // odm_sepolicy.cil is default but optional. const char* version_as_string = NULL; asprintf(&version_as_string, "%d", max_policy_version); - const char plat_policy_cil_file[] = "/system/etc/selinux/plat_sepolicy.cil"; + char* plat_policy_cil_file = "/system/etc/selinux/plat_sepolicy.cil"; + char* plat_policy_cil_file_sar = "/system/system/etc/selinux/plat_sepolicy.cil"; + if (!access(plat_policy_cil_file_sar, F_OK)) { + plat_policy_cil_file = plat_policy_cil_file_sar; + } + char mapping_file_sar[] = "/system/system/etc/selinux/mapping/29.0.cil"; + if (!access(mapping_file_sar, F_OK)) { + mapping_file = mapping_file_sar; + } + + char* secilc = "/system/bin/secilc"; + char* secilc_sar = "/system/system/bin/secilc"; + if (!access(secilc_sar, F_OK)) { + secilc = secilc_sar; + } // clang-format off char* compile_args[] = { - "/system/bin/secilc", + secilc, plat_policy_cil_file, "-m", "-M", "true", "-G", "-N", // Target the highest policy language version supported by the kernel @@ -1822,7 +1850,6 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom mkdir_with_perms("/system", 0755, NULL, NULL); mkdir_with_perms("/data", 0771, "system", "system"); mkdir_with_perms("/cache", 0770, "system", "cache"); - mkdir_with_perms("/vendor", 0755, NULL, NULL); if(has_fw) mkdir_with_perms("/firmware", 0771, "system", "system"); @@ -1831,9 +1858,20 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom * So we can safely remove it */ if (lstat("/vendor_boot", &stat) == 0) { - remove("/vendor"); - rename("/vendor_boot", "/vendor"); + INFO("/vendor_boot found"); + int error = unlink("/vendor"); + if (error == -1) { + INFO("unlink failed!!: %s\n", strerror(errno)); + } + error = rename("/vendor_boot", "/vendor"); + if (error == -1) { + INFO("rename failed!!: %s\n", strerror(errno)); + } + } else { + INFO("/vendor_boot not found"); + unlink("/vendor"); } + mkdir_with_perms("/vendor", 0755, NULL, NULL); static const char *folders[4] = { "system" , "vendor" , "data" , "cache"}; unsigned long flags[4] = { MS_RDONLY , MS_RDONLY, MS_NOSUID | MS_NODEV , MS_NOSUID | MS_NODEV}; @@ -1896,9 +1934,10 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom //System as root detection char* system_path = NULL; bool system_as_root = false; + bool modern_sar = false; asprintf(&system_path, "%s/system.sparse.img", rom->base_path); - if (!multirom_path_exists("/system", "init.rc")) { + if (!multirom_path_exists("/system", "init.rc") && multirom_path_exists("/", "apex")) { umount("/system"); mkdir_with_perms("/system_root", 0755, NULL, NULL); multirom_mount_image(system_path, "/system_root", "ext4", MS_RDONLY, NULL); @@ -1912,7 +1951,36 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom rom_quirks_on_initrd_finalized(); LoadSplitPolicy(); DIR* dir = opendir("/system_root"); - copy_init_contents(dir, "/system_root", "/", true, "system"); + char* exclude_dirs[] = {"system", "vendor", "product", NULL}; + copy_init_contents(dir, "/system_root", "/", true, exclude_dirs); + } else if (!multirom_path_exists("/", "apex")) { + umount("/system"); + mkdir_with_perms("/system_root", 0755, NULL, NULL); + multirom_mount_image(system_path, "/system_root", "ext4", MS_RDONLY, NULL); + system_as_root = true; + modern_sar = true; + //DIR* dir = opendir("/system_root"); + //char* exclude_dirs[] = {"system", "vendor", "product", NULL}; + //copy_init_contents(dir, "/system_root", "/", true, exclude_dirs); + /*if(mount("/vendor", "/system_root/vendor", "ext4", MS_BIND | MS_RDONLY, "discard,nomblk_io_submit") < 0) { + INFO("mount error\n"); + } else { + INFO("Bind mounted /vendor on /system_root/vendor\n"); + }*/ + rom_quirks_on_initrd_finalized(); + if (access("/system/bin/init", F_OK)) { + mkdir_with_perms("/system/bin", 0755, NULL, NULL); + copy_file("/init", "/system/bin/init"); + chmod("/system/bin/init", EXEC_MASK_NEW); + } + //LoadSplitPolicy(); + /*char* context = calloc(1, 50); + getfilecon("/system_root/system/bin/init", &context); + mkdir_with_perms("/system/bin", 0755, NULL, NULL); + copy_file_with_context("/system_root/system/bin/init", "/system/bin/init", context);*/ + //DIR* dir = opendir("/system"); + //char* exclude_dirs[] = {"system", "vendor", "product", NULL}; + //copy_init_contents(dir, "/system", "/", true, exclude_dirs); } sprintf(path, "%s/boot", rom->base_path); @@ -1921,8 +1989,9 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom rom_quirks_on_initrd_finalized(); LoadSplitPolicy(); } - copy_init_contents(dir, path, "/", false, "system"); - if (system_as_root && !access("/system/bin/init", F_OK) && is_symlink("/system_root/init")) { + char* exclude_dirs[] = {"system", "vendor", "product", NULL}; + copy_init_contents(dir, path, "/", false, exclude_dirs); + if (system_as_root && !access("/system/bin/init", F_OK) && is_symlink("/system_root/init") && !modern_sar) { char* context = calloc(1, 50); char* initPath = "/main_init"; getfilecon("/system/bin/init", &context); @@ -1950,7 +2019,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom munmap(addr, size); close(initfd); chmod("/main_init", EXEC_MASK_NEW); - } else if (system_as_root && !is_symlink("/system_root/init") && !access("/system_root/init", F_OK)) { + } else if (system_as_root && !is_symlink("/system_root/init") && !access("/system_root/init", F_OK) && !modern_sar) { char* context = calloc(1, 50); getfilecon("/system_root/init", &context); copy_file_with_context("/system_root/init", "/main_init", context); @@ -1960,11 +2029,11 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom if(multirom_process_android_fstab(fstab_name, has_fw, &fw_part, 0) != 0) { INFO("fstab couldnt be found in ramdisk. Rom maybe treble. Retry after vendor mount\n"); } else { - found_fstab = 1; + //found_fstab = 1; } if(!found_fstab && multirom_process_android_fstab(NULL, has_fw, &fw_part, 1) != 0) { INFO("fstab not found even in vendor!\n"); - goto exit; + //goto exit; } @@ -1978,6 +2047,9 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom if(statfs(to, &statfs_buf) < 0) ERROR("Couldn't statfs %s (%d: %s)\n", to, errno, strerror(errno)); else if((flags[i] & ~statfs_buf.f_flags)) { + if (modern_sar && !strcmp(to, "/system")) { + snprintf(to, sizeof(to), "/system_root"); + } INFO("Mount flags of %s are 0x%08lX but should include 0x%08lX, attempting remount\n", to, (unsigned long) statfs_buf.f_flags, flags[i]); @@ -2153,7 +2225,12 @@ int multirom_process_android_fstab(char *fstab_name, int has_fw, struct fstab_pa int multirom_create_media_link(struct multirom_status *s) { int media_new = 0; - int api_level = multirom_get_api_level("/system/build.prop"); + char* buildprop = "/system/build.prop"; + char* buildprop_sar = "/system_root/system/build.prop"; + if (!access(buildprop_sar, F_OK)) { + buildprop = buildprop_sar; + } + int api_level = multirom_get_api_level(buildprop); if(api_level <= 0) return -1; diff --git a/rom_quirks.c b/rom_quirks.c index 33b88089..54d0227e 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -138,6 +138,11 @@ void rom_quirks_on_initrd_finalized(void) // walk over all _regular_ files in / char* path = "/system/etc/selinux/plat_file_contexts"; + char* mnt_path = "/system/etc/selinux/plat_file_contexts"; + char* pathsar = "/system_root/system/etc/selinux/plat_file_contexts"; + if (!access(pathsar, F_OK)) { + path = pathsar; + } if (!access(path, F_OK)) { char buf; int sourcefile, destfile, n; @@ -200,8 +205,13 @@ void rom_quirks_on_initrd_finalized(void) closedir(d); } - if (!access(path, F_OK)) { - if(!mount("/plat_file_contexts", path, "ext4", MS_BIND, "discard,nomblk_io_submit")) { + if (access("/system/etc/selinux", F_OK)) { + mkdir_with_perms("/system/etc/", 0755, "root", "root"); + mkdir_with_perms("/system/etc/selinux", 0755, "root", "root"); + copy_file("/plat_file_contexts", "/system/etc/selinux/plat_file_contexts"); + } + if (!access(mnt_path, F_OK)) { + if(!mount("/plat_file_contexts", mnt_path, "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("file_contexts bind mounted in system\n"); } else { ERROR("file_contexts bind mount failed! %s\n", strerror(errno)); @@ -246,6 +256,11 @@ char* convert_to_raw(char* str) { void rom_quirks_change_patch_and_osver(struct multirom_status *s, struct multirom_rom *to_boot) { char* path = "/system/build.prop"; + char* mnt_path = "/system/build.prop"; + char* pathsar = "/system_root/system/build.prop"; + if (!access(pathsar, F_OK)) { + path = pathsar; + } char* patchstring = NULL, *stringtoappend = NULL; char* existing_ver = NULL; char* existing_level = NULL; @@ -313,8 +328,11 @@ void rom_quirks_change_patch_and_osver(struct multirom_status *s, struct multiro close(destfile); - if (!access(path, F_OK)) { - if(!mount("/build.prop", path, "ext4", MS_BIND, "discard,nomblk_io_submit")) { + if (access("/system/build.prop", F_OK)) { + copy_file("/build.prop", "/system/build.prop"); + } + if (!access(mnt_path, F_OK)) { + if(!mount("/build.prop", mnt_path, "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("build.prop bind mounted in system\n"); } else { ERROR("build.prop bind mount failed! %s\n", strerror(errno)); diff --git a/trampoline/Android.mk b/trampoline/Android.mk index 84933873..a69d3ff5 100644 --- a/trampoline/Android.mk +++ b/trampoline/Android.mk @@ -3,7 +3,7 @@ include $(CLEAR_VARS) LOCAL_C_INCLUDES += $(multirom_local_path) $(multirom_local_path)/lib LOCAL_SRC_FILES:= \ - trampoline.c \ + trampoline.cpp \ devices.c \ adb.c \ @@ -72,4 +72,6 @@ ifeq ($(MR_DEVICE_HAS_DRM_GRAPHICS),true) LOCAL_CFLAGS += -DMR_DEVICE_HAS_DRM_GRAPHICS endif +LOCAL_CPPFLAGS += $(LOCAL_CFLAGS) + include $(BUILD_EXECUTABLE) diff --git a/trampoline/encryption.c b/trampoline/encryption.c index 30a4ae0d..b45aaf6c 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -155,7 +155,7 @@ int encryption_cleanup(void) tramp_hook_encryption_cleanup(); #endif if (lstat("/vendor_boot", &stat) == 0) { - remove("/vendor"); + unlink("/vendor"); rename("/vendor_boot", "/vendor"); } diff --git a/trampoline/trampoline.c b/trampoline/trampoline.cpp similarity index 86% rename from trampoline/trampoline.c rename to trampoline/trampoline.cpp index 6a9a181c..6a09046f 100644 --- a/trampoline/trampoline.c +++ b/trampoline/trampoline.cpp @@ -15,6 +15,7 @@ * along with MultiROM. If not, see . */ +extern "C" { #define _GNU_SOURCE #include #include @@ -24,6 +25,7 @@ #include #include #include +#include #include #include #include @@ -51,6 +53,11 @@ #endif #include "trampoline.h" +} + +#include +#include +#include static char path_multirom[64] = { 0 }; @@ -86,7 +93,7 @@ int fork_and_exec_with_stdout(char *cmd, char *const *envp) { close(fd[1]); - char *res = malloc(512); + char *res = (char*)malloc(512); char buffer[512]; int size = 512, written = 0, len; while ((len = read(fd[0], buffer, sizeof(buffer))) > 0) @@ -94,7 +101,7 @@ int fork_and_exec_with_stdout(char *cmd, char *const *envp) if(written + len + 1 > size) { size = written + len + 256; - res = realloc(res, size); + res = (char*)realloc(res, size); } memcpy(res+written, buffer, len); written += len; @@ -281,6 +288,7 @@ static int mount_and_run(struct fstab *fstab) } mkdir(REALDATA, 0755); + mkdir("/data", 0755); if(try_mount_all_entries(fstab, datap) < 0) { @@ -384,6 +392,48 @@ static void fixup_symlinks(void) } } +static void switch_root(const char* path) { + INFO("Switch root to %s\n", path); + FILE *fp = setmntent("/proc/mounts", "re"); + if (fp) { + struct mntent mentry; + char buf[4096]; + std::vector v; + bool add = true; + while (getmntent_r(fp, &mentry, buf, sizeof(buf))) { + if (!strcmp(mentry.mnt_dir, "/") || !strcmp(mentry.mnt_dir, path)) { + INFO("skip %s\n", mentry.mnt_dir); + continue; + } + + for (auto i : v) { + if (!strncmp(mentry.mnt_dir, i.data(), i.length())) { + add = false; + break; + } else { + add = true; + } + } + + if (add) { + v.emplace_back(mentry.mnt_dir); + INFO("%s added to vector\n", mentry.mnt_dir); + } else { + INFO("%s not added to vector\n", mentry.mnt_dir); + } + } + endmntent(fp); + + for (auto i : v) { + char* new_path = NULL; + asprintf(&new_path, "%s%s", path, i.data()); + INFO("move mount point %s to %s\n", i.data(), new_path); + mkdir(new_path, 0755); + mount(i.data(), new_path, NULL, MS_MOVE, NULL); + } + } +} + static int do_cmdline(int argc, char *argv[]) { int i; @@ -391,6 +441,35 @@ static int do_cmdline(int argc, char *argv[]) char *mrom_dir = NULL; int force_inject = 0; + if (argc > 1 && !strcmp(argv[1], "selinux_setup")) { + INFO("multirom second stage init\n"); + //remove_dir("/system"); + switch_root("/system_root"); + int error = chdir("/system_root"); + if (error == -1) { + INFO("chdir failed!!: %s\n", strerror(errno)); + } else { + INFO("chdir returned %d\n", error); + } + error = mount("/system_root", "/", NULL, MS_MOVE, NULL); + if (error == -1) { + INFO("mount failed!!: %s\n", strerror(errno)); + } else { + INFO("mount returned %d\n", error); + } + error = chroot("."); + if (error == -1) { + INFO("chroot failed!!: %s\n", strerror(errno)); + } else { + INFO("chroot returned %d\n", error); + } + int res; + static char *const cmd[] = { "/init", "selinux_setup", NULL }; + res = execv(cmd[0], cmd); + return 0; + } + + for(i = 1; i < argc; ++i) { if(strcmp(argv[i], "-v") == 0) @@ -484,7 +563,7 @@ char *trampoline_get_klog(void) if (len < 16*1024) len = 16*1024; else if (len > 16*1024*1024) len = 16*1024*1024; - char *buff = malloc(len + 1); + char *buff = (char*)malloc(len + 1); len = klogctl(3, buff, len); if(len <= 0) { @@ -624,7 +703,7 @@ int main(int argc, char *argv[]) fixup_symlinks(); - char* context = calloc(1, 50); + char* context = (char*)calloc(1, 50); getfilecon("/main_init", &context); INFO("context of main_init is %s", context); chmod("/main_init", EXEC_MASK); @@ -632,14 +711,6 @@ int main(int argc, char *argv[]) getfilecon("/init", &context); INFO("context of init is %s", context); - pthread_t klog_thread; - if(pthread_create(&klog_thread, NULL, klog_periodic, NULL)) { - - fprintf(stderr, "Error creating thread\n"); - return 1; - - } - //setexeccon("u:object_r:kernel:s0"); //trampoline_copy_log(NULL, "/data/last_kmsg"); From 659604d6134da80295bf8d5ae35d06d5458c4f19 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 9 Nov 2019 16:38:10 +0530 Subject: [PATCH 55/65] Fix bugs in parsing cmdline --- lib/inject.c | 1 + multirom.c | 8 ++++++-- rom_quirks.c | 5 ++++- 3 files changed, 11 insertions(+), 3 deletions(-) diff --git a/lib/inject.c b/lib/inject.c index 7c4c0a7d..c6bc0452 100644 --- a/lib/inject.c +++ b/lib/inject.c @@ -335,6 +335,7 @@ int inject_cmdline(struct bootimg *image) libbootimg_set_cmdline(&image->hdr, newcmdline); free(newcmdline); + free(cmdline); } return res; diff --git a/multirom.c b/multirom.c index d62b9e47..3e08dfd5 100644 --- a/multirom.c +++ b/multirom.c @@ -1516,14 +1516,17 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to { if (!access(DT_FSTAB_PATH, F_OK)) { if (mount_dtb_fstab("system") == 0) { - disable_dtb_fstab("system"); + rom_quirks_on_initrd_finalized(); + umount("/system_root"); + //disable_dtb_fstab("system"); } //if (mount_dtb_fstab("vendor") == 0) { //disable_dtb_fstab("vendor"); // } // remove_dtb_fstab(); + } else { + rom_quirks_on_initrd_finalized(); } - rom_quirks_on_initrd_finalized(); //LoadSplitPolicy(); break; } @@ -1744,6 +1747,7 @@ bool LoadSplitPolicy() { if (!vend_plat_vers) { return false; } + vend_plat_vers[4] = '\0'; char* mapping_file = NULL; asprintf(&mapping_file, "/system/etc/selinux/mapping/%s.cil",vend_plat_vers); // vendor_sepolicy.cil and plat_pub_versioned.cil are the new design to replace diff --git a/rom_quirks.c b/rom_quirks.c index 54d0227e..113962aa 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -205,7 +205,8 @@ void rom_quirks_on_initrd_finalized(void) closedir(d); } - if (access("/system/etc/selinux", F_OK)) { + if (access("/system/etc/selinux/plat_file_contexts", F_OK)) { + mkdir_with_perms("/system/", 0755, "root", "root"); mkdir_with_perms("/system/etc/", 0755, "root", "root"); mkdir_with_perms("/system/etc/selinux", 0755, "root", "root"); copy_file("/plat_file_contexts", "/system/etc/selinux/plat_file_contexts"); @@ -216,6 +217,8 @@ void rom_quirks_on_initrd_finalized(void) } else { ERROR("file_contexts bind mount failed! %s\n", strerror(errno)); } + } else { + INFO("No mount point to bind!!"); } if (failed_file_contexts_injections) From 2abe345fff3819a968435ca347ba6af2d92da33e Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Wed, 1 Jan 2020 17:38:24 +0530 Subject: [PATCH 56/65] Fix storage access on Q --- multirom.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/multirom.c b/multirom.c index 3e08dfd5..cc059962 100644 --- a/multirom.c +++ b/multirom.c @@ -369,6 +369,7 @@ int multirom(const char *rom_to_boot) multirom_load_status(&s); multirom_dump_status(&s); + multirom_get_current_oslevel(&s); if (s.enable_kmsg_logging != 0) { @@ -511,7 +512,6 @@ int multirom(const char *rom_to_boot) if (s.is_second_boot != 0) { - multirom_get_current_oslevel(&s); // Restore primary boot.img, and continue if (nokexec_restore_primary_and_cleanup() < 0) MR_NO_KEXEC_ABORT; @@ -2078,7 +2078,8 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom snprintf(from, sizeof(from), "%s/firmware.img", rom->base_path); fw_part->device = realloc(fw_part->device, strlen(from)+1); strcpy(fw_part->device, from); - multirom_inject_fw_mounter(s, fw_part); + multirom_mount_image(from, MR_FIRMWARE_DIR, "vfat", MS_RDONLY, "shortname=lower,uid=0,gid=1000,dmask=227,fmask=337,context=u:object_r:firmware_file:s0"); + //multirom_inject_fw_mounter(s, fw_part); } #if MR_DEVICE_HOOKS >= 1 @@ -2278,6 +2279,7 @@ int multirom_create_media_link(struct multirom_status *s) return -1; } +#if 0 if(api_level >= 17) { char buf[16]; @@ -2307,6 +2309,7 @@ int multirom_create_media_link(struct multirom_status *s) // but can't do it here because selinux was not initialized rcadditions_append_trigger(&s->rc, "post-fs-data", " restorecon " LAYOUT_VERSION "\n"); } +#endif return 0; } From 6a979cd4b202255882598145cb812979b6848bb9 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 22 Aug 2020 18:25:50 +0530 Subject: [PATCH 57/65] Support FBE. Android cannot boot this way though. --- install_zip/Android.mk | 4 +- lib/util.c | 2 + trampoline/Android.mk | 2 +- trampoline/encryption.c | 88 +++++++++++-------- trampoline/encryption.h | 4 +- trampoline/trampoline.cpp | 30 +++++-- trampoline_encmnt/Android.mk | 10 ++- trampoline_encmnt/encmnt.cpp | 126 +++++++++++++++++++++------- trampoline_encmnt/fake_properties.c | 71 ++++++++++++++++ trampoline_encmnt/pw_ui.cpp | 32 ++++--- trampoline_encmnt/pw_ui.h | 2 +- 11 files changed, 281 insertions(+), 90 deletions(-) diff --git a/install_zip/Android.mk b/install_zip/Android.mk index 527a12e5..26503ec1 100644 --- a/install_zip/Android.mk +++ b/install_zip/Android.mk @@ -17,9 +17,9 @@ ifeq ($(MR_ENCRYPTION),true) multirom_extra_dep += trampoline_encmnt linker multirom_cp_enc_libs := \ - libcryptfslollipop.so libcrypto.so libc.so libcutils.so \ + libcryptfslollipop.so libcrypto.so libext4_utils.so libsparse.so libext2_uuid.so libe4crypt.so libc.so libcutils.so \ libdl.so libhardware.so liblog.so libm.so libstdc++.so \ - libc++.so + libc++.so libwifikeystorehal.so libsoftkeymasterdevice.so android.system.wifi.keystore@1.0.so android.hardware.weaver@1.0.so ifeq ($(TARGET_HW_DISK_ENCRYPTION),true) multirom_cp_enc_libs += \ diff --git a/lib/util.c b/lib/util.c index 27304721..6a19b42b 100644 --- a/lib/util.c +++ b/lib/util.c @@ -432,11 +432,13 @@ void clone_dir(DIR* d, char* dirpath, char* target, bool preserve_context, char* copy_dir_contents(dir, in, out, exclude_dir); continue; } else if (dp->d_type == DT_LNK) { + ERROR("copying link %s to %s\n", in, out); char target[256]; readlink(in, target, sizeof(target)); symlink(target, out); setattr(out, &a); } else if (dp->d_type == DT_REG) { + ERROR("copying file %s to %s\n", in, out); if (preserve_context) { char* context = calloc(1, 50); getfilecon(in, &context); diff --git a/trampoline/Android.mk b/trampoline/Android.mk index a69d3ff5..5203b74f 100644 --- a/trampoline/Android.mk +++ b/trampoline/Android.mk @@ -12,7 +12,7 @@ LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) -LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static libbootimg libselinux +LOCAL_STATIC_LIBRARIES := libcutils libc libmultirom_static libbootimg libselinux libext4_utils libkeyutils libbase liblog LOCAL_C_INCLUDES += system/extras/libbootimg/include LOCAL_FORCE_STATIC_EXECUTABLE := true diff --git a/trampoline/encryption.c b/trampoline/encryption.c index b45aaf6c..8d34248a 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -32,16 +32,18 @@ #include "../trampoline_encmnt/encmnt_defines.h" #include "../hooks.h" +extern int e4crypt_install_keyring(); + static char encmnt_cmd_arg[64] = { 0 }; static char *const encmnt_cmd[] = { "/mrom_enc/trampoline_encmnt", encmnt_cmd_arg, NULL }; #ifdef MR_ENCRYPTION_FAKE_PROPERTIES -static char *const encmnt_envp[] = { "LD_LIBRARY_PATH=/mrom_enc/", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", NULL }; +static char *const encmnt_envp[] = { "LD_CONFIG_FILE='/mrom_enc/ld.config.txt'", "LD_LIBRARY_PATH=/mrom_enc/", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", NULL }; #else -static char *const encmnt_envp[] = { "LD_LIBRARY_PATH=/mrom_enc/", NULL }; +static char *const encmnt_envp[] = { "LD_CONFIG_FILE='/mrom_enc/ld.config.txt'", "LD_LIBRARY_PATH=/mrom_enc/", NULL }; #endif static int g_decrypted = 0; -int encryption_before_mount(struct fstab *fstab) +int encryption_before_mount(struct fstab *fstab, bool isFbe) { int exit_code = -1; char *output = NULL, *itr; @@ -80,52 +82,70 @@ int encryption_before_mount(struct fstab *fstab) INFO("Running trampoline_encmnt\n"); - strcpy(encmnt_cmd_arg, "decrypt"); + if (isFbe) { + //rename("/realdata", "/data"); + int err = mount("/realdata", "/data", NULL, MS_MOVE, NULL); + INFO("err %d %s\n", err, strerror(errno)); + int ret = e4crypt_install_keyring(); + strcpy(encmnt_cmd_arg, "decryptfbe"); + } else { + strcpy(encmnt_cmd_arg, "decrypt"); + } output = run_get_stdout_with_exit_with_env(encmnt_cmd, &exit_code, encmnt_envp); - if(exit_code != 0 || !output) + if(exit_code != 0 || (!isFbe && !output)) { ERROR("Failed to run trampoline_encmnt, exit code %d: %s\n", exit_code, output); goto exit; } - itr = output + strlen(output) - 1; - while(itr >= output && isspace(*itr)) - *itr-- = 0; - - if(strcmp(output, ENCMNT_BOOT_INTERNAL_OUTPUT) == 0) - { - INFO("trampoline_encmnt requested to boot internal ROM.\n"); - res = ENC_RES_BOOT_INTERNAL; - goto exit; + if (!isFbe || exit_code != 0) { + itr = output + strlen(output) - 1; + while(itr >= output && isspace(*itr)) + *itr-- = 0; + + if(strcmp(output, ENCMNT_BOOT_INTERNAL_OUTPUT) == 0) + { + INFO("trampoline_encmnt requested to boot internal ROM.\n"); + res = ENC_RES_BOOT_INTERNAL; + goto exit; + } + + if(strcmp(output, ENCMNT_BOOT_RECOVERY_OUTPUT) == 0) + { + INFO("trampoline_encmnt requested to boot recovery.\n"); + res = ENC_RES_BOOT_RECOVERY; + goto exit; + } } - if(strcmp(output, ENCMNT_BOOT_RECOVERY_OUTPUT) == 0) - { - INFO("trampoline_encmnt requested to boot recovery.\n"); - res = ENC_RES_BOOT_RECOVERY; - goto exit; - } + if (!isFbe) { - if(!strstartswith(output, "/dev")) - { - ERROR("Invalid trampoline_encmnt output: %s\n", output); - goto exit; - } + if(!strstartswith(output, "/dev")) + { + ERROR("Invalid trampoline_encmnt output: %s\n", output); + goto exit; + } - g_decrypted = 1; + g_decrypted = 1; - struct fstab_part *datap = fstab_find_first_by_path(fstab, "/data"); - if(!datap) - { - ERROR("Failed to find /data in fstab!\n"); - goto exit; - } + struct fstab_part *datap = fstab_find_first_by_path(fstab, "/data"); + if(!datap) + { + ERROR("Failed to find /data in fstab!\n"); + goto exit; + } - INFO("Updating device %s to %s in fstab due to encryption.\n", datap->device, output); - fstab_update_device(fstab, datap->device, output); + INFO("Updating device %s to %s in fstab due to encryption.\n", datap->device, output); + fstab_update_device(fstab, datap->device, output); + } res = ENC_RES_OK; exit: + if (isFbe) { + //rename("/data", "/realdata"); + mount("/data", "/realdata", NULL, MS_MOVE, NULL); + mkdir("/data", 0755); + } free(output); return res; } diff --git a/trampoline/encryption.h b/trampoline/encryption.h index 068833c5..d40b94a9 100644 --- a/trampoline/encryption.h +++ b/trampoline/encryption.h @@ -24,11 +24,11 @@ #define ENC_RES_BOOT_RECOVERY 2 #ifdef MR_ENCRYPTION -int encryption_before_mount(struct fstab *fstab); +int encryption_before_mount(struct fstab *fstab, bool isFbe); void encryption_destroy(void); int encryption_cleanup(void); #else -int encryption_before_mount(struct fstab *fstab) { return ENC_RES_OK; } +int encryption_before_mount(struct fstab *fstab, bool isFbe) { return ENC_RES_OK; } void encryption_destroy(void) { } int encryption_cleanup(void) { return 0; } #endif diff --git a/trampoline/trampoline.cpp b/trampoline/trampoline.cpp index 6a09046f..da3a2ee7 100644 --- a/trampoline/trampoline.cpp +++ b/trampoline/trampoline.cpp @@ -241,8 +241,15 @@ static int try_mount_all_entries(struct fstab *fstab, struct fstab_part *first_d // su binaries on /data p_itr->mountflags &= ~(MS_NOSUID); - if(mount(p_itr->device, REALDATA, p_itr->type, p_itr->mountflags, p_itr->options) >= 0) - return 0; + if(mount(p_itr->device, REALDATA, p_itr->type, p_itr->mountflags, p_itr->options) >= 0) { + struct stat info; + if(stat("/realdata/unencrypted/key/version", &info) < 0) { + return 0; + } else { + INFO("File system is FBE encrypted"); + return -2; + } + } } while((p_itr = fstab_find_next_by_path(fstab, "/data", p_itr))); @@ -261,6 +268,13 @@ static int try_mount_all_entries(struct fstab *fstab, struct fstab_part *first_d if(mount(first_data_p->device, REALDATA, fs_types[i], first_data_p->mountflags, fs_opts[i]) >= 0) { INFO("/realdata successfuly mounted with fs %s\n", fs_types[i]); + struct stat info; + if(stat("/realdata/unencrypted/key/version", &info) < 0) { + return 0; + } else { + INFO("File system is FBE encrypted\n"); + return -2; + } return 0; } } @@ -290,14 +304,15 @@ static int mount_and_run(struct fstab *fstab) mkdir(REALDATA, 0755); mkdir("/data", 0755); - if(try_mount_all_entries(fstab, datap) < 0) + int ret = try_mount_all_entries(fstab, datap); + if(ret < 0) { #ifndef MR_ENCRYPTION ERROR("Failed to mount /data with all possible filesystems!\n"); return -1; #else - INFO("Failed to mount /data, trying encryption...\n"); - switch(encryption_before_mount(fstab)) + INFO("Failed to mount /realdata, trying encryption...\n"); + switch(encryption_before_mount(fstab, ret == -2)) { case ENC_RES_ERR: ERROR("/data decryption failed!\n"); @@ -314,7 +329,7 @@ static int mount_and_run(struct fstab *fstab) default: case ENC_RES_OK: { - if(try_mount_all_entries(fstab, datap) < 0) + if(ret != -2 && try_mount_all_entries(fstab, datap) < 0) { ERROR("Failed to mount decrypted /data with all possible filesystems!\n"); return -1; @@ -635,6 +650,7 @@ int main(int argc, char *argv[]) mkdir("/dev/socket", 0755); mkdir("/proc", 0755); mkdir("/sys", 0755); + mkdir("/tmp", 0755); mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"); mount("devpts", "/dev/pts", "devpts", 0, NULL); @@ -691,6 +707,8 @@ int main(int argc, char *argv[]) if (access("/fakefstab/", F_OK)) { DIR* dir = opendir("/proc/device-tree/firmware/android"); copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); + //remove("/fakefstab/fstab/system/mnt_point"); + rmdir("/fakefstab/fstab/vendor"); } umount("/proc"); umount("/sys/fs/pstore"); diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index 3d85a612..36611cb6 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -5,8 +5,8 @@ LOCAL_MODULE:= trampoline_encmnt LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) -LOCAL_SHARED_LIBRARIES := libcryptfslollipop libcutils -LOCAL_STATIC_LIBRARIES := libmultirom_static +LOCAL_SHARED_LIBRARIES := libcryptfslollipop libcutils libe4crypt +LOCAL_STATIC_LIBRARIES := libmultirom_static libext4_utils LOCAL_ADDITIONAL_DEPENDENCIES += libstdc++ @@ -29,8 +29,9 @@ else $(error Failed to find path to TWRP, which is required to build MultiROM with encryption support) endif -LOCAL_C_INCLUDES += $(multirom_local_path) $(mr_twrp_path) $(mr_twrp_path)/crypto/scrypt/lib/crypto external/openssl/include external/boringssl/include +LOCAL_C_INCLUDES += $(multirom_local_path) $(mr_twrp_path) $(mr_twrp_path)/crypto/scrypt/lib/crypto $(mr_twrp_path)/crypto/ext4crypt external/openssl/include external/boringssl/include LOCAL_C_INCLUDES += system/extras/libbootimg/include +LOCAL_C_INCLUDES += system/extras/ext4_utils/include/ext4_utils LOCAL_SRC_FILES := \ encmnt.cpp \ @@ -49,8 +50,9 @@ ifeq ($(MR_ENCRYPTION_FAKE_PROPERTIES),true) LOCAL_MODULE := libmultirom_fake_properties LOCAL_MODULE_TAGS := optional LOCAL_C_INCLUDES += $(multirom_local_path) + LOCAL_C_INCLUDES += system/extras/libbootimg/include - LOCAL_SRC_FILES := fake_properties.c + LOCAL_SRC_FILES := fake_properties.c klog.c LOCAL_SHARED_LIBRARIES := liblog ifneq ($(MR_ENCRYPTION_FAKE_PROPERTIES_EXTRAS),) diff --git a/trampoline_encmnt/encmnt.cpp b/trampoline_encmnt/encmnt.cpp index 2cf08433..f0bbc852 100644 --- a/trampoline_encmnt/encmnt.cpp +++ b/trampoline_encmnt/encmnt.cpp @@ -30,14 +30,16 @@ extern "C" { } #include "crypto/lollipop/cryptfs.h" +#include "crypto/ext4crypt/Decrypt.h" #include "pw_ui.h" #include "encmnt_defines.h" #define CMD_NONE 0 #define CMD_DECRYPT 1 -#define CMD_REMOVE 2 -#define CMD_PWTYPE 3 +#define CMD_DECRYPTFBE 2 +#define CMD_REMOVE 3 +#define CMD_PWTYPE 4 #define FSTAB_FLAGS "flags=" @@ -115,6 +117,64 @@ static int handle_pwtype(int stdout_fd) return 0; } +static int handle_decryptfbe(int stdout_fd, char *password) +{ + int retry_count = 3; + static const char *default_password = "!"; + int pwtype = -1; + //property_set("ro.crypto.state", "encrypted"); + //property_set("ro.crypto.type", "file"); + //INFO("return %d\n", ret); + while (!Decrypt_DE() && --retry_count) + usleep(2000); + if (retry_count > 0) { + std::string filename; + pwtype = Get_Password_Type(0, filename); + ERROR("Password type is %d %s\n", pwtype, filename.c_str()); + if (pwtype < 0) { + ERROR("This TWRP does not have synthetic password decrypt support\n"); + pwtype = 0; // default password + } + } + + if(pwtype < 0) + { + ERROR("get_password_type failed!"); + return -1; + } + else if (pwtype == CRYPT_TYPE_DEFAULT) + password = (char*)default_password; + + if (password) { + if (Decrypt_User(0, password)) { + return 0; + } + } else + { + switch(pw_ui_run(pwtype, true)) + { + default: + case ENCMNT_UIRES_ERROR: + ERROR("pw_ui_run() failed!\n"); + return -1; + case ENCMNT_UIRES_BOOT_INTERNAL: + INFO("Wants to boot internal!\n"); + write(stdout_fd, ENCMNT_BOOT_INTERNAL_OUTPUT, strlen(ENCMNT_BOOT_INTERNAL_OUTPUT)); + fsync(stdout_fd); + return 0; + case ENCMNT_UIRES_BOOT_RECOVERY: + INFO("Wants to boot recoveryl!\n"); + write(stdout_fd, ENCMNT_BOOT_RECOVERY_OUTPUT, strlen(ENCMNT_BOOT_RECOVERY_OUTPUT)); + fsync(stdout_fd); + return 0; + case ENCMNT_UIRES_PASS_OK: + return 0; + } + } + + return -1; +} + static int handle_decrypt(int stdout_fd, char *password) { DIR *d; @@ -148,7 +208,7 @@ static int handle_decrypt(int stdout_fd, char *password) } else { - switch(pw_ui_run(pwtype)) + switch(pw_ui_run(pwtype, false)) { default: case ENCMNT_UIRES_ERROR: @@ -247,7 +307,9 @@ int main(int argc, char *argv[]) } else if(cmd == CMD_NONE) { - if(strcmp(argv[i], "decrypt") == 0) + if(strcmp(argv[i], "decryptfbe") == 0) + cmd = CMD_DECRYPTFBE; + else if(strcmp(argv[i], "decrypt") == 0) cmd = CMD_DECRYPT; else if(strcmp(argv[i], "remove") == 0) cmd = CMD_REMOVE; @@ -266,37 +328,40 @@ int main(int argc, char *argv[]) return 0; } - fstab = fstab_auto_load(); - if(!fstab) - { - ERROR("Failed to load fstab!"); - return 1; - } + if (cmd == CMD_DECRYPT) { + fstab = fstab_auto_load(); + if(!fstab) + { + ERROR("Failed to load fstab!"); + return 1; + } - p = fstab_find_first_by_path(fstab, "/data"); - if(!p) - { - ERROR("Failed to find /data partition in fstab\n"); - goto exit; - } + p = fstab_find_first_by_path(fstab, "/data"); + if(!p) + { + ERROR("Failed to find /data partition in fstab\n"); + goto exit; + } - found_footer_location = 0; + found_footer_location = 0; - if(p->options) - found_footer_location = get_footer_from_opts(footer_location, sizeof(footer_location), p->options) == 0; + if(p->options) + found_footer_location = get_footer_from_opts(footer_location, sizeof(footer_location), p->options) == 0; - if(!found_footer_location && p->options2) - found_footer_location = get_footer_from_opts(footer_location, sizeof(footer_location), p->options2) == 0; + if(!found_footer_location && p->options2) + found_footer_location = get_footer_from_opts(footer_location, sizeof(footer_location), p->options2) == 0; - if(!found_footer_location) - { - ERROR("Failed to find footer location\n"); - goto exit; - } + if(!found_footer_location) + { + ERROR("Failed to find footer location\n"); + goto exit; + } - INFO("Setting encrypted partition data to %s %s %s\n", p->device, footer_location, p->type); - set_partition_data(p->device, footer_location, p->type); + INFO("Setting encrypted partition data to %s %s %s\n", p->device, footer_location, p->type); + set_partition_data(p->device, footer_location, p->type); + fstab_destroy(fstab); + } //cryptfs prints informations, we don't want that stdout_fd = dup(1); freopen("/dev/null", "ae", stdout); @@ -312,6 +377,10 @@ int main(int argc, char *argv[]) if(handle_decrypt(stdout_fd, argument) < 0) goto exit; break; + case CMD_DECRYPTFBE: + if(handle_decryptfbe(stdout_fd, argument) < 0) + goto exit; + break; case CMD_REMOVE: if(handle_remove() < 0) goto exit; @@ -320,6 +389,5 @@ int main(int argc, char *argv[]) res = 0; exit: - fstab_destroy(fstab); return res; } diff --git a/trampoline_encmnt/fake_properties.c b/trampoline_encmnt/fake_properties.c index a55fa92a..a41dd415 100644 --- a/trampoline_encmnt/fake_properties.c +++ b/trampoline_encmnt/fake_properties.c @@ -22,8 +22,13 @@ #include #include #include +#include "log.h" +#include +#include #define PROPERTY_SOCKET "/property_socket" +char* os_version = NULL; +char* os_level = NULL; /* MultiROM doesn't initialize the property service, * but decryption on Nexus 6P waits for one property to become true * so we hardcode it here @@ -74,12 +79,78 @@ int property_get(const char *key, char *value, const char *default_value) return strlen(value); } +void stdio_to_null(void) +{ + int fd = open("/dev/null", O_RDWR|O_CLOEXEC); + if(fd >= 0) + { + dup2(fd, 0); + dup2(fd, 1); + dup2(fd, 2); + close(fd); + } +} + +static int fork_and_exec(char *cmd, char** env, char** argv) +{ + pid_t pID = fork(); + if(pID == 0) + { + stdio_to_null(); + setpgid(0, getpid()); + if (strstr(cmd, "keystore_auth")) { + setuid(1000); + } else if (strstr(cmd, "keymaster") || strstr(cmd, "qsee")) { + } + setenv("LD_LIBRARY_PATH", "/mrom_enc", 1); + setenv("LD_PRELOAD", "/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", 1); + execve(cmd, argv, environ); + INFO("Failed to exec %s: %s\n", cmd[0], strerror(errno)); + _exit(127); + } + return pID; +} + +int keystore_pid = -1; +int keystore_auth_pid; + int property_set(char* property, char* value) { char* property_value; int i, s, len; struct sockaddr_un saun; + char* env[] = {"LD_CONFIG_FILE=/mron_enc/ld.config.txt", "LD_LIBRARY_PATH=/mrom_enc", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", NULL}; + if (property && value && strstr(property, "ctl.start") && !strcmp(value, "keystore")) { + char* args[] = {"keystore", "/tmp/misc/keystore", NULL}; + keystore_pid = fork_and_exec("/mrom_enc/keystore", env, args); + if (keystore_pid == -1) + INFO("Failed to fork for keymaster; should never happen!\n"); + else + INFO("keystore started: pid=%d\n", keystore_pid); + return 0; + } + + if (property && value && strstr(property, "ctl.start") && !strcmp(value, "keystore_auth")) { + char* args[] = {"keystore_auth", NULL}; + keystore_auth_pid = fork_and_exec("/mrom_enc/keystore_auth", env, args); + if (keystore_auth_pid == -1) + INFO("Failed to fork for keymaster; should never happen!\n"); + else + INFO("keystore started: pid=%d\n", keystore_auth_pid); + return 0; + } + + if (property && value && strstr(property, "ctl.stop") && !strcmp(value, "keystore")) { + if (keystore_pid != -1) + { + kill(-keystore_pid, SIGTERM); // kill the entire process group + waitpid(keystore_pid, NULL, 0); + ERROR("keystore killed %d\n", keystore_pid); + } + return 0; + } + ALOGE("property_set called for %s:%s\n", property, value); property_value = calloc(strlen(property) + strlen(value) + 1, 1); diff --git a/trampoline_encmnt/pw_ui.cpp b/trampoline_encmnt/pw_ui.cpp index dd9f3633..25977b1f 100644 --- a/trampoline_encmnt/pw_ui.cpp +++ b/trampoline_encmnt/pw_ui.cpp @@ -38,6 +38,7 @@ extern "C" { } #include "crypto/lollipop/cryptfs.h" +#include "crypto/ext4crypt/Decrypt.h" #define HEADER_HEIGHT (110*DPI_MUL) #define PWUI_DOT_R (15*DPI_MUL) @@ -53,6 +54,7 @@ struct pwui_type_pass_data { char *pass_buf; char *pass_buf_stars; size_t pass_buf_cap; + bool isFbe; }; struct pwui_type_pattern_data { @@ -63,6 +65,7 @@ struct pwui_type_pattern_data { int connected_dots[PWUI_DOTS_CNT]; size_t connected_dots_len; int touch_id; + bool isFbe; }; static pthread_mutex_t exit_code_mutex = PTHREAD_MUTEX_INITIALIZER; @@ -120,7 +123,7 @@ static void reveal_rect_alpha_step(void *data, float interpolated) fb_request_draw(); } -static int try_password(char *pass) +static int try_password(char *pass, bool isFbe) { fb_text_set_content(invalid_pass_text, ""); @@ -129,7 +132,12 @@ static int try_password(char *pass) ncard_set_text(b, "Verifying password..."); ncard_show(b, 1); - if(cryptfs_check_passwd(pass) != 0) + if (isFbe && Decrypt_User(0, pass) == false) { + ncard_hide(); + fb_text_set_content(invalid_pass_text, "Invalid password!"); + center_text(invalid_pass_text, 0, -1, fb_width, -1); + return -1; + } else if(!isFbe && cryptfs_check_passwd(pass) != 0) { ncard_hide(); fb_text_set_content(invalid_pass_text, "Invalid password!"); @@ -206,16 +214,17 @@ static void type_pass_key_pressed(void *data, uint8_t code) fb_request_draw(); break; case OSK_ENTER: - try_password(d->pass_buf); + try_password(d->pass_buf, d->isFbe); break; } } -static void type_pass_init(int pwtype) +static void type_pass_init(int pwtype, bool isFbe) { struct pwui_type_pass_data *d = (pwui_type_pass_data*)mzalloc(sizeof(struct pwui_type_pass_data)); d->keyboard = keyboard_create(pwtype == CRYPT_TYPE_PIN ? KEYBOARD_PIN : KEYBOARD_NORMAL, 0, fb_height*0.65, fb_width, fb_height*0.35); + d->isFbe = isFbe; keyboard_set_callback(d->keyboard, type_pass_key_pressed, d); d->passwd_text = fb_add_text(0, 0, C_TEXT, SIZE_BIG, ""); @@ -351,7 +360,7 @@ static int type_pattern_touch_handler(touch_event *ev, void *data) passwd[i] = '1' + d->connected_dots[i]; passwd[i] = 0; - if(try_password(passwd) < 0) + if(try_password(passwd, d->isFbe) < 0) { list_clear(&d->active_dots, (callback)fb_remove_item); list_clear(&d->complete_lines, (callback)fb_remove_item); @@ -364,7 +373,7 @@ static int type_pattern_touch_handler(touch_event *ev, void *data) return 0; } -static void type_pattern_init(void) +static void type_pattern_init(bool isFbe) { struct pwui_type_pattern_data *d = (pwui_type_pattern_data*)mzalloc(sizeof(struct pwui_type_pattern_data)); int cx, cy; @@ -388,6 +397,7 @@ static void type_pattern_init(void) } d->touch_id = -1; + d->isFbe = isFbe; add_touch_handler(type_pattern_touch_handler, d); pwui_type_data = d; @@ -405,7 +415,7 @@ static void type_pattern_destroy(void) pwui_type_data = NULL; } -static void init_ui(int pwtype) +static void init_ui(int pwtype, bool isFbe) { fb_add_rect_lvl(100, 0, 0, fb_width, HEADER_HEIGHT, C_HIGHLIGHT_BG); @@ -450,10 +460,10 @@ static void init_ui(int pwtype) { case CRYPT_TYPE_PASSWORD: case CRYPT_TYPE_PIN: - type_pass_init(pwtype); + type_pass_init(pwtype, isFbe); break; case CRYPT_TYPE_PATTERN: - type_pattern_init(); + type_pattern_init(isFbe); break; default: t = fb_add_text(0, 0, C_TEXT, SIZE_NORMAL, "Error: unknown password type %d", pwtype); @@ -491,7 +501,7 @@ static int pw_ui_shutdown_counter_touch_handler(UNUSED touch_event *ev, void *da return -1; } -int pw_ui_run(int pwtype) +int pw_ui_run(int pwtype, bool isFbe) { int shutdown_counter = 0; @@ -507,7 +517,7 @@ int pw_ui_run(int pwtype) workers_start(); anim_init(1.f); - init_ui(pwtype); + init_ui(pwtype, isFbe); start_input_thread(); add_touch_handler(pw_ui_shutdown_counter_touch_handler, &shutdown_counter); diff --git a/trampoline_encmnt/pw_ui.h b/trampoline_encmnt/pw_ui.h index 1a869509..64f86d29 100644 --- a/trampoline_encmnt/pw_ui.h +++ b/trampoline_encmnt/pw_ui.h @@ -18,6 +18,6 @@ #ifndef PW_UI_H #define PW_UI_H -int pw_ui_run(int pwtype); +int pw_ui_run(int pwtype, bool isFbe); #endif From 08526d2080c7973f4fbb9aeb9c833564964cd69d Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 25 Oct 2020 16:24:30 +0530 Subject: [PATCH 58/65] Attempt android 11 support --- multirom.c | 44 ++++++++++++++++++++++++++++++++++++-------- 1 file changed, 36 insertions(+), 8 deletions(-) diff --git a/multirom.c b/multirom.c index cc059962..d4674b73 100644 --- a/multirom.c +++ b/multirom.c @@ -122,6 +122,28 @@ void remove_dtb_fstab() { } } +int multirom_is_android10() { + if (!multirom_path_exists("/", "apex")) { + return 1; + } + char* initPath = "/main_init"; + if (!multirom_path_exists("/", "/.backup/init")) { + initPath = "/.backup/init"; + } + + char *addr; + int initfd = open(initPath, O_RDWR); + struct stat st; + lstat(initPath, &st); + size_t size = st.st_size; + addr = mmap(NULL, size, PROT_WRITE, MAP_SHARED, initfd, 0); + int contains = strstr(addr, "selinux_setup") != NULL; + munmap(addr, size); + close(initfd); + return contains; +} + + int mount_dtb_fstab(char* partition) { int rc = -1; @@ -135,7 +157,7 @@ int mount_dtb_fstab(char* partition) { sprintf(type, "%s%s", root_path, "/type"); sprintf(mnt_flags, "%s%s", root_path, "/mnt_flags"); - if (!strcmp(partition, "system") && !multirom_path_exists("/", "apex")) { + if (!strcmp(partition, "system") && multirom_is_android10()) { partition = "system_root"; mkdir_with_perms("/system_root", 0755, NULL, NULL); if (access("/system/bin/init", F_OK)) { @@ -356,7 +378,7 @@ int multirom_get_current_oslevel(struct multirom_status *s) return 0; } -int multirom(const char *rom_to_boot) +int multirom(const char *rom_to_boot, int always_reboot) { if(multirom_find_base_dir() == -1) { @@ -476,7 +498,11 @@ int multirom(const char *rom_to_boot) switch(multirom_ui(&s, &to_boot)) { - case UI_EXIT_BOOT_ROM: break; + case UI_EXIT_BOOT_ROM: + if (always_reboot) { + exit = (EXIT_REBOOT | EXIT_UMOUNT); + } + break; case UI_EXIT_REBOOT: exit = (EXIT_REBOOT | EXIT_UMOUNT); break; @@ -545,7 +571,7 @@ int multirom(const char *rom_to_boot) if(rom_to_boot == NULL) multirom_run_scripts("run-on-boot", to_boot); - exit = multirom_prepare_for_boot(&s, to_boot); + exit = multirom_prepare_for_boot(&s, to_boot, always_reboot); INFO("prepare for boot returned %d\n", exit); // Something went wrong, exit/reboot @@ -1493,9 +1519,9 @@ struct multirom_rom *multirom_get_rom_by_id(struct multirom_status *s, int id) return NULL; } -int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to_boot) +int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to_boot, int always_reboot) { - int exit = EXIT_UMOUNT; + int exit = always_reboot ? (EXIT_REBOOT | EXIT_UMOUNT) : EXIT_UMOUNT; int type = to_boot->type; @@ -1520,6 +1546,7 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to umount("/system_root"); //disable_dtb_fstab("system"); } + nokexec_set_skip_mr_flag(); //if (mount_dtb_fstab("vendor") == 0) { //disable_dtb_fstab("vendor"); // } @@ -1834,6 +1861,7 @@ bool LoadSplitPolicy() { return true; } + int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom *rom) { char in[128]; @@ -1941,7 +1969,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom bool modern_sar = false; asprintf(&system_path, "%s/system.sparse.img", rom->base_path); - if (!multirom_path_exists("/system", "init.rc") && multirom_path_exists("/", "apex")) { + if (!multirom_path_exists("/system", "init.rc") && !multirom_is_android10()) { umount("/system"); mkdir_with_perms("/system_root", 0755, NULL, NULL); multirom_mount_image(system_path, "/system_root", "ext4", MS_RDONLY, NULL); @@ -1957,7 +1985,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom DIR* dir = opendir("/system_root"); char* exclude_dirs[] = {"system", "vendor", "product", NULL}; copy_init_contents(dir, "/system_root", "/", true, exclude_dirs); - } else if (!multirom_path_exists("/", "apex")) { + } else if (multirom_is_android10()) { umount("/system"); mkdir_with_perms("/system_root", 0755, NULL, NULL); multirom_mount_image(system_path, "/system_root", "ext4", MS_RDONLY, NULL); From 65b1dd114cdf92088973ff9413a41a7611d8e6f2 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 25 Oct 2020 16:25:54 +0530 Subject: [PATCH 59/65] Reboot to primary again if on FBE Since File based encryption keys can't be added more than once per boot, we reboot the device after initial decryption and set multirom to skip the boot menu (just like what happens with secondary ROMs) for primary ROM as well. This will happen only on devices using FBE. Existing devices will continue seeing the current behaviour --- main.c | 6 +- no_kexec.c | 144 ++++++++++++++++++++++++++++++++++++-- no_kexec.h | 3 + trampoline/trampoline.cpp | 39 +++++++---- 4 files changed, 174 insertions(+), 18 deletions(-) diff --git a/main.c b/main.c index 9086c545..64face8b 100644 --- a/main.c +++ b/main.c @@ -51,6 +51,7 @@ int main(int argc, const char *argv[]) { int i; const char *rom_to_boot = NULL; + int always_reboot = 0; for(i = 1; i < argc; ++i) { @@ -105,6 +106,9 @@ int main(int argc, const char *argv[]) { rom_to_boot = argv[i] + sizeof("--boot-rom"); } + else if (!strcmp(argv[i], "alwaysreboot")) { + always_reboot = 1; + } } srand(time(0)); @@ -122,7 +126,7 @@ int main(int argc, const char *argv[]) if(rom_to_boot) mount(NULL, "/", NULL, MS_REMOUNT, NULL); - int exit = multirom(rom_to_boot); + int exit = multirom(rom_to_boot, always_reboot); if(rom_to_boot) mount(NULL, "/", NULL, MS_RDONLY | MS_REMOUNT, NULL); diff --git a/no_kexec.c b/no_kexec.c index e8076398..5364689e 100644 --- a/no_kexec.c +++ b/no_kexec.c @@ -76,22 +76,22 @@ char *nokexec_find_boot_mmcblk_path(struct multirom_status *s) INFO(NO_KEXEC_LOG_TEXT ": found boot at '%s'\n", boot->device); else { - INFO(NO_KEXEC_LOG_TEXT ": not found in fstab, try looking at mrom.fstab...\n"); + INFO(NO_KEXEC_LOG_TEXT ": not found in fstab, try looking at mrom_fstab...\n"); struct fstab *mrom_fstab; char path_mrom_fstab[256]; - sprintf(path_mrom_fstab, "%s/%s", mrom_dir(), "mrom.fstab"); + sprintf(path_mrom_fstab, "%s/%s", mrom_dir(), "mrom_fsbat"); mrom_fstab = fstab_load(path_mrom_fstab, 1); if (!mrom_fstab) { - ERROR(NO_KEXEC_LOG_TEXT ": couldn't load mrom.fstab '%s'\n", path_mrom_fstab); + ERROR(NO_KEXEC_LOG_TEXT ": couldn't load mrom_fstab '%s'\n", path_mrom_fstab); return NULL; } boot = fstab_find_first_by_path(mrom_fstab, "/boot"); if (boot) - INFO(NO_KEXEC_LOG_TEXT ": found boot (using mrom.fstab) at '%s'\n", boot->device); + INFO(NO_KEXEC_LOG_TEXT ": found boot (using mrom_fstab) at '%s'\n", boot->device); else return NULL; } @@ -185,6 +185,68 @@ int nokexec_set_secondary_flag(void) return res; } +int nokexec_set_skip_mr_flag(void) +{ + // echo -ne "\x71" | dd of=/dev/nk bs=1 seek=63 count=1 conv=notrunc + int res = -1; + struct bootimg img; + + // make note that the primary slot now contains a secondary boot.img + // by tagging the BOOT_NAME at the very end, even after a null terminated "tr_verNN" string + INFO(NO_KEXEC_LOG_TEXT ": Going to tag the bootimg in primary slot as skip_mr\n"); + + if (libbootimg_init_load(&img, nokexec_s.path_boot_mmcblk, LIBBOOTIMG_LOAD_ALL) < 0) + { + ERROR(NO_KEXEC_LOG_TEXT ": Could not open boot image (%s)!\n", nokexec_s.path_boot_mmcblk); + return -1; + } + + // Update the boot.img + img.hdr.name[BOOT_NAME_SIZE-1] = 0x72; + + INFO(NO_KEXEC_LOG_TEXT ": Writing boot.img updated with secondary flag set\n"); + if (libbootimg_write_img(&img, nokexec_s.path_boot_mmcblk) < 0) + { + ERROR("Failed to libbootimg_write_img!\n"); + } + else + res = 0; + + libbootimg_destroy(&img); + return res; +} + +int nokexec_unset_skip_mr_flag(void) +{ + // echo -ne "\x71" | dd of=/dev/nk bs=1 seek=63 count=1 conv=notrunc + int res = -1; + struct bootimg img; + + // make note that the primary slot now contains a secondary boot.img + // by tagging the BOOT_NAME at the very end, even after a null terminated "tr_verNN" string + INFO(NO_KEXEC_LOG_TEXT ": Going to tag the bootimg in primary slot as skip_mr\n"); + + if (libbootimg_init_load(&img, "/dev/block/bootdevice/by-name/boot", LIBBOOTIMG_LOAD_ALL) < 0) + { + ERROR(NO_KEXEC_LOG_TEXT ": Could not open boot image (%s)!\n", nokexec_s.path_boot_mmcblk); + return -1; + } + + // Update the boot.img + img.hdr.name[BOOT_NAME_SIZE-1] = 0x70; + + INFO(NO_KEXEC_LOG_TEXT ": Writing boot.img updated with secondary flag set\n"); + if (libbootimg_write_img(&img, "/dev/block/bootdevice/by-name/boot") < 0) + { + ERROR("Failed to libbootimg_write_img!\n"); + } + else + res = 0; + + libbootimg_destroy(&img); + return res; +} + int nokexec_set_oslevel(char *secondary_path) { int res = -1; @@ -322,6 +384,26 @@ int nokexec_is_secondary_in_primary(const char *path_boot_mmcblk) return res; } +int nokexec_is_skip_mr_flag(const char *path_boot_mmcblk) +{ + int res = 0; + struct boot_img_hdr hdr; + + if (libbootimg_load_header(&hdr, path_boot_mmcblk) < 0) + { + ERROR(NO_KEXEC_LOG_TEXT ": Could not open boot image (%s)!\n", path_boot_mmcblk); + res = -1; + } + else + { + if (hdr.name[BOOT_NAME_SIZE-1] == 0x72) + res = 1; + } + INFO(NO_KEXEC_LOG_TEXT ": Checking the primary slot bootimg for the secondary tag; res=%d\n", res); + + return res; +} + int nokexec_is_new_primary(void) { int is_new = 0; @@ -377,6 +459,40 @@ int nokexec_is_second_boot(void) return is_second_boot; } +int nokexec_is_skip_mr(void) +{ + static int is_second_boot = -1; + if(is_second_boot != -1) { + INFO(NO_KEXEC_LOG_TEXT ": returning cached info is_second_boot=%d\n", is_second_boot); + return is_second_boot; + } + + int res; + INFO(NO_KEXEC_LOG_TEXT ": Checking primary slot...\n"); + char * path_boot_mmcblk = nokexec_find_boot_mmcblk_path(NULL); + if (!path_boot_mmcblk) + return -1; + + res = nokexec_is_skip_mr_flag(path_boot_mmcblk); + free(path_boot_mmcblk); + + if (res < 0) + return -1; + else if (res == 1) + { + // it's a secondary boot.img so set second_boot=1 + INFO(NO_KEXEC_LOG_TEXT ": secondary bootimg, so second_boot=1\n"); + is_second_boot = 1; + } + else + { + INFO(NO_KEXEC_LOG_TEXT ": primary bootimg, so second_boot=0\n"); + is_second_boot = 0; + } + + return is_second_boot; +} + int nokexec_flash_secondary_bootimg(struct multirom_rom *secondary_rom) { @@ -408,6 +524,26 @@ int nokexec_flash_secondary_bootimg(struct multirom_rom *secondary_rom) return 0; } +int nokexec_flash_skip_mr_bootimg(struct multirom_rom *secondary_rom) +{ + // make sure all the paths are set up, otherwise abort + if (!nokexec_s.path_boot_mmcblk || !nokexec_s.path_primary_bootimg) + return -1; + + // now flash the secondary boot.img to primary slot + char path_bootimg[256]; + sprintf(path_bootimg, "%s/%s", secondary_rom->base_path, "boot.img"); + + if (nokexec_flash_to_primary(path_bootimg)) + return -3; + + // make note that the primary slot now contains a secondary boot.img + if (nokexec_set_skip_mr_flag()) + return -4; + + return 0; +} + int nokexec_restore_primary_and_cleanup(void) { // make sure all the paths are set up, otherwise abort diff --git a/no_kexec.h b/no_kexec.h index c45bd91c..b381c38b 100644 --- a/no_kexec.h +++ b/no_kexec.h @@ -82,5 +82,8 @@ int nokexec_restore_primary_and_cleanup(void); int nokexec_flash_secondary_bootimg(struct multirom_rom *secondary_rom); int nokexec_is_second_boot(void); +int nokexec_is_skip_mr(void); +int nokexec_set_skip_mr_flag(void); +int nokexec_unset_skip_mr_flag(void); #endif diff --git a/trampoline/trampoline.cpp b/trampoline/trampoline.cpp index da3a2ee7..4dd41a62 100644 --- a/trampoline/trampoline.cpp +++ b/trampoline/trampoline.cpp @@ -47,6 +47,7 @@ extern "C" { #include "adb.h" #include "../hooks.h" #include "encryption.h" +#include "../no_kexec.h" #ifdef MR_POPULATE_BY_NAME_PATH #include "Populate_ByName_using_emmc.c" @@ -190,7 +191,7 @@ static int find_multirom(void) return -1; } -static void run_multirom(void) +static void run_multirom(int isFbe) { char path[256]; struct stat info; @@ -217,11 +218,11 @@ static void run_multirom(void) } chmod(path, EXEC_MASK); - char *cmd[] = { path, NULL }; + const char *cmd[] = { path, isFbe ? "alwaysreboot" : NULL, NULL }; do { ERROR("Running multirom\n"); - int res = run_cmd(cmd); + int res = run_cmd((char**)cmd); if(res == 0) break; else @@ -340,15 +341,18 @@ static int mount_and_run(struct fstab *fstab) #endif } - if(find_multirom() == -1) - { - ERROR("Could not find multirom folder!\n"); - return -1; - } + if (ret == -2 && !nokexec_is_skip_mr()) { + INFO("skip mr flag false.. running multirom"); + if(find_multirom() == -1) + { + ERROR("Could not find multirom folder!\n"); + return -1; + } - adb_init(path_multirom); - run_multirom(); - adb_quit(); + adb_init(path_multirom); + run_multirom(ret == -2); + adb_quit(); + } return 0; } @@ -686,7 +690,12 @@ int main(int argc, char *argv[]) devices_init(); INFO("Done initializing\n"); - run_core(); + if (nokexec_is_skip_mr()) { + INFO("skip mr flag true.. setting it to false for next boot\n"); + nokexec_unset_skip_mr_flag(); + } else { + run_core(); + } // close and destroy everything devices_close(); @@ -695,6 +704,7 @@ int main(int argc, char *argv[]) umount("/dev/pts"); rmdir("/dev/pts"); rmdir("/dev/socket"); + rmdir("/tmp"); if(access(KEEP_REALDATA, F_OK) < 0) { umount("/dev"); @@ -708,7 +718,8 @@ int main(int argc, char *argv[]) DIR* dir = opendir("/proc/device-tree/firmware/android"); copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); //remove("/fakefstab/fstab/system/mnt_point"); - rmdir("/fakefstab/fstab/vendor"); + closedir(dir); + //remove("/fakefstab/fstab/vendor/mnt_point"); } umount("/proc"); umount("/sys/fs/pstore"); @@ -721,6 +732,8 @@ int main(int argc, char *argv[]) fixup_symlinks(); + //INFO("%s\n", read_file("strace-qseecomd")); + char* context = (char*)calloc(1, 50); getfilecon("/main_init", &context); INFO("context of main_init is %s", context); From 4a4c3c7b7a77cfe4524c6f59c1616f7323c28666 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 25 Oct 2020 16:30:16 +0530 Subject: [PATCH 60/65] Rename fstab to fsbat to skip magisk fstab detection I can't believe I have to do this --- install_zip/prebuilt-uninstaller/scripts/clear_boot.sh | 4 ++-- lib/fstab.c | 4 ++-- lib/inject.c | 4 ++-- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/install_zip/prebuilt-uninstaller/scripts/clear_boot.sh b/install_zip/prebuilt-uninstaller/scripts/clear_boot.sh index f927a831..1fc82d77 100644 --- a/install_zip/prebuilt-uninstaller/scripts/clear_boot.sh +++ b/install_zip/prebuilt-uninstaller/scripts/clear_boot.sh @@ -65,8 +65,8 @@ if [ -L /tmp/boot/sbin/watchdogd ] ; then ln -sf ../init /tmp/boot/sbin/watchdogd fi -if [ -e /tmp/boot/mrom.fstab ] ; then - rm /tmp/boot/mrom.fstab +if [ -e /tmp/boot/mrom_fsbat ] ; then + rm /tmp/boot/mrom_fsbat fi # Remove encryption files diff --git a/lib/fstab.c b/lib/fstab.c index a3fdaf3e..22847559 100644 --- a/lib/fstab.c +++ b/lib/fstab.c @@ -338,8 +338,8 @@ struct fstab *fstab_auto_load(void) char path[64]; path[0] = 0; - if(access("/mrom.fstab", F_OK) >= 0) - strcpy(path, "/mrom.fstab"); + if(access("/mrom_fsbat", F_OK) >= 0) + strcpy(path, "/mrom_fsbat"); else { DIR *d = opendir("/"); diff --git a/lib/inject.c b/lib/inject.c index c6bc0452..75b42b7b 100644 --- a/lib/inject.c +++ b/lib/inject.c @@ -73,7 +73,7 @@ static int copy_rd_files(UNUSED const char *path, const char *target) } snprintf(path_main, sizeof(path_main), "%s%s", target, "/main_init"); snprintf(path_mrom_enc, sizeof(path_mrom_enc), "%s%s", target, "/mrom_enc"); - snprintf(path_mrom_fstab, sizeof(path_mrom_fstab), "%s%s", target, "/mrom.fstab"); + snprintf(path_mrom_fstab, sizeof(path_mrom_fstab), "%s%s", target, "/mrom_fsbat"); snprintf(path_hwservice_contexts, sizeof(path_hwservice_contexts), "%s%s", target, "/plat_hwservice_contexts"); snprintf(path_nonplat_hwservice_contexts, sizeof(path_nonplat_hwservice_contexts), "%s%s", target, "/nonplat_hwservice_contexts"); snprintf(path_ueventd, sizeof(path_ueventd), "%s%s", target, "/sbin/ueventd"); @@ -99,7 +99,7 @@ static int copy_rd_files(UNUSED const char *path, const char *target) symlink("../main_init", path_watchdog); #ifdef MR_USE_MROM_FSTAB - snprintf(buf, sizeof(buf), "%s/mrom.fstab", mrom_dir()); + snprintf(buf, sizeof(buf), "%s/mrom_fsbat", mrom_dir()); copy_file(buf, path_mrom_fstab); #else remove(path_mrom_fstab); From b50be1331fa39cb4a21495d51624800b5653e4fe Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 25 Oct 2020 16:31:43 +0530 Subject: [PATCH 61/65] Add fake logger library This library used LD_PRELOAD injection to redirect logcat symbols to kernel logger since logcat is not available during early boot. Very useful while debugging. --- install_zip/Android.mk | 4 +++- lib/Android.mk | 9 +++++++++ lib/fake_logger.c | 18 ++++++++++++++++++ lib/klog.c | 10 +++++++--- lib/util.c | 11 +++++++++-- multirom.h | 4 ++-- trampoline/encryption.c | 6 +++--- trampoline_encmnt/Android.mk | 4 ++-- trampoline_encmnt/fake_properties.c | 20 +++++++------------- trampoline_encmnt/pw_ui.cpp | 2 +- 10 files changed, 61 insertions(+), 27 deletions(-) create mode 100644 lib/fake_logger.c diff --git a/install_zip/Android.mk b/install_zip/Android.mk index 26503ec1..e6344dc8 100644 --- a/install_zip/Android.mk +++ b/install_zip/Android.mk @@ -32,6 +32,8 @@ ifeq ($(MR_ENCRYPTION),true) multirom_cp_enc_libs += libmultirom_fake_properties.so multirom_extra_dep += libmultirom_fake_propertywait multirom_cp_enc_libs += libmultirom_fake_propertywait.so + multirom_extra_dep += libmultirom_fake_logger + multirom_cp_enc_libs += libmultirom_fake_logger.so endif else MR_ENCRYPTION := false @@ -103,7 +105,7 @@ $(MULTIROM_ZIP_TARGET): multirom trampoline signapk bbootimg mrom_kexec_static m @if [ -n "$(MR_INFOS)" ]; then cp -vr $(PWD)/$(MR_INFOS)/* $(MULTIROM_INST_DIR)/multirom/infos/; fi @echo Copying scripts @cp -a $(TARGET_OUT_OPTIONAL_EXECUTABLES)/bbootimg $(MULTIROM_INST_DIR)/scripts/ - @cp $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/multirom/mrom.fstab + @cp $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/multirom/mrom_fsbat @echo Preparing installer script @$(install_zip_path)/extract_boot_dev.sh $(PWD)/$(MR_FSTAB) $(MULTIROM_INST_DIR)/scripts/bootdev @$(install_zip_path)/make_updater_script.sh "$(MR_DEVICES)" $(MULTIROM_INST_DIR)/META-INF/com/google/android "Installing MultiROM for" diff --git a/lib/Android.mk b/lib/Android.mk index 532fc400..65e5ef54 100644 --- a/lib/Android.mk +++ b/lib/Android.mk @@ -91,7 +91,16 @@ include $(multirom_local_path)/device_defines.mk include $(BUILD_STATIC_LIBRARY) +include $(CLEAR_VARS) + +LOCAL_MODULE := libmultirom_fake_logger +LOCAL_MODULE_TAGS := optional +LOCAL_SRC_FILES := fake_logger.c +LOCAL_SRC_FILES += klog.c + + +include $(BUILD_SHARED_LIBRARY) include $(CLEAR_VARS) diff --git a/lib/fake_logger.c b/lib/fake_logger.c new file mode 100644 index 00000000..347ee78f --- /dev/null +++ b/lib/fake_logger.c @@ -0,0 +1,18 @@ +#include + +#define LOG_BUF_MAX 51200 +extern void multirom_klog_write(int level, const char* fmt, ...); +extern void multirom_klog_set_level(int level); +#define INFO(tag, fmt, ...) multirom_klog_write(6, "<6>%s: " fmt, tag, ##__VA_ARGS__) + +int __android_log_print(int prio, const char* tag, const char* fmt, ...) { + + char buf[LOG_BUF_MAX]; + va_list ap; + va_start(ap, fmt); + vsnprintf(buf, sizeof(buf), fmt, ap); + va_end(ap); + buf[LOG_BUF_MAX - 1] = 0; + INFO(tag, "%s", buf); + return 0; +} diff --git a/lib/klog.c b/lib/klog.c index 379a36db..fff10d71 100644 --- a/lib/klog.c +++ b/lib/klog.c @@ -41,18 +41,22 @@ void multirom_klog_set_level(int level) { void multirom_klog_init(void) { if (klog_fd >= 0) return; /* Already initialized */ - klog_fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); + /*klog_fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC); if (klog_fd >= 0) { return; - } + }*/ - static const char* name = "/dev/__kmsg__"; + static const char* name = "/__kmsg__"; if (mknod(name, S_IFCHR | 0600, (1 << 8) | 11) == 0) { klog_fd = open(name, O_WRONLY | O_CLOEXEC); unlink(name); } } +void multirom_klog_close() { + close(klog_fd); +} + #define LOG_BUF_MAX 51200 void multirom_klog_writev(int level, const struct iovec* iov, int iov_count) { diff --git a/lib/util.c b/lib/util.c index 6a19b42b..39e432bb 100644 --- a/lib/util.c +++ b/lib/util.c @@ -564,10 +564,17 @@ int run_cmd_with_env(char **cmd, char *const *envp) char* read_file(char* file) { - char* buf = calloc(1, 256); + char* buf = calloc(1, 256000); + int nread = 0; + int offset = 0; + char buff[256]; FILE* fp = fopen(file, "r"); if (fp) { - fread(buf, 1, 256, fp); + while ((nread = fread(buff, 1, 256, fp)) > 0) { + INFO("buf %s\n", buff); + memcpy(buf + offset, buff, nread); + offset += nread; + } fclose(fp); } else { ERROR("cannot open %s %s\n", file, strerror(errno)); diff --git a/multirom.h b/multirom.h index 544060eb..b1931d27 100644 --- a/multirom.h +++ b/multirom.h @@ -131,7 +131,7 @@ struct multirom_status struct rcadditions rc; }; -int multirom(const char *rom_to_boot); +int multirom(const char *rom_to_boot, int always_reboot); int multirom_find_base_dir(void); void multirom_emergency_reboot(void); int multirom_default_status(struct multirom_status *s); @@ -145,7 +145,7 @@ void multirom_import_internal(void); void multirom_dump_status(struct multirom_status *s); int multirom_save_status(struct multirom_status *s); void multirom_fixup_rom_name(struct multirom_rom *rom, char *name, const char *def); -int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to_boot); +int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to_boot, int always_reboot); void multirom_free_status(struct multirom_status *s); void multirom_free_rom(void *rom); int multirom_init_fb(int rotation); diff --git a/trampoline/encryption.c b/trampoline/encryption.c index 8d34248a..22ed29a5 100644 --- a/trampoline/encryption.c +++ b/trampoline/encryption.c @@ -37,7 +37,7 @@ extern int e4crypt_install_keyring(); static char encmnt_cmd_arg[64] = { 0 }; static char *const encmnt_cmd[] = { "/mrom_enc/trampoline_encmnt", encmnt_cmd_arg, NULL }; #ifdef MR_ENCRYPTION_FAKE_PROPERTIES -static char *const encmnt_envp[] = { "LD_CONFIG_FILE='/mrom_enc/ld.config.txt'", "LD_LIBRARY_PATH=/mrom_enc/", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", NULL }; +static char *const encmnt_envp[] = { "LD_CONFIG_FILE='/mrom_enc/ld.config.txt'", "LD_LIBRARY_PATH=/mrom_enc/", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so /mrom_enc/libmultirom_fake_logger.so", NULL }; #else static char *const encmnt_envp[] = { "LD_CONFIG_FILE='/mrom_enc/ld.config.txt'", "LD_LIBRARY_PATH=/mrom_enc/", NULL }; #endif @@ -98,7 +98,7 @@ int encryption_before_mount(struct fstab *fstab, bool isFbe) goto exit; } - if (!isFbe || exit_code != 0) { + if (output != NULL) { itr = output + strlen(output) - 1; while(itr >= output && isspace(*itr)) *itr-- = 0; @@ -146,7 +146,7 @@ int encryption_before_mount(struct fstab *fstab, bool isFbe) mount("/data", "/realdata", NULL, MS_MOVE, NULL); mkdir("/data", 0755); } - free(output); + //free(output); return res; } diff --git a/trampoline_encmnt/Android.mk b/trampoline_encmnt/Android.mk index 36611cb6..4cfecc75 100644 --- a/trampoline_encmnt/Android.mk +++ b/trampoline_encmnt/Android.mk @@ -5,7 +5,7 @@ LOCAL_MODULE:= trampoline_encmnt LOCAL_MODULE_TAGS := optional LOCAL_MODULE_PATH := $(TARGET_ROOT_OUT) LOCAL_UNSTRIPPED_PATH := $(TARGET_ROOT_OUT_UNSTRIPPED) -LOCAL_SHARED_LIBRARIES := libcryptfslollipop libcutils libe4crypt +LOCAL_SHARED_LIBRARIES := libcryptfslollipop libcutils libe4crypt libwifikeystorehal libsoftkeymasterdevice android.system.wifi.keystore@1.0 LOCAL_STATIC_LIBRARIES := libmultirom_static libext4_utils LOCAL_ADDITIONAL_DEPENDENCIES += libstdc++ @@ -52,7 +52,7 @@ ifeq ($(MR_ENCRYPTION_FAKE_PROPERTIES),true) LOCAL_C_INCLUDES += $(multirom_local_path) LOCAL_C_INCLUDES += system/extras/libbootimg/include - LOCAL_SRC_FILES := fake_properties.c klog.c + LOCAL_SRC_FILES := fake_properties.c LOCAL_SHARED_LIBRARIES := liblog ifneq ($(MR_ENCRYPTION_FAKE_PROPERTIES_EXTRAS),) diff --git a/trampoline_encmnt/fake_properties.c b/trampoline_encmnt/fake_properties.c index a41dd415..52c324bb 100644 --- a/trampoline_encmnt/fake_properties.c +++ b/trampoline_encmnt/fake_properties.c @@ -22,7 +22,7 @@ #include #include #include -#include "log.h" +//#include "log.h" #include #include @@ -105,7 +105,6 @@ static int fork_and_exec(char *cmd, char** env, char** argv) setenv("LD_LIBRARY_PATH", "/mrom_enc", 1); setenv("LD_PRELOAD", "/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", 1); execve(cmd, argv, environ); - INFO("Failed to exec %s: %s\n", cmd[0], strerror(errno)); _exit(127); } return pID; @@ -120,25 +119,21 @@ int property_set(char* property, char* value) { int i, s, len; struct sockaddr_un saun; - char* env[] = {"LD_CONFIG_FILE=/mron_enc/ld.config.txt", "LD_LIBRARY_PATH=/mrom_enc", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so", NULL}; + char* env[] = {"LD_CONFIG_FILE=/mron_enc/ld.config.txt", "LD_LIBRARY_PATH=/mrom_enc", "LD_PRELOAD=/mrom_enc/libmultirom_fake_properties.so /mrom_enc/libmultirom_fake_propertywait.so /mrom_enc/libmultirom_fake_logger.so", NULL}; if (property && value && strstr(property, "ctl.start") && !strcmp(value, "keystore")) { char* args[] = {"keystore", "/tmp/misc/keystore", NULL}; keystore_pid = fork_and_exec("/mrom_enc/keystore", env, args); - if (keystore_pid == -1) - INFO("Failed to fork for keymaster; should never happen!\n"); - else - INFO("keystore started: pid=%d\n", keystore_pid); + if (keystore_pid != -1) { + ALOGE("keystore running %d", keystore_pid); + } else { + ALOGE("keystore failed %d", keystore_pid); + } return 0; } if (property && value && strstr(property, "ctl.start") && !strcmp(value, "keystore_auth")) { char* args[] = {"keystore_auth", NULL}; keystore_auth_pid = fork_and_exec("/mrom_enc/keystore_auth", env, args); - if (keystore_auth_pid == -1) - INFO("Failed to fork for keymaster; should never happen!\n"); - else - INFO("keystore started: pid=%d\n", keystore_auth_pid); - return 0; } if (property && value && strstr(property, "ctl.stop") && !strcmp(value, "keystore")) { @@ -146,7 +141,6 @@ int property_set(char* property, char* value) { { kill(-keystore_pid, SIGTERM); // kill the entire process group waitpid(keystore_pid, NULL, 0); - ERROR("keystore killed %d\n", keystore_pid); } return 0; } diff --git a/trampoline_encmnt/pw_ui.cpp b/trampoline_encmnt/pw_ui.cpp index 25977b1f..8c3c6547 100644 --- a/trampoline_encmnt/pw_ui.cpp +++ b/trampoline_encmnt/pw_ui.cpp @@ -83,7 +83,7 @@ static void boot_internal_clicked(UNUSED void *data) // We need to run quirks for primary ROM to prevent // restorecon breaking everything - rom_quirks_on_initrd_finalized(); + //rom_quirks_on_initrd_finalized(); pthread_mutex_lock(&exit_code_mutex); exit_code = ENCMNT_UIRES_BOOT_INTERNAL; From 67410b4c2aa89c39e5370077c49d27e89e980681 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 6 Dec 2020 17:06:42 +0530 Subject: [PATCH 62/65] Fix unknown android version on 11 --- rom_quirks.c | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/rom_quirks.c b/rom_quirks.c index 113962aa..bb400166 100644 --- a/rom_quirks.c +++ b/rom_quirks.c @@ -309,7 +309,15 @@ void rom_quirks_change_patch_and_osver(struct multirom_status *s, struct multiro char* existing_level_raw = convert_to_raw(existing_level); char* existing_ver_raw = convert_to_raw(existing_ver); - INFO("primary %s existing %s", primary_os_level_raw, existing_level_raw); + if (strtol(existing_ver_raw, NULL, 10) >= 1100) { + free(patchstring); + asprintf(&patchstring, "%s=%s\n%s=%s\n%s=%s", "ro.build.version.security_patch", primary_os_level, "ro.build.version.release", primary_os_version, "ro.build.version.release_or_codename", primary_os_version); + free(filebuf); + filebuf = calloc(1, size + strlen(patchstring)); + + } + + INFO("primary %s %s existing %s", primary_os_level_raw, primary_os_ver_raw, existing_level_raw, existing_ver_raw); if (strtol(primary_os_ver_raw, NULL, 10) != strtol(existing_ver_raw, NULL, 10) || strtol(primary_os_level_raw, NULL, 10) != strtol(existing_level_raw, NULL, 10) || s->use_primary_kernel || !to_boot->has_bootimg) { From cb751b821d6b0e65f32156bf21a96b253c9b8ea0 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 6 Dec 2020 17:08:58 +0530 Subject: [PATCH 63/65] Fix fde booting --- lib/util.c | 35 ++++++++++++++++++++++------------- multirom.c | 6 ++++-- trampoline/trampoline.cpp | 2 +- 3 files changed, 27 insertions(+), 16 deletions(-) diff --git a/lib/util.c b/lib/util.c index 39e432bb..afa01233 100644 --- a/lib/util.c +++ b/lib/util.c @@ -994,12 +994,12 @@ int multirom_mount_image(const char *src, const char *dst, const char *fs, int f static int next_loop_num = MULTIROM_LOOP_NUM_START; char path[64]; int device_fd; - int loop_num = 0; - int res = -1; + int loop_num = -1; + int res = 0; struct stat info; struct loop_info64 lo_info; - for(loop_num = next_loop_num; loop_num < MAX_LOOP_NUM; ++loop_num) + /*for(loop_num = next_loop_num; loop_num < MAX_LOOP_NUM; ++loop_num) { sprintf(path, "/dev/block/loop%d", loop_num); if(stat(path, &info) < 0) @@ -1021,27 +1021,36 @@ int multirom_mount_image(const char *src, const char *dst, const char *fs, int f { ERROR("mount_image: failed to find suitable loop device number!\n"); return -1; - } + }*/ // now change to /multirom/dev/ mkdir_recursive_with_perms(MULTIROM_DEV_PATH, 0777, NULL, NULL); sprintf(path, MULTIROM_DEV_PATH "/%s", dst); create_loop: - if(create_loop_device(path, src, loop_num, 0777) < 0) + if(create_loop_device(path, src, loop_num, 0777) < 0) { res = -1; + } else { + res = 0; + } - // never reuse an existing loop - next_loop_num = loop_num + 1; - if(mount(path, dst, fs, flags, data) < 0) - ERROR("Failed to mount loop (%d: %s)\n", errno, strerror(errno)); - else - res = 0; + if (res != -1) { + if(mount(path, dst, fs, flags, data) < 0) { + ERROR("Failed to mount loop (%d: %s)\n", errno, strerror(errno)); + res = -1; + } else { + res = 0; + } + } - if(res) { - if (loop_num == MULTIROM_LOOP_NUM_START) + INFO("multirom create loop device %d\n", loop_num); + //multirom_kmsg_logging(BACKUP_LATE_KLOG); + if(res && loop_num < MAX_LOOP_NUM) { + if (loop_num == -1) loop_num = 0; + else + loop_num = loop_num + 1; sprintf(path, "/dev/block/loop%d", loop_num); goto create_loop; } diff --git a/multirom.c b/multirom.c index d4674b73..db96cf83 100644 --- a/multirom.c +++ b/multirom.c @@ -1546,7 +1546,9 @@ int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to umount("/system_root"); //disable_dtb_fstab("system"); } - nokexec_set_skip_mr_flag(); + if (always_reboot) { + nokexec_set_skip_mr_flag(); + } //if (mount_dtb_fstab("vendor") == 0) { //disable_dtb_fstab("vendor"); // } @@ -1798,7 +1800,7 @@ bool LoadSplitPolicy() { if (!access(plat_policy_cil_file_sar, F_OK)) { plat_policy_cil_file = plat_policy_cil_file_sar; } - char mapping_file_sar[] = "/system/system/etc/selinux/mapping/29.0.cil"; + char mapping_file_sar[] = "/system/system/etc/selinux/mapping/30.0.cil"; if (!access(mapping_file_sar, F_OK)) { mapping_file = mapping_file_sar; } diff --git a/trampoline/trampoline.cpp b/trampoline/trampoline.cpp index 4dd41a62..1a928f18 100644 --- a/trampoline/trampoline.cpp +++ b/trampoline/trampoline.cpp @@ -341,7 +341,7 @@ static int mount_and_run(struct fstab *fstab) #endif } - if (ret == -2 && !nokexec_is_skip_mr()) { + if (ret == -2 && !nokexec_is_skip_mr() || ret != -2) { INFO("skip mr flag false.. running multirom"); if(find_multirom() == -1) { From 350f3eda37db4de1428d663fd4d63dc61f7f2254 Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sat, 2 Jan 2021 17:42:27 +0530 Subject: [PATCH 64/65] Switch multirom directory to /data/media/MultiROM FBE devices leave this directory unencrypted and this saves us a lot of hassle of decrypting and rebooting the phone --- .../scripts/extract_multirom.sh | 12 +++---- multirom.c | 2 +- trampoline/trampoline.cpp | 32 ++++++++++++++++--- 3 files changed, 33 insertions(+), 13 deletions(-) diff --git a/install_zip/prebuilt-installer/scripts/extract_multirom.sh b/install_zip/prebuilt-installer/scripts/extract_multirom.sh index dee6faac..3a5db8c6 100644 --- a/install_zip/prebuilt-installer/scripts/extract_multirom.sh +++ b/install_zip/prebuilt-installer/scripts/extract_multirom.sh @@ -9,6 +9,9 @@ if [ -d "/data/media/multirom" ] && [ ! -d "/data/media/MultiROM/multirom" ]; th elif [ -d "/data/media/0/multirom" ] && [ ! -d "/data/media/0/MultiROM/multirom" ]; then mkdir "/data/media/0/MultiROM" mv "/data/media/0/multirom" "/data/media/0/MultiROM/multirom" +elif [ -d "/data/media/0/MultiROM/multirom" ] && [ ! -d "/data/media/MultiROM/multirom" ]; then + mkdir "/data/media/MultiROM" + mv "/data/media/0/MultiROM/multirom" "/data/media/MultiROM/multirom" fi # Check for existing dirs otherwise create them @@ -19,13 +22,8 @@ elif [ -d "/data/media/0/MultiROM/multirom" ] ; then cont="/data/media/0/MultiROM" base="/data/media/0/MultiROM/multirom" else - if [ -d "/data/media/0" ] ; then - cont="/data/media/0/MultiROM" - base="/data/media/0/MultiROM/multirom" - else - cont="/data/media/MultiROM" - base="/data/media/MultiROM/multirom" - fi + cont="/data/media/MultiROM" + base="/data/media/MultiROM/multirom" mkdir "$cont" chown root:root "$cont" diff --git a/multirom.c b/multirom.c index db96cf83..d89d37e4 100644 --- a/multirom.c +++ b/multirom.c @@ -1521,7 +1521,7 @@ struct multirom_rom *multirom_get_rom_by_id(struct multirom_status *s, int id) int multirom_prepare_for_boot(struct multirom_status *s, struct multirom_rom *to_boot, int always_reboot) { - int exit = always_reboot ? (EXIT_REBOOT | EXIT_UMOUNT) : EXIT_UMOUNT; + int exit = EXIT_UMOUNT; int type = to_boot->type; diff --git a/trampoline/trampoline.cpp b/trampoline/trampoline.cpp index 1a928f18..81b6b7ee 100644 --- a/trampoline/trampoline.cpp +++ b/trampoline/trampoline.cpp @@ -247,8 +247,13 @@ static int try_mount_all_entries(struct fstab *fstab, struct fstab_part *first_d if(stat("/realdata/unencrypted/key/version", &info) < 0) { return 0; } else { - INFO("File system is FBE encrypted"); - return -2; + if (!mrom_is_second_boot() && stat("/realdata/media/MultiROM/multirom", &info) >= 0) { + INFO("Multirom found"); + return 0; + } else { + INFO("File system is FBE encrypted"); + return -2; + } } } } @@ -273,8 +278,13 @@ static int try_mount_all_entries(struct fstab *fstab, struct fstab_part *first_d if(stat("/realdata/unencrypted/key/version", &info) < 0) { return 0; } else { - INFO("File system is FBE encrypted\n"); - return -2; + if (!mrom_is_second_boot() && stat("/realdata/media/MultiROM/multirom", &info) >= 0) { + INFO("Multirom found"); + return 0; + } else { + INFO("File system is FBE encrypted\n"); + return -2; + } } return 0; } @@ -426,7 +436,8 @@ static void switch_root(const char* path) { } for (auto i : v) { - if (!strncmp(mentry.mnt_dir, i.data(), i.length())) { + if (!strcmp(mentry.mnt_dir, i.data())) { + INFO("%s %s %d not adding to vector\n", mentry.mnt_dir, i.data(), i.length()); add = false; break; } else { @@ -482,6 +493,17 @@ static int do_cmdline(int argc, char *argv[]) } else { INFO("chroot returned %d\n", error); } + struct stat info; + if(stat("/system/etc/selinux", &info) < 0) { + INFO("/system/etc/selinux does not exist!\n"); + } else { + INFO("/system/etc/selinux exists\n"); + } + if (stat("/vendor/etc/selinux", &info) < 0) { + INFO("/vendor/etc/selinux does not exist!\n"); + } else { + INFO("/vendor/etc/selinux exists\n"); + } int res; static char *const cmd[] = { "/init", "selinux_setup", NULL }; res = execv(cmd[0], cmd); From 7e04c91d0923833f2dbc3dfc51db0074189eb08d Mon Sep 17 00:00:00 2001 From: Vasishath Kaushal Date: Sun, 9 May 2021 13:28:50 +0530 Subject: [PATCH 65/65] Fix android 10+ support --- lib/inject.c | 2 +- multirom.c | 26 +++++++++++++++++++------- no_kexec.c | 2 +- trampoline/trampoline.cpp | 4 ++-- 4 files changed, 23 insertions(+), 11 deletions(-) diff --git a/lib/inject.c b/lib/inject.c index 75b42b7b..be217244 100644 --- a/lib/inject.c +++ b/lib/inject.c @@ -326,7 +326,7 @@ static int inject_rd(const char *path) int inject_cmdline(struct bootimg *image) { int res = 0; - char* custom_cmdline = "printk.devkmsg=on androidboot.android_dt_dir=/fakefstab/"; + char* custom_cmdline = "printk.devkmsg=on androidboot.android_dt_dir=/fakefsbat/"; char* cmdline = libbootimg_get_cmdline(&image->hdr); char* newcmdline = NULL; diff --git a/multirom.c b/multirom.c index d89d37e4..dfa7c55b 100644 --- a/multirom.c +++ b/multirom.c @@ -100,13 +100,13 @@ void disable_dtb_fstab(char* partition) { if (access("status", F_OK)) { DIR* dir = opendir("/proc/device-tree/firmware/android"); char** exclude_dirs = NULL; - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", exclude_dirs); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefsbat", exclude_dirs); FILE* fp = fopen("status", "w"); fprintf(fp, "disabled"); fclose(fp); } char path[256]; - sprintf(path, "/fakefstab/fstab/%s/status", partition); + sprintf(path, "/fakefsbat/fstab/%s/status", partition); copy_file("/status", path); } @@ -114,8 +114,8 @@ void remove_dtb_fstab() { mkdir("/dummy_fw", S_IFDIR); DIR* dir = opendir("/proc/device-tree/firmware/android"); char** exclude_dirs = NULL; - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", exclude_dirs); - if (!mount("/dummy_fw", "/fakefstab", "ext4", MS_BIND, "discard,nomblk_io_submit")) { + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefsbat", exclude_dirs); + if (!mount("/dummy_fw", "/fakefsbat", "ext4", MS_BIND, "discard,nomblk_io_submit")) { INFO("dummy dtb node bind mounted in procfs\n"); } else { ERROR("dummy dtb node bind mount failed! %s\n", strerror(errno)); @@ -124,6 +124,11 @@ void remove_dtb_fstab() { int multirom_is_android10() { if (!multirom_path_exists("/", "apex")) { + INFO("APEX folder found\n"); + return 1; + } + if (!multirom_path_exists("/system", "system/bin/init")) { + INFO("system/bin/init found\n"); return 1; } char* initPath = "/main_init"; @@ -131,15 +136,20 @@ int multirom_is_android10() { initPath = "/.backup/init"; } - char *addr; + void *addr; int initfd = open(initPath, O_RDWR); + INFO("open file %s result %d\n", initPath, initfd); struct stat st; lstat(initPath, &st); size_t size = st.st_size; - addr = mmap(NULL, size, PROT_WRITE, MAP_SHARED, initfd, 0); - int contains = strstr(addr, "selinux_setup") != NULL; + addr = mmap(NULL, size, PROT_READ, MAP_SHARED, initfd, 0); + if (addr == -1) { + INFO("mmap error! %s\n", strerror(errno)); + } + int contains = memmem(addr, size, "selinux_setup", 13) != NULL; munmap(addr, size); close(initfd); + INFO("init contains selinux_setup %d\n", contains); return contains; } @@ -1972,6 +1982,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom asprintf(&system_path, "%s/system.sparse.img", rom->base_path); if (!multirom_path_exists("/system", "init.rc") && !multirom_is_android10()) { + INFO("ROM is not android 10\n"); umount("/system"); mkdir_with_perms("/system_root", 0755, NULL, NULL); multirom_mount_image(system_path, "/system_root", "ext4", MS_RDONLY, NULL); @@ -1988,6 +1999,7 @@ int multirom_prep_android_mounts(struct multirom_status *s, struct multirom_rom char* exclude_dirs[] = {"system", "vendor", "product", NULL}; copy_init_contents(dir, "/system_root", "/", true, exclude_dirs); } else if (multirom_is_android10()) { + INFO("ROM is android 10+\n"); umount("/system"); mkdir_with_perms("/system_root", 0755, NULL, NULL); multirom_mount_image(system_path, "/system_root", "ext4", MS_RDONLY, NULL); diff --git a/no_kexec.c b/no_kexec.c index 5364689e..c691481a 100644 --- a/no_kexec.c +++ b/no_kexec.c @@ -293,7 +293,7 @@ int nokexec_set_cmdline(char *secondary_path) { int res = 0; struct bootimg image; - char* custom_cmdline = "androidboot.selinux=permissive printk.devkmsg=on androidboot.android_dt_dir=/fakefstab/"; + char* custom_cmdline = "androidboot.selinux=permissive printk.devkmsg=on androidboot.android_dt_dir=/fakefsbat/"; INFO(NO_KEXEC_LOG_TEXT ": Going to check the bootimg in primary slot for slevel\n"); diff --git a/trampoline/trampoline.cpp b/trampoline/trampoline.cpp index 81b6b7ee..c95be0c1 100644 --- a/trampoline/trampoline.cpp +++ b/trampoline/trampoline.cpp @@ -736,9 +736,9 @@ int main(int argc, char *argv[]) umount("/sys/kernel/debug"); #endif - if (access("/fakefstab/", F_OK)) { + if (access("/fakefsbat/", F_OK)) { DIR* dir = opendir("/proc/device-tree/firmware/android"); - copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefstab", NULL); + copy_dir_contents(dir, "/proc/device-tree/firmware/android", "/fakefsbat", NULL); //remove("/fakefstab/fstab/system/mnt_point"); closedir(dir); //remove("/fakefstab/fstab/vendor/mnt_point");