diff --git a/native/jni/Android.mk b/native/jni/Android.mk index 7430533bf..d129a7106 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -12,25 +12,25 @@ LOCAL_STATIC_LIBRARIES := libnanopb libsystemproperties libutils LOCAL_C_INCLUDES := jni/include LOCAL_SRC_FILES := \ - core/applets.cpp \ - core/magisk.cpp \ - core/daemon.cpp \ - core/bootstages.cpp \ - core/socket.cpp \ - core/db.cpp \ - core/scripting.cpp \ - core/restorecon.cpp \ - core/module.cpp \ - magiskhide/magiskhide.cpp \ - magiskhide/proc_monitor.cpp \ - magiskhide/hide_utils.cpp \ - magiskhide/hide_policy.cpp \ - resetprop/persist_properties.cpp \ - resetprop/resetprop.cpp \ - su/su.cpp \ - su/connect.cpp \ - su/pts.cpp \ - su/su_daemon.cpp + core/applets.cpp \ + core/magisk.cpp \ + core/daemon.cpp \ + core/bootstages.cpp \ + core/socket.cpp \ + core/db.cpp \ + core/scripting.cpp \ + core/restorecon.cpp \ + core/module.cpp \ + magiskhide/magiskhide.cpp \ + magiskhide/proc_monitor.cpp \ + magiskhide/hide_utils.cpp \ + magiskhide/hide_policy.cpp \ + resetprop/persist_properties.cpp \ + resetprop/resetprop.cpp \ + su/su.cpp \ + su/connect.cpp \ + su/pts.cpp \ + su/su_daemon.cpp LOCAL_LDLIBS := -llog include $(BUILD_EXECUTABLE) @@ -52,24 +52,24 @@ ifdef BB_INIT LOCAL_STATIC_LIBRARIES := libsepol libxz libutils LOCAL_C_INCLUDES := \ - jni/include \ - out \ - out/$(TARGET_ARCH_ABI) + jni/include \ + out \ + out/$(TARGET_ARCH_ABI) LOCAL_SRC_FILES := \ - init/init.cpp \ - init/mount.cpp \ - init/rootdir.cpp \ - init/getinfo.cpp \ - init/twostage.cpp \ - init/raw_data.cpp \ - core/socket.cpp \ - magiskpolicy/sepolicy.cpp \ - magiskpolicy/magiskpolicy.cpp \ - magiskpolicy/rules.cpp \ - magiskpolicy/policydb.cpp \ - magiskpolicy/statement.cpp \ - magiskboot/pattern.cpp + init/init.cpp \ + init/mount.cpp \ + init/rootdir.cpp \ + init/getinfo.cpp \ + init/twostage.cpp \ + init/raw_data.cpp \ + core/socket.cpp \ + magiskpolicy/sepolicy.cpp \ + magiskpolicy/magiskpolicy.cpp \ + magiskpolicy/rules.cpp \ + magiskpolicy/policydb.cpp \ + magiskpolicy/statement.cpp \ + magiskboot/pattern.cpp LOCAL_LDFLAGS := -static include $(BUILD_EXECUTABLE) @@ -84,15 +84,15 @@ LOCAL_STATIC_LIBRARIES := libmincrypt liblzma liblz4 libbz2 libfdt libutils LOCAL_C_INCLUDES := jni/include LOCAL_SRC_FILES := \ - magiskboot/main.cpp \ - magiskboot/bootimg.cpp \ - magiskboot/hexpatch.cpp \ - magiskboot/compress.cpp \ - magiskboot/format.cpp \ - magiskboot/dtb.cpp \ - magiskboot/ramdisk.cpp \ - magiskboot/pattern.cpp \ - utils/cpio.cpp + magiskboot/main.cpp \ + magiskboot/bootimg.cpp \ + magiskboot/hexpatch.cpp \ + magiskboot/compress.cpp \ + magiskboot/format.cpp \ + magiskboot/dtb.cpp \ + magiskboot/ramdisk.cpp \ + magiskboot/pattern.cpp \ + utils/cpio.cpp LOCAL_LDLIBS := -lz LOCAL_LDFLAGS := -static @@ -108,12 +108,12 @@ LOCAL_STATIC_LIBRARIES := libsepol libutils LOCAL_C_INCLUDES := jni/include LOCAL_SRC_FILES := \ - core/applet_stub.cpp \ - magiskpolicy/sepolicy.cpp \ - magiskpolicy/magiskpolicy.cpp \ - magiskpolicy/rules.cpp \ - magiskpolicy/policydb.cpp \ - magiskpolicy/statement.cpp + core/applet_stub.cpp \ + magiskpolicy/sepolicy.cpp \ + magiskpolicy/magiskpolicy.cpp \ + magiskpolicy/rules.cpp \ + magiskpolicy/policydb.cpp \ + magiskpolicy/statement.cpp LOCAL_CFLAGS := -DAPPLET_STUB_MAIN=magiskpolicy_main LOCAL_LDFLAGS := -static @@ -129,9 +129,9 @@ LOCAL_STATIC_LIBRARIES := libnanopb libsystemproperties libutils LOCAL_C_INCLUDES := jni/include LOCAL_SRC_FILES := \ - core/applet_stub.cpp \ - resetprop/persist_properties.cpp \ - resetprop/resetprop.cpp \ + core/applet_stub.cpp \ + resetprop/persist_properties.cpp \ + resetprop/resetprop.cpp \ LOCAL_CFLAGS := -DAPPLET_STUB_MAIN=resetprop_main LOCAL_LDFLAGS := -static diff --git a/native/jni/core/applet_stub.cpp b/native/jni/core/applet_stub.cpp index d479f2254..643d546ae 100644 --- a/native/jni/core/applet_stub.cpp +++ b/native/jni/core/applet_stub.cpp @@ -4,7 +4,7 @@ #include int main(int argc, char *argv[]) { - umask(0); - cmdline_logging(); - return APPLET_STUB_MAIN(argc, argv); + umask(0); + cmdline_logging(); + return APPLET_STUB_MAIN(argc, argv); } diff --git a/native/jni/core/applets.cpp b/native/jni/core/applets.cpp index 0b076b4f1..808a55b9e 100644 --- a/native/jni/core/applets.cpp +++ b/native/jni/core/applets.cpp @@ -15,32 +15,32 @@ using main_fun = int (*)(int, char *[]); static main_fun applet_main[] = { su_client_main, resetprop_main, magiskhide_main, nullptr }; [[noreturn]] static void call_applet(int argc, char **argv) { - // Applets - for (int i = 0; applet_names[i]; ++i) { - if (strcmp(basename(argv[0]), applet_names[i]) == 0) { - exit((*applet_main[i])(argc, argv)); - } - } - fprintf(stderr, "%s: applet not found\n", basename(argv[0])); - exit(1); + // Applets + for (int i = 0; applet_names[i]; ++i) { + if (strcmp(basename(argv[0]), applet_names[i]) == 0) { + exit((*applet_main[i])(argc, argv)); + } + } + fprintf(stderr, "%s: applet not found\n", basename(argv[0])); + exit(1); } int main(int argc, char *argv[]) { - umask(0); - dload_selinux(); - cmdline_logging(); - init_argv0(argc, argv); + umask(0); + dload_selinux(); + cmdline_logging(); + init_argv0(argc, argv); - if (basename(argv[0]) == "magisk"sv) { - if (argc > 1 && argv[1][0] != '-') { - // Calling applet via magisk [applet] args - --argc; - ++argv; - } else { - return magisk_main(argc, argv); - } - } + if (basename(argv[0]) == "magisk"sv) { + if (argc > 1 && argv[1][0] != '-') { + // Calling applet via magisk [applet] args + --argc; + ++argv; + } else { + return magisk_main(argc, argv); + } + } - call_applet(argc, argv); + call_applet(argc, argv); } diff --git a/native/jni/core/bootstages.cpp b/native/jni/core/bootstages.cpp index 70b7ec592..200503612 100644 --- a/native/jni/core/bootstages.cpp +++ b/native/jni/core/bootstages.cpp @@ -37,64 +37,64 @@ static bool safe_mode = false; #define mount_mirror(part, flag) \ else if (MNT_DIR_IS("/" #part) && me->mnt_type != "tmpfs"sv && lstat(me->mnt_dir, &st) == 0) \ - do_mount_mirror(part, flag) + do_mount_mirror(part, flag) #define link_mirror(part) \ SETMIR(buf1, part); \ if (access("/system/" #part, F_OK) == 0 && access(buf1, F_OK) != 0) { \ - xsymlink("./system/" #part, buf1); \ - LOGI("link: %s\n", buf1); \ + xsymlink("./system/" #part, buf1); \ + LOGI("link: %s\n", buf1); \ } #define link_orig_dir(dir, part) \ else if (MNT_DIR_IS(dir) && me->mnt_type != "tmpfs"sv) { \ - SETMIR(buf1, part); \ - rmdir(buf1); \ - xsymlink(dir, buf1); \ - LOGI("link: %s\n", buf1); \ + SETMIR(buf1, part); \ + rmdir(buf1); \ + xsymlink(dir, buf1); \ + LOGI("link: %s\n", buf1); \ } #define link_orig(part) link_orig_dir("/" #part, part) static void mount_mirrors() { - char buf1[4096]; - char buf2[4096]; + char buf1[4096]; + char buf2[4096]; - LOGI("* Mounting mirrors\n"); + LOGI("* Mounting mirrors\n"); - parse_mnt("/proc/mounts", [&](mntent *me) { - struct stat st; - if (0) {} - mount_mirror(system, MS_RDONLY) - mount_mirror(vendor, MS_RDONLY) - mount_mirror(product, MS_RDONLY) - mount_mirror(system_ext, MS_RDONLY) - mount_mirror(data, 0) - link_orig(cache) - link_orig(metadata) - link_orig(persist) - link_orig_dir("/mnt/vendor/persist", persist) - else if (SDK_INT >= 24 && MNT_DIR_IS("/proc") && !strstr(me->mnt_opts, "hidepid=2")) { - xmount(nullptr, "/proc", nullptr, MS_REMOUNT, "hidepid=2,gid=3009"); - } - return true; - }); - SETMIR(buf1, system); - if (access(buf1, F_OK) != 0) { - xsymlink("./system_root/system", buf1); - LOGI("link: %s\n", buf1); - parse_mnt("/proc/mounts", [&](mntent *me) { - struct stat st; - if (MNT_DIR_IS("/") && me->mnt_type != "rootfs"sv && stat("/", &st) == 0) { - do_mount_mirror(system_root, MS_RDONLY) - return false; - } - return true; - }); - } - link_mirror(vendor) - link_mirror(product) - link_mirror(system_ext) + parse_mnt("/proc/mounts", [&](mntent *me) { + struct stat st; + if (0) {} + mount_mirror(system, MS_RDONLY) + mount_mirror(vendor, MS_RDONLY) + mount_mirror(product, MS_RDONLY) + mount_mirror(system_ext, MS_RDONLY) + mount_mirror(data, 0) + link_orig(cache) + link_orig(metadata) + link_orig(persist) + link_orig_dir("/mnt/vendor/persist", persist) + else if (SDK_INT >= 24 && MNT_DIR_IS("/proc") && !strstr(me->mnt_opts, "hidepid=2")) { + xmount(nullptr, "/proc", nullptr, MS_REMOUNT, "hidepid=2,gid=3009"); + } + return true; + }); + SETMIR(buf1, system); + if (access(buf1, F_OK) != 0) { + xsymlink("./system_root/system", buf1); + LOGI("link: %s\n", buf1); + parse_mnt("/proc/mounts", [&](mntent *me) { + struct stat st; + if (MNT_DIR_IS("/") && me->mnt_type != "rootfs"sv && stat("/", &st) == 0) { + do_mount_mirror(system_root, MS_RDONLY) + return false; + } + return true; + }); + } + link_mirror(vendor) + link_mirror(product) + link_mirror(system_ext) } constexpr char bb_script[] = R"EOF( @@ -105,167 +105,167 @@ exec /data/adb/magisk/busybox.bin "$@" )EOF"; static bool magisk_env() { - char buf[4096]; + char buf[4096]; - LOGI("* Initializing Magisk environment\n"); + LOGI("* Initializing Magisk environment\n"); - string pkg; - check_manager(&pkg); + string pkg; + check_manager(&pkg); - sprintf(buf, "%s/0/%s/install", APP_DATA_DIR, pkg.data()); + sprintf(buf, "%s/0/%s/install", APP_DATA_DIR, pkg.data()); - // Alternative binaries paths - const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", buf }; - for (auto alt : alt_bin) { - struct stat st; - if (lstat(alt, &st) == 0) { - if (S_ISLNK(st.st_mode)) { - unlink(alt); - continue; - } - rm_rf(DATABIN); - cp_afc(alt, DATABIN); - rm_rf(alt); - break; - } - } + // Alternative binaries paths + const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", buf }; + for (auto alt : alt_bin) { + struct stat st; + if (lstat(alt, &st) == 0) { + if (S_ISLNK(st.st_mode)) { + unlink(alt); + continue; + } + rm_rf(DATABIN); + cp_afc(alt, DATABIN); + rm_rf(alt); + break; + } + } - // Remove stuffs - rm_rf("/cache/data_adb"); - rm_rf("/data/adb/modules/.core"); - unlink("/data/adb/magisk.img"); - unlink("/data/adb/magisk_merge.img"); - unlink("/data/magisk.img"); - unlink("/data/magisk_merge.img"); - unlink("/data/magisk_debug.log"); + // Remove stuffs + rm_rf("/cache/data_adb"); + rm_rf("/data/adb/modules/.core"); + unlink("/data/adb/magisk.img"); + unlink("/data/adb/magisk_merge.img"); + unlink("/data/magisk.img"); + unlink("/data/magisk_merge.img"); + unlink("/data/magisk_debug.log"); - // Directories in /data/adb - xmkdir(DATABIN, 0755); - xmkdir(MODULEROOT, 0755); - xmkdir(SECURE_DIR "/post-fs-data.d", 0755); - xmkdir(SECURE_DIR "/service.d", 0755); + // Directories in /data/adb + xmkdir(DATABIN, 0755); + xmkdir(MODULEROOT, 0755); + xmkdir(SECURE_DIR "/post-fs-data.d", 0755); + xmkdir(SECURE_DIR "/service.d", 0755); - // Disable/remove magiskhide, resetprop - if (SDK_INT < 19) { - unlink("/sbin/resetprop"); - unlink("/sbin/magiskhide"); - } + // Disable/remove magiskhide, resetprop + if (SDK_INT < 19) { + unlink("/sbin/resetprop"); + unlink("/sbin/magiskhide"); + } - if (access(DATABIN "/busybox.bin", X_OK)) { - if (access(DATABIN "/busybox", X_OK)) - return false; - rename(DATABIN "/busybox", DATABIN "/busybox.bin"); - } + if (access(DATABIN "/busybox.bin", X_OK)) { + if (access(DATABIN "/busybox", X_OK)) + return false; + rename(DATABIN "/busybox", DATABIN "/busybox.bin"); + } - sprintf(buf, "%s/" BBPATH "/busybox", MAGISKTMP.data()); - { - auto fp = open_file(DATABIN "/busybox", "we"); - fprintf(fp.get(), bb_script, buf); - } - chmod(DATABIN "/busybox", 0755); - mkdir(dirname(buf), 0755); - cp_afc(DATABIN "/busybox.bin", buf); - exec_command_async(buf, "--install", "-s", dirname(buf)); + sprintf(buf, "%s/" BBPATH "/busybox", MAGISKTMP.data()); + { + auto fp = open_file(DATABIN "/busybox", "we"); + fprintf(fp.get(), bb_script, buf); + } + chmod(DATABIN "/busybox", 0755); + mkdir(dirname(buf), 0755); + cp_afc(DATABIN "/busybox.bin", buf); + exec_command_async(buf, "--install", "-s", dirname(buf)); - return true; + return true; } void reboot() { - if (RECOVERY_MODE) - exec_command_sync("/system/bin/reboot", "recovery"); - else - exec_command_sync("/system/bin/reboot"); + if (RECOVERY_MODE) + exec_command_sync("/system/bin/reboot", "recovery"); + else + exec_command_sync("/system/bin/reboot"); } static bool check_data() { - bool mnt = false; - file_readline("/proc/mounts", [&](string_view s) { - if (str_contains(s, " /data ") && !str_contains(s, "tmpfs")) { - mnt = true; - return false; - } - return true; - }); - if (!mnt) - return false; - auto crypto = getprop("ro.crypto.state"); - if (!crypto.empty()) { - if (crypto == "unencrypted") { - // Unencrypted, we can directly access data - return true; - } else { - // Encrypted, check whether vold is started - return !getprop("init.svc.vold").empty(); - } - } - // ro.crypto.state is not set, assume it's unencrypted - return true; + bool mnt = false; + file_readline("/proc/mounts", [&](string_view s) { + if (str_contains(s, " /data ") && !str_contains(s, "tmpfs")) { + mnt = true; + return false; + } + return true; + }); + if (!mnt) + return false; + auto crypto = getprop("ro.crypto.state"); + if (!crypto.empty()) { + if (crypto == "unencrypted") { + // Unencrypted, we can directly access data + return true; + } else { + // Encrypted, check whether vold is started + return !getprop("init.svc.vold").empty(); + } + } + // ro.crypto.state is not set, assume it's unencrypted + return true; } void unlock_blocks() { - int fd, dev, OFF = 0; + int fd, dev, OFF = 0; - auto dir = xopen_dir("/dev/block"); - if (!dir) - return; - dev = dirfd(dir.get()); + auto dir = xopen_dir("/dev/block"); + if (!dir) + return; + dev = dirfd(dir.get()); - for (dirent *entry; (entry = readdir(dir.get()));) { - if (entry->d_type == DT_BLK) { - if ((fd = openat(dev, entry->d_name, O_RDONLY | O_CLOEXEC)) < 0) - continue; - if (ioctl(fd, BLKROSET, &OFF) < 0) - PLOGE("unlock %s", entry->d_name); - close(fd); - } - } + for (dirent *entry; (entry = readdir(dir.get()));) { + if (entry->d_type == DT_BLK) { + if ((fd = openat(dev, entry->d_name, O_RDONLY | O_CLOEXEC)) < 0) + continue; + if (ioctl(fd, BLKROSET, &OFF) < 0) + PLOGE("unlock %s", entry->d_name); + close(fd); + } + } } #define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8))) static bool check_key_combo() { - uint8_t bitmask[(KEY_MAX + 1) / 8]; - vector events; - constexpr char name[] = "/dev/.ev"; + uint8_t bitmask[(KEY_MAX + 1) / 8]; + vector events; + constexpr char name[] = "/dev/.ev"; - // First collect candidate events that accepts volume down - for (int minor = 64; minor < 96; ++minor) { - if (xmknod(name, S_IFCHR | 0444, makedev(13, minor))) - continue; - int fd = open(name, O_RDONLY | O_CLOEXEC); - unlink(name); - if (fd < 0) - continue; - memset(bitmask, 0, sizeof(bitmask)); - ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitmask)), bitmask); - if (test_bit(KEY_VOLUMEDOWN, bitmask)) - events.push_back(fd); - else - close(fd); - } - if (events.empty()) - return false; + // First collect candidate events that accepts volume down + for (int minor = 64; minor < 96; ++minor) { + if (xmknod(name, S_IFCHR | 0444, makedev(13, minor))) + continue; + int fd = open(name, O_RDONLY | O_CLOEXEC); + unlink(name); + if (fd < 0) + continue; + memset(bitmask, 0, sizeof(bitmask)); + ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitmask)), bitmask); + if (test_bit(KEY_VOLUMEDOWN, bitmask)) + events.push_back(fd); + else + close(fd); + } + if (events.empty()) + return false; - run_finally fin([&]{ std::for_each(events.begin(), events.end(), close); }); + run_finally fin([&]{ std::for_each(events.begin(), events.end(), close); }); - // Check if volume down key is held continuously for more than 3 seconds - for (int i = 0; i < 300; ++i) { - bool pressed = false; - for (const int &fd : events) { - memset(bitmask, 0, sizeof(bitmask)); - ioctl(fd, EVIOCGKEY(sizeof(bitmask)), bitmask); - if (test_bit(KEY_VOLUMEDOWN, bitmask)) { - pressed = true; - break; - } - } - if (!pressed) - return false; - // Check every 10ms - usleep(10000); - } - LOGD("KEY_VOLUMEDOWN detected: enter safe mode\n"); - return true; + // Check if volume down key is held continuously for more than 3 seconds + for (int i = 0; i < 300; ++i) { + bool pressed = false; + for (const int &fd : events) { + memset(bitmask, 0, sizeof(bitmask)); + ioctl(fd, EVIOCGKEY(sizeof(bitmask)), bitmask); + if (test_bit(KEY_VOLUMEDOWN, bitmask)) { + pressed = true; + break; + } + } + if (!pressed) + return false; + // Check every 10ms + usleep(10000); + } + LOGD("KEY_VOLUMEDOWN detected: enter safe mode\n"); + return true; } /*********************** @@ -275,114 +275,114 @@ static bool check_key_combo() { static pthread_mutex_t stage_lock = PTHREAD_MUTEX_INITIALIZER; void post_fs_data(int client) { - // ack - write_int(client, 0); - close(client); + // ack + write_int(client, 0); + close(client); - mutex_guard lock(stage_lock); + mutex_guard lock(stage_lock); - if (getenv("REMOUNT_ROOT")) - xmount(nullptr, "/", nullptr, MS_REMOUNT | MS_RDONLY, nullptr); + if (getenv("REMOUNT_ROOT")) + xmount(nullptr, "/", nullptr, MS_REMOUNT | MS_RDONLY, nullptr); - if (!check_data()) - goto unblock_init; + if (!check_data()) + goto unblock_init; - DAEMON_STATE = STATE_POST_FS_DATA; - setup_logfile(true); + DAEMON_STATE = STATE_POST_FS_DATA; + setup_logfile(true); - LOGI("** post-fs-data mode running\n"); + LOGI("** post-fs-data mode running\n"); - unlock_blocks(); - mount_mirrors(); + unlock_blocks(); + mount_mirrors(); - if (access(SECURE_DIR, F_OK) != 0) { - if (SDK_INT < 24) { - // There is no FBE pre 7.0, we can directly create the folder without issues - xmkdir(SECURE_DIR, 0700); - } else { - // If the folder is not automatically created by Android, - // do NOT proceed further. Manual creation of the folder - // will cause bootloops on FBE devices. - LOGE(SECURE_DIR " is not present, abort\n"); - goto early_abort; - } - } + if (access(SECURE_DIR, F_OK) != 0) { + if (SDK_INT < 24) { + // There is no FBE pre 7.0, we can directly create the folder without issues + xmkdir(SECURE_DIR, 0700); + } else { + // If the folder is not automatically created by Android, + // do NOT proceed further. Manual creation of the folder + // will cause bootloops on FBE devices. + LOGE(SECURE_DIR " is not present, abort\n"); + goto early_abort; + } + } - if (!magisk_env()) { - LOGE("* Magisk environment incomplete, abort\n"); - goto early_abort; - } + if (!magisk_env()) { + LOGE("* Magisk environment incomplete, abort\n"); + goto early_abort; + } - if (getprop("persist.sys.safemode", true) == "1" || check_key_combo()) { - safe_mode = true; - // Disable all modules and magiskhide so next boot will be clean - disable_modules(); - stop_magiskhide(); - } else { - exec_common_scripts("post-fs-data"); - auto_start_magiskhide(); - handle_modules(); - } + if (getprop("persist.sys.safemode", true) == "1" || check_key_combo()) { + safe_mode = true; + // Disable all modules and magiskhide so next boot will be clean + disable_modules(); + stop_magiskhide(); + } else { + exec_common_scripts("post-fs-data"); + auto_start_magiskhide(); + handle_modules(); + } early_abort: - // We still do magic mount because root itself might need it - magic_mount(); - DAEMON_STATE = STATE_POST_FS_DATA_DONE; + // We still do magic mount because root itself might need it + magic_mount(); + DAEMON_STATE = STATE_POST_FS_DATA_DONE; unblock_init: - close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT, 0)); + close(xopen(UNBLOCKFILE, O_RDONLY | O_CREAT, 0)); } void late_start(int client) { - // ack - write_int(client, 0); - close(client); + // ack + write_int(client, 0); + close(client); - mutex_guard lock(stage_lock); - run_finally fin([]{ DAEMON_STATE = STATE_LATE_START_DONE; }); - setup_logfile(false); + mutex_guard lock(stage_lock); + run_finally fin([]{ DAEMON_STATE = STATE_LATE_START_DONE; }); + setup_logfile(false); - LOGI("** late_start service mode running\n"); + LOGI("** late_start service mode running\n"); - if (DAEMON_STATE < STATE_POST_FS_DATA_DONE || safe_mode) - return; + if (DAEMON_STATE < STATE_POST_FS_DATA_DONE || safe_mode) + return; - exec_common_scripts("service"); - exec_module_scripts("service"); + exec_common_scripts("service"); + exec_module_scripts("service"); } void boot_complete(int client) { - // ack - write_int(client, 0); - close(client); + // ack + write_int(client, 0); + close(client); - mutex_guard lock(stage_lock); - DAEMON_STATE = STATE_BOOT_COMPLETE; - setup_logfile(false); + mutex_guard lock(stage_lock); + DAEMON_STATE = STATE_BOOT_COMPLETE; + setup_logfile(false); - LOGI("** boot_complete triggered\n"); + LOGI("** boot_complete triggered\n"); - if (safe_mode) - return; + if (safe_mode) + return; - // At this point it's safe to create the folder - if (access(SECURE_DIR, F_OK) != 0) - xmkdir(SECURE_DIR, 0700); + // At this point it's safe to create the folder + if (access(SECURE_DIR, F_OK) != 0) + xmkdir(SECURE_DIR, 0700); - auto_start_magiskhide(); + auto_start_magiskhide(); - if (!check_manager()) { - if (access(MANAGERAPK, F_OK) == 0) { - // Only try to install APK when no manager is installed - // Magisk Manager should be upgraded by itself, not through recovery installs - rename(MANAGERAPK, "/data/magisk.apk"); - install_apk("/data/magisk.apk"); - } else { - // Install stub - auto init = MAGISKTMP + "/magiskinit"; - exec_command_sync(init.data(), "-x", "manager", "/data/magisk.apk"); - install_apk("/data/magisk.apk"); - } - } - unlink(MANAGERAPK); + if (!check_manager()) { + if (access(MANAGERAPK, F_OK) == 0) { + // Only try to install APK when no manager is installed + // Magisk Manager should be upgraded by itself, not through recovery installs + rename(MANAGERAPK, "/data/magisk.apk"); + install_apk("/data/magisk.apk"); + } else { + // Install stub + auto init = MAGISKTMP + "/magiskinit"; + exec_command_sync(init.data(), "-x", "manager", "/data/magisk.apk"); + install_apk("/data/magisk.apk"); + } + } + unlink(MANAGERAPK); } diff --git a/native/jni/core/daemon.cpp b/native/jni/core/daemon.cpp index d2b87057a..c802e80e9 100644 --- a/native/jni/core/daemon.cpp +++ b/native/jni/core/daemon.cpp @@ -26,101 +26,101 @@ int DAEMON_STATE = STATE_NONE; static struct stat self_st; static bool verify_client(pid_t pid) { - // Verify caller is the same as server - char path[32]; - sprintf(path, "/proc/%d/exe", pid); - struct stat st; - return !(stat(path, &st) || st.st_dev != self_st.st_dev || st.st_ino != self_st.st_ino); + // Verify caller is the same as server + char path[32]; + sprintf(path, "/proc/%d/exe", pid); + struct stat st; + return !(stat(path, &st) || st.st_dev != self_st.st_dev || st.st_ino != self_st.st_ino); } static void request_handler(int client, int req_code, ucred cred) { - switch (req_code) { - case MAGISKHIDE: - magiskhide_handler(client); - break; - case SUPERUSER: - su_daemon_handler(client, &cred); - break; - case POST_FS_DATA: - post_fs_data(client); - break; - case LATE_START: - late_start(client); - break; - case BOOT_COMPLETE: - boot_complete(client); - break; - case SQLITE_CMD: - exec_sql(client); - break; - case REMOVE_MODULES: - remove_modules(); - write_int(client, 0); - close(client); - reboot(); - break; - default: - close(client); - break; - } + switch (req_code) { + case MAGISKHIDE: + magiskhide_handler(client); + break; + case SUPERUSER: + su_daemon_handler(client, &cred); + break; + case POST_FS_DATA: + post_fs_data(client); + break; + case LATE_START: + late_start(client); + break; + case BOOT_COMPLETE: + boot_complete(client); + break; + case SQLITE_CMD: + exec_sql(client); + break; + case REMOVE_MODULES: + remove_modules(); + write_int(client, 0); + close(client); + reboot(); + break; + default: + close(client); + break; + } } static void handle_request(int client) { - int req_code; + int req_code; - // Verify client credentials - ucred cred; - get_client_cred(client, &cred); - if (cred.uid != 0 && !verify_client(cred.pid)) - goto shortcut; + // Verify client credentials + ucred cred; + get_client_cred(client, &cred); + if (cred.uid != 0 && !verify_client(cred.pid)) + goto shortcut; - req_code = read_int(client); - if (req_code < 0 || req_code >= DAEMON_CODE_END) - goto shortcut; + req_code = read_int(client); + if (req_code < 0 || req_code >= DAEMON_CODE_END) + goto shortcut; - // Check client permissions - switch (req_code) { - case MAGISKHIDE: - case POST_FS_DATA: - case LATE_START: - case BOOT_COMPLETE: - case SQLITE_CMD: - case GET_PATH: - if (cred.uid != 0) { - write_int(client, ROOT_REQUIRED); - goto shortcut; - } - break; - case REMOVE_MODULES: - if (cred.uid != UID_SHELL && cred.uid != UID_ROOT) { - write_int(client, 1); - goto shortcut; - } - break; - } + // Check client permissions + switch (req_code) { + case MAGISKHIDE: + case POST_FS_DATA: + case LATE_START: + case BOOT_COMPLETE: + case SQLITE_CMD: + case GET_PATH: + if (cred.uid != 0) { + write_int(client, ROOT_REQUIRED); + goto shortcut; + } + break; + case REMOVE_MODULES: + if (cred.uid != UID_SHELL && cred.uid != UID_ROOT) { + write_int(client, 1); + goto shortcut; + } + break; + } - // Simple requests - switch (req_code) { - case CHECK_VERSION: - write_string(client, MAGISK_VERSION ":MAGISK"); - goto shortcut; - case CHECK_VERSION_CODE: - write_int(client, MAGISK_VER_CODE); - goto shortcut; - case GET_PATH: - write_string(client, MAGISKTMP.data()); - goto shortcut; - case START_DAEMON: - setup_logfile(true); - goto shortcut; - } + // Simple requests + switch (req_code) { + case CHECK_VERSION: + write_string(client, MAGISK_VERSION ":MAGISK"); + goto shortcut; + case CHECK_VERSION_CODE: + write_int(client, MAGISK_VER_CODE); + goto shortcut; + case GET_PATH: + write_string(client, MAGISKTMP.data()); + goto shortcut; + case START_DAEMON: + setup_logfile(true); + goto shortcut; + } - // Create new thread to handle complex requests - new_daemon_thread([=] { return request_handler(client, req_code, cred); }); - return; + // Create new thread to handle complex requests + new_daemon_thread([=] { return request_handler(client, req_code, cred); }); + return; shortcut: - close(client); + close(client); } static shared_ptr log_file; @@ -130,185 +130,185 @@ static char *log_buf; static size_t log_buf_len; void setup_logfile(bool reset) { - if (file_backed.test_and_set(memory_order_relaxed)) - return; - if (reset) - rename(LOGFILE, LOGFILE ".bak"); + if (file_backed.test_and_set(memory_order_relaxed)) + return; + if (reset) + rename(LOGFILE, LOGFILE ".bak"); - int fd = xopen(LOGFILE, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0644); - if (fd < 0) { - log_file.reset(); - return; - } + int fd = xopen(LOGFILE, O_WRONLY | O_APPEND | O_CREAT | O_CLOEXEC, 0644); + if (fd < 0) { + log_file.reset(); + return; + } - // Dump all logs in memory (if exists) - if (log_buf) - write(fd, log_buf, log_buf_len); + // Dump all logs in memory (if exists) + if (log_buf) + write(fd, log_buf, log_buf_len); - if (FILE *fp = fdopen(fd, "a")) { - setbuf(fp, nullptr); - log_file.reset(fp, &fclose); - } + if (FILE *fp = fdopen(fd, "a")) { + setbuf(fp, nullptr); + log_file.reset(fp, &fclose); + } } static int magisk_log(int prio, const char *fmt, va_list ap) { - va_list args; - va_copy(args, ap); + va_list args; + va_copy(args, ap); - // Log to logcat - __android_log_vprint(prio, "Magisk", fmt, ap); + // Log to logcat + __android_log_vprint(prio, "Magisk", fmt, ap); - auto local_log_file = log_file; - if (!local_log_file) - return 0; + auto local_log_file = log_file; + if (!local_log_file) + return 0; - char buf[4096]; - timeval tv; - tm tm; - char type; - switch (prio) { - case ANDROID_LOG_DEBUG: - type = 'D'; - break; - case ANDROID_LOG_INFO: - type = 'I'; - break; - case ANDROID_LOG_WARN: - type = 'W'; - break; - default: - type = 'E'; - break; - } - gettimeofday(&tv, nullptr); - localtime_r(&tv.tv_sec, &tm); - size_t len = strftime(buf, sizeof(buf), "%m-%d %T", &tm); - int ms = tv.tv_usec / 1000; - len += sprintf(buf + len, ".%03d %c : ", ms, type); - strcpy(buf + len, fmt); - return vfprintf(local_log_file.get(), buf, args); + char buf[4096]; + timeval tv; + tm tm; + char type; + switch (prio) { + case ANDROID_LOG_DEBUG: + type = 'D'; + break; + case ANDROID_LOG_INFO: + type = 'I'; + break; + case ANDROID_LOG_WARN: + type = 'W'; + break; + default: + type = 'E'; + break; + } + gettimeofday(&tv, nullptr); + localtime_r(&tv.tv_sec, &tm); + size_t len = strftime(buf, sizeof(buf), "%m-%d %T", &tm); + int ms = tv.tv_usec / 1000; + len += sprintf(buf + len, ".%03d %c : ", ms, type); + strcpy(buf + len, fmt); + return vfprintf(local_log_file.get(), buf, args); } static void android_logging() { - auto in_mem_file = make_stream_fp(log_buf, log_buf_len); - log_file.reset(in_mem_file.release(), [](FILE *) { - free(log_buf); - log_buf = nullptr; - }); - log_cb.d = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_DEBUG, fmt, ap); }; - log_cb.i = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_INFO, fmt, ap); }; - log_cb.w = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_WARN, fmt, ap); }; - log_cb.e = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_ERROR, fmt, ap); }; - log_cb.ex = nop_ex; + auto in_mem_file = make_stream_fp(log_buf, log_buf_len); + log_file.reset(in_mem_file.release(), [](FILE *) { + free(log_buf); + log_buf = nullptr; + }); + log_cb.d = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_DEBUG, fmt, ap); }; + log_cb.i = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_INFO, fmt, ap); }; + log_cb.w = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_WARN, fmt, ap); }; + log_cb.e = [](auto fmt, auto ap){ return magisk_log(ANDROID_LOG_ERROR, fmt, ap); }; + log_cb.ex = nop_ex; } static void daemon_entry(int ppid) { - android_logging(); + android_logging(); - int fd = xopen("/dev/null", O_WRONLY); - xdup2(fd, STDOUT_FILENO); - xdup2(fd, STDERR_FILENO); - if (fd > STDERR_FILENO) - close(fd); - fd = xopen("/dev/zero", O_RDONLY); - xdup2(fd, STDIN_FILENO); - if (fd > STDERR_FILENO) - close(fd); + int fd = xopen("/dev/null", O_WRONLY); + xdup2(fd, STDOUT_FILENO); + xdup2(fd, STDERR_FILENO); + if (fd > STDERR_FILENO) + close(fd); + fd = xopen("/dev/zero", O_RDONLY); + xdup2(fd, STDIN_FILENO); + if (fd > STDERR_FILENO) + close(fd); - setsid(); - setcon("u:r:" SEPOL_PROC_DOMAIN ":s0"); + setsid(); + setcon("u:r:" SEPOL_PROC_DOMAIN ":s0"); - LOGI(NAME_WITH_VER(Magisk) " daemon started\n"); + LOGI(NAME_WITH_VER(Magisk) " daemon started\n"); - // Make sure ppid is not in acct - char src[64], dest[64]; - sprintf(src, "/acct/uid_0/pid_%d", ppid); - sprintf(dest, "/acct/uid_0/pid_%d", getpid()); - rename(src, dest); + // Make sure ppid is not in acct + char src[64], dest[64]; + sprintf(src, "/acct/uid_0/pid_%d", ppid); + sprintf(dest, "/acct/uid_0/pid_%d", getpid()); + rename(src, dest); - // Get self stat - xreadlink("/proc/self/exe", src, sizeof(src)); - MAGISKTMP = dirname(src); - xstat("/proc/self/exe", &self_st); + // Get self stat + xreadlink("/proc/self/exe", src, sizeof(src)); + MAGISKTMP = dirname(src); + xstat("/proc/self/exe", &self_st); - // Get API level - parse_prop_file("/system/build.prop", [](auto key, auto val) -> bool { - if (key == "ro.build.version.sdk") { - SDK_INT = parse_int(val); - return false; - } - return true; - }); - if (SDK_INT < 0) { - // In case some devices do not store this info in build.prop, fallback to getprop - auto sdk = getprop("ro.build.version.sdk"); - if (!sdk.empty()) { - SDK_INT = parse_int(sdk); - } - } - LOGI("* Device API level: %d\n", SDK_INT); + // Get API level + parse_prop_file("/system/build.prop", [](auto key, auto val) -> bool { + if (key == "ro.build.version.sdk") { + SDK_INT = parse_int(val); + return false; + } + return true; + }); + if (SDK_INT < 0) { + // In case some devices do not store this info in build.prop, fallback to getprop + auto sdk = getprop("ro.build.version.sdk"); + if (!sdk.empty()) { + SDK_INT = parse_int(sdk); + } + } + LOGI("* Device API level: %d\n", SDK_INT); - restore_tmpcon(); + restore_tmpcon(); - // SAR cleanups - auto mount_list = MAGISKTMP + "/" ROOTMNT; - if (access(mount_list.data(), F_OK) == 0) { - file_readline(true, mount_list.data(), [](string_view line) -> bool { - umount2(line.data(), MNT_DETACH); - return true; - }); - } - unlink("/dev/.se"); + // SAR cleanups + auto mount_list = MAGISKTMP + "/" ROOTMNT; + if (access(mount_list.data(), F_OK) == 0) { + file_readline(true, mount_list.data(), [](string_view line) -> bool { + umount2(line.data(), MNT_DETACH); + return true; + }); + } + unlink("/dev/.se"); - // Load config status - auto config = MAGISKTMP + "/" INTLROOT "/config"; - parse_prop_file(config.data(), [](auto key, auto val) -> bool { - if (key == "RECOVERYMODE" && val == "true") - RECOVERY_MODE = true; - return true; - }); + // Load config status + auto config = MAGISKTMP + "/" INTLROOT "/config"; + parse_prop_file(config.data(), [](auto key, auto val) -> bool { + if (key == "RECOVERYMODE" && val == "true") + RECOVERY_MODE = true; + return true; + }); - struct sockaddr_un sun; - socklen_t len = setup_sockaddr(&sun, MAIN_SOCKET); - fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (xbind(fd, (struct sockaddr*) &sun, len)) - exit(1); - xlisten(fd, 10); + struct sockaddr_un sun; + socklen_t len = setup_sockaddr(&sun, MAIN_SOCKET); + fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (xbind(fd, (struct sockaddr*) &sun, len)) + exit(1); + xlisten(fd, 10); - // Change process name - set_nice_name("magiskd"); + // Change process name + set_nice_name("magiskd"); - // Block all signals - sigset_t block_set; - sigfillset(&block_set); - pthread_sigmask(SIG_SETMASK, &block_set, nullptr); + // Block all signals + sigset_t block_set; + sigfillset(&block_set); + pthread_sigmask(SIG_SETMASK, &block_set, nullptr); - // Loop forever to listen for requests - for (;;) { - int client = xaccept4(fd, nullptr, nullptr, SOCK_CLOEXEC); - handle_request(client); - } + // Loop forever to listen for requests + for (;;) { + int client = xaccept4(fd, nullptr, nullptr, SOCK_CLOEXEC); + handle_request(client); + } } int connect_daemon(bool create) { - struct sockaddr_un sun; - socklen_t len = setup_sockaddr(&sun, MAIN_SOCKET); - int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (connect(fd, (struct sockaddr*) &sun, len)) { - if (!create || getuid() != UID_ROOT || getgid() != UID_ROOT) { - LOGE("No daemon is currently running!\n"); - exit(1); - } + struct sockaddr_un sun; + socklen_t len = setup_sockaddr(&sun, MAIN_SOCKET); + int fd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (connect(fd, (struct sockaddr*) &sun, len)) { + if (!create || getuid() != UID_ROOT || getgid() != UID_ROOT) { + LOGE("No daemon is currently running!\n"); + exit(1); + } - int ppid = getpid(); - LOGD("client: launching new main daemon process\n"); - if (fork_dont_care() == 0) { - close(fd); - daemon_entry(ppid); - } + int ppid = getpid(); + LOGD("client: launching new main daemon process\n"); + if (fork_dont_care() == 0) { + close(fd); + daemon_entry(ppid); + } - while (connect(fd, (struct sockaddr*) &sun, len)) - usleep(10000); - } - return fd; + while (connect(fd, (struct sockaddr*) &sun, len)) + usleep(10000); + } + return fd; } diff --git a/native/jni/core/db.cpp b/native/jni/core/db.cpp index b196d7c2a..8694e690b 100644 --- a/native/jni/core/db.cpp +++ b/native/jni/core/db.cpp @@ -26,19 +26,19 @@ static sqlite3 *mDB = nullptr; #define SQLITE_OPEN_FULLMUTEX 0x00010000 /* Ok for sqlite3_open_v2() */ static int (*sqlite3_open_v2)( - const char *filename, - sqlite3 **ppDb, - int flags, - const char *zVfs); + const char *filename, + sqlite3 **ppDb, + int flags, + const char *zVfs); static const char *(*sqlite3_errmsg)(sqlite3 *db); static int (*sqlite3_close)(sqlite3 *db); static void (*sqlite3_free)(void *v); static int (*sqlite3_exec)( - sqlite3 *db, - const char *sql, - int (*callback)(void*, int, char**, char**), - void *v, - char **errmsg); + sqlite3 *db, + const char *sql, + int (*callback)(void*, int, char**, char**), + void *v, + char **errmsg); // Internal Android linker APIs @@ -46,14 +46,14 @@ static void (*android_get_LD_LIBRARY_PATH)(char *buffer, size_t buffer_size); static void (*android_update_LD_LIBRARY_PATH)(const char *ld_library_path); #define DLERR(ptr) if (!(ptr)) { \ - LOGE("db: %s\n", dlerror()); \ - return false; \ + LOGE("db: %s\n", dlerror()); \ + return false; \ } #define DLOAD(handle, arg) {\ - auto f = dlsym(handle, #arg); \ - DLERR(f) \ - *(void **) &(arg) = f; \ + auto f = dlsym(handle, #arg); \ + DLERR(f) \ + *(void **) &(arg) = f; \ } #ifdef __LP64__ @@ -65,339 +65,339 @@ constexpr char apex_path[] = "/apex/com.android.runtime/lib:/apex/com.android.ar static int dl_init = 0; static bool dload_sqlite() { - if (dl_init) - return dl_init > 0; - dl_init = -1; + if (dl_init) + return dl_init > 0; + dl_init = -1; - auto sqlite = dlopen("libsqlite.so", RTLD_LAZY); - if (!sqlite) { - // Should only happen on Android 10+ - auto dl = dlopen("libdl_android.so", RTLD_LAZY); - DLERR(dl); + auto sqlite = dlopen("libsqlite.so", RTLD_LAZY); + if (!sqlite) { + // Should only happen on Android 10+ + auto dl = dlopen("libdl_android.so", RTLD_LAZY); + DLERR(dl); - DLOAD(dl, android_get_LD_LIBRARY_PATH); - DLOAD(dl, android_update_LD_LIBRARY_PATH); + DLOAD(dl, android_get_LD_LIBRARY_PATH); + DLOAD(dl, android_update_LD_LIBRARY_PATH); - // Inject APEX into LD_LIBRARY_PATH - char ld_path[4096]; - memcpy(ld_path, apex_path, sizeof(apex_path)); - constexpr int len = sizeof(apex_path) - 1; - android_get_LD_LIBRARY_PATH(ld_path + len, sizeof(ld_path) - len); - android_update_LD_LIBRARY_PATH(ld_path); - sqlite = dlopen("libsqlite.so", RTLD_LAZY); + // Inject APEX into LD_LIBRARY_PATH + char ld_path[4096]; + memcpy(ld_path, apex_path, sizeof(apex_path)); + constexpr int len = sizeof(apex_path) - 1; + android_get_LD_LIBRARY_PATH(ld_path + len, sizeof(ld_path) - len); + android_update_LD_LIBRARY_PATH(ld_path); + sqlite = dlopen("libsqlite.so", RTLD_LAZY); - // Revert LD_LIBRARY_PATH just in case - android_update_LD_LIBRARY_PATH(ld_path + len); - } - DLERR(sqlite); + // Revert LD_LIBRARY_PATH just in case + android_update_LD_LIBRARY_PATH(ld_path + len); + } + DLERR(sqlite); - DLOAD(sqlite, sqlite3_open_v2); - DLOAD(sqlite, sqlite3_errmsg); - DLOAD(sqlite, sqlite3_close); - DLOAD(sqlite, sqlite3_exec); - DLOAD(sqlite, sqlite3_free); + DLOAD(sqlite, sqlite3_open_v2); + DLOAD(sqlite, sqlite3_errmsg); + DLOAD(sqlite, sqlite3_close); + DLOAD(sqlite, sqlite3_exec); + DLOAD(sqlite, sqlite3_free); - dl_init = 1; - return true; + dl_init = 1; + return true; } int db_strings::getKeyIdx(string_view key) const { - int idx = DB_STRING_NUM; - for (int i = 0; i < DB_STRING_NUM; ++i) { - if (key == DB_STRING_KEYS[i]) - idx = i; - } - return idx; + int idx = DB_STRING_NUM; + for (int i = 0; i < DB_STRING_NUM; ++i) { + if (key == DB_STRING_KEYS[i]) + idx = i; + } + return idx; } db_settings::db_settings() { - // Default settings - data[ROOT_ACCESS] = ROOT_ACCESS_APPS_AND_ADB; - data[SU_MULTIUSER_MODE] = MULTIUSER_MODE_OWNER_ONLY; - data[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER; - data[HIDE_CONFIG] = false; + // Default settings + data[ROOT_ACCESS] = ROOT_ACCESS_APPS_AND_ADB; + data[SU_MULTIUSER_MODE] = MULTIUSER_MODE_OWNER_ONLY; + data[SU_MNT_NS] = NAMESPACE_MODE_REQUESTER; + data[HIDE_CONFIG] = false; } int db_settings::getKeyIdx(string_view key) const { - int idx = DB_SETTINGS_NUM; - for (int i = 0; i < DB_SETTINGS_NUM; ++i) { - if (key == DB_SETTING_KEYS[i]) - idx = i; - } - return idx; + int idx = DB_SETTINGS_NUM; + for (int i = 0; i < DB_SETTINGS_NUM; ++i) { + if (key == DB_SETTING_KEYS[i]) + idx = i; + } + return idx; } static int ver_cb(void *ver, int, char **data, char **) { - *((int *) ver) = parse_int(data[0]); - return 0; + *((int *) ver) = parse_int(data[0]); + return 0; } #define err_ret(e) if (e) return e; static char *open_and_init_db(sqlite3 *&db) { - if (!dload_sqlite()) - return strdup("Cannot load libsqlite.so"); + if (!dload_sqlite()) + return strdup("Cannot load libsqlite.so"); - int ret = sqlite3_open_v2(MAGISKDB, &db, - SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, nullptr); - if (ret) - return strdup(sqlite3_errmsg(db)); - int ver; - bool upgrade = false; - char *err; - sqlite3_exec(db, "PRAGMA user_version", ver_cb, &ver, &err); - err_ret(err); - if (ver > DB_VERSION) { - // Don't support downgrading database - sqlite3_close(db); - return nullptr; - } - if (ver < 3) { - // Policies - sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS policies " - "(uid INT, package_name TEXT, policy INT, until INT, " - "logging INT, notification INT, PRIMARY KEY(uid))", - nullptr, nullptr, &err); - err_ret(err); - // Settings - sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS settings " - "(key TEXT, value INT, PRIMARY KEY(key))", - nullptr, nullptr, &err); - err_ret(err); - ver = 3; - upgrade = true; - } - if (ver < 4) { - // Strings - sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS strings " - "(key TEXT, value TEXT, PRIMARY KEY(key))", - nullptr, nullptr, &err); - err_ret(err); - ver = 4; - upgrade = true; - } - if (ver < 5) { - sqlite3_exec(db, "UPDATE policies SET uid=uid%100000", nullptr, nullptr, &err); - err_ret(err); - /* Directly jump to version 6 */ - ver = 6; - upgrade = true; - } - if (ver < 7) { - sqlite3_exec(db, - "CREATE TABLE IF NOT EXISTS hidelist " - "(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));", - nullptr, nullptr, &err); - err_ret(err); - /* Directly jump to version 9 */ - ver = 9; - upgrade = true; - } - if (ver < 8) { - sqlite3_exec(db, - "BEGIN TRANSACTION;" - "ALTER TABLE hidelist RENAME TO hidelist_tmp;" - "CREATE TABLE IF NOT EXISTS hidelist " - "(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));" - "INSERT INTO hidelist SELECT process as package_name, process FROM hidelist_tmp;" - "DROP TABLE hidelist_tmp;" - "COMMIT;", - nullptr, nullptr, &err); - err_ret(err); - /* Directly jump to version 9 */ - ver = 9; - upgrade = true; - } - if (ver < 9) { - sqlite3_exec(db, - "BEGIN TRANSACTION;" - "ALTER TABLE hidelist RENAME TO hidelist_tmp;" - "CREATE TABLE IF NOT EXISTS hidelist " - "(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));" - "INSERT INTO hidelist SELECT * FROM hidelist_tmp;" - "DROP TABLE hidelist_tmp;" - "COMMIT;", - nullptr, nullptr, &err); - err_ret(err); - ver = 9; - upgrade = true; - } - if (ver < 10) { - sqlite3_exec(db, "DROP TABLE IF EXISTS logs", nullptr, nullptr, &err); - err_ret(err); - ver = 10; - upgrade = true; - } + int ret = sqlite3_open_v2(MAGISKDB, &db, + SQLITE_OPEN_READWRITE | SQLITE_OPEN_CREATE | SQLITE_OPEN_FULLMUTEX, nullptr); + if (ret) + return strdup(sqlite3_errmsg(db)); + int ver; + bool upgrade = false; + char *err; + sqlite3_exec(db, "PRAGMA user_version", ver_cb, &ver, &err); + err_ret(err); + if (ver > DB_VERSION) { + // Don't support downgrading database + sqlite3_close(db); + return nullptr; + } + if (ver < 3) { + // Policies + sqlite3_exec(db, + "CREATE TABLE IF NOT EXISTS policies " + "(uid INT, package_name TEXT, policy INT, until INT, " + "logging INT, notification INT, PRIMARY KEY(uid))", + nullptr, nullptr, &err); + err_ret(err); + // Settings + sqlite3_exec(db, + "CREATE TABLE IF NOT EXISTS settings " + "(key TEXT, value INT, PRIMARY KEY(key))", + nullptr, nullptr, &err); + err_ret(err); + ver = 3; + upgrade = true; + } + if (ver < 4) { + // Strings + sqlite3_exec(db, + "CREATE TABLE IF NOT EXISTS strings " + "(key TEXT, value TEXT, PRIMARY KEY(key))", + nullptr, nullptr, &err); + err_ret(err); + ver = 4; + upgrade = true; + } + if (ver < 5) { + sqlite3_exec(db, "UPDATE policies SET uid=uid%100000", nullptr, nullptr, &err); + err_ret(err); + /* Directly jump to version 6 */ + ver = 6; + upgrade = true; + } + if (ver < 7) { + sqlite3_exec(db, + "CREATE TABLE IF NOT EXISTS hidelist " + "(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));", + nullptr, nullptr, &err); + err_ret(err); + /* Directly jump to version 9 */ + ver = 9; + upgrade = true; + } + if (ver < 8) { + sqlite3_exec(db, + "BEGIN TRANSACTION;" + "ALTER TABLE hidelist RENAME TO hidelist_tmp;" + "CREATE TABLE IF NOT EXISTS hidelist " + "(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));" + "INSERT INTO hidelist SELECT process as package_name, process FROM hidelist_tmp;" + "DROP TABLE hidelist_tmp;" + "COMMIT;", + nullptr, nullptr, &err); + err_ret(err); + /* Directly jump to version 9 */ + ver = 9; + upgrade = true; + } + if (ver < 9) { + sqlite3_exec(db, + "BEGIN TRANSACTION;" + "ALTER TABLE hidelist RENAME TO hidelist_tmp;" + "CREATE TABLE IF NOT EXISTS hidelist " + "(package_name TEXT, process TEXT, PRIMARY KEY(package_name, process));" + "INSERT INTO hidelist SELECT * FROM hidelist_tmp;" + "DROP TABLE hidelist_tmp;" + "COMMIT;", + nullptr, nullptr, &err); + err_ret(err); + ver = 9; + upgrade = true; + } + if (ver < 10) { + sqlite3_exec(db, "DROP TABLE IF EXISTS logs", nullptr, nullptr, &err); + err_ret(err); + ver = 10; + upgrade = true; + } - if (upgrade) { - // Set version - char query[32]; - sprintf(query, "PRAGMA user_version=%d", ver); - sqlite3_exec(db, query, nullptr, nullptr, &err); - err_ret(err); - } - return nullptr; + if (upgrade) { + // Set version + char query[32]; + sprintf(query, "PRAGMA user_version=%d", ver); + sqlite3_exec(db, query, nullptr, nullptr, &err); + err_ret(err); + } + return nullptr; } char *db_exec(const char *sql) { - char *err; - if (mDB == nullptr) { - err = open_and_init_db(mDB); - db_err_cmd(err, - // Open fails, remove and reconstruct - unlink(MAGISKDB); - err = open_and_init_db(mDB); - err_ret(err); - ); - } - if (mDB) { - sqlite3_exec(mDB, sql, nullptr, nullptr, &err); - return err; - } - return nullptr; + char *err; + if (mDB == nullptr) { + err = open_and_init_db(mDB); + db_err_cmd(err, + // Open fails, remove and reconstruct + unlink(MAGISKDB); + err = open_and_init_db(mDB); + err_ret(err); + ); + } + if (mDB) { + sqlite3_exec(mDB, sql, nullptr, nullptr, &err); + return err; + } + return nullptr; } char *db_exec(const char *sql, const db_row_cb &fn) { - char *err; - if (mDB == nullptr) { - err = open_and_init_db(mDB); - db_err_cmd(err, - // Open fails, remove and reconstruct - unlink(MAGISKDB); - err = open_and_init_db(mDB); - err_ret(err); - ); - } - if (mDB) { - sqlite3_exec(mDB, sql, [](void *cb, int col_num, char **data, char **col_name) -> int { - auto &func = *reinterpret_cast(cb); - db_row row; - for (int i = 0; i < col_num; ++i) - row[col_name[i]] = data[i]; - return func(row) ? 0 : 1; - }, (void *) &fn, &err); - return err; - } - return nullptr; + char *err; + if (mDB == nullptr) { + err = open_and_init_db(mDB); + db_err_cmd(err, + // Open fails, remove and reconstruct + unlink(MAGISKDB); + err = open_and_init_db(mDB); + err_ret(err); + ); + } + if (mDB) { + sqlite3_exec(mDB, sql, [](void *cb, int col_num, char **data, char **col_name) -> int { + auto &func = *reinterpret_cast(cb); + db_row row; + for (int i = 0; i < col_num; ++i) + row[col_name[i]] = data[i]; + return func(row) ? 0 : 1; + }, (void *) &fn, &err); + return err; + } + return nullptr; } int get_db_settings(db_settings &cfg, int key) { - char *err; - auto settings_cb = [&](db_row &row) -> bool { - cfg[row["key"]] = parse_int(row["value"]); - LOGD("magiskdb: query %s=[%s]\n", row["key"].data(), row["value"].data()); - return true; - }; - if (key >= 0) { - char query[128]; - sprintf(query, "SELECT key, value FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]); - err = db_exec(query, settings_cb); - } else { - err = db_exec("SELECT key, value FROM settings", settings_cb); - } - db_err_cmd(err, return 1); - return 0; + char *err; + auto settings_cb = [&](db_row &row) -> bool { + cfg[row["key"]] = parse_int(row["value"]); + LOGD("magiskdb: query %s=[%s]\n", row["key"].data(), row["value"].data()); + return true; + }; + if (key >= 0) { + char query[128]; + sprintf(query, "SELECT key, value FROM settings WHERE key='%s'", DB_SETTING_KEYS[key]); + err = db_exec(query, settings_cb); + } else { + err = db_exec("SELECT key, value FROM settings", settings_cb); + } + db_err_cmd(err, return 1); + return 0; } int get_db_strings(db_strings &str, int key) { - char *err; - auto string_cb = [&](db_row &row) -> bool { - str[row["key"]] = row["value"]; - return true; - }; - if (key >= 0) { - char query[128]; - sprintf(query, "SELECT key, value FROM strings WHERE key='%s'", DB_STRING_KEYS[key]); - err = db_exec(query, string_cb); - } else { - err = db_exec("SELECT key, value FROM strings", string_cb); - } - db_err_cmd(err, return 1); - return 0; + char *err; + auto string_cb = [&](db_row &row) -> bool { + str[row["key"]] = row["value"]; + return true; + }; + if (key >= 0) { + char query[128]; + sprintf(query, "SELECT key, value FROM strings WHERE key='%s'", DB_STRING_KEYS[key]); + err = db_exec(query, string_cb); + } else { + err = db_exec("SELECT key, value FROM strings", string_cb); + } + db_err_cmd(err, return 1); + return 0; } int get_uid_policy(su_access &su, int uid) { - char query[256], *err; - sprintf(query, "SELECT policy, logging, notification FROM policies " - "WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr)); - err = db_exec(query, [&](db_row &row) -> bool { - su.policy = (policy_t) parse_int(row["policy"]); - su.log = parse_int(row["logging"]); - su.notify = parse_int(row["notification"]); - LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n", su.policy, su.log, su.notify); - return true; - }); - db_err_cmd(err, return 1); - return 0; + char query[256], *err; + sprintf(query, "SELECT policy, logging, notification FROM policies " + "WHERE uid=%d AND (until=0 OR until>%li)", uid, time(nullptr)); + err = db_exec(query, [&](db_row &row) -> bool { + su.policy = (policy_t) parse_int(row["policy"]); + su.log = parse_int(row["logging"]); + su.notify = parse_int(row["notification"]); + LOGD("magiskdb: query policy=[%d] log=[%d] notify=[%d]\n", su.policy, su.log, su.notify); + return true; + }); + db_err_cmd(err, return 1); + return 0; } bool check_manager(string *pkg) { - db_strings str; - get_db_strings(str, SU_MANAGER); - bool ret = validate_manager(str[SU_MANAGER], 0, nullptr); - if (pkg) { - if (ret) - pkg->swap(str[SU_MANAGER]); - else - *pkg = "xxx"; /* Make sure the return pkg can never exist */ - } - return ret; + db_strings str; + get_db_strings(str, SU_MANAGER); + bool ret = validate_manager(str[SU_MANAGER], 0, nullptr); + if (pkg) { + if (ret) + pkg->swap(str[SU_MANAGER]); + else + *pkg = "xxx"; /* Make sure the return pkg can never exist */ + } + return ret; } bool validate_manager(string &pkg, int userid, struct stat *st) { - struct stat tmp_st; - if (st == nullptr) - st = &tmp_st; + struct stat tmp_st; + if (st == nullptr) + st = &tmp_st; - // Prefer DE storage - char app_path[128]; - sprintf(app_path, "%s/%d/%s", APP_DATA_DIR, userid, pkg.data()); - if (pkg.empty() || stat(app_path, st)) { - // Check the official package name - sprintf(app_path, "%s/%d/" JAVA_PACKAGE_NAME, APP_DATA_DIR, userid); - if (stat(app_path, st)) { - LOGE("su: cannot find manager\n"); - memset(st, 0, sizeof(*st)); - pkg.clear(); - return false; - } else { - // Switch to official package if exists - pkg = JAVA_PACKAGE_NAME; - } - } - return true; + // Prefer DE storage + char app_path[128]; + sprintf(app_path, "%s/%d/%s", APP_DATA_DIR, userid, pkg.data()); + if (pkg.empty() || stat(app_path, st)) { + // Check the official package name + sprintf(app_path, "%s/%d/" JAVA_PACKAGE_NAME, APP_DATA_DIR, userid); + if (stat(app_path, st)) { + LOGE("su: cannot find manager\n"); + memset(st, 0, sizeof(*st)); + pkg.clear(); + return false; + } else { + // Switch to official package if exists + pkg = JAVA_PACKAGE_NAME; + } + } + return true; } void exec_sql(int client) { - run_finally f([=]{ close(client); }); - char *sql = read_string(client); - char *err = db_exec(sql, [&](db_row &row) -> bool { - string out; - bool first = true; - for (auto it : row) { - if (first) first = false; - else out += '|'; - out += it.first; - out += '='; - out += it.second; - } - write_int(client, out.length()); - xwrite(client, out.data(), out.length()); - return true; - }); - free(sql); - write_int(client, 0); - db_err_cmd(err, return; ); + run_finally f([=]{ close(client); }); + char *sql = read_string(client); + char *err = db_exec(sql, [&](db_row &row) -> bool { + string out; + bool first = true; + for (auto it : row) { + if (first) first = false; + else out += '|'; + out += it.first; + out += '='; + out += it.second; + } + write_int(client, out.length()); + xwrite(client, out.data(), out.length()); + return true; + }); + free(sql); + write_int(client, 0); + db_err_cmd(err, return; ); } bool db_err(char *e) { - if (e) { - LOGE("sqlite3_exec: %s\n", e); - sqlite3_free(e); - return true; - } - return false; + if (e) { + LOGE("sqlite3_exec: %s\n", e); + sqlite3_free(e); + return true; + } + return false; } diff --git a/native/jni/core/magisk.cpp b/native/jni/core/magisk.cpp index c050ada90..15254dead 100644 --- a/native/jni/core/magisk.cpp +++ b/native/jni/core/magisk.cpp @@ -10,7 +10,7 @@ using namespace std; [[noreturn]] static void usage() { - fprintf(stderr, + fprintf(stderr, R"EOF(Magisk - Multi-purpose Utility Usage: magisk [applet [arguments]...] @@ -39,92 +39,92 @@ Advanced Options (Internal APIs): Available applets: )EOF"); - for (int i = 0; applet_names[i]; ++i) - fprintf(stderr, i ? ", %s" : " %s", applet_names[i]); - fprintf(stderr, "\n\n"); - exit(1); + for (int i = 0; applet_names[i]; ++i) + fprintf(stderr, i ? ", %s" : " %s", applet_names[i]); + fprintf(stderr, "\n\n"); + exit(1); } int magisk_main(int argc, char *argv[]) { - if (argc < 2) - usage(); - if (argv[1] == "-c"sv) { - printf(MAGISK_VERSION ":MAGISK (" str(MAGISK_VER_CODE) ")\n"); - return 0; - } else if (argv[1] == "-v"sv) { - int fd = connect_daemon(); - write_int(fd, CHECK_VERSION); - char *v = read_string(fd); - printf("%s\n", v); - free(v); - return 0; - } else if (argv[1] == "-V"sv) { - int fd = connect_daemon(); - write_int(fd, CHECK_VERSION_CODE); - printf("%d\n", read_int(fd)); - return 0; - } else if (argv[1] == "--list"sv) { - for (int i = 0; applet_names[i]; ++i) - printf("%s\n", applet_names[i]); - return 0; - } else if (argv[1] == "--unlock-blocks"sv) { - unlock_blocks(); - return 0; - } else if (argv[1] == "--restorecon"sv) { - restorecon(); - return 0; - } else if (argc >= 4 && argv[1] == "--clone-attr"sv) {; - clone_attr(argv[2], argv[3]); - return 0; - } else if (argc >= 4 && argv[1] == "--clone"sv) { - cp_afc(argv[2], argv[3]); - return 0; - } else if (argv[1] == "--daemon"sv) { - int fd = connect_daemon(true); - write_int(fd, START_DAEMON); - return 0; - } else if (argv[1] == "--post-fs-data"sv) { - int fd = connect_daemon(true); - write_int(fd, POST_FS_DATA); - return read_int(fd); - } else if (argv[1] == "--service"sv) { - int fd = connect_daemon(true); - write_int(fd, LATE_START); - return read_int(fd); - } else if (argv[1] == "--boot-complete"sv) { - int fd = connect_daemon(true); - write_int(fd, BOOT_COMPLETE); - return read_int(fd); - } else if (argc >= 3 && argv[1] == "--sqlite"sv) { - int fd = connect_daemon(); - write_int(fd, SQLITE_CMD); - write_string(fd, argv[2]); - for (;;) { - char *res = read_string(fd); - if (res[0] == '\0') { - return 0; - } - printf("%s\n", res); - free(res); - } - } else if (argv[1] == "--remove-modules"sv) { - int fd = connect_daemon(); - write_int(fd, REMOVE_MODULES); - return read_int(fd); - } else if (argv[1] == "--path"sv) { - int fd = connect_daemon(); - write_int(fd, GET_PATH); - char *path = read_string(fd); - printf("%s\n", path); - return 0; - } else if (argc >= 3 && argv[1] == "--install-module"sv) { - install_module(argv[2]); - } + if (argc < 2) + usage(); + if (argv[1] == "-c"sv) { + printf(MAGISK_VERSION ":MAGISK (" str(MAGISK_VER_CODE) ")\n"); + return 0; + } else if (argv[1] == "-v"sv) { + int fd = connect_daemon(); + write_int(fd, CHECK_VERSION); + char *v = read_string(fd); + printf("%s\n", v); + free(v); + return 0; + } else if (argv[1] == "-V"sv) { + int fd = connect_daemon(); + write_int(fd, CHECK_VERSION_CODE); + printf("%d\n", read_int(fd)); + return 0; + } else if (argv[1] == "--list"sv) { + for (int i = 0; applet_names[i]; ++i) + printf("%s\n", applet_names[i]); + return 0; + } else if (argv[1] == "--unlock-blocks"sv) { + unlock_blocks(); + return 0; + } else if (argv[1] == "--restorecon"sv) { + restorecon(); + return 0; + } else if (argc >= 4 && argv[1] == "--clone-attr"sv) {; + clone_attr(argv[2], argv[3]); + return 0; + } else if (argc >= 4 && argv[1] == "--clone"sv) { + cp_afc(argv[2], argv[3]); + return 0; + } else if (argv[1] == "--daemon"sv) { + int fd = connect_daemon(true); + write_int(fd, START_DAEMON); + return 0; + } else if (argv[1] == "--post-fs-data"sv) { + int fd = connect_daemon(true); + write_int(fd, POST_FS_DATA); + return read_int(fd); + } else if (argv[1] == "--service"sv) { + int fd = connect_daemon(true); + write_int(fd, LATE_START); + return read_int(fd); + } else if (argv[1] == "--boot-complete"sv) { + int fd = connect_daemon(true); + write_int(fd, BOOT_COMPLETE); + return read_int(fd); + } else if (argc >= 3 && argv[1] == "--sqlite"sv) { + int fd = connect_daemon(); + write_int(fd, SQLITE_CMD); + write_string(fd, argv[2]); + for (;;) { + char *res = read_string(fd); + if (res[0] == '\0') { + return 0; + } + printf("%s\n", res); + free(res); + } + } else if (argv[1] == "--remove-modules"sv) { + int fd = connect_daemon(); + write_int(fd, REMOVE_MODULES); + return read_int(fd); + } else if (argv[1] == "--path"sv) { + int fd = connect_daemon(); + write_int(fd, GET_PATH); + char *path = read_string(fd); + printf("%s\n", path); + return 0; + } else if (argc >= 3 && argv[1] == "--install-module"sv) { + install_module(argv[2]); + } #if 0 - /* Entry point for testing stuffs */ - else if (argv[1] == "--test"sv) { - return 0; - } + /* Entry point for testing stuffs */ + else if (argv[1] == "--test"sv) { + return 0; + } #endif - usage(); + usage(); } diff --git a/native/jni/core/module.cpp b/native/jni/core/module.cpp index eecdc324c..1811f5679 100644 --- a/native/jni/core/module.cpp +++ b/native/jni/core/module.cpp @@ -33,10 +33,10 @@ class root_node; static void merge_node(node_entry *a, node_entry *b); template static bool isa(node_entry *node); static int bind_mount(const char *from, const char *to) { - int ret = xmount(from, to, nullptr, MS_BIND, nullptr); - if (ret == 0) - VLOGD("bind_mnt", from, to); - return ret; + int ret = xmount(from, to, nullptr, MS_BIND, nullptr); + if (ret == 0) + VLOGD("bind_mnt", from, to); + return ret; } template uint8_t type_id() { return TYPE_CUSTOM; } @@ -49,262 +49,262 @@ template<> uint8_t type_id() { return TYPE_ROOT; } class node_entry { public: - virtual ~node_entry() = default; + virtual ~node_entry() = default; - bool is_dir() { return file_type() == DT_DIR; } - bool is_lnk() { return file_type() == DT_LNK; } - bool is_reg() { return file_type() == DT_REG; } + bool is_dir() { return file_type() == DT_DIR; } + bool is_lnk() { return file_type() == DT_LNK; } + bool is_reg() { return file_type() == DT_REG; } - uint8_t type() { return node_type; } - const string &name() { return _name; } + uint8_t type() { return node_type; } + const string &name() { return _name; } - // Paths - const string &node_path(); - string mirror_path() { return mirror_dir + node_path(); } + // Paths + const string &node_path(); + string mirror_path() { return mirror_dir + node_path(); } - dir_node *parent() { return _parent; } + dir_node *parent() { return _parent; } - virtual void mount() = 0; + virtual void mount() = 0; - static string module_mnt; - static string mirror_dir; + static string module_mnt; + static string mirror_dir; protected: - template - node_entry(const char *name, uint8_t file_type, T*) - : _name(name), _file_type(file_type), node_type(type_id()) {} + template + node_entry(const char *name, uint8_t file_type, T*) + : _name(name), _file_type(file_type), node_type(type_id()) {} - template - explicit node_entry(T*) : node_type(type_id()) {} + template + explicit node_entry(T*) : node_type(type_id()) {} - void create_and_mount(const string &src); + void create_and_mount(const string &src); - /* Use top bit of _file_type for node exist status */ - bool exist() { return static_cast(_file_type & (1 << 7)); } - void set_exist(bool b) { if (b) _file_type |= (1 << 7); else _file_type &= ~(1 << 7); } - uint8_t file_type() { return static_cast(_file_type & ~(1 << 7)); } + /* Use top bit of _file_type for node exist status */ + bool exist() { return static_cast(_file_type & (1 << 7)); } + void set_exist(bool b) { if (b) _file_type |= (1 << 7); else _file_type &= ~(1 << 7); } + uint8_t file_type() { return static_cast(_file_type & ~(1 << 7)); } private: - friend void merge_node(node_entry *a, node_entry *b); - friend class dir_node; + friend void merge_node(node_entry *a, node_entry *b); + friend class dir_node; - bool need_skel_upgrade(node_entry *child); + bool need_skel_upgrade(node_entry *child); - // Node properties - string _name; - uint8_t _file_type; - uint8_t node_type; + // Node properties + string _name; + uint8_t _file_type; + uint8_t node_type; - dir_node *_parent = nullptr; + dir_node *_parent = nullptr; - // Cache - string _node_path; + // Cache + string _node_path; }; class dir_node : public node_entry { public: - friend void merge_node(node_entry *a, node_entry *b); + friend void merge_node(node_entry *a, node_entry *b); - typedef map map_type; - typedef map_type::iterator map_iter; + typedef map map_type; + typedef map_type::iterator map_iter; - ~dir_node() override { - for (auto &it : children) - delete it.second; - children.clear(); - } + ~dir_node() override { + for (auto &it : children) + delete it.second; + children.clear(); + } - // Return false to indicate need to upgrade to module - bool collect_files(const char *module, int dfd); + // Return false to indicate need to upgrade to module + bool collect_files(const char *module, int dfd); - // Return false to indicate need to upgrade to skeleton - bool prepare(); + // Return false to indicate need to upgrade to skeleton + bool prepare(); - // Default directory mount logic - void mount() override { - for (auto &pair : children) - pair.second->mount(); - } + // Default directory mount logic + void mount() override { + for (auto &pair : children) + pair.second->mount(); + } - /*************** - * Tree Methods - ***************/ + /*************** + * Tree Methods + ***************/ - bool is_empty() { return children.empty(); } + bool is_empty() { return children.empty(); } - template - T *child(string_view name) { return iter_to_node(children.find(name)); } + template + T *child(string_view name) { return iter_to_node(children.find(name)); } - // Lazy val - root_node *root() { - if (!_root) - _root = _parent->root(); - return _root; - } + // Lazy val + root_node *root() { + if (!_root) + _root = _parent->root(); + return _root; + } - // Return child with name or nullptr - node_entry *extract(string_view name); + // Return child with name or nullptr + node_entry *extract(string_view name); - // Return false if rejected - bool insert(node_entry *node) { - return node - ? iter_to_node(insert(children.find(node->_name), node->node_type, - [=](auto _) { return node; })) != nullptr - : false; - } + // Return false if rejected + bool insert(node_entry *node) { + return node + ? iter_to_node(insert(children.find(node->_name), node->node_type, + [=](auto _) { return node; })) != nullptr + : false; + } - // Return inserted node or null if rejected - template - T *emplace(string_view name, Args &...args) { - return iter_to_node(insert(children.find(name), type_id(), - [&](auto _) { return new T(std::forward(args)...); })); - } + // Return inserted node or null if rejected + template + T *emplace(string_view name, Args &...args) { + return iter_to_node(insert(children.find(name), type_id(), + [&](auto _) { return new T(std::forward(args)...); })); + } - // Return inserted node, existing node with same rank, or null - template - T *emplace_or_get(string_view name, Args &...args) { - return iter_to_node(insert(children.find(name), type_id(), - [&](auto _) { return new T(std::forward(args)...); }, true)); - } + // Return inserted node, existing node with same rank, or null + template + T *emplace_or_get(string_view name, Args &...args) { + return iter_to_node(insert(children.find(name), type_id(), + [&](auto _) { return new T(std::forward(args)...); }, true)); + } - // Return upgraded node or null if rejected - template - T *upgrade(string_view name, Args &...args) { - return iter_to_node(upgrade(children.find(name), args...)); - } + // Return upgraded node or null if rejected + template + T *upgrade(string_view name, Args &...args) { + return iter_to_node(upgrade(children.find(name), args...)); + } protected: - template - dir_node(const char *name, uint8_t file_type, T *self) : node_entry(name, file_type, self) { - if constexpr (std::is_same_v) - _root = self; - } + template + dir_node(const char *name, uint8_t file_type, T *self) : node_entry(name, file_type, self) { + if constexpr (std::is_same_v) + _root = self; + } - template - dir_node(node_entry *node, T *self) : node_entry(self) { - merge_node(this, node); - if constexpr (std::is_same_v) - _root = self; - } + template + dir_node(node_entry *node, T *self) : node_entry(self) { + merge_node(this, node); + if constexpr (std::is_same_v) + _root = self; + } - template - dir_node(const char *name, T *self) : dir_node(name, DT_DIR, self) {} + template + dir_node(const char *name, T *self) : dir_node(name, DT_DIR, self) {} - template - T *iter_to_node(const map_iter &it) { - return reinterpret_cast(it == children.end() ? nullptr : it->second); - } + template + T *iter_to_node(const map_iter &it) { + return reinterpret_cast(it == children.end() ? nullptr : it->second); + } - /* fn signature: (node_ent *&) -> node_ent * - * fn gets reference to the existing node, may be null. - * If fn consumes input, need to set reference to null. - * Returns new node or null to reject the insertion. */ + /* fn signature: (node_ent *&) -> node_ent * + * fn gets reference to the existing node, may be null. + * If fn consumes input, need to set reference to null. + * Returns new node or null to reject the insertion. */ - template - map_iter insert(map_iter it, uint8_t type, Func fn, bool allow_same = false); + template + map_iter insert(map_iter it, uint8_t type, Func fn, bool allow_same = false); - template - map_iter upgrade(map_iter it, Args &...args) { - return insert(it, type_id(), [&](node_entry *&ex) -> node_entry * { - if (!ex) - return nullptr; - if constexpr (!std::is_same_v) { - // Type check if specific type is selected - if (!isa(ex)) - return nullptr; - } - auto node = new To(reinterpret_cast(ex), std::forward(args)...); - ex = nullptr; - return node; - }); - } + template + map_iter upgrade(map_iter it, Args &...args) { + return insert(it, type_id(), [&](node_entry *&ex) -> node_entry * { + if (!ex) + return nullptr; + if constexpr (!std::is_same_v) { + // Type check if specific type is selected + if (!isa(ex)) + return nullptr; + } + auto node = new To(reinterpret_cast(ex), std::forward(args)...); + ex = nullptr; + return node; + }); + } - // dir nodes host children - map_type children; + // dir nodes host children + map_type children; - // Root node lookup cache - root_node *_root; + // Root node lookup cache + root_node *_root; }; class root_node : public dir_node { public: - explicit root_node(const char *name) : dir_node(name, this), prefix("") {} - explicit root_node(node_entry *node) : dir_node(node, this), prefix("/system") {} - const char * const prefix; + explicit root_node(const char *name) : dir_node(name, this), prefix("") {} + explicit root_node(node_entry *node) : dir_node(node, this), prefix("/system") {} + const char * const prefix; }; class inter_node : public dir_node { public: - inter_node(const char *name, const char *module) : dir_node(name, this), module(module) {} + inter_node(const char *name, const char *module) : dir_node(name, this), module(module) {} private: - const char *module; - friend class module_node; + const char *module; + friend class module_node; }; class module_node : public node_entry { public: - module_node(const char *module, dirent *entry) - : node_entry(entry->d_name, entry->d_type, this), module(module) {} + module_node(const char *module, dirent *entry) + : node_entry(entry->d_name, entry->d_type, this), module(module) {} - module_node(node_entry *node, const char *module) : node_entry(this), module(module) { - merge_node(this, node); - } + module_node(node_entry *node, const char *module) : node_entry(this), module(module) { + merge_node(this, node); + } - explicit module_node(inter_node *node) : module_node(node, node->module) {} + explicit module_node(inter_node *node) : module_node(node, node->module) {} - void mount() override; + void mount() override; private: - const char *module; + const char *module; }; class mirror_node : public node_entry { public: - explicit mirror_node(dirent *entry) : node_entry(entry->d_name, entry->d_type, this) {} - void mount() override { - create_and_mount(mirror_path()); - } + explicit mirror_node(dirent *entry) : node_entry(entry->d_name, entry->d_type, this) {} + void mount() override { + create_and_mount(mirror_path()); + } }; class skel_node : public dir_node { public: - explicit skel_node(node_entry *node); - void mount() override; + explicit skel_node(node_entry *node); + void mount() override; }; // Poor man's dynamic cast without RTTI template static bool isa(node_entry *node) { - return node && (node->type() & type_id()); + return node && (node->type() & type_id()); } template static T *dyn_cast(node_entry *node) { - return isa(node) ? reinterpret_cast(node) : nullptr; + return isa(node) ? reinterpret_cast(node) : nullptr; } // Merge b -> a, b will be deleted static void merge_node(node_entry *a, node_entry *b) { - a->_name.swap(b->_name); - a->_file_type = b->_file_type; - a->_parent = b->_parent; + a->_name.swap(b->_name); + a->_file_type = b->_file_type; + a->_parent = b->_parent; - // Merge children if both is dir - if (auto aa = dyn_cast(a); aa) { - if (auto bb = dyn_cast(b); bb) { - aa->children.merge(bb->children); - for (auto &pair : aa->children) - pair.second->_parent = aa; - } - } - delete b; + // Merge children if both is dir + if (auto aa = dyn_cast(a); aa) { + if (auto bb = dyn_cast(b); bb) { + aa->children.merge(bb->children); + for (auto &pair : aa->children) + pair.second->_parent = aa; + } + } + delete b; } string node_entry::module_mnt; string node_entry::mirror_dir; const string &node_entry::node_path() { - if (_parent && _node_path.empty()) - _node_path = _parent->node_path() + '/' + _name; - return _node_path; + if (_parent && _node_path.empty()) + _node_path = _parent->node_path() + '/' + _name; + return _node_path; } /************************* @@ -313,135 +313,135 @@ const string &node_entry::node_path() { template dir_node::map_iter dir_node::insert(dir_node::map_iter it, uint8_t type, Func fn, bool allow_same) { - node_entry *node = nullptr; - if (it != children.end()) { - if (it->second->node_type < type) { - // Upgrade existing node only if higher precedence - node = fn(it->second); - if (!node) - return children.end(); - if (it->second) - merge_node(node, it->second); - it = children.erase(it); - // Minor optimization to make insert O(1) by using hint - if (it == children.begin()) - it = children.emplace(node->_name, node).first; - else - it = children.emplace_hint(--it, node->_name, node); - } else { - if (allow_same && it->second->node_type == type) - return it; - return children.end(); - } - } else { - node = fn(node); - if (!node) - return it; - node->_parent = this; - it = children.emplace(node->_name, node).first; - } - return it; + node_entry *node = nullptr; + if (it != children.end()) { + if (it->second->node_type < type) { + // Upgrade existing node only if higher precedence + node = fn(it->second); + if (!node) + return children.end(); + if (it->second) + merge_node(node, it->second); + it = children.erase(it); + // Minor optimization to make insert O(1) by using hint + if (it == children.begin()) + it = children.emplace(node->_name, node).first; + else + it = children.emplace_hint(--it, node->_name, node); + } else { + if (allow_same && it->second->node_type == type) + return it; + return children.end(); + } + } else { + node = fn(node); + if (!node) + return it; + node->_parent = this; + it = children.emplace(node->_name, node).first; + } + return it; } node_entry* dir_node::extract(string_view name) { - auto it = children.find(name); - if (it != children.end()) { - auto ret = it->second; - children.erase(it); - return ret; - } - return nullptr; + auto it = children.find(name); + if (it != children.end()) { + auto ret = it->second; + children.erase(it); + return ret; + } + return nullptr; } skel_node::skel_node(node_entry *node) : dir_node(node, this) { - string mirror = mirror_path(); - if (auto dir = open_dir(mirror.data()); dir) { - set_exist(true); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - // Insert mirror nodes - emplace(entry->d_name, entry); - } - } else { - // It is actually possible that mirror does not exist (nested mount points) - // Set self to non exist so this node will be ignored at mount - set_exist(false); - return; - } + string mirror = mirror_path(); + if (auto dir = open_dir(mirror.data()); dir) { + set_exist(true); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + // Insert mirror nodes + emplace(entry->d_name, entry); + } + } else { + // It is actually possible that mirror does not exist (nested mount points) + // Set self to non exist so this node will be ignored at mount + set_exist(false); + return; + } - for (auto it = children.begin(); it != children.end(); ++it) { - // Need to upgrade all inter_node children to skel_node - if (isa(it->second)) - it = upgrade(it); - } + for (auto it = children.begin(); it != children.end(); ++it) { + // Need to upgrade all inter_node children to skel_node + if (isa(it->second)) + it = upgrade(it); + } } bool node_entry::need_skel_upgrade(node_entry *child) { - /* We need to upgrade to skeleton if: - * - Target does not exist - * - Source or target is a symlink */ - bool upgrade = false; - struct stat st; - if (lstat(child->node_path().data(), &st) != 0) { - upgrade = true; - } else { - child->set_exist(true); - if (child->is_lnk() || S_ISLNK(st.st_mode)) - upgrade = true; - } - return upgrade; + /* We need to upgrade to skeleton if: + * - Target does not exist + * - Source or target is a symlink */ + bool upgrade = false; + struct stat st; + if (lstat(child->node_path().data(), &st) != 0) { + upgrade = true; + } else { + child->set_exist(true); + if (child->is_lnk() || S_ISLNK(st.st_mode)) + upgrade = true; + } + return upgrade; } bool dir_node::prepare() { - bool to_skel = false; - for (auto it = children.begin(); it != children.end();) { - if (need_skel_upgrade(it->second)) { - if (node_type > type_id()) { - // Upgrade will fail, remove the unsupported child node - delete it->second; - it = children.erase(it); - continue; - } - // Tell parent to upgrade self to skel - to_skel = true; - // If child is inter_node, upgrade to module - if (auto nit = upgrade(it); nit != children.end()) { - it = nit; - goto next_node; - } - } - if (auto dn = dyn_cast(it->second); dn && dn->is_dir() && !dn->prepare()) { - // Upgrade child to skeleton - it = upgrade(it); - } + bool to_skel = false; + for (auto it = children.begin(); it != children.end();) { + if (need_skel_upgrade(it->second)) { + if (node_type > type_id()) { + // Upgrade will fail, remove the unsupported child node + delete it->second; + it = children.erase(it); + continue; + } + // Tell parent to upgrade self to skel + to_skel = true; + // If child is inter_node, upgrade to module + if (auto nit = upgrade(it); nit != children.end()) { + it = nit; + goto next_node; + } + } + if (auto dn = dyn_cast(it->second); dn && dn->is_dir() && !dn->prepare()) { + // Upgrade child to skeleton + it = upgrade(it); + } next_node: - ++it; - } - return !to_skel; + ++it; + } + return !to_skel; } bool dir_node::collect_files(const char *module, int dfd) { - auto dir = xopen_dir(xopenat(dfd, _name.data(), O_RDONLY | O_CLOEXEC)); - if (!dir) - return true; + auto dir = xopen_dir(xopenat(dfd, _name.data(), O_RDONLY | O_CLOEXEC)); + if (!dir) + return true; - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (entry->d_name == ".replace"sv) { - // Stop traversing and tell parent to upgrade self to module - return false; - } + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (entry->d_name == ".replace"sv) { + // Stop traversing and tell parent to upgrade self to module + return false; + } - if (entry->d_type == DT_DIR) { - // Need check cause emplace could fail due to previous module dir replace - if (auto dn = emplace_or_get(entry->d_name, entry->d_name, module); - dn && !dn->collect_files(module, dirfd(dir.get()))) { - // Upgrade node to module due to '.replace' - upgrade(dn->name(), module); - } - } else { - emplace(entry->d_name, module, entry); - } - } - return true; + if (entry->d_type == DT_DIR) { + // Need check cause emplace could fail due to previous module dir replace + if (auto dn = emplace_or_get(entry->d_name, entry->d_name, module); + dn && !dn->collect_files(module, dirfd(dir.get()))) { + // Upgrade node to module due to '.replace' + upgrade(dn->name(), module); + } + } else { + emplace(entry->d_name, module, entry); + } + } + return true; } /************************ @@ -449,46 +449,46 @@ bool dir_node::collect_files(const char *module, int dfd) { ************************/ void node_entry::create_and_mount(const string &src) { - const string &dest = node_path(); - if (is_lnk()) { - VLOGD("cp_link", src.data(), dest.data()); - cp_afc(src.data(), dest.data()); - } else { - if (is_dir()) - xmkdir(dest.data(), 0); - else if (is_reg()) - close(xopen(dest.data(), O_RDONLY | O_CREAT | O_CLOEXEC, 0)); - else - return; - bind_mount(src.data(), dest.data()); - } + const string &dest = node_path(); + if (is_lnk()) { + VLOGD("cp_link", src.data(), dest.data()); + cp_afc(src.data(), dest.data()); + } else { + if (is_dir()) + xmkdir(dest.data(), 0); + else if (is_reg()) + close(xopen(dest.data(), O_RDONLY | O_CREAT | O_CLOEXEC, 0)); + else + return; + bind_mount(src.data(), dest.data()); + } } void module_node::mount() { - string src = module_mnt + module + parent()->root()->prefix + node_path(); - if (exist()) - clone_attr(mirror_path().data(), src.data()); - if (isa(parent())) - create_and_mount(src); - else if (is_dir() || is_reg()) - bind_mount(src.data(), node_path().data()); + string src = module_mnt + module + parent()->root()->prefix + node_path(); + if (exist()) + clone_attr(mirror_path().data(), src.data()); + if (isa(parent())) + create_and_mount(src); + else if (is_dir() || is_reg()) + bind_mount(src.data(), node_path().data()); } void skel_node::mount() { - if (!exist()) - return; - string src = mirror_path(); - const string &dest = node_path(); - file_attr a; - getattr(src.data(), &a); - mkdir(dest.data(), 0); - if (!isa(parent())) { - // We don't need another layer of tmpfs if parent is skel - xmount("tmpfs", dest.data(), "tmpfs", 0, nullptr); - VLOGD("mnt_tmp", "tmpfs", dest.data()); - } - setattr(dest.data(), &a); - dir_node::mount(); + if (!exist()) + return; + string src = mirror_path(); + const string &dest = node_path(); + file_attr a; + getattr(src.data(), &a); + mkdir(dest.data(), 0); + if (!isa(parent())) { + // We don't need another layer of tmpfs if parent is skel + xmount("tmpfs", dest.data(), "tmpfs", 0, nullptr); + VLOGD("mnt_tmp", "tmpfs", dest.data()); + } + setattr(dest.data(), &a); + dir_node::mount(); } /**************** @@ -497,210 +497,210 @@ void skel_node::mount() { class magisk_node : public node_entry { public: - explicit magisk_node(const char *name) : node_entry(name, DT_REG, this) {} + explicit magisk_node(const char *name) : node_entry(name, DT_REG, this) {} - void mount() override { - const string &dir_name = parent()->node_path(); - if (name() == "magisk") { - for (int i = 0; applet_names[i]; ++i) { - string dest = dir_name + "/" + applet_names[i]; - VLOGD("create", "./magisk", dest.data()); - xsymlink("./magisk", dest.data()); - } - } else { - for (int i = 0; init_applet[i]; ++i) { - string dest = dir_name + "/" + init_applet[i]; - VLOGD("create", "./magiskinit", dest.data()); - xsymlink("./magiskinit", dest.data()); - } - } - create_and_mount(MAGISKTMP + "/" + name()); - } + void mount() override { + const string &dir_name = parent()->node_path(); + if (name() == "magisk") { + for (int i = 0; applet_names[i]; ++i) { + string dest = dir_name + "/" + applet_names[i]; + VLOGD("create", "./magisk", dest.data()); + xsymlink("./magisk", dest.data()); + } + } else { + for (int i = 0; init_applet[i]; ++i) { + string dest = dir_name + "/" + init_applet[i]; + VLOGD("create", "./magiskinit", dest.data()); + xsymlink("./magiskinit", dest.data()); + } + } + create_and_mount(MAGISKTMP + "/" + name()); + } }; static void inject_magisk_bins(root_node *system) { - auto bin = system->child("bin"); - if (!bin) { - bin = new inter_node("bin", ""); - system->insert(bin); - } + auto bin = system->child("bin"); + if (!bin) { + bin = new inter_node("bin", ""); + system->insert(bin); + } - // Insert binaries - bin->insert(new magisk_node("magisk")); - bin->insert(new magisk_node("magiskinit")); + // Insert binaries + bin->insert(new magisk_node("magisk")); + bin->insert(new magisk_node("magiskinit")); - // Also delete all applets to make sure no modules can override it - for (int i = 0; applet_names[i]; ++i) - delete bin->extract(applet_names[i]); - for (int i = 0; init_applet[i]; ++i) - delete bin->extract(init_applet[i]); + // Also delete all applets to make sure no modules can override it + for (int i = 0; applet_names[i]; ++i) + delete bin->extract(applet_names[i]); + for (int i = 0; init_applet[i]; ++i) + delete bin->extract(init_applet[i]); } void magic_mount() { - node_entry::mirror_dir = MAGISKTMP + "/" MIRRDIR; - node_entry::module_mnt = MAGISKTMP + "/" MODULEMNT "/"; + node_entry::mirror_dir = MAGISKTMP + "/" MIRRDIR; + node_entry::module_mnt = MAGISKTMP + "/" MODULEMNT "/"; - auto root = make_unique(""); - auto system = new root_node("system"); - root->insert(system); + auto root = make_unique(""); + auto system = new root_node("system"); + root->insert(system); - char buf1[4096]; - char buf2[4096]; - LOGI("* Loading modules\n"); - for (const auto &m : module_list) { - auto module = m.data(); - char *b1 = buf1 + sprintf(buf1, MODULEROOT "/%s/", module); + char buf1[4096]; + char buf2[4096]; + LOGI("* Loading modules\n"); + for (const auto &m : module_list) { + auto module = m.data(); + char *b1 = buf1 + sprintf(buf1, MODULEROOT "/%s/", module); - // Read props - strcpy(b1, "system.prop"); - if (access(buf1, F_OK) == 0) { - LOGI("%s: loading [system.prop]\n", module); - load_prop_file(buf1, false); - } + // Read props + strcpy(b1, "system.prop"); + if (access(buf1, F_OK) == 0) { + LOGI("%s: loading [system.prop]\n", module); + load_prop_file(buf1, false); + } - // Copy sepolicy rules - strcpy(b1, "sepolicy.rule"); - char *b2 = buf2 + sprintf(buf2, "%s/" MIRRDIR "/persist", MAGISKTMP.data()); - if (access(buf1, F_OK) == 0 && access(buf2, F_OK) == 0) { - b2 += sprintf(b2, "/magisk/%s", module); - xmkdirs(buf2, 0755); - strcpy(b2, "/sepolicy.rule"); - cp_afc(buf1, buf2); - } + // Copy sepolicy rules + strcpy(b1, "sepolicy.rule"); + char *b2 = buf2 + sprintf(buf2, "%s/" MIRRDIR "/persist", MAGISKTMP.data()); + if (access(buf1, F_OK) == 0 && access(buf2, F_OK) == 0) { + b2 += sprintf(b2, "/magisk/%s", module); + xmkdirs(buf2, 0755); + strcpy(b2, "/sepolicy.rule"); + cp_afc(buf1, buf2); + } - // Check whether skip mounting - strcpy(b1, "skip_mount"); - if (access(buf1, F_OK) == 0) - continue; + // Check whether skip mounting + strcpy(b1, "skip_mount"); + if (access(buf1, F_OK) == 0) + continue; - // Double check whether the system folder exists - strcpy(b1, "system"); - if (access(buf1, F_OK) != 0) - continue; + // Double check whether the system folder exists + strcpy(b1, "system"); + if (access(buf1, F_OK) != 0) + continue; - LOGI("%s: loading mount files\n", module); - b1[-1] = '\0'; - int fd = xopen(buf1, O_RDONLY | O_CLOEXEC); - system->collect_files(module, fd); - close(fd); - } + LOGI("%s: loading mount files\n", module); + b1[-1] = '\0'; + int fd = xopen(buf1, O_RDONLY | O_CLOEXEC); + system->collect_files(module, fd); + close(fd); + } - if (MAGISKTMP != "/sbin") { - // Need to inject our binaries into /system/bin - inject_magisk_bins(system); - } + if (MAGISKTMP != "/sbin") { + // Need to inject our binaries into /system/bin + inject_magisk_bins(system); + } - if (system->is_empty()) - return; + if (system->is_empty()) + return; - // Handle special read-only partitions - for (const char *part : { "/vendor", "/product", "/system_ext" }) { - struct stat st; - if (lstat(part, &st) == 0 && S_ISDIR(st.st_mode)) { - if (auto old = system->extract(part + 1); old) { - auto new_node = new root_node(old); - root->insert(new_node); - } - } - } + // Handle special read-only partitions + for (const char *part : { "/vendor", "/product", "/system_ext" }) { + struct stat st; + if (lstat(part, &st) == 0 && S_ISDIR(st.st_mode)) { + if (auto old = system->extract(part + 1); old) { + auto new_node = new root_node(old); + root->insert(new_node); + } + } + } - root->prepare(); - root->mount(); + root->prepare(); + root->mount(); } static void prepare_modules() { - // Upgrade modules - if (auto dir = open_dir(MODULEUPGRADE); dir) { - int ufd = dirfd(dir.get()); - int mfd = xopen(MODULEROOT, O_RDONLY | O_CLOEXEC); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (entry->d_type == DT_DIR) { - // Cleanup old module if exists - if (faccessat(mfd, entry->d_name, F_OK, 0) == 0) { - int modfd = xopenat(mfd, entry->d_name, O_RDONLY | O_CLOEXEC); - if (faccessat(modfd, "disable", F_OK, 0) == 0) { - auto disable = entry->d_name + "/disable"s; - close(xopenat(ufd, disable.data(), O_RDONLY | O_CREAT | O_CLOEXEC, 0)); - } - frm_rf(modfd); - unlinkat(mfd, entry->d_name, AT_REMOVEDIR); - } - LOGI("Upgrade / New module: %s\n", entry->d_name); - renameat(ufd, entry->d_name, mfd, entry->d_name); - } - } - close(mfd); - rm_rf(MODULEUPGRADE); - } + // Upgrade modules + if (auto dir = open_dir(MODULEUPGRADE); dir) { + int ufd = dirfd(dir.get()); + int mfd = xopen(MODULEROOT, O_RDONLY | O_CLOEXEC); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (entry->d_type == DT_DIR) { + // Cleanup old module if exists + if (faccessat(mfd, entry->d_name, F_OK, 0) == 0) { + int modfd = xopenat(mfd, entry->d_name, O_RDONLY | O_CLOEXEC); + if (faccessat(modfd, "disable", F_OK, 0) == 0) { + auto disable = entry->d_name + "/disable"s; + close(xopenat(ufd, disable.data(), O_RDONLY | O_CREAT | O_CLOEXEC, 0)); + } + frm_rf(modfd); + unlinkat(mfd, entry->d_name, AT_REMOVEDIR); + } + LOGI("Upgrade / New module: %s\n", entry->d_name); + renameat(ufd, entry->d_name, mfd, entry->d_name); + } + } + close(mfd); + rm_rf(MODULEUPGRADE); + } - // Setup module mount (workaround nosuid selabel issue) - auto src = MAGISKTMP + "/" MIRRDIR MODULEROOT; - auto dest = MAGISKTMP + "/" MODULEMNT; - xmkdir(dest.data(), 0755); - bind_mount(src.data(), dest.data()); + // Setup module mount (workaround nosuid selabel issue) + auto src = MAGISKTMP + "/" MIRRDIR MODULEROOT; + auto dest = MAGISKTMP + "/" MODULEMNT; + xmkdir(dest.data(), 0755); + bind_mount(src.data(), dest.data()); - restorecon(); - chmod(SECURE_DIR, 0700); + restorecon(); + chmod(SECURE_DIR, 0700); } template static void foreach_module(Func fn) { - auto dir = open_dir(MODULEROOT); - if (!dir) - return; + auto dir = open_dir(MODULEROOT); + if (!dir) + return; - int dfd = dirfd(dir.get()); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (entry->d_type == DT_DIR && entry->d_name != ".core"sv) { - int modfd = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC); - fn(dfd, entry, modfd); - close(modfd); - } - } + int dfd = dirfd(dir.get()); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (entry->d_type == DT_DIR && entry->d_name != ".core"sv) { + int modfd = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC); + fn(dfd, entry, modfd); + close(modfd); + } + } } static void collect_modules() { - foreach_module([](int dfd, dirent *entry, int modfd) { - if (faccessat(modfd, "remove", F_OK, 0) == 0) { - LOGI("%s: remove\n", entry->d_name); - auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh"; - if (access(uninstaller.data(), F_OK) == 0) - exec_script(uninstaller.data()); - frm_rf(xdup(modfd)); - unlinkat(dfd, entry->d_name, AT_REMOVEDIR); - return; - } - unlinkat(modfd, "update", 0); - if (faccessat(modfd, "disable", F_OK, 0) != 0) - module_list.emplace_back(entry->d_name); - }); + foreach_module([](int dfd, dirent *entry, int modfd) { + if (faccessat(modfd, "remove", F_OK, 0) == 0) { + LOGI("%s: remove\n", entry->d_name); + auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh"; + if (access(uninstaller.data(), F_OK) == 0) + exec_script(uninstaller.data()); + frm_rf(xdup(modfd)); + unlinkat(dfd, entry->d_name, AT_REMOVEDIR); + return; + } + unlinkat(modfd, "update", 0); + if (faccessat(modfd, "disable", F_OK, 0) != 0) + module_list.emplace_back(entry->d_name); + }); } void handle_modules() { - prepare_modules(); - collect_modules(); - exec_module_scripts("post-fs-data"); + prepare_modules(); + collect_modules(); + exec_module_scripts("post-fs-data"); - // Recollect modules (module scripts could remove itself) - module_list.clear(); - collect_modules(); + // Recollect modules (module scripts could remove itself) + module_list.clear(); + collect_modules(); } void disable_modules() { - foreach_module([](int, auto, int modfd) { - close(xopenat(modfd, "disable", O_RDONLY | O_CREAT | O_CLOEXEC, 0)); - }); + foreach_module([](int, auto, int modfd) { + close(xopenat(modfd, "disable", O_RDONLY | O_CREAT | O_CLOEXEC, 0)); + }); } void remove_modules() { - foreach_module([](int, dirent *entry, int) { - auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh"; - if (access(uninstaller.data(), F_OK) == 0) - exec_script(uninstaller.data()); - }); - rm_rf(MODULEROOT); + foreach_module([](int, dirent *entry, int) { + auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh"; + if (access(uninstaller.data(), F_OK) == 0) + exec_script(uninstaller.data()); + }); + rm_rf(MODULEROOT); } void exec_module_scripts(const char *stage) { - exec_module_scripts(stage, module_list); + exec_module_scripts(stage, module_list); } diff --git a/native/jni/core/restorecon.cpp b/native/jni/core/restorecon.cpp index e2886528c..e2efabdc3 100644 --- a/native/jni/core/restorecon.cpp +++ b/native/jni/core/restorecon.cpp @@ -15,89 +15,89 @@ using namespace std; #define EXEC_CON "u:object_r:" SEPOL_EXEC_TYPE ":s0" static void restore_syscon(int dirfd) { - struct dirent *entry; - DIR *dir; - char *con; + struct dirent *entry; + DIR *dir; + char *con; - fgetfilecon(dirfd, &con); - if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) - fsetfilecon(dirfd, SYSTEM_CON); - freecon(con); + fgetfilecon(dirfd, &con); + if (strlen(con) == 0 || strcmp(con, UNLABEL_CON) == 0) + fsetfilecon(dirfd, SYSTEM_CON); + freecon(con); - dir = xfdopendir(dirfd); - while ((entry = xreaddir(dir))) { - int fd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); - if (entry->d_type == DT_DIR) { - restore_syscon(fd); - } else if (entry->d_type == DT_REG) { - fgetfilecon(fd, &con); - if (con[0] == '\0' || strcmp(con, UNLABEL_CON) == 0) - fsetfilecon(fd, SYSTEM_CON); - freecon(con); - } else if (entry->d_type == DT_LNK) { - getfilecon_at(dirfd, entry->d_name, &con); - if (con[0] == '\0' || strcmp(con, UNLABEL_CON) == 0) - setfilecon_at(dirfd, entry->d_name, con); - freecon(con); - } - close(fd); - } + dir = xfdopendir(dirfd); + while ((entry = xreaddir(dir))) { + int fd = openat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); + if (entry->d_type == DT_DIR) { + restore_syscon(fd); + } else if (entry->d_type == DT_REG) { + fgetfilecon(fd, &con); + if (con[0] == '\0' || strcmp(con, UNLABEL_CON) == 0) + fsetfilecon(fd, SYSTEM_CON); + freecon(con); + } else if (entry->d_type == DT_LNK) { + getfilecon_at(dirfd, entry->d_name, &con); + if (con[0] == '\0' || strcmp(con, UNLABEL_CON) == 0) + setfilecon_at(dirfd, entry->d_name, con); + freecon(con); + } + close(fd); + } } static void restore_magiskcon(int dirfd) { - struct dirent *entry; - DIR *dir; + struct dirent *entry; + DIR *dir; - fsetfilecon(dirfd, MAGISK_CON); - fchown(dirfd, 0, 0); + fsetfilecon(dirfd, MAGISK_CON); + fchown(dirfd, 0, 0); - dir = xfdopendir(dirfd); - while ((entry = xreaddir(dir))) { - int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); - if (entry->d_type == DT_DIR) { - restore_magiskcon(fd); - } else if (entry->d_type) { - fsetfilecon(fd, MAGISK_CON); - fchown(fd, 0, 0); - } - close(fd); - } + dir = xfdopendir(dirfd); + while ((entry = xreaddir(dir))) { + int fd = xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC); + if (entry->d_type == DT_DIR) { + restore_magiskcon(fd); + } else if (entry->d_type) { + fsetfilecon(fd, MAGISK_CON); + fchown(fd, 0, 0); + } + close(fd); + } } void restorecon() { - int fd = xopen(SELINUX_CONTEXT, O_WRONLY | O_CLOEXEC); - if (write(fd, ADB_CON, sizeof(ADB_CON)) >= 0) - lsetfilecon(SECURE_DIR, ADB_CON); - close(fd); - lsetfilecon(MODULEROOT, SYSTEM_CON); - fd = xopen(MODULEROOT, O_RDONLY | O_CLOEXEC); - restore_syscon(fd); - close(fd); - fd = xopen(DATABIN, O_RDONLY | O_CLOEXEC); - restore_magiskcon(fd); - close(fd); + int fd = xopen(SELINUX_CONTEXT, O_WRONLY | O_CLOEXEC); + if (write(fd, ADB_CON, sizeof(ADB_CON)) >= 0) + lsetfilecon(SECURE_DIR, ADB_CON); + close(fd); + lsetfilecon(MODULEROOT, SYSTEM_CON); + fd = xopen(MODULEROOT, O_RDONLY | O_CLOEXEC); + restore_syscon(fd); + close(fd); + fd = xopen(DATABIN, O_RDONLY | O_CLOEXEC); + restore_magiskcon(fd); + close(fd); } void restore_tmpcon() { - if (MAGISKTMP == "/system/bin") { - // Running with emulator.sh - if (SDK_INT >= 26) - lsetfilecon("/system/bin/magisk", EXEC_CON); - return; - } + if (MAGISKTMP == "/system/bin") { + // Running with emulator.sh + if (SDK_INT >= 26) + lsetfilecon("/system/bin/magisk", EXEC_CON); + return; + } - if (MAGISKTMP == "/sbin") - setfilecon(MAGISKTMP.data(), ROOT_CON); - else - chmod(MAGISKTMP.data(), 0700); + if (MAGISKTMP == "/sbin") + setfilecon(MAGISKTMP.data(), ROOT_CON); + else + chmod(MAGISKTMP.data(), 0700); - auto dir = xopen_dir(MAGISKTMP.data()); - int dfd = dirfd(dir.get()); + auto dir = xopen_dir(MAGISKTMP.data()); + int dfd = dirfd(dir.get()); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (SDK_INT >= 26 && entry->d_name == "magisk"sv) - setfilecon_at(dfd, entry->d_name, EXEC_CON); - else - setfilecon_at(dfd, entry->d_name, SYSTEM_CON); - } + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (SDK_INT >= 26 && entry->d_name == "magisk"sv) + setfilecon_at(dfd, entry->d_name, EXEC_CON); + else + setfilecon_at(dfd, entry->d_name, SYSTEM_CON); + } } diff --git a/native/jni/core/scripting.cpp b/native/jni/core/scripting.cpp index ebf25fdf5..3a6536315 100644 --- a/native/jni/core/scripting.cpp +++ b/native/jni/core/scripting.cpp @@ -11,139 +11,139 @@ using namespace std; #define BBEXEC_CMD bbpath(), "sh" static const char *bbpath() { - static string path; - if (path.empty()) - path = MAGISKTMP + "/" BBPATH "/busybox"; - return path.data(); + static string path; + if (path.empty()) + path = MAGISKTMP + "/" BBPATH "/busybox"; + return path.data(); } static void set_script_env() { - setenv("ASH_STANDALONE", "1", 1); - char new_path[4096]; - sprintf(new_path, "%s:%s", getenv("PATH"), MAGISKTMP.data()); - setenv("PATH", new_path, 1); + setenv("ASH_STANDALONE", "1", 1); + char new_path[4096]; + sprintf(new_path, "%s:%s", getenv("PATH"), MAGISKTMP.data()); + setenv("PATH", new_path, 1); }; void exec_script(const char *script) { - exec_t exec { - .pre_exec = set_script_env, - .fork = fork_no_orphan - }; - exec_command_sync(exec, BBEXEC_CMD, script); + exec_t exec { + .pre_exec = set_script_env, + .fork = fork_no_orphan + }; + exec_command_sync(exec, BBEXEC_CMD, script); } static timespec pfs_timeout; #define PFS_SETUP() \ if (pfs) { \ - if (int pid = xfork()) { \ - if (pid < 0) \ - return; \ - /* In parent process, simply wait for child to finish */ \ - waitpid(pid, nullptr, 0); \ - return; \ - } \ - timer_pid = xfork(); \ - if (timer_pid == 0) { \ - /* In timer process, count down */ \ - clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &pfs_timeout, nullptr); \ - exit(0); \ - } \ + if (int pid = xfork()) { \ + if (pid < 0) \ + return; \ + /* In parent process, simply wait for child to finish */ \ + waitpid(pid, nullptr, 0); \ + return; \ + } \ + timer_pid = xfork(); \ + if (timer_pid == 0) { \ + /* In timer process, count down */ \ + clock_nanosleep(CLOCK_MONOTONIC, TIMER_ABSTIME, &pfs_timeout, nullptr); \ + exit(0); \ + } \ } #define PFS_WAIT() \ if (pfs) { \ - /* If we ran out of time, don't block */ \ - if (timer_pid < 0) \ - continue; \ - if (int pid = waitpid(-1, nullptr, 0); pid == timer_pid) { \ - LOGW("* post-fs-data scripts blocking phase timeout\n"); \ - timer_pid = -1; \ - } \ + /* If we ran out of time, don't block */ \ + if (timer_pid < 0) \ + continue; \ + if (int pid = waitpid(-1, nullptr, 0); pid == timer_pid) { \ + LOGW("* post-fs-data scripts blocking phase timeout\n"); \ + timer_pid = -1; \ + } \ } #define PFS_DONE() \ if (pfs) { \ - if (timer_pid > 0) \ - kill(timer_pid, SIGKILL); \ - exit(0); \ + if (timer_pid > 0) \ + kill(timer_pid, SIGKILL); \ + exit(0); \ } void exec_common_scripts(const char *stage) { - LOGI("* Running %s.d scripts\n", stage); - char path[4096]; - char *name = path + sprintf(path, SECURE_DIR "/%s.d", stage); - auto dir = xopen_dir(path); - if (!dir) return; + LOGI("* Running %s.d scripts\n", stage); + char path[4096]; + char *name = path + sprintf(path, SECURE_DIR "/%s.d", stage); + auto dir = xopen_dir(path); + if (!dir) return; - bool pfs = stage == "post-fs-data"sv; - int timer_pid = -1; - if (pfs) { - // Setup timer - clock_gettime(CLOCK_MONOTONIC, &pfs_timeout); - pfs_timeout.tv_sec += POST_FS_DATA_SCRIPT_MAX_TIME; - } - PFS_SETUP() + bool pfs = stage == "post-fs-data"sv; + int timer_pid = -1; + if (pfs) { + // Setup timer + clock_gettime(CLOCK_MONOTONIC, &pfs_timeout); + pfs_timeout.tv_sec += POST_FS_DATA_SCRIPT_MAX_TIME; + } + PFS_SETUP() - *(name++) = '/'; - int dfd = dirfd(dir.get()); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (entry->d_type == DT_REG) { - if (faccessat(dfd, entry->d_name, X_OK, 0) != 0) - continue; - LOGI("%s.d: exec [%s]\n", stage, entry->d_name); - strcpy(name, entry->d_name); - exec_t exec { - .pre_exec = set_script_env, - .fork = pfs ? xfork : fork_dont_care - }; - exec_command(exec, BBEXEC_CMD, path); - PFS_WAIT() - } - } + *(name++) = '/'; + int dfd = dirfd(dir.get()); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (entry->d_type == DT_REG) { + if (faccessat(dfd, entry->d_name, X_OK, 0) != 0) + continue; + LOGI("%s.d: exec [%s]\n", stage, entry->d_name); + strcpy(name, entry->d_name); + exec_t exec { + .pre_exec = set_script_env, + .fork = pfs ? xfork : fork_dont_care + }; + exec_command(exec, BBEXEC_CMD, path); + PFS_WAIT() + } + } - PFS_DONE() + PFS_DONE() } // Return if a > b static bool timespec_larger(timespec *a, timespec *b) { - if (a->tv_sec != b->tv_sec) - return a->tv_sec > b->tv_sec; - return a->tv_nsec > b->tv_nsec; + if (a->tv_sec != b->tv_sec) + return a->tv_sec > b->tv_sec; + return a->tv_nsec > b->tv_nsec; } void exec_module_scripts(const char *stage, const vector &module_list) { - LOGI("* Running module %s scripts\n", stage); - if (module_list.empty()) - return; + LOGI("* Running module %s scripts\n", stage); + if (module_list.empty()) + return; - bool pfs = stage == "post-fs-data"sv; - if (pfs) { - timespec now{}; - clock_gettime(CLOCK_MONOTONIC, &now); - // If we had already timed out, treat it as service mode - if (timespec_larger(&now, &pfs_timeout)) - pfs = false; - } - int timer_pid = -1; - PFS_SETUP() + bool pfs = stage == "post-fs-data"sv; + if (pfs) { + timespec now{}; + clock_gettime(CLOCK_MONOTONIC, &now); + // If we had already timed out, treat it as service mode + if (timespec_larger(&now, &pfs_timeout)) + pfs = false; + } + int timer_pid = -1; + PFS_SETUP() - char path[4096]; - for (auto &m : module_list) { - const char* module = m.data(); - sprintf(path, MODULEROOT "/%s/%s.sh", module, stage); - if (access(path, F_OK) == -1) - continue; - LOGI("%s: exec [%s.sh]\n", module, stage); - exec_t exec { - .pre_exec = set_script_env, - .fork = pfs ? xfork : fork_dont_care - }; - exec_command(exec, BBEXEC_CMD, path); - PFS_WAIT() - } + char path[4096]; + for (auto &m : module_list) { + const char* module = m.data(); + sprintf(path, MODULEROOT "/%s/%s.sh", module, stage); + if (access(path, F_OK) == -1) + continue; + LOGI("%s: exec [%s.sh]\n", module, stage); + exec_t exec { + .pre_exec = set_script_env, + .fork = pfs ? xfork : fork_dont_care + }; + exec_command(exec, BBEXEC_CMD, path); + PFS_WAIT() + } - PFS_DONE() + PFS_DONE() } constexpr char install_script[] = R"EOF( @@ -154,23 +154,23 @@ rm -f $APK )EOF"; void install_apk(const char *apk) { - setfilecon(apk, "u:object_r:" SEPOL_FILE_TYPE ":s0"); - exec_t exec { - .fork = fork_no_orphan - }; - char cmds[sizeof(install_script) + 4096]; - sprintf(cmds, install_script, apk); - exec_command_sync(exec, "/system/bin/sh", "-c", cmds); + setfilecon(apk, "u:object_r:" SEPOL_FILE_TYPE ":s0"); + exec_t exec { + .fork = fork_no_orphan + }; + char cmds[sizeof(install_script) + 4096]; + sprintf(cmds, install_script, apk); + exec_command_sync(exec, "/system/bin/sh", "-c", cmds); } [[noreturn]] __printflike(2, 3) static void abort(FILE *fp, const char *fmt, ...) { - va_list valist; - va_start(valist, fmt); - vfprintf(fp, fmt, valist); - fprintf(fp, "\n\n"); - va_end(valist); - exit(1); + va_list valist; + va_start(valist, fmt); + vfprintf(fp, fmt, valist); + fprintf(fp, "\n\n"); + va_end(valist); + exit(1); } constexpr char install_module_script[] = R"EOF( @@ -181,24 +181,24 @@ exit 0' )EOF"; void install_module(const char *file) { - if (getuid() != 0) - abort(stderr, "Run this command with root"); - if (access(DATABIN, F_OK) || - access(DATABIN "/busybox", X_OK) || - access(DATABIN "/util_functions.sh", F_OK)) - abort(stderr, "Incomplete Magisk install"); - if (access(file, F_OK)) - abort(stderr, "'%s' does not exist", file); + if (getuid() != 0) + abort(stderr, "Run this command with root"); + if (access(DATABIN, F_OK) || + access(DATABIN "/busybox", X_OK) || + access(DATABIN "/util_functions.sh", F_OK)) + abort(stderr, "Incomplete Magisk install"); + if (access(file, F_OK)) + abort(stderr, "'%s' does not exist", file); - setenv("OUTFD", "1", 1); - setenv("ZIPFILE", file, 1); - setenv("ASH_STANDALONE", "1", 1); + setenv("OUTFD", "1", 1); + setenv("ZIPFILE", file, 1); + setenv("ASH_STANDALONE", "1", 1); - int fd = xopen("/dev/null", O_RDONLY); - xdup2(fd, STDERR_FILENO); - close(fd); + int fd = xopen("/dev/null", O_RDONLY); + xdup2(fd, STDERR_FILENO); + close(fd); - const char *argv[] = { "/system/bin/sh", "-c", install_module_script, nullptr }; - execve(argv[0], (char **) argv, environ); - abort(stdout, "Failed to execute BusyBox shell"); + const char *argv[] = { "/system/bin/sh", "-c", install_module_script, nullptr }; + execve(argv[0], (char **) argv, environ); + abort(stdout, "Failed to execute BusyBox shell"); } diff --git a/native/jni/core/socket.cpp b/native/jni/core/socket.cpp index 06faf539e..529066204 100644 --- a/native/jni/core/socket.cpp +++ b/native/jni/core/socket.cpp @@ -7,30 +7,30 @@ #include static size_t socket_len(sockaddr_un *sun) { - if (sun->sun_path[0]) - return sizeof(sa_family_t) + strlen(sun->sun_path) + 1; - else - return sizeof(sa_family_t) + strlen(sun->sun_path + 1) + 1; + if (sun->sun_path[0]) + return sizeof(sa_family_t) + strlen(sun->sun_path) + 1; + else + return sizeof(sa_family_t) + strlen(sun->sun_path + 1) + 1; } socklen_t setup_sockaddr(sockaddr_un *sun, const char *name) { - memset(sun, 0, sizeof(*sun)); - sun->sun_family = AF_UNIX; - strcpy(sun->sun_path + 1, name); - return socket_len(sun); + memset(sun, 0, sizeof(*sun)); + sun->sun_family = AF_UNIX; + strcpy(sun->sun_path + 1, name); + return socket_len(sun); } int socket_accept(int sockfd, int timeout) { - struct pollfd pfd = { - .fd = sockfd, - .events = POLL_IN - }; - return xpoll(&pfd, 1, timeout * 1000) <= 0 ? -1 : xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC); + struct pollfd pfd = { + .fd = sockfd, + .events = POLL_IN + }; + return xpoll(&pfd, 1, timeout * 1000) <= 0 ? -1 : xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC); } void get_client_cred(int fd, struct ucred *cred) { - socklen_t ucred_length = sizeof(*cred); - getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length); + socklen_t ucred_length = sizeof(*cred); + getsockopt(fd, SOL_SOCKET, SO_PEERCRED, cred, &ucred_length); } /* @@ -43,50 +43,50 @@ void get_client_cred(int fd, struct ucred *cred) { * On error the function terminates by calling exit(-1) */ int recv_fd(int sockfd) { - // Need to receive data from the message, otherwise don't care about it. - char iovbuf; - struct cmsghdr *cmsg; + // Need to receive data from the message, otherwise don't care about it. + char iovbuf; + struct cmsghdr *cmsg; - struct iovec iov = { - .iov_base = &iovbuf, - .iov_len = 1, - }; + struct iovec iov = { + .iov_base = &iovbuf, + .iov_len = 1, + }; - char cmsgbuf[CMSG_SPACE(sizeof(int))]; + char cmsgbuf[CMSG_SPACE(sizeof(int))]; - struct msghdr msg = { - .msg_iov = &iov, - .msg_iovlen = 1, - .msg_control = cmsgbuf, - .msg_controllen = sizeof(cmsgbuf), - }; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + .msg_control = cmsgbuf, + .msg_controllen = sizeof(cmsgbuf), + }; - xrecvmsg(sockfd, &msg, MSG_WAITALL); + xrecvmsg(sockfd, &msg, MSG_WAITALL); - // Was a control message actually sent? - switch (msg.msg_controllen) { - case 0: - // No, so the file descriptor was closed and won't be used. - return -1; - case sizeof(cmsgbuf): - // Yes, grab the file descriptor from it. - break; - default: - goto error; - } + // Was a control message actually sent? + switch (msg.msg_controllen) { + case 0: + // No, so the file descriptor was closed and won't be used. + return -1; + case sizeof(cmsgbuf): + // Yes, grab the file descriptor from it. + break; + default: + goto error; + } - cmsg = CMSG_FIRSTHDR(&msg); + cmsg = CMSG_FIRSTHDR(&msg); - if (cmsg == nullptr || - cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || - cmsg->cmsg_level != SOL_SOCKET || - cmsg->cmsg_type != SCM_RIGHTS) { + if (cmsg == nullptr || + cmsg->cmsg_len != CMSG_LEN(sizeof(int)) || + cmsg->cmsg_level != SOL_SOCKET || + cmsg->cmsg_type != SCM_RIGHTS) { error: - LOGE("unable to read fd\n"); - exit(-1); - } + LOGE("unable to read fd\n"); + exit(-1); + } - return *(int *)CMSG_DATA(cmsg); + return *(int *)CMSG_DATA(cmsg); } /* @@ -99,106 +99,106 @@ error: * but no control message with the FD is sent. */ void send_fd(int sockfd, int fd) { - // Need to send some data in the message, this will do. - char junk[] = { '\0' }; - struct iovec iov = { - .iov_base = junk, - .iov_len = 1, - }; + // Need to send some data in the message, this will do. + char junk[] = { '\0' }; + struct iovec iov = { + .iov_base = junk, + .iov_len = 1, + }; - struct msghdr msg = { - .msg_iov = &iov, - .msg_iovlen = 1, - }; + struct msghdr msg = { + .msg_iov = &iov, + .msg_iovlen = 1, + }; - char cmsgbuf[CMSG_SPACE(sizeof(int))]; + char cmsgbuf[CMSG_SPACE(sizeof(int))]; - if (fd != -1) { - // Is the file descriptor actually open? - if (fcntl(fd, F_GETFD) == -1) { - if (errno != EBADF) { - PLOGE("unable to send fd"); - } - // It's closed, don't send a control message or sendmsg will EBADF. - } else { - // It's open, send the file descriptor in a control message. - msg.msg_control = cmsgbuf; - msg.msg_controllen = sizeof(cmsgbuf); + if (fd != -1) { + // Is the file descriptor actually open? + if (fcntl(fd, F_GETFD) == -1) { + if (errno != EBADF) { + PLOGE("unable to send fd"); + } + // It's closed, don't send a control message or sendmsg will EBADF. + } else { + // It's open, send the file descriptor in a control message. + msg.msg_control = cmsgbuf; + msg.msg_controllen = sizeof(cmsgbuf); - struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); + struct cmsghdr *cmsg = CMSG_FIRSTHDR(&msg); - cmsg->cmsg_len = CMSG_LEN(sizeof(int)); - cmsg->cmsg_level = SOL_SOCKET; - cmsg->cmsg_type = SCM_RIGHTS; + cmsg->cmsg_len = CMSG_LEN(sizeof(int)); + cmsg->cmsg_level = SOL_SOCKET; + cmsg->cmsg_type = SCM_RIGHTS; - *(int *)CMSG_DATA(cmsg) = fd; - } - } + *(int *)CMSG_DATA(cmsg) = fd; + } + } - xsendmsg(sockfd, &msg, 0); + xsendmsg(sockfd, &msg, 0); } int read_int(int fd) { - int val; - if (xxread(fd, &val, sizeof(val)) != sizeof(val)) - return -1; - return val; + int val; + if (xxread(fd, &val, sizeof(val)) != sizeof(val)) + return -1; + return val; } int read_int_be(int fd) { - uint32_t val; - if (xxread(fd, &val, sizeof(val)) != sizeof(val)) - return -1; - return ntohl(val); + uint32_t val; + if (xxread(fd, &val, sizeof(val)) != sizeof(val)) + return -1; + return ntohl(val); } void write_int(int fd, int val) { - if (fd < 0) return; - xwrite(fd, &val, sizeof(val)); + if (fd < 0) return; + xwrite(fd, &val, sizeof(val)); } void write_int_be(int fd, int val) { - uint32_t nl = htonl(val); - xwrite(fd, &nl, sizeof(nl)); + uint32_t nl = htonl(val); + xwrite(fd, &nl, sizeof(nl)); } static char *rd_str(int fd, int len) { - char *val = (char *) xmalloc(sizeof(char) * (len + 1)); - xxread(fd, val, len); - val[len] = '\0'; - return val; + char *val = (char *) xmalloc(sizeof(char) * (len + 1)); + xxread(fd, val, len); + val[len] = '\0'; + return val; } char* read_string(int fd) { - int len = read_int(fd); - return rd_str(fd, len); + int len = read_int(fd); + return rd_str(fd, len); } char* read_string_be(int fd) { - int len = read_int_be(fd); - return rd_str(fd, len); + int len = read_int_be(fd); + return rd_str(fd, len); } void write_string(int fd, const char *val) { - if (fd < 0) return; - int len = strlen(val); - write_int(fd, len); - xwrite(fd, val, len); + if (fd < 0) return; + int len = strlen(val); + write_int(fd, len); + xwrite(fd, val, len); } void write_string_be(int fd, const char *val) { - int len = strlen(val); - write_int_be(fd, len); - xwrite(fd, val, len); + int len = strlen(val); + write_int_be(fd, len); + xwrite(fd, val, len); } void write_key_value(int fd, const char *key, const char *val) { - write_string_be(fd, key); - write_string_be(fd, val); + write_string_be(fd, key); + write_string_be(fd, val); } void write_key_token(int fd, const char *key, int tok) { - char val[16]; - sprintf(val, "%d", tok); - write_key_value(fd, key, val); + char val[16]; + sprintf(val, "%d", tok); + write_key_value(fd, key, val); } diff --git a/native/jni/external/Android.mk b/native/jni/external/Android.mk index 026f51821..b9db72b79 100644 --- a/native/jni/external/Android.mk +++ b/native/jni/external/Android.mk @@ -6,9 +6,9 @@ LOCAL_MODULE:= libxz LOCAL_C_INCLUDES := $(LOCAL_PATH)/xz-embedded LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_SRC_FILES := \ - xz-embedded/xz_crc32.c \ - xz-embedded/xz_dec_lzma2.c \ - xz-embedded/xz_dec_stream.c + xz-embedded/xz_crc32.c \ + xz-embedded/xz_dec_lzma2.c \ + xz-embedded/xz_dec_stream.c include $(BUILD_STATIC_LIBRARY) # libnanopb.a @@ -17,9 +17,9 @@ LOCAL_MODULE:= libnanopb LOCAL_C_INCLUDES := $(LOCAL_PATH)/nanopb LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_SRC_FILES := \ - nanopb/pb_common.c \ - nanopb/pb_decode.c \ - nanopb/pb_encode.c + nanopb/pb_common.c \ + nanopb/pb_decode.c \ + nanopb/pb_encode.c include $(BUILD_STATIC_LIBRARY) # libfdt.a @@ -28,15 +28,15 @@ LOCAL_MODULE:= libfdt LOCAL_C_INCLUDES := $(LOCAL_PATH)/dtc/libfdt LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_SRC_FILES := \ - dtc/libfdt/fdt.c \ - dtc/libfdt/fdt_addresses.c \ - dtc/libfdt/fdt_empty_tree.c \ - dtc/libfdt/fdt_overlay.c \ - dtc/libfdt/fdt_ro.c \ - dtc/libfdt/fdt_rw.c \ - dtc/libfdt/fdt_strerror.c \ - dtc/libfdt/fdt_sw.c \ - dtc/libfdt/fdt_wip.c + dtc/libfdt/fdt.c \ + dtc/libfdt/fdt_addresses.c \ + dtc/libfdt/fdt_empty_tree.c \ + dtc/libfdt/fdt_overlay.c \ + dtc/libfdt/fdt_ro.c \ + dtc/libfdt/fdt_rw.c \ + dtc/libfdt/fdt_strerror.c \ + dtc/libfdt/fdt_sw.c \ + dtc/libfdt/fdt_wip.c include $(BUILD_STATIC_LIBRARY) # liblz4.a @@ -45,10 +45,10 @@ LOCAL_MODULE := liblz4 LOCAL_C_INCLUDES := $(LOCAL_PATH)/lz4/lib LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_SRC_FILES := \ - lz4/lib/lz4.c \ - lz4/lib/lz4frame.c \ - lz4/lib/lz4hc.c \ - lz4/lib/xxhash.c + lz4/lib/lz4.c \ + lz4/lib/lz4frame.c \ + lz4/lib/lz4hc.c \ + lz4/lib/xxhash.c include $(BUILD_STATIC_LIBRARY) # libbz2.a @@ -57,112 +57,112 @@ LOCAL_MODULE := libbz2 LOCAL_C_INCLUDES := $(LOCAL_PATH)/bzip2 LOCAL_EXPORT_C_INCLUDES := $(LOCAL_C_INCLUDES) LOCAL_SRC_FILES := \ - bzip2/blocksort.c \ - bzip2/huffman.c \ - bzip2/crctable.c \ - bzip2/randtable.c \ - bzip2/compress.c \ - bzip2/decompress.c \ - bzip2/bzlib.c + bzip2/blocksort.c \ + bzip2/huffman.c \ + bzip2/crctable.c \ + bzip2/randtable.c \ + bzip2/compress.c \ + bzip2/decompress.c \ + bzip2/bzlib.c include $(BUILD_STATIC_LIBRARY) # liblzma.a include $(CLEAR_VARS) LOCAL_MODULE := liblzma LOCAL_C_INCLUDES := \ - $(LOCAL_PATH)/xz_config \ - $(LOCAL_PATH)/xz/src/common \ - $(LOCAL_PATH)/xz/src/liblzma/api \ - $(LOCAL_PATH)/xz/src/liblzma/check \ - $(LOCAL_PATH)/xz/src/liblzma/common \ - $(LOCAL_PATH)/xz/src/liblzma/delta \ - $(LOCAL_PATH)/xz/src/liblzma/lz \ - $(LOCAL_PATH)/xz/src/liblzma/lzma \ - $(LOCAL_PATH)/xz/src/liblzma/rangecoder \ - $(LOCAL_PATH)/xz/src/liblzma/simple \ - $(LOCAL_PATH)/xz/src/liblzma + $(LOCAL_PATH)/xz_config \ + $(LOCAL_PATH)/xz/src/common \ + $(LOCAL_PATH)/xz/src/liblzma/api \ + $(LOCAL_PATH)/xz/src/liblzma/check \ + $(LOCAL_PATH)/xz/src/liblzma/common \ + $(LOCAL_PATH)/xz/src/liblzma/delta \ + $(LOCAL_PATH)/xz/src/liblzma/lz \ + $(LOCAL_PATH)/xz/src/liblzma/lzma \ + $(LOCAL_PATH)/xz/src/liblzma/rangecoder \ + $(LOCAL_PATH)/xz/src/liblzma/simple \ + $(LOCAL_PATH)/xz/src/liblzma LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/xz/src/liblzma/api LOCAL_SRC_FILES := \ - xz/src/common/tuklib_cpucores.c \ - xz/src/common/tuklib_exit.c \ - xz/src/common/tuklib_mbstr_fw.c \ - xz/src/common/tuklib_mbstr_width.c \ - xz/src/common/tuklib_open_stdxxx.c \ - xz/src/common/tuklib_physmem.c \ - xz/src/common/tuklib_progname.c \ - xz/src/liblzma/check/check.c \ - xz/src/liblzma/check/crc32_fast.c \ - xz/src/liblzma/check/crc32_table.c \ - xz/src/liblzma/check/crc64_fast.c \ - xz/src/liblzma/check/crc64_table.c \ - xz/src/liblzma/check/sha256.c \ - xz/src/liblzma/common/alone_decoder.c \ - xz/src/liblzma/common/alone_encoder.c \ - xz/src/liblzma/common/auto_decoder.c \ - xz/src/liblzma/common/block_buffer_decoder.c \ - xz/src/liblzma/common/block_buffer_encoder.c \ - xz/src/liblzma/common/block_decoder.c \ - xz/src/liblzma/common/block_encoder.c \ - xz/src/liblzma/common/block_header_decoder.c \ - xz/src/liblzma/common/block_header_encoder.c \ - xz/src/liblzma/common/block_util.c \ - xz/src/liblzma/common/common.c \ - xz/src/liblzma/common/easy_buffer_encoder.c \ - xz/src/liblzma/common/easy_decoder_memusage.c \ - xz/src/liblzma/common/easy_encoder.c \ - xz/src/liblzma/common/easy_encoder_memusage.c \ - xz/src/liblzma/common/easy_preset.c \ - xz/src/liblzma/common/filter_buffer_decoder.c \ - xz/src/liblzma/common/filter_buffer_encoder.c \ - xz/src/liblzma/common/filter_common.c \ - xz/src/liblzma/common/filter_decoder.c \ - xz/src/liblzma/common/filter_encoder.c \ - xz/src/liblzma/common/filter_flags_decoder.c \ - xz/src/liblzma/common/filter_flags_encoder.c \ - xz/src/liblzma/common/hardware_cputhreads.c \ - xz/src/liblzma/common/hardware_physmem.c \ - xz/src/liblzma/common/index.c \ - xz/src/liblzma/common/index_decoder.c \ - xz/src/liblzma/common/index_encoder.c \ - xz/src/liblzma/common/index_hash.c \ - xz/src/liblzma/common/outqueue.c \ - xz/src/liblzma/common/stream_buffer_decoder.c \ - xz/src/liblzma/common/stream_buffer_encoder.c \ - xz/src/liblzma/common/stream_decoder.c \ - xz/src/liblzma/common/stream_encoder.c \ - xz/src/liblzma/common/stream_encoder_mt.c \ - xz/src/liblzma/common/stream_flags_common.c \ - xz/src/liblzma/common/stream_flags_decoder.c \ - xz/src/liblzma/common/stream_flags_encoder.c \ - xz/src/liblzma/common/vli_decoder.c \ - xz/src/liblzma/common/vli_encoder.c \ - xz/src/liblzma/common/vli_size.c \ - xz/src/liblzma/delta/delta_common.c \ - xz/src/liblzma/delta/delta_decoder.c \ - xz/src/liblzma/delta/delta_encoder.c \ - xz/src/liblzma/lz/lz_decoder.c \ - xz/src/liblzma/lz/lz_encoder.c \ - xz/src/liblzma/lz/lz_encoder_mf.c \ - xz/src/liblzma/lzma/fastpos_table.c \ - xz/src/liblzma/lzma/fastpos_tablegen.c \ - xz/src/liblzma/lzma/lzma2_decoder.c \ - xz/src/liblzma/lzma/lzma2_encoder.c \ - xz/src/liblzma/lzma/lzma_decoder.c \ - xz/src/liblzma/lzma/lzma_encoder.c \ - xz/src/liblzma/lzma/lzma_encoder_optimum_fast.c \ - xz/src/liblzma/lzma/lzma_encoder_optimum_normal.c \ - xz/src/liblzma/lzma/lzma_encoder_presets.c \ - xz/src/liblzma/rangecoder/price_table.c \ - xz/src/liblzma/rangecoder/price_tablegen.c \ - xz/src/liblzma/simple/arm.c \ - xz/src/liblzma/simple/armthumb.c \ - xz/src/liblzma/simple/ia64.c \ - xz/src/liblzma/simple/powerpc.c \ - xz/src/liblzma/simple/simple_coder.c \ - xz/src/liblzma/simple/simple_decoder.c \ - xz/src/liblzma/simple/simple_encoder.c \ - xz/src/liblzma/simple/sparc.c \ - xz/src/liblzma/simple/x86.c + xz/src/common/tuklib_cpucores.c \ + xz/src/common/tuklib_exit.c \ + xz/src/common/tuklib_mbstr_fw.c \ + xz/src/common/tuklib_mbstr_width.c \ + xz/src/common/tuklib_open_stdxxx.c \ + xz/src/common/tuklib_physmem.c \ + xz/src/common/tuklib_progname.c \ + xz/src/liblzma/check/check.c \ + xz/src/liblzma/check/crc32_fast.c \ + xz/src/liblzma/check/crc32_table.c \ + xz/src/liblzma/check/crc64_fast.c \ + xz/src/liblzma/check/crc64_table.c \ + xz/src/liblzma/check/sha256.c \ + xz/src/liblzma/common/alone_decoder.c \ + xz/src/liblzma/common/alone_encoder.c \ + xz/src/liblzma/common/auto_decoder.c \ + xz/src/liblzma/common/block_buffer_decoder.c \ + xz/src/liblzma/common/block_buffer_encoder.c \ + xz/src/liblzma/common/block_decoder.c \ + xz/src/liblzma/common/block_encoder.c \ + xz/src/liblzma/common/block_header_decoder.c \ + xz/src/liblzma/common/block_header_encoder.c \ + xz/src/liblzma/common/block_util.c \ + xz/src/liblzma/common/common.c \ + xz/src/liblzma/common/easy_buffer_encoder.c \ + xz/src/liblzma/common/easy_decoder_memusage.c \ + xz/src/liblzma/common/easy_encoder.c \ + xz/src/liblzma/common/easy_encoder_memusage.c \ + xz/src/liblzma/common/easy_preset.c \ + xz/src/liblzma/common/filter_buffer_decoder.c \ + xz/src/liblzma/common/filter_buffer_encoder.c \ + xz/src/liblzma/common/filter_common.c \ + xz/src/liblzma/common/filter_decoder.c \ + xz/src/liblzma/common/filter_encoder.c \ + xz/src/liblzma/common/filter_flags_decoder.c \ + xz/src/liblzma/common/filter_flags_encoder.c \ + xz/src/liblzma/common/hardware_cputhreads.c \ + xz/src/liblzma/common/hardware_physmem.c \ + xz/src/liblzma/common/index.c \ + xz/src/liblzma/common/index_decoder.c \ + xz/src/liblzma/common/index_encoder.c \ + xz/src/liblzma/common/index_hash.c \ + xz/src/liblzma/common/outqueue.c \ + xz/src/liblzma/common/stream_buffer_decoder.c \ + xz/src/liblzma/common/stream_buffer_encoder.c \ + xz/src/liblzma/common/stream_decoder.c \ + xz/src/liblzma/common/stream_encoder.c \ + xz/src/liblzma/common/stream_encoder_mt.c \ + xz/src/liblzma/common/stream_flags_common.c \ + xz/src/liblzma/common/stream_flags_decoder.c \ + xz/src/liblzma/common/stream_flags_encoder.c \ + xz/src/liblzma/common/vli_decoder.c \ + xz/src/liblzma/common/vli_encoder.c \ + xz/src/liblzma/common/vli_size.c \ + xz/src/liblzma/delta/delta_common.c \ + xz/src/liblzma/delta/delta_decoder.c \ + xz/src/liblzma/delta/delta_encoder.c \ + xz/src/liblzma/lz/lz_decoder.c \ + xz/src/liblzma/lz/lz_encoder.c \ + xz/src/liblzma/lz/lz_encoder_mf.c \ + xz/src/liblzma/lzma/fastpos_table.c \ + xz/src/liblzma/lzma/fastpos_tablegen.c \ + xz/src/liblzma/lzma/lzma2_decoder.c \ + xz/src/liblzma/lzma/lzma2_encoder.c \ + xz/src/liblzma/lzma/lzma_decoder.c \ + xz/src/liblzma/lzma/lzma_encoder.c \ + xz/src/liblzma/lzma/lzma_encoder_optimum_fast.c \ + xz/src/liblzma/lzma/lzma_encoder_optimum_normal.c \ + xz/src/liblzma/lzma/lzma_encoder_presets.c \ + xz/src/liblzma/rangecoder/price_table.c \ + xz/src/liblzma/rangecoder/price_tablegen.c \ + xz/src/liblzma/simple/arm.c \ + xz/src/liblzma/simple/armthumb.c \ + xz/src/liblzma/simple/ia64.c \ + xz/src/liblzma/simple/powerpc.c \ + xz/src/liblzma/simple/simple_coder.c \ + xz/src/liblzma/simple/simple_decoder.c \ + xz/src/liblzma/simple/simple_encoder.c \ + xz/src/liblzma/simple/sparc.c \ + xz/src/liblzma/simple/x86.c LOCAL_CFLAGS := -DHAVE_CONFIG_H -Wno-implicit-function-declaration include $(BUILD_STATIC_LIBRARY) @@ -175,72 +175,72 @@ LOCAL_MODULE := libsepol LOCAL_C_INCLUDES := $(LIBSEPOL) $(LOCAL_PATH)/selinux/libsepol/src LOCAL_EXPORT_C_INCLUDES := $(LIBSEPOL) LOCAL_SRC_FILES := \ - selinux/libsepol/src/assertion.c \ - selinux/libsepol/src/avrule_block.c \ - selinux/libsepol/src/avtab.c \ - selinux/libsepol/src/boolean_record.c \ - selinux/libsepol/src/booleans.c \ - selinux/libsepol/src/conditional.c \ - selinux/libsepol/src/constraint.c \ - selinux/libsepol/src/context.c \ - selinux/libsepol/src/context_record.c \ - selinux/libsepol/src/debug.c \ - selinux/libsepol/src/deprecated_funcs.c \ - selinux/libsepol/src/ebitmap.c \ - selinux/libsepol/src/expand.c \ - selinux/libsepol/src/handle.c \ - selinux/libsepol/src/hashtab.c \ - selinux/libsepol/src/hierarchy.c \ - selinux/libsepol/src/ibendport_record.c \ - selinux/libsepol/src/ibendports.c \ - selinux/libsepol/src/ibpkey_record.c \ - selinux/libsepol/src/ibpkeys.c \ - selinux/libsepol/src/iface_record.c \ - selinux/libsepol/src/interfaces.c \ - selinux/libsepol/src/kernel_to_cil.c \ - selinux/libsepol/src/kernel_to_common.c \ - selinux/libsepol/src/kernel_to_conf.c \ - selinux/libsepol/src/link.c \ - selinux/libsepol/src/mls.c \ - selinux/libsepol/src/module.c \ - selinux/libsepol/src/module_to_cil.c \ - selinux/libsepol/src/node_record.c \ - selinux/libsepol/src/nodes.c \ - selinux/libsepol/src/optimize.c \ - selinux/libsepol/src/polcaps.c \ - selinux/libsepol/src/policydb.c \ - selinux/libsepol/src/policydb_convert.c \ - selinux/libsepol/src/policydb_public.c \ - selinux/libsepol/src/port_record.c \ - selinux/libsepol/src/ports.c \ - selinux/libsepol/src/roles.c \ - selinux/libsepol/src/services.c \ - selinux/libsepol/src/sidtab.c \ - selinux/libsepol/src/symtab.c \ - selinux/libsepol/src/user_record.c \ - selinux/libsepol/src/users.c \ - selinux/libsepol/src/util.c \ - selinux/libsepol/src/write.c \ - selinux/libsepol/cil/src/cil.c \ - selinux/libsepol/cil/src/cil_binary.c \ - selinux/libsepol/cil/src/cil_build_ast.c \ - selinux/libsepol/cil/src/cil_copy_ast.c \ - selinux/libsepol/cil/src/cil_find.c \ - selinux/libsepol/cil/src/cil_fqn.c \ - selinux/libsepol/cil/src/cil_lexer.c \ - selinux/libsepol/cil/src/cil_list.c \ - selinux/libsepol/cil/src/cil_log.c \ - selinux/libsepol/cil/src/cil_mem.c \ - selinux/libsepol/cil/src/cil_parser.c \ - selinux/libsepol/cil/src/cil_policy.c \ - selinux/libsepol/cil/src/cil_post.c \ - selinux/libsepol/cil/src/cil_reset_ast.c \ - selinux/libsepol/cil/src/cil_resolve_ast.c \ - selinux/libsepol/cil/src/cil_stack.c \ - selinux/libsepol/cil/src/cil_strpool.c \ - selinux/libsepol/cil/src/cil_symtab.c \ - selinux/libsepol/cil/src/cil_tree.c \ - selinux/libsepol/cil/src/cil_verify.c + selinux/libsepol/src/assertion.c \ + selinux/libsepol/src/avrule_block.c \ + selinux/libsepol/src/avtab.c \ + selinux/libsepol/src/boolean_record.c \ + selinux/libsepol/src/booleans.c \ + selinux/libsepol/src/conditional.c \ + selinux/libsepol/src/constraint.c \ + selinux/libsepol/src/context.c \ + selinux/libsepol/src/context_record.c \ + selinux/libsepol/src/debug.c \ + selinux/libsepol/src/deprecated_funcs.c \ + selinux/libsepol/src/ebitmap.c \ + selinux/libsepol/src/expand.c \ + selinux/libsepol/src/handle.c \ + selinux/libsepol/src/hashtab.c \ + selinux/libsepol/src/hierarchy.c \ + selinux/libsepol/src/ibendport_record.c \ + selinux/libsepol/src/ibendports.c \ + selinux/libsepol/src/ibpkey_record.c \ + selinux/libsepol/src/ibpkeys.c \ + selinux/libsepol/src/iface_record.c \ + selinux/libsepol/src/interfaces.c \ + selinux/libsepol/src/kernel_to_cil.c \ + selinux/libsepol/src/kernel_to_common.c \ + selinux/libsepol/src/kernel_to_conf.c \ + selinux/libsepol/src/link.c \ + selinux/libsepol/src/mls.c \ + selinux/libsepol/src/module.c \ + selinux/libsepol/src/module_to_cil.c \ + selinux/libsepol/src/node_record.c \ + selinux/libsepol/src/nodes.c \ + selinux/libsepol/src/optimize.c \ + selinux/libsepol/src/polcaps.c \ + selinux/libsepol/src/policydb.c \ + selinux/libsepol/src/policydb_convert.c \ + selinux/libsepol/src/policydb_public.c \ + selinux/libsepol/src/port_record.c \ + selinux/libsepol/src/ports.c \ + selinux/libsepol/src/roles.c \ + selinux/libsepol/src/services.c \ + selinux/libsepol/src/sidtab.c \ + selinux/libsepol/src/symtab.c \ + selinux/libsepol/src/user_record.c \ + selinux/libsepol/src/users.c \ + selinux/libsepol/src/util.c \ + selinux/libsepol/src/write.c \ + selinux/libsepol/cil/src/cil.c \ + selinux/libsepol/cil/src/cil_binary.c \ + selinux/libsepol/cil/src/cil_build_ast.c \ + selinux/libsepol/cil/src/cil_copy_ast.c \ + selinux/libsepol/cil/src/cil_find.c \ + selinux/libsepol/cil/src/cil_fqn.c \ + selinux/libsepol/cil/src/cil_lexer.c \ + selinux/libsepol/cil/src/cil_list.c \ + selinux/libsepol/cil/src/cil_log.c \ + selinux/libsepol/cil/src/cil_mem.c \ + selinux/libsepol/cil/src/cil_parser.c \ + selinux/libsepol/cil/src/cil_policy.c \ + selinux/libsepol/cil/src/cil_post.c \ + selinux/libsepol/cil/src/cil_reset_ast.c \ + selinux/libsepol/cil/src/cil_resolve_ast.c \ + selinux/libsepol/cil/src/cil_stack.c \ + selinux/libsepol/cil/src/cil_strpool.c \ + selinux/libsepol/cil/src/cil_symtab.c \ + selinux/libsepol/cil/src/cil_tree.c \ + selinux/libsepol/cil/src/cil_verify.c LOCAL_CFLAGS := -Dgetline=__getline -Wno-implicit-function-declaration include $(BUILD_STATIC_LIBRARY) @@ -252,67 +252,67 @@ LOCAL_C_INCLUDES := $(LIBSELINUX) LOCAL_EXPORT_C_INCLUDES := $(LIBSELINUX) LOCAL_STATIC_LIBRARIES := libpcre2 LOCAL_CFLAGS := \ - -Wno-implicit-function-declaration -Wno-int-conversion -Wno-unused-function \ - -D_GNU_SOURCE -DUSE_PCRE2 \ - -DNO_PERSISTENTLY_STORED_PATTERNS -DDISABLE_SETRANS -DDISABLE_BOOL \ - -DNO_MEDIA_BACKEND -DNO_X_BACKEND -DNO_DB_BACKEND -DNO_ANDROID_BACKEND + -Wno-implicit-function-declaration -Wno-int-conversion -Wno-unused-function \ + -D_GNU_SOURCE -DUSE_PCRE2 \ + -DNO_PERSISTENTLY_STORED_PATTERNS -DDISABLE_SETRANS -DDISABLE_BOOL \ + -DNO_MEDIA_BACKEND -DNO_X_BACKEND -DNO_DB_BACKEND -DNO_ANDROID_BACKEND LOCAL_SRC_FILES := \ - selinux/libselinux/src/avc.c \ - selinux/libselinux/src/avc_internal.c \ - selinux/libselinux/src/avc_sidtab.c \ - selinux/libselinux/src/booleans.c \ - selinux/libselinux/src/callbacks.c \ - selinux/libselinux/src/canonicalize_context.c \ - selinux/libselinux/src/checkAccess.c \ - selinux/libselinux/src/check_context.c \ - selinux/libselinux/src/checkreqprot.c \ - selinux/libselinux/src/compute_av.c \ - selinux/libselinux/src/compute_create.c \ - selinux/libselinux/src/compute_member.c \ - selinux/libselinux/src/compute_relabel.c \ - selinux/libselinux/src/compute_user.c \ - selinux/libselinux/src/context.c \ - selinux/libselinux/src/deny_unknown.c \ - selinux/libselinux/src/disable.c \ - selinux/libselinux/src/enabled.c \ - selinux/libselinux/src/fgetfilecon.c \ - selinux/libselinux/src/freecon.c \ - selinux/libselinux/src/freeconary.c \ - selinux/libselinux/src/fsetfilecon.c \ - selinux/libselinux/src/get_context_list.c \ - selinux/libselinux/src/get_default_type.c \ - selinux/libselinux/src/get_initial_context.c \ - selinux/libselinux/src/getenforce.c \ - selinux/libselinux/src/getfilecon.c \ - selinux/libselinux/src/getpeercon.c \ - selinux/libselinux/src/init.c \ - selinux/libselinux/src/is_customizable_type.c \ - selinux/libselinux/src/label.c \ - selinux/libselinux/src/label_file.c \ - selinux/libselinux/src/label_support.c \ - selinux/libselinux/src/lgetfilecon.c \ - selinux/libselinux/src/load_policy.c \ - selinux/libselinux/src/lsetfilecon.c \ - selinux/libselinux/src/mapping.c \ - selinux/libselinux/src/matchmediacon.c \ - selinux/libselinux/src/matchpathcon.c \ - selinux/libselinux/src/policyvers.c \ - selinux/libselinux/src/procattr.c \ - selinux/libselinux/src/query_user_context.c \ - selinux/libselinux/src/regex.c \ - selinux/libselinux/src/reject_unknown.c \ - selinux/libselinux/src/selinux_check_securetty_context.c \ - selinux/libselinux/src/selinux_config.c \ - selinux/libselinux/src/selinux_restorecon.c \ - selinux/libselinux/src/sestatus.c \ - selinux/libselinux/src/setenforce.c \ - selinux/libselinux/src/setexecfilecon.c \ - selinux/libselinux/src/setfilecon.c \ - selinux/libselinux/src/setrans_client.c \ - selinux/libselinux/src/seusers.c \ - selinux/libselinux/src/sha1.c \ - selinux/libselinux/src/stringrep.c \ - selinux/libselinux/src/validatetrans.c + selinux/libselinux/src/avc.c \ + selinux/libselinux/src/avc_internal.c \ + selinux/libselinux/src/avc_sidtab.c \ + selinux/libselinux/src/booleans.c \ + selinux/libselinux/src/callbacks.c \ + selinux/libselinux/src/canonicalize_context.c \ + selinux/libselinux/src/checkAccess.c \ + selinux/libselinux/src/check_context.c \ + selinux/libselinux/src/checkreqprot.c \ + selinux/libselinux/src/compute_av.c \ + selinux/libselinux/src/compute_create.c \ + selinux/libselinux/src/compute_member.c \ + selinux/libselinux/src/compute_relabel.c \ + selinux/libselinux/src/compute_user.c \ + selinux/libselinux/src/context.c \ + selinux/libselinux/src/deny_unknown.c \ + selinux/libselinux/src/disable.c \ + selinux/libselinux/src/enabled.c \ + selinux/libselinux/src/fgetfilecon.c \ + selinux/libselinux/src/freecon.c \ + selinux/libselinux/src/freeconary.c \ + selinux/libselinux/src/fsetfilecon.c \ + selinux/libselinux/src/get_context_list.c \ + selinux/libselinux/src/get_default_type.c \ + selinux/libselinux/src/get_initial_context.c \ + selinux/libselinux/src/getenforce.c \ + selinux/libselinux/src/getfilecon.c \ + selinux/libselinux/src/getpeercon.c \ + selinux/libselinux/src/init.c \ + selinux/libselinux/src/is_customizable_type.c \ + selinux/libselinux/src/label.c \ + selinux/libselinux/src/label_file.c \ + selinux/libselinux/src/label_support.c \ + selinux/libselinux/src/lgetfilecon.c \ + selinux/libselinux/src/load_policy.c \ + selinux/libselinux/src/lsetfilecon.c \ + selinux/libselinux/src/mapping.c \ + selinux/libselinux/src/matchmediacon.c \ + selinux/libselinux/src/matchpathcon.c \ + selinux/libselinux/src/policyvers.c \ + selinux/libselinux/src/procattr.c \ + selinux/libselinux/src/query_user_context.c \ + selinux/libselinux/src/regex.c \ + selinux/libselinux/src/reject_unknown.c \ + selinux/libselinux/src/selinux_check_securetty_context.c \ + selinux/libselinux/src/selinux_config.c \ + selinux/libselinux/src/selinux_restorecon.c \ + selinux/libselinux/src/sestatus.c \ + selinux/libselinux/src/setenforce.c \ + selinux/libselinux/src/setexecfilecon.c \ + selinux/libselinux/src/setfilecon.c \ + selinux/libselinux/src/setrans_client.c \ + selinux/libselinux/src/seusers.c \ + selinux/libselinux/src/sha1.c \ + selinux/libselinux/src/stringrep.c \ + selinux/libselinux/src/validatetrans.c include $(BUILD_STATIC_LIBRARY) # libpcre2.a @@ -323,34 +323,34 @@ LOCAL_CFLAGS := -DHAVE_CONFIG_H LOCAL_C_INCLUDES := $(LIBPCRE2) $(LIBPCRE2)_internal LOCAL_EXPORT_C_INCLUDES := $(LIBPCRE2) LOCAL_SRC_FILES := \ - pcre/dist2/src/pcre2_auto_possess.c \ - pcre/dist2/src/pcre2_chartables.c \ - pcre/dist2/src/pcre2_compile.c \ - pcre/dist2/src/pcre2_config.c \ - pcre/dist2/src/pcre2_context.c \ - pcre/dist2/src/pcre2_convert.c \ - pcre/dist2/src/pcre2_dfa_match.c \ - pcre/dist2/src/pcre2_error.c \ - pcre/dist2/src/pcre2_extuni.c \ - pcre/dist2/src/pcre2_find_bracket.c \ - pcre/dist2/src/pcre2_fuzzsupport.c \ - pcre/dist2/src/pcre2_jit_compile.c \ - pcre/dist2/src/pcre2_maketables.c \ - pcre/dist2/src/pcre2_match.c \ - pcre/dist2/src/pcre2_match_data.c \ - pcre/dist2/src/pcre2_newline.c \ - pcre/dist2/src/pcre2_ord2utf.c \ - pcre/dist2/src/pcre2_pattern_info.c \ - pcre/dist2/src/pcre2_script_run.c \ - pcre/dist2/src/pcre2_serialize.c \ - pcre/dist2/src/pcre2_string_utils.c \ - pcre/dist2/src/pcre2_study.c \ - pcre/dist2/src/pcre2_substitute.c \ - pcre/dist2/src/pcre2_substring.c \ - pcre/dist2/src/pcre2_tables.c \ - pcre/dist2/src/pcre2_ucd.c \ - pcre/dist2/src/pcre2_valid_utf.c \ - pcre/dist2/src/pcre2_xclass.c + pcre/dist2/src/pcre2_auto_possess.c \ + pcre/dist2/src/pcre2_chartables.c \ + pcre/dist2/src/pcre2_compile.c \ + pcre/dist2/src/pcre2_config.c \ + pcre/dist2/src/pcre2_context.c \ + pcre/dist2/src/pcre2_convert.c \ + pcre/dist2/src/pcre2_dfa_match.c \ + pcre/dist2/src/pcre2_error.c \ + pcre/dist2/src/pcre2_extuni.c \ + pcre/dist2/src/pcre2_find_bracket.c \ + pcre/dist2/src/pcre2_fuzzsupport.c \ + pcre/dist2/src/pcre2_jit_compile.c \ + pcre/dist2/src/pcre2_maketables.c \ + pcre/dist2/src/pcre2_match.c \ + pcre/dist2/src/pcre2_match_data.c \ + pcre/dist2/src/pcre2_newline.c \ + pcre/dist2/src/pcre2_ord2utf.c \ + pcre/dist2/src/pcre2_pattern_info.c \ + pcre/dist2/src/pcre2_script_run.c \ + pcre/dist2/src/pcre2_serialize.c \ + pcre/dist2/src/pcre2_string_utils.c \ + pcre/dist2/src/pcre2_study.c \ + pcre/dist2/src/pcre2_substitute.c \ + pcre/dist2/src/pcre2_substring.c \ + pcre/dist2/src/pcre2_tables.c \ + pcre/dist2/src/pcre2_ucd.c \ + pcre/dist2/src/pcre2_valid_utf.c \ + pcre/dist2/src/pcre2_xclass.c include $(BUILD_STATIC_LIBRARY) include $(LOCAL_PATH)/mincrypt/Android.mk diff --git a/native/jni/external/xz-embedded/xz.h b/native/jni/external/xz-embedded/xz.h index 0a4b38d33..fd0423882 100644 --- a/native/jni/external/xz-embedded/xz.h +++ b/native/jni/external/xz-embedded/xz.h @@ -54,9 +54,9 @@ extern "C" { * be built with fewer features to minimize code size. */ enum xz_mode { - XZ_SINGLE, - XZ_PREALLOC, - XZ_DYNALLOC + XZ_SINGLE, + XZ_PREALLOC, + XZ_DYNALLOC }; /** @@ -110,15 +110,15 @@ enum xz_mode { * is used instead of XZ_BUF_ERROR. */ enum xz_ret { - XZ_OK, - XZ_STREAM_END, - XZ_UNSUPPORTED_CHECK, - XZ_MEM_ERROR, - XZ_MEMLIMIT_ERROR, - XZ_FORMAT_ERROR, - XZ_OPTIONS_ERROR, - XZ_DATA_ERROR, - XZ_BUF_ERROR + XZ_OK, + XZ_STREAM_END, + XZ_UNSUPPORTED_CHECK, + XZ_MEM_ERROR, + XZ_MEMLIMIT_ERROR, + XZ_FORMAT_ERROR, + XZ_OPTIONS_ERROR, + XZ_DATA_ERROR, + XZ_BUF_ERROR }; /** @@ -138,13 +138,13 @@ enum xz_ret { * the variables in_pos and out_pos are modified by the XZ code. */ struct xz_buf { - const uint8_t *in; - size_t in_pos; - size_t in_size; + const uint8_t *in; + size_t in_pos; + size_t in_size; - uint8_t *out; - size_t out_pos; - size_t out_size; + uint8_t *out; + size_t out_pos; + size_t out_size; }; /** diff --git a/native/jni/external/xz-embedded/xz_config.h b/native/jni/external/xz-embedded/xz_config.h index eb9dac1a4..4031c95a5 100644 --- a/native/jni/external/xz-embedded/xz_config.h +++ b/native/jni/external/xz-embedded/xz_config.h @@ -65,7 +65,7 @@ typedef unsigned char bool; #ifndef __always_inline # ifdef __GNUC__ # define __always_inline \ - inline __attribute__((__always_inline__)) + inline __attribute__((__always_inline__)) # else # define __always_inline inline # endif @@ -75,40 +75,40 @@ typedef unsigned char bool; #ifndef get_unaligned_le32 static inline uint32_t get_unaligned_le32(const uint8_t *buf) { - return (uint32_t)buf[0] - | ((uint32_t)buf[1] << 8) - | ((uint32_t)buf[2] << 16) - | ((uint32_t)buf[3] << 24); + return (uint32_t)buf[0] + | ((uint32_t)buf[1] << 8) + | ((uint32_t)buf[2] << 16) + | ((uint32_t)buf[3] << 24); } #endif #ifndef get_unaligned_be32 static inline uint32_t get_unaligned_be32(const uint8_t *buf) { - return (uint32_t)(buf[0] << 24) - | ((uint32_t)buf[1] << 16) - | ((uint32_t)buf[2] << 8) - | (uint32_t)buf[3]; + return (uint32_t)(buf[0] << 24) + | ((uint32_t)buf[1] << 16) + | ((uint32_t)buf[2] << 8) + | (uint32_t)buf[3]; } #endif #ifndef put_unaligned_le32 static inline void put_unaligned_le32(uint32_t val, uint8_t *buf) { - buf[0] = (uint8_t)val; - buf[1] = (uint8_t)(val >> 8); - buf[2] = (uint8_t)(val >> 16); - buf[3] = (uint8_t)(val >> 24); + buf[0] = (uint8_t)val; + buf[1] = (uint8_t)(val >> 8); + buf[2] = (uint8_t)(val >> 16); + buf[3] = (uint8_t)(val >> 24); } #endif #ifndef put_unaligned_be32 static inline void put_unaligned_be32(uint32_t val, uint8_t *buf) { - buf[0] = (uint8_t)(val >> 24); - buf[1] = (uint8_t)(val >> 16); - buf[2] = (uint8_t)(val >> 8); - buf[3] = (uint8_t)val; + buf[0] = (uint8_t)(val >> 24); + buf[1] = (uint8_t)(val >> 16); + buf[2] = (uint8_t)(val >> 8); + buf[3] = (uint8_t)val; } #endif diff --git a/native/jni/external/xz-embedded/xz_crc32.c b/native/jni/external/xz-embedded/xz_crc32.c index 34532d14f..bcbed22f0 100644 --- a/native/jni/external/xz-embedded/xz_crc32.c +++ b/native/jni/external/xz-embedded/xz_crc32.c @@ -29,31 +29,31 @@ STATIC_RW_DATA uint32_t xz_crc32_table[256]; XZ_EXTERN void xz_crc32_init(void) { - const uint32_t poly = 0xEDB88320; + const uint32_t poly = 0xEDB88320; - uint32_t i; - uint32_t j; - uint32_t r; + uint32_t i; + uint32_t j; + uint32_t r; - for (i = 0; i < 256; ++i) { - r = i; - for (j = 0; j < 8; ++j) - r = (r >> 1) ^ (poly & ~((r & 1) - 1)); + for (i = 0; i < 256; ++i) { + r = i; + for (j = 0; j < 8; ++j) + r = (r >> 1) ^ (poly & ~((r & 1) - 1)); - xz_crc32_table[i] = r; - } + xz_crc32_table[i] = r; + } - return; + return; } XZ_EXTERN uint32_t xz_crc32(const uint8_t *buf, size_t size, uint32_t crc) { - crc = ~crc; + crc = ~crc; - while (size != 0) { - crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); - --size; - } + while (size != 0) { + crc = xz_crc32_table[*buf++ ^ (crc & 0xFF)] ^ (crc >> 8); + --size; + } - return ~crc; + return ~crc; } diff --git a/native/jni/external/xz-embedded/xz_dec_lzma2.c b/native/jni/external/xz-embedded/xz_dec_lzma2.c index a6cdc969e..6c0a80957 100644 --- a/native/jni/external/xz-embedded/xz_dec_lzma2.c +++ b/native/jni/external/xz-embedded/xz_dec_lzma2.c @@ -42,237 +42,237 @@ * buffer directly. */ struct dictionary { - /* Beginning of the history buffer */ - uint8_t *buf; + /* Beginning of the history buffer */ + uint8_t *buf; - /* Old position in buf (before decoding more data) */ - size_t start; + /* Old position in buf (before decoding more data) */ + size_t start; - /* Position in buf */ - size_t pos; + /* Position in buf */ + size_t pos; - /* - * How full dictionary is. This is used to detect corrupt input that - * would read beyond the beginning of the uncompressed stream. - */ - size_t full; + /* + * How full dictionary is. This is used to detect corrupt input that + * would read beyond the beginning of the uncompressed stream. + */ + size_t full; - /* Write limit; we don't write to buf[limit] or later bytes. */ - size_t limit; + /* Write limit; we don't write to buf[limit] or later bytes. */ + size_t limit; - /* - * End of the dictionary buffer. In multi-call mode, this is - * the same as the dictionary size. In single-call mode, this - * indicates the size of the output buffer. - */ - size_t end; + /* + * End of the dictionary buffer. In multi-call mode, this is + * the same as the dictionary size. In single-call mode, this + * indicates the size of the output buffer. + */ + size_t end; - /* - * Size of the dictionary as specified in Block Header. This is used - * together with "full" to detect corrupt input that would make us - * read beyond the beginning of the uncompressed stream. - */ - uint32_t size; + /* + * Size of the dictionary as specified in Block Header. This is used + * together with "full" to detect corrupt input that would make us + * read beyond the beginning of the uncompressed stream. + */ + uint32_t size; - /* - * Maximum allowed dictionary size in multi-call mode. - * This is ignored in single-call mode. - */ - uint32_t size_max; + /* + * Maximum allowed dictionary size in multi-call mode. + * This is ignored in single-call mode. + */ + uint32_t size_max; - /* - * Amount of memory currently allocated for the dictionary. - * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC, - * size_max is always the same as the allocated size.) - */ - uint32_t allocated; + /* + * Amount of memory currently allocated for the dictionary. + * This is used only with XZ_DYNALLOC. (With XZ_PREALLOC, + * size_max is always the same as the allocated size.) + */ + uint32_t allocated; - /* Operation mode */ - enum xz_mode mode; + /* Operation mode */ + enum xz_mode mode; }; /* Range decoder */ struct rc_dec { - uint32_t range; - uint32_t code; + uint32_t range; + uint32_t code; - /* - * Number of initializing bytes remaining to be read - * by rc_read_init(). - */ - uint32_t init_bytes_left; + /* + * Number of initializing bytes remaining to be read + * by rc_read_init(). + */ + uint32_t init_bytes_left; - /* - * Buffer from which we read our input. It can be either - * temp.buf or the caller-provided input buffer. - */ - const uint8_t *in; - size_t in_pos; - size_t in_limit; + /* + * Buffer from which we read our input. It can be either + * temp.buf or the caller-provided input buffer. + */ + const uint8_t *in; + size_t in_pos; + size_t in_limit; }; /* Probabilities for a length decoder. */ struct lzma_len_dec { - /* Probability of match length being at least 10 */ - uint16_t choice; + /* Probability of match length being at least 10 */ + uint16_t choice; - /* Probability of match length being at least 18 */ - uint16_t choice2; + /* Probability of match length being at least 18 */ + uint16_t choice2; - /* Probabilities for match lengths 2-9 */ - uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; + /* Probabilities for match lengths 2-9 */ + uint16_t low[POS_STATES_MAX][LEN_LOW_SYMBOLS]; - /* Probabilities for match lengths 10-17 */ - uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; + /* Probabilities for match lengths 10-17 */ + uint16_t mid[POS_STATES_MAX][LEN_MID_SYMBOLS]; - /* Probabilities for match lengths 18-273 */ - uint16_t high[LEN_HIGH_SYMBOLS]; + /* Probabilities for match lengths 18-273 */ + uint16_t high[LEN_HIGH_SYMBOLS]; }; struct lzma_dec { - /* Distances of latest four matches */ - uint32_t rep0; - uint32_t rep1; - uint32_t rep2; - uint32_t rep3; + /* Distances of latest four matches */ + uint32_t rep0; + uint32_t rep1; + uint32_t rep2; + uint32_t rep3; - /* Types of the most recently seen LZMA symbols */ - enum lzma_state state; + /* Types of the most recently seen LZMA symbols */ + enum lzma_state state; - /* - * Length of a match. This is updated so that dict_repeat can - * be called again to finish repeating the whole match. - */ - uint32_t len; + /* + * Length of a match. This is updated so that dict_repeat can + * be called again to finish repeating the whole match. + */ + uint32_t len; - /* - * LZMA properties or related bit masks (number of literal - * context bits, a mask dervied from the number of literal - * position bits, and a mask dervied from the number - * position bits) - */ - uint32_t lc; - uint32_t literal_pos_mask; /* (1 << lp) - 1 */ - uint32_t pos_mask; /* (1 << pb) - 1 */ + /* + * LZMA properties or related bit masks (number of literal + * context bits, a mask dervied from the number of literal + * position bits, and a mask dervied from the number + * position bits) + */ + uint32_t lc; + uint32_t literal_pos_mask; /* (1 << lp) - 1 */ + uint32_t pos_mask; /* (1 << pb) - 1 */ - /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ - uint16_t is_match[STATES][POS_STATES_MAX]; + /* If 1, it's a match. Otherwise it's a single 8-bit literal. */ + uint16_t is_match[STATES][POS_STATES_MAX]; - /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */ - uint16_t is_rep[STATES]; + /* If 1, it's a repeated match. The distance is one of rep0 .. rep3. */ + uint16_t is_rep[STATES]; - /* - * If 0, distance of a repeated match is rep0. - * Otherwise check is_rep1. - */ - uint16_t is_rep0[STATES]; + /* + * If 0, distance of a repeated match is rep0. + * Otherwise check is_rep1. + */ + uint16_t is_rep0[STATES]; - /* - * If 0, distance of a repeated match is rep1. - * Otherwise check is_rep2. - */ - uint16_t is_rep1[STATES]; + /* + * If 0, distance of a repeated match is rep1. + * Otherwise check is_rep2. + */ + uint16_t is_rep1[STATES]; - /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */ - uint16_t is_rep2[STATES]; + /* If 0, distance of a repeated match is rep2. Otherwise it is rep3. */ + uint16_t is_rep2[STATES]; - /* - * If 1, the repeated match has length of one byte. Otherwise - * the length is decoded from rep_len_decoder. - */ - uint16_t is_rep0_long[STATES][POS_STATES_MAX]; + /* + * If 1, the repeated match has length of one byte. Otherwise + * the length is decoded from rep_len_decoder. + */ + uint16_t is_rep0_long[STATES][POS_STATES_MAX]; - /* - * Probability tree for the highest two bits of the match - * distance. There is a separate probability tree for match - * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273]. - */ - uint16_t dist_slot[DIST_STATES][DIST_SLOTS]; + /* + * Probability tree for the highest two bits of the match + * distance. There is a separate probability tree for match + * lengths of 2 (i.e. MATCH_LEN_MIN), 3, 4, and [5, 273]. + */ + uint16_t dist_slot[DIST_STATES][DIST_SLOTS]; - /* - * Probility trees for additional bits for match distance - * when the distance is in the range [4, 127]. - */ - uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END]; + /* + * Probility trees for additional bits for match distance + * when the distance is in the range [4, 127]. + */ + uint16_t dist_special[FULL_DISTANCES - DIST_MODEL_END]; - /* - * Probability tree for the lowest four bits of a match - * distance that is equal to or greater than 128. - */ - uint16_t dist_align[ALIGN_SIZE]; + /* + * Probability tree for the lowest four bits of a match + * distance that is equal to or greater than 128. + */ + uint16_t dist_align[ALIGN_SIZE]; - /* Length of a normal match */ - struct lzma_len_dec match_len_dec; + /* Length of a normal match */ + struct lzma_len_dec match_len_dec; - /* Length of a repeated match */ - struct lzma_len_dec rep_len_dec; + /* Length of a repeated match */ + struct lzma_len_dec rep_len_dec; - /* Probabilities of literals */ - uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; + /* Probabilities of literals */ + uint16_t literal[LITERAL_CODERS_MAX][LITERAL_CODER_SIZE]; }; struct lzma2_dec { - /* Position in xz_dec_lzma2_run(). */ - enum lzma2_seq { - SEQ_CONTROL, - SEQ_UNCOMPRESSED_1, - SEQ_UNCOMPRESSED_2, - SEQ_COMPRESSED_0, - SEQ_COMPRESSED_1, - SEQ_PROPERTIES, - SEQ_LZMA_PREPARE, - SEQ_LZMA_RUN, - SEQ_COPY - } sequence; + /* Position in xz_dec_lzma2_run(). */ + enum lzma2_seq { + SEQ_CONTROL, + SEQ_UNCOMPRESSED_1, + SEQ_UNCOMPRESSED_2, + SEQ_COMPRESSED_0, + SEQ_COMPRESSED_1, + SEQ_PROPERTIES, + SEQ_LZMA_PREPARE, + SEQ_LZMA_RUN, + SEQ_COPY + } sequence; - /* Next position after decoding the compressed size of the chunk. */ - enum lzma2_seq next_sequence; + /* Next position after decoding the compressed size of the chunk. */ + enum lzma2_seq next_sequence; - /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ - uint32_t uncompressed; + /* Uncompressed size of LZMA chunk (2 MiB at maximum) */ + uint32_t uncompressed; - /* - * Compressed size of LZMA chunk or compressed/uncompressed - * size of uncompressed chunk (64 KiB at maximum) - */ - uint32_t compressed; + /* + * Compressed size of LZMA chunk or compressed/uncompressed + * size of uncompressed chunk (64 KiB at maximum) + */ + uint32_t compressed; - /* - * True if dictionary reset is needed. This is false before - * the first chunk (LZMA or uncompressed). - */ - bool need_dict_reset; + /* + * True if dictionary reset is needed. This is false before + * the first chunk (LZMA or uncompressed). + */ + bool need_dict_reset; - /* - * True if new LZMA properties are needed. This is false - * before the first LZMA chunk. - */ - bool need_props; + /* + * True if new LZMA properties are needed. This is false + * before the first LZMA chunk. + */ + bool need_props; }; struct xz_dec_lzma2 { - /* - * The order below is important on x86 to reduce code size and - * it shouldn't hurt on other platforms. Everything up to and - * including lzma.pos_mask are in the first 128 bytes on x86-32, - * which allows using smaller instructions to access those - * variables. On x86-64, fewer variables fit into the first 128 - * bytes, but this is still the best order without sacrificing - * the readability by splitting the structures. - */ - struct rc_dec rc; - struct dictionary dict; - struct lzma2_dec lzma2; - struct lzma_dec lzma; + /* + * The order below is important on x86 to reduce code size and + * it shouldn't hurt on other platforms. Everything up to and + * including lzma.pos_mask are in the first 128 bytes on x86-32, + * which allows using smaller instructions to access those + * variables. On x86-64, fewer variables fit into the first 128 + * bytes, but this is still the best order without sacrificing + * the readability by splitting the structures. + */ + struct rc_dec rc; + struct dictionary dict; + struct lzma2_dec lzma2; + struct lzma_dec lzma; - /* - * Temporary buffer which holds small number of input bytes between - * decoder calls. See lzma2_lzma() for details. - */ - struct { - uint32_t size; - uint8_t buf[3 * LZMA_IN_REQUIRED]; - } temp; + /* + * Temporary buffer which holds small number of input bytes between + * decoder calls. See lzma2_lzma() for details. + */ + struct { + uint32_t size; + uint8_t buf[3 * LZMA_IN_REQUIRED]; + } temp; }; /************** @@ -285,30 +285,30 @@ struct xz_dec_lzma2 { */ static void dict_reset(struct dictionary *dict, struct xz_buf *b) { - if (DEC_IS_SINGLE(dict->mode)) { - dict->buf = b->out + b->out_pos; - dict->end = b->out_size - b->out_pos; - } + if (DEC_IS_SINGLE(dict->mode)) { + dict->buf = b->out + b->out_pos; + dict->end = b->out_size - b->out_pos; + } - dict->start = 0; - dict->pos = 0; - dict->limit = 0; - dict->full = 0; + dict->start = 0; + dict->pos = 0; + dict->limit = 0; + dict->full = 0; } /* Set dictionary write limit */ static void dict_limit(struct dictionary *dict, size_t out_max) { - if (dict->end - dict->pos <= out_max) - dict->limit = dict->end; - else - dict->limit = dict->pos + out_max; + if (dict->end - dict->pos <= out_max) + dict->limit = dict->end; + else + dict->limit = dict->pos + out_max; } /* Return true if at least one byte can be written into the dictionary. */ static inline bool dict_has_space(const struct dictionary *dict) { - return dict->pos < dict->limit; + return dict->pos < dict->limit; } /* @@ -319,12 +319,12 @@ static inline bool dict_has_space(const struct dictionary *dict) */ static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist) { - size_t offset = dict->pos - dist - 1; + size_t offset = dict->pos - dist - 1; - if (dist >= dict->pos) - offset += dict->end; + if (dist >= dict->pos) + offset += dict->end; - return dict->full > 0 ? dict->buf[offset] : 0; + return dict->full > 0 ? dict->buf[offset] : 0; } /* @@ -332,10 +332,10 @@ static inline uint32_t dict_get(const struct dictionary *dict, uint32_t dist) */ static inline void dict_put(struct dictionary *dict, uint8_t byte) { - dict->buf[dict->pos++] = byte; + dict->buf[dict->pos++] = byte; - if (dict->full < dict->pos) - dict->full = dict->pos; + if (dict->full < dict->pos) + dict->full = dict->pos; } /* @@ -345,67 +345,67 @@ static inline void dict_put(struct dictionary *dict, uint8_t byte) */ static bool dict_repeat(struct dictionary *dict, uint32_t *len, uint32_t dist) { - size_t back; - uint32_t left; + size_t back; + uint32_t left; - if (dist >= dict->full || dist >= dict->size) - return false; + if (dist >= dict->full || dist >= dict->size) + return false; - left = min_t(size_t, dict->limit - dict->pos, *len); - *len -= left; + left = min_t(size_t, dict->limit - dict->pos, *len); + *len -= left; - back = dict->pos - dist - 1; - if (dist >= dict->pos) - back += dict->end; + back = dict->pos - dist - 1; + if (dist >= dict->pos) + back += dict->end; - do { - dict->buf[dict->pos++] = dict->buf[back++]; - if (back == dict->end) - back = 0; - } while (--left > 0); + do { + dict->buf[dict->pos++] = dict->buf[back++]; + if (back == dict->end) + back = 0; + } while (--left > 0); - if (dict->full < dict->pos) - dict->full = dict->pos; + if (dict->full < dict->pos) + dict->full = dict->pos; - return true; + return true; } /* Copy uncompressed data as is from input to dictionary and output buffers. */ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, - uint32_t *left) + uint32_t *left) { - size_t copy_size; + size_t copy_size; - while (*left > 0 && b->in_pos < b->in_size - && b->out_pos < b->out_size) { - copy_size = min(b->in_size - b->in_pos, - b->out_size - b->out_pos); - if (copy_size > dict->end - dict->pos) - copy_size = dict->end - dict->pos; - if (copy_size > *left) - copy_size = *left; + while (*left > 0 && b->in_pos < b->in_size + && b->out_pos < b->out_size) { + copy_size = min(b->in_size - b->in_pos, + b->out_size - b->out_pos); + if (copy_size > dict->end - dict->pos) + copy_size = dict->end - dict->pos; + if (copy_size > *left) + copy_size = *left; - *left -= copy_size; + *left -= copy_size; - memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); - dict->pos += copy_size; + memcpy(dict->buf + dict->pos, b->in + b->in_pos, copy_size); + dict->pos += copy_size; - if (dict->full < dict->pos) - dict->full = dict->pos; + if (dict->full < dict->pos) + dict->full = dict->pos; - if (DEC_IS_MULTI(dict->mode)) { - if (dict->pos == dict->end) - dict->pos = 0; + if (DEC_IS_MULTI(dict->mode)) { + if (dict->pos == dict->end) + dict->pos = 0; - memcpy(b->out + b->out_pos, b->in + b->in_pos, - copy_size); - } + memcpy(b->out + b->out_pos, b->in + b->in_pos, + copy_size); + } - dict->start = dict->pos; + dict->start = dict->pos; - b->out_pos += copy_size; - b->in_pos += copy_size; - } + b->out_pos += copy_size; + b->in_pos += copy_size; + } } /* @@ -415,19 +415,19 @@ static void dict_uncompressed(struct dictionary *dict, struct xz_buf *b, */ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) { - size_t copy_size = dict->pos - dict->start; + size_t copy_size = dict->pos - dict->start; - if (DEC_IS_MULTI(dict->mode)) { - if (dict->pos == dict->end) - dict->pos = 0; + if (DEC_IS_MULTI(dict->mode)) { + if (dict->pos == dict->end) + dict->pos = 0; - memcpy(b->out + b->out_pos, dict->buf + dict->start, - copy_size); - } + memcpy(b->out + b->out_pos, dict->buf + dict->start, + copy_size); + } - dict->start = dict->pos; - b->out_pos += copy_size; - return copy_size; + dict->start = dict->pos; + b->out_pos += copy_size; + return copy_size; } /***************** @@ -437,9 +437,9 @@ static uint32_t dict_flush(struct dictionary *dict, struct xz_buf *b) /* Reset the range decoder. */ static void rc_reset(struct rc_dec *rc) { - rc->range = (uint32_t)-1; - rc->code = 0; - rc->init_bytes_left = RC_INIT_BYTES; + rc->range = (uint32_t)-1; + rc->code = 0; + rc->init_bytes_left = RC_INIT_BYTES; } /* @@ -448,21 +448,21 @@ static void rc_reset(struct rc_dec *rc) */ static bool rc_read_init(struct rc_dec *rc, struct xz_buf *b) { - while (rc->init_bytes_left > 0) { - if (b->in_pos == b->in_size) - return false; + while (rc->init_bytes_left > 0) { + if (b->in_pos == b->in_size) + return false; - rc->code = (rc->code << 8) + b->in[b->in_pos++]; - --rc->init_bytes_left; - } + rc->code = (rc->code << 8) + b->in[b->in_pos++]; + --rc->init_bytes_left; + } - return true; + return true; } /* Return true if there may not be enough input for the next decoding loop. */ static inline bool rc_limit_exceeded(const struct rc_dec *rc) { - return rc->in_pos > rc->in_limit; + return rc->in_pos > rc->in_limit; } /* @@ -471,16 +471,16 @@ static inline bool rc_limit_exceeded(const struct rc_dec *rc) */ static inline bool rc_is_finished(const struct rc_dec *rc) { - return rc->code == 0; + return rc->code == 0; } /* Read the next input byte if needed. */ static __always_inline void rc_normalize(struct rc_dec *rc) { - if (rc->range < RC_TOP_VALUE) { - rc->range <<= RC_SHIFT_BITS; - rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; - } + if (rc->range < RC_TOP_VALUE) { + rc->range <<= RC_SHIFT_BITS; + rc->code = (rc->code << RC_SHIFT_BITS) + rc->in[rc->in_pos++]; + } } /* @@ -496,72 +496,72 @@ static __always_inline void rc_normalize(struct rc_dec *rc) */ static __always_inline int rc_bit(struct rc_dec *rc, uint16_t *prob) { - uint32_t bound; - int bit; + uint32_t bound; + int bit; - rc_normalize(rc); - bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; - if (rc->code < bound) { - rc->range = bound; - *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; - bit = 0; - } else { - rc->range -= bound; - rc->code -= bound; - *prob -= *prob >> RC_MOVE_BITS; - bit = 1; - } + rc_normalize(rc); + bound = (rc->range >> RC_BIT_MODEL_TOTAL_BITS) * *prob; + if (rc->code < bound) { + rc->range = bound; + *prob += (RC_BIT_MODEL_TOTAL - *prob) >> RC_MOVE_BITS; + bit = 0; + } else { + rc->range -= bound; + rc->code -= bound; + *prob -= *prob >> RC_MOVE_BITS; + bit = 1; + } - return bit; + return bit; } /* Decode a bittree starting from the most significant bit. */ static __always_inline uint32_t rc_bittree(struct rc_dec *rc, - uint16_t *probs, uint32_t limit) + uint16_t *probs, uint32_t limit) { - uint32_t symbol = 1; + uint32_t symbol = 1; - do { - if (rc_bit(rc, &probs[symbol])) - symbol = (symbol << 1) + 1; - else - symbol <<= 1; - } while (symbol < limit); + do { + if (rc_bit(rc, &probs[symbol])) + symbol = (symbol << 1) + 1; + else + symbol <<= 1; + } while (symbol < limit); - return symbol; + return symbol; } /* Decode a bittree starting from the least significant bit. */ static __always_inline void rc_bittree_reverse(struct rc_dec *rc, - uint16_t *probs, - uint32_t *dest, uint32_t limit) + uint16_t *probs, + uint32_t *dest, uint32_t limit) { - uint32_t symbol = 1; - uint32_t i = 0; + uint32_t symbol = 1; + uint32_t i = 0; - do { - if (rc_bit(rc, &probs[symbol])) { - symbol = (symbol << 1) + 1; - *dest += 1 << i; - } else { - symbol <<= 1; - } - } while (++i < limit); + do { + if (rc_bit(rc, &probs[symbol])) { + symbol = (symbol << 1) + 1; + *dest += 1 << i; + } else { + symbol <<= 1; + } + } while (++i < limit); } /* Decode direct bits (fixed fifty-fifty probability) */ static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit) { - uint32_t mask; + uint32_t mask; - do { - rc_normalize(rc); - rc->range >>= 1; - rc->code -= rc->range; - mask = (uint32_t)0 - (rc->code >> 31); - rc->code += rc->range & mask; - *dest = (*dest << 1) + (mask + 1); - } while (--limit > 0); + do { + rc_normalize(rc); + rc->range >>= 1; + rc->code -= rc->range; + mask = (uint32_t)0 - (rc->code >> 31); + rc->code += rc->range & mask; + *dest = (*dest << 1) + (mask + 1); + } while (--limit > 0); } /******** @@ -571,114 +571,114 @@ static inline void rc_direct(struct rc_dec *rc, uint32_t *dest, uint32_t limit) /* Get pointer to literal coder probability array. */ static uint16_t *lzma_literal_probs(struct xz_dec_lzma2 *s) { - uint32_t prev_byte = dict_get(&s->dict, 0); - uint32_t low = prev_byte >> (8 - s->lzma.lc); - uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; - return s->lzma.literal[low + high]; + uint32_t prev_byte = dict_get(&s->dict, 0); + uint32_t low = prev_byte >> (8 - s->lzma.lc); + uint32_t high = (s->dict.pos & s->lzma.literal_pos_mask) << s->lzma.lc; + return s->lzma.literal[low + high]; } /* Decode a literal (one 8-bit byte) */ static void lzma_literal(struct xz_dec_lzma2 *s) { - uint16_t *probs; - uint32_t symbol; - uint32_t match_byte; - uint32_t match_bit; - uint32_t offset; - uint32_t i; + uint16_t *probs; + uint32_t symbol; + uint32_t match_byte; + uint32_t match_bit; + uint32_t offset; + uint32_t i; - probs = lzma_literal_probs(s); + probs = lzma_literal_probs(s); - if (lzma_state_is_literal(s->lzma.state)) { - symbol = rc_bittree(&s->rc, probs, 0x100); - } else { - symbol = 1; - match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; - offset = 0x100; + if (lzma_state_is_literal(s->lzma.state)) { + symbol = rc_bittree(&s->rc, probs, 0x100); + } else { + symbol = 1; + match_byte = dict_get(&s->dict, s->lzma.rep0) << 1; + offset = 0x100; - do { - match_bit = match_byte & offset; - match_byte <<= 1; - i = offset + match_bit + symbol; + do { + match_bit = match_byte & offset; + match_byte <<= 1; + i = offset + match_bit + symbol; - if (rc_bit(&s->rc, &probs[i])) { - symbol = (symbol << 1) + 1; - offset &= match_bit; - } else { - symbol <<= 1; - offset &= ~match_bit; - } - } while (symbol < 0x100); - } + if (rc_bit(&s->rc, &probs[i])) { + symbol = (symbol << 1) + 1; + offset &= match_bit; + } else { + symbol <<= 1; + offset &= ~match_bit; + } + } while (symbol < 0x100); + } - dict_put(&s->dict, (uint8_t)symbol); - lzma_state_literal(&s->lzma.state); + dict_put(&s->dict, (uint8_t)symbol); + lzma_state_literal(&s->lzma.state); } /* Decode the length of the match into s->lzma.len. */ static void lzma_len(struct xz_dec_lzma2 *s, struct lzma_len_dec *l, - uint32_t pos_state) + uint32_t pos_state) { - uint16_t *probs; - uint32_t limit; + uint16_t *probs; + uint32_t limit; - if (!rc_bit(&s->rc, &l->choice)) { - probs = l->low[pos_state]; - limit = LEN_LOW_SYMBOLS; - s->lzma.len = MATCH_LEN_MIN; - } else { - if (!rc_bit(&s->rc, &l->choice2)) { - probs = l->mid[pos_state]; - limit = LEN_MID_SYMBOLS; - s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; - } else { - probs = l->high; - limit = LEN_HIGH_SYMBOLS; - s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS - + LEN_MID_SYMBOLS; - } - } + if (!rc_bit(&s->rc, &l->choice)) { + probs = l->low[pos_state]; + limit = LEN_LOW_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN; + } else { + if (!rc_bit(&s->rc, &l->choice2)) { + probs = l->mid[pos_state]; + limit = LEN_MID_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS; + } else { + probs = l->high; + limit = LEN_HIGH_SYMBOLS; + s->lzma.len = MATCH_LEN_MIN + LEN_LOW_SYMBOLS + + LEN_MID_SYMBOLS; + } + } - s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; + s->lzma.len += rc_bittree(&s->rc, probs, limit) - limit; } /* Decode a match. The distance will be stored in s->lzma.rep0. */ static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) { - uint16_t *probs; - uint32_t dist_slot; - uint32_t limit; + uint16_t *probs; + uint32_t dist_slot; + uint32_t limit; - lzma_state_match(&s->lzma.state); + lzma_state_match(&s->lzma.state); - s->lzma.rep3 = s->lzma.rep2; - s->lzma.rep2 = s->lzma.rep1; - s->lzma.rep1 = s->lzma.rep0; + s->lzma.rep3 = s->lzma.rep2; + s->lzma.rep2 = s->lzma.rep1; + s->lzma.rep1 = s->lzma.rep0; - lzma_len(s, &s->lzma.match_len_dec, pos_state); + lzma_len(s, &s->lzma.match_len_dec, pos_state); - probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; - dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; + probs = s->lzma.dist_slot[lzma_get_dist_state(s->lzma.len)]; + dist_slot = rc_bittree(&s->rc, probs, DIST_SLOTS) - DIST_SLOTS; - if (dist_slot < DIST_MODEL_START) { - s->lzma.rep0 = dist_slot; - } else { - limit = (dist_slot >> 1) - 1; - s->lzma.rep0 = 2 + (dist_slot & 1); + if (dist_slot < DIST_MODEL_START) { + s->lzma.rep0 = dist_slot; + } else { + limit = (dist_slot >> 1) - 1; + s->lzma.rep0 = 2 + (dist_slot & 1); - if (dist_slot < DIST_MODEL_END) { - s->lzma.rep0 <<= limit; - probs = s->lzma.dist_special + s->lzma.rep0 - - dist_slot - 1; - rc_bittree_reverse(&s->rc, probs, - &s->lzma.rep0, limit); - } else { - rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); - s->lzma.rep0 <<= ALIGN_BITS; - rc_bittree_reverse(&s->rc, s->lzma.dist_align, - &s->lzma.rep0, ALIGN_BITS); - } - } + if (dist_slot < DIST_MODEL_END) { + s->lzma.rep0 <<= limit; + probs = s->lzma.dist_special + s->lzma.rep0 + - dist_slot - 1; + rc_bittree_reverse(&s->rc, probs, + &s->lzma.rep0, limit); + } else { + rc_direct(&s->rc, &s->lzma.rep0, limit - ALIGN_BITS); + s->lzma.rep0 <<= ALIGN_BITS; + rc_bittree_reverse(&s->rc, s->lzma.dist_align, + &s->lzma.rep0, ALIGN_BITS); + } + } } /* @@ -687,77 +687,77 @@ static void lzma_match(struct xz_dec_lzma2 *s, uint32_t pos_state) */ static void lzma_rep_match(struct xz_dec_lzma2 *s, uint32_t pos_state) { - uint32_t tmp; + uint32_t tmp; - if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) { - if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[ - s->lzma.state][pos_state])) { - lzma_state_short_rep(&s->lzma.state); - s->lzma.len = 1; - return; - } - } else { - if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) { - tmp = s->lzma.rep1; - } else { - if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) { - tmp = s->lzma.rep2; - } else { - tmp = s->lzma.rep3; - s->lzma.rep3 = s->lzma.rep2; - } + if (!rc_bit(&s->rc, &s->lzma.is_rep0[s->lzma.state])) { + if (!rc_bit(&s->rc, &s->lzma.is_rep0_long[ + s->lzma.state][pos_state])) { + lzma_state_short_rep(&s->lzma.state); + s->lzma.len = 1; + return; + } + } else { + if (!rc_bit(&s->rc, &s->lzma.is_rep1[s->lzma.state])) { + tmp = s->lzma.rep1; + } else { + if (!rc_bit(&s->rc, &s->lzma.is_rep2[s->lzma.state])) { + tmp = s->lzma.rep2; + } else { + tmp = s->lzma.rep3; + s->lzma.rep3 = s->lzma.rep2; + } - s->lzma.rep2 = s->lzma.rep1; - } + s->lzma.rep2 = s->lzma.rep1; + } - s->lzma.rep1 = s->lzma.rep0; - s->lzma.rep0 = tmp; - } + s->lzma.rep1 = s->lzma.rep0; + s->lzma.rep0 = tmp; + } - lzma_state_long_rep(&s->lzma.state); - lzma_len(s, &s->lzma.rep_len_dec, pos_state); + lzma_state_long_rep(&s->lzma.state); + lzma_len(s, &s->lzma.rep_len_dec, pos_state); } /* LZMA decoder core */ static bool lzma_main(struct xz_dec_lzma2 *s) { - uint32_t pos_state; + uint32_t pos_state; - /* - * If the dictionary was reached during the previous call, try to - * finish the possibly pending repeat in the dictionary. - */ - if (dict_has_space(&s->dict) && s->lzma.len > 0) - dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); + /* + * If the dictionary was reached during the previous call, try to + * finish the possibly pending repeat in the dictionary. + */ + if (dict_has_space(&s->dict) && s->lzma.len > 0) + dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0); - /* - * Decode more LZMA symbols. One iteration may consume up to - * LZMA_IN_REQUIRED - 1 bytes. - */ - while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) { - pos_state = s->dict.pos & s->lzma.pos_mask; + /* + * Decode more LZMA symbols. One iteration may consume up to + * LZMA_IN_REQUIRED - 1 bytes. + */ + while (dict_has_space(&s->dict) && !rc_limit_exceeded(&s->rc)) { + pos_state = s->dict.pos & s->lzma.pos_mask; - if (!rc_bit(&s->rc, &s->lzma.is_match[ - s->lzma.state][pos_state])) { - lzma_literal(s); - } else { - if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) - lzma_rep_match(s, pos_state); - else - lzma_match(s, pos_state); + if (!rc_bit(&s->rc, &s->lzma.is_match[ + s->lzma.state][pos_state])) { + lzma_literal(s); + } else { + if (rc_bit(&s->rc, &s->lzma.is_rep[s->lzma.state])) + lzma_rep_match(s, pos_state); + else + lzma_match(s, pos_state); - if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) - return false; - } - } + if (!dict_repeat(&s->dict, &s->lzma.len, s->lzma.rep0)) + return false; + } + } - /* - * Having the range decoder always normalized when we are outside - * this function makes it easier to correctly handle end of the chunk. - */ - rc_normalize(&s->rc); + /* + * Having the range decoder always normalized when we are outside + * this function makes it easier to correctly handle end of the chunk. + */ + rc_normalize(&s->rc); - return true; + return true; } /* @@ -766,29 +766,29 @@ static bool lzma_main(struct xz_dec_lzma2 *s) */ static void lzma_reset(struct xz_dec_lzma2 *s) { - uint16_t *probs; - size_t i; + uint16_t *probs; + size_t i; - s->lzma.state = STATE_LIT_LIT; - s->lzma.rep0 = 0; - s->lzma.rep1 = 0; - s->lzma.rep2 = 0; - s->lzma.rep3 = 0; + s->lzma.state = STATE_LIT_LIT; + s->lzma.rep0 = 0; + s->lzma.rep1 = 0; + s->lzma.rep2 = 0; + s->lzma.rep3 = 0; - /* - * All probabilities are initialized to the same value. This hack - * makes the code smaller by avoiding a separate loop for each - * probability array. - * - * This could be optimized so that only that part of literal - * probabilities that are actually required. In the common case - * we would write 12 KiB less. - */ - probs = s->lzma.is_match[0]; - for (i = 0; i < PROBS_TOTAL; ++i) - probs[i] = RC_BIT_MODEL_TOTAL / 2; + /* + * All probabilities are initialized to the same value. This hack + * makes the code smaller by avoiding a separate loop for each + * probability array. + * + * This could be optimized so that only that part of literal + * probabilities that are actually required. In the common case + * we would write 12 KiB less. + */ + probs = s->lzma.is_match[0]; + for (i = 0; i < PROBS_TOTAL; ++i) + probs[i] = RC_BIT_MODEL_TOTAL / 2; - rc_reset(&s->rc); + rc_reset(&s->rc); } /* @@ -798,33 +798,33 @@ static void lzma_reset(struct xz_dec_lzma2 *s) */ static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props) { - if (props > (4 * 5 + 4) * 9 + 8) - return false; + if (props > (4 * 5 + 4) * 9 + 8) + return false; - s->lzma.pos_mask = 0; - while (props >= 9 * 5) { - props -= 9 * 5; - ++s->lzma.pos_mask; - } + s->lzma.pos_mask = 0; + while (props >= 9 * 5) { + props -= 9 * 5; + ++s->lzma.pos_mask; + } - s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1; + s->lzma.pos_mask = (1 << s->lzma.pos_mask) - 1; - s->lzma.literal_pos_mask = 0; - while (props >= 9) { - props -= 9; - ++s->lzma.literal_pos_mask; - } + s->lzma.literal_pos_mask = 0; + while (props >= 9) { + props -= 9; + ++s->lzma.literal_pos_mask; + } - s->lzma.lc = props; + s->lzma.lc = props; - if (s->lzma.lc + s->lzma.literal_pos_mask > 4) - return false; + if (s->lzma.lc + s->lzma.literal_pos_mask > 4) + return false; - s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1; + s->lzma.literal_pos_mask = (1 << s->lzma.literal_pos_mask) - 1; - lzma_reset(s); + lzma_reset(s); - return true; + return true; } /********* @@ -845,83 +845,83 @@ static bool lzma_props(struct xz_dec_lzma2 *s, uint8_t props) */ static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b) { - size_t in_avail; - uint32_t tmp; + size_t in_avail; + uint32_t tmp; - in_avail = b->in_size - b->in_pos; - if (s->temp.size > 0 || s->lzma2.compressed == 0) { - tmp = 2 * LZMA_IN_REQUIRED - s->temp.size; - if (tmp > s->lzma2.compressed - s->temp.size) - tmp = s->lzma2.compressed - s->temp.size; - if (tmp > in_avail) - tmp = in_avail; + in_avail = b->in_size - b->in_pos; + if (s->temp.size > 0 || s->lzma2.compressed == 0) { + tmp = 2 * LZMA_IN_REQUIRED - s->temp.size; + if (tmp > s->lzma2.compressed - s->temp.size) + tmp = s->lzma2.compressed - s->temp.size; + if (tmp > in_avail) + tmp = in_avail; - memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp); + memcpy(s->temp.buf + s->temp.size, b->in + b->in_pos, tmp); - if (s->temp.size + tmp == s->lzma2.compressed) { - memzero(s->temp.buf + s->temp.size + tmp, - sizeof(s->temp.buf) - - s->temp.size - tmp); - s->rc.in_limit = s->temp.size + tmp; - } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) { - s->temp.size += tmp; - b->in_pos += tmp; - return true; - } else { - s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED; - } + if (s->temp.size + tmp == s->lzma2.compressed) { + memzero(s->temp.buf + s->temp.size + tmp, + sizeof(s->temp.buf) + - s->temp.size - tmp); + s->rc.in_limit = s->temp.size + tmp; + } else if (s->temp.size + tmp < LZMA_IN_REQUIRED) { + s->temp.size += tmp; + b->in_pos += tmp; + return true; + } else { + s->rc.in_limit = s->temp.size + tmp - LZMA_IN_REQUIRED; + } - s->rc.in = s->temp.buf; - s->rc.in_pos = 0; + s->rc.in = s->temp.buf; + s->rc.in_pos = 0; - if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp) - return false; + if (!lzma_main(s) || s->rc.in_pos > s->temp.size + tmp) + return false; - s->lzma2.compressed -= s->rc.in_pos; + s->lzma2.compressed -= s->rc.in_pos; - if (s->rc.in_pos < s->temp.size) { - s->temp.size -= s->rc.in_pos; - memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, - s->temp.size); - return true; - } + if (s->rc.in_pos < s->temp.size) { + s->temp.size -= s->rc.in_pos; + memmove(s->temp.buf, s->temp.buf + s->rc.in_pos, + s->temp.size); + return true; + } - b->in_pos += s->rc.in_pos - s->temp.size; - s->temp.size = 0; - } + b->in_pos += s->rc.in_pos - s->temp.size; + s->temp.size = 0; + } - in_avail = b->in_size - b->in_pos; - if (in_avail >= LZMA_IN_REQUIRED) { - s->rc.in = b->in; - s->rc.in_pos = b->in_pos; + in_avail = b->in_size - b->in_pos; + if (in_avail >= LZMA_IN_REQUIRED) { + s->rc.in = b->in; + s->rc.in_pos = b->in_pos; - if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED) - s->rc.in_limit = b->in_pos + s->lzma2.compressed; - else - s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED; + if (in_avail >= s->lzma2.compressed + LZMA_IN_REQUIRED) + s->rc.in_limit = b->in_pos + s->lzma2.compressed; + else + s->rc.in_limit = b->in_size - LZMA_IN_REQUIRED; - if (!lzma_main(s)) - return false; + if (!lzma_main(s)) + return false; - in_avail = s->rc.in_pos - b->in_pos; - if (in_avail > s->lzma2.compressed) - return false; + in_avail = s->rc.in_pos - b->in_pos; + if (in_avail > s->lzma2.compressed) + return false; - s->lzma2.compressed -= in_avail; - b->in_pos = s->rc.in_pos; - } + s->lzma2.compressed -= in_avail; + b->in_pos = s->rc.in_pos; + } - in_avail = b->in_size - b->in_pos; - if (in_avail < LZMA_IN_REQUIRED) { - if (in_avail > s->lzma2.compressed) - in_avail = s->lzma2.compressed; + in_avail = b->in_size - b->in_pos; + if (in_avail < LZMA_IN_REQUIRED) { + if (in_avail > s->lzma2.compressed) + in_avail = s->lzma2.compressed; - memcpy(s->temp.buf, b->in + b->in_pos, in_avail); - s->temp.size = in_avail; - b->in_pos += in_avail; - } + memcpy(s->temp.buf, b->in + b->in_pos, in_avail); + s->temp.size = in_avail; + b->in_pos += in_avail; + } - return true; + return true; } /* @@ -929,243 +929,243 @@ static bool lzma2_lzma(struct xz_dec_lzma2 *s, struct xz_buf *b) * decoding or copying of uncompressed chunks to other functions. */ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, - struct xz_buf *b) + struct xz_buf *b) { - uint32_t tmp; + uint32_t tmp; - while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) { - switch (s->lzma2.sequence) { - case SEQ_CONTROL: - /* - * LZMA2 control byte - * - * Exact values: - * 0x00 End marker - * 0x01 Dictionary reset followed by - * an uncompressed chunk - * 0x02 Uncompressed chunk (no dictionary reset) - * - * Highest three bits (s->control & 0xE0): - * 0xE0 Dictionary reset, new properties and state - * reset, followed by LZMA compressed chunk - * 0xC0 New properties and state reset, followed - * by LZMA compressed chunk (no dictionary - * reset) - * 0xA0 State reset using old properties, - * followed by LZMA compressed chunk (no - * dictionary reset) - * 0x80 LZMA chunk (no dictionary or state reset) - * - * For LZMA compressed chunks, the lowest five bits - * (s->control & 1F) are the highest bits of the - * uncompressed size (bits 16-20). - * - * A new LZMA2 stream must begin with a dictionary - * reset. The first LZMA chunk must set new - * properties and reset the LZMA state. - * - * Values that don't match anything described above - * are invalid and we return XZ_DATA_ERROR. - */ - tmp = b->in[b->in_pos++]; + while (b->in_pos < b->in_size || s->lzma2.sequence == SEQ_LZMA_RUN) { + switch (s->lzma2.sequence) { + case SEQ_CONTROL: + /* + * LZMA2 control byte + * + * Exact values: + * 0x00 End marker + * 0x01 Dictionary reset followed by + * an uncompressed chunk + * 0x02 Uncompressed chunk (no dictionary reset) + * + * Highest three bits (s->control & 0xE0): + * 0xE0 Dictionary reset, new properties and state + * reset, followed by LZMA compressed chunk + * 0xC0 New properties and state reset, followed + * by LZMA compressed chunk (no dictionary + * reset) + * 0xA0 State reset using old properties, + * followed by LZMA compressed chunk (no + * dictionary reset) + * 0x80 LZMA chunk (no dictionary or state reset) + * + * For LZMA compressed chunks, the lowest five bits + * (s->control & 1F) are the highest bits of the + * uncompressed size (bits 16-20). + * + * A new LZMA2 stream must begin with a dictionary + * reset. The first LZMA chunk must set new + * properties and reset the LZMA state. + * + * Values that don't match anything described above + * are invalid and we return XZ_DATA_ERROR. + */ + tmp = b->in[b->in_pos++]; - if (tmp == 0x00) - return XZ_STREAM_END; + if (tmp == 0x00) + return XZ_STREAM_END; - if (tmp >= 0xE0 || tmp == 0x01) { - s->lzma2.need_props = true; - s->lzma2.need_dict_reset = false; - dict_reset(&s->dict, b); - } else if (s->lzma2.need_dict_reset) { - return XZ_DATA_ERROR; - } + if (tmp >= 0xE0 || tmp == 0x01) { + s->lzma2.need_props = true; + s->lzma2.need_dict_reset = false; + dict_reset(&s->dict, b); + } else if (s->lzma2.need_dict_reset) { + return XZ_DATA_ERROR; + } - if (tmp >= 0x80) { - s->lzma2.uncompressed = (tmp & 0x1F) << 16; - s->lzma2.sequence = SEQ_UNCOMPRESSED_1; + if (tmp >= 0x80) { + s->lzma2.uncompressed = (tmp & 0x1F) << 16; + s->lzma2.sequence = SEQ_UNCOMPRESSED_1; - if (tmp >= 0xC0) { - /* - * When there are new properties, - * state reset is done at - * SEQ_PROPERTIES. - */ - s->lzma2.need_props = false; - s->lzma2.next_sequence - = SEQ_PROPERTIES; + if (tmp >= 0xC0) { + /* + * When there are new properties, + * state reset is done at + * SEQ_PROPERTIES. + */ + s->lzma2.need_props = false; + s->lzma2.next_sequence + = SEQ_PROPERTIES; - } else if (s->lzma2.need_props) { - return XZ_DATA_ERROR; + } else if (s->lzma2.need_props) { + return XZ_DATA_ERROR; - } else { - s->lzma2.next_sequence - = SEQ_LZMA_PREPARE; - if (tmp >= 0xA0) - lzma_reset(s); - } - } else { - if (tmp > 0x02) - return XZ_DATA_ERROR; + } else { + s->lzma2.next_sequence + = SEQ_LZMA_PREPARE; + if (tmp >= 0xA0) + lzma_reset(s); + } + } else { + if (tmp > 0x02) + return XZ_DATA_ERROR; - s->lzma2.sequence = SEQ_COMPRESSED_0; - s->lzma2.next_sequence = SEQ_COPY; - } + s->lzma2.sequence = SEQ_COMPRESSED_0; + s->lzma2.next_sequence = SEQ_COPY; + } - break; + break; - case SEQ_UNCOMPRESSED_1: - s->lzma2.uncompressed - += (uint32_t)b->in[b->in_pos++] << 8; - s->lzma2.sequence = SEQ_UNCOMPRESSED_2; - break; + case SEQ_UNCOMPRESSED_1: + s->lzma2.uncompressed + += (uint32_t)b->in[b->in_pos++] << 8; + s->lzma2.sequence = SEQ_UNCOMPRESSED_2; + break; - case SEQ_UNCOMPRESSED_2: - s->lzma2.uncompressed - += (uint32_t)b->in[b->in_pos++] + 1; - s->lzma2.sequence = SEQ_COMPRESSED_0; - break; + case SEQ_UNCOMPRESSED_2: + s->lzma2.uncompressed + += (uint32_t)b->in[b->in_pos++] + 1; + s->lzma2.sequence = SEQ_COMPRESSED_0; + break; - case SEQ_COMPRESSED_0: - s->lzma2.compressed - = (uint32_t)b->in[b->in_pos++] << 8; - s->lzma2.sequence = SEQ_COMPRESSED_1; - break; + case SEQ_COMPRESSED_0: + s->lzma2.compressed + = (uint32_t)b->in[b->in_pos++] << 8; + s->lzma2.sequence = SEQ_COMPRESSED_1; + break; - case SEQ_COMPRESSED_1: - s->lzma2.compressed - += (uint32_t)b->in[b->in_pos++] + 1; - s->lzma2.sequence = s->lzma2.next_sequence; - break; + case SEQ_COMPRESSED_1: + s->lzma2.compressed + += (uint32_t)b->in[b->in_pos++] + 1; + s->lzma2.sequence = s->lzma2.next_sequence; + break; - case SEQ_PROPERTIES: - if (!lzma_props(s, b->in[b->in_pos++])) - return XZ_DATA_ERROR; + case SEQ_PROPERTIES: + if (!lzma_props(s, b->in[b->in_pos++])) + return XZ_DATA_ERROR; - s->lzma2.sequence = SEQ_LZMA_PREPARE; + s->lzma2.sequence = SEQ_LZMA_PREPARE; - case SEQ_LZMA_PREPARE: - if (s->lzma2.compressed < RC_INIT_BYTES) - return XZ_DATA_ERROR; + case SEQ_LZMA_PREPARE: + if (s->lzma2.compressed < RC_INIT_BYTES) + return XZ_DATA_ERROR; - if (!rc_read_init(&s->rc, b)) - return XZ_OK; + if (!rc_read_init(&s->rc, b)) + return XZ_OK; - s->lzma2.compressed -= RC_INIT_BYTES; - s->lzma2.sequence = SEQ_LZMA_RUN; + s->lzma2.compressed -= RC_INIT_BYTES; + s->lzma2.sequence = SEQ_LZMA_RUN; - case SEQ_LZMA_RUN: - /* - * Set dictionary limit to indicate how much we want - * to be encoded at maximum. Decode new data into the - * dictionary. Flush the new data from dictionary to - * b->out. Check if we finished decoding this chunk. - * In case the dictionary got full but we didn't fill - * the output buffer yet, we may run this loop - * multiple times without changing s->lzma2.sequence. - */ - dict_limit(&s->dict, min_t(size_t, - b->out_size - b->out_pos, - s->lzma2.uncompressed)); - if (!lzma2_lzma(s, b)) - return XZ_DATA_ERROR; + case SEQ_LZMA_RUN: + /* + * Set dictionary limit to indicate how much we want + * to be encoded at maximum. Decode new data into the + * dictionary. Flush the new data from dictionary to + * b->out. Check if we finished decoding this chunk. + * In case the dictionary got full but we didn't fill + * the output buffer yet, we may run this loop + * multiple times without changing s->lzma2.sequence. + */ + dict_limit(&s->dict, min_t(size_t, + b->out_size - b->out_pos, + s->lzma2.uncompressed)); + if (!lzma2_lzma(s, b)) + return XZ_DATA_ERROR; - s->lzma2.uncompressed -= dict_flush(&s->dict, b); + s->lzma2.uncompressed -= dict_flush(&s->dict, b); - if (s->lzma2.uncompressed == 0) { - if (s->lzma2.compressed > 0 || s->lzma.len > 0 - || !rc_is_finished(&s->rc)) - return XZ_DATA_ERROR; + if (s->lzma2.uncompressed == 0) { + if (s->lzma2.compressed > 0 || s->lzma.len > 0 + || !rc_is_finished(&s->rc)) + return XZ_DATA_ERROR; - rc_reset(&s->rc); - s->lzma2.sequence = SEQ_CONTROL; + rc_reset(&s->rc); + s->lzma2.sequence = SEQ_CONTROL; - } else if (b->out_pos == b->out_size - || (b->in_pos == b->in_size - && s->temp.size - < s->lzma2.compressed)) { - return XZ_OK; - } + } else if (b->out_pos == b->out_size + || (b->in_pos == b->in_size + && s->temp.size + < s->lzma2.compressed)) { + return XZ_OK; + } - break; + break; - case SEQ_COPY: - dict_uncompressed(&s->dict, b, &s->lzma2.compressed); - if (s->lzma2.compressed > 0) - return XZ_OK; + case SEQ_COPY: + dict_uncompressed(&s->dict, b, &s->lzma2.compressed); + if (s->lzma2.compressed > 0) + return XZ_OK; - s->lzma2.sequence = SEQ_CONTROL; - break; - } - } + s->lzma2.sequence = SEQ_CONTROL; + break; + } + } - return XZ_OK; + return XZ_OK; } XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, - uint32_t dict_max) + uint32_t dict_max) { - struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL); - if (s == NULL) - return NULL; + struct xz_dec_lzma2 *s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) + return NULL; - s->dict.mode = mode; - s->dict.size_max = dict_max; + s->dict.mode = mode; + s->dict.size_max = dict_max; - if (DEC_IS_PREALLOC(mode)) { - s->dict.buf = vmalloc(dict_max); - if (s->dict.buf == NULL) { - kfree(s); - return NULL; - } - } else if (DEC_IS_DYNALLOC(mode)) { - s->dict.buf = NULL; - s->dict.allocated = 0; - } + if (DEC_IS_PREALLOC(mode)) { + s->dict.buf = vmalloc(dict_max); + if (s->dict.buf == NULL) { + kfree(s); + return NULL; + } + } else if (DEC_IS_DYNALLOC(mode)) { + s->dict.buf = NULL; + s->dict.allocated = 0; + } - return s; + return s; } XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, uint8_t props) { - /* This limits dictionary size to 3 GiB to keep parsing simpler. */ - if (props > 39) - return XZ_OPTIONS_ERROR; + /* This limits dictionary size to 3 GiB to keep parsing simpler. */ + if (props > 39) + return XZ_OPTIONS_ERROR; - s->dict.size = 2 + (props & 1); - s->dict.size <<= (props >> 1) + 11; + s->dict.size = 2 + (props & 1); + s->dict.size <<= (props >> 1) + 11; - if (DEC_IS_MULTI(s->dict.mode)) { - if (s->dict.size > s->dict.size_max) - return XZ_MEMLIMIT_ERROR; + if (DEC_IS_MULTI(s->dict.mode)) { + if (s->dict.size > s->dict.size_max) + return XZ_MEMLIMIT_ERROR; - s->dict.end = s->dict.size; + s->dict.end = s->dict.size; - if (DEC_IS_DYNALLOC(s->dict.mode)) { - if (s->dict.allocated < s->dict.size) { - vfree(s->dict.buf); - s->dict.buf = vmalloc(s->dict.size); - if (s->dict.buf == NULL) { - s->dict.allocated = 0; - return XZ_MEM_ERROR; - } - } - } - } + if (DEC_IS_DYNALLOC(s->dict.mode)) { + if (s->dict.allocated < s->dict.size) { + vfree(s->dict.buf); + s->dict.buf = vmalloc(s->dict.size); + if (s->dict.buf == NULL) { + s->dict.allocated = 0; + return XZ_MEM_ERROR; + } + } + } + } - s->lzma.len = 0; + s->lzma.len = 0; - s->lzma2.sequence = SEQ_CONTROL; - s->lzma2.need_dict_reset = true; + s->lzma2.sequence = SEQ_CONTROL; + s->lzma2.need_dict_reset = true; - s->temp.size = 0; + s->temp.size = 0; - return XZ_OK; + return XZ_OK; } XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s) { - if (DEC_IS_MULTI(s->dict.mode)) - vfree(s->dict.buf); + if (DEC_IS_MULTI(s->dict.mode)) + vfree(s->dict.buf); - kfree(s); + kfree(s); } diff --git a/native/jni/external/xz-embedded/xz_dec_stream.c b/native/jni/external/xz-embedded/xz_dec_stream.c index d6525506a..a02e56400 100644 --- a/native/jni/external/xz-embedded/xz_dec_stream.c +++ b/native/jni/external/xz-embedded/xz_dec_stream.c @@ -18,144 +18,144 @@ /* Hash used to validate the Index field */ struct xz_dec_hash { - vli_type unpadded; - vli_type uncompressed; - uint32_t crc32; + vli_type unpadded; + vli_type uncompressed; + uint32_t crc32; }; struct xz_dec { - /* Position in dec_main() */ - enum { - SEQ_STREAM_HEADER, - SEQ_BLOCK_START, - SEQ_BLOCK_HEADER, - SEQ_BLOCK_UNCOMPRESS, - SEQ_BLOCK_PADDING, - SEQ_BLOCK_CHECK, - SEQ_INDEX, - SEQ_INDEX_PADDING, - SEQ_INDEX_CRC32, - SEQ_STREAM_FOOTER - } sequence; + /* Position in dec_main() */ + enum { + SEQ_STREAM_HEADER, + SEQ_BLOCK_START, + SEQ_BLOCK_HEADER, + SEQ_BLOCK_UNCOMPRESS, + SEQ_BLOCK_PADDING, + SEQ_BLOCK_CHECK, + SEQ_INDEX, + SEQ_INDEX_PADDING, + SEQ_INDEX_CRC32, + SEQ_STREAM_FOOTER + } sequence; - /* Position in variable-length integers and Check fields */ - uint32_t pos; + /* Position in variable-length integers and Check fields */ + uint32_t pos; - /* Variable-length integer decoded by dec_vli() */ - vli_type vli; + /* Variable-length integer decoded by dec_vli() */ + vli_type vli; - /* Saved in_pos and out_pos */ - size_t in_start; - size_t out_start; + /* Saved in_pos and out_pos */ + size_t in_start; + size_t out_start; #ifdef XZ_USE_CRC64 - /* CRC32 or CRC64 value in Block or CRC32 value in Index */ - uint64_t crc; + /* CRC32 or CRC64 value in Block or CRC32 value in Index */ + uint64_t crc; #else - /* CRC32 value in Block or Index */ - uint32_t crc; + /* CRC32 value in Block or Index */ + uint32_t crc; #endif - /* Type of the integrity check calculated from uncompressed data */ - enum xz_check check_type; + /* Type of the integrity check calculated from uncompressed data */ + enum xz_check check_type; - /* Operation mode */ - enum xz_mode mode; + /* Operation mode */ + enum xz_mode mode; - /* - * True if the next call to xz_dec_run() is allowed to return - * XZ_BUF_ERROR. - */ - bool allow_buf_error; + /* + * True if the next call to xz_dec_run() is allowed to return + * XZ_BUF_ERROR. + */ + bool allow_buf_error; - /* Information stored in Block Header */ - struct { - /* - * Value stored in the Compressed Size field, or - * VLI_UNKNOWN if Compressed Size is not present. - */ - vli_type compressed; + /* Information stored in Block Header */ + struct { + /* + * Value stored in the Compressed Size field, or + * VLI_UNKNOWN if Compressed Size is not present. + */ + vli_type compressed; - /* - * Value stored in the Uncompressed Size field, or - * VLI_UNKNOWN if Uncompressed Size is not present. - */ - vli_type uncompressed; + /* + * Value stored in the Uncompressed Size field, or + * VLI_UNKNOWN if Uncompressed Size is not present. + */ + vli_type uncompressed; - /* Size of the Block Header field */ - uint32_t size; - } block_header; + /* Size of the Block Header field */ + uint32_t size; + } block_header; - /* Information collected when decoding Blocks */ - struct { - /* Observed compressed size of the current Block */ - vli_type compressed; + /* Information collected when decoding Blocks */ + struct { + /* Observed compressed size of the current Block */ + vli_type compressed; - /* Observed uncompressed size of the current Block */ - vli_type uncompressed; + /* Observed uncompressed size of the current Block */ + vli_type uncompressed; - /* Number of Blocks decoded so far */ - vli_type count; + /* Number of Blocks decoded so far */ + vli_type count; - /* - * Hash calculated from the Block sizes. This is used to - * validate the Index field. - */ - struct xz_dec_hash hash; - } block; + /* + * Hash calculated from the Block sizes. This is used to + * validate the Index field. + */ + struct xz_dec_hash hash; + } block; - /* Variables needed when verifying the Index field */ - struct { - /* Position in dec_index() */ - enum { - SEQ_INDEX_COUNT, - SEQ_INDEX_UNPADDED, - SEQ_INDEX_UNCOMPRESSED - } sequence; + /* Variables needed when verifying the Index field */ + struct { + /* Position in dec_index() */ + enum { + SEQ_INDEX_COUNT, + SEQ_INDEX_UNPADDED, + SEQ_INDEX_UNCOMPRESSED + } sequence; - /* Size of the Index in bytes */ - vli_type size; + /* Size of the Index in bytes */ + vli_type size; - /* Number of Records (matches block.count in valid files) */ - vli_type count; + /* Number of Records (matches block.count in valid files) */ + vli_type count; - /* - * Hash calculated from the Records (matches block.hash in - * valid files). - */ - struct xz_dec_hash hash; - } index; + /* + * Hash calculated from the Records (matches block.hash in + * valid files). + */ + struct xz_dec_hash hash; + } index; - /* - * Temporary buffer needed to hold Stream Header, Block Header, - * and Stream Footer. The Block Header is the biggest (1 KiB) - * so we reserve space according to that. buf[] has to be aligned - * to a multiple of four bytes; the size_t variables before it - * should guarantee this. - */ - struct { - size_t pos; - size_t size; - uint8_t buf[1024]; - } temp; + /* + * Temporary buffer needed to hold Stream Header, Block Header, + * and Stream Footer. The Block Header is the biggest (1 KiB) + * so we reserve space according to that. buf[] has to be aligned + * to a multiple of four bytes; the size_t variables before it + * should guarantee this. + */ + struct { + size_t pos; + size_t size; + uint8_t buf[1024]; + } temp; - struct xz_dec_lzma2 *lzma2; + struct xz_dec_lzma2 *lzma2; #ifdef XZ_DEC_BCJ - struct xz_dec_bcj *bcj; - bool bcj_active; + struct xz_dec_bcj *bcj; + bool bcj_active; #endif }; #ifdef XZ_DEC_ANY_CHECK /* Sizes of the Check field with different Check IDs */ static const uint8_t check_sizes[16] = { - 0, - 4, 4, 4, - 8, 8, 8, - 16, 16, 16, - 32, 32, 32, - 64, 64, 64 + 0, + 4, 4, 4, + 8, 8, 8, + 16, 16, 16, + 32, 32, 32, + 64, 64, 64 }; #endif @@ -167,51 +167,51 @@ static const uint8_t check_sizes[16] = { */ static bool fill_temp(struct xz_dec *s, struct xz_buf *b) { - size_t copy_size = min_t(size_t, - b->in_size - b->in_pos, s->temp.size - s->temp.pos); + size_t copy_size = min_t(size_t, + b->in_size - b->in_pos, s->temp.size - s->temp.pos); - memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size); - b->in_pos += copy_size; - s->temp.pos += copy_size; + memcpy(s->temp.buf + s->temp.pos, b->in + b->in_pos, copy_size); + b->in_pos += copy_size; + s->temp.pos += copy_size; - if (s->temp.pos == s->temp.size) { - s->temp.pos = 0; - return true; - } + if (s->temp.pos == s->temp.size) { + s->temp.pos = 0; + return true; + } - return false; + return false; } /* Decode a variable-length integer (little-endian base-128 encoding) */ static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in, - size_t *in_pos, size_t in_size) + size_t *in_pos, size_t in_size) { - uint8_t byte; + uint8_t byte; - if (s->pos == 0) - s->vli = 0; + if (s->pos == 0) + s->vli = 0; - while (*in_pos < in_size) { - byte = in[*in_pos]; - ++*in_pos; + while (*in_pos < in_size) { + byte = in[*in_pos]; + ++*in_pos; - s->vli |= (vli_type)(byte & 0x7F) << s->pos; + s->vli |= (vli_type)(byte & 0x7F) << s->pos; - if ((byte & 0x80) == 0) { - /* Don't allow non-minimal encodings. */ - if (byte == 0 && s->pos != 0) - return XZ_DATA_ERROR; + if ((byte & 0x80) == 0) { + /* Don't allow non-minimal encodings. */ + if (byte == 0 && s->pos != 0) + return XZ_DATA_ERROR; - s->pos = 0; - return XZ_STREAM_END; - } + s->pos = 0; + return XZ_STREAM_END; + } - s->pos += 7; - if (s->pos == 7 * VLI_BYTES_MAX) - return XZ_DATA_ERROR; - } + s->pos += 7; + if (s->pos == 7 * VLI_BYTES_MAX) + return XZ_DATA_ERROR; + } - return XZ_OK; + return XZ_OK; } /* @@ -228,79 +228,79 @@ static enum xz_ret dec_vli(struct xz_dec *s, const uint8_t *in, */ static enum xz_ret dec_block(struct xz_dec *s, struct xz_buf *b) { - enum xz_ret ret; + enum xz_ret ret; - s->in_start = b->in_pos; - s->out_start = b->out_pos; + s->in_start = b->in_pos; + s->out_start = b->out_pos; #ifdef XZ_DEC_BCJ - if (s->bcj_active) - ret = xz_dec_bcj_run(s->bcj, s->lzma2, b); - else + if (s->bcj_active) + ret = xz_dec_bcj_run(s->bcj, s->lzma2, b); + else #endif - ret = xz_dec_lzma2_run(s->lzma2, b); + ret = xz_dec_lzma2_run(s->lzma2, b); - s->block.compressed += b->in_pos - s->in_start; - s->block.uncompressed += b->out_pos - s->out_start; + s->block.compressed += b->in_pos - s->in_start; + s->block.uncompressed += b->out_pos - s->out_start; - /* - * There is no need to separately check for VLI_UNKNOWN, since - * the observed sizes are always smaller than VLI_UNKNOWN. - */ - if (s->block.compressed > s->block_header.compressed - || s->block.uncompressed - > s->block_header.uncompressed) - return XZ_DATA_ERROR; + /* + * There is no need to separately check for VLI_UNKNOWN, since + * the observed sizes are always smaller than VLI_UNKNOWN. + */ + if (s->block.compressed > s->block_header.compressed + || s->block.uncompressed + > s->block_header.uncompressed) + return XZ_DATA_ERROR; - if (s->check_type == XZ_CHECK_CRC32) - s->crc = xz_crc32(b->out + s->out_start, - b->out_pos - s->out_start, s->crc); + if (s->check_type == XZ_CHECK_CRC32) + s->crc = xz_crc32(b->out + s->out_start, + b->out_pos - s->out_start, s->crc); #ifdef XZ_USE_CRC64 - else if (s->check_type == XZ_CHECK_CRC64) - s->crc = xz_crc64(b->out + s->out_start, - b->out_pos - s->out_start, s->crc); + else if (s->check_type == XZ_CHECK_CRC64) + s->crc = xz_crc64(b->out + s->out_start, + b->out_pos - s->out_start, s->crc); #endif - if (ret == XZ_STREAM_END) { - if (s->block_header.compressed != VLI_UNKNOWN - && s->block_header.compressed - != s->block.compressed) - return XZ_DATA_ERROR; + if (ret == XZ_STREAM_END) { + if (s->block_header.compressed != VLI_UNKNOWN + && s->block_header.compressed + != s->block.compressed) + return XZ_DATA_ERROR; - if (s->block_header.uncompressed != VLI_UNKNOWN - && s->block_header.uncompressed - != s->block.uncompressed) - return XZ_DATA_ERROR; + if (s->block_header.uncompressed != VLI_UNKNOWN + && s->block_header.uncompressed + != s->block.uncompressed) + return XZ_DATA_ERROR; - s->block.hash.unpadded += s->block_header.size - + s->block.compressed; + s->block.hash.unpadded += s->block_header.size + + s->block.compressed; #ifdef XZ_DEC_ANY_CHECK - s->block.hash.unpadded += check_sizes[s->check_type]; + s->block.hash.unpadded += check_sizes[s->check_type]; #else - if (s->check_type == XZ_CHECK_CRC32) - s->block.hash.unpadded += 4; - else if (IS_CRC64(s->check_type)) - s->block.hash.unpadded += 8; + if (s->check_type == XZ_CHECK_CRC32) + s->block.hash.unpadded += 4; + else if (IS_CRC64(s->check_type)) + s->block.hash.unpadded += 8; #endif - s->block.hash.uncompressed += s->block.uncompressed; - s->block.hash.crc32 = xz_crc32( - (const uint8_t *)&s->block.hash, - sizeof(s->block.hash), s->block.hash.crc32); + s->block.hash.uncompressed += s->block.uncompressed; + s->block.hash.crc32 = xz_crc32( + (const uint8_t *)&s->block.hash, + sizeof(s->block.hash), s->block.hash.crc32); - ++s->block.count; - } + ++s->block.count; + } - return ret; + return ret; } /* Update the Index size and the CRC32 value. */ static void index_update(struct xz_dec *s, const struct xz_buf *b) { - size_t in_used = b->in_pos - s->in_start; - s->index.size += in_used; - s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc); + size_t in_used = b->in_pos - s->in_start; + s->index.size += in_used; + s->crc = xz_crc32(b->in + s->in_start, in_used, s->crc); } /* @@ -313,48 +313,48 @@ static void index_update(struct xz_dec *s, const struct xz_buf *b) */ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) { - enum xz_ret ret; + enum xz_ret ret; - do { - ret = dec_vli(s, b->in, &b->in_pos, b->in_size); - if (ret != XZ_STREAM_END) { - index_update(s, b); - return ret; - } + do { + ret = dec_vli(s, b->in, &b->in_pos, b->in_size); + if (ret != XZ_STREAM_END) { + index_update(s, b); + return ret; + } - switch (s->index.sequence) { - case SEQ_INDEX_COUNT: - s->index.count = s->vli; + switch (s->index.sequence) { + case SEQ_INDEX_COUNT: + s->index.count = s->vli; - /* - * Validate that the Number of Records field - * indicates the same number of Records as - * there were Blocks in the Stream. - */ - if (s->index.count != s->block.count) - return XZ_DATA_ERROR; + /* + * Validate that the Number of Records field + * indicates the same number of Records as + * there were Blocks in the Stream. + */ + if (s->index.count != s->block.count) + return XZ_DATA_ERROR; - s->index.sequence = SEQ_INDEX_UNPADDED; - break; + s->index.sequence = SEQ_INDEX_UNPADDED; + break; - case SEQ_INDEX_UNPADDED: - s->index.hash.unpadded += s->vli; - s->index.sequence = SEQ_INDEX_UNCOMPRESSED; - break; + case SEQ_INDEX_UNPADDED: + s->index.hash.unpadded += s->vli; + s->index.sequence = SEQ_INDEX_UNCOMPRESSED; + break; - case SEQ_INDEX_UNCOMPRESSED: - s->index.hash.uncompressed += s->vli; - s->index.hash.crc32 = xz_crc32( - (const uint8_t *)&s->index.hash, - sizeof(s->index.hash), - s->index.hash.crc32); - --s->index.count; - s->index.sequence = SEQ_INDEX_UNPADDED; - break; - } - } while (s->index.count > 0); + case SEQ_INDEX_UNCOMPRESSED: + s->index.hash.uncompressed += s->vli; + s->index.hash.crc32 = xz_crc32( + (const uint8_t *)&s->index.hash, + sizeof(s->index.hash), + s->index.hash.crc32); + --s->index.count; + s->index.sequence = SEQ_INDEX_UNPADDED; + break; + } + } while (s->index.count > 0); - return XZ_STREAM_END; + return XZ_STREAM_END; } /* @@ -363,23 +363,23 @@ static enum xz_ret dec_index(struct xz_dec *s, struct xz_buf *b) * The "bits" argument allows using the same code for both CRC32 and CRC64. */ static enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b, - uint32_t bits) + uint32_t bits) { - do { - if (b->in_pos == b->in_size) - return XZ_OK; + do { + if (b->in_pos == b->in_size) + return XZ_OK; - if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++]) - return XZ_DATA_ERROR; + if (((s->crc >> s->pos) & 0xFF) != b->in[b->in_pos++]) + return XZ_DATA_ERROR; - s->pos += 8; + s->pos += 8; - } while (s->pos < bits); + } while (s->pos < bits); - s->crc = 0; - s->pos = 0; + s->crc = 0; + s->pos = 0; - return XZ_STREAM_END; + return XZ_STREAM_END; } #ifdef XZ_DEC_ANY_CHECK @@ -389,347 +389,347 @@ static enum xz_ret crc_validate(struct xz_dec *s, struct xz_buf *b, */ static bool check_skip(struct xz_dec *s, struct xz_buf *b) { - while (s->pos < check_sizes[s->check_type]) { - if (b->in_pos == b->in_size) - return false; + while (s->pos < check_sizes[s->check_type]) { + if (b->in_pos == b->in_size) + return false; - ++b->in_pos; - ++s->pos; - } + ++b->in_pos; + ++s->pos; + } - s->pos = 0; + s->pos = 0; - return true; + return true; } #endif /* Decode the Stream Header field (the first 12 bytes of the .xz Stream). */ static enum xz_ret dec_stream_header(struct xz_dec *s) { - if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE)) - return XZ_FORMAT_ERROR; + if (!memeq(s->temp.buf, HEADER_MAGIC, HEADER_MAGIC_SIZE)) + return XZ_FORMAT_ERROR; - if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0) - != get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2)) - return XZ_DATA_ERROR; + if (xz_crc32(s->temp.buf + HEADER_MAGIC_SIZE, 2, 0) + != get_le32(s->temp.buf + HEADER_MAGIC_SIZE + 2)) + return XZ_DATA_ERROR; - if (s->temp.buf[HEADER_MAGIC_SIZE] != 0) - return XZ_OPTIONS_ERROR; + if (s->temp.buf[HEADER_MAGIC_SIZE] != 0) + return XZ_OPTIONS_ERROR; - /* - * Of integrity checks, we support none (Check ID = 0), - * CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4). - * However, if XZ_DEC_ANY_CHECK is defined, we will accept other - * check types too, but then the check won't be verified and - * a warning (XZ_UNSUPPORTED_CHECK) will be given. - */ - s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1]; + /* + * Of integrity checks, we support none (Check ID = 0), + * CRC32 (Check ID = 1), and optionally CRC64 (Check ID = 4). + * However, if XZ_DEC_ANY_CHECK is defined, we will accept other + * check types too, but then the check won't be verified and + * a warning (XZ_UNSUPPORTED_CHECK) will be given. + */ + s->check_type = s->temp.buf[HEADER_MAGIC_SIZE + 1]; #ifdef XZ_DEC_ANY_CHECK - if (s->check_type > XZ_CHECK_MAX) - return XZ_OPTIONS_ERROR; + if (s->check_type > XZ_CHECK_MAX) + return XZ_OPTIONS_ERROR; - if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) - return XZ_UNSUPPORTED_CHECK; + if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) + return XZ_UNSUPPORTED_CHECK; #else - if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) - return XZ_OPTIONS_ERROR; + if (s->check_type > XZ_CHECK_CRC32 && !IS_CRC64(s->check_type)) + return XZ_OPTIONS_ERROR; #endif - return XZ_OK; + return XZ_OK; } /* Decode the Stream Footer field (the last 12 bytes of the .xz Stream) */ static enum xz_ret dec_stream_footer(struct xz_dec *s) { - if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE)) - return XZ_DATA_ERROR; + if (!memeq(s->temp.buf + 10, FOOTER_MAGIC, FOOTER_MAGIC_SIZE)) + return XZ_DATA_ERROR; - if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf)) - return XZ_DATA_ERROR; + if (xz_crc32(s->temp.buf + 4, 6, 0) != get_le32(s->temp.buf)) + return XZ_DATA_ERROR; - /* - * Validate Backward Size. Note that we never added the size of the - * Index CRC32 field to s->index.size, thus we use s->index.size / 4 - * instead of s->index.size / 4 - 1. - */ - if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) - return XZ_DATA_ERROR; + /* + * Validate Backward Size. Note that we never added the size of the + * Index CRC32 field to s->index.size, thus we use s->index.size / 4 + * instead of s->index.size / 4 - 1. + */ + if ((s->index.size >> 2) != get_le32(s->temp.buf + 4)) + return XZ_DATA_ERROR; - if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type) - return XZ_DATA_ERROR; + if (s->temp.buf[8] != 0 || s->temp.buf[9] != s->check_type) + return XZ_DATA_ERROR; - /* - * Use XZ_STREAM_END instead of XZ_OK to be more convenient - * for the caller. - */ - return XZ_STREAM_END; + /* + * Use XZ_STREAM_END instead of XZ_OK to be more convenient + * for the caller. + */ + return XZ_STREAM_END; } /* Decode the Block Header and initialize the filter chain. */ static enum xz_ret dec_block_header(struct xz_dec *s) { - enum xz_ret ret; + enum xz_ret ret; - /* - * Validate the CRC32. We know that the temp buffer is at least - * eight bytes so this is safe. - */ - s->temp.size -= 4; - if (xz_crc32(s->temp.buf, s->temp.size, 0) - != get_le32(s->temp.buf + s->temp.size)) - return XZ_DATA_ERROR; + /* + * Validate the CRC32. We know that the temp buffer is at least + * eight bytes so this is safe. + */ + s->temp.size -= 4; + if (xz_crc32(s->temp.buf, s->temp.size, 0) + != get_le32(s->temp.buf + s->temp.size)) + return XZ_DATA_ERROR; - s->temp.pos = 2; + s->temp.pos = 2; - /* - * Catch unsupported Block Flags. We support only one or two filters - * in the chain, so we catch that with the same test. - */ + /* + * Catch unsupported Block Flags. We support only one or two filters + * in the chain, so we catch that with the same test. + */ #ifdef XZ_DEC_BCJ - if (s->temp.buf[1] & 0x3E) + if (s->temp.buf[1] & 0x3E) #else - if (s->temp.buf[1] & 0x3F) + if (s->temp.buf[1] & 0x3F) #endif - return XZ_OPTIONS_ERROR; + return XZ_OPTIONS_ERROR; - /* Compressed Size */ - if (s->temp.buf[1] & 0x40) { - if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) - != XZ_STREAM_END) - return XZ_DATA_ERROR; + /* Compressed Size */ + if (s->temp.buf[1] & 0x40) { + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) + != XZ_STREAM_END) + return XZ_DATA_ERROR; - s->block_header.compressed = s->vli; - } else { - s->block_header.compressed = VLI_UNKNOWN; - } + s->block_header.compressed = s->vli; + } else { + s->block_header.compressed = VLI_UNKNOWN; + } - /* Uncompressed Size */ - if (s->temp.buf[1] & 0x80) { - if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) - != XZ_STREAM_END) - return XZ_DATA_ERROR; + /* Uncompressed Size */ + if (s->temp.buf[1] & 0x80) { + if (dec_vli(s, s->temp.buf, &s->temp.pos, s->temp.size) + != XZ_STREAM_END) + return XZ_DATA_ERROR; - s->block_header.uncompressed = s->vli; - } else { - s->block_header.uncompressed = VLI_UNKNOWN; - } + s->block_header.uncompressed = s->vli; + } else { + s->block_header.uncompressed = VLI_UNKNOWN; + } #ifdef XZ_DEC_BCJ - /* If there are two filters, the first one must be a BCJ filter. */ - s->bcj_active = s->temp.buf[1] & 0x01; - if (s->bcj_active) { - if (s->temp.size - s->temp.pos < 2) - return XZ_OPTIONS_ERROR; + /* If there are two filters, the first one must be a BCJ filter. */ + s->bcj_active = s->temp.buf[1] & 0x01; + if (s->bcj_active) { + if (s->temp.size - s->temp.pos < 2) + return XZ_OPTIONS_ERROR; - ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]); - if (ret != XZ_OK) - return ret; + ret = xz_dec_bcj_reset(s->bcj, s->temp.buf[s->temp.pos++]); + if (ret != XZ_OK) + return ret; - /* - * We don't support custom start offset, - * so Size of Properties must be zero. - */ - if (s->temp.buf[s->temp.pos++] != 0x00) - return XZ_OPTIONS_ERROR; - } + /* + * We don't support custom start offset, + * so Size of Properties must be zero. + */ + if (s->temp.buf[s->temp.pos++] != 0x00) + return XZ_OPTIONS_ERROR; + } #endif - /* Valid Filter Flags always take at least two bytes. */ - if (s->temp.size - s->temp.pos < 2) - return XZ_DATA_ERROR; + /* Valid Filter Flags always take at least two bytes. */ + if (s->temp.size - s->temp.pos < 2) + return XZ_DATA_ERROR; - /* Filter ID = LZMA2 */ - if (s->temp.buf[s->temp.pos++] != 0x21) - return XZ_OPTIONS_ERROR; + /* Filter ID = LZMA2 */ + if (s->temp.buf[s->temp.pos++] != 0x21) + return XZ_OPTIONS_ERROR; - /* Size of Properties = 1-byte Filter Properties */ - if (s->temp.buf[s->temp.pos++] != 0x01) - return XZ_OPTIONS_ERROR; + /* Size of Properties = 1-byte Filter Properties */ + if (s->temp.buf[s->temp.pos++] != 0x01) + return XZ_OPTIONS_ERROR; - /* Filter Properties contains LZMA2 dictionary size. */ - if (s->temp.size - s->temp.pos < 1) - return XZ_DATA_ERROR; + /* Filter Properties contains LZMA2 dictionary size. */ + if (s->temp.size - s->temp.pos < 1) + return XZ_DATA_ERROR; - ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]); - if (ret != XZ_OK) - return ret; + ret = xz_dec_lzma2_reset(s->lzma2, s->temp.buf[s->temp.pos++]); + if (ret != XZ_OK) + return ret; - /* The rest must be Header Padding. */ - while (s->temp.pos < s->temp.size) - if (s->temp.buf[s->temp.pos++] != 0x00) - return XZ_OPTIONS_ERROR; + /* The rest must be Header Padding. */ + while (s->temp.pos < s->temp.size) + if (s->temp.buf[s->temp.pos++] != 0x00) + return XZ_OPTIONS_ERROR; - s->temp.pos = 0; - s->block.compressed = 0; - s->block.uncompressed = 0; + s->temp.pos = 0; + s->block.compressed = 0; + s->block.uncompressed = 0; - return XZ_OK; + return XZ_OK; } static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) { - enum xz_ret ret; + enum xz_ret ret; - /* - * Store the start position for the case when we are in the middle - * of the Index field. - */ - s->in_start = b->in_pos; + /* + * Store the start position for the case when we are in the middle + * of the Index field. + */ + s->in_start = b->in_pos; - while (true) { - switch (s->sequence) { - case SEQ_STREAM_HEADER: - /* - * Stream Header is copied to s->temp, and then - * decoded from there. This way if the caller - * gives us only little input at a time, we can - * still keep the Stream Header decoding code - * simple. Similar approach is used in many places - * in this file. - */ - if (!fill_temp(s, b)) - return XZ_OK; + while (true) { + switch (s->sequence) { + case SEQ_STREAM_HEADER: + /* + * Stream Header is copied to s->temp, and then + * decoded from there. This way if the caller + * gives us only little input at a time, we can + * still keep the Stream Header decoding code + * simple. Similar approach is used in many places + * in this file. + */ + if (!fill_temp(s, b)) + return XZ_OK; - /* - * If dec_stream_header() returns - * XZ_UNSUPPORTED_CHECK, it is still possible - * to continue decoding if working in multi-call - * mode. Thus, update s->sequence before calling - * dec_stream_header(). - */ - s->sequence = SEQ_BLOCK_START; + /* + * If dec_stream_header() returns + * XZ_UNSUPPORTED_CHECK, it is still possible + * to continue decoding if working in multi-call + * mode. Thus, update s->sequence before calling + * dec_stream_header(). + */ + s->sequence = SEQ_BLOCK_START; - ret = dec_stream_header(s); - if (ret != XZ_OK) - return ret; + ret = dec_stream_header(s); + if (ret != XZ_OK) + return ret; - case SEQ_BLOCK_START: - /* We need one byte of input to continue. */ - if (b->in_pos == b->in_size) - return XZ_OK; + case SEQ_BLOCK_START: + /* We need one byte of input to continue. */ + if (b->in_pos == b->in_size) + return XZ_OK; - /* See if this is the beginning of the Index field. */ - if (b->in[b->in_pos] == 0) { - s->in_start = b->in_pos++; - s->sequence = SEQ_INDEX; - break; - } + /* See if this is the beginning of the Index field. */ + if (b->in[b->in_pos] == 0) { + s->in_start = b->in_pos++; + s->sequence = SEQ_INDEX; + break; + } - /* - * Calculate the size of the Block Header and - * prepare to decode it. - */ - s->block_header.size - = ((uint32_t)b->in[b->in_pos] + 1) * 4; + /* + * Calculate the size of the Block Header and + * prepare to decode it. + */ + s->block_header.size + = ((uint32_t)b->in[b->in_pos] + 1) * 4; - s->temp.size = s->block_header.size; - s->temp.pos = 0; - s->sequence = SEQ_BLOCK_HEADER; + s->temp.size = s->block_header.size; + s->temp.pos = 0; + s->sequence = SEQ_BLOCK_HEADER; - case SEQ_BLOCK_HEADER: - if (!fill_temp(s, b)) - return XZ_OK; + case SEQ_BLOCK_HEADER: + if (!fill_temp(s, b)) + return XZ_OK; - ret = dec_block_header(s); - if (ret != XZ_OK) - return ret; + ret = dec_block_header(s); + if (ret != XZ_OK) + return ret; - s->sequence = SEQ_BLOCK_UNCOMPRESS; + s->sequence = SEQ_BLOCK_UNCOMPRESS; - case SEQ_BLOCK_UNCOMPRESS: - ret = dec_block(s, b); - if (ret != XZ_STREAM_END) - return ret; + case SEQ_BLOCK_UNCOMPRESS: + ret = dec_block(s, b); + if (ret != XZ_STREAM_END) + return ret; - s->sequence = SEQ_BLOCK_PADDING; + s->sequence = SEQ_BLOCK_PADDING; - case SEQ_BLOCK_PADDING: - /* - * Size of Compressed Data + Block Padding - * must be a multiple of four. We don't need - * s->block.compressed for anything else - * anymore, so we use it here to test the size - * of the Block Padding field. - */ - while (s->block.compressed & 3) { - if (b->in_pos == b->in_size) - return XZ_OK; + case SEQ_BLOCK_PADDING: + /* + * Size of Compressed Data + Block Padding + * must be a multiple of four. We don't need + * s->block.compressed for anything else + * anymore, so we use it here to test the size + * of the Block Padding field. + */ + while (s->block.compressed & 3) { + if (b->in_pos == b->in_size) + return XZ_OK; - if (b->in[b->in_pos++] != 0) - return XZ_DATA_ERROR; + if (b->in[b->in_pos++] != 0) + return XZ_DATA_ERROR; - ++s->block.compressed; - } + ++s->block.compressed; + } - s->sequence = SEQ_BLOCK_CHECK; + s->sequence = SEQ_BLOCK_CHECK; - case SEQ_BLOCK_CHECK: - if (s->check_type == XZ_CHECK_CRC32) { - ret = crc_validate(s, b, 32); - if (ret != XZ_STREAM_END) - return ret; - } - else if (IS_CRC64(s->check_type)) { - ret = crc_validate(s, b, 64); - if (ret != XZ_STREAM_END) - return ret; - } + case SEQ_BLOCK_CHECK: + if (s->check_type == XZ_CHECK_CRC32) { + ret = crc_validate(s, b, 32); + if (ret != XZ_STREAM_END) + return ret; + } + else if (IS_CRC64(s->check_type)) { + ret = crc_validate(s, b, 64); + if (ret != XZ_STREAM_END) + return ret; + } #ifdef XZ_DEC_ANY_CHECK - else if (!check_skip(s, b)) { - return XZ_OK; - } + else if (!check_skip(s, b)) { + return XZ_OK; + } #endif - s->sequence = SEQ_BLOCK_START; - break; + s->sequence = SEQ_BLOCK_START; + break; - case SEQ_INDEX: - ret = dec_index(s, b); - if (ret != XZ_STREAM_END) - return ret; + case SEQ_INDEX: + ret = dec_index(s, b); + if (ret != XZ_STREAM_END) + return ret; - s->sequence = SEQ_INDEX_PADDING; + s->sequence = SEQ_INDEX_PADDING; - case SEQ_INDEX_PADDING: - while ((s->index.size + (b->in_pos - s->in_start)) - & 3) { - if (b->in_pos == b->in_size) { - index_update(s, b); - return XZ_OK; - } + case SEQ_INDEX_PADDING: + while ((s->index.size + (b->in_pos - s->in_start)) + & 3) { + if (b->in_pos == b->in_size) { + index_update(s, b); + return XZ_OK; + } - if (b->in[b->in_pos++] != 0) - return XZ_DATA_ERROR; - } + if (b->in[b->in_pos++] != 0) + return XZ_DATA_ERROR; + } - /* Finish the CRC32 value and Index size. */ - index_update(s, b); + /* Finish the CRC32 value and Index size. */ + index_update(s, b); - /* Compare the hashes to validate the Index field. */ - if (!memeq(&s->block.hash, &s->index.hash, - sizeof(s->block.hash))) - return XZ_DATA_ERROR; + /* Compare the hashes to validate the Index field. */ + if (!memeq(&s->block.hash, &s->index.hash, + sizeof(s->block.hash))) + return XZ_DATA_ERROR; - s->sequence = SEQ_INDEX_CRC32; + s->sequence = SEQ_INDEX_CRC32; - case SEQ_INDEX_CRC32: - ret = crc_validate(s, b, 32); - if (ret != XZ_STREAM_END) - return ret; + case SEQ_INDEX_CRC32: + ret = crc_validate(s, b, 32); + if (ret != XZ_STREAM_END) + return ret; - s->temp.size = STREAM_HEADER_SIZE; - s->sequence = SEQ_STREAM_FOOTER; + s->temp.size = STREAM_HEADER_SIZE; + s->sequence = SEQ_STREAM_FOOTER; - case SEQ_STREAM_FOOTER: - if (!fill_temp(s, b)) - return XZ_OK; + case SEQ_STREAM_FOOTER: + if (!fill_temp(s, b)) + return XZ_OK; - return dec_stream_footer(s); - } - } + return dec_stream_footer(s); + } + } - /* Never reached */ + /* Never reached */ } /* @@ -759,89 +759,89 @@ static enum xz_ret dec_main(struct xz_dec *s, struct xz_buf *b) */ XZ_EXTERN enum xz_ret xz_dec_run(struct xz_dec *s, struct xz_buf *b) { - size_t in_start; - size_t out_start; - enum xz_ret ret; + size_t in_start; + size_t out_start; + enum xz_ret ret; - if (DEC_IS_SINGLE(s->mode)) - xz_dec_reset(s); + if (DEC_IS_SINGLE(s->mode)) + xz_dec_reset(s); - in_start = b->in_pos; - out_start = b->out_pos; - ret = dec_main(s, b); + in_start = b->in_pos; + out_start = b->out_pos; + ret = dec_main(s, b); - if (DEC_IS_SINGLE(s->mode)) { - if (ret == XZ_OK) - ret = b->in_pos == b->in_size - ? XZ_DATA_ERROR : XZ_BUF_ERROR; + if (DEC_IS_SINGLE(s->mode)) { + if (ret == XZ_OK) + ret = b->in_pos == b->in_size + ? XZ_DATA_ERROR : XZ_BUF_ERROR; - if (ret != XZ_STREAM_END) { - b->in_pos = in_start; - b->out_pos = out_start; - } + if (ret != XZ_STREAM_END) { + b->in_pos = in_start; + b->out_pos = out_start; + } - } else if (ret == XZ_OK && in_start == b->in_pos - && out_start == b->out_pos) { - if (s->allow_buf_error) - ret = XZ_BUF_ERROR; + } else if (ret == XZ_OK && in_start == b->in_pos + && out_start == b->out_pos) { + if (s->allow_buf_error) + ret = XZ_BUF_ERROR; - s->allow_buf_error = true; - } else { - s->allow_buf_error = false; - } + s->allow_buf_error = true; + } else { + s->allow_buf_error = false; + } - return ret; + return ret; } XZ_EXTERN struct xz_dec *xz_dec_init(enum xz_mode mode, uint32_t dict_max) { - struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL); - if (s == NULL) - return NULL; + struct xz_dec *s = kmalloc(sizeof(*s), GFP_KERNEL); + if (s == NULL) + return NULL; - s->mode = mode; + s->mode = mode; #ifdef XZ_DEC_BCJ - s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode)); - if (s->bcj == NULL) - goto error_bcj; + s->bcj = xz_dec_bcj_create(DEC_IS_SINGLE(mode)); + if (s->bcj == NULL) + goto error_bcj; #endif - s->lzma2 = xz_dec_lzma2_create(mode, dict_max); - if (s->lzma2 == NULL) - goto error_lzma2; + s->lzma2 = xz_dec_lzma2_create(mode, dict_max); + if (s->lzma2 == NULL) + goto error_lzma2; - xz_dec_reset(s); - return s; + xz_dec_reset(s); + return s; error_lzma2: #ifdef XZ_DEC_BCJ - xz_dec_bcj_end(s->bcj); + xz_dec_bcj_end(s->bcj); error_bcj: #endif - kfree(s); - return NULL; + kfree(s); + return NULL; } XZ_EXTERN void xz_dec_reset(struct xz_dec *s) { - s->sequence = SEQ_STREAM_HEADER; - s->allow_buf_error = false; - s->pos = 0; - s->crc = 0; - memzero(&s->block, sizeof(s->block)); - memzero(&s->index, sizeof(s->index)); - s->temp.pos = 0; - s->temp.size = STREAM_HEADER_SIZE; + s->sequence = SEQ_STREAM_HEADER; + s->allow_buf_error = false; + s->pos = 0; + s->crc = 0; + memzero(&s->block, sizeof(s->block)); + memzero(&s->index, sizeof(s->index)); + s->temp.pos = 0; + s->temp.size = STREAM_HEADER_SIZE; } XZ_EXTERN void xz_dec_end(struct xz_dec *s) { - if (s != NULL) { - xz_dec_lzma2_end(s->lzma2); + if (s != NULL) { + xz_dec_lzma2_end(s->lzma2); #ifdef XZ_DEC_BCJ - xz_dec_bcj_end(s->bcj); + xz_dec_bcj_end(s->bcj); #endif - kfree(s); - } + kfree(s); + } } diff --git a/native/jni/external/xz-embedded/xz_lzma2.h b/native/jni/external/xz-embedded/xz_lzma2.h index 071d67bee..aa05d9563 100644 --- a/native/jni/external/xz-embedded/xz_lzma2.h +++ b/native/jni/external/xz-embedded/xz_lzma2.h @@ -40,18 +40,18 @@ * either short or long repeated match, and NONLIT means any non-literal. */ enum lzma_state { - STATE_LIT_LIT, - STATE_MATCH_LIT_LIT, - STATE_REP_LIT_LIT, - STATE_SHORTREP_LIT_LIT, - STATE_MATCH_LIT, - STATE_REP_LIT, - STATE_SHORTREP_LIT, - STATE_LIT_MATCH, - STATE_LIT_LONGREP, - STATE_LIT_SHORTREP, - STATE_NONLIT_MATCH, - STATE_NONLIT_REP + STATE_LIT_LIT, + STATE_MATCH_LIT_LIT, + STATE_REP_LIT_LIT, + STATE_SHORTREP_LIT_LIT, + STATE_MATCH_LIT, + STATE_REP_LIT, + STATE_SHORTREP_LIT, + STATE_LIT_MATCH, + STATE_LIT_LONGREP, + STATE_LIT_SHORTREP, + STATE_NONLIT_MATCH, + STATE_NONLIT_REP }; /* Total number of states */ @@ -63,36 +63,36 @@ enum lzma_state { /* Indicate that the latest symbol was a literal. */ static inline void lzma_state_literal(enum lzma_state *state) { - if (*state <= STATE_SHORTREP_LIT_LIT) - *state = STATE_LIT_LIT; - else if (*state <= STATE_LIT_SHORTREP) - *state -= 3; - else - *state -= 6; + if (*state <= STATE_SHORTREP_LIT_LIT) + *state = STATE_LIT_LIT; + else if (*state <= STATE_LIT_SHORTREP) + *state -= 3; + else + *state -= 6; } /* Indicate that the latest symbol was a match. */ static inline void lzma_state_match(enum lzma_state *state) { - *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH; + *state = *state < LIT_STATES ? STATE_LIT_MATCH : STATE_NONLIT_MATCH; } /* Indicate that the latest state was a long repeated match. */ static inline void lzma_state_long_rep(enum lzma_state *state) { - *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP; + *state = *state < LIT_STATES ? STATE_LIT_LONGREP : STATE_NONLIT_REP; } /* Indicate that the latest symbol was a short match. */ static inline void lzma_state_short_rep(enum lzma_state *state) { - *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP; + *state = *state < LIT_STATES ? STATE_LIT_SHORTREP : STATE_NONLIT_REP; } /* Test if the previous symbol was a literal. */ static inline bool lzma_state_is_literal(enum lzma_state state) { - return state < LIT_STATES; + return state < LIT_STATES; } /* Each literal coder is divided in three sections: @@ -146,8 +146,8 @@ static inline bool lzma_state_is_literal(enum lzma_state state) */ static inline uint32_t lzma_get_dist_state(uint32_t len) { - return len < DIST_STATES + MATCH_LEN_MIN - ? len - MATCH_LEN_MIN : DIST_STATES - 1; + return len < DIST_STATES + MATCH_LEN_MIN + ? len - MATCH_LEN_MIN : DIST_STATES - 1; } /* diff --git a/native/jni/external/xz-embedded/xz_private.h b/native/jni/external/xz-embedded/xz_private.h index 482b90f36..c531e6588 100644 --- a/native/jni/external/xz-embedded/xz_private.h +++ b/native/jni/external/xz-embedded/xz_private.h @@ -14,7 +14,7 @@ # include # include # include - /* XZ_PREBOOT may be defined only via decompress_unxz.c. */ + /* XZ_PREBOOT may be defined only via decompress_unxz.c. */ # ifndef XZ_PREBOOT # include # include @@ -42,17 +42,17 @@ # endif # define get_le32(p) le32_to_cpup((const uint32_t *)(p)) #else - /* - * For userspace builds, use a separate header to define the required - * macros and functions. This makes it easier to adapt the code into - * different environments and avoids clutter in the Linux kernel tree. - */ + /* + * For userspace builds, use a separate header to define the required + * macros and functions. This makes it easier to adapt the code into + * different environments and avoids clutter in the Linux kernel tree. + */ # include "xz_config.h" #endif /* If no specific decoding mode is requested, enable support for all modes. */ #if !defined(XZ_DEC_SINGLE) && !defined(XZ_DEC_PREALLOC) \ - && !defined(XZ_DEC_DYNALLOC) + && !defined(XZ_DEC_DYNALLOC) # define XZ_DEC_SINGLE # define XZ_DEC_PREALLOC # define XZ_DEC_DYNALLOC @@ -95,9 +95,9 @@ */ #ifndef XZ_DEC_BCJ # if defined(XZ_DEC_X86) || defined(XZ_DEC_POWERPC) \ - || defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \ - || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \ - || defined(XZ_DEC_SPARC) + || defined(XZ_DEC_IA64) || defined(XZ_DEC_ARM) \ + || defined(XZ_DEC_ARM) || defined(XZ_DEC_ARMTHUMB) \ + || defined(XZ_DEC_SPARC) # define XZ_DEC_BCJ # endif #endif @@ -107,7 +107,7 @@ * before calling xz_dec_lzma2_run(). */ XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, - uint32_t dict_max); + uint32_t dict_max); /* * Decode the LZMA2 properties (one byte) and reset the decoder. Return @@ -116,11 +116,11 @@ XZ_EXTERN struct xz_dec_lzma2 *xz_dec_lzma2_create(enum xz_mode mode, * decoder doesn't support. */ XZ_EXTERN enum xz_ret xz_dec_lzma2_reset(struct xz_dec_lzma2 *s, - uint8_t props); + uint8_t props); /* Decode raw LZMA2 stream from b->in to b->out. */ XZ_EXTERN enum xz_ret xz_dec_lzma2_run(struct xz_dec_lzma2 *s, - struct xz_buf *b); + struct xz_buf *b); /* Free the memory allocated for the LZMA2 decoder. */ XZ_EXTERN void xz_dec_lzma2_end(struct xz_dec_lzma2 *s); @@ -146,8 +146,8 @@ XZ_EXTERN enum xz_ret xz_dec_bcj_reset(struct xz_dec_bcj *s, uint8_t id); * must be called directly. */ XZ_EXTERN enum xz_ret xz_dec_bcj_run(struct xz_dec_bcj *s, - struct xz_dec_lzma2 *lzma2, - struct xz_buf *b); + struct xz_dec_lzma2 *lzma2, + struct xz_buf *b); /* Free the memory allocated for the BCJ filters. */ #define xz_dec_bcj_end(s) kfree(s) diff --git a/native/jni/external/xz-embedded/xz_stream.h b/native/jni/external/xz-embedded/xz_stream.h index 66cb5a705..1c629c222 100644 --- a/native/jni/external/xz-embedded/xz_stream.h +++ b/native/jni/external/xz-embedded/xz_stream.h @@ -14,7 +14,7 @@ # include # undef crc32 # define xz_crc32(buf, size, crc) \ - (~crc32_le(~(uint32_t)(crc), buf, size)) + (~crc32_le(~(uint32_t)(crc), buf, size)) #endif /* @@ -50,10 +50,10 @@ typedef uint64_t vli_type; /* Integrity Check types */ enum xz_check { - XZ_CHECK_NONE = 0, - XZ_CHECK_CRC32 = 1, - XZ_CHECK_CRC64 = 4, - XZ_CHECK_SHA256 = 10 + XZ_CHECK_NONE = 0, + XZ_CHECK_CRC32 = 1, + XZ_CHECK_CRC64 = 4, + XZ_CHECK_SHA256 = 10 }; /* Maximum possible Check ID */ diff --git a/native/jni/include/daemon.hpp b/native/jni/include/daemon.hpp index 3464b1cd4..6a58f01fb 100644 --- a/native/jni/include/daemon.hpp +++ b/native/jni/include/daemon.hpp @@ -8,35 +8,35 @@ // Daemon command codes enum { - START_DAEMON, - SUPERUSER, - CHECK_VERSION, - CHECK_VERSION_CODE, - POST_FS_DATA, - LATE_START, - BOOT_COMPLETE, - MAGISKHIDE, - SQLITE_CMD, - REMOVE_MODULES, - GET_PATH, - DAEMON_CODE_END, + START_DAEMON, + SUPERUSER, + CHECK_VERSION, + CHECK_VERSION_CODE, + POST_FS_DATA, + LATE_START, + BOOT_COMPLETE, + MAGISKHIDE, + SQLITE_CMD, + REMOVE_MODULES, + GET_PATH, + DAEMON_CODE_END, }; // Return codes for daemon enum { - DAEMON_ERROR = -1, - DAEMON_SUCCESS = 0, - ROOT_REQUIRED, - DAEMON_LAST + DAEMON_ERROR = -1, + DAEMON_SUCCESS = 0, + ROOT_REQUIRED, + DAEMON_LAST }; // Daemon state enum { - STATE_NONE, - STATE_POST_FS_DATA, - STATE_POST_FS_DATA_DONE, - STATE_LATE_START_DONE, - STATE_BOOT_COMPLETE + STATE_NONE, + STATE_POST_FS_DATA, + STATE_POST_FS_DATA_DONE, + STATE_LATE_START_DONE, + STATE_BOOT_COMPLETE }; extern int SDK_INT; diff --git a/native/jni/include/db.hpp b/native/jni/include/db.hpp index d994b9eb3..b03f45a85 100644 --- a/native/jni/include/db.hpp +++ b/native/jni/include/db.hpp @@ -9,25 +9,25 @@ template class db_data_base { public: - T& operator [](std::string_view key) { - return data[getKeyIdx(key)]; - } + T& operator [](std::string_view key) { + return data[getKeyIdx(key)]; + } - const T& operator [](std::string_view key) const { - return data[getKeyIdx(key)]; - } + const T& operator [](std::string_view key) const { + return data[getKeyIdx(key)]; + } - T& operator [](int key) { - return data[key]; - } + T& operator [](int key) { + return data[key]; + } - const T& operator [](int key) const { - return data[key]; - } + const T& operator [](int key) const { + return data[key]; + } protected: - T data[num + 1]; - virtual int getKeyIdx(std::string_view key) const = 0; + T data[num + 1]; + virtual int getKeyIdx(std::string_view key) const = 0; }; /*************** @@ -46,40 +46,40 @@ protected: // Settings keys enum { - ROOT_ACCESS = 0, - SU_MULTIUSER_MODE, - SU_MNT_NS, - HIDE_CONFIG + ROOT_ACCESS = 0, + SU_MULTIUSER_MODE, + SU_MNT_NS, + HIDE_CONFIG }; // Values for root_access enum { - ROOT_ACCESS_DISABLED = 0, - ROOT_ACCESS_APPS_ONLY, - ROOT_ACCESS_ADB_ONLY, - ROOT_ACCESS_APPS_AND_ADB + ROOT_ACCESS_DISABLED = 0, + ROOT_ACCESS_APPS_ONLY, + ROOT_ACCESS_ADB_ONLY, + ROOT_ACCESS_APPS_AND_ADB }; // Values for multiuser_mode enum { - MULTIUSER_MODE_OWNER_ONLY = 0, - MULTIUSER_MODE_OWNER_MANAGED, - MULTIUSER_MODE_USER + MULTIUSER_MODE_OWNER_ONLY = 0, + MULTIUSER_MODE_OWNER_MANAGED, + MULTIUSER_MODE_USER }; // Values for mnt_ns enum { - NAMESPACE_MODE_GLOBAL = 0, - NAMESPACE_MODE_REQUESTER, - NAMESPACE_MODE_ISOLATE + NAMESPACE_MODE_GLOBAL = 0, + NAMESPACE_MODE_REQUESTER, + NAMESPACE_MODE_ISOLATE }; class db_settings : public db_data_base { public: - db_settings(); + db_settings(); protected: - int getKeyIdx(std::string_view key) const override; + int getKeyIdx(std::string_view key) const override; }; /************** @@ -95,12 +95,12 @@ protected: // Strings keys enum { - SU_MANAGER = 0 + SU_MANAGER = 0 }; class db_strings : public db_data_base { protected: - int getKeyIdx(std::string_view key) const override; + int getKeyIdx(std::string_view key) const override; }; /************* @@ -108,15 +108,15 @@ protected: *************/ typedef enum { - QUERY = 0, - DENY = 1, - ALLOW = 2, + QUERY = 0, + DENY = 1, + ALLOW = 2, } policy_t; struct su_access { - policy_t policy; - int log; - int notify; + policy_t policy; + int log; + int notify; }; #define DEFAULT_SU_ACCESS (su_access) { \ diff --git a/native/jni/include/magiskpolicy.hpp b/native/jni/include/magiskpolicy.hpp index 5c3d5d05a..ea6ddc449 100644 --- a/native/jni/include/magiskpolicy.hpp +++ b/native/jni/include/magiskpolicy.hpp @@ -9,52 +9,52 @@ struct policydb; class sepolicy { public: - typedef const char * c_str; - ~sepolicy(); + typedef const char * c_str; + ~sepolicy(); - // Public static factory functions - static sepolicy *from_file(c_str file); - static sepolicy *from_split(); - static sepolicy *compile_split(); + // Public static factory functions + static sepolicy *from_file(c_str file); + static sepolicy *from_split(); + static sepolicy *compile_split(); - // External APIs - bool to_file(c_str file); - void parse_statement(c_str stmt); - void load_rule_file(c_str file); + // External APIs + bool to_file(c_str file); + void parse_statement(c_str stmt); + void load_rule_file(c_str file); - // Operation on types - bool type(c_str name, c_str attr); - bool attribute(c_str name); - bool permissive(c_str type); - bool enforce(c_str type); - bool typeattribute(c_str type, c_str attr); - bool exists(c_str type); + // Operation on types + bool type(c_str name, c_str attr); + bool attribute(c_str name); + bool permissive(c_str type); + bool enforce(c_str type); + bool typeattribute(c_str type, c_str attr); + bool exists(c_str type); - // Access vector rules - bool allow(c_str src, c_str tgt, c_str cls, c_str perm); - bool deny(c_str src, c_str tgt, c_str cls, c_str perm); - bool auditallow(c_str src, c_str tgt, c_str cls, c_str perm); - bool dontaudit(c_str src, c_str tgt, c_str cls, c_str perm); + // Access vector rules + bool allow(c_str src, c_str tgt, c_str cls, c_str perm); + bool deny(c_str src, c_str tgt, c_str cls, c_str perm); + bool auditallow(c_str src, c_str tgt, c_str cls, c_str perm); + bool dontaudit(c_str src, c_str tgt, c_str cls, c_str perm); - // Extended permissions access vector rules - bool allowxperm(c_str src, c_str tgt, c_str cls, c_str range); - bool auditallowxperm(c_str src, c_str tgt, c_str cls, c_str range); - bool dontauditxperm(c_str src, c_str tgt, c_str cls, c_str range); + // Extended permissions access vector rules + bool allowxperm(c_str src, c_str tgt, c_str cls, c_str range); + bool auditallowxperm(c_str src, c_str tgt, c_str cls, c_str range); + bool dontauditxperm(c_str src, c_str tgt, c_str cls, c_str range); - // Type rules - bool type_transition(c_str src, c_str tgt, c_str cls, c_str def, c_str obj = nullptr); - bool type_change(c_str src, c_str tgt, c_str cls, c_str def); - bool type_member(c_str src, c_str tgt, c_str cls, c_str def); + // Type rules + bool type_transition(c_str src, c_str tgt, c_str cls, c_str def, c_str obj = nullptr); + bool type_change(c_str src, c_str tgt, c_str cls, c_str def); + bool type_member(c_str src, c_str tgt, c_str cls, c_str def); - // File system labeling - bool genfscon(c_str fs_name, c_str path, c_str ctx); + // File system labeling + bool genfscon(c_str fs_name, c_str path, c_str ctx); - // Magisk - void magisk_rules(); + // Magisk + void magisk_rules(); - // Deprecate - bool create(c_str name) { return type(name, "domain"); } + // Deprecate + bool create(c_str name) { return type(name, "domain"); } protected: - policydb *db; + policydb *db; }; diff --git a/native/jni/include/resetprop.hpp b/native/jni/include/resetprop.hpp index c34078816..c90dc6109 100644 --- a/native/jni/include/resetprop.hpp +++ b/native/jni/include/resetprop.hpp @@ -6,6 +6,6 @@ int setprop(const char *name, const char *value, bool prop_svc = true); std::string getprop(const char *name, bool persist = false); void getprops(void (*callback)(const char *, const char *, void *), - void *cookie = nullptr, bool persist = false); + void *cookie = nullptr, bool persist = false); int delprop(const char *name, bool persist = false); void load_prop_file(const char *filename, bool prop_svc = true); diff --git a/native/jni/init/getinfo.cpp b/native/jni/init/getinfo.cpp index 1b23f3f65..58524e82a 100644 --- a/native/jni/init/getinfo.cpp +++ b/native/jni/init/getinfo.cpp @@ -13,121 +13,121 @@ using namespace std; template static void parse_cmdline(const Func &fn) { - char cmdline[4096]; - int fd = xopen("/proc/cmdline", O_RDONLY | O_CLOEXEC); - cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0'; - close(fd); + char cmdline[4096]; + int fd = xopen("/proc/cmdline", O_RDONLY | O_CLOEXEC); + cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0'; + close(fd); - char *tok, *eql, *tmp, *saveptr; - saveptr = cmdline; - while ((tok = strtok_r(nullptr, " \n", &saveptr)) != nullptr) { - eql = strchr(tok, '='); - if (eql) { - *eql = '\0'; - if (eql[1] == '"') { - tmp = strchr(saveptr, '"'); - if (tmp != nullptr) { - *tmp = '\0'; - saveptr[-1] = ' '; - saveptr = tmp + 1; - eql++; - } - } - fn(tok, eql + 1); - } else { - fn(tok, ""); - } - } + char *tok, *eql, *tmp, *saveptr; + saveptr = cmdline; + while ((tok = strtok_r(nullptr, " \n", &saveptr)) != nullptr) { + eql = strchr(tok, '='); + if (eql) { + *eql = '\0'; + if (eql[1] == '"') { + tmp = strchr(saveptr, '"'); + if (tmp != nullptr) { + *tmp = '\0'; + saveptr[-1] = ' '; + saveptr = tmp + 1; + eql++; + } + } + fn(tok, eql + 1); + } else { + fn(tok, ""); + } + } } #define test_bit(bit, array) (array[bit / 8] & (1 << (bit % 8))) static bool check_key_combo() { - uint8_t bitmask[(KEY_MAX + 1) / 8]; - vector events; - constexpr const char *name = "/event"; + uint8_t bitmask[(KEY_MAX + 1) / 8]; + vector events; + constexpr const char *name = "/event"; - for (int minor = 64; minor < 96; ++minor) { - if (xmknod(name, S_IFCHR | 0444, makedev(13, minor))) - continue; - int fd = open(name, O_RDONLY | O_CLOEXEC); - unlink(name); - if (fd < 0) - continue; - memset(bitmask, 0, sizeof(bitmask)); - ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitmask)), bitmask); - if (test_bit(KEY_VOLUMEUP, bitmask)) - events.push_back(fd); - else - close(fd); - } - if (events.empty()) - return false; + for (int minor = 64; minor < 96; ++minor) { + if (xmknod(name, S_IFCHR | 0444, makedev(13, minor))) + continue; + int fd = open(name, O_RDONLY | O_CLOEXEC); + unlink(name); + if (fd < 0) + continue; + memset(bitmask, 0, sizeof(bitmask)); + ioctl(fd, EVIOCGBIT(EV_KEY, sizeof(bitmask)), bitmask); + if (test_bit(KEY_VOLUMEUP, bitmask)) + events.push_back(fd); + else + close(fd); + } + if (events.empty()) + return false; - run_finally fin([&]{ std::for_each(events.begin(), events.end(), close); }); + run_finally fin([&]{ std::for_each(events.begin(), events.end(), close); }); - // Return true if volume up key is held for more than 3 seconds - int count = 0; - for (int i = 0; i < 500; ++i) { - for (const int &fd : events) { - memset(bitmask, 0, sizeof(bitmask)); - ioctl(fd, EVIOCGKEY(sizeof(bitmask)), bitmask); - if (test_bit(KEY_VOLUMEUP, bitmask)) { - count++; - break; - } - } - if (count >= 300) { - LOGD("KEY_VOLUMEUP detected: disable system-as-root\n"); - return true; - } - // Check every 10ms - usleep(10000); - } - return false; + // Return true if volume up key is held for more than 3 seconds + int count = 0; + for (int i = 0; i < 500; ++i) { + for (const int &fd : events) { + memset(bitmask, 0, sizeof(bitmask)); + ioctl(fd, EVIOCGKEY(sizeof(bitmask)), bitmask); + if (test_bit(KEY_VOLUMEUP, bitmask)) { + count++; + break; + } + } + if (count >= 300) { + LOGD("KEY_VOLUMEUP detected: disable system-as-root\n"); + return true; + } + // Check every 10ms + usleep(10000); + } + return false; } static FILE *kmsg; static char kmsg_buf[4096]; static int vprintk(const char *fmt, va_list ap) { - vsnprintf(kmsg_buf + 12, sizeof(kmsg_buf) - 12, fmt, ap); - return fprintf(kmsg, "%s", kmsg_buf); + vsnprintf(kmsg_buf + 12, sizeof(kmsg_buf) - 12, fmt, ap); + return fprintf(kmsg, "%s", kmsg_buf); } void setup_klog() { - // Shut down first 3 fds - int fd; - if (access("/dev/null", W_OK) == 0) { - fd = xopen("/dev/null", O_RDWR | O_CLOEXEC); - } else { - mknod("/null", S_IFCHR | 0666, makedev(1, 3)); - fd = xopen("/null", O_RDWR | O_CLOEXEC); - unlink("/null"); - } - xdup3(fd, STDIN_FILENO, O_CLOEXEC); - xdup3(fd, STDOUT_FILENO, O_CLOEXEC); - xdup3(fd, STDERR_FILENO, O_CLOEXEC); - if (fd > STDERR_FILENO) - close(fd); + // Shut down first 3 fds + int fd; + if (access("/dev/null", W_OK) == 0) { + fd = xopen("/dev/null", O_RDWR | O_CLOEXEC); + } else { + mknod("/null", S_IFCHR | 0666, makedev(1, 3)); + fd = xopen("/null", O_RDWR | O_CLOEXEC); + unlink("/null"); + } + xdup3(fd, STDIN_FILENO, O_CLOEXEC); + xdup3(fd, STDOUT_FILENO, O_CLOEXEC); + xdup3(fd, STDERR_FILENO, O_CLOEXEC); + if (fd > STDERR_FILENO) + close(fd); - if (access("/dev/kmsg", W_OK) == 0) { - fd = xopen("/dev/kmsg", O_WRONLY | O_CLOEXEC); - } else { - mknod("/kmsg", S_IFCHR | 0666, makedev(1, 11)); - fd = xopen("/kmsg", O_WRONLY | O_CLOEXEC); - unlink("/kmsg"); - } + if (access("/dev/kmsg", W_OK) == 0) { + fd = xopen("/dev/kmsg", O_WRONLY | O_CLOEXEC); + } else { + mknod("/kmsg", S_IFCHR | 0666, makedev(1, 11)); + fd = xopen("/kmsg", O_WRONLY | O_CLOEXEC); + unlink("/kmsg"); + } - kmsg = fdopen(fd, "w"); - setbuf(kmsg, nullptr); - log_cb.d = log_cb.i = log_cb.w = log_cb.e = vprintk; - log_cb.ex = nop_ex; - strcpy(kmsg_buf, "magiskinit: "); + kmsg = fdopen(fd, "w"); + setbuf(kmsg, nullptr); + log_cb.d = log_cb.i = log_cb.w = log_cb.e = vprintk; + log_cb.ex = nop_ex; + strcpy(kmsg_buf, "magiskinit: "); - // Disable kmsg rate limiting - if (FILE *rate = fopen("/proc/sys/kernel/printk_devkmsg", "w")) { - fprintf(rate, "on\n"); - fclose(rate); - } + // Disable kmsg rate limiting + if (FILE *rate = fopen("/proc/sys/kernel/printk_devkmsg", "w")) { + fprintf(rate, "on\n"); + fclose(rate); + } } #define read_dt(name, key) \ @@ -141,78 +141,78 @@ if (access(file_name, R_OK) == 0){ \ } void load_kernel_info(cmdline *cmd) { - // Get kernel data using procfs and sysfs - xmkdir("/proc", 0755); - xmount("proc", "/proc", "proc", 0, nullptr); - xmkdir("/sys", 0755); - xmount("sysfs", "/sys", "sysfs", 0, nullptr); + // Get kernel data using procfs and sysfs + xmkdir("/proc", 0755); + xmount("proc", "/proc", "proc", 0, nullptr); + xmkdir("/sys", 0755); + xmount("sysfs", "/sys", "sysfs", 0, nullptr); - // Log to kernel - setup_klog(); + // Log to kernel + setup_klog(); - parse_cmdline([=](string_view key, const char *value) -> void { - if (key == "androidboot.slot_suffix") { - strcpy(cmd->slot, value); - } else if (key == "androidboot.slot") { - cmd->slot[0] = '_'; - strcpy(cmd->slot + 1, value); - } else if (key == "skip_initramfs") { - cmd->skip_initramfs = true; - } else if (key == "androidboot.force_normal_boot") { - cmd->force_normal_boot = value[0] == '1'; - } else if (key == "rootwait") { - cmd->rootwait = true; - } else if (key == "androidboot.android_dt_dir") { - strcpy(cmd->dt_dir, value); - } else if (key == "androidboot.hardware") { - strcpy(cmd->hardware, value); - } else if (key == "androidboot.hardware.platform") { - strcpy(cmd->hardware_plat, value); - } else if (key == "androidboot.fstab_suffix") { - strcpy(cmd->fstab_suffix, value); - } - }); + parse_cmdline([=](string_view key, const char *value) -> void { + if (key == "androidboot.slot_suffix") { + strcpy(cmd->slot, value); + } else if (key == "androidboot.slot") { + cmd->slot[0] = '_'; + strcpy(cmd->slot + 1, value); + } else if (key == "skip_initramfs") { + cmd->skip_initramfs = true; + } else if (key == "androidboot.force_normal_boot") { + cmd->force_normal_boot = value[0] == '1'; + } else if (key == "rootwait") { + cmd->rootwait = true; + } else if (key == "androidboot.android_dt_dir") { + strcpy(cmd->dt_dir, value); + } else if (key == "androidboot.hardware") { + strcpy(cmd->hardware, value); + } else if (key == "androidboot.hardware.platform") { + strcpy(cmd->hardware_plat, value); + } else if (key == "androidboot.fstab_suffix") { + strcpy(cmd->fstab_suffix, value); + } + }); - LOGD("Kernel cmdline info:\n"); - LOGD("skip_initramfs=[%d]\n", cmd->skip_initramfs); - LOGD("force_normal_boot=[%d]\n", cmd->force_normal_boot); - LOGD("rootwait=[%d]\n", cmd->rootwait); - LOGD("slot=[%s]\n", cmd->slot); - LOGD("dt_dir=[%s]\n", cmd->dt_dir); - LOGD("fstab_suffix=[%s]\n", cmd->fstab_suffix); - LOGD("hardware=[%s]\n", cmd->hardware); - LOGD("hardware.platform=[%s]\n", cmd->hardware_plat); + LOGD("Kernel cmdline info:\n"); + LOGD("skip_initramfs=[%d]\n", cmd->skip_initramfs); + LOGD("force_normal_boot=[%d]\n", cmd->force_normal_boot); + LOGD("rootwait=[%d]\n", cmd->rootwait); + LOGD("slot=[%s]\n", cmd->slot); + LOGD("dt_dir=[%s]\n", cmd->dt_dir); + LOGD("fstab_suffix=[%s]\n", cmd->fstab_suffix); + LOGD("hardware=[%s]\n", cmd->hardware); + LOGD("hardware.platform=[%s]\n", cmd->hardware_plat); - parse_prop_file("/.backup/.magisk", [=](auto key, auto value) -> bool { - if (key == "RECOVERYMODE" && value == "true") { - LOGD("Running in recovery mode, waiting for key...\n"); - cmd->skip_initramfs = !check_key_combo(); - return false; - } - return true; - }); + parse_prop_file("/.backup/.magisk", [=](auto key, auto value) -> bool { + if (key == "RECOVERYMODE" && value == "true") { + LOGD("Running in recovery mode, waiting for key...\n"); + cmd->skip_initramfs = !check_key_combo(); + return false; + } + return true; + }); - if (cmd->dt_dir[0] == '\0') - strcpy(cmd->dt_dir, DEFAULT_DT_DIR); + if (cmd->dt_dir[0] == '\0') + strcpy(cmd->dt_dir, DEFAULT_DT_DIR); - char file_name[128]; - read_dt("fstab_suffix", fstab_suffix) - read_dt("hardware", hardware) - read_dt("hardware.platform", hardware_plat) + char file_name[128]; + read_dt("fstab_suffix", fstab_suffix) + read_dt("hardware", hardware) + read_dt("hardware.platform", hardware_plat) - LOGD("Device tree info:\n"); - LOGD("dt_dir=[%s]\n", cmd->dt_dir); - LOGD("fstab_suffix=[%s]\n", cmd->fstab_suffix); - LOGD("hardware=[%s]\n", cmd->hardware); - LOGD("hardware.platform=[%s]\n", cmd->hardware_plat); + LOGD("Device tree info:\n"); + LOGD("dt_dir=[%s]\n", cmd->dt_dir); + LOGD("fstab_suffix=[%s]\n", cmd->fstab_suffix); + LOGD("hardware=[%s]\n", cmd->hardware); + LOGD("hardware.platform=[%s]\n", cmd->hardware_plat); } bool check_two_stage() { - if (access("/apex", F_OK) == 0) - return true; - if (access("/system/bin/init", F_OK) == 0) - return true; - // If we still have no indication, parse the original init and see what's up - auto init = raw_data::mmap_ro("/.backup/init"); - return init.contains("selinux_setup"); + if (access("/apex", F_OK) == 0) + return true; + if (access("/system/bin/init", F_OK) == 0) + return true; + // If we still have no indication, parse the original init and see what's up + auto init = raw_data::mmap_ro("/.backup/init"); + return init.contains("selinux_setup"); } diff --git a/native/jni/init/init.cpp b/native/jni/init/init.cpp index 9a69ef724..33e2283a9 100644 --- a/native/jni/init/init.cpp +++ b/native/jni/init/init.cpp @@ -24,163 +24,163 @@ using namespace std; #define ENABLE_TEST 0 constexpr int (*init_applet_main[])(int, char *[]) = - { magiskpolicy_main, magiskpolicy_main, nullptr }; + { magiskpolicy_main, magiskpolicy_main, nullptr }; static bool unxz(int fd, const uint8_t *buf, size_t size) { - uint8_t out[8192]; - xz_crc32_init(); - struct xz_dec *dec = xz_dec_init(XZ_DYNALLOC, 1 << 26); - struct xz_buf b = { - .in = buf, - .in_pos = 0, - .in_size = size, - .out = out, - .out_pos = 0, - .out_size = sizeof(out) - }; - enum xz_ret ret; - do { - ret = xz_dec_run(dec, &b); - if (ret != XZ_OK && ret != XZ_STREAM_END) - return false; - write(fd, out, b.out_pos); - b.out_pos = 0; - } while (b.in_pos != size); - return true; + uint8_t out[8192]; + xz_crc32_init(); + struct xz_dec *dec = xz_dec_init(XZ_DYNALLOC, 1 << 26); + struct xz_buf b = { + .in = buf, + .in_pos = 0, + .in_size = size, + .out = out, + .out_pos = 0, + .out_size = sizeof(out) + }; + enum xz_ret ret; + do { + ret = xz_dec_run(dec, &b); + if (ret != XZ_OK && ret != XZ_STREAM_END) + return false; + write(fd, out, b.out_pos); + b.out_pos = 0; + } while (b.in_pos != size); + return true; } int dump_magisk(const char *path, mode_t mode) { - int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); - if (fd < 0) - return 1; - if (!unxz(fd, magisk_xz, sizeof(magisk_xz))) - return 1; - close(fd); - return 0; + int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); + if (fd < 0) + return 1; + if (!unxz(fd, magisk_xz, sizeof(magisk_xz))) + return 1; + close(fd); + return 0; } static int dump_manager(const char *path, mode_t mode) { - int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); - if (fd < 0) - return 1; - if (!unxz(fd, manager_xz, sizeof(manager_xz))) - return 1; - close(fd); - return 0; + int fd = xopen(path, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, mode); + if (fd < 0) + return 1; + if (!unxz(fd, manager_xz, sizeof(manager_xz))) + return 1; + close(fd); + return 0; } class RecoveryInit : public BaseInit { public: - RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {} - void start() override { - LOGD("Ramdisk is recovery, abort\n"); - rename("/.backup/init", "/init"); - rm_rf("/.backup"); - exec_init(); - } + RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {} + void start() override { + LOGD("Ramdisk is recovery, abort\n"); + rename("/.backup/init", "/init"); + rm_rf("/.backup"); + exec_init(); + } }; #if ENABLE_TEST class TestInit : public BaseInit { public: - TestInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; - void start() override { - // Place init tests here - } + TestInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; + void start() override { + // Place init tests here + } }; static int test_main(int argc, char *argv[]) { - // Log to console - cmdline_logging(); - log_cb.ex = nop_ex; + // Log to console + cmdline_logging(); + log_cb.ex = nop_ex; - // Switch to isolate namespace - xunshare(CLONE_NEWNS); - xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr); + // Switch to isolate namespace + xunshare(CLONE_NEWNS); + xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr); - // Unmount everything in reverse - vector mounts; - parse_mnt("/proc/mounts", [&](mntent *me) { - if (me->mnt_dir != "/"sv) - mounts.emplace_back(me->mnt_dir); - return true; - }); - for (auto &m : reversed(mounts)) - xumount(m.data()); + // Unmount everything in reverse + vector mounts; + parse_mnt("/proc/mounts", [&](mntent *me) { + if (me->mnt_dir != "/"sv) + mounts.emplace_back(me->mnt_dir); + return true; + }); + for (auto &m : reversed(mounts)) + xumount(m.data()); - // chroot jail - chdir(dirname(argv[0])); - chroot("."); - chdir("/"); + // chroot jail + chdir(dirname(argv[0])); + chroot("."); + chdir("/"); - cmdline cmd{}; - load_kernel_info(&cmd); + cmdline cmd{}; + load_kernel_info(&cmd); - auto init = make_unique(argv, &cmd); - init->start(); + auto init = make_unique(argv, &cmd); + init->start(); - return 1; + return 1; } #endif // ENABLE_TEST static int magisk_proxy_main(int argc, char *argv[]) { - setup_klog(); - auto init = make_unique(argv); - init->start(); - return 1; + setup_klog(); + auto init = make_unique(argv); + init->start(); + return 1; } int main(int argc, char *argv[]) { - umask(0); + umask(0); - auto name = basename(argv[0]); - if (name == "magisk"sv) - return magisk_proxy_main(argc, argv); - for (int i = 0; init_applet[i]; ++i) { - if (strcmp(name, init_applet[i]) == 0) - return (*init_applet_main[i])(argc, argv); - } + auto name = basename(argv[0]); + if (name == "magisk"sv) + return magisk_proxy_main(argc, argv); + for (int i = 0; init_applet[i]; ++i) { + if (strcmp(name, init_applet[i]) == 0) + return (*init_applet_main[i])(argc, argv); + } #if ENABLE_TEST - if (getenv("INIT_TEST") != nullptr) - return test_main(argc, argv); + if (getenv("INIT_TEST") != nullptr) + return test_main(argc, argv); #endif - if (argc > 1 && argv[1] == "-x"sv) { - if (argv[2] == "magisk"sv) - return dump_magisk(argv[3], 0755); - else if (argv[2] == "manager"sv) - return dump_manager(argv[3], 0644); - } + if (argc > 1 && argv[1] == "-x"sv) { + if (argv[2] == "magisk"sv) + return dump_magisk(argv[3], 0755); + else if (argv[2] == "manager"sv) + return dump_manager(argv[3], 0644); + } - if (getpid() != 1) - return 1; + if (getpid() != 1) + return 1; - BaseInit *init; - cmdline cmd{}; + BaseInit *init; + cmdline cmd{}; - if (argc > 1 && argv[1] == "selinux_setup"sv) { - setup_klog(); - init = new SecondStageInit(argv); - } else { - // This will also mount /sys and /proc - load_kernel_info(&cmd); + if (argc > 1 && argv[1] == "selinux_setup"sv) { + setup_klog(); + init = new SecondStageInit(argv); + } else { + // This will also mount /sys and /proc + load_kernel_info(&cmd); - if (cmd.skip_initramfs) { - init = new SARInit(argv, &cmd); - } else { - if (cmd.force_normal_boot) - init = new FirstStageInit(argv, &cmd); - else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0) - init = new RecoveryInit(argv, &cmd); - else if (check_two_stage()) - init = new FirstStageInit(argv, &cmd); - else - init = new RootFSInit(argv, &cmd); - } - } + if (cmd.skip_initramfs) { + init = new SARInit(argv, &cmd); + } else { + if (cmd.force_normal_boot) + init = new FirstStageInit(argv, &cmd); + else if (access("/sbin/recovery", F_OK) == 0 || access("/system/bin/recovery", F_OK) == 0) + init = new RecoveryInit(argv, &cmd); + else if (check_two_stage()) + init = new FirstStageInit(argv, &cmd); + else + init = new RootFSInit(argv, &cmd); + } + } - // Run the main routine - init->start(); - exit(1); + // Run the main routine + init->start(); + exit(1); } diff --git a/native/jni/init/init.hpp b/native/jni/init/init.hpp index 2b15c02af..0642a5fd5 100644 --- a/native/jni/init/init.hpp +++ b/native/jni/init/init.hpp @@ -3,27 +3,27 @@ #include "raw_data.hpp" struct cmdline { - bool skip_initramfs; - bool force_normal_boot; - bool rootwait; - char slot[3]; - char dt_dir[64]; - char fstab_suffix[32]; - char hardware[32]; - char hardware_plat[32]; + bool skip_initramfs; + bool force_normal_boot; + bool rootwait; + char slot[3]; + char dt_dir[64]; + char fstab_suffix[32]; + char hardware[32]; + char hardware_plat[32]; }; struct fstab_entry { - std::string dev; - std::string mnt_point; - std::string type; - std::string mnt_flags; - std::string fsmgr_flags; + std::string dev; + std::string mnt_point; + std::string type; + std::string mnt_flags; + std::string fsmgr_flags; - fstab_entry() = default; - fstab_entry(const fstab_entry &) = delete; - fstab_entry(fstab_entry &&) = default; - void to_file(FILE *fp); + fstab_entry() = default; + fstab_entry(const fstab_entry &) = delete; + fstab_entry(fstab_entry &&) = default; + void to_file(FILE *fp); }; #define INIT_SOCKET "MAGISKINIT" @@ -40,41 +40,41 @@ void setup_klog(); class BaseInit { protected: - cmdline *cmd; - char **argv; - std::vector mount_list; + cmdline *cmd; + char **argv; + std::vector mount_list; - [[noreturn]] void exec_init(); - void read_dt_fstab(std::vector &fstab); + [[noreturn]] void exec_init(); + void read_dt_fstab(std::vector &fstab); public: - BaseInit(char *argv[], cmdline *cmd) : cmd(cmd), argv(argv), mount_list{"/sys", "/proc"} {} - virtual ~BaseInit() = default; - virtual void start() = 0; + BaseInit(char *argv[], cmdline *cmd) : cmd(cmd), argv(argv), mount_list{"/sys", "/proc"} {} + virtual ~BaseInit() = default; + virtual void start() = 0; }; class MagiskInit : public BaseInit { protected: - auto_data self; - auto_data config; - std::string custom_rules_dir; + auto_data self; + auto_data config; + std::string custom_rules_dir; - void mount_with_dt(); - bool patch_sepolicy(const char *file); - void setup_tmp(const char *path); - void mount_rules_dir(const char *dev_base, const char *mnt_base); + void mount_with_dt(); + bool patch_sepolicy(const char *file); + void setup_tmp(const char *path); + void mount_rules_dir(const char *dev_base, const char *mnt_base); public: - MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {} + MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {} }; class SARBase : public MagiskInit { protected: - std::vector overlays; + std::vector overlays; - void backup_files(); - void patch_rootdir(); - void mount_system_root(); + void backup_files(); + void patch_rootdir(); + void mount_system_root(); public: - SARBase(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {} + SARBase(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {} }; /*************** @@ -83,31 +83,31 @@ public: class FirstStageInit : public BaseInit { private: - void prepare(); + void prepare(); public: - FirstStageInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) { - LOGD("%s\n", __FUNCTION__); - }; - void start() override { - prepare(); - exec_init(); - } + FirstStageInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) { + LOGD("%s\n", __FUNCTION__); + }; + void start() override { + prepare(); + exec_init(); + } }; class SecondStageInit : public SARBase { private: - void prepare(); + void prepare(); public: - SecondStageInit(char *argv[]) : SARBase(argv, nullptr) { - LOGD("%s\n", __FUNCTION__); - // Do not unmount /sys and /proc - mount_list.clear(); - }; - void start() override { - prepare(); - patch_rootdir(); - exec_init(); - } + SecondStageInit(char *argv[]) : SARBase(argv, nullptr) { + LOGD("%s\n", __FUNCTION__); + // Do not unmount /sys and /proc + mount_list.clear(); + }; + void start() override { + prepare(); + patch_rootdir(); + exec_init(); + } }; /************* @@ -116,22 +116,22 @@ public: class SARInit : public SARBase { private: - bool is_two_stage; + bool is_two_stage; - void early_mount(); - void first_stage_prep(); + void early_mount(); + void first_stage_prep(); public: - SARInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd), is_two_stage(false) { - LOGD("%s\n", __FUNCTION__); - }; - void start() override { - early_mount(); - if (is_two_stage) - first_stage_prep(); - else - patch_rootdir(); - exec_init(); - } + SARInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd), is_two_stage(false) { + LOGD("%s\n", __FUNCTION__); + }; + void start() override { + early_mount(); + if (is_two_stage) + first_stage_prep(); + else + patch_rootdir(); + exec_init(); + } }; /************ @@ -140,23 +140,23 @@ public: class RootFSInit : public MagiskInit { private: - void early_mount(); - void patch_rootfs(); + void early_mount(); + void patch_rootfs(); public: - RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) { - LOGD("%s\n", __FUNCTION__); - } - void start() override { - early_mount(); - patch_rootfs(); - exec_init(); - } + RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) { + LOGD("%s\n", __FUNCTION__); + } + void start() override { + early_mount(); + patch_rootfs(); + exec_init(); + } }; class MagiskProxy : public MagiskInit { public: - explicit MagiskProxy(char *argv[]) : MagiskInit(argv, nullptr) { - LOGD("%s\n", __FUNCTION__); - } - void start() override; + explicit MagiskProxy(char *argv[]) : MagiskInit(argv, nullptr) { + LOGD("%s\n", __FUNCTION__); + } + void start() override; }; diff --git a/native/jni/init/mount.cpp b/native/jni/init/mount.cpp index ebea25c43..a32da3754 100644 --- a/native/jni/init/mount.cpp +++ b/native/jni/init/mount.cpp @@ -11,406 +11,406 @@ using namespace std; static string rtrim(string &&str) { - // Trim space, newline, and null byte from end of string - while (memchr(" \n\r", str[str.length() - 1], 4)) - str.pop_back(); - return std::move(str); + // Trim space, newline, and null byte from end of string + while (memchr(" \n\r", str[str.length() - 1], 4)) + str.pop_back(); + return std::move(str); } struct devinfo { - int major; - int minor; - char devname[32]; - char partname[32]; - char dmname[32]; + int major; + int minor; + char devname[32]; + char partname[32]; + char dmname[32]; }; static vector dev_list; static void parse_device(devinfo *dev, const char *uevent) { - dev->partname[0] = '\0'; - parse_prop_file(uevent, [=](string_view key, string_view value) -> bool { - if (key == "MAJOR") - dev->major = parse_int(value.data()); - else if (key == "MINOR") - dev->minor = parse_int(value.data()); - else if (key == "DEVNAME") - strcpy(dev->devname, value.data()); - else if (key == "PARTNAME") - strcpy(dev->partname, value.data()); + dev->partname[0] = '\0'; + parse_prop_file(uevent, [=](string_view key, string_view value) -> bool { + if (key == "MAJOR") + dev->major = parse_int(value.data()); + else if (key == "MINOR") + dev->minor = parse_int(value.data()); + else if (key == "DEVNAME") + strcpy(dev->devname, value.data()); + else if (key == "PARTNAME") + strcpy(dev->partname, value.data()); - return true; - }); + return true; + }); } static void collect_devices() { - char path[128]; - devinfo dev{}; - if (auto dir = xopen_dir("/sys/dev/block"); dir) { - for (dirent *entry; (entry = readdir(dir.get()));) { - if (entry->d_name == "."sv || entry->d_name == ".."sv) - continue; - sprintf(path, "/sys/dev/block/%s/uevent", entry->d_name); - parse_device(&dev, path); - sprintf(path, "/sys/dev/block/%s/dm/name", entry->d_name); - if (access(path, F_OK) == 0) { - auto name = rtrim(full_read(path)); - strcpy(dev.dmname, name.data()); - } - dev_list.push_back(dev); - } - } + char path[128]; + devinfo dev{}; + if (auto dir = xopen_dir("/sys/dev/block"); dir) { + for (dirent *entry; (entry = readdir(dir.get()));) { + if (entry->d_name == "."sv || entry->d_name == ".."sv) + continue; + sprintf(path, "/sys/dev/block/%s/uevent", entry->d_name); + parse_device(&dev, path); + sprintf(path, "/sys/dev/block/%s/dm/name", entry->d_name); + if (access(path, F_OK) == 0) { + auto name = rtrim(full_read(path)); + strcpy(dev.dmname, name.data()); + } + dev_list.push_back(dev); + } + } } static struct { - char partname[32]; - char block_dev[64]; + char partname[32]; + char block_dev[64]; } blk_info; static int64_t setup_block(bool write_block) { - if (dev_list.empty()) - collect_devices(); - xmkdir("/dev", 0755); - xmkdir("/dev/block", 0755); + if (dev_list.empty()) + collect_devices(); + xmkdir("/dev", 0755); + xmkdir("/dev/block", 0755); - for (int tries = 0; tries < 3; ++tries) { - for (auto &dev : dev_list) { - if (strcasecmp(dev.partname, blk_info.partname) == 0) - LOGD("Setup %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor); - else if (strcasecmp(dev.dmname, blk_info.partname) == 0) - LOGD("Setup %s: [%s] (%d, %d)\n", dev.dmname, dev.devname, dev.major, dev.minor); - else - continue; + for (int tries = 0; tries < 3; ++tries) { + for (auto &dev : dev_list) { + if (strcasecmp(dev.partname, blk_info.partname) == 0) + LOGD("Setup %s: [%s] (%d, %d)\n", dev.partname, dev.devname, dev.major, dev.minor); + else if (strcasecmp(dev.dmname, blk_info.partname) == 0) + LOGD("Setup %s: [%s] (%d, %d)\n", dev.dmname, dev.devname, dev.major, dev.minor); + else + continue; - if (write_block) { - sprintf(blk_info.block_dev, "/dev/block/%s", dev.devname); - } - dev_t rdev = makedev(dev.major, dev.minor); - mknod(blk_info.block_dev, S_IFBLK | 0600, rdev); - return rdev; - } - // Wait 10ms and try again - usleep(10000); - dev_list.clear(); - collect_devices(); - } + if (write_block) { + sprintf(blk_info.block_dev, "/dev/block/%s", dev.devname); + } + dev_t rdev = makedev(dev.major, dev.minor); + mknod(blk_info.block_dev, S_IFBLK | 0600, rdev); + return rdev; + } + // Wait 10ms and try again + usleep(10000); + dev_list.clear(); + collect_devices(); + } - // The requested partname does not exist - return -1; + // The requested partname does not exist + return -1; } static bool is_lnk(const char *name) { - struct stat st; - if (lstat(name, &st)) - return false; - return S_ISLNK(st.st_mode); + struct stat st; + if (lstat(name, &st)) + return false; + return S_ISLNK(st.st_mode); } #define read_info(val) \ if (access(#val, F_OK) == 0) {\ - entry.val = rtrim(full_read(#val)); \ + entry.val = rtrim(full_read(#val)); \ } void BaseInit::read_dt_fstab(vector &fstab) { - if (access(cmd->dt_dir, F_OK) != 0) - return; + if (access(cmd->dt_dir, F_OK) != 0) + return; - char cwd[128]; - getcwd(cwd, sizeof(cwd)); - chdir(cmd->dt_dir); - run_finally cd([&]{ chdir(cwd); }); + char cwd[128]; + getcwd(cwd, sizeof(cwd)); + chdir(cmd->dt_dir); + run_finally cd([&]{ chdir(cwd); }); - if (access("fstab", F_OK) != 0) - return; - chdir("fstab"); + if (access("fstab", F_OK) != 0) + return; + chdir("fstab"); - // Make sure dt fstab is enabled - if (access("status", F_OK) == 0) { - auto status = rtrim(full_read("status")); - if (status != "okay" && status != "ok") - return; - } + // Make sure dt fstab is enabled + if (access("status", F_OK) == 0) { + auto status = rtrim(full_read("status")); + if (status != "okay" && status != "ok") + return; + } - auto dir = xopen_dir("."); - for (dirent *dp; (dp = xreaddir(dir.get()));) { - if (dp->d_type != DT_DIR) - continue; - chdir(dp->d_name); - run_finally f([]{ chdir(".."); }); + auto dir = xopen_dir("."); + for (dirent *dp; (dp = xreaddir(dir.get()));) { + if (dp->d_type != DT_DIR) + continue; + chdir(dp->d_name); + run_finally f([]{ chdir(".."); }); - if (access("status", F_OK) == 0) { - auto status = rtrim(full_read("status")); - if (status != "okay" && status != "ok") - continue; - } + if (access("status", F_OK) == 0) { + auto status = rtrim(full_read("status")); + if (status != "okay" && status != "ok") + continue; + } - fstab_entry entry; + fstab_entry entry; - read_info(dev); - read_info(mnt_point) else { - entry.mnt_point = "/"; - entry.mnt_point += dp->d_name; - } - read_info(type); - read_info(mnt_flags); - read_info(fsmgr_flags); + read_info(dev); + read_info(mnt_point) else { + entry.mnt_point = "/"; + entry.mnt_point += dp->d_name; + } + read_info(type); + read_info(mnt_flags); + read_info(fsmgr_flags); - fstab.emplace_back(std::move(entry)); - } + fstab.emplace_back(std::move(entry)); + } } void MagiskInit::mount_with_dt() { - vector fstab; - read_dt_fstab(fstab); - for (const auto &entry : fstab) { - if (is_lnk(entry.mnt_point.data())) - continue; - // Derive partname from dev - sprintf(blk_info.partname, "%s%s", basename(entry.dev.data()), cmd->slot); - setup_block(true); - xmkdir(entry.mnt_point.data(), 0755); - xmount(blk_info.block_dev, entry.mnt_point.data(), entry.type.data(), MS_RDONLY, nullptr); - mount_list.push_back(entry.mnt_point); - } + vector fstab; + read_dt_fstab(fstab); + for (const auto &entry : fstab) { + if (is_lnk(entry.mnt_point.data())) + continue; + // Derive partname from dev + sprintf(blk_info.partname, "%s%s", basename(entry.dev.data()), cmd->slot); + setup_block(true); + xmkdir(entry.mnt_point.data(), 0755); + xmount(blk_info.block_dev, entry.mnt_point.data(), entry.type.data(), MS_RDONLY, nullptr); + mount_list.push_back(entry.mnt_point); + } } static void switch_root(const string &path) { - LOGD("Switch root to %s\n", path.data()); - int root = xopen("/", O_RDONLY); - vector mounts; - parse_mnt("/proc/mounts", [&](mntent *me) { - // Skip root and self - if (me->mnt_dir == "/"sv || me->mnt_dir == path) - return true; - // Do not include subtrees - for (const auto &m : mounts) { - if (strncmp(me->mnt_dir, m.data(), m.length()) == 0 && me->mnt_dir[m.length()] == '/') - return true; - } - mounts.emplace_back(me->mnt_dir); - return true; - }); - for (auto &dir : mounts) { - auto new_path = path + dir; - mkdir(new_path.data(), 0755); - xmount(dir.data(), new_path.data(), nullptr, MS_MOVE, nullptr); - } - chdir(path.data()); - xmount(path.data(), "/", nullptr, MS_MOVE, nullptr); - chroot("."); + LOGD("Switch root to %s\n", path.data()); + int root = xopen("/", O_RDONLY); + vector mounts; + parse_mnt("/proc/mounts", [&](mntent *me) { + // Skip root and self + if (me->mnt_dir == "/"sv || me->mnt_dir == path) + return true; + // Do not include subtrees + for (const auto &m : mounts) { + if (strncmp(me->mnt_dir, m.data(), m.length()) == 0 && me->mnt_dir[m.length()] == '/') + return true; + } + mounts.emplace_back(me->mnt_dir); + return true; + }); + for (auto &dir : mounts) { + auto new_path = path + dir; + mkdir(new_path.data(), 0755); + xmount(dir.data(), new_path.data(), nullptr, MS_MOVE, nullptr); + } + chdir(path.data()); + xmount(path.data(), "/", nullptr, MS_MOVE, nullptr); + chroot("."); - LOGD("Cleaning rootfs\n"); - frm_rf(root); + LOGD("Cleaning rootfs\n"); + frm_rf(root); } void MagiskInit::mount_rules_dir(const char *dev_base, const char *mnt_base) { - char path[128]; - xrealpath(dev_base, blk_info.block_dev); - xrealpath(mnt_base, path); - char *b = blk_info.block_dev + strlen(blk_info.block_dev); - char *p = path + strlen(path); + char path[128]; + xrealpath(dev_base, blk_info.block_dev); + xrealpath(mnt_base, path); + char *b = blk_info.block_dev + strlen(blk_info.block_dev); + char *p = path + strlen(path); - auto do_mount = [&](const char *type) -> bool { - xmkdir(path, 0755); - bool success = xmount(blk_info.block_dev, path, type, 0, nullptr) == 0; - if (success) - mount_list.emplace_back(path); - return success; - }; + auto do_mount = [&](const char *type) -> bool { + xmkdir(path, 0755); + bool success = xmount(blk_info.block_dev, path, type, 0, nullptr) == 0; + if (success) + mount_list.emplace_back(path); + return success; + }; - // First try userdata - strcpy(blk_info.partname, "userdata"); - strcpy(b, "/data"); - strcpy(p, "/data"); - if (setup_block(false) < 0) { - // Try NVIDIA naming scheme - strcpy(blk_info.partname, "UDA"); - if (setup_block(false) < 0) - goto cache; - } - // Try to mount with either ext4 or f2fs - // Failure means either FDE or metadata encryption - if (!do_mount("ext4") && !do_mount("f2fs")) - goto cache; + // First try userdata + strcpy(blk_info.partname, "userdata"); + strcpy(b, "/data"); + strcpy(p, "/data"); + if (setup_block(false) < 0) { + // Try NVIDIA naming scheme + strcpy(blk_info.partname, "UDA"); + if (setup_block(false) < 0) + goto cache; + } + // Try to mount with either ext4 or f2fs + // Failure means either FDE or metadata encryption + if (!do_mount("ext4") && !do_mount("f2fs")) + goto cache; - strcpy(p, "/data/unencrypted"); - if (access(path, F_OK) == 0) { - // FBE, need to use an unencrypted path - custom_rules_dir = path + "/magisk"s; - } else { - // Skip if /data/adb does not exist - strcpy(p, "/data/adb"); - if (access(path, F_OK) != 0) - return; - // Unencrypted, directly use module paths - custom_rules_dir = string(mnt_base) + MODULEROOT; - } - goto success; + strcpy(p, "/data/unencrypted"); + if (access(path, F_OK) == 0) { + // FBE, need to use an unencrypted path + custom_rules_dir = path + "/magisk"s; + } else { + // Skip if /data/adb does not exist + strcpy(p, "/data/adb"); + if (access(path, F_OK) != 0) + return; + // Unencrypted, directly use module paths + custom_rules_dir = string(mnt_base) + MODULEROOT; + } + goto success; cache: - // Fallback to cache - strcpy(blk_info.partname, "cache"); - strcpy(b, "/cache"); - strcpy(p, "/cache"); - if (setup_block(false) < 0) { - // Try NVIDIA naming scheme - strcpy(blk_info.partname, "CAC"); - if (setup_block(false) < 0) - goto metadata; - } - if (!do_mount("ext4")) - goto metadata; - custom_rules_dir = path + "/magisk"s; - goto success; + // Fallback to cache + strcpy(blk_info.partname, "cache"); + strcpy(b, "/cache"); + strcpy(p, "/cache"); + if (setup_block(false) < 0) { + // Try NVIDIA naming scheme + strcpy(blk_info.partname, "CAC"); + if (setup_block(false) < 0) + goto metadata; + } + if (!do_mount("ext4")) + goto metadata; + custom_rules_dir = path + "/magisk"s; + goto success; metadata: - // Fallback to metadata - strcpy(blk_info.partname, "metadata"); - strcpy(b, "/metadata"); - strcpy(p, "/metadata"); - if (setup_block(false) < 0 || !do_mount("ext4")) - goto persist; - custom_rules_dir = path + "/magisk"s; - goto success; + // Fallback to metadata + strcpy(blk_info.partname, "metadata"); + strcpy(b, "/metadata"); + strcpy(p, "/metadata"); + if (setup_block(false) < 0 || !do_mount("ext4")) + goto persist; + custom_rules_dir = path + "/magisk"s; + goto success; persist: - // Fallback to persist - strcpy(blk_info.partname, "persist"); - strcpy(b, "/persist"); - strcpy(p, "/persist"); - if (setup_block(false) < 0 || !do_mount("ext4")) - return; - custom_rules_dir = path + "/magisk"s; + // Fallback to persist + strcpy(blk_info.partname, "persist"); + strcpy(b, "/persist"); + strcpy(p, "/persist"); + if (setup_block(false) < 0 || !do_mount("ext4")) + return; + custom_rules_dir = path + "/magisk"s; success: - // Create symlinks so we don't need to go through this logic again - strcpy(p, "/sepolicy.rules"); - xsymlink(custom_rules_dir.data(), path); + // Create symlinks so we don't need to go through this logic again + strcpy(p, "/sepolicy.rules"); + xsymlink(custom_rules_dir.data(), path); } void RootFSInit::early_mount() { - self = raw_data::read("/init"); + self = raw_data::read("/init"); - LOGD("Restoring /init\n"); - rename("/.backup/init", "/init"); + LOGD("Restoring /init\n"); + rename("/.backup/init", "/init"); - mount_with_dt(); + mount_with_dt(); } void SARBase::backup_files() { - if (access("/overlay.d", F_OK) == 0) - backup_folder("/overlay.d", overlays); + if (access("/overlay.d", F_OK) == 0) + backup_folder("/overlay.d", overlays); - self = raw_data::read("/proc/self/exe"); - if (access("/.backup/.magisk", R_OK) == 0) - config = raw_data::read("/.backup/.magisk"); + self = raw_data::read("/proc/self/exe"); + if (access("/.backup/.magisk", R_OK) == 0) + config = raw_data::read("/.backup/.magisk"); } void SARBase::mount_system_root() { - LOGD("Early mount system_root\n"); - strcpy(blk_info.block_dev, "/dev/root"); + LOGD("Early mount system_root\n"); + strcpy(blk_info.block_dev, "/dev/root"); - do { - // Try legacy SAR dm-verity - strcpy(blk_info.partname, "vroot"); - auto dev = setup_block(false); - if (dev >= 0) - goto mount_root; + do { + // Try legacy SAR dm-verity + strcpy(blk_info.partname, "vroot"); + auto dev = setup_block(false); + if (dev >= 0) + goto mount_root; - // Try NVIDIA naming scheme - strcpy(blk_info.partname, "APP"); - dev = setup_block(false); - if (dev >= 0) - goto mount_root; + // Try NVIDIA naming scheme + strcpy(blk_info.partname, "APP"); + dev = setup_block(false); + if (dev >= 0) + goto mount_root; - sprintf(blk_info.partname, "system%s", cmd->slot); - dev = setup_block(false); - if (dev >= 0) - goto mount_root; + sprintf(blk_info.partname, "system%s", cmd->slot); + dev = setup_block(false); + if (dev >= 0) + goto mount_root; - // Poll forever if rootwait was given in cmdline - } while (cmd->rootwait); + // Poll forever if rootwait was given in cmdline + } while (cmd->rootwait); - // We don't really know what to do at this point... - LOGE("Cannot find root partition, abort\n"); - exit(1); + // We don't really know what to do at this point... + LOGE("Cannot find root partition, abort\n"); + exit(1); mount_root: - xmkdir("/system_root", 0755); - if (xmount("/dev/root", "/system_root", "ext4", MS_RDONLY, nullptr)) - xmount("/dev/root", "/system_root", "erofs", MS_RDONLY, nullptr); + xmkdir("/system_root", 0755); + if (xmount("/dev/root", "/system_root", "ext4", MS_RDONLY, nullptr)) + xmount("/dev/root", "/system_root", "erofs", MS_RDONLY, nullptr); } void SARInit::early_mount() { - backup_files(); - mount_system_root(); - switch_root("/system_root"); + backup_files(); + mount_system_root(); + switch_root("/system_root"); - { - auto init = raw_data::mmap_ro("/init"); - is_two_stage = init.contains("selinux_setup"); - } - LOGD("is_two_stage: [%d]\n", is_two_stage); + { + auto init = raw_data::mmap_ro("/init"); + is_two_stage = init.contains("selinux_setup"); + } + LOGD("is_two_stage: [%d]\n", is_two_stage); - if (!is_two_stage) { - // Make dev writable - xmkdir("/dev", 0755); - xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755"); - mount_list.emplace_back("/dev"); - mount_with_dt(); - } + if (!is_two_stage) { + // Make dev writable + xmkdir("/dev", 0755); + xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755"); + mount_list.emplace_back("/dev"); + mount_with_dt(); + } } void SecondStageInit::prepare() { - backup_files(); + backup_files(); - umount2("/init", MNT_DETACH); - umount2("/proc/self/exe", MNT_DETACH); + umount2("/init", MNT_DETACH); + umount2("/proc/self/exe", MNT_DETACH); - if (access("/system_root", F_OK) == 0) - switch_root("/system_root"); + if (access("/system_root", F_OK) == 0) + switch_root("/system_root"); } void BaseInit::exec_init() { - // Unmount in reverse order - for (auto &p : reversed(mount_list)) { - if (xumount(p.data()) == 0) - LOGD("Unmount [%s]\n", p.data()); - } - execv("/init", argv); - exit(1); + // Unmount in reverse order + for (auto &p : reversed(mount_list)) { + if (xumount(p.data()) == 0) + LOGD("Unmount [%s]\n", p.data()); + } + execv("/init", argv); + exit(1); } static void patch_socket_name(const char *path) { - char rstr[16]; - gen_rand_str(rstr, sizeof(rstr)); - auto bin = raw_data::mmap_rw(path); - bin.patch({ make_pair(MAIN_SOCKET, rstr) }); + char rstr[16]; + gen_rand_str(rstr, sizeof(rstr)); + auto bin = raw_data::mmap_rw(path); + bin.patch({ make_pair(MAIN_SOCKET, rstr) }); } void MagiskInit::setup_tmp(const char *path) { - LOGD("Setup Magisk tmp at %s\n", path); - xmount("tmpfs", path, "tmpfs", 0, "mode=755"); + LOGD("Setup Magisk tmp at %s\n", path); + xmount("tmpfs", path, "tmpfs", 0, "mode=755"); - chdir(path); + chdir(path); - xmkdir(INTLROOT, 0755); - xmkdir(MIRRDIR, 0); - xmkdir(BLOCKDIR, 0); + xmkdir(INTLROOT, 0755); + xmkdir(MIRRDIR, 0); + xmkdir(BLOCKDIR, 0); - int fd = xopen(INTLROOT "/config", O_WRONLY | O_CREAT, 0); - xwrite(fd, config.buf, config.sz); - close(fd); - fd = xopen("magiskinit", O_WRONLY | O_CREAT, 0755); - xwrite(fd, self.buf, self.sz); - close(fd); - dump_magisk("magisk", 0755); - patch_socket_name("magisk"); + int fd = xopen(INTLROOT "/config", O_WRONLY | O_CREAT, 0); + xwrite(fd, config.buf, config.sz); + close(fd); + fd = xopen("magiskinit", O_WRONLY | O_CREAT, 0755); + xwrite(fd, self.buf, self.sz); + close(fd); + dump_magisk("magisk", 0755); + patch_socket_name("magisk"); - // Create applet symlinks - for (int i = 0; applet_names[i]; ++i) - xsymlink("./magisk", applet_names[i]); - xsymlink("./magiskinit", "magiskpolicy"); - xsymlink("./magiskinit", "supolicy"); + // Create applet symlinks + for (int i = 0; applet_names[i]; ++i) + xsymlink("./magisk", applet_names[i]); + xsymlink("./magiskinit", "magiskpolicy"); + xsymlink("./magiskinit", "supolicy"); - chdir("/"); + chdir("/"); } diff --git a/native/jni/init/raw_data.cpp b/native/jni/init/raw_data.cpp index 01ae06372..1164e1e18 100644 --- a/native/jni/init/raw_data.cpp +++ b/native/jni/init/raw_data.cpp @@ -3,62 +3,62 @@ using namespace std; int data_holder::patch(str_pairs list) { - if (buf == nullptr) - return 0; - int count = 0; - for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) { - for (auto [from, to] : list) { - if (memcmp(p, from.data(), from.length() + 1) == 0) { - LOGD("Replace [%s] -> [%s]\n", from.data(), to.data()); - memset(p, 0, from.length()); - memcpy(p, to.data(), to.length()); - ++count; - p += from.length(); - } - } - } - return count; + if (buf == nullptr) + return 0; + int count = 0; + for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) { + for (auto [from, to] : list) { + if (memcmp(p, from.data(), from.length() + 1) == 0) { + LOGD("Replace [%s] -> [%s]\n", from.data(), to.data()); + memset(p, 0, from.length()); + memcpy(p, to.data(), to.length()); + ++count; + p += from.length(); + } + } + } + return count; } bool data_holder::contains(string_view pattern) { - if (buf == nullptr) - return false; - for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) { - if (memcmp(p, pattern.data(), pattern.length() + 1) == 0) { - LOGD("Found pattern [%s]\n", pattern.data()); - return true; - } - } - return false; + if (buf == nullptr) + return false; + for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) { + if (memcmp(p, pattern.data(), pattern.length() + 1) == 0) { + LOGD("Found pattern [%s]\n", pattern.data()); + return true; + } + } + return false; } void data_holder::consume(data_holder &other) { - buf = other.buf; - sz = other.sz; - other.buf = nullptr; - other.sz = 0; + buf = other.buf; + sz = other.sz; + other.buf = nullptr; + other.sz = 0; } auto_data raw_data::read(int fd) { - auto_data data; - fd_full_read(fd, data.buf, data.sz); - return data; + auto_data data; + fd_full_read(fd, data.buf, data.sz); + return data; } auto_data raw_data::read(const char *name) { - auto_data data; - full_read(name, data.buf, data.sz); - return data; + auto_data data; + full_read(name, data.buf, data.sz); + return data; } auto_data raw_data::mmap_rw(const char *name) { - auto_data data; - ::mmap_rw(name, data.buf, data.sz); - return data; + auto_data data; + ::mmap_rw(name, data.buf, data.sz); + return data; } auto_data raw_data::mmap_ro(const char *name) { - auto_data data; - ::mmap_ro(name, data.buf, data.sz); - return data; + auto_data data; + ::mmap_ro(name, data.buf, data.sz); + return data; } diff --git a/native/jni/init/raw_data.hpp b/native/jni/init/raw_data.hpp index 5fa63d74c..049e05094 100644 --- a/native/jni/init/raw_data.hpp +++ b/native/jni/init/raw_data.hpp @@ -3,30 +3,30 @@ #include struct data_holder { - uint8_t *buf = nullptr; - size_t sz = 0; - using str_pairs = std::initializer_list>; - int patch(str_pairs list); - bool contains(std::string_view pattern); + uint8_t *buf = nullptr; + size_t sz = 0; + using str_pairs = std::initializer_list>; + int patch(str_pairs list); + bool contains(std::string_view pattern); protected: - void consume(data_holder &other); + void consume(data_holder &other); }; enum data_type { HEAP, MMAP }; template struct auto_data : public data_holder { - auto_data() = default; - auto_data(const auto_data&) = delete; - auto_data(auto_data &&other) { consume(other); } - ~auto_data() {} - auto_data& operator=(auto_data &&other) { consume(other); return *this; } + auto_data() = default; + auto_data(const auto_data&) = delete; + auto_data(auto_data &&other) { consume(other); } + ~auto_data() {} + auto_data& operator=(auto_data &&other) { consume(other); return *this; } }; template <> inline auto_data::~auto_data() { if (buf) munmap(buf, sz); } template <> inline auto_data::~auto_data() { free(buf); } namespace raw_data { - auto_data read(const char *name); - auto_data read(int fd); - auto_data mmap_rw(const char *name); - auto_data mmap_ro(const char *name); + auto_data read(const char *name); + auto_data read(int fd); + auto_data mmap_rw(const char *name); + auto_data mmap_ro(const char *name); } diff --git a/native/jni/init/rootdir.cpp b/native/jni/init/rootdir.cpp index 87a8fffdf..807babb8c 100644 --- a/native/jni/init/rootdir.cpp +++ b/native/jni/init/rootdir.cpp @@ -20,164 +20,164 @@ using namespace std; static vector rc_list; static void patch_init_rc(const char *src, const char *dest, const char *tmp_dir) { - FILE *rc = xfopen(dest, "we"); - file_readline(src, [=](string_view line) -> bool { - // Do not start vaultkeeper - if (str_contains(line, "start vaultkeeper")) { - LOGD("Remove vaultkeeper\n"); - return true; - } - // Do not run flash_recovery - if (str_starts(line, "service flash_recovery")) { - LOGD("Remove flash_recovery\n"); - fprintf(rc, "service flash_recovery /system/bin/xxxxx\n"); - return true; - } - // Else just write the line - fprintf(rc, "%s", line.data()); - return true; - }); + FILE *rc = xfopen(dest, "we"); + file_readline(src, [=](string_view line) -> bool { + // Do not start vaultkeeper + if (str_contains(line, "start vaultkeeper")) { + LOGD("Remove vaultkeeper\n"); + return true; + } + // Do not run flash_recovery + if (str_starts(line, "service flash_recovery")) { + LOGD("Remove flash_recovery\n"); + fprintf(rc, "service flash_recovery /system/bin/xxxxx\n"); + return true; + } + // Else just write the line + fprintf(rc, "%s", line.data()); + return true; + }); - fprintf(rc, "\n"); + fprintf(rc, "\n"); - // Inject custom rc scripts - for (auto &script : rc_list) { - // Replace template arguments of rc scripts with dynamic paths - replace_all(script, "${MAGISKTMP}", tmp_dir); - fprintf(rc, "\n%s\n", script.data()); - } - rc_list.clear(); + // Inject custom rc scripts + for (auto &script : rc_list) { + // Replace template arguments of rc scripts with dynamic paths + replace_all(script, "${MAGISKTMP}", tmp_dir); + fprintf(rc, "\n%s\n", script.data()); + } + rc_list.clear(); - // Inject Magisk rc scripts - char pfd_svc[16], ls_svc[16], bc_svc[16]; - gen_rand_str(pfd_svc, sizeof(pfd_svc)); - gen_rand_str(ls_svc, sizeof(ls_svc)); - gen_rand_str(bc_svc, sizeof(bc_svc)); - LOGD("Inject magisk services: [%s] [%s] [%s]\n", pfd_svc, ls_svc, bc_svc); - fprintf(rc, MAGISK_RC, tmp_dir, pfd_svc, ls_svc, bc_svc); + // Inject Magisk rc scripts + char pfd_svc[16], ls_svc[16], bc_svc[16]; + gen_rand_str(pfd_svc, sizeof(pfd_svc)); + gen_rand_str(ls_svc, sizeof(ls_svc)); + gen_rand_str(bc_svc, sizeof(bc_svc)); + LOGD("Inject magisk services: [%s] [%s] [%s]\n", pfd_svc, ls_svc, bc_svc); + fprintf(rc, MAGISK_RC, tmp_dir, pfd_svc, ls_svc, bc_svc); - fclose(rc); - clone_attr(src, dest); + fclose(rc); + clone_attr(src, dest); } static void load_overlay_rc(const char *overlay) { - auto dir = open_dir(overlay); - if (!dir) return; + auto dir = open_dir(overlay); + if (!dir) return; - int dfd = dirfd(dir.get()); - // Do not allow overwrite init.rc - unlinkat(dfd, "init.rc", 0); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (str_ends(entry->d_name, ".rc")) { - LOGD("Found rc script [%s]\n", entry->d_name); - int rc = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC); - rc_list.push_back(fd_full_read(rc)); - close(rc); - unlinkat(dfd, entry->d_name, 0); - } - } + int dfd = dirfd(dir.get()); + // Do not allow overwrite init.rc + unlinkat(dfd, "init.rc", 0); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (str_ends(entry->d_name, ".rc")) { + LOGD("Found rc script [%s]\n", entry->d_name); + int rc = xopenat(dfd, entry->d_name, O_RDONLY | O_CLOEXEC); + rc_list.push_back(fd_full_read(rc)); + close(rc); + unlinkat(dfd, entry->d_name, 0); + } + } } bool MagiskInit::patch_sepolicy(const char *file) { - bool patch_init = false; - sepolicy *sepol = nullptr; + bool patch_init = false; + sepolicy *sepol = nullptr; - if (access(SPLIT_PLAT_CIL, R_OK) == 0) { - LOGD("sepol: split policy\n"); - patch_init = true; - } else if (access("/sepolicy", R_OK) == 0) { - LOGD("sepol: monolithic policy\n"); - sepol = sepolicy::from_file("/sepolicy"); - } else { - LOGD("sepol: no selinux\n"); - return false; - } + if (access(SPLIT_PLAT_CIL, R_OK) == 0) { + LOGD("sepol: split policy\n"); + patch_init = true; + } else if (access("/sepolicy", R_OK) == 0) { + LOGD("sepol: monolithic policy\n"); + sepol = sepolicy::from_file("/sepolicy"); + } else { + LOGD("sepol: no selinux\n"); + return false; + } - if (access(SELINUX_VERSION, F_OK) != 0) { - // Mount selinuxfs to communicate with kernel - xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr); - mount_list.emplace_back(SELINUX_MNT); - } + if (access(SELINUX_VERSION, F_OK) != 0) { + // Mount selinuxfs to communicate with kernel + xmount("selinuxfs", SELINUX_MNT, "selinuxfs", 0, nullptr); + mount_list.emplace_back(SELINUX_MNT); + } - if (patch_init) - sepol = sepolicy::from_split(); + if (patch_init) + sepol = sepolicy::from_split(); - sepol->magisk_rules(); + sepol->magisk_rules(); - // Custom rules - if (!custom_rules_dir.empty()) { - if (auto dir = open_dir(custom_rules_dir.data())) { - for (dirent *entry; (entry = xreaddir(dir.get()));) { - auto rule = custom_rules_dir + "/" + entry->d_name + "/sepolicy.rule"; - if (access(rule.data(), R_OK) == 0) { - LOGD("Loading custom sepolicy patch: [%s]\n", rule.data()); - sepol->load_rule_file(rule.data()); - } - } - } - } + // Custom rules + if (!custom_rules_dir.empty()) { + if (auto dir = open_dir(custom_rules_dir.data())) { + for (dirent *entry; (entry = xreaddir(dir.get()));) { + auto rule = custom_rules_dir + "/" + entry->d_name + "/sepolicy.rule"; + if (access(rule.data(), R_OK) == 0) { + LOGD("Loading custom sepolicy patch: [%s]\n", rule.data()); + sepol->load_rule_file(rule.data()); + } + } + } + } - LOGD("Dumping sepolicy to: [%s]\n", file); - sepol->to_file(file); - delete sepol; + LOGD("Dumping sepolicy to: [%s]\n", file); + sepol->to_file(file); + delete sepol; - // Remove OnePlus stupid debug sepolicy and use our own - if (access("/sepolicy_debug", F_OK) == 0) { - unlink("/sepolicy_debug"); - link("/sepolicy", "/sepolicy_debug"); - } + // Remove OnePlus stupid debug sepolicy and use our own + if (access("/sepolicy_debug", F_OK) == 0) { + unlink("/sepolicy_debug"); + link("/sepolicy", "/sepolicy_debug"); + } - return patch_init; + return patch_init; } static void recreate_sbin(const char *mirror, bool use_bind_mount) { - auto dp = xopen_dir(mirror); - int src = dirfd(dp.get()); - char buf[4096]; - for (dirent *entry; (entry = xreaddir(dp.get()));) { - string sbin_path = "/sbin/"s + entry->d_name; - struct stat st; - fstatat(src, entry->d_name, &st, AT_SYMLINK_NOFOLLOW); - if (S_ISLNK(st.st_mode)) { - xreadlinkat(src, entry->d_name, buf, sizeof(buf)); - xsymlink(buf, sbin_path.data()); - } else { - sprintf(buf, "%s/%s", mirror, entry->d_name); - if (use_bind_mount) { - auto mode = st.st_mode & 0777; - // Create dummy - if (S_ISDIR(st.st_mode)) - xmkdir(sbin_path.data(), mode); - else - close(xopen(sbin_path.data(), O_CREAT | O_WRONLY | O_CLOEXEC, mode)); + auto dp = xopen_dir(mirror); + int src = dirfd(dp.get()); + char buf[4096]; + for (dirent *entry; (entry = xreaddir(dp.get()));) { + string sbin_path = "/sbin/"s + entry->d_name; + struct stat st; + fstatat(src, entry->d_name, &st, AT_SYMLINK_NOFOLLOW); + if (S_ISLNK(st.st_mode)) { + xreadlinkat(src, entry->d_name, buf, sizeof(buf)); + xsymlink(buf, sbin_path.data()); + } else { + sprintf(buf, "%s/%s", mirror, entry->d_name); + if (use_bind_mount) { + auto mode = st.st_mode & 0777; + // Create dummy + if (S_ISDIR(st.st_mode)) + xmkdir(sbin_path.data(), mode); + else + close(xopen(sbin_path.data(), O_CREAT | O_WRONLY | O_CLOEXEC, mode)); - xmount(buf, sbin_path.data(), nullptr, MS_BIND, nullptr); - } else { - xsymlink(buf, sbin_path.data()); - } - } - } + xmount(buf, sbin_path.data(), nullptr, MS_BIND, nullptr); + } else { + xsymlink(buf, sbin_path.data()); + } + } + } } static string magic_mount_list; static void magic_mount(const string &sdir, const string &ddir = "") { - auto dir = xopen_dir(sdir.data()); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - string src = sdir + "/" + entry->d_name; - string dest = ddir + "/" + entry->d_name; - if (access(dest.data(), F_OK) == 0) { - if (entry->d_type == DT_DIR) { - // Recursive - magic_mount(src, dest); - } else { - LOGD("Mount [%s] -> [%s]\n", src.data(), dest.data()); - xmount(src.data(), dest.data(), nullptr, MS_BIND, nullptr); - magic_mount_list += dest; - magic_mount_list += '\n'; - } - } - } + auto dir = xopen_dir(sdir.data()); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + string src = sdir + "/" + entry->d_name; + string dest = ddir + "/" + entry->d_name; + if (access(dest.data(), F_OK) == 0) { + if (entry->d_type == DT_DIR) { + // Recursive + magic_mount(src, dest); + } else { + LOGD("Mount [%s] -> [%s]\n", src.data(), dest.data()); + xmount(src.data(), dest.data(), nullptr, MS_BIND, nullptr); + magic_mount_list += dest; + magic_mount_list += '\n'; + } + } + } } #define ROOTMIR MIRRDIR "/system_root" @@ -186,169 +186,169 @@ static void magic_mount(const string &sdir, const string &ddir = "") { #define NEW_INITRC "/system/etc/init/hw/init.rc" void SARBase::patch_rootdir() { - string tmp_dir; - const char *sepol; + string tmp_dir; + const char *sepol; - if (access("/sbin", F_OK) == 0) { - tmp_dir = "/sbin"; - sepol = "/sbin/.se"; - } else { - char buf[8]; - gen_rand_str(buf, sizeof(buf)); - tmp_dir = "/dev/"s + buf; - xmkdir(tmp_dir.data(), 0); - sepol = "/dev/.se"; - } + if (access("/sbin", F_OK) == 0) { + tmp_dir = "/sbin"; + sepol = "/sbin/.se"; + } else { + char buf[8]; + gen_rand_str(buf, sizeof(buf)); + tmp_dir = "/dev/"s + buf; + xmkdir(tmp_dir.data(), 0); + sepol = "/dev/.se"; + } - setup_tmp(tmp_dir.data()); - chdir(tmp_dir.data()); + setup_tmp(tmp_dir.data()); + chdir(tmp_dir.data()); - mount_rules_dir(BLOCKDIR, MIRRDIR); + mount_rules_dir(BLOCKDIR, MIRRDIR); - // Mount system_root mirror - xmkdir(ROOTMIR, 0755); - xmount("/", ROOTMIR, nullptr, MS_BIND, nullptr); - mount_list.emplace_back(tmp_dir + "/" ROOTMIR); + // Mount system_root mirror + xmkdir(ROOTMIR, 0755); + xmount("/", ROOTMIR, nullptr, MS_BIND, nullptr); + mount_list.emplace_back(tmp_dir + "/" ROOTMIR); - // Recreate original sbin structure if necessary - if (tmp_dir == "/sbin") - recreate_sbin(ROOTMIR "/sbin", true); + // Recreate original sbin structure if necessary + if (tmp_dir == "/sbin") + recreate_sbin(ROOTMIR "/sbin", true); - // Patch init - int patch_count; - { - int src = xopen("/init", O_RDONLY | O_CLOEXEC); - auto init = raw_data::read(src); - patch_count = init.patch({ - make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */ - make_pair(MONOPOLICY, sepol) /* Redirect /sepolicy to custom path */ - }); - xmkdir(ROOTOVL, 0); - int dest = xopen(ROOTOVL "/init", O_CREAT | O_WRONLY | O_CLOEXEC, 0); - xwrite(dest, init.buf, init.sz); - fclone_attr(src, dest); - close(src); - close(dest); - } + // Patch init + int patch_count; + { + int src = xopen("/init", O_RDONLY | O_CLOEXEC); + auto init = raw_data::read(src); + patch_count = init.patch({ + make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */ + make_pair(MONOPOLICY, sepol) /* Redirect /sepolicy to custom path */ + }); + xmkdir(ROOTOVL, 0); + int dest = xopen(ROOTOVL "/init", O_CREAT | O_WRONLY | O_CLOEXEC, 0); + xwrite(dest, init.buf, init.sz); + fclone_attr(src, dest); + close(src); + close(dest); + } - if (patch_count != 2 && access(LIBSELINUX, F_OK) == 0) { - // init is dynamically linked, need to patch libselinux - auto lib = raw_data::read(LIBSELINUX); - lib.patch({make_pair(MONOPOLICY, sepol)}); - xmkdirs(dirname(ROOTOVL LIBSELINUX), 0755); - int dest = xopen(ROOTOVL LIBSELINUX, O_CREAT | O_WRONLY | O_CLOEXEC, 0); - xwrite(dest, lib.buf, lib.sz); - close(dest); - clone_attr(LIBSELINUX, ROOTOVL LIBSELINUX); - } + if (patch_count != 2 && access(LIBSELINUX, F_OK) == 0) { + // init is dynamically linked, need to patch libselinux + auto lib = raw_data::read(LIBSELINUX); + lib.patch({make_pair(MONOPOLICY, sepol)}); + xmkdirs(dirname(ROOTOVL LIBSELINUX), 0755); + int dest = xopen(ROOTOVL LIBSELINUX, O_CREAT | O_WRONLY | O_CLOEXEC, 0); + xwrite(dest, lib.buf, lib.sz); + close(dest); + clone_attr(LIBSELINUX, ROOTOVL LIBSELINUX); + } - // sepolicy - patch_sepolicy(sepol); + // sepolicy + patch_sepolicy(sepol); - // Restore backup files - struct sockaddr_un sun; - int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - if (connect(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)) == 0) { - LOGD("ACK init daemon to write backup files\n"); - // Let daemon know where tmp_dir is - write_string(sockfd, tmp_dir.data()); - // Wait for daemon to finish restoring files - int ack; - read(sockfd, &ack, sizeof(ack)); - } else { - LOGD("Restore backup files locally\n"); - restore_folder(ROOTOVL, overlays); - overlays.clear(); - } - close(sockfd); + // Restore backup files + struct sockaddr_un sun; + int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + if (connect(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)) == 0) { + LOGD("ACK init daemon to write backup files\n"); + // Let daemon know where tmp_dir is + write_string(sockfd, tmp_dir.data()); + // Wait for daemon to finish restoring files + int ack; + read(sockfd, &ack, sizeof(ack)); + } else { + LOGD("Restore backup files locally\n"); + restore_folder(ROOTOVL, overlays); + overlays.clear(); + } + close(sockfd); - // Handle overlay.d - load_overlay_rc(ROOTOVL); - if (access(ROOTOVL "/sbin", F_OK) == 0) { - // Move files in overlay.d/sbin into tmp_dir - mv_path(ROOTOVL "/sbin", "."); - } + // Handle overlay.d + load_overlay_rc(ROOTOVL); + if (access(ROOTOVL "/sbin", F_OK) == 0) { + // Move files in overlay.d/sbin into tmp_dir + mv_path(ROOTOVL "/sbin", "."); + } - // Patch init.rc - if (access("/init.rc", F_OK) == 0) { - patch_init_rc("/init.rc", ROOTOVL "/init.rc", tmp_dir.data()); - } else { - // Android 11's new init.rc - xmkdirs(dirname(ROOTOVL NEW_INITRC), 0755); - patch_init_rc(NEW_INITRC, ROOTOVL NEW_INITRC, tmp_dir.data()); - } + // Patch init.rc + if (access("/init.rc", F_OK) == 0) { + patch_init_rc("/init.rc", ROOTOVL "/init.rc", tmp_dir.data()); + } else { + // Android 11's new init.rc + xmkdirs(dirname(ROOTOVL NEW_INITRC), 0755); + patch_init_rc(NEW_INITRC, ROOTOVL NEW_INITRC, tmp_dir.data()); + } - // Mount rootdir - magic_mount(ROOTOVL); - int dest = xopen(ROOTMNT, O_WRONLY | O_CREAT | O_CLOEXEC, 0); - write(dest, magic_mount_list.data(), magic_mount_list.length()); - close(dest); + // Mount rootdir + magic_mount(ROOTOVL); + int dest = xopen(ROOTMNT, O_WRONLY | O_CREAT | O_CLOEXEC, 0); + write(dest, magic_mount_list.data(), magic_mount_list.length()); + close(dest); - chdir("/"); + chdir("/"); } #define TMP_MNTDIR "/dev/mnt" #define TMP_RULESDIR "/.backup/.sepolicy.rules" void RootFSInit::patch_rootfs() { - // Handle custom sepolicy rules - xmkdir(TMP_MNTDIR, 0755); - mount_rules_dir("/dev/block", TMP_MNTDIR); - // Preserve custom rule path - if (!custom_rules_dir.empty()) { - string rules_dir = "./" + custom_rules_dir.substr(sizeof(TMP_MNTDIR)); - xsymlink(rules_dir.data(), TMP_RULESDIR); - } + // Handle custom sepolicy rules + xmkdir(TMP_MNTDIR, 0755); + mount_rules_dir("/dev/block", TMP_MNTDIR); + // Preserve custom rule path + if (!custom_rules_dir.empty()) { + string rules_dir = "./" + custom_rules_dir.substr(sizeof(TMP_MNTDIR)); + xsymlink(rules_dir.data(), TMP_RULESDIR); + } - if (patch_sepolicy("/sepolicy")) { - auto init = raw_data::mmap_rw("/init"); - init.patch({ make_pair(SPLIT_PLAT_CIL, "xxx") }); - } + if (patch_sepolicy("/sepolicy")) { + auto init = raw_data::mmap_rw("/init"); + init.patch({ make_pair(SPLIT_PLAT_CIL, "xxx") }); + } - // Handle overlays - if (access("/overlay.d", F_OK) == 0) { - LOGD("Merge overlay.d\n"); - load_overlay_rc("/overlay.d"); - mv_path("/overlay.d", "/"); - } + // Handle overlays + if (access("/overlay.d", F_OK) == 0) { + LOGD("Merge overlay.d\n"); + load_overlay_rc("/overlay.d"); + mv_path("/overlay.d", "/"); + } - patch_init_rc("/init.rc", "/init.p.rc", "/sbin"); - rename("/init.p.rc", "/init.rc"); + patch_init_rc("/init.rc", "/init.p.rc", "/sbin"); + rename("/init.p.rc", "/init.rc"); - // Create hardlink mirror of /sbin to /root - mkdir("/root", 0750); - clone_attr("/sbin", "/root"); - link_path("/sbin", "/root"); + // Create hardlink mirror of /sbin to /root + mkdir("/root", 0750); + clone_attr("/sbin", "/root"); + link_path("/sbin", "/root"); - // Dump magiskinit as magisk - int fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755); - write(fd, self.buf, self.sz); - close(fd); + // Dump magiskinit as magisk + int fd = xopen("/sbin/magisk", O_WRONLY | O_CREAT, 0755); + write(fd, self.buf, self.sz); + close(fd); } void MagiskProxy::start() { - // Mount rootfs as rw to do post-init rootfs patches - xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr); + // Mount rootfs as rw to do post-init rootfs patches + xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr); - // Backup stuffs before removing them - self = raw_data::read("/sbin/magisk"); - config = raw_data::read("/.backup/.magisk"); - char custom_rules_dir[64]; - custom_rules_dir[0] = '\0'; - xreadlink(TMP_RULESDIR, custom_rules_dir, sizeof(custom_rules_dir)); + // Backup stuffs before removing them + self = raw_data::read("/sbin/magisk"); + config = raw_data::read("/.backup/.magisk"); + char custom_rules_dir[64]; + custom_rules_dir[0] = '\0'; + xreadlink(TMP_RULESDIR, custom_rules_dir, sizeof(custom_rules_dir)); - unlink("/sbin/magisk"); - rm_rf("/.backup"); + unlink("/sbin/magisk"); + rm_rf("/.backup"); - setup_tmp("/sbin"); + setup_tmp("/sbin"); - // Create symlinks pointing back to /root - recreate_sbin("/root", false); + // Create symlinks pointing back to /root + recreate_sbin("/root", false); - if (custom_rules_dir[0]) - xsymlink(custom_rules_dir, "/sbin/" RULESDIR); + if (custom_rules_dir[0]) + xsymlink(custom_rules_dir, "/sbin/" RULESDIR); - // Tell magiskd to remount rootfs - setenv("REMOUNT_ROOT", "1", 1); - execv("/sbin/magisk", argv); + // Tell magiskd to remount rootfs + setenv("REMOUNT_ROOT", "1", 1); + execv("/sbin/magisk", argv); } diff --git a/native/jni/init/twostage.cpp b/native/jni/init/twostage.cpp index df5ffa121..c015fc748 100644 --- a/native/jni/init/twostage.cpp +++ b/native/jni/init/twostage.cpp @@ -9,8 +9,8 @@ using namespace std; void fstab_entry::to_file(FILE *fp) { - fprintf(fp, "%s %s %s %s %s\n", dev.data(), mnt_point.data(), - type.data(), mnt_flags.data(), fsmgr_flags.data()); + fprintf(fp, "%s %s %s %s %s\n", dev.data(), mnt_point.data(), + type.data(), mnt_flags.data(), fsmgr_flags.data()); } #define set_info(val) \ @@ -22,193 +22,193 @@ entry.val = &line[val##0]; extern uint32_t patch_verity(void *buf, uint32_t size); void FirstStageInit::prepare() { - if (cmd->force_normal_boot) { - xmkdirs(FSR "/system/bin", 0755); - rename("/init" /* magiskinit */, FSR "/system/bin/init"); - symlink("/system/bin/init", FSR "/init"); - rename("/.backup", FSR "/.backup"); - rename("/overlay.d", FSR "/overlay.d"); - xsymlink("/system/bin/init", "/init"); + if (cmd->force_normal_boot) { + xmkdirs(FSR "/system/bin", 0755); + rename("/init" /* magiskinit */, FSR "/system/bin/init"); + symlink("/system/bin/init", FSR "/init"); + rename("/.backup", FSR "/.backup"); + rename("/overlay.d", FSR "/overlay.d"); + xsymlink("/system/bin/init", "/init"); - chdir(FSR); - } else { - xmkdir("/system", 0755); - xmkdir("/system/bin", 0755); - rename("/init" /* magiskinit */ , "/system/bin/init"); - rename("/.backup/init", "/init"); - } + chdir(FSR); + } else { + xmkdir("/system", 0755); + xmkdir("/system/bin", 0755); + rename("/init" /* magiskinit */ , "/system/bin/init"); + rename("/.backup/init", "/init"); + } - // Try to load fstab from dt - vector fstab; - read_dt_fstab(fstab); + // Try to load fstab from dt + vector fstab; + read_dt_fstab(fstab); - char fstab_file[128]; - fstab_file[0] = '\0'; + char fstab_file[128]; + fstab_file[0] = '\0'; - // Find existing fstab file - for (const char *hw : { cmd->fstab_suffix, cmd->hardware, cmd->hardware_plat }) { - if (hw[0] == '\0') - continue; - sprintf(fstab_file, "fstab.%s", hw); - if (access(fstab_file, F_OK) != 0) { - fstab_file[0] = '\0'; - continue; - } else { - LOGD("Found fstab file: %s\n", fstab_file); - break; - } - } + // Find existing fstab file + for (const char *hw : { cmd->fstab_suffix, cmd->hardware, cmd->hardware_plat }) { + if (hw[0] == '\0') + continue; + sprintf(fstab_file, "fstab.%s", hw); + if (access(fstab_file, F_OK) != 0) { + fstab_file[0] = '\0'; + continue; + } else { + LOGD("Found fstab file: %s\n", fstab_file); + break; + } + } - if (fstab.empty()) { - // fstab has to be somewhere in ramdisk - if (fstab_file[0] == '\0') { - LOGE("Cannot find fstab file in ramdisk!\n"); - return; - } + if (fstab.empty()) { + // fstab has to be somewhere in ramdisk + if (fstab_file[0] == '\0') { + LOGE("Cannot find fstab file in ramdisk!\n"); + return; + } - // Parse and load fstab file - file_readline(fstab_file, [&](string_view l) -> bool { - if (l[0] == '#' || l.length() == 1) - return true; - char *line = (char *) l.data(); + // Parse and load fstab file + file_readline(fstab_file, [&](string_view l) -> bool { + if (l[0] == '#' || l.length() == 1) + return true; + char *line = (char *) l.data(); - int dev0, dev1, mnt_point0, mnt_point1, type0, type1, - mnt_flags0, mnt_flags1, fsmgr_flags0, fsmgr_flags1; + int dev0, dev1, mnt_point0, mnt_point1, type0, type1, + mnt_flags0, mnt_flags1, fsmgr_flags0, fsmgr_flags1; - sscanf(line, "%n%*s%n %n%*s%n %n%*s%n %n%*s%n %n%*s%n", - &dev0, &dev1, &mnt_point0, &mnt_point1, &type0, &type1, - &mnt_flags0, &mnt_flags1, &fsmgr_flags0, &fsmgr_flags1); + sscanf(line, "%n%*s%n %n%*s%n %n%*s%n %n%*s%n %n%*s%n", + &dev0, &dev1, &mnt_point0, &mnt_point1, &type0, &type1, + &mnt_flags0, &mnt_flags1, &fsmgr_flags0, &fsmgr_flags1); - fstab_entry entry; + fstab_entry entry; - set_info(dev); - set_info(mnt_point); - set_info(type); - set_info(mnt_flags); - set_info(fsmgr_flags); + set_info(dev); + set_info(mnt_point); + set_info(type); + set_info(mnt_flags); + set_info(fsmgr_flags); - fstab.emplace_back(std::move(entry)); - return true; - }); - } else { - // All dt fstab entries should be first_stage_mount - for (auto &entry : fstab) { - if (!str_contains(entry.fsmgr_flags, "first_stage_mount")) { - if (!entry.fsmgr_flags.empty()) - entry.fsmgr_flags += ','; - entry.fsmgr_flags += "first_stage_mount"; - } - } + fstab.emplace_back(std::move(entry)); + return true; + }); + } else { + // All dt fstab entries should be first_stage_mount + for (auto &entry : fstab) { + if (!str_contains(entry.fsmgr_flags, "first_stage_mount")) { + if (!entry.fsmgr_flags.empty()) + entry.fsmgr_flags += ','; + entry.fsmgr_flags += "first_stage_mount"; + } + } - // Dump dt fstab to fstab file in rootfs - if (fstab_file[0] == '\0') { - const char *suffix = - cmd->fstab_suffix[0] ? cmd->fstab_suffix : - (cmd->hardware[0] ? cmd->hardware : - (cmd->hardware_plat[0] ? cmd->hardware_plat : nullptr)); - if (suffix == nullptr) { - LOGE("Cannot determine fstab suffix!\n"); - return; - } - sprintf(fstab_file, "fstab.%s", suffix); - } + // Dump dt fstab to fstab file in rootfs + if (fstab_file[0] == '\0') { + const char *suffix = + cmd->fstab_suffix[0] ? cmd->fstab_suffix : + (cmd->hardware[0] ? cmd->hardware : + (cmd->hardware_plat[0] ? cmd->hardware_plat : nullptr)); + if (suffix == nullptr) { + LOGE("Cannot determine fstab suffix!\n"); + return; + } + sprintf(fstab_file, "fstab.%s", suffix); + } - // Patch init to force IsDtFstabCompatible() return false - auto init = raw_data::mmap_rw("/init"); - init.patch({ make_pair("android,fstab", "xxx") }); - } + // Patch init to force IsDtFstabCompatible() return false + auto init = raw_data::mmap_rw("/init"); + init.patch({ make_pair("android,fstab", "xxx") }); + } - { - LOGD("Write fstab file: %s\n", fstab_file); - auto fp = xopen_file(fstab_file, "we"); - for (auto &entry : fstab) { - // Redirect system mnt_point so init won't switch root in first stage init - if (entry.mnt_point == "/system") - entry.mnt_point = "/system_root"; + { + LOGD("Write fstab file: %s\n", fstab_file); + auto fp = xopen_file(fstab_file, "we"); + for (auto &entry : fstab) { + // Redirect system mnt_point so init won't switch root in first stage init + if (entry.mnt_point == "/system") + entry.mnt_point = "/system_root"; - // Force remove AVB for 2SI since it may bootloop some devices - auto len = patch_verity(entry.fsmgr_flags.data(), entry.fsmgr_flags.length()); - entry.fsmgr_flags.resize(len); + // Force remove AVB for 2SI since it may bootloop some devices + auto len = patch_verity(entry.fsmgr_flags.data(), entry.fsmgr_flags.length()); + entry.fsmgr_flags.resize(len); - entry.to_file(fp.get()); - } - } - chmod(fstab_file, 0644); + entry.to_file(fp.get()); + } + } + chmod(fstab_file, 0644); - chdir("/"); + chdir("/"); } #define INIT_PATH "/system/bin/init" #define REDIR_PATH "/system/bin/am" void SARInit::first_stage_prep() { - int pid = getpid(); + int pid = getpid(); - xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755"); + xmount("tmpfs", "/dev", "tmpfs", 0, "mode=755"); - // Patch init binary - int src = xopen("/init", O_RDONLY); - int dest = xopen("/dev/init", O_CREAT | O_WRONLY, 0); - { - auto init = raw_data::read(src); - init.patch({ make_pair(INIT_PATH, REDIR_PATH) }); - write(dest, init.buf, init.sz); - fclone_attr(src, dest); - close(dest); - } + // Patch init binary + int src = xopen("/init", O_RDONLY); + int dest = xopen("/dev/init", O_CREAT | O_WRONLY, 0); + { + auto init = raw_data::read(src); + init.patch({ make_pair(INIT_PATH, REDIR_PATH) }); + write(dest, init.buf, init.sz); + fclone_attr(src, dest); + close(dest); + } - // Replace redirect init with magiskinit - dest = xopen("/dev/magiskinit", O_CREAT | O_WRONLY, 0); - write(dest, self.buf, self.sz); - fclone_attr(src, dest); - close(src); - close(dest); + // Replace redirect init with magiskinit + dest = xopen("/dev/magiskinit", O_CREAT | O_WRONLY, 0); + write(dest, self.buf, self.sz); + fclone_attr(src, dest); + close(src); + close(dest); - xmount("/dev/init", "/init", nullptr, MS_BIND, nullptr); - xmount("/dev/magiskinit", REDIR_PATH, nullptr, MS_BIND, nullptr); - xumount2("/dev", MNT_DETACH); + xmount("/dev/init", "/init", nullptr, MS_BIND, nullptr); + xmount("/dev/magiskinit", REDIR_PATH, nullptr, MS_BIND, nullptr); + xumount2("/dev", MNT_DETACH); - // Block SIGUSR1 - sigset_t block, old; - sigemptyset(&block); - sigaddset(&block, SIGUSR1); - sigprocmask(SIG_BLOCK, &block, &old); + // Block SIGUSR1 + sigset_t block, old; + sigemptyset(&block); + sigaddset(&block, SIGUSR1); + sigprocmask(SIG_BLOCK, &block, &old); - if (int child = xfork(); child) { - LOGD("init daemon [%d]\n", child); - // Wait for children signal - int sig; - sigwait(&block, &sig); + if (int child = xfork(); child) { + LOGD("init daemon [%d]\n", child); + // Wait for children signal + int sig; + sigwait(&block, &sig); - // Restore sigmask - sigprocmask(SIG_SETMASK, &old, nullptr); - } else { - // Establish socket for 2nd stage ack - struct sockaddr_un sun; - int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); - xbind(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)); - xlisten(sockfd, 1); + // Restore sigmask + sigprocmask(SIG_SETMASK, &old, nullptr); + } else { + // Establish socket for 2nd stage ack + struct sockaddr_un sun; + int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0); + xbind(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)); + xlisten(sockfd, 1); - // Resume parent - kill(pid, SIGUSR1); + // Resume parent + kill(pid, SIGUSR1); - // Wait for second stage ack - int client = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC); + // Wait for second stage ack + int client = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC); - // Write backup files - char *tmp_dir = read_string(client); - chdir(tmp_dir); - free(tmp_dir); - int cfg = xopen(INTLROOT "/config", O_WRONLY | O_CREAT, 0); - xwrite(cfg, config.buf, config.sz); - close(cfg); - restore_folder(ROOTOVL, overlays); + // Write backup files + char *tmp_dir = read_string(client); + chdir(tmp_dir); + free(tmp_dir); + int cfg = xopen(INTLROOT "/config", O_WRONLY | O_CREAT, 0); + xwrite(cfg, config.buf, config.sz); + close(cfg); + restore_folder(ROOTOVL, overlays); - // Ack and bail out! - write(sockfd, &sockfd, sizeof(sockfd)); - close(client); - close(sockfd); + // Ack and bail out! + write(sockfd, &sockfd, sizeof(sockfd)); + close(client); + close(sockfd); - exit(0); - } + exit(0); + } } diff --git a/native/jni/magiskboot/bootimg.cpp b/native/jni/magiskboot/bootimg.cpp index c4c00d55d..881e9fc72 100644 --- a/native/jni/magiskboot/bootimg.cpp +++ b/native/jni/magiskboot/bootimg.cpp @@ -23,220 +23,220 @@ uint64_t dyn_img_hdr::j64 = 0; #define PADDING 15 static void decompress(format_t type, int fd, const void *in, size_t size) { - auto ptr = get_decoder(type, make_unique(fd)); - ptr->write(in, size); + auto ptr = get_decoder(type, make_unique(fd)); + ptr->write(in, size); } static off_t compress(format_t type, int fd, const void *in, size_t size) { - auto prev = lseek(fd, 0, SEEK_CUR); - { - auto strm = get_encoder(type, make_unique(fd)); - strm->write(in, size); - } - auto now = lseek(fd, 0, SEEK_CUR); - return now - prev; + auto prev = lseek(fd, 0, SEEK_CUR); + { + auto strm = get_encoder(type, make_unique(fd)); + strm->write(in, size); + } + auto now = lseek(fd, 0, SEEK_CUR); + return now - prev; } static void dump(void *buf, size_t size, const char *filename) { - if (size == 0) - return; - int fd = creat(filename, 0644); - xwrite(fd, buf, size); - close(fd); + if (size == 0) + return; + int fd = creat(filename, 0644); + xwrite(fd, buf, size); + close(fd); } static size_t restore(int fd, const char *filename) { - int ifd = xopen(filename, O_RDONLY); - size_t size = lseek(ifd, 0, SEEK_END); - lseek(ifd, 0, SEEK_SET); - xsendfile(fd, ifd, nullptr, size); - close(ifd); - return size; + int ifd = xopen(filename, O_RDONLY); + size_t size = lseek(ifd, 0, SEEK_END); + lseek(ifd, 0, SEEK_SET); + xsendfile(fd, ifd, nullptr, size); + close(ifd); + return size; } static void restore_buf(int fd, const void *buf, size_t size) { - xwrite(fd, buf, size); + xwrite(fd, buf, size); } void dyn_img_hdr::print() { - uint32_t ver = header_version(); - fprintf(stderr, "%-*s [%u]\n", PADDING, "HEADER_VER", ver); - fprintf(stderr, "%-*s [%u]\n", PADDING, "KERNEL_SZ", kernel_size()); - fprintf(stderr, "%-*s [%u]\n", PADDING, "RAMDISK_SZ", ramdisk_size()); - if (ver < 3) - fprintf(stderr, "%-*s [%u]\n", PADDING, "SECOND_SZ", second_size()); - if (ver == 0) - fprintf(stderr, "%-*s [%u]\n", PADDING, "EXTRA_SZ", extra_size()); - if (ver == 1 || ver == 2) - fprintf(stderr, "%-*s [%u]\n", PADDING, "RECOV_DTBO_SZ", recovery_dtbo_size()); - if (ver == 2) - fprintf(stderr, "%-*s [%u]\n", PADDING, "DTB_SZ", dtb_size()); + uint32_t ver = header_version(); + fprintf(stderr, "%-*s [%u]\n", PADDING, "HEADER_VER", ver); + fprintf(stderr, "%-*s [%u]\n", PADDING, "KERNEL_SZ", kernel_size()); + fprintf(stderr, "%-*s [%u]\n", PADDING, "RAMDISK_SZ", ramdisk_size()); + if (ver < 3) + fprintf(stderr, "%-*s [%u]\n", PADDING, "SECOND_SZ", second_size()); + if (ver == 0) + fprintf(stderr, "%-*s [%u]\n", PADDING, "EXTRA_SZ", extra_size()); + if (ver == 1 || ver == 2) + fprintf(stderr, "%-*s [%u]\n", PADDING, "RECOV_DTBO_SZ", recovery_dtbo_size()); + if (ver == 2) + fprintf(stderr, "%-*s [%u]\n", PADDING, "DTB_SZ", dtb_size()); - if (uint32_t os_ver = os_version()) { - int a,b,c,y,m = 0; - int version = os_ver >> 11; - int patch_level = os_ver & 0x7ff; + if (uint32_t os_ver = os_version()) { + int a,b,c,y,m = 0; + int version = os_ver >> 11; + int patch_level = os_ver & 0x7ff; - a = (version >> 14) & 0x7f; - b = (version >> 7) & 0x7f; - c = version & 0x7f; - fprintf(stderr, "%-*s [%d.%d.%d]\n", PADDING, "OS_VERSION", a, b, c); + a = (version >> 14) & 0x7f; + b = (version >> 7) & 0x7f; + c = version & 0x7f; + fprintf(stderr, "%-*s [%d.%d.%d]\n", PADDING, "OS_VERSION", a, b, c); - y = (patch_level >> 4) + 2000; - m = patch_level & 0xf; - fprintf(stderr, "%-*s [%d-%02d]\n", PADDING, "OS_PATCH_LEVEL", y, m); - } + y = (patch_level >> 4) + 2000; + m = patch_level & 0xf; + fprintf(stderr, "%-*s [%d-%02d]\n", PADDING, "OS_PATCH_LEVEL", y, m); + } - fprintf(stderr, "%-*s [%u]\n", PADDING, "PAGESIZE", page_size()); - if (ver < 3) { - fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", name()); - } - fprintf(stderr, "%-*s [%.*s%.*s]\n", PADDING, "CMDLINE", - BOOT_ARGS_SIZE, cmdline(), BOOT_EXTRA_ARGS_SIZE, extra_cmdline()); - if (auto chksum = reinterpret_cast(id())) { - fprintf(stderr, "%-*s [", PADDING, "CHECKSUM"); - for (int i = 0; i < SHA256_DIGEST_SIZE; ++i) - fprintf(stderr, "%02hhx", chksum[i]); - fprintf(stderr, "]\n"); - } + fprintf(stderr, "%-*s [%u]\n", PADDING, "PAGESIZE", page_size()); + if (ver < 3) { + fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", name()); + } + fprintf(stderr, "%-*s [%.*s%.*s]\n", PADDING, "CMDLINE", + BOOT_ARGS_SIZE, cmdline(), BOOT_EXTRA_ARGS_SIZE, extra_cmdline()); + if (auto chksum = reinterpret_cast(id())) { + fprintf(stderr, "%-*s [", PADDING, "CHECKSUM"); + for (int i = 0; i < SHA256_DIGEST_SIZE; ++i) + fprintf(stderr, "%02hhx", chksum[i]); + fprintf(stderr, "]\n"); + } } void dyn_img_hdr::dump_hdr_file() { - FILE *fp = xfopen(HEADER_FILE, "w"); - fprintf(fp, "pagesize=%u\n", page_size()); - if (name()) - fprintf(fp, "name=%s\n", name()); - fprintf(fp, "cmdline=%.*s%.*s\n", BOOT_ARGS_SIZE, cmdline(), BOOT_EXTRA_ARGS_SIZE, extra_cmdline()); - uint32_t ver = os_version(); - if (ver) { - int a, b, c, y, m; - int version, patch_level; - version = ver >> 11; - patch_level = ver & 0x7ff; + FILE *fp = xfopen(HEADER_FILE, "w"); + fprintf(fp, "pagesize=%u\n", page_size()); + if (name()) + fprintf(fp, "name=%s\n", name()); + fprintf(fp, "cmdline=%.*s%.*s\n", BOOT_ARGS_SIZE, cmdline(), BOOT_EXTRA_ARGS_SIZE, extra_cmdline()); + uint32_t ver = os_version(); + if (ver) { + int a, b, c, y, m; + int version, patch_level; + version = ver >> 11; + patch_level = ver & 0x7ff; - a = (version >> 14) & 0x7f; - b = (version >> 7) & 0x7f; - c = version & 0x7f; - fprintf(fp, "os_version=%d.%d.%d\n", a, b, c); + a = (version >> 14) & 0x7f; + b = (version >> 7) & 0x7f; + c = version & 0x7f; + fprintf(fp, "os_version=%d.%d.%d\n", a, b, c); - y = (patch_level >> 4) + 2000; - m = patch_level & 0xf; - fprintf(fp, "os_patch_level=%d-%02d\n", y, m); - } - fclose(fp); + y = (patch_level >> 4) + 2000; + m = patch_level & 0xf; + fprintf(fp, "os_patch_level=%d-%02d\n", y, m); + } + fclose(fp); } void dyn_img_hdr::load_hdr_file() { - parse_prop_file(HEADER_FILE, [=](string_view key, string_view value) -> bool { - if (key == "page_size") { - page_size() = parse_int(value); - } else if (key == "name" && name()) { - memset(name(), 0, 16); - memcpy(name(), value.data(), value.length() > 15 ? 15 : value.length()); - } else if (key == "cmdline") { - memset(cmdline(), 0, BOOT_ARGS_SIZE); - memset(extra_cmdline(), 0, BOOT_EXTRA_ARGS_SIZE); - if (value.length() > BOOT_ARGS_SIZE) { - memcpy(cmdline(), value.data(), BOOT_ARGS_SIZE); - auto len = std::min(value.length() - BOOT_ARGS_SIZE, (size_t) BOOT_EXTRA_ARGS_SIZE); - memcpy(extra_cmdline(), &value[BOOT_ARGS_SIZE], len); - } else { - memcpy(cmdline(), value.data(), value.length()); - } - } else if (key == "os_version") { - int patch_level = os_version() & 0x7ff; - int a, b, c; - sscanf(value.data(), "%d.%d.%d", &a, &b, &c); - os_version() = (((a << 14) | (b << 7) | c) << 11) | patch_level; - } else if (key == "os_patch_level") { - int os_ver = os_version() >> 11; - int y, m; - sscanf(value.data(), "%d-%d", &y, &m); - y -= 2000; - os_version() = (os_ver << 11) | (y << 4) | m; - } - return true; - }); + parse_prop_file(HEADER_FILE, [=](string_view key, string_view value) -> bool { + if (key == "page_size") { + page_size() = parse_int(value); + } else if (key == "name" && name()) { + memset(name(), 0, 16); + memcpy(name(), value.data(), value.length() > 15 ? 15 : value.length()); + } else if (key == "cmdline") { + memset(cmdline(), 0, BOOT_ARGS_SIZE); + memset(extra_cmdline(), 0, BOOT_EXTRA_ARGS_SIZE); + if (value.length() > BOOT_ARGS_SIZE) { + memcpy(cmdline(), value.data(), BOOT_ARGS_SIZE); + auto len = std::min(value.length() - BOOT_ARGS_SIZE, (size_t) BOOT_EXTRA_ARGS_SIZE); + memcpy(extra_cmdline(), &value[BOOT_ARGS_SIZE], len); + } else { + memcpy(cmdline(), value.data(), value.length()); + } + } else if (key == "os_version") { + int patch_level = os_version() & 0x7ff; + int a, b, c; + sscanf(value.data(), "%d.%d.%d", &a, &b, &c); + os_version() = (((a << 14) | (b << 7) | c) << 11) | patch_level; + } else if (key == "os_patch_level") { + int os_ver = os_version() >> 11; + int y, m; + sscanf(value.data(), "%d-%d", &y, &m); + y -= 2000; + os_version() = (os_ver << 11) | (y << 4) | m; + } + return true; + }); } boot_img::boot_img(const char *image) { - mmap_ro(image, map_addr, map_size); - fprintf(stderr, "Parsing boot image: [%s]\n", image); - for (uint8_t *addr = map_addr; addr < map_addr + map_size; ++addr) { - format_t fmt = check_fmt(addr, map_size); - switch (fmt) { - case CHROMEOS: - // chromeos require external signing - flags |= CHROMEOS_FLAG; - addr += 65535; - break; - case DHTB: - flags |= (DHTB_FLAG | SEANDROID_FLAG); - fprintf(stderr, "DHTB_HDR\n"); - addr += sizeof(dhtb_hdr) - 1; - break; - case BLOB: - flags |= BLOB_FLAG; - fprintf(stderr, "TEGRA_BLOB\n"); - addr += sizeof(blob_hdr) - 1; - break; - case AOSP: - case AOSP_VENDOR: - parse_image(addr, fmt); - return; - default: - break; - } - } - exit(1); + mmap_ro(image, map_addr, map_size); + fprintf(stderr, "Parsing boot image: [%s]\n", image); + for (uint8_t *addr = map_addr; addr < map_addr + map_size; ++addr) { + format_t fmt = check_fmt(addr, map_size); + switch (fmt) { + case CHROMEOS: + // chromeos require external signing + flags |= CHROMEOS_FLAG; + addr += 65535; + break; + case DHTB: + flags |= (DHTB_FLAG | SEANDROID_FLAG); + fprintf(stderr, "DHTB_HDR\n"); + addr += sizeof(dhtb_hdr) - 1; + break; + case BLOB: + flags |= BLOB_FLAG; + fprintf(stderr, "TEGRA_BLOB\n"); + addr += sizeof(blob_hdr) - 1; + break; + case AOSP: + case AOSP_VENDOR: + parse_image(addr, fmt); + return; + default: + break; + } + } + exit(1); } boot_img::~boot_img() { - munmap(map_addr, map_size); - delete hdr; + munmap(map_addr, map_size); + delete hdr; } static int find_dtb_offset(uint8_t *buf, unsigned sz) { - for (int off = 0; off + sizeof(fdt_header) < sz; ++off) { - auto fdt_hdr = reinterpret_cast(buf + off); - if (fdt32_to_cpu(fdt_hdr->magic) != FDT_MAGIC) - continue; + for (int off = 0; off + sizeof(fdt_header) < sz; ++off) { + auto fdt_hdr = reinterpret_cast(buf + off); + if (fdt32_to_cpu(fdt_hdr->magic) != FDT_MAGIC) + continue; - // Check that fdt_header.totalsize does not overflow kernel image size - uint32_t totalsize = fdt32_to_cpu(fdt_hdr->totalsize); - if (totalsize + off > sz) - continue; + // Check that fdt_header.totalsize does not overflow kernel image size + uint32_t totalsize = fdt32_to_cpu(fdt_hdr->totalsize); + if (totalsize + off > sz) + continue; - // Check that fdt_header.off_dt_struct does not overflow kernel image size - uint32_t off_dt_struct = fdt32_to_cpu(fdt_hdr->off_dt_struct); - if (off_dt_struct + off > sz) - continue; + // Check that fdt_header.off_dt_struct does not overflow kernel image size + uint32_t off_dt_struct = fdt32_to_cpu(fdt_hdr->off_dt_struct); + if (off_dt_struct + off > sz) + continue; - // Check that fdt_node_header.tag of first node is FDT_BEGIN_NODE - auto fdt_node_hdr = reinterpret_cast(buf + off + off_dt_struct); - if (fdt32_to_cpu(fdt_node_hdr->tag) != FDT_BEGIN_NODE) - continue; + // Check that fdt_node_header.tag of first node is FDT_BEGIN_NODE + auto fdt_node_hdr = reinterpret_cast(buf + off + off_dt_struct); + if (fdt32_to_cpu(fdt_node_hdr->tag) != FDT_BEGIN_NODE) + continue; - return off; - } - return -1; + return off; + } + return -1; } static format_t check_fmt_lg(uint8_t *buf, unsigned sz) { - format_t fmt = check_fmt(buf, sz); - if (fmt == LZ4_LEGACY) { - // We need to check if it is LZ4_LG - unsigned off = 4; - unsigned block_sz; - while (off + sizeof(block_sz) <= sz) { - memcpy(&block_sz, buf + off, sizeof(block_sz)); - off += sizeof(block_sz); - if (off + block_sz > sz) - return LZ4_LG; - off += block_sz; - } - } - return fmt; + format_t fmt = check_fmt(buf, sz); + if (fmt == LZ4_LEGACY) { + // We need to check if it is LZ4_LG + unsigned off = 4; + unsigned block_sz; + while (off + sizeof(block_sz) <= sz) { + memcpy(&block_sz, buf + off, sizeof(block_sz)); + off += sizeof(block_sz); + if (off + block_sz > sz) + return LZ4_LG; + off += block_sz; + } + } + return fmt; } #define get_block(name) {\ @@ -246,407 +246,407 @@ off = do_align(off, hdr->page_size()); \ } void boot_img::parse_image(uint8_t *addr, format_t type) { - auto hp = reinterpret_cast(addr); - if (type == AOSP_VENDOR) { - fprintf(stderr, "VENDOR_BOOT_HDR\n"); - hdr = new dyn_img_vnd_v3(addr); - } else if (hp->page_size >= 0x02000000) { - fprintf(stderr, "PXA_BOOT_HDR\n"); - hdr = new dyn_img_pxa(addr); - } else { - if (memcmp(hp->cmdline, NOOKHD_RL_MAGIC, 10) == 0 || - memcmp(hp->cmdline, NOOKHD_GL_MAGIC, 12) == 0 || - memcmp(hp->cmdline, NOOKHD_GR_MAGIC, 14) == 0 || - memcmp(hp->cmdline, NOOKHD_EB_MAGIC, 26) == 0 || - memcmp(hp->cmdline, NOOKHD_ER_MAGIC, 30) == 0) { - flags |= NOOKHD_FLAG; - fprintf(stderr, "NOOKHD_LOADER\n"); - addr += NOOKHD_PRE_HEADER_SZ; - } else if (memcmp(hp->name, ACCLAIM_MAGIC, 10) == 0) { - flags |= ACCLAIM_FLAG; - fprintf(stderr, "ACCLAIM_LOADER\n"); - addr += ACCLAIM_PRE_HEADER_SZ; - } + auto hp = reinterpret_cast(addr); + if (type == AOSP_VENDOR) { + fprintf(stderr, "VENDOR_BOOT_HDR\n"); + hdr = new dyn_img_vnd_v3(addr); + } else if (hp->page_size >= 0x02000000) { + fprintf(stderr, "PXA_BOOT_HDR\n"); + hdr = new dyn_img_pxa(addr); + } else { + if (memcmp(hp->cmdline, NOOKHD_RL_MAGIC, 10) == 0 || + memcmp(hp->cmdline, NOOKHD_GL_MAGIC, 12) == 0 || + memcmp(hp->cmdline, NOOKHD_GR_MAGIC, 14) == 0 || + memcmp(hp->cmdline, NOOKHD_EB_MAGIC, 26) == 0 || + memcmp(hp->cmdline, NOOKHD_ER_MAGIC, 30) == 0) { + flags |= NOOKHD_FLAG; + fprintf(stderr, "NOOKHD_LOADER\n"); + addr += NOOKHD_PRE_HEADER_SZ; + } else if (memcmp(hp->name, ACCLAIM_MAGIC, 10) == 0) { + flags |= ACCLAIM_FLAG; + fprintf(stderr, "ACCLAIM_LOADER\n"); + addr += ACCLAIM_PRE_HEADER_SZ; + } - switch (hp->header_version) { - case 1: - hdr = new dyn_img_v1(addr); - break; - case 2: - hdr = new dyn_img_v2(addr); - break; - case 3: - hdr = new dyn_img_v3(addr); - break; - default: - hdr = new dyn_img_v0(addr); - break; - } - } + switch (hp->header_version) { + case 1: + hdr = new dyn_img_v1(addr); + break; + case 2: + hdr = new dyn_img_v2(addr); + break; + case 3: + hdr = new dyn_img_v3(addr); + break; + default: + hdr = new dyn_img_v0(addr); + break; + } + } - if (char *id = hdr->id()) { - for (int i = SHA_DIGEST_SIZE + 4; i < SHA256_DIGEST_SIZE; ++i) { - if (id[i]) { - flags |= SHA256_FLAG; - break; - } - } - } + if (char *id = hdr->id()) { + for (int i = SHA_DIGEST_SIZE + 4; i < SHA256_DIGEST_SIZE; ++i) { + if (id[i]) { + flags |= SHA256_FLAG; + break; + } + } + } - hdr->print(); + hdr->print(); - size_t off = hdr->hdr_space(); - hdr_addr = addr; - get_block(kernel); - get_block(ramdisk); - get_block(second); - get_block(extra); - get_block(recovery_dtbo); - get_block(dtb); + size_t off = hdr->hdr_space(); + hdr_addr = addr; + get_block(kernel); + get_block(ramdisk); + get_block(second); + get_block(extra); + get_block(recovery_dtbo); + get_block(dtb); - if (addr + off < map_addr + map_size) { - tail = addr + off; - tail_size = map_size - (tail - map_addr); - } + if (addr + off < map_addr + map_size) { + tail = addr + off; + tail_size = map_size - (tail - map_addr); + } - // Check tail info, currently only for LG Bump and Samsung SEANDROIDENFORCE - if (tail_size >= 16 && memcmp(tail, SEANDROID_MAGIC, 16) == 0) { - flags |= SEANDROID_FLAG; - } else if (tail_size >= 16 && memcmp(tail, LG_BUMP_MAGIC, 16) == 0) { - flags |= LG_BUMP_FLAG; - } + // Check tail info, currently only for LG Bump and Samsung SEANDROIDENFORCE + if (tail_size >= 16 && memcmp(tail, SEANDROID_MAGIC, 16) == 0) { + flags |= SEANDROID_FLAG; + } else if (tail_size >= 16 && memcmp(tail, LG_BUMP_MAGIC, 16) == 0) { + flags |= LG_BUMP_FLAG; + } - if (int dtb_off = find_dtb_offset(kernel, hdr->kernel_size()); dtb_off > 0) { - kernel_dtb = kernel + dtb_off; - kernel_dt_size = hdr->kernel_size() - dtb_off; - hdr->kernel_size() = dtb_off; - fprintf(stderr, "%-*s [%u]\n", PADDING, "KERNEL_DTB", kernel_dt_size); - } + if (int dtb_off = find_dtb_offset(kernel, hdr->kernel_size()); dtb_off > 0) { + kernel_dtb = kernel + dtb_off; + kernel_dt_size = hdr->kernel_size() - dtb_off; + hdr->kernel_size() = dtb_off; + fprintf(stderr, "%-*s [%u]\n", PADDING, "KERNEL_DTB", kernel_dt_size); + } - if (auto size = hdr->kernel_size()) { - k_fmt = check_fmt_lg(kernel, size); - if (k_fmt == MTK) { - fprintf(stderr, "MTK_KERNEL_HDR\n"); - flags |= MTK_KERNEL; - k_hdr = reinterpret_cast(kernel); - fprintf(stderr, "%-*s [%u]\n", PADDING, "KERNEL", k_hdr->size); - fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", k_hdr->name); - kernel += sizeof(mtk_hdr); - hdr->kernel_size() -= sizeof(mtk_hdr); - k_fmt = check_fmt_lg(kernel, hdr->kernel_size()); - } - fprintf(stderr, "%-*s [%s]\n", PADDING, "KERNEL_FMT", fmt2name[k_fmt]); - } - if (auto size = hdr->ramdisk_size()) { - r_fmt = check_fmt_lg(ramdisk, size); - if (r_fmt == MTK) { - fprintf(stderr, "MTK_RAMDISK_HDR\n"); - flags |= MTK_RAMDISK; - r_hdr = reinterpret_cast(ramdisk); - fprintf(stderr, "%-*s [%u]\n", PADDING, "RAMDISK", r_hdr->size); - fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", r_hdr->name); - ramdisk += sizeof(mtk_hdr); - hdr->ramdisk_size() -= sizeof(mtk_hdr); - r_fmt = check_fmt_lg(ramdisk, hdr->ramdisk_size()); - } - fprintf(stderr, "%-*s [%s]\n", PADDING, "RAMDISK_FMT", fmt2name[r_fmt]); - } - if (auto size = hdr->extra_size()) { - e_fmt = check_fmt_lg(extra, size); - fprintf(stderr, "%-*s [%s]\n", PADDING, "EXTRA_FMT", fmt2name[e_fmt]); - } + if (auto size = hdr->kernel_size()) { + k_fmt = check_fmt_lg(kernel, size); + if (k_fmt == MTK) { + fprintf(stderr, "MTK_KERNEL_HDR\n"); + flags |= MTK_KERNEL; + k_hdr = reinterpret_cast(kernel); + fprintf(stderr, "%-*s [%u]\n", PADDING, "KERNEL", k_hdr->size); + fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", k_hdr->name); + kernel += sizeof(mtk_hdr); + hdr->kernel_size() -= sizeof(mtk_hdr); + k_fmt = check_fmt_lg(kernel, hdr->kernel_size()); + } + fprintf(stderr, "%-*s [%s]\n", PADDING, "KERNEL_FMT", fmt2name[k_fmt]); + } + if (auto size = hdr->ramdisk_size()) { + r_fmt = check_fmt_lg(ramdisk, size); + if (r_fmt == MTK) { + fprintf(stderr, "MTK_RAMDISK_HDR\n"); + flags |= MTK_RAMDISK; + r_hdr = reinterpret_cast(ramdisk); + fprintf(stderr, "%-*s [%u]\n", PADDING, "RAMDISK", r_hdr->size); + fprintf(stderr, "%-*s [%s]\n", PADDING, "NAME", r_hdr->name); + ramdisk += sizeof(mtk_hdr); + hdr->ramdisk_size() -= sizeof(mtk_hdr); + r_fmt = check_fmt_lg(ramdisk, hdr->ramdisk_size()); + } + fprintf(stderr, "%-*s [%s]\n", PADDING, "RAMDISK_FMT", fmt2name[r_fmt]); + } + if (auto size = hdr->extra_size()) { + e_fmt = check_fmt_lg(extra, size); + fprintf(stderr, "%-*s [%s]\n", PADDING, "EXTRA_FMT", fmt2name[e_fmt]); + } } int split_image_dtb(const char *filename) { - uint8_t *buf; - size_t sz; - mmap_ro(filename, buf, sz); - run_finally f([=]{ munmap(buf, sz); }); + uint8_t *buf; + size_t sz; + mmap_ro(filename, buf, sz); + run_finally f([=]{ munmap(buf, sz); }); - if (int off = find_dtb_offset(buf, sz); off > 0) { - format_t fmt = check_fmt_lg(buf, sz); - if (COMPRESSED(fmt)) { - int fd = creat(KERNEL_FILE, 0644); - decompress(fmt, fd, buf, off); - close(fd); - } else { - dump(buf, off, KERNEL_FILE); - } - dump(buf + off, sz - off, KER_DTB_FILE); - return 0; - } else { - fprintf(stderr, "Cannot find DTB in %s\n", filename); - return 1; - } + if (int off = find_dtb_offset(buf, sz); off > 0) { + format_t fmt = check_fmt_lg(buf, sz); + if (COMPRESSED(fmt)) { + int fd = creat(KERNEL_FILE, 0644); + decompress(fmt, fd, buf, off); + close(fd); + } else { + dump(buf, off, KERNEL_FILE); + } + dump(buf + off, sz - off, KER_DTB_FILE); + return 0; + } else { + fprintf(stderr, "Cannot find DTB in %s\n", filename); + return 1; + } } int unpack(const char *image, bool skip_decomp, bool hdr) { - boot_img boot(image); + boot_img boot(image); - if (hdr) - boot.hdr->dump_hdr_file(); + if (hdr) + boot.hdr->dump_hdr_file(); - // Dump kernel - if (!skip_decomp && COMPRESSED(boot.k_fmt)) { - int fd = creat(KERNEL_FILE, 0644); - decompress(boot.k_fmt, fd, boot.kernel, boot.hdr->kernel_size()); - close(fd); - } else { - dump(boot.kernel, boot.hdr->kernel_size(), KERNEL_FILE); - } + // Dump kernel + if (!skip_decomp && COMPRESSED(boot.k_fmt)) { + int fd = creat(KERNEL_FILE, 0644); + decompress(boot.k_fmt, fd, boot.kernel, boot.hdr->kernel_size()); + close(fd); + } else { + dump(boot.kernel, boot.hdr->kernel_size(), KERNEL_FILE); + } - // Dump kernel_dtb - dump(boot.kernel_dtb, boot.kernel_dt_size, KER_DTB_FILE); + // Dump kernel_dtb + dump(boot.kernel_dtb, boot.kernel_dt_size, KER_DTB_FILE); - // Dump ramdisk - if (!skip_decomp && COMPRESSED(boot.r_fmt)) { - int fd = creat(RAMDISK_FILE, 0644); - decompress(boot.r_fmt, fd, boot.ramdisk, boot.hdr->ramdisk_size()); - close(fd); - } else { - dump(boot.ramdisk, boot.hdr->ramdisk_size(), RAMDISK_FILE); - } + // Dump ramdisk + if (!skip_decomp && COMPRESSED(boot.r_fmt)) { + int fd = creat(RAMDISK_FILE, 0644); + decompress(boot.r_fmt, fd, boot.ramdisk, boot.hdr->ramdisk_size()); + close(fd); + } else { + dump(boot.ramdisk, boot.hdr->ramdisk_size(), RAMDISK_FILE); + } - // Dump second - dump(boot.second, boot.hdr->second_size(), SECOND_FILE); + // Dump second + dump(boot.second, boot.hdr->second_size(), SECOND_FILE); - // Dump extra - if (!skip_decomp && COMPRESSED(boot.e_fmt)) { - int fd = creat(EXTRA_FILE, 0644); - decompress(boot.e_fmt, fd, boot.extra, boot.hdr->extra_size()); - close(fd); - } else { - dump(boot.extra, boot.hdr->extra_size(), EXTRA_FILE); - } + // Dump extra + if (!skip_decomp && COMPRESSED(boot.e_fmt)) { + int fd = creat(EXTRA_FILE, 0644); + decompress(boot.e_fmt, fd, boot.extra, boot.hdr->extra_size()); + close(fd); + } else { + dump(boot.extra, boot.hdr->extra_size(), EXTRA_FILE); + } - // Dump recovery_dtbo - dump(boot.recovery_dtbo, boot.hdr->recovery_dtbo_size(), RECV_DTBO_FILE); + // Dump recovery_dtbo + dump(boot.recovery_dtbo, boot.hdr->recovery_dtbo_size(), RECV_DTBO_FILE); - // Dump dtb - dump(boot.dtb, boot.hdr->dtb_size(), DTB_FILE); + // Dump dtb + dump(boot.dtb, boot.hdr->dtb_size(), DTB_FILE); - return (boot.flags & CHROMEOS_FLAG) ? 2 : 0; + return (boot.flags & CHROMEOS_FLAG) ? 2 : 0; } #define file_align() \ write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR) - off.header, boot.hdr->page_size())) void repack(const char* src_img, const char* out_img, bool skip_comp) { - boot_img boot(src_img); + boot_img boot(src_img); - auto is_flag = [&](unsigned flag) -> bool { return (boot.flags & flag); }; + auto is_flag = [&](unsigned flag) -> bool { return (boot.flags & flag); }; - struct { - uint32_t header; - uint32_t kernel; - uint32_t ramdisk; - uint32_t second; - uint32_t extra; - uint32_t dtb; - } off; + struct { + uint32_t header; + uint32_t kernel; + uint32_t ramdisk; + uint32_t second; + uint32_t extra; + uint32_t dtb; + } off; - fprintf(stderr, "Repack to boot image: [%s]\n", out_img); + fprintf(stderr, "Repack to boot image: [%s]\n", out_img); - // Reset sizes - boot.hdr->kernel_size() = 0; - boot.hdr->ramdisk_size() = 0; - boot.hdr->second_size() = 0; - boot.hdr->dtb_size() = 0; - boot.kernel_dt_size = 0; + // Reset sizes + boot.hdr->kernel_size() = 0; + boot.hdr->ramdisk_size() = 0; + boot.hdr->second_size() = 0; + boot.hdr->dtb_size() = 0; + boot.kernel_dt_size = 0; - if (access(HEADER_FILE, R_OK) == 0) - boot.hdr->load_hdr_file(); + if (access(HEADER_FILE, R_OK) == 0) + boot.hdr->load_hdr_file(); - /***************** - * Writing blocks - *****************/ + /***************** + * Writing blocks + *****************/ - // Create new image - int fd = creat(out_img, 0644); + // Create new image + int fd = creat(out_img, 0644); - if (is_flag(DHTB_FLAG)) { - // Skip DHTB header - write_zero(fd, sizeof(dhtb_hdr)); - } else if (is_flag(BLOB_FLAG)) { - restore_buf(fd, boot.map_addr, sizeof(blob_hdr)); - } else if (is_flag(NOOKHD_FLAG)) { - restore_buf(fd, boot.map_addr, NOOKHD_PRE_HEADER_SZ); - } else if (is_flag(ACCLAIM_FLAG)) { - restore_buf(fd, boot.map_addr, ACCLAIM_PRE_HEADER_SZ); - } + if (is_flag(DHTB_FLAG)) { + // Skip DHTB header + write_zero(fd, sizeof(dhtb_hdr)); + } else if (is_flag(BLOB_FLAG)) { + restore_buf(fd, boot.map_addr, sizeof(blob_hdr)); + } else if (is_flag(NOOKHD_FLAG)) { + restore_buf(fd, boot.map_addr, NOOKHD_PRE_HEADER_SZ); + } else if (is_flag(ACCLAIM_FLAG)) { + restore_buf(fd, boot.map_addr, ACCLAIM_PRE_HEADER_SZ); + } - // Copy header - off.header = lseek(fd, 0, SEEK_CUR); - restore_buf(fd, boot.hdr_addr, boot.hdr->hdr_space()); + // Copy header + off.header = lseek(fd, 0, SEEK_CUR); + restore_buf(fd, boot.hdr_addr, boot.hdr->hdr_space()); - // kernel - off.kernel = lseek(fd, 0, SEEK_CUR); - if (is_flag(MTK_KERNEL)) { - // Copy MTK headers - restore_buf(fd, boot.k_hdr, sizeof(mtk_hdr)); - } - if (access(KERNEL_FILE, R_OK) == 0) { - size_t raw_size; - void *raw_buf; - mmap_ro(KERNEL_FILE, raw_buf, raw_size); - if (!COMPRESSED_ANY(check_fmt(raw_buf, raw_size)) && COMPRESSED(boot.k_fmt)) { - boot.hdr->kernel_size() = compress(boot.k_fmt, fd, raw_buf, raw_size); - } else { - boot.hdr->kernel_size() = xwrite(fd, raw_buf, raw_size); - } - munmap(raw_buf, raw_size); - } + // kernel + off.kernel = lseek(fd, 0, SEEK_CUR); + if (is_flag(MTK_KERNEL)) { + // Copy MTK headers + restore_buf(fd, boot.k_hdr, sizeof(mtk_hdr)); + } + if (access(KERNEL_FILE, R_OK) == 0) { + size_t raw_size; + void *raw_buf; + mmap_ro(KERNEL_FILE, raw_buf, raw_size); + if (!COMPRESSED_ANY(check_fmt(raw_buf, raw_size)) && COMPRESSED(boot.k_fmt)) { + boot.hdr->kernel_size() = compress(boot.k_fmt, fd, raw_buf, raw_size); + } else { + boot.hdr->kernel_size() = xwrite(fd, raw_buf, raw_size); + } + munmap(raw_buf, raw_size); + } - // kernel dtb - if (access(KER_DTB_FILE, R_OK) == 0) - boot.hdr->kernel_size() += restore(fd, KER_DTB_FILE); - file_align(); + // kernel dtb + if (access(KER_DTB_FILE, R_OK) == 0) + boot.hdr->kernel_size() += restore(fd, KER_DTB_FILE); + file_align(); - // ramdisk - off.ramdisk = lseek(fd, 0, SEEK_CUR); - if (is_flag(MTK_RAMDISK)) { - // Copy MTK headers - restore_buf(fd, boot.r_hdr, sizeof(mtk_hdr)); - } - if (access(RAMDISK_FILE, R_OK) == 0) { - size_t raw_size; - void *raw_buf; - mmap_ro(RAMDISK_FILE, raw_buf, raw_size); - if (!skip_comp && !COMPRESSED_ANY(check_fmt(raw_buf, raw_size)) && COMPRESSED(boot.r_fmt)) { - boot.hdr->ramdisk_size() = compress(boot.r_fmt, fd, raw_buf, raw_size); - } else { - boot.hdr->ramdisk_size() = xwrite(fd, raw_buf, raw_size); - } - munmap(raw_buf, raw_size); - file_align(); - } + // ramdisk + off.ramdisk = lseek(fd, 0, SEEK_CUR); + if (is_flag(MTK_RAMDISK)) { + // Copy MTK headers + restore_buf(fd, boot.r_hdr, sizeof(mtk_hdr)); + } + if (access(RAMDISK_FILE, R_OK) == 0) { + size_t raw_size; + void *raw_buf; + mmap_ro(RAMDISK_FILE, raw_buf, raw_size); + if (!skip_comp && !COMPRESSED_ANY(check_fmt(raw_buf, raw_size)) && COMPRESSED(boot.r_fmt)) { + boot.hdr->ramdisk_size() = compress(boot.r_fmt, fd, raw_buf, raw_size); + } else { + boot.hdr->ramdisk_size() = xwrite(fd, raw_buf, raw_size); + } + munmap(raw_buf, raw_size); + file_align(); + } - // second - off.second = lseek(fd, 0, SEEK_CUR); - if (access(SECOND_FILE, R_OK) == 0) { - boot.hdr->second_size() = restore(fd, SECOND_FILE); - file_align(); - } + // second + off.second = lseek(fd, 0, SEEK_CUR); + if (access(SECOND_FILE, R_OK) == 0) { + boot.hdr->second_size() = restore(fd, SECOND_FILE); + file_align(); + } - // extra - off.extra = lseek(fd, 0, SEEK_CUR); - if (access(EXTRA_FILE, R_OK) == 0) { - size_t raw_size; - void *raw_buf; - mmap_ro(EXTRA_FILE, raw_buf, raw_size); - if (!skip_comp && !COMPRESSED_ANY(check_fmt(raw_buf, raw_size)) && COMPRESSED(boot.e_fmt)) { - boot.hdr->extra_size() = compress(boot.e_fmt, fd, raw_buf, raw_size); - } else { - boot.hdr->extra_size() = xwrite(fd, raw_buf, raw_size); - } - munmap(raw_buf, raw_size); - file_align(); - } + // extra + off.extra = lseek(fd, 0, SEEK_CUR); + if (access(EXTRA_FILE, R_OK) == 0) { + size_t raw_size; + void *raw_buf; + mmap_ro(EXTRA_FILE, raw_buf, raw_size); + if (!skip_comp && !COMPRESSED_ANY(check_fmt(raw_buf, raw_size)) && COMPRESSED(boot.e_fmt)) { + boot.hdr->extra_size() = compress(boot.e_fmt, fd, raw_buf, raw_size); + } else { + boot.hdr->extra_size() = xwrite(fd, raw_buf, raw_size); + } + munmap(raw_buf, raw_size); + file_align(); + } - // recovery_dtbo - if (access(RECV_DTBO_FILE, R_OK) == 0) { - boot.hdr->recovery_dtbo_offset() = lseek(fd, 0, SEEK_CUR); - boot.hdr->recovery_dtbo_size() = restore(fd, RECV_DTBO_FILE); - file_align(); - } + // recovery_dtbo + if (access(RECV_DTBO_FILE, R_OK) == 0) { + boot.hdr->recovery_dtbo_offset() = lseek(fd, 0, SEEK_CUR); + boot.hdr->recovery_dtbo_size() = restore(fd, RECV_DTBO_FILE); + file_align(); + } - // dtb - off.dtb = lseek(fd, 0, SEEK_CUR); - if (access(DTB_FILE, R_OK) == 0) { - boot.hdr->dtb_size() = restore(fd, DTB_FILE); - file_align(); - } + // dtb + off.dtb = lseek(fd, 0, SEEK_CUR); + if (access(DTB_FILE, R_OK) == 0) { + boot.hdr->dtb_size() = restore(fd, DTB_FILE); + file_align(); + } - // Append tail info - if (is_flag(SEANDROID_FLAG)) { - restore_buf(fd, SEANDROID_MAGIC "\xFF\xFF\xFF\xFF", 20); - } - if (is_flag(LG_BUMP_FLAG)) { - restore_buf(fd, LG_BUMP_MAGIC, 16); - } + // Append tail info + if (is_flag(SEANDROID_FLAG)) { + restore_buf(fd, SEANDROID_MAGIC "\xFF\xFF\xFF\xFF", 20); + } + if (is_flag(LG_BUMP_FLAG)) { + restore_buf(fd, LG_BUMP_MAGIC, 16); + } - // Pad image to at least original size if not chromeos (as it requires post processing) - if (!is_flag(CHROMEOS_FLAG)) { - auto current_sz = lseek(fd, 0, SEEK_CUR); - if (current_sz < boot.map_size) { - int padding = boot.map_size - current_sz; - write_zero(fd, padding); - } - } + // Pad image to at least original size if not chromeos (as it requires post processing) + if (!is_flag(CHROMEOS_FLAG)) { + auto current_sz = lseek(fd, 0, SEEK_CUR); + if (current_sz < boot.map_size) { + int padding = boot.map_size - current_sz; + write_zero(fd, padding); + } + } - close(fd); + close(fd); - /********************* - * Patching the image - *********************/ + /********************* + * Patching the image + *********************/ - // Map output image as rw - munmap(boot.map_addr, boot.map_size); - mmap_rw(out_img, boot.map_addr, boot.map_size); + // Map output image as rw + munmap(boot.map_addr, boot.map_size); + mmap_rw(out_img, boot.map_addr, boot.map_size); - // MTK headers - if (is_flag(MTK_KERNEL)) { - auto hdr = reinterpret_cast(boot.map_addr + off.kernel); - hdr->size = boot.hdr->kernel_size(); - boot.hdr->kernel_size() += sizeof(*hdr); - } - if (is_flag(MTK_RAMDISK)) { - auto hdr = reinterpret_cast(boot.map_addr + off.ramdisk); - hdr->size = boot.hdr->ramdisk_size(); - boot.hdr->ramdisk_size() += sizeof(*hdr); - } + // MTK headers + if (is_flag(MTK_KERNEL)) { + auto hdr = reinterpret_cast(boot.map_addr + off.kernel); + hdr->size = boot.hdr->kernel_size(); + boot.hdr->kernel_size() += sizeof(*hdr); + } + if (is_flag(MTK_RAMDISK)) { + auto hdr = reinterpret_cast(boot.map_addr + off.ramdisk); + hdr->size = boot.hdr->ramdisk_size(); + boot.hdr->ramdisk_size() += sizeof(*hdr); + } - // Make sure header size matches - boot.hdr->header_size() = boot.hdr->hdr_size(); + // Make sure header size matches + boot.hdr->header_size() = boot.hdr->hdr_size(); - // Update checksum - if (char *id = boot.hdr->id()) { - HASH_CTX ctx; - is_flag(SHA256_FLAG) ? SHA256_init(&ctx) : SHA_init(&ctx); - uint32_t size = boot.hdr->kernel_size(); - HASH_update(&ctx, boot.map_addr + off.kernel, size); - HASH_update(&ctx, &size, sizeof(size)); - size = boot.hdr->ramdisk_size(); - HASH_update(&ctx, boot.map_addr + off.ramdisk, size); - HASH_update(&ctx, &size, sizeof(size)); - size = boot.hdr->second_size(); - HASH_update(&ctx, boot.map_addr + off.second, size); - HASH_update(&ctx, &size, sizeof(size)); - size = boot.hdr->extra_size(); - if (size) { - HASH_update(&ctx, boot.map_addr + off.extra, size); - HASH_update(&ctx, &size, sizeof(size)); - } - uint32_t ver = boot.hdr->header_version(); - if (ver == 1 || ver == 2) { - size = boot.hdr->recovery_dtbo_size(); - HASH_update(&ctx, boot.map_addr + boot.hdr->recovery_dtbo_offset(), size); - HASH_update(&ctx, &size, sizeof(size)); - } - if (ver == 2) { - size = boot.hdr->dtb_size(); - HASH_update(&ctx, boot.map_addr + off.dtb, size); - HASH_update(&ctx, &size, sizeof(size)); - } - memset(id, 0, BOOT_ID_SIZE); - memcpy(id, HASH_final(&ctx), is_flag(SHA256_FLAG) ? SHA256_DIGEST_SIZE : SHA_DIGEST_SIZE); - } + // Update checksum + if (char *id = boot.hdr->id()) { + HASH_CTX ctx; + is_flag(SHA256_FLAG) ? SHA256_init(&ctx) : SHA_init(&ctx); + uint32_t size = boot.hdr->kernel_size(); + HASH_update(&ctx, boot.map_addr + off.kernel, size); + HASH_update(&ctx, &size, sizeof(size)); + size = boot.hdr->ramdisk_size(); + HASH_update(&ctx, boot.map_addr + off.ramdisk, size); + HASH_update(&ctx, &size, sizeof(size)); + size = boot.hdr->second_size(); + HASH_update(&ctx, boot.map_addr + off.second, size); + HASH_update(&ctx, &size, sizeof(size)); + size = boot.hdr->extra_size(); + if (size) { + HASH_update(&ctx, boot.map_addr + off.extra, size); + HASH_update(&ctx, &size, sizeof(size)); + } + uint32_t ver = boot.hdr->header_version(); + if (ver == 1 || ver == 2) { + size = boot.hdr->recovery_dtbo_size(); + HASH_update(&ctx, boot.map_addr + boot.hdr->recovery_dtbo_offset(), size); + HASH_update(&ctx, &size, sizeof(size)); + } + if (ver == 2) { + size = boot.hdr->dtb_size(); + HASH_update(&ctx, boot.map_addr + off.dtb, size); + HASH_update(&ctx, &size, sizeof(size)); + } + memset(id, 0, BOOT_ID_SIZE); + memcpy(id, HASH_final(&ctx), is_flag(SHA256_FLAG) ? SHA256_DIGEST_SIZE : SHA_DIGEST_SIZE); + } - // Print new image info - boot.hdr->print(); + // Print new image info + boot.hdr->print(); - // Main header - memcpy(boot.map_addr + off.header, boot.hdr->raw_hdr(), boot.hdr->hdr_size()); + // Main header + memcpy(boot.map_addr + off.header, boot.hdr->raw_hdr(), boot.hdr->hdr_size()); - if (is_flag(DHTB_FLAG)) { - // DHTB header - auto hdr = reinterpret_cast(boot.map_addr); - memcpy(hdr, DHTB_MAGIC, 8); - hdr->size = boot.map_size - sizeof(dhtb_hdr); - SHA256_hash(boot.map_addr + sizeof(dhtb_hdr), hdr->size, hdr->checksum); - } else if (is_flag(BLOB_FLAG)) { - // Blob header - auto hdr = reinterpret_cast(boot.map_addr); - hdr->size = boot.map_size - sizeof(blob_hdr); - } + if (is_flag(DHTB_FLAG)) { + // DHTB header + auto hdr = reinterpret_cast(boot.map_addr); + memcpy(hdr, DHTB_MAGIC, 8); + hdr->size = boot.map_size - sizeof(dhtb_hdr); + SHA256_hash(boot.map_addr + sizeof(dhtb_hdr), hdr->size, hdr->checksum); + } else if (is_flag(BLOB_FLAG)) { + // Blob header + auto hdr = reinterpret_cast(boot.map_addr); + hdr->size = boot.map_size - sizeof(blob_hdr); + } } diff --git a/native/jni/magiskboot/bootimg.hpp b/native/jni/magiskboot/bootimg.hpp index 9be673b33..579047ea7 100644 --- a/native/jni/magiskboot/bootimg.hpp +++ b/native/jni/magiskboot/bootimg.hpp @@ -9,35 +9,35 @@ *****************/ struct mtk_hdr { - uint32_t magic; /* MTK magic */ - uint32_t size; /* Size of the content */ - char name[32]; /* The type of the header */ + uint32_t magic; /* MTK magic */ + uint32_t size; /* Size of the content */ + char name[32]; /* The type of the header */ - char padding[472]; /* Padding to 512 bytes */ + char padding[472]; /* Padding to 512 bytes */ } __attribute__((packed)); struct dhtb_hdr { - char magic[8]; /* DHTB magic */ - uint8_t checksum[40]; /* Payload SHA256, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */ - uint32_t size; /* Payload size, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */ + char magic[8]; /* DHTB magic */ + uint8_t checksum[40]; /* Payload SHA256, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */ + uint32_t size; /* Payload size, whole image + SEANDROIDENFORCE + 0xFFFFFFFF */ - char padding[460]; /* Padding to 512 bytes */ + char padding[460]; /* Padding to 512 bytes */ } __attribute__((packed)); struct blob_hdr { - char secure_magic[20]; /* "-SIGNED-BY-SIGNBLOB-" */ - uint32_t datalen; /* 0x00000000 */ - uint32_t signature; /* 0x00000000 */ - char magic[16]; /* "MSM-RADIO-UPDATE" */ - uint32_t hdr_version; /* 0x00010000 */ - uint32_t hdr_size; /* Size of header */ - uint32_t part_offset; /* Same as size */ - uint32_t num_parts; /* Number of partitions */ - uint32_t unknown[7]; /* All 0x00000000 */ - char name[4]; /* Name of partition */ - uint32_t offset; /* offset in blob where this partition starts */ - uint32_t size; /* Size of data */ - uint32_t version; /* 0x00000001 */ + char secure_magic[20]; /* "-SIGNED-BY-SIGNBLOB-" */ + uint32_t datalen; /* 0x00000000 */ + uint32_t signature; /* 0x00000000 */ + char magic[16]; /* "MSM-RADIO-UPDATE" */ + uint32_t hdr_version; /* 0x00010000 */ + uint32_t hdr_size; /* Size of header */ + uint32_t part_offset; /* Same as size */ + uint32_t num_parts; /* Number of partitions */ + uint32_t unknown[7]; /* All 0x00000000 */ + char name[4]; /* Name of partition */ + uint32_t offset; /* offset in blob where this partition starts */ + uint32_t size; /* Size of data */ + uint32_t version; /* 0x00000001 */ } __attribute__((packed)); @@ -78,54 +78,54 @@ struct blob_hdr { */ struct boot_img_hdr_common { - char magic[BOOT_MAGIC_SIZE]; + char magic[BOOT_MAGIC_SIZE]; - uint32_t kernel_size; /* size in bytes */ - uint32_t kernel_addr; /* physical load addr */ + uint32_t kernel_size; /* size in bytes */ + uint32_t kernel_addr; /* physical load addr */ - uint32_t ramdisk_size; /* size in bytes */ - uint32_t ramdisk_addr; /* physical load addr */ + uint32_t ramdisk_size; /* size in bytes */ + uint32_t ramdisk_addr; /* physical load addr */ - uint32_t second_size; /* size in bytes */ - uint32_t second_addr; /* physical load addr */ + uint32_t second_size; /* size in bytes */ + uint32_t second_addr; /* physical load addr */ } __attribute__((packed)); struct boot_img_hdr_v0 : public boot_img_hdr_common { - uint32_t tags_addr; /* physical addr for kernel tags */ - uint32_t page_size; /* flash page size we assume */ + uint32_t tags_addr; /* physical addr for kernel tags */ + uint32_t page_size; /* flash page size we assume */ - // In header v1, this field is used for header version - // However, on some devices like Samsung, this field is used to store DTB - // We treat this field differently based on its value - union { - uint32_t header_version; /* the version of the header */ - uint32_t extra_size; /* extra blob size in bytes */ - }; + // In header v1, this field is used for header version + // However, on some devices like Samsung, this field is used to store DTB + // We treat this field differently based on its value + union { + uint32_t header_version; /* the version of the header */ + uint32_t extra_size; /* extra blob size in bytes */ + }; - // Operating system version and security patch level. - // For version "A.B.C" and patch level "Y-M-D": - // (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M) - // os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0] - uint32_t os_version; + // Operating system version and security patch level. + // For version "A.B.C" and patch level "Y-M-D": + // (7 bits for each of A, B, C; 7 bits for (Y-2000), 4 bits for M) + // os_version = A[31:25] B[24:18] C[17:11] (Y-2000)[10:4] M[3:0] + uint32_t os_version; - char name[BOOT_NAME_SIZE]; /* asciiz product name */ - char cmdline[BOOT_ARGS_SIZE]; - char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */ + char name[BOOT_NAME_SIZE]; /* asciiz product name */ + char cmdline[BOOT_ARGS_SIZE]; + char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */ - // Supplemental command line data; kept here to maintain - // binary compatibility with older versions of mkbootimg. - char extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; + // Supplemental command line data; kept here to maintain + // binary compatibility with older versions of mkbootimg. + char extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; } __attribute__((packed)); struct boot_img_hdr_v1 : public boot_img_hdr_v0 { - uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */ - uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */ - uint32_t header_size; + uint32_t recovery_dtbo_size; /* size in bytes for recovery DTBO/ACPIO image */ + uint64_t recovery_dtbo_offset; /* offset to recovery dtbo/acpio in boot image */ + uint32_t header_size; } __attribute__((packed)); struct boot_img_hdr_v2 : public boot_img_hdr_v1 { - uint32_t dtb_size; /* size in bytes for DTB image */ - uint64_t dtb_addr; /* physical load address for DTB image */ + uint32_t dtb_size; /* size in bytes for DTB image */ + uint64_t dtb_addr; /* physical load address for DTB image */ } __attribute__((packed)); // Default to hdr v2 @@ -133,16 +133,16 @@ using boot_img_hdr = boot_img_hdr_v2; // Special Samsung header struct boot_img_hdr_pxa : public boot_img_hdr_common { - uint32_t extra_size; /* extra blob size in bytes */ - uint32_t unknown; - uint32_t tags_addr; /* physical addr for kernel tags */ - uint32_t page_size; /* flash page size we assume */ + uint32_t extra_size; /* extra blob size in bytes */ + uint32_t unknown; + uint32_t tags_addr; /* physical addr for kernel tags */ + uint32_t page_size; /* flash page size we assume */ - char name[24]; /* asciiz product name */ - char cmdline[BOOT_ARGS_SIZE]; - char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */ + char name[24]; /* asciiz product name */ + char cmdline[BOOT_ARGS_SIZE]; + char id[BOOT_ID_SIZE]; /* timestamp / checksum / sha1 / etc */ - char extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; + char extra_cmdline[BOOT_EXTRA_ARGS_SIZE]; } __attribute__((packed)); /* When the boot image header has a version of 3, the structure of the boot @@ -178,34 +178,34 @@ struct boot_img_hdr_pxa : public boot_img_hdr_common { */ struct boot_img_hdr_v3 { - uint8_t magic[BOOT_MAGIC_SIZE]; + uint8_t magic[BOOT_MAGIC_SIZE]; - uint32_t kernel_size; /* size in bytes */ - uint32_t ramdisk_size; /* size in bytes */ - uint32_t os_version; - uint32_t header_size; - uint32_t reserved[4]; + uint32_t kernel_size; /* size in bytes */ + uint32_t ramdisk_size; /* size in bytes */ + uint32_t os_version; + uint32_t header_size; + uint32_t reserved[4]; - uint32_t header_version; + uint32_t header_version; - char cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE]; + char cmdline[BOOT_ARGS_SIZE + BOOT_EXTRA_ARGS_SIZE]; } __attribute__((packed)); struct boot_img_hdr_vnd_v3 { - // Must be VENDOR_BOOT_MAGIC. - uint8_t magic[BOOT_MAGIC_SIZE]; - // Version of the vendor boot image header. - uint32_t header_version; - uint32_t page_size; /* flash page size we assume */ - uint32_t kernel_addr; /* physical load addr */ - uint32_t ramdisk_addr; /* physical load addr */ - uint32_t ramdisk_size; /* size in bytes */ - char cmdline[VENDOR_BOOT_ARGS_SIZE]; - uint32_t tags_addr; /* physical addr for kernel tags (if required) */ - char name[BOOT_NAME_SIZE]; /* asciiz product name */ - uint32_t header_size; - uint32_t dtb_size; /* size in bytes for DTB image */ - uint64_t dtb_addr; /* physical load address for DTB image */ + // Must be VENDOR_BOOT_MAGIC. + uint8_t magic[BOOT_MAGIC_SIZE]; + // Version of the vendor boot image header. + uint32_t header_version; + uint32_t page_size; /* flash page size we assume */ + uint32_t kernel_addr; /* physical load addr */ + uint32_t ramdisk_addr; /* physical load addr */ + uint32_t ramdisk_size; /* size in bytes */ + char cmdline[VENDOR_BOOT_ARGS_SIZE]; + uint32_t tags_addr; /* physical addr for kernel tags (if required) */ + char name[BOOT_NAME_SIZE]; /* asciiz product name */ + uint32_t header_size; + uint32_t dtb_size; /* size in bytes for DTB image */ + uint64_t dtb_addr; /* physical load address for DTB image */ } __attribute__((packed)); /******************************* @@ -219,51 +219,51 @@ virtual type name() { return 0; } struct dyn_img_hdr { - // Standard entries - decl_var(kernel_size, 32) - decl_var(ramdisk_size, 32) - decl_var(second_size, 32) - decl_var(page_size, 32) - decl_val(header_version, uint32_t) - decl_var(extra_size, 32) - decl_var(os_version, 32) - decl_val(name, char *) - decl_val(cmdline, char *) - decl_val(id, char *) - decl_val(extra_cmdline, char *) + // Standard entries + decl_var(kernel_size, 32) + decl_var(ramdisk_size, 32) + decl_var(second_size, 32) + decl_var(page_size, 32) + decl_val(header_version, uint32_t) + decl_var(extra_size, 32) + decl_var(os_version, 32) + decl_val(name, char *) + decl_val(cmdline, char *) + decl_val(id, char *) + decl_val(extra_cmdline, char *) - // v1/v2 specific - decl_var(recovery_dtbo_size, 32) - decl_var(recovery_dtbo_offset, 64) - decl_var(header_size, 32) - decl_var(dtb_size, 32) + // v1/v2 specific + decl_var(recovery_dtbo_size, 32) + decl_var(recovery_dtbo_offset, 64) + decl_var(header_size, 32) + decl_var(dtb_size, 32) - virtual ~dyn_img_hdr() { - free(raw); - } + virtual ~dyn_img_hdr() { + free(raw); + } - virtual size_t hdr_size() = 0; - virtual size_t hdr_space() { return page_size(); } + virtual size_t hdr_size() = 0; + virtual size_t hdr_space() { return page_size(); } - const void *raw_hdr() const { return raw; } - void print(); - void dump_hdr_file(); - void load_hdr_file(); + const void *raw_hdr() const { return raw; } + void print(); + void dump_hdr_file(); + void load_hdr_file(); protected: - union { - // Main header could be either AOSP or PXA - boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */ - boot_img_hdr_v3 *v3_hdr; /* AOSP v3 header */ - boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */ - boot_img_hdr_vnd_v3 *vnd; /* AOSP vendor v3 header */ - void *raw; /* Raw pointer */ - }; + union { + // Main header could be either AOSP or PXA + boot_img_hdr_v2 *v2_hdr; /* AOSP v2 header */ + boot_img_hdr_v3 *v3_hdr; /* AOSP v3 header */ + boot_img_hdr_pxa *hdr_pxa; /* Samsung PXA header */ + boot_img_hdr_vnd_v3 *vnd; /* AOSP vendor v3 header */ + void *raw; /* Raw pointer */ + }; private: - // Junk for references - static uint32_t j32; - static uint64_t j64; + // Junk for references + static uint32_t j32; + static uint64_t j64; }; #undef decl_var @@ -273,8 +273,8 @@ private: protected: name() = default; \ public: \ name(void *ptr) { \ - raw = xmalloc(sizeof(hdr)); \ - memcpy(raw, ptr, sizeof(hdr)); \ + raw = xmalloc(sizeof(hdr)); \ + memcpy(raw, ptr, sizeof(hdr)); \ } \ size_t hdr_size() override { return sizeof(hdr); } @@ -285,93 +285,93 @@ decltype(std::declval().name()) name() override { return hdr_name-> #define impl_val(name) __impl_val(name, v2_hdr) struct dyn_img_common : public dyn_img_hdr { - impl_val(kernel_size) - impl_val(ramdisk_size) - impl_val(second_size) + impl_val(kernel_size) + impl_val(ramdisk_size) + impl_val(second_size) }; struct dyn_img_v0 : public dyn_img_common { - impl_cls(v0) + impl_cls(v0) - impl_val(page_size) - impl_val(extra_size) - impl_val(os_version) - impl_val(name) - impl_val(cmdline) - impl_val(id) - impl_val(extra_cmdline) + impl_val(page_size) + impl_val(extra_size) + impl_val(os_version) + impl_val(name) + impl_val(cmdline) + impl_val(id) + impl_val(extra_cmdline) }; struct dyn_img_v1 : public dyn_img_v0 { - impl_cls(v1) + impl_cls(v1) - impl_val(header_version) - impl_val(recovery_dtbo_size) - impl_val(recovery_dtbo_offset) - impl_val(header_size) + impl_val(header_version) + impl_val(recovery_dtbo_size) + impl_val(recovery_dtbo_offset) + impl_val(header_size) - uint32_t &extra_size() override { return dyn_img_hdr::extra_size(); } + uint32_t &extra_size() override { return dyn_img_hdr::extra_size(); } }; struct dyn_img_v2 : public dyn_img_v1 { - impl_cls(v2) + impl_cls(v2) - impl_val(dtb_size) + impl_val(dtb_size) }; #undef impl_val #define impl_val(name) __impl_val(name, hdr_pxa) struct dyn_img_pxa : public dyn_img_common { - impl_cls(pxa) + impl_cls(pxa) - impl_val(extra_size) - impl_val(page_size) - impl_val(name) - impl_val(cmdline) - impl_val(id) - impl_val(extra_cmdline) + impl_val(extra_size) + impl_val(page_size) + impl_val(name) + impl_val(cmdline) + impl_val(id) + impl_val(extra_cmdline) }; #undef impl_val #define impl_val(name) __impl_val(name, v3_hdr) struct dyn_img_v3 : public dyn_img_hdr { - impl_cls(v3) + impl_cls(v3) - impl_val(kernel_size) - impl_val(ramdisk_size) - impl_val(os_version) - impl_val(header_size) - impl_val(header_version) - impl_val(cmdline) + impl_val(kernel_size) + impl_val(ramdisk_size) + impl_val(os_version) + impl_val(header_size) + impl_val(header_version) + impl_val(cmdline) - // Make API compatible - uint32_t &page_size() override { page_sz = 4096; return page_sz; } - char *extra_cmdline() override { return &v3_hdr->cmdline[BOOT_ARGS_SIZE]; } + // Make API compatible + uint32_t &page_size() override { page_sz = 4096; return page_sz; } + char *extra_cmdline() override { return &v3_hdr->cmdline[BOOT_ARGS_SIZE]; } private: - uint32_t page_sz; + uint32_t page_sz; }; #undef impl_val #define impl_val(name) __impl_val(name, vnd) struct dyn_img_vnd_v3 : public dyn_img_hdr { - impl_cls(vnd_v3) + impl_cls(vnd_v3) - impl_val(header_version) - impl_val(page_size) - impl_val(ramdisk_size) - impl_val(cmdline) - impl_val(name) - impl_val(header_size) - impl_val(dtb_size) + impl_val(header_version) + impl_val(page_size) + impl_val(ramdisk_size) + impl_val(cmdline) + impl_val(name) + impl_val(header_size) + impl_val(dtb_size) - size_t hdr_space() override { auto sz = page_size(); return do_align(hdr_size(), sz); } + size_t hdr_space() override { auto sz = page_size(); return do_align(hdr_size(), sz); } - // Make API compatible - char *extra_cmdline() override { return &vnd->cmdline[BOOT_ARGS_SIZE]; } + // Make API compatible + char *extra_cmdline() override { return &vnd->cmdline[BOOT_ARGS_SIZE]; } }; #undef __impl_cls @@ -395,48 +395,48 @@ struct dyn_img_vnd_v3 : public dyn_img_hdr { #define ACCLAIM_FLAG (1 << 9) struct boot_img { - // Memory map of the whole image - uint8_t *map_addr; - size_t map_size; + // Memory map of the whole image + uint8_t *map_addr; + size_t map_size; - // Android image header - dyn_img_hdr *hdr; + // Android image header + dyn_img_hdr *hdr; - // Flags to indicate the state of current boot image - uint16_t flags = 0; + // Flags to indicate the state of current boot image + uint16_t flags = 0; - // The format of kernel, ramdisk and extra - format_t k_fmt = UNKNOWN; - format_t r_fmt = UNKNOWN; - format_t e_fmt = UNKNOWN; + // The format of kernel, ramdisk and extra + format_t k_fmt = UNKNOWN; + format_t r_fmt = UNKNOWN; + format_t e_fmt = UNKNOWN; - /*************************************************** - * Following pointers points within the mmap region - ***************************************************/ + /*************************************************** + * Following pointers points within the mmap region + ***************************************************/ - // MTK headers - mtk_hdr *k_hdr; - mtk_hdr *r_hdr; + // MTK headers + mtk_hdr *k_hdr; + mtk_hdr *r_hdr; - // Pointer to dtb that is embedded in kernel - uint8_t *kernel_dtb; - uint32_t kernel_dt_size = 0; + // Pointer to dtb that is embedded in kernel + uint8_t *kernel_dtb; + uint32_t kernel_dt_size = 0; - // Pointer to end of image - uint8_t *tail; - size_t tail_size = 0; + // Pointer to end of image + uint8_t *tail; + size_t tail_size = 0; - // Pointers to blocks defined in header - uint8_t *hdr_addr; - uint8_t *kernel; - uint8_t *ramdisk; - uint8_t *second; - uint8_t *extra; - uint8_t *recovery_dtbo; - uint8_t *dtb; + // Pointers to blocks defined in header + uint8_t *hdr_addr; + uint8_t *kernel; + uint8_t *ramdisk; + uint8_t *second; + uint8_t *extra; + uint8_t *recovery_dtbo; + uint8_t *dtb; - boot_img(const char *); - ~boot_img(); + boot_img(const char *); + ~boot_img(); - void parse_image(uint8_t *addr, format_t type); + void parse_image(uint8_t *addr, format_t type); }; diff --git a/native/jni/magiskboot/compress.cpp b/native/jni/magiskboot/compress.cpp index 4a5c2ae0b..3b72fa5d8 100644 --- a/native/jni/magiskboot/compress.cpp +++ b/native/jni/magiskboot/compress.cpp @@ -28,622 +28,622 @@ constexpr size_t LZ4_COMPRESSED = LZ4_COMPRESSBOUND(LZ4_UNCOMPRESSED); class cpr_stream : public filter_stream { public: - using filter_stream::filter_stream; - using stream::read; + using filter_stream::filter_stream; + using stream::read; }; class gz_strm : public cpr_stream { public: - int write(const void *buf, size_t len) override { - return len ? write(buf, len, Z_NO_FLUSH) : 0; - } + int write(const void *buf, size_t len) override { + return len ? write(buf, len, Z_NO_FLUSH) : 0; + } - ~gz_strm() override { - write(nullptr, 0, Z_FINISH); - switch(mode) { - case DECODE: - inflateEnd(&strm); - break; - case ENCODE: - deflateEnd(&strm); - break; - } - } + ~gz_strm() override { + write(nullptr, 0, Z_FINISH); + switch(mode) { + case DECODE: + inflateEnd(&strm); + break; + case ENCODE: + deflateEnd(&strm); + break; + } + } protected: - enum mode_t { - DECODE, - ENCODE - } mode; + enum mode_t { + DECODE, + ENCODE + } mode; - gz_strm(mode_t mode, stream_ptr &&base) : cpr_stream(std::move(base)), mode(mode) { - switch(mode) { - case DECODE: - inflateInit2(&strm, 15 | 16); - break; - case ENCODE: - deflateInit2(&strm, 9, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); - break; - } - } + gz_strm(mode_t mode, stream_ptr &&base) : cpr_stream(std::move(base)), mode(mode) { + switch(mode) { + case DECODE: + inflateInit2(&strm, 15 | 16); + break; + case ENCODE: + deflateInit2(&strm, 9, Z_DEFLATED, 15 | 16, 8, Z_DEFAULT_STRATEGY); + break; + } + } private: - z_stream strm; - uint8_t outbuf[CHUNK]; + z_stream strm; + uint8_t outbuf[CHUNK]; - int write(const void *buf, size_t len, int flush) { - int ret = 0; - strm.next_in = (Bytef *) buf; - strm.avail_in = len; - do { - int code; - strm.next_out = outbuf; - strm.avail_out = sizeof(outbuf); - switch(mode) { - case DECODE: - code = inflate(&strm, flush); - break; - case ENCODE: - code = deflate(&strm, flush); - break; - } - if (code == Z_STREAM_ERROR) { - LOGW("gzip %s failed (%d)\n", mode ? "encode" : "decode", code); - return -1; - } - ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out); - } while (strm.avail_out == 0); - return ret; - } + int write(const void *buf, size_t len, int flush) { + int ret = 0; + strm.next_in = (Bytef *) buf; + strm.avail_in = len; + do { + int code; + strm.next_out = outbuf; + strm.avail_out = sizeof(outbuf); + switch(mode) { + case DECODE: + code = inflate(&strm, flush); + break; + case ENCODE: + code = deflate(&strm, flush); + break; + } + if (code == Z_STREAM_ERROR) { + LOGW("gzip %s failed (%d)\n", mode ? "encode" : "decode", code); + return -1; + } + ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out); + } while (strm.avail_out == 0); + return ret; + } }; class gz_decoder : public gz_strm { public: - explicit gz_decoder(stream_ptr &&base) : gz_strm(DECODE, std::move(base)) {}; + explicit gz_decoder(stream_ptr &&base) : gz_strm(DECODE, std::move(base)) {}; }; class gz_encoder : public gz_strm { public: - explicit gz_encoder(stream_ptr &&base) : gz_strm(ENCODE, std::move(base)) {}; + explicit gz_encoder(stream_ptr &&base) : gz_strm(ENCODE, std::move(base)) {}; }; class bz_strm : public cpr_stream { public: - int write(const void *buf, size_t len) override { - return len ? write(buf, len, BZ_RUN) : 0; - } + int write(const void *buf, size_t len) override { + return len ? write(buf, len, BZ_RUN) : 0; + } - ~bz_strm() override { - switch(mode) { - case DECODE: - BZ2_bzDecompressEnd(&strm); - break; - case ENCODE: - write(nullptr, 0, BZ_FINISH); - BZ2_bzCompressEnd(&strm); - break; - } - } + ~bz_strm() override { + switch(mode) { + case DECODE: + BZ2_bzDecompressEnd(&strm); + break; + case ENCODE: + write(nullptr, 0, BZ_FINISH); + BZ2_bzCompressEnd(&strm); + break; + } + } protected: - enum mode_t { - DECODE, - ENCODE - } mode; + enum mode_t { + DECODE, + ENCODE + } mode; - bz_strm(mode_t mode, stream_ptr &&base) : cpr_stream(std::move(base)), mode(mode) { - switch(mode) { - case DECODE: - BZ2_bzDecompressInit(&strm, 0, 0); - break; - case ENCODE: - BZ2_bzCompressInit(&strm, 9, 0, 0); - break; - } - } + bz_strm(mode_t mode, stream_ptr &&base) : cpr_stream(std::move(base)), mode(mode) { + switch(mode) { + case DECODE: + BZ2_bzDecompressInit(&strm, 0, 0); + break; + case ENCODE: + BZ2_bzCompressInit(&strm, 9, 0, 0); + break; + } + } private: - bz_stream strm; - char outbuf[CHUNK]; + bz_stream strm; + char outbuf[CHUNK]; - int write(const void *buf, size_t len, int flush) { - int ret = 0; - strm.next_in = (char *) buf; - strm.avail_in = len; - do { - int code; - strm.avail_out = sizeof(outbuf); - strm.next_out = outbuf; - switch(mode) { - case DECODE: - code = BZ2_bzDecompress(&strm); - break; - case ENCODE: - code = BZ2_bzCompress(&strm, flush); - break; - } - if (code < 0) { - LOGW("bzip2 %s failed (%d)\n", mode ? "encode" : "decode", code); - return -1; - } - ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out); - } while (strm.avail_out == 0); - return ret; - } + int write(const void *buf, size_t len, int flush) { + int ret = 0; + strm.next_in = (char *) buf; + strm.avail_in = len; + do { + int code; + strm.avail_out = sizeof(outbuf); + strm.next_out = outbuf; + switch(mode) { + case DECODE: + code = BZ2_bzDecompress(&strm); + break; + case ENCODE: + code = BZ2_bzCompress(&strm, flush); + break; + } + if (code < 0) { + LOGW("bzip2 %s failed (%d)\n", mode ? "encode" : "decode", code); + return -1; + } + ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out); + } while (strm.avail_out == 0); + return ret; + } }; class bz_decoder : public bz_strm { public: - explicit bz_decoder(stream_ptr &&base) : bz_strm(DECODE, std::move(base)) {}; + explicit bz_decoder(stream_ptr &&base) : bz_strm(DECODE, std::move(base)) {}; }; class bz_encoder : public bz_strm { public: - explicit bz_encoder(stream_ptr &&base) : bz_strm(ENCODE, std::move(base)) {}; + explicit bz_encoder(stream_ptr &&base) : bz_strm(ENCODE, std::move(base)) {}; }; class lzma_strm : public cpr_stream { public: - int write(const void *buf, size_t len) override { - return len ? write(buf, len, LZMA_RUN) : 0; - } + int write(const void *buf, size_t len) override { + return len ? write(buf, len, LZMA_RUN) : 0; + } - ~lzma_strm() override { - write(nullptr, 0, LZMA_FINISH); - lzma_end(&strm); - } + ~lzma_strm() override { + write(nullptr, 0, LZMA_FINISH); + lzma_end(&strm); + } protected: - enum mode_t { - DECODE, - ENCODE_XZ, - ENCODE_LZMA - } mode; + enum mode_t { + DECODE, + ENCODE_XZ, + ENCODE_LZMA + } mode; - lzma_strm(mode_t mode, stream_ptr &&base) - : cpr_stream(std::move(base)), mode(mode), strm(LZMA_STREAM_INIT) { - lzma_options_lzma opt; + lzma_strm(mode_t mode, stream_ptr &&base) + : cpr_stream(std::move(base)), mode(mode), strm(LZMA_STREAM_INIT) { + lzma_options_lzma opt; - // Initialize preset - lzma_lzma_preset(&opt, 9); - lzma_filter filters[] = { - { .id = LZMA_FILTER_LZMA2, .options = &opt }, - { .id = LZMA_VLI_UNKNOWN, .options = nullptr }, - }; + // Initialize preset + lzma_lzma_preset(&opt, 9); + lzma_filter filters[] = { + { .id = LZMA_FILTER_LZMA2, .options = &opt }, + { .id = LZMA_VLI_UNKNOWN, .options = nullptr }, + }; - lzma_ret ret; - switch(mode) { - case DECODE: - ret = lzma_auto_decoder(&strm, UINT64_MAX, 0); - break; - case ENCODE_XZ: - ret = lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32); - break; - case ENCODE_LZMA: - ret = lzma_alone_encoder(&strm, &opt); - break; - } - } + lzma_ret ret; + switch(mode) { + case DECODE: + ret = lzma_auto_decoder(&strm, UINT64_MAX, 0); + break; + case ENCODE_XZ: + ret = lzma_stream_encoder(&strm, filters, LZMA_CHECK_CRC32); + break; + case ENCODE_LZMA: + ret = lzma_alone_encoder(&strm, &opt); + break; + } + } private: - lzma_stream strm; - uint8_t outbuf[CHUNK]; + lzma_stream strm; + uint8_t outbuf[CHUNK]; - int write(const void *buf, size_t len, lzma_action flush) { - int ret = 0; - strm.next_in = (uint8_t *) buf; - strm.avail_in = len; - do { - strm.avail_out = sizeof(outbuf); - strm.next_out = outbuf; - int code = lzma_code(&strm, flush); - if (code != LZMA_OK && code != LZMA_STREAM_END) { - LOGW("LZMA %s failed (%d)\n", mode ? "encode" : "decode", code); - return -1; - } - ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out); - } while (strm.avail_out == 0); - return ret; - } + int write(const void *buf, size_t len, lzma_action flush) { + int ret = 0; + strm.next_in = (uint8_t *) buf; + strm.avail_in = len; + do { + strm.avail_out = sizeof(outbuf); + strm.next_out = outbuf; + int code = lzma_code(&strm, flush); + if (code != LZMA_OK && code != LZMA_STREAM_END) { + LOGW("LZMA %s failed (%d)\n", mode ? "encode" : "decode", code); + return -1; + } + ret += bwrite(outbuf, sizeof(outbuf) - strm.avail_out); + } while (strm.avail_out == 0); + return ret; + } }; class lzma_decoder : public lzma_strm { public: - explicit lzma_decoder(stream_ptr &&base) : lzma_strm(DECODE, std::move(base)) {} + explicit lzma_decoder(stream_ptr &&base) : lzma_strm(DECODE, std::move(base)) {} }; class xz_encoder : public lzma_strm { public: - explicit xz_encoder(stream_ptr &&base) : lzma_strm(ENCODE_XZ, std::move(base)) {} + explicit xz_encoder(stream_ptr &&base) : lzma_strm(ENCODE_XZ, std::move(base)) {} }; class lzma_encoder : public lzma_strm { public: - explicit lzma_encoder(stream_ptr &&base) : lzma_strm(ENCODE_LZMA, std::move(base)) {} + explicit lzma_encoder(stream_ptr &&base) : lzma_strm(ENCODE_LZMA, std::move(base)) {} }; class LZ4F_decoder : public cpr_stream { public: - explicit LZ4F_decoder(stream_ptr &&base) : cpr_stream(std::move(base)), outbuf(nullptr) { - LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION); - } + explicit LZ4F_decoder(stream_ptr &&base) : cpr_stream(std::move(base)), outbuf(nullptr) { + LZ4F_createDecompressionContext(&ctx, LZ4F_VERSION); + } - ~LZ4F_decoder() override { - LZ4F_freeDecompressionContext(ctx); - delete[] outbuf; - } + ~LZ4F_decoder() override { + LZ4F_freeDecompressionContext(ctx); + delete[] outbuf; + } - int write(const void *buf, size_t len) override { - int ret = 0; - auto inbuf = reinterpret_cast(buf); - if (!outbuf) - read_header(inbuf, len); - size_t read, write; - LZ4F_errorCode_t code; - do { - read = len; - write = outCapacity; - code = LZ4F_decompress(ctx, outbuf, &write, inbuf, &read, nullptr); - if (LZ4F_isError(code)) { - LOGW("LZ4F decode error: %s\n", LZ4F_getErrorName(code)); - return -1; - } - len -= read; - inbuf += read; - ret += bwrite(outbuf, write); - } while (len != 0 || write != 0); - return ret; - } + int write(const void *buf, size_t len) override { + int ret = 0; + auto inbuf = reinterpret_cast(buf); + if (!outbuf) + read_header(inbuf, len); + size_t read, write; + LZ4F_errorCode_t code; + do { + read = len; + write = outCapacity; + code = LZ4F_decompress(ctx, outbuf, &write, inbuf, &read, nullptr); + if (LZ4F_isError(code)) { + LOGW("LZ4F decode error: %s\n", LZ4F_getErrorName(code)); + return -1; + } + len -= read; + inbuf += read; + ret += bwrite(outbuf, write); + } while (len != 0 || write != 0); + return ret; + } private: - LZ4F_decompressionContext_t ctx; - uint8_t *outbuf; - size_t outCapacity; + LZ4F_decompressionContext_t ctx; + uint8_t *outbuf; + size_t outCapacity; - void read_header(const uint8_t *&in, size_t &size) { - size_t read = size; - LZ4F_frameInfo_t info; - LZ4F_getFrameInfo(ctx, &info, in, &read); - switch (info.blockSizeID) { - case LZ4F_default: - case LZ4F_max64KB: outCapacity = 1 << 16; break; - case LZ4F_max256KB: outCapacity = 1 << 18; break; - case LZ4F_max1MB: outCapacity = 1 << 20; break; - case LZ4F_max4MB: outCapacity = 1 << 22; break; - } - outbuf = new uint8_t[outCapacity]; - in += read; - size -= read; - } + void read_header(const uint8_t *&in, size_t &size) { + size_t read = size; + LZ4F_frameInfo_t info; + LZ4F_getFrameInfo(ctx, &info, in, &read); + switch (info.blockSizeID) { + case LZ4F_default: + case LZ4F_max64KB: outCapacity = 1 << 16; break; + case LZ4F_max256KB: outCapacity = 1 << 18; break; + case LZ4F_max1MB: outCapacity = 1 << 20; break; + case LZ4F_max4MB: outCapacity = 1 << 22; break; + } + outbuf = new uint8_t[outCapacity]; + in += read; + size -= read; + } }; class LZ4F_encoder : public cpr_stream { public: - explicit LZ4F_encoder(stream_ptr &&base) - : cpr_stream(std::move(base)), outbuf(nullptr), outCapacity(0) { - LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); - } + explicit LZ4F_encoder(stream_ptr &&base) + : cpr_stream(std::move(base)), outbuf(nullptr), outCapacity(0) { + LZ4F_createCompressionContext(&ctx, LZ4F_VERSION); + } - int write(const void *buf, size_t len) override { - int ret = 0; - if (!outbuf) - ret += write_header(); - if (len == 0) - return 0; - auto inbuf = reinterpret_cast(buf); - size_t read, write; - do { - read = len > BLOCK_SZ ? BLOCK_SZ : len; - write = LZ4F_compressUpdate(ctx, outbuf, outCapacity, inbuf, read, nullptr); - if (LZ4F_isError(write)) { - LOGW("LZ4F encode error: %s\n", LZ4F_getErrorName(write)); - return -1; - } - len -= read; - inbuf += read; - ret += bwrite(outbuf, write); - } while (len != 0); - return ret; - } + int write(const void *buf, size_t len) override { + int ret = 0; + if (!outbuf) + ret += write_header(); + if (len == 0) + return 0; + auto inbuf = reinterpret_cast(buf); + size_t read, write; + do { + read = len > BLOCK_SZ ? BLOCK_SZ : len; + write = LZ4F_compressUpdate(ctx, outbuf, outCapacity, inbuf, read, nullptr); + if (LZ4F_isError(write)) { + LOGW("LZ4F encode error: %s\n", LZ4F_getErrorName(write)); + return -1; + } + len -= read; + inbuf += read; + ret += bwrite(outbuf, write); + } while (len != 0); + return ret; + } - ~LZ4F_encoder() override { - size_t len = LZ4F_compressEnd(ctx, outbuf, outCapacity, nullptr); - bwrite(outbuf, len); - LZ4F_freeCompressionContext(ctx); - delete[] outbuf; - } + ~LZ4F_encoder() override { + size_t len = LZ4F_compressEnd(ctx, outbuf, outCapacity, nullptr); + bwrite(outbuf, len); + LZ4F_freeCompressionContext(ctx); + delete[] outbuf; + } private: - LZ4F_compressionContext_t ctx; - uint8_t *outbuf; - size_t outCapacity; + LZ4F_compressionContext_t ctx; + uint8_t *outbuf; + size_t outCapacity; - static constexpr size_t BLOCK_SZ = 1 << 22; + static constexpr size_t BLOCK_SZ = 1 << 22; - int write_header() { - LZ4F_preferences_t prefs { - .autoFlush = 1, - .compressionLevel = 9, - .frameInfo = { - .blockMode = LZ4F_blockIndependent, - .blockSizeID = LZ4F_max4MB, - .blockChecksumFlag = LZ4F_noBlockChecksum, - .contentChecksumFlag = LZ4F_contentChecksumEnabled - } - }; - outCapacity = LZ4F_compressBound(BLOCK_SZ, &prefs); - outbuf = new uint8_t[outCapacity]; - size_t write = LZ4F_compressBegin(ctx, outbuf, outCapacity, &prefs); - return bwrite(outbuf, write); - } + int write_header() { + LZ4F_preferences_t prefs { + .autoFlush = 1, + .compressionLevel = 9, + .frameInfo = { + .blockMode = LZ4F_blockIndependent, + .blockSizeID = LZ4F_max4MB, + .blockChecksumFlag = LZ4F_noBlockChecksum, + .contentChecksumFlag = LZ4F_contentChecksumEnabled + } + }; + outCapacity = LZ4F_compressBound(BLOCK_SZ, &prefs); + outbuf = new uint8_t[outCapacity]; + size_t write = LZ4F_compressBegin(ctx, outbuf, outCapacity, &prefs); + return bwrite(outbuf, write); + } }; class LZ4_decoder : public cpr_stream { public: - explicit LZ4_decoder(stream_ptr &&base) - : cpr_stream(std::move(base)), out_buf(new char[LZ4_UNCOMPRESSED]), - buf(new char[LZ4_COMPRESSED]), init(false), block_sz(0), buf_off(0) {} + explicit LZ4_decoder(stream_ptr &&base) + : cpr_stream(std::move(base)), out_buf(new char[LZ4_UNCOMPRESSED]), + buf(new char[LZ4_COMPRESSED]), init(false), block_sz(0), buf_off(0) {} - ~LZ4_decoder() override { - delete[] out_buf; - delete[] buf; - } + ~LZ4_decoder() override { + delete[] out_buf; + delete[] buf; + } - int write(const void *in, size_t size) override { - int ret = 0; - auto inbuf = static_cast(in); - if (!init) { - // Skip magic - inbuf += 4; - size -= 4; - init = true; - } - for (int consumed; size != 0;) { - if (block_sz == 0) { - if (buf_off + size >= sizeof(block_sz)) { - consumed = sizeof(block_sz) - buf_off; - memcpy(buf + buf_off, inbuf, consumed); - memcpy(&block_sz, buf, sizeof(block_sz)); - buf_off = 0; - } else { - consumed = size; - memcpy(buf + buf_off, inbuf, size); - } - inbuf += consumed; - size -= consumed; - } else if (buf_off + size >= block_sz) { - consumed = block_sz - buf_off; - memcpy(buf + buf_off, inbuf, consumed); - inbuf += consumed; - size -= consumed; + int write(const void *in, size_t size) override { + int ret = 0; + auto inbuf = static_cast(in); + if (!init) { + // Skip magic + inbuf += 4; + size -= 4; + init = true; + } + for (int consumed; size != 0;) { + if (block_sz == 0) { + if (buf_off + size >= sizeof(block_sz)) { + consumed = sizeof(block_sz) - buf_off; + memcpy(buf + buf_off, inbuf, consumed); + memcpy(&block_sz, buf, sizeof(block_sz)); + buf_off = 0; + } else { + consumed = size; + memcpy(buf + buf_off, inbuf, size); + } + inbuf += consumed; + size -= consumed; + } else if (buf_off + size >= block_sz) { + consumed = block_sz - buf_off; + memcpy(buf + buf_off, inbuf, consumed); + inbuf += consumed; + size -= consumed; - int write = LZ4_decompress_safe(buf, out_buf, block_sz, LZ4_UNCOMPRESSED); - if (write < 0) { - LOGW("LZ4HC decompression failure (%d)\n", write); - return -1; - } - ret += bwrite(out_buf, write); + int write = LZ4_decompress_safe(buf, out_buf, block_sz, LZ4_UNCOMPRESSED); + if (write < 0) { + LOGW("LZ4HC decompression failure (%d)\n", write); + return -1; + } + ret += bwrite(out_buf, write); - // Reset - buf_off = 0; - block_sz = 0; - } else { - // Copy to internal buffer - memcpy(buf + buf_off, inbuf, size); - buf_off += size; - break; - } - } - return ret; - } + // Reset + buf_off = 0; + block_sz = 0; + } else { + // Copy to internal buffer + memcpy(buf + buf_off, inbuf, size); + buf_off += size; + break; + } + } + return ret; + } private: - char *out_buf; - char *buf; - bool init; - unsigned block_sz; - int buf_off; + char *out_buf; + char *buf; + bool init; + unsigned block_sz; + int buf_off; }; class LZ4_encoder : public cpr_stream { public: - explicit LZ4_encoder(stream_ptr &&base, bool lg) - : cpr_stream(std::move(base)), outbuf(new char[LZ4_COMPRESSED]), - buf(new char[LZ4_UNCOMPRESSED]), init(false), lg(lg), buf_off(0), in_total(0) {} + explicit LZ4_encoder(stream_ptr &&base, bool lg) + : cpr_stream(std::move(base)), outbuf(new char[LZ4_COMPRESSED]), + buf(new char[LZ4_UNCOMPRESSED]), init(false), lg(lg), buf_off(0), in_total(0) {} - int write(const void *in, size_t size) override { - int ret = 0; - if (!init) { - ret += bwrite("\x02\x21\x4c\x18", 4); - init = true; - } - if (size == 0) - return 0; - in_total += size; - const char *inbuf = (const char *) in; - size_t consumed; - do { - if (buf_off + size >= LZ4_UNCOMPRESSED) { - consumed = LZ4_UNCOMPRESSED - buf_off; - memcpy(buf + buf_off, inbuf, consumed); - inbuf += consumed; - size -= consumed; - buf_off = LZ4_UNCOMPRESSED; + int write(const void *in, size_t size) override { + int ret = 0; + if (!init) { + ret += bwrite("\x02\x21\x4c\x18", 4); + init = true; + } + if (size == 0) + return 0; + in_total += size; + const char *inbuf = (const char *) in; + size_t consumed; + do { + if (buf_off + size >= LZ4_UNCOMPRESSED) { + consumed = LZ4_UNCOMPRESSED - buf_off; + memcpy(buf + buf_off, inbuf, consumed); + inbuf += consumed; + size -= consumed; + buf_off = LZ4_UNCOMPRESSED; - if (int written = write_block(); written < 0) - return -1; - else - ret += written; + if (int written = write_block(); written < 0) + return -1; + else + ret += written; - // Reset buffer - buf_off = 0; - } else { - // Copy to internal buffer - memcpy(buf + buf_off, inbuf, size); - buf_off += size; - size = 0; - } - } while (size != 0); - return ret; - } + // Reset buffer + buf_off = 0; + } else { + // Copy to internal buffer + memcpy(buf + buf_off, inbuf, size); + buf_off += size; + size = 0; + } + } while (size != 0); + return ret; + } - ~LZ4_encoder() override { - if (buf_off) - write_block(); - if (lg) - bwrite(&in_total, sizeof(in_total)); - delete[] outbuf; - delete[] buf; - } + ~LZ4_encoder() override { + if (buf_off) + write_block(); + if (lg) + bwrite(&in_total, sizeof(in_total)); + delete[] outbuf; + delete[] buf; + } private: - char *outbuf; - char *buf; - bool init; - bool lg; - int buf_off; - unsigned in_total; + char *outbuf; + char *buf; + bool init; + bool lg; + int buf_off; + unsigned in_total; - int write_block() { - int written = LZ4_compress_HC(buf, outbuf, buf_off, LZ4_COMPRESSED, LZ4HC_CLEVEL_MAX); - if (written == 0) { - LOGW("LZ4HC compression failure\n"); - return -1; - } - bwrite(&written, sizeof(written)); - bwrite(outbuf, written); - return written + sizeof(written); - } + int write_block() { + int written = LZ4_compress_HC(buf, outbuf, buf_off, LZ4_COMPRESSED, LZ4HC_CLEVEL_MAX); + if (written == 0) { + LOGW("LZ4HC compression failure\n"); + return -1; + } + bwrite(&written, sizeof(written)); + bwrite(outbuf, written); + return written + sizeof(written); + } }; stream_ptr get_encoder(format_t type, stream_ptr &&base) { - switch (type) { - case XZ: - return make_unique(std::move(base)); - case LZMA: - return make_unique(std::move(base)); - case BZIP2: - return make_unique(std::move(base)); - case LZ4: - return make_unique(std::move(base)); - case LZ4_LEGACY: - return make_unique(std::move(base), false); - case LZ4_LG: - return make_unique(std::move(base), true); - case GZIP: - default: - return make_unique(std::move(base)); - } + switch (type) { + case XZ: + return make_unique(std::move(base)); + case LZMA: + return make_unique(std::move(base)); + case BZIP2: + return make_unique(std::move(base)); + case LZ4: + return make_unique(std::move(base)); + case LZ4_LEGACY: + return make_unique(std::move(base), false); + case LZ4_LG: + return make_unique(std::move(base), true); + case GZIP: + default: + return make_unique(std::move(base)); + } } stream_ptr get_decoder(format_t type, stream_ptr &&base) { - switch (type) { - case XZ: - case LZMA: - return make_unique(std::move(base)); - case BZIP2: - return make_unique(std::move(base)); - case LZ4: - return make_unique(std::move(base)); - case LZ4_LEGACY: - return make_unique(std::move(base)); - case GZIP: - default: - return make_unique(std::move(base)); - } + switch (type) { + case XZ: + case LZMA: + return make_unique(std::move(base)); + case BZIP2: + return make_unique(std::move(base)); + case LZ4: + return make_unique(std::move(base)); + case LZ4_LEGACY: + return make_unique(std::move(base)); + case GZIP: + default: + return make_unique(std::move(base)); + } } void decompress(char *infile, const char *outfile) { - bool in_std = infile == "-"sv; - bool rm_in = false; + bool in_std = infile == "-"sv; + bool rm_in = false; - FILE *in_fp = in_std ? stdin : xfopen(infile, "re"); - stream_ptr strm; + FILE *in_fp = in_std ? stdin : xfopen(infile, "re"); + stream_ptr strm; - char buf[4096]; - size_t len; - while ((len = fread(buf, 1, sizeof(buf), in_fp))) { - if (!strm) { - format_t type = check_fmt(buf, len); + char buf[4096]; + size_t len; + while ((len = fread(buf, 1, sizeof(buf), in_fp))) { + if (!strm) { + format_t type = check_fmt(buf, len); - fprintf(stderr, "Detected format: [%s]\n", fmt2name[type]); + fprintf(stderr, "Detected format: [%s]\n", fmt2name[type]); - if (!COMPRESSED(type)) - LOGE("Input file is not a supported compressed type!\n"); + if (!COMPRESSED(type)) + LOGE("Input file is not a supported compressed type!\n"); - /* If user does not provide outfile, infile has to be either - * .[ext], or '-'. Outfile will be either or '-'. - * If the input does not have proper format, abort */ + /* If user does not provide outfile, infile has to be either + * .[ext], or '-'. Outfile will be either or '-'. + * If the input does not have proper format, abort */ - char *ext = nullptr; - if (outfile == nullptr) { - outfile = infile; - if (!in_std) { - ext = strrchr(infile, '.'); - if (ext == nullptr || strcmp(ext, fmt2ext[type]) != 0) - LOGE("Input file is not a supported type!\n"); + char *ext = nullptr; + if (outfile == nullptr) { + outfile = infile; + if (!in_std) { + ext = strrchr(infile, '.'); + if (ext == nullptr || strcmp(ext, fmt2ext[type]) != 0) + LOGE("Input file is not a supported type!\n"); - // Strip out extension and remove input - *ext = '\0'; - rm_in = true; - fprintf(stderr, "Decompressing to [%s]\n", outfile); - } - } + // Strip out extension and remove input + *ext = '\0'; + rm_in = true; + fprintf(stderr, "Decompressing to [%s]\n", outfile); + } + } - FILE *out_fp = outfile == "-"sv ? stdout : xfopen(outfile, "we"); - strm = get_decoder(type, make_unique(out_fp)); - if (ext) *ext = '.'; - } - if (strm->write(buf, len) < 0) - LOGE("Decompression error!\n"); - } + FILE *out_fp = outfile == "-"sv ? stdout : xfopen(outfile, "we"); + strm = get_decoder(type, make_unique(out_fp)); + if (ext) *ext = '.'; + } + if (strm->write(buf, len) < 0) + LOGE("Decompression error!\n"); + } - strm.reset(nullptr); - fclose(in_fp); + strm.reset(nullptr); + fclose(in_fp); - if (rm_in) - unlink(infile); + if (rm_in) + unlink(infile); } void compress(const char *method, const char *infile, const char *outfile) { - auto it = name2fmt.find(method); - if (it == name2fmt.end()) - LOGE("Unknown compression method: [%s]\n", method); + auto it = name2fmt.find(method); + if (it == name2fmt.end()) + LOGE("Unknown compression method: [%s]\n", method); - bool in_std = infile == "-"sv; - bool rm_in = false; + bool in_std = infile == "-"sv; + bool rm_in = false; - FILE *in_fp = in_std ? stdin : xfopen(infile, "re"); - FILE *out_fp; + FILE *in_fp = in_std ? stdin : xfopen(infile, "re"); + FILE *out_fp; - if (outfile == nullptr) { - if (in_std) { - out_fp = stdout; - } else { - /* If user does not provide outfile and infile is not - * STDIN, output to .[ext] */ - string tmp(infile); - tmp += fmt2ext[it->second]; - out_fp = xfopen(tmp.data(), "we"); - fprintf(stderr, "Compressing to [%s]\n", tmp.data()); - rm_in = true; - } - } else { - out_fp = outfile == "-"sv ? stdout : xfopen(outfile, "we"); - } + if (outfile == nullptr) { + if (in_std) { + out_fp = stdout; + } else { + /* If user does not provide outfile and infile is not + * STDIN, output to .[ext] */ + string tmp(infile); + tmp += fmt2ext[it->second]; + out_fp = xfopen(tmp.data(), "we"); + fprintf(stderr, "Compressing to [%s]\n", tmp.data()); + rm_in = true; + } + } else { + out_fp = outfile == "-"sv ? stdout : xfopen(outfile, "we"); + } - auto strm = get_encoder(it->second, make_unique(out_fp)); + auto strm = get_encoder(it->second, make_unique(out_fp)); - char buf[4096]; - size_t len; - while ((len = fread(buf, 1, sizeof(buf), in_fp))) { - if (strm->write(buf, len) < 0) - LOGE("Compression error!\n"); - }; + char buf[4096]; + size_t len; + while ((len = fread(buf, 1, sizeof(buf), in_fp))) { + if (strm->write(buf, len) < 0) + LOGE("Compression error!\n"); + }; - strm.reset(nullptr); - fclose(in_fp); + strm.reset(nullptr); + fclose(in_fp); - if (rm_in) - unlink(infile); + if (rm_in) + unlink(infile); } diff --git a/native/jni/magiskboot/dtb.cpp b/native/jni/magiskboot/dtb.cpp index a4b0c99f4..88eee5549 100644 --- a/native/jni/magiskboot/dtb.cpp +++ b/native/jni/magiskboot/dtb.cpp @@ -18,437 +18,437 @@ constexpr int MAX_DEPTH = 32; static bitset depth_set; static void pretty_node(int depth) { - if (depth == 0) - return; + if (depth == 0) + return; - for (int i = 0; i < depth - 1; ++i) - printf(depth_set[i] ? "│ " : " "); + for (int i = 0; i < depth - 1; ++i) + printf(depth_set[i] ? "│ " : " "); - printf(depth_set[depth - 1] ? "├── " : "└── "); + printf(depth_set[depth - 1] ? "├── " : "└── "); } static void pretty_prop(int depth) { - for (int i = 0; i < depth; ++i) - printf(depth_set[i] ? "│ " : " "); + for (int i = 0; i < depth; ++i) + printf(depth_set[i] ? "│ " : " "); - printf(depth_set[depth] ? "│ " : " "); + printf(depth_set[depth] ? "│ " : " "); } static void print_node(const void *fdt, int node = 0, int depth = 0) { - // Print node itself - pretty_node(depth); - printf("#%d: %s\n", node, fdt_get_name(fdt, node, nullptr)); + // Print node itself + pretty_node(depth); + printf("#%d: %s\n", node, fdt_get_name(fdt, node, nullptr)); - // Print properties - depth_set[depth] = fdt_first_subnode(fdt, node) >= 0; - int prop; - fdt_for_each_property_offset(prop, fdt, node) { - pretty_prop(depth); - int size; - const char *name; - auto value = static_cast(fdt_getprop_by_offset(fdt, prop, &name, &size)); + // Print properties + depth_set[depth] = fdt_first_subnode(fdt, node) >= 0; + int prop; + fdt_for_each_property_offset(prop, fdt, node) { + pretty_prop(depth); + int size; + const char *name; + auto value = static_cast(fdt_getprop_by_offset(fdt, prop, &name, &size)); - bool is_str = !(size > 1 && value[0] == 0); - if (is_str) { - // Scan through value to see if printable - for (int i = 0; i < size; ++i) { - char c = value[i]; - if (i == size - 1) { - // Make sure null terminate - is_str = c == '\0'; - } else if ((c > 0 && c < 32) || c >= 127) { - is_str = false; - break; - } - } - } + bool is_str = !(size > 1 && value[0] == 0); + if (is_str) { + // Scan through value to see if printable + for (int i = 0; i < size; ++i) { + char c = value[i]; + if (i == size - 1) { + // Make sure null terminate + is_str = c == '\0'; + } else if ((c > 0 && c < 32) || c >= 127) { + is_str = false; + break; + } + } + } - if (is_str) { - printf("[%s]: [%s]\n", name, value); - } else { - printf("[%s]: (%d)\n", name, size); - } - } + if (is_str) { + printf("[%s]: [%s]\n", name, value); + } else { + printf("[%s]: (%d)\n", name, size); + } + } - // Recursive - if (depth_set[depth]) { - int child; - int prev = -1; - fdt_for_each_subnode(child, fdt, node) { - if (prev >= 0) - print_node(fdt, prev, depth + 1); - prev = child; - } - depth_set[depth] = false; - print_node(fdt, prev, depth + 1); - } + // Recursive + if (depth_set[depth]) { + int child; + int prev = -1; + fdt_for_each_subnode(child, fdt, node) { + if (prev >= 0) + print_node(fdt, prev, depth + 1); + prev = child; + } + depth_set[depth] = false; + print_node(fdt, prev, depth + 1); + } } static int find_fstab(const void *fdt, int node = 0) { - if (fdt_get_name(fdt, node, nullptr) == "fstab"sv) - return node; - int child; - fdt_for_each_subnode(child, fdt, node) { - int fstab = find_fstab(fdt, child); - if (fstab >= 0) - return fstab; - } - return -1; + if (fdt_get_name(fdt, node, nullptr) == "fstab"sv) + return node; + int child; + fdt_for_each_subnode(child, fdt, node) { + int fstab = find_fstab(fdt, child); + if (fstab >= 0) + return fstab; + } + return -1; } static void dtb_print(const char *file, bool fstab) { - size_t size; - uint8_t *dtb; - fprintf(stderr, "Loading dtbs from [%s]\n", file); - mmap_ro(file, dtb, size); - // Loop through all the dtbs - int dtb_num = 0; - for (int i = 0; i < size; ++i) { - if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) { - auto fdt = dtb + i; - if (fstab) { - int node = find_fstab(fdt); - if (node >= 0) { - fprintf(stderr, "Found fstab in dtb.%04d\n", dtb_num); - print_node(fdt, node); - } - } else { - fprintf(stderr, "Printing dtb.%04d\n", dtb_num); - print_node(fdt); - } - ++dtb_num; - i += fdt_totalsize(fdt) - 1; - } - } - fprintf(stderr, "\n"); - munmap(dtb, size); + size_t size; + uint8_t *dtb; + fprintf(stderr, "Loading dtbs from [%s]\n", file); + mmap_ro(file, dtb, size); + // Loop through all the dtbs + int dtb_num = 0; + for (int i = 0; i < size; ++i) { + if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) { + auto fdt = dtb + i; + if (fstab) { + int node = find_fstab(fdt); + if (node >= 0) { + fprintf(stderr, "Found fstab in dtb.%04d\n", dtb_num); + print_node(fdt, node); + } + } else { + fprintf(stderr, "Printing dtb.%04d\n", dtb_num); + print_node(fdt); + } + ++dtb_num; + i += fdt_totalsize(fdt) - 1; + } + } + fprintf(stderr, "\n"); + munmap(dtb, size); } static bool dtb_patch(const char *file) { - bool keepverity = check_env("KEEPVERITY"); - bool patched = false; - size_t size; - uint8_t *dtb; - fprintf(stderr, "Loading dtbs from [%s]\n", file); - mmap_rw(file, dtb, size); - // Loop through all the dtbs - int dtb_num = 0; - for (int i = 0; i < size; ++i) { - if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) { - auto fdt = dtb + i; - fprintf(stderr, "Loading dtb.%04d\n", dtb_num); - if (int fstab = find_fstab(fdt); fstab >= 0) { - int node; - fdt_for_each_subnode(node, fdt, fstab) { - const char *name = fdt_get_name(fdt, node, nullptr); - fprintf(stderr, "Found fstab entry [%s]\n", name); - if (!keepverity) { - int len; - auto value = fdt_getprop(fdt, node, "fsmgr_flags", &len); - patched |= patch_verity(const_cast(value), len) != len; - } - } - } - ++dtb_num; - i += fdt_totalsize(fdt) - 1; - } - } - fprintf(stderr, "\n"); - munmap(dtb, size); - return patched; + bool keepverity = check_env("KEEPVERITY"); + bool patched = false; + size_t size; + uint8_t *dtb; + fprintf(stderr, "Loading dtbs from [%s]\n", file); + mmap_rw(file, dtb, size); + // Loop through all the dtbs + int dtb_num = 0; + for (int i = 0; i < size; ++i) { + if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) { + auto fdt = dtb + i; + fprintf(stderr, "Loading dtb.%04d\n", dtb_num); + if (int fstab = find_fstab(fdt); fstab >= 0) { + int node; + fdt_for_each_subnode(node, fdt, fstab) { + const char *name = fdt_get_name(fdt, node, nullptr); + fprintf(stderr, "Found fstab entry [%s]\n", name); + if (!keepverity) { + int len; + auto value = fdt_getprop(fdt, node, "fsmgr_flags", &len); + patched |= patch_verity(const_cast(value), len) != len; + } + } + } + ++dtb_num; + i += fdt_totalsize(fdt) - 1; + } + } + fprintf(stderr, "\n"); + munmap(dtb, size); + return patched; } int dtb_commands(int argc, char *argv[]) { - char *dtb = argv[0]; - ++argv; - --argc; + char *dtb = argv[0]; + ++argv; + --argc; - if (argv[0] == "print"sv) { - dtb_print(dtb, argc > 1 && argv[1] == "-f"sv); - return 0; - } else if (argv[0] == "patch"sv) { - if (!dtb_patch(dtb)) - exit(1); - return 0; - } else { - return 1; - } + if (argv[0] == "print"sv) { + dtb_print(dtb, argc > 1 && argv[1] == "-f"sv); + return 0; + } else if (argv[0] == "patch"sv) { + if (!dtb_patch(dtb)) + exit(1); + return 0; + } else { + return 1; + } } namespace { - // Unused, but keep these precious code as they took TONs of effort to write + // Unused, but keep these precious code as they took TONs of effort to write - struct fdt_blob { - void *fdt; - uint32_t offset; - uint32_t len; - }; + struct fdt_blob { + void *fdt; + uint32_t offset; + uint32_t len; + }; - template - class fdt_map_iter { - public: - typedef decltype(std::declval().fdt) value_type; - typedef value_type* pointer; - typedef value_type& reference; + template + class fdt_map_iter { + public: + typedef decltype(std::declval().fdt) value_type; + typedef value_type* pointer; + typedef value_type& reference; - explicit fdt_map_iter(Iter j) : i(j) {} - fdt_map_iter& operator++() { ++i; return *this; } - fdt_map_iter operator++(int) { auto tmp = *this; ++(*this); return tmp; } - fdt_map_iter& operator--() { --i; return *this; } - fdt_map_iter operator--(int) { auto tmp = *this; --(*this); return tmp; } - bool operator==(fdt_map_iter j) const { return i == j.i; } - bool operator!=(fdt_map_iter j) const { return !(*this == j); } - reference operator*() { return i->second.fdt; } - pointer operator->() { return &i->second.fdt; } - private: - Iter i; - }; + explicit fdt_map_iter(Iter j) : i(j) {} + fdt_map_iter& operator++() { ++i; return *this; } + fdt_map_iter operator++(int) { auto tmp = *this; ++(*this); return tmp; } + fdt_map_iter& operator--() { --i; return *this; } + fdt_map_iter operator--(int) { auto tmp = *this; --(*this); return tmp; } + bool operator==(fdt_map_iter j) const { return i == j.i; } + bool operator!=(fdt_map_iter j) const { return !(*this == j); } + reference operator*() { return i->second.fdt; } + pointer operator->() { return &i->second.fdt; } + private: + Iter i; + }; - template - inline fdt_map_iter make_iter(Iter j) { return fdt_map_iter(j); } + template + inline fdt_map_iter make_iter(Iter j) { return fdt_map_iter(j); } - template - static bool fdt_patch(Iter first, Iter last) { - bool keepverity = check_env("KEEPVERITY"); - bool redirect = check_env("TWOSTAGEINIT"); - bool modified = false; + template + static bool fdt_patch(Iter first, Iter last) { + bool keepverity = check_env("KEEPVERITY"); + bool redirect = check_env("TWOSTAGEINIT"); + bool modified = false; - int idx = 0; - for (auto it = first; it != last; ++it) { - ++idx; - auto fdt = *it; - int fstab = find_fstab(fdt); - if (fstab < 0) - continue; - fprintf(stderr, "Found fstab in dtb.%04d\n", idx - 1); - int block; - fdt_for_each_subnode(block, fdt, fstab) { - const char *name = fdt_get_name(fdt, block, nullptr); - fprintf(stderr, "Found entry [%s] in fstab\n", name); - if (!keepverity) { - int size; - auto value = fdt_getprop(fdt, block, "fsmgr_flags", &size); - char *copy = static_cast(memcpy(malloc(size), value, size)); - if (patch_verity(copy, size) != size) { - modified = true; - fdt_setprop_string(fdt, block, "fsmgr_flags", copy); - } - free(copy); - } - if (redirect && name == "system"sv) { - modified = true; - fprintf(stderr, "Changing mnt_point to /system_root\n"); - fdt_setprop_string(fdt, block, "mnt_point", "/system_root"); - } - } - } - return modified; - } + int idx = 0; + for (auto it = first; it != last; ++it) { + ++idx; + auto fdt = *it; + int fstab = find_fstab(fdt); + if (fstab < 0) + continue; + fprintf(stderr, "Found fstab in dtb.%04d\n", idx - 1); + int block; + fdt_for_each_subnode(block, fdt, fstab) { + const char *name = fdt_get_name(fdt, block, nullptr); + fprintf(stderr, "Found entry [%s] in fstab\n", name); + if (!keepverity) { + int size; + auto value = fdt_getprop(fdt, block, "fsmgr_flags", &size); + char *copy = static_cast(memcpy(malloc(size), value, size)); + if (patch_verity(copy, size) != size) { + modified = true; + fdt_setprop_string(fdt, block, "fsmgr_flags", copy); + } + free(copy); + } + if (redirect && name == "system"sv) { + modified = true; + fprintf(stderr, "Changing mnt_point to /system_root\n"); + fdt_setprop_string(fdt, block, "mnt_point", "/system_root"); + } + } + } + return modified; + } #define MAX_FDT_GROWTH 256 - template - static int dt_table_patch(const Header *hdr, const char *out) { - map dtb_map; - auto buf = reinterpret_cast(hdr); - auto tables = reinterpret_cast(hdr + 1); + template + static int dt_table_patch(const Header *hdr, const char *out) { + map dtb_map; + auto buf = reinterpret_cast(hdr); + auto tables = reinterpret_cast(hdr + 1); - constexpr bool is_dt_table = std::is_same_v; + constexpr bool is_dt_table = std::is_same_v; - using endian_conv = uint32_t (*)(uint32_t); - endian_conv be_to_le; - endian_conv le_to_be; - if constexpr (is_dt_table) { - be_to_le = fdt32_to_cpu; - le_to_be = cpu_to_fdt32; - } else { - be_to_le = le_to_be = [](uint32_t x) -> auto { return x; }; - } + using endian_conv = uint32_t (*)(uint32_t); + endian_conv be_to_le; + endian_conv le_to_be; + if constexpr (is_dt_table) { + be_to_le = fdt32_to_cpu; + le_to_be = cpu_to_fdt32; + } else { + be_to_le = le_to_be = [](uint32_t x) -> auto { return x; }; + } - // Collect all dtbs - auto num_dtb = be_to_le(hdr->num_dtbs); - for (int i = 0; i < num_dtb; ++i) { - auto offset = be_to_le(tables[i].offset); - if (dtb_map.count(offset) == 0) { - auto blob = buf + offset; - uint32_t size = fdt_totalsize(blob); - auto fdt = xmalloc(size + MAX_FDT_GROWTH); - memcpy(fdt, blob, size); - fdt_open_into(fdt, fdt, size + MAX_FDT_GROWTH); - dtb_map[offset] = { fdt, offset }; - } - } - if (dtb_map.empty()) - return 1; + // Collect all dtbs + auto num_dtb = be_to_le(hdr->num_dtbs); + for (int i = 0; i < num_dtb; ++i) { + auto offset = be_to_le(tables[i].offset); + if (dtb_map.count(offset) == 0) { + auto blob = buf + offset; + uint32_t size = fdt_totalsize(blob); + auto fdt = xmalloc(size + MAX_FDT_GROWTH); + memcpy(fdt, blob, size); + fdt_open_into(fdt, fdt, size + MAX_FDT_GROWTH); + dtb_map[offset] = { fdt, offset }; + } + } + if (dtb_map.empty()) + return 1; - // Patch fdt - if (!fdt_patch(make_iter(dtb_map.begin()), make_iter(dtb_map.end()))) - return 1; + // Patch fdt + if (!fdt_patch(make_iter(dtb_map.begin()), make_iter(dtb_map.end()))) + return 1; - unlink(out); - int fd = xopen(out, O_RDWR | O_CREAT | O_CLOEXEC, 0644); + unlink(out); + int fd = xopen(out, O_RDWR | O_CREAT | O_CLOEXEC, 0644); - uint32_t total_size = 0; + uint32_t total_size = 0; - // Copy headers and tables - total_size += xwrite(fd, buf, dtb_map.begin()->first); + // Copy headers and tables + total_size += xwrite(fd, buf, dtb_map.begin()->first); - // mmap rw to patch table values retroactively - auto mmap_sz = lseek(fd, 0, SEEK_CUR); - auto addr = (uint8_t *) xmmap(nullptr, mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); + // mmap rw to patch table values retroactively + auto mmap_sz = lseek(fd, 0, SEEK_CUR); + auto addr = (uint8_t *) xmmap(nullptr, mmap_sz, PROT_READ | PROT_WRITE, MAP_SHARED, fd, 0); - // Guess alignment using gcd - uint32_t align = 1; - if constexpr (!is_dt_table) { - auto it = dtb_map.begin(); - align = (it++)->first; - for (; it != dtb_map.end(); ++it) - align = binary_gcd(align, it->first); - } + // Guess alignment using gcd + uint32_t align = 1; + if constexpr (!is_dt_table) { + auto it = dtb_map.begin(); + align = (it++)->first; + for (; it != dtb_map.end(); ++it) + align = binary_gcd(align, it->first); + } - // Write dtbs - for (auto &val : dtb_map) { - val.second.offset = lseek(fd, 0, SEEK_CUR); - auto fdt = val.second.fdt; - fdt_pack(fdt); - auto size = fdt_totalsize(fdt); - total_size += xwrite(fd, fdt, size); - val.second.len = do_align(size, align); - write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), align)); - // total_size += align_off(lseek(fd, 0, SEEK_CUR), align); /* Not needed */ - free(fdt); - } + // Write dtbs + for (auto &val : dtb_map) { + val.second.offset = lseek(fd, 0, SEEK_CUR); + auto fdt = val.second.fdt; + fdt_pack(fdt); + auto size = fdt_totalsize(fdt); + total_size += xwrite(fd, fdt, size); + val.second.len = do_align(size, align); + write_zero(fd, align_off(lseek(fd, 0, SEEK_CUR), align)); + // total_size += align_off(lseek(fd, 0, SEEK_CUR), align); /* Not needed */ + free(fdt); + } - // Patch headers - if constexpr (is_dt_table) { - auto hdr_rw = reinterpret_cast
(addr); - hdr_rw->total_size = le_to_be(total_size); - } - auto tables_rw = reinterpret_cast(addr + sizeof(Header)); - for (int i = 0; i < num_dtb; ++i) { - auto &blob = dtb_map[be_to_le(tables_rw[i].offset)]; - tables_rw[i].offset = le_to_be(blob.offset); - tables_rw[i].len = le_to_be(blob.len); - } + // Patch headers + if constexpr (is_dt_table) { + auto hdr_rw = reinterpret_cast
(addr); + hdr_rw->total_size = le_to_be(total_size); + } + auto tables_rw = reinterpret_cast
(addr + sizeof(Header)); + for (int i = 0; i < num_dtb; ++i) { + auto &blob = dtb_map[be_to_le(tables_rw[i].offset)]; + tables_rw[i].offset = le_to_be(blob.offset); + tables_rw[i].len = le_to_be(blob.len); + } - munmap(addr, mmap_sz); - close(fd); + munmap(addr, mmap_sz); + close(fd); - return 0; - } + return 0; + } - static int blob_patch(uint8_t *dtb, size_t dtb_sz, const char *out) { - vector fdt_list; - vector padding_list; - for (int i = 0; i < dtb_sz; ++i) { - if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) { - auto len = fdt_totalsize(dtb + i); - auto fdt = static_cast(xmalloc(len + MAX_FDT_GROWTH)); - memcpy(fdt, dtb + i, len); - fdt_pack(fdt); - uint32_t padding = len - fdt_totalsize(fdt); - padding_list.push_back(padding); - fdt_open_into(fdt, fdt, len + MAX_FDT_GROWTH); - fdt_list.push_back(fdt); - i += len - 1; - } - } + static int blob_patch(uint8_t *dtb, size_t dtb_sz, const char *out) { + vector fdt_list; + vector padding_list; + for (int i = 0; i < dtb_sz; ++i) { + if (memcmp(dtb + i, FDT_MAGIC_STR, 4) == 0) { + auto len = fdt_totalsize(dtb + i); + auto fdt = static_cast(xmalloc(len + MAX_FDT_GROWTH)); + memcpy(fdt, dtb + i, len); + fdt_pack(fdt); + uint32_t padding = len - fdt_totalsize(fdt); + padding_list.push_back(padding); + fdt_open_into(fdt, fdt, len + MAX_FDT_GROWTH); + fdt_list.push_back(fdt); + i += len - 1; + } + } - if (!fdt_patch(fdt_list.begin(), fdt_list.end())) - return 1; + if (!fdt_patch(fdt_list.begin(), fdt_list.end())) + return 1; - unlink(out); - int fd = xopen(out, O_WRONLY | O_CREAT | O_CLOEXEC, 0644); + unlink(out); + int fd = xopen(out, O_WRONLY | O_CREAT | O_CLOEXEC, 0644); - for (int i = 0; i < fdt_list.size(); ++i) { - auto fdt = fdt_list[i]; - fdt_pack(fdt); - // Only add padding back if it is anything meaningful - if (padding_list[i] > 4) { - auto len = fdt_totalsize(fdt); - fdt_set_totalsize(fdt, len + padding_list[i]); - } - xwrite(fd, fdt, fdt_totalsize(fdt)); - free(fdt); - } - close(fd); + for (int i = 0; i < fdt_list.size(); ++i) { + auto fdt = fdt_list[i]; + fdt_pack(fdt); + // Only add padding back if it is anything meaningful + if (padding_list[i] > 4) { + auto len = fdt_totalsize(fdt); + fdt_set_totalsize(fdt, len + padding_list[i]); + } + xwrite(fd, fdt, fdt_totalsize(fdt)); + free(fdt); + } + close(fd); - return 0; - } + return 0; + } #define MATCH(s) (memcmp(dtb, s, sizeof(s) - 1) == 0) - [[maybe_unused]] static int dtb_patch(const char *in, const char *out) { - if (!out) - out = in; - size_t dtb_sz ; - uint8_t *dtb; - fprintf(stderr, "Loading dtbs from [%s]\n", in); - mmap_ro(in, dtb, dtb_sz); - run_finally f([&]{ munmap(dtb, dtb_sz); }); + [[maybe_unused]] static int dtb_patch(const char *in, const char *out) { + if (!out) + out = in; + size_t dtb_sz ; + uint8_t *dtb; + fprintf(stderr, "Loading dtbs from [%s]\n", in); + mmap_ro(in, dtb, dtb_sz); + run_finally f([&]{ munmap(dtb, dtb_sz); }); - if (MATCH(QCDT_MAGIC)) { - auto hdr = reinterpret_cast(dtb); - switch (hdr->version) { - case 1: - fprintf(stderr, "QCDT v1\n"); - return dt_table_patch(hdr, out); - case 2: - fprintf(stderr, "QCDT v2\n"); - return dt_table_patch(hdr, out); - case 3: - fprintf(stderr, "QCDT v3\n"); - return dt_table_patch(hdr, out); - default: - return 1; - } - } else if (MATCH(DTBH_MAGIC)) { - auto hdr = reinterpret_cast(dtb); - switch (hdr->version) { - case 2: - fprintf(stderr, "DTBH v2\n"); - return dt_table_patch(hdr, out); - default: - return 1; - } - } else if (MATCH(PXADT_MAGIC)) { - auto hdr = reinterpret_cast(dtb); - switch (hdr->version) { - case 1: - fprintf(stderr, "PXA-DT v1\n"); - return dt_table_patch(hdr, out); - default: - return 1; - } - } else if (MATCH(PXA19xx_MAGIC)) { - auto hdr = reinterpret_cast(dtb); - switch (hdr->version) { - case 1: - fprintf(stderr, "PXA-19xx v1\n"); - return dt_table_patch(hdr, out); - default: - return 1; - } - } else if (MATCH(SPRD_MAGIC)) { - auto hdr = reinterpret_cast(dtb); - switch (hdr->version) { - case 1: - fprintf(stderr, "SPRD v1\n"); - return dt_table_patch(hdr, out); - default: - return 1; - } - } else if (MATCH(DT_TABLE_MAGIC)) { - auto hdr = reinterpret_cast(dtb); - switch (hdr->version) { - case 0: - fprintf(stderr, "DT_TABLE v0\n"); - return dt_table_patch(hdr, out); - default: - return 1; - } - } else { - return blob_patch(dtb, dtb_sz, out); - } - } + if (MATCH(QCDT_MAGIC)) { + auto hdr = reinterpret_cast(dtb); + switch (hdr->version) { + case 1: + fprintf(stderr, "QCDT v1\n"); + return dt_table_patch(hdr, out); + case 2: + fprintf(stderr, "QCDT v2\n"); + return dt_table_patch(hdr, out); + case 3: + fprintf(stderr, "QCDT v3\n"); + return dt_table_patch(hdr, out); + default: + return 1; + } + } else if (MATCH(DTBH_MAGIC)) { + auto hdr = reinterpret_cast(dtb); + switch (hdr->version) { + case 2: + fprintf(stderr, "DTBH v2\n"); + return dt_table_patch(hdr, out); + default: + return 1; + } + } else if (MATCH(PXADT_MAGIC)) { + auto hdr = reinterpret_cast(dtb); + switch (hdr->version) { + case 1: + fprintf(stderr, "PXA-DT v1\n"); + return dt_table_patch(hdr, out); + default: + return 1; + } + } else if (MATCH(PXA19xx_MAGIC)) { + auto hdr = reinterpret_cast(dtb); + switch (hdr->version) { + case 1: + fprintf(stderr, "PXA-19xx v1\n"); + return dt_table_patch(hdr, out); + default: + return 1; + } + } else if (MATCH(SPRD_MAGIC)) { + auto hdr = reinterpret_cast(dtb); + switch (hdr->version) { + case 1: + fprintf(stderr, "SPRD v1\n"); + return dt_table_patch(hdr, out); + default: + return 1; + } + } else if (MATCH(DT_TABLE_MAGIC)) { + auto hdr = reinterpret_cast(dtb); + switch (hdr->version) { + case 0: + fprintf(stderr, "DT_TABLE v0\n"); + return dt_table_patch(hdr, out); + default: + return 1; + } + } else { + return blob_patch(dtb, dtb_sz, out); + } + } } diff --git a/native/jni/magiskboot/dtb.hpp b/native/jni/magiskboot/dtb.hpp index a303b5b3d..ce2b0d71e 100644 --- a/native/jni/magiskboot/dtb.hpp +++ b/native/jni/magiskboot/dtb.hpp @@ -11,94 +11,94 @@ #define SPRD_MAGIC "SPRD" struct qcdt_hdr { - char magic[4]; /* "QCDT" */ - uint32_t version; /* QCDT version */ - uint32_t num_dtbs; /* Number of DTBs */ + char magic[4]; /* "QCDT" */ + uint32_t version; /* QCDT version */ + uint32_t num_dtbs; /* Number of DTBs */ } __attribute__((packed)); struct qctable_v1 { - uint32_t cpu_info[3]; /* Some CPU info */ - uint32_t offset; /* DTB offset in QCDT */ - uint32_t len; /* DTB size */ + uint32_t cpu_info[3]; /* Some CPU info */ + uint32_t offset; /* DTB offset in QCDT */ + uint32_t len; /* DTB size */ } __attribute__((packed)); struct qctable_v2 { - uint32_t cpu_info[4]; /* Some CPU info */ - uint32_t offset; /* DTB offset in QCDT */ - uint32_t len; /* DTB size */ + uint32_t cpu_info[4]; /* Some CPU info */ + uint32_t offset; /* DTB offset in QCDT */ + uint32_t len; /* DTB size */ } __attribute__((packed)); struct qctable_v3 { - uint32_t cpu_info[8]; /* Some CPU info */ - uint32_t offset; /* DTB offset in QCDT */ - uint32_t len; /* DTB size */ + uint32_t cpu_info[8]; /* Some CPU info */ + uint32_t offset; /* DTB offset in QCDT */ + uint32_t len; /* DTB size */ } __attribute__((packed)); struct dtbh_hdr { - char magic[4]; /* "DTBH" */ - uint32_t version; /* DTBH version */ - uint32_t num_dtbs; /* Number of DTBs */ + char magic[4]; /* "DTBH" */ + uint32_t version; /* DTBH version */ + uint32_t num_dtbs; /* Number of DTBs */ } __attribute__((packed)); struct bhtable_v2 { - uint32_t cpu_info[5]; /* Some CPU info */ - uint32_t offset; /* DTB offset in DTBH */ - uint32_t len; /* DTB size */ - uint32_t space; /* 0x00000020 */ + uint32_t cpu_info[5]; /* Some CPU info */ + uint32_t offset; /* DTB offset in DTBH */ + uint32_t len; /* DTB size */ + uint32_t space; /* 0x00000020 */ } __attribute__((packed)); struct pxadt_hdr { - char magic[6]; /* "PXA-DT" */ - uint32_t version; /* PXA-* version */ - uint32_t num_dtbs; /* Number of DTBs */ + char magic[6]; /* "PXA-DT" */ + uint32_t version; /* PXA-* version */ + uint32_t num_dtbs; /* Number of DTBs */ } __attribute__((packed)); struct pxa19xx_hdr { - char magic[8]; /* "PXA-19xx" */ - uint32_t version; /* PXA-* version */ - uint32_t num_dtbs; /* Number of DTBs */ + char magic[8]; /* "PXA-19xx" */ + uint32_t version; /* PXA-* version */ + uint32_t num_dtbs; /* Number of DTBs */ } __attribute__((packed)); struct pxatable_v1 { - uint32_t cpu_info[2]; /* Some CPU info */ - uint32_t offset; /* DTB offset in PXA-* */ - uint32_t len; /* DTB size */ + uint32_t cpu_info[2]; /* Some CPU info */ + uint32_t offset; /* DTB offset in PXA-* */ + uint32_t len; /* DTB size */ } __attribute__((packed)); struct sprd_hdr { - char magic[4]; /* "SPRD" */ - uint32_t version; /* SPRD version */ - uint32_t num_dtbs; /* Number of DTBs */ + char magic[4]; /* "SPRD" */ + uint32_t version; /* SPRD version */ + uint32_t num_dtbs; /* Number of DTBs */ } __attribute__((packed)); struct sprdtable_v1 { - uint32_t cpu_info[3]; /* Some CPU info */ - uint32_t offset; /* DTB offset in SPRD */ - uint32_t len; /* DTB size */ + uint32_t cpu_info[3]; /* Some CPU info */ + uint32_t offset; /* DTB offset in SPRD */ + uint32_t len; /* DTB size */ } __attribute__((packed)); /* AOSP DTB/DTBO partition layout */ struct dt_table_header { - uint32_t magic; /* DT_TABLE_MAGIC */ - uint32_t total_size; /* includes dt_table_header + all dt_table_entry */ - uint32_t header_size; /* sizeof(dt_table_header) */ + uint32_t magic; /* DT_TABLE_MAGIC */ + uint32_t total_size; /* includes dt_table_header + all dt_table_entry */ + uint32_t header_size; /* sizeof(dt_table_header) */ - uint32_t dt_entry_size; /* sizeof(dt_table_entry) */ - uint32_t num_dtbs; /* number of dt_table_entry */ - uint32_t dt_entries_offset; /* offset to the first dt_table_entry */ + uint32_t dt_entry_size; /* sizeof(dt_table_entry) */ + uint32_t num_dtbs; /* number of dt_table_entry */ + uint32_t dt_entries_offset; /* offset to the first dt_table_entry */ - uint32_t page_size; /* flash page size we assume */ - uint32_t version; /* DTBO image version */ + uint32_t page_size; /* flash page size we assume */ + uint32_t version; /* DTBO image version */ } __attribute__((packed)); struct dt_table_entry { - uint32_t len; /* DTB size */ - uint32_t offset; + uint32_t len; /* DTB size */ + uint32_t offset; - uint32_t id; - uint32_t rev; - uint32_t flags; + uint32_t id; + uint32_t rev; + uint32_t flags; - uint32_t custom[3]; + uint32_t custom[3]; } __attribute__((packed)); diff --git a/native/jni/magiskboot/format.cpp b/native/jni/magiskboot/format.cpp index 44c56cc00..b38414209 100644 --- a/native/jni/magiskboot/format.cpp +++ b/native/jni/magiskboot/format.cpp @@ -8,15 +8,15 @@ Fmt2Ext fmt2ext; class FormatInit { public: - FormatInit() { - name2fmt["gzip"] = GZIP; - name2fmt["xz"] = XZ; - name2fmt["lzma"] = LZMA; - name2fmt["bzip2"] = BZIP2; - name2fmt["lz4"] = LZ4; - name2fmt["lz4_legacy"] = LZ4_LEGACY; - name2fmt["lz4_lg"] = LZ4_LG; - } + FormatInit() { + name2fmt["gzip"] = GZIP; + name2fmt["xz"] = XZ; + name2fmt["lzma"] = LZMA; + name2fmt["bzip2"] = BZIP2; + name2fmt["lz4"] = LZ4; + name2fmt["lz4_legacy"] = LZ4_LEGACY; + name2fmt["lz4_lg"] = LZ4_LG; + } }; static FormatInit init; @@ -24,82 +24,82 @@ static FormatInit init; #define MATCH(s) (len >= (sizeof(s) - 1) && memcmp(buf, s, sizeof(s) - 1) == 0) format_t check_fmt(const void *buf, size_t len) { - if (MATCH(CHROMEOS_MAGIC)) { - return CHROMEOS; - } else if (MATCH(BOOT_MAGIC)) { - return AOSP; - } else if (MATCH(VENDOR_BOOT_MAGIC)) { - return AOSP_VENDOR; - } else if (MATCH(GZIP1_MAGIC) || MATCH(GZIP2_MAGIC)) { - return GZIP; - } else if (MATCH(LZOP_MAGIC)) { - return LZOP; - } else if (MATCH(XZ_MAGIC)) { - return XZ; - } else if (len >= 13 && memcmp(buf, "\x5d\x00\x00", 3) == 0 - && (((char *)buf)[12] == '\xff' || ((char *)buf)[12] == '\x00')) { - return LZMA; - } else if (MATCH(BZIP_MAGIC)) { - return BZIP2; - } else if (MATCH(LZ41_MAGIC) || MATCH(LZ42_MAGIC)) { - return LZ4; - } else if (MATCH(LZ4_LEG_MAGIC)) { - return LZ4_LEGACY; - } else if (MATCH(MTK_MAGIC)) { - return MTK; - } else if (MATCH(DTB_MAGIC)) { - return DTB; - } else if (MATCH(DHTB_MAGIC)) { - return DHTB; - } else if (MATCH(TEGRABLOB_MAGIC)) { - return BLOB; - } else { - return UNKNOWN; - } + if (MATCH(CHROMEOS_MAGIC)) { + return CHROMEOS; + } else if (MATCH(BOOT_MAGIC)) { + return AOSP; + } else if (MATCH(VENDOR_BOOT_MAGIC)) { + return AOSP_VENDOR; + } else if (MATCH(GZIP1_MAGIC) || MATCH(GZIP2_MAGIC)) { + return GZIP; + } else if (MATCH(LZOP_MAGIC)) { + return LZOP; + } else if (MATCH(XZ_MAGIC)) { + return XZ; + } else if (len >= 13 && memcmp(buf, "\x5d\x00\x00", 3) == 0 + && (((char *)buf)[12] == '\xff' || ((char *)buf)[12] == '\x00')) { + return LZMA; + } else if (MATCH(BZIP_MAGIC)) { + return BZIP2; + } else if (MATCH(LZ41_MAGIC) || MATCH(LZ42_MAGIC)) { + return LZ4; + } else if (MATCH(LZ4_LEG_MAGIC)) { + return LZ4_LEGACY; + } else if (MATCH(MTK_MAGIC)) { + return MTK; + } else if (MATCH(DTB_MAGIC)) { + return DTB; + } else if (MATCH(DHTB_MAGIC)) { + return DHTB; + } else if (MATCH(TEGRABLOB_MAGIC)) { + return BLOB; + } else { + return UNKNOWN; + } } const char *Fmt2Name::operator[](format_t fmt) { - switch (fmt) { - case GZIP: - return "gzip"; - case LZOP: - return "lzop"; - case XZ: - return "xz"; - case LZMA: - return "lzma"; - case BZIP2: - return "bzip2"; - case LZ4: - return "lz4"; - case LZ4_LEGACY: - return "lz4_legacy"; - case LZ4_LG: - return "lz4_lg"; - case DTB: - return "dtb"; - default: - return "raw"; - } + switch (fmt) { + case GZIP: + return "gzip"; + case LZOP: + return "lzop"; + case XZ: + return "xz"; + case LZMA: + return "lzma"; + case BZIP2: + return "bzip2"; + case LZ4: + return "lz4"; + case LZ4_LEGACY: + return "lz4_legacy"; + case LZ4_LG: + return "lz4_lg"; + case DTB: + return "dtb"; + default: + return "raw"; + } } const char *Fmt2Ext::operator[](format_t fmt) { - switch (fmt) { - case GZIP: - return ".gz"; - case LZOP: - return ".lzo"; - case XZ: - return ".xz"; - case LZMA: - return ".lzma"; - case BZIP2: - return ".bz2"; - case LZ4: - case LZ4_LEGACY: - case LZ4_LG: - return ".lz4"; - default: - return ""; - } + switch (fmt) { + case GZIP: + return ".gz"; + case LZOP: + return ".lzo"; + case XZ: + return ".xz"; + case LZMA: + return ".lzma"; + case BZIP2: + return ".bz2"; + case LZ4: + case LZ4_LEGACY: + case LZ4_LG: + return ".lz4"; + default: + return ""; + } } diff --git a/native/jni/magiskboot/format.hpp b/native/jni/magiskboot/format.hpp index c35ba7797..3d7c641f1 100644 --- a/native/jni/magiskboot/format.hpp +++ b/native/jni/magiskboot/format.hpp @@ -4,26 +4,26 @@ #include typedef enum { - UNKNOWN, + UNKNOWN, /* Boot formats */ - CHROMEOS, - AOSP, - AOSP_VENDOR, - DHTB, - BLOB, + CHROMEOS, + AOSP, + AOSP_VENDOR, + DHTB, + BLOB, /* Compression formats */ - GZIP, - XZ, - LZMA, - BZIP2, - LZ4, - LZ4_LEGACY, - LZ4_LG, + GZIP, + XZ, + LZMA, + BZIP2, + LZ4, + LZ4_LEGACY, + LZ4_LG, /* Unsupported compression */ - LZOP, + LZOP, /* Misc */ - MTK, - DTB, + MTK, + DTB, } format_t; #define COMPRESSED(fmt) ((fmt) >= GZIP && (fmt) < LZOP) @@ -57,12 +57,12 @@ typedef enum { class Fmt2Name { public: - const char *operator[](format_t fmt); + const char *operator[](format_t fmt); }; class Fmt2Ext { public: - const char *operator[](format_t fmt); + const char *operator[](format_t fmt); }; format_t check_fmt(const void *buf, size_t len); diff --git a/native/jni/magiskboot/hexpatch.cpp b/native/jni/magiskboot/hexpatch.cpp index edcd34f8f..bfd243881 100644 --- a/native/jni/magiskboot/hexpatch.cpp +++ b/native/jni/magiskboot/hexpatch.cpp @@ -8,36 +8,36 @@ #include "magiskboot.hpp" static void hex2byte(uint8_t *hex, uint8_t *str) { - char high, low; - for (int i = 0, length = strlen((char *) hex); i < length; i += 2) { - high = toupper(hex[i]) - '0'; - low = toupper(hex[i + 1]) - '0'; - str[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low); - } + char high, low; + for (int i = 0, length = strlen((char *) hex); i < length; i += 2) { + high = toupper(hex[i]) - '0'; + low = toupper(hex[i + 1]) - '0'; + str[i / 2] = ((high > 9 ? high - 7 : high) << 4) + (low > 9 ? low - 7 : low); + } } int hexpatch(const char *image, const char *from, const char *to) { - int patternsize = strlen(from) / 2, patchsize = strlen(to) / 2; - int patched = 1; - size_t filesize; - uint8_t *file, *pattern, *patch; - mmap_rw(image, file, filesize); - pattern = (uint8_t *) xmalloc(patternsize); - patch = (uint8_t *) xmalloc(patchsize); - hex2byte((uint8_t *) from, pattern); - hex2byte((uint8_t *) to, patch); - for (size_t i = 0; filesize > 0 && i < filesize - patternsize; ++i) { - if (memcmp(file + i, pattern, patternsize) == 0) { - fprintf(stderr, "Patch @ %08X [%s]->[%s]\n", (unsigned) i, from, to); - memset(file + i, 0, patternsize); - memcpy(file + i, patch, patchsize); - i += patternsize - 1; - patched = 0; - } - } - munmap(file, filesize); - free(pattern); - free(patch); + int patternsize = strlen(from) / 2, patchsize = strlen(to) / 2; + int patched = 1; + size_t filesize; + uint8_t *file, *pattern, *patch; + mmap_rw(image, file, filesize); + pattern = (uint8_t *) xmalloc(patternsize); + patch = (uint8_t *) xmalloc(patchsize); + hex2byte((uint8_t *) from, pattern); + hex2byte((uint8_t *) to, patch); + for (size_t i = 0; filesize > 0 && i < filesize - patternsize; ++i) { + if (memcmp(file + i, pattern, patternsize) == 0) { + fprintf(stderr, "Patch @ %08X [%s]->[%s]\n", (unsigned) i, from, to); + memset(file + i, 0, patternsize); + memcpy(file + i, patch, patchsize); + i += patternsize - 1; + patched = 0; + } + } + munmap(file, filesize); + free(pattern); + free(patch); - return patched; + return patched; } diff --git a/native/jni/magiskboot/main.cpp b/native/jni/magiskboot/main.cpp index 1d04fd8fd..f353ac515 100644 --- a/native/jni/magiskboot/main.cpp +++ b/native/jni/magiskboot/main.cpp @@ -13,7 +13,7 @@ using namespace std; static void usage(char *arg0) { - fprintf(stderr, + fprintf(stderr, R"EOF(MagiskBoot - Boot Image Modification Tool Usage: %s [args...] @@ -96,100 +96,100 @@ Supported actions: /[outfile] can be '-' to be STDIN/STDOUT Supported methods: )EOF", arg0); - for (auto &it : name2fmt) - fprintf(stderr, "%s ", it.first.data()); + for (auto &it : name2fmt) + fprintf(stderr, "%s ", it.first.data()); - fprintf(stderr, R"EOF( + fprintf(stderr, R"EOF( decompress [outfile] Detect method and decompress , optionally to [outfile] /[outfile] can be '-' to be STDIN/STDOUT Supported methods: )EOF"); - for (auto &it : name2fmt) - fprintf(stderr, "%s ", it.first.data()); + for (auto &it : name2fmt) + fprintf(stderr, "%s ", it.first.data()); - fprintf(stderr, "\n\n"); - exit(1); + fprintf(stderr, "\n\n"); + exit(1); } int main(int argc, char *argv[]) { - cmdline_logging(); - umask(0); + cmdline_logging(); + umask(0); - if (argc < 2) - usage(argv[0]); + if (argc < 2) + usage(argv[0]); - // Skip '--' for backwards compatibility - string_view action(argv[1]); - if (str_starts(action, "--")) - action = argv[1] + 2; + // Skip '--' for backwards compatibility + string_view action(argv[1]); + if (str_starts(action, "--")) + action = argv[1] + 2; - if (action == "cleanup") { - fprintf(stderr, "Cleaning up...\n"); - unlink(HEADER_FILE); - unlink(KERNEL_FILE); - unlink(RAMDISK_FILE); - unlink(SECOND_FILE); - unlink(KER_DTB_FILE); - unlink(EXTRA_FILE); - unlink(RECV_DTBO_FILE); - unlink(DTB_FILE); - } else if (argc > 2 && action == "sha1") { - uint8_t sha1[SHA_DIGEST_SIZE]; - void *buf; - size_t size; - mmap_ro(argv[2], buf, size); - SHA_hash(buf, size, sha1); - for (uint8_t i : sha1) - printf("%02x", i); - printf("\n"); - munmap(buf, size); - } else if (argc > 2 && action == "split") { - return split_image_dtb(argv[2]); - } else if (argc > 2 && action == "unpack") { - int idx = 2; - bool nodecomp = false; - bool hdr = false; - for (;;) { - if (idx >= argc) - usage(argv[0]); - if (argv[idx][0] != '-') - break; - for (char *flag = &argv[idx][1]; *flag; ++flag) { - if (*flag == 'n') - nodecomp = true; - else if (*flag == 'h') - hdr = true; - else - usage(argv[0]); - } - ++idx; - } - return unpack(argv[idx], nodecomp, hdr); - } else if (argc > 2 && action == "repack") { - if (argv[2] == "-n"sv) { - if (argc == 3) - usage(argv[0]); - repack(argv[3], argv[4] ? argv[4] : NEW_BOOT, true); - } else { - repack(argv[2], argv[3] ? argv[3] : NEW_BOOT); - } - } else if (argc > 2 && action == "decompress") { - decompress(argv[2], argv[3]); - } else if (argc > 2 && str_starts(action, "compress")) { - compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]); - } else if (argc > 4 && action == "hexpatch") { - return hexpatch(argv[2], argv[3], argv[4]); - } else if (argc > 2 && action == "cpio"sv) { - if (cpio_commands(argc - 2, argv + 2)) - usage(argv[0]); - } else if (argc > 3 && action == "dtb") { - if (dtb_commands(argc - 2, argv + 2)) - usage(argv[0]); - } else { - usage(argv[0]); - } + if (action == "cleanup") { + fprintf(stderr, "Cleaning up...\n"); + unlink(HEADER_FILE); + unlink(KERNEL_FILE); + unlink(RAMDISK_FILE); + unlink(SECOND_FILE); + unlink(KER_DTB_FILE); + unlink(EXTRA_FILE); + unlink(RECV_DTBO_FILE); + unlink(DTB_FILE); + } else if (argc > 2 && action == "sha1") { + uint8_t sha1[SHA_DIGEST_SIZE]; + void *buf; + size_t size; + mmap_ro(argv[2], buf, size); + SHA_hash(buf, size, sha1); + for (uint8_t i : sha1) + printf("%02x", i); + printf("\n"); + munmap(buf, size); + } else if (argc > 2 && action == "split") { + return split_image_dtb(argv[2]); + } else if (argc > 2 && action == "unpack") { + int idx = 2; + bool nodecomp = false; + bool hdr = false; + for (;;) { + if (idx >= argc) + usage(argv[0]); + if (argv[idx][0] != '-') + break; + for (char *flag = &argv[idx][1]; *flag; ++flag) { + if (*flag == 'n') + nodecomp = true; + else if (*flag == 'h') + hdr = true; + else + usage(argv[0]); + } + ++idx; + } + return unpack(argv[idx], nodecomp, hdr); + } else if (argc > 2 && action == "repack") { + if (argv[2] == "-n"sv) { + if (argc == 3) + usage(argv[0]); + repack(argv[3], argv[4] ? argv[4] : NEW_BOOT, true); + } else { + repack(argv[2], argv[3] ? argv[3] : NEW_BOOT); + } + } else if (argc > 2 && action == "decompress") { + decompress(argv[2], argv[3]); + } else if (argc > 2 && str_starts(action, "compress")) { + compress(action[8] == '=' ? &action[9] : "gzip", argv[2], argv[3]); + } else if (argc > 4 && action == "hexpatch") { + return hexpatch(argv[2], argv[3], argv[4]); + } else if (argc > 2 && action == "cpio"sv) { + if (cpio_commands(argc - 2, argv + 2)) + usage(argv[0]); + } else if (argc > 3 && action == "dtb") { + if (dtb_commands(argc - 2, argv + 2)) + usage(argv[0]); + } else { + usage(argv[0]); + } - return 0; + return 0; } diff --git a/native/jni/magiskboot/pattern.cpp b/native/jni/magiskboot/pattern.cpp index b62ff62a8..240915fd5 100644 --- a/native/jni/magiskboot/pattern.cpp +++ b/native/jni/magiskboot/pattern.cpp @@ -8,56 +8,56 @@ #define MATCH(p) else if (strncmp(s + skip, p, sizeof(p) - 1) == 0) skip += (sizeof(p) - 1) static int check_verity_pattern(const char *s) { - int skip = s[0] == ','; + int skip = s[0] == ','; - if (0) {} - MATCH("verifyatboot"); - MATCH("verify"); - MATCH("avb_keys"); - MATCH("avb"); - MATCH("support_scfs"); - MATCH("fsverity"); - else return -1; + if (0) {} + MATCH("verifyatboot"); + MATCH("verify"); + MATCH("avb_keys"); + MATCH("avb"); + MATCH("support_scfs"); + MATCH("fsverity"); + else return -1; - if (s[skip] == '=') { - while (s[skip] != '\0' && s[skip] != ' ' && s[skip] != '\n' && s[skip] != ',') - ++skip; - } - return skip; + if (s[skip] == '=') { + while (s[skip] != '\0' && s[skip] != ' ' && s[skip] != '\n' && s[skip] != ',') + ++skip; + } + return skip; } #undef MATCH #define MATCH(p) else if (strncmp(s, p, sizeof(p) - 1) == 0) return (sizeof(p) - 1) static int check_encryption_pattern(const char *s) { - if (0) {} - MATCH("forceencrypt"); - MATCH("forcefdeorfbe"); - MATCH("fileencryption"); - else return -1; + if (0) {} + MATCH("forceencrypt"); + MATCH("forcefdeorfbe"); + MATCH("fileencryption"); + else return -1; } static uint32_t remove_pattern(void *buf, uint32_t size, int(*pattern_skip)(const char *)) { - auto src = static_cast(buf); - int orig_sz = size; - int write = 0; - for (int read = 0; read < orig_sz;) { - if (int skip = pattern_skip(src + read); skip > 0) { - fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read); - size -= skip; - read += skip; - } else { - src[write++] = src[read++]; - } - } - memset(src + write, 0, orig_sz - write); - return size; + auto src = static_cast(buf); + int orig_sz = size; + int write = 0; + for (int read = 0; read < orig_sz;) { + if (int skip = pattern_skip(src + read); skip > 0) { + fprintf(stderr, "Remove pattern [%.*s]\n", skip, src + read); + size -= skip; + read += skip; + } else { + src[write++] = src[read++]; + } + } + memset(src + write, 0, orig_sz - write); + return size; } uint32_t patch_verity(void *buf, uint32_t size) { - return remove_pattern(buf, size, check_verity_pattern); + return remove_pattern(buf, size, check_verity_pattern); } uint32_t patch_encryption(void *buf, uint32_t size) { - return remove_pattern(buf, size, check_encryption_pattern); + return remove_pattern(buf, size, check_encryption_pattern); } diff --git a/native/jni/magiskboot/ramdisk.cpp b/native/jni/magiskboot/ramdisk.cpp index c5576a7ee..bf4dfe47c 100644 --- a/native/jni/magiskboot/ramdisk.cpp +++ b/native/jni/magiskboot/ramdisk.cpp @@ -13,60 +13,60 @@ using namespace std; constexpr char RAMDISK_XZ[] = "ramdisk.cpio.xz"; static const char *UNSUPPORT_LIST[] = - { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", - "boot/sbin/launch_daemonsu.sh" }; + { "sbin/launch_daemonsu.sh", "sbin/su", "init.xposed.rc", + "boot/sbin/launch_daemonsu.sh" }; static const char *MAGISK_LIST[] = - { ".backup/.magisk", "init.magisk.rc", - "overlay/init.magisk.rc" }; + { ".backup/.magisk", "init.magisk.rc", + "overlay/init.magisk.rc" }; class magisk_cpio : public cpio_rw { public: - magisk_cpio() = default; - explicit magisk_cpio(const char *filename) : cpio_rw(filename) {} - void patch(); - int test(); - char *sha1(); - void restore(); - void backup(const char *orig); - void compress(); - void decompress(); + magisk_cpio() = default; + explicit magisk_cpio(const char *filename) : cpio_rw(filename) {} + void patch(); + int test(); + char *sha1(); + void restore(); + void backup(const char *orig); + void compress(); + void decompress(); }; bool check_env(const char *name) { - const char *val = getenv(name); - return val ? strcmp(val, "true") == 0 : false; + const char *val = getenv(name); + return val ? strcmp(val, "true") == 0 : false; } void magisk_cpio::patch() { - bool keepverity = check_env("KEEPVERITY"); - bool keepforceencrypt = check_env("KEEPFORCEENCRYPT"); - fprintf(stderr, "Patch with flag KEEPVERITY=[%s] KEEPFORCEENCRYPT=[%s]\n", - keepverity ? "true" : "false", keepforceencrypt ? "true" : "false"); + bool keepverity = check_env("KEEPVERITY"); + bool keepforceencrypt = check_env("KEEPFORCEENCRYPT"); + fprintf(stderr, "Patch with flag KEEPVERITY=[%s] KEEPFORCEENCRYPT=[%s]\n", + keepverity ? "true" : "false", keepforceencrypt ? "true" : "false"); - for (auto it = entries.begin(); it != entries.end();) { - auto cur = it++; - bool fstab = (!keepverity || !keepforceencrypt) && - S_ISREG(cur->second->mode) && - !str_starts(cur->first, ".backup") && - !str_contains(cur->first, "twrp") && - !str_contains(cur->first, "recovery") && - str_contains(cur->first, "fstab"); - if (!keepverity) { - if (fstab) { - fprintf(stderr, "Found fstab file [%s]\n", cur->first.data()); - cur->second->filesize = patch_verity(cur->second->data, cur->second->filesize); - } else if (cur->first == "verity_key") { - rm(cur); - continue; - } - } - if (!keepforceencrypt) { - if (fstab) { - cur->second->filesize = patch_encryption(cur->second->data, cur->second->filesize); - } - } - } + for (auto it = entries.begin(); it != entries.end();) { + auto cur = it++; + bool fstab = (!keepverity || !keepforceencrypt) && + S_ISREG(cur->second->mode) && + !str_starts(cur->first, ".backup") && + !str_contains(cur->first, "twrp") && + !str_contains(cur->first, "recovery") && + str_contains(cur->first, "fstab"); + if (!keepverity) { + if (fstab) { + fprintf(stderr, "Found fstab file [%s]\n", cur->first.data()); + cur->second->filesize = patch_verity(cur->second->data, cur->second->filesize); + } else if (cur->first == "verity_key") { + rm(cur); + continue; + } + } + if (!keepforceencrypt) { + if (fstab) { + cur->second->filesize = patch_encryption(cur->second->data, cur->second->filesize); + } + } + } } #define STOCK_BOOT 0 @@ -76,274 +76,274 @@ void magisk_cpio::patch() { #define TWO_STAGE_INIT (1 << 3) int magisk_cpio::test() { - for (auto file : UNSUPPORT_LIST) - if (exists(file)) - return UNSUPPORTED_CPIO; + for (auto file : UNSUPPORT_LIST) + if (exists(file)) + return UNSUPPORTED_CPIO; - int flags = STOCK_BOOT; + int flags = STOCK_BOOT; - if (exists(RAMDISK_XZ)) { - flags |= COMPRESSED_CPIO | MAGISK_PATCHED; - decompress(); - } + if (exists(RAMDISK_XZ)) { + flags |= COMPRESSED_CPIO | MAGISK_PATCHED; + decompress(); + } - if (exists("apex") || exists("first_stage_ramdisk")) - flags |= TWO_STAGE_INIT; + if (exists("apex") || exists("first_stage_ramdisk")) + flags |= TWO_STAGE_INIT; - for (auto file : MAGISK_LIST) { - if (exists(file)) { - flags |= MAGISK_PATCHED; - break; - } - } + for (auto file : MAGISK_LIST) { + if (exists(file)) { + flags |= MAGISK_PATCHED; + break; + } + } - return flags; + return flags; } #define for_each_line(line, buf, size) \ for (line = (char *) buf; line < (char *) buf + size && line[0]; line = strchr(line + 1, '\n') + 1) char *magisk_cpio::sha1() { - decompress(); - char sha1[41]; - char *line; - for (auto &e : entries) { - if (e.first == "init.magisk.rc" || e.first == "overlay/init.magisk.rc") { - for_each_line(line, e.second->data, e.second->filesize) { - if (strncmp(line, "#STOCKSHA1=", 11) == 0) { - strncpy(sha1, line + 12, 40); - sha1[40] = '\0'; - return strdup(sha1); - } - } - } else if (e.first == ".backup/.magisk") { - for_each_line(line, e.second->data, e.second->filesize) { - if (strncmp(line, "SHA1=", 5) == 0) { - strncpy(sha1, line + 5, 40); - sha1[40] = '\0'; - return strdup(sha1); - } - } - } else if (e.first == ".backup/.sha1") { - return (char *) e.second->data; - } - } - return nullptr; + decompress(); + char sha1[41]; + char *line; + for (auto &e : entries) { + if (e.first == "init.magisk.rc" || e.first == "overlay/init.magisk.rc") { + for_each_line(line, e.second->data, e.second->filesize) { + if (strncmp(line, "#STOCKSHA1=", 11) == 0) { + strncpy(sha1, line + 12, 40); + sha1[40] = '\0'; + return strdup(sha1); + } + } + } else if (e.first == ".backup/.magisk") { + for_each_line(line, e.second->data, e.second->filesize) { + if (strncmp(line, "SHA1=", 5) == 0) { + strncpy(sha1, line + 5, 40); + sha1[40] = '\0'; + return strdup(sha1); + } + } + } else if (e.first == ".backup/.sha1") { + return (char *) e.second->data; + } + } + return nullptr; } #define for_each_str(str, buf, size) \ for (str = (char *) buf; str < (char *) buf + size; str = str += strlen(str) + 1) void magisk_cpio::restore() { - decompress(); + decompress(); - if (auto it = entries.find(".backup/.rmlist"); it != entries.end()) { - char *file; - for_each_str(file, it->second->data, it->second->filesize) - rm(file, false); - rm(it); - } + if (auto it = entries.find(".backup/.rmlist"); it != entries.end()) { + char *file; + for_each_str(file, it->second->data, it->second->filesize) + rm(file, false); + rm(it); + } - for (auto it = entries.begin(); it != entries.end();) { - auto cur = it++; - if (str_starts(cur->first, ".backup")) { - if (cur->first.length() == 7 || cur->first.substr(8) == ".magisk") { - rm(cur); - } else { - mv(cur, &cur->first[8]); - } - } else if (str_starts(cur->first, "magisk") || - cur->first == "overlay/init.magisk.rc" || - cur->first == "sbin/magic_mask.sh" || - cur->first == "init.magisk.rc") { - // Some known stuff we can remove - rm(cur); - } - } + for (auto it = entries.begin(); it != entries.end();) { + auto cur = it++; + if (str_starts(cur->first, ".backup")) { + if (cur->first.length() == 7 || cur->first.substr(8) == ".magisk") { + rm(cur); + } else { + mv(cur, &cur->first[8]); + } + } else if (str_starts(cur->first, "magisk") || + cur->first == "overlay/init.magisk.rc" || + cur->first == "sbin/magic_mask.sh" || + cur->first == "init.magisk.rc") { + // Some known stuff we can remove + rm(cur); + } + } } void magisk_cpio::backup(const char *orig) { - if (access(orig, R_OK)) - return; - entry_map bkup_entries; - string remv; + if (access(orig, R_OK)) + return; + entry_map bkup_entries; + string remv; - auto b = new cpio_entry(".backup", S_IFDIR); - bkup_entries[b->filename].reset(b); + auto b = new cpio_entry(".backup", S_IFDIR); + bkup_entries[b->filename].reset(b); - magisk_cpio o(orig); + magisk_cpio o(orig); - // Remove possible backups in original ramdisk - o.rm(".backup", true); - rm(".backup", true); + // Remove possible backups in original ramdisk + o.rm(".backup", true); + rm(".backup", true); - auto lhs = o.entries.begin(); - auto rhs = entries.begin(); + auto lhs = o.entries.begin(); + auto rhs = entries.begin(); - while (lhs != o.entries.end() || rhs != entries.end()) { - int res; - bool backup = false; - if (lhs != o.entries.end() && rhs != entries.end()) { - res = lhs->first.compare(rhs->first); - } else if (lhs == o.entries.end()) { - res = 1; - } else { - res = -1; - } + while (lhs != o.entries.end() || rhs != entries.end()) { + int res; + bool backup = false; + if (lhs != o.entries.end() && rhs != entries.end()) { + res = lhs->first.compare(rhs->first); + } else if (lhs == o.entries.end()) { + res = 1; + } else { + res = -1; + } - if (res < 0) { - // Something is missing in new ramdisk, backup! - backup = true; - fprintf(stderr, "Backup missing entry: "); - } else if (res == 0) { - if (lhs->second->filesize != rhs->second->filesize || - memcmp(lhs->second->data, rhs->second->data, lhs->second->filesize) != 0) { - // Not the same! - backup = true; - fprintf(stderr, "Backup mismatch entry: "); - } - } else { - // Something new in ramdisk - remv += rhs->first; - remv += (char) '\0'; - fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", rhs->first.data()); - } - if (backup) { - string back_name(".backup/"); - back_name += lhs->first; - fprintf(stderr, "[%s] -> [%s]\n", lhs->first.data(), back_name.data()); - auto ex = static_cast(lhs->second.release()); - ex->filename = back_name; - bkup_entries[ex->filename].reset(ex); - } + if (res < 0) { + // Something is missing in new ramdisk, backup! + backup = true; + fprintf(stderr, "Backup missing entry: "); + } else if (res == 0) { + if (lhs->second->filesize != rhs->second->filesize || + memcmp(lhs->second->data, rhs->second->data, lhs->second->filesize) != 0) { + // Not the same! + backup = true; + fprintf(stderr, "Backup mismatch entry: "); + } + } else { + // Something new in ramdisk + remv += rhs->first; + remv += (char) '\0'; + fprintf(stderr, "Record new entry: [%s] -> [.backup/.rmlist]\n", rhs->first.data()); + } + if (backup) { + string back_name(".backup/"); + back_name += lhs->first; + fprintf(stderr, "[%s] -> [%s]\n", lhs->first.data(), back_name.data()); + auto ex = static_cast(lhs->second.release()); + ex->filename = back_name; + bkup_entries[ex->filename].reset(ex); + } - // Increment positions - if (res < 0) { - ++lhs; - } else if (res == 0) { - ++lhs; ++rhs; - } else { - ++rhs; - } - } + // Increment positions + if (res < 0) { + ++lhs; + } else if (res == 0) { + ++lhs; ++rhs; + } else { + ++rhs; + } + } - if (!remv.empty()) { - auto rmlist = new cpio_entry(".backup/.rmlist", S_IFREG); - rmlist->filesize = remv.length(); - rmlist->data = xmalloc(remv.length()); - memcpy(rmlist->data, remv.data(), remv.length()); - bkup_entries[rmlist->filename].reset(rmlist); - } + if (!remv.empty()) { + auto rmlist = new cpio_entry(".backup/.rmlist", S_IFREG); + rmlist->filesize = remv.length(); + rmlist->data = xmalloc(remv.length()); + memcpy(rmlist->data, remv.data(), remv.length()); + bkup_entries[rmlist->filename].reset(rmlist); + } - if (bkup_entries.size() > 1) - entries.merge(bkup_entries); + if (bkup_entries.size() > 1) + entries.merge(bkup_entries); } void magisk_cpio::compress() { - if (exists(RAMDISK_XZ)) - return; - fprintf(stderr, "Compressing cpio -> [%s]\n", RAMDISK_XZ); - auto init = entries.extract("init"); + if (exists(RAMDISK_XZ)) + return; + fprintf(stderr, "Compressing cpio -> [%s]\n", RAMDISK_XZ); + auto init = entries.extract("init"); - uint8_t *data; - size_t len; - auto strm = make_stream_fp(get_encoder(XZ, make_unique(data, len))); - dump(strm.release()); + uint8_t *data; + size_t len; + auto strm = make_stream_fp(get_encoder(XZ, make_unique(data, len))); + dump(strm.release()); - entries.clear(); - entries.insert(std::move(init)); - auto xz = new cpio_entry(RAMDISK_XZ, S_IFREG); - xz->data = data; - xz->filesize = len; - insert(xz); + entries.clear(); + entries.insert(std::move(init)); + auto xz = new cpio_entry(RAMDISK_XZ, S_IFREG); + xz->data = data; + xz->filesize = len; + insert(xz); } void magisk_cpio::decompress() { - auto it = entries.find(RAMDISK_XZ); - if (it == entries.end()) - return; - fprintf(stderr, "Decompressing cpio [%s]\n", RAMDISK_XZ); + auto it = entries.find(RAMDISK_XZ); + if (it == entries.end()) + return; + fprintf(stderr, "Decompressing cpio [%s]\n", RAMDISK_XZ); - char *data; - size_t len; - { - auto strm = get_decoder(XZ, make_unique(data, len)); - strm->write(it->second->data, it->second->filesize); - } + char *data; + size_t len; + { + auto strm = get_decoder(XZ, make_unique(data, len)); + strm->write(it->second->data, it->second->filesize); + } - entries.erase(it); - load_cpio(data, len); - free(data); + entries.erase(it); + load_cpio(data, len); + free(data); } int cpio_commands(int argc, char *argv[]) { - char *incpio = argv[0]; - ++argv; - --argc; + char *incpio = argv[0]; + ++argv; + --argc; - magisk_cpio cpio; - if (access(incpio, R_OK) == 0) - cpio.load_cpio(incpio); + magisk_cpio cpio; + if (access(incpio, R_OK) == 0) + cpio.load_cpio(incpio); - int cmdc; - char *cmdv[6]; + int cmdc; + char *cmdv[6]; - while (argc) { - // Clean up - cmdc = 0; - memset(cmdv, NULL, sizeof(cmdv)); + while (argc) { + // Clean up + cmdc = 0; + memset(cmdv, NULL, sizeof(cmdv)); - // Split the commands - for (char *tok = strtok(argv[0], " "); tok; tok = strtok(nullptr, " ")) - cmdv[cmdc++] = tok; + // Split the commands + for (char *tok = strtok(argv[0], " "); tok; tok = strtok(nullptr, " ")) + cmdv[cmdc++] = tok; - if (cmdc == 0) - continue; + if (cmdc == 0) + continue; - if (strcmp(cmdv[0], "test") == 0) { - exit(cpio.test()); - } else if (strcmp(cmdv[0], "restore") == 0) { - cpio.restore(); - } else if (strcmp(cmdv[0], "sha1") == 0) { - char *sha1 = cpio.sha1(); - if (sha1) printf("%s\n", sha1); - return 0; - } else if (strcmp(cmdv[0], "compress") == 0){ - cpio.compress(); - } else if (strcmp(cmdv[0], "decompress") == 0){ - cpio.decompress(); - } else if (strcmp(cmdv[0], "patch") == 0) { - cpio.patch(); - } else if (cmdc == 2 && strcmp(cmdv[0], "exists") == 0) { - exit(!cpio.exists(cmdv[1])); - } else if (cmdc == 2 && strcmp(cmdv[0], "backup") == 0) { - cpio.backup(cmdv[1]); - } else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) { - bool r = cmdc > 2 && strcmp(cmdv[1], "-r") == 0; - cpio.rm(cmdv[1 + r], r); - } else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) { - cpio.mv(cmdv[1], cmdv[2]); - } else if (strcmp(cmdv[0], "extract") == 0) { - if (cmdc == 3) { - return !cpio.extract(cmdv[1], cmdv[2]); - } else { - cpio.extract(); - return 0; - } - } else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) { - cpio.mkdir(strtoul(cmdv[1], nullptr, 8), cmdv[2]); - } else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) { - cpio.ln(cmdv[1], cmdv[2]); - } else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) { - cpio.add(strtoul(cmdv[1], nullptr, 8), cmdv[2], cmdv[3]); - } else { - return 1; - } + if (strcmp(cmdv[0], "test") == 0) { + exit(cpio.test()); + } else if (strcmp(cmdv[0], "restore") == 0) { + cpio.restore(); + } else if (strcmp(cmdv[0], "sha1") == 0) { + char *sha1 = cpio.sha1(); + if (sha1) printf("%s\n", sha1); + return 0; + } else if (strcmp(cmdv[0], "compress") == 0){ + cpio.compress(); + } else if (strcmp(cmdv[0], "decompress") == 0){ + cpio.decompress(); + } else if (strcmp(cmdv[0], "patch") == 0) { + cpio.patch(); + } else if (cmdc == 2 && strcmp(cmdv[0], "exists") == 0) { + exit(!cpio.exists(cmdv[1])); + } else if (cmdc == 2 && strcmp(cmdv[0], "backup") == 0) { + cpio.backup(cmdv[1]); + } else if (cmdc >= 2 && strcmp(cmdv[0], "rm") == 0) { + bool r = cmdc > 2 && strcmp(cmdv[1], "-r") == 0; + cpio.rm(cmdv[1 + r], r); + } else if (cmdc == 3 && strcmp(cmdv[0], "mv") == 0) { + cpio.mv(cmdv[1], cmdv[2]); + } else if (strcmp(cmdv[0], "extract") == 0) { + if (cmdc == 3) { + return !cpio.extract(cmdv[1], cmdv[2]); + } else { + cpio.extract(); + return 0; + } + } else if (cmdc == 3 && strcmp(cmdv[0], "mkdir") == 0) { + cpio.mkdir(strtoul(cmdv[1], nullptr, 8), cmdv[2]); + } else if (cmdc == 3 && strcmp(cmdv[0], "ln") == 0) { + cpio.ln(cmdv[1], cmdv[2]); + } else if (cmdc == 4 && strcmp(cmdv[0], "add") == 0) { + cpio.add(strtoul(cmdv[1], nullptr, 8), cmdv[2], cmdv[3]); + } else { + return 1; + } - --argc; - ++argv; - } + --argc; + ++argv; + } - cpio.dump(incpio); - return 0; + cpio.dump(incpio); + return 0; } diff --git a/native/jni/magiskhide/hide_policy.cpp b/native/jni/magiskhide/hide_policy.cpp index 64c530c50..067344086 100644 --- a/native/jni/magiskhide/hide_policy.cpp +++ b/native/jni/magiskhide/hide_policy.cpp @@ -10,123 +10,123 @@ using namespace std; static const char *prop_key[] = - { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", - "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit", - "ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags", - "ro.vendor.boot.warranty_bit", "ro.vendor.warranty_bit", - "vendor.boot.vbmeta.device_state", nullptr }; + { "ro.boot.vbmeta.device_state", "ro.boot.verifiedbootstate", "ro.boot.flash.locked", + "ro.boot.veritymode", "ro.boot.warranty_bit", "ro.warranty_bit", + "ro.debuggable", "ro.secure", "ro.build.type", "ro.build.tags", + "ro.vendor.boot.warranty_bit", "ro.vendor.warranty_bit", + "vendor.boot.vbmeta.device_state", nullptr }; static const char *prop_val[] = - { "locked", "green", "1", - "enforcing", "0", "0", - "0", "1", "user", "release-keys", - "0", "0", - "locked", nullptr }; + { "locked", "green", "1", + "enforcing", "0", "0", + "0", "1", "user", "release-keys", + "0", "0", + "locked", nullptr }; static const char *late_prop_key[] = - { "vendor.boot.verifiedbootstate", nullptr }; + { "vendor.boot.verifiedbootstate", nullptr }; static const char *late_prop_val[] = - { "green", nullptr }; + { "green", nullptr }; void hide_sensitive_props() { - LOGI("hide_policy: Hiding sensitive props\n"); + LOGI("hide_policy: Hiding sensitive props\n"); - for (int i = 0; prop_key[i]; ++i) { - auto value = getprop(prop_key[i]); - if (!value.empty() && value != prop_val[i]) - setprop(prop_key[i], prop_val[i], false); - } + for (int i = 0; prop_key[i]; ++i) { + auto value = getprop(prop_key[i]); + if (!value.empty() && value != prop_val[i]) + setprop(prop_key[i], prop_val[i], false); + } - // Hide that we booted from recovery when magisk is in recovery mode - auto bootmode = getprop("ro.bootmode"); - if (!bootmode.empty() && str_contains(bootmode, "recovery")) - setprop("ro.bootmode", "unknown", false); - bootmode = getprop("ro.boot.mode"); - if (!bootmode.empty() && str_contains(bootmode, "recovery")) - setprop("ro.boot.mode", "unknown", false); - bootmode = getprop("vendor.boot.mode"); - if (!bootmode.empty() && str_contains(bootmode, "recovery")) - setprop("vendor.boot.mode", "unknown", false); + // Hide that we booted from recovery when magisk is in recovery mode + auto bootmode = getprop("ro.bootmode"); + if (!bootmode.empty() && str_contains(bootmode, "recovery")) + setprop("ro.bootmode", "unknown", false); + bootmode = getprop("ro.boot.mode"); + if (!bootmode.empty() && str_contains(bootmode, "recovery")) + setprop("ro.boot.mode", "unknown", false); + bootmode = getprop("vendor.boot.mode"); + if (!bootmode.empty() && str_contains(bootmode, "recovery")) + setprop("vendor.boot.mode", "unknown", false); - // Xiaomi cross region flash - auto hwc = getprop("ro.boot.hwc"); - if (!hwc.empty() && str_contains(hwc, "CN")) - setprop("ro.boot.hwc", "GLOBAL", false); - auto hwcountry = getprop("ro.boot.hwcountry"); - if (!hwcountry.empty() && str_contains(hwcountry, "China")) - setprop("ro.boot.hwcountry", "GLOBAL", false); + // Xiaomi cross region flash + auto hwc = getprop("ro.boot.hwc"); + if (!hwc.empty() && str_contains(hwc, "CN")) + setprop("ro.boot.hwc", "GLOBAL", false); + auto hwcountry = getprop("ro.boot.hwcountry"); + if (!hwcountry.empty() && str_contains(hwcountry, "China")) + setprop("ro.boot.hwcountry", "GLOBAL", false); - auto selinux = getprop("ro.build.selinux"); - if (!selinux.empty()) - delprop("ro.build.selinux"); + auto selinux = getprop("ro.build.selinux"); + if (!selinux.empty()) + delprop("ro.build.selinux"); } void hide_late_sensitive_props() { - LOGI("hide_policy: Hiding sensitive props (late)\n"); + LOGI("hide_policy: Hiding sensitive props (late)\n"); - for (int i = 0; late_prop_key[i]; ++i) { - auto value = getprop(late_prop_key[i]); - if (!value.empty() && value != late_prop_val[i]) - setprop(late_prop_key[i], late_prop_val[i], false); - } + for (int i = 0; late_prop_key[i]; ++i) { + auto value = getprop(late_prop_key[i]); + if (!value.empty() && value != late_prop_val[i]) + setprop(late_prop_key[i], late_prop_val[i], false); + } } static void lazy_unmount(const char* mountpoint) { - if (umount2(mountpoint, MNT_DETACH) != -1) - LOGD("hide_policy: Unmounted (%s)\n", mountpoint); + if (umount2(mountpoint, MNT_DETACH) != -1) + LOGD("hide_policy: Unmounted (%s)\n", mountpoint); } void hide_daemon(int pid) { - if (fork_dont_care() == 0) { - hide_unmount(pid); - // Send resume signal - kill(pid, SIGCONT); - _exit(0); - } + if (fork_dont_care() == 0) { + hide_unmount(pid); + // Send resume signal + kill(pid, SIGCONT); + _exit(0); + } } #define TMPFS_MNT(dir) (mentry->mnt_type == "tmpfs"sv && \ strncmp(mentry->mnt_dir, "/" #dir, sizeof("/" #dir) - 1) == 0) void hide_unmount(int pid) { - if (switch_mnt_ns(pid)) - return; + if (switch_mnt_ns(pid)) + return; - LOGD("hide_policy: handling PID=[%d]\n", pid); + LOGD("hide_policy: handling PID=[%d]\n", pid); - char val; - int fd = xopen(SELINUX_ENFORCE, O_RDONLY); - xxread(fd, &val, sizeof(val)); - close(fd); - // Permissive - if (val == '0') { - chmod(SELINUX_ENFORCE, 0640); - chmod(SELINUX_POLICY, 0440); - } + char val; + int fd = xopen(SELINUX_ENFORCE, O_RDONLY); + xxread(fd, &val, sizeof(val)); + close(fd); + // Permissive + if (val == '0') { + chmod(SELINUX_ENFORCE, 0640); + chmod(SELINUX_POLICY, 0440); + } - vector targets; + vector targets; - // Unmount dummy skeletons and /sbin links - targets.push_back(MAGISKTMP); - parse_mnt("/proc/self/mounts", [&](mntent *mentry) { - if (TMPFS_MNT(system) || TMPFS_MNT(vendor) || TMPFS_MNT(product) || TMPFS_MNT(system_ext)) - targets.emplace_back(mentry->mnt_dir); - return true; - }); + // Unmount dummy skeletons and /sbin links + targets.push_back(MAGISKTMP); + parse_mnt("/proc/self/mounts", [&](mntent *mentry) { + if (TMPFS_MNT(system) || TMPFS_MNT(vendor) || TMPFS_MNT(product) || TMPFS_MNT(system_ext)) + targets.emplace_back(mentry->mnt_dir); + return true; + }); - for (auto &s : reversed(targets)) - lazy_unmount(s.data()); - targets.clear(); + for (auto &s : reversed(targets)) + lazy_unmount(s.data()); + targets.clear(); - // Unmount all Magisk created mounts - parse_mnt("/proc/self/mounts", [&](mntent *mentry) { - if (strstr(mentry->mnt_fsname, BLOCKDIR)) - targets.emplace_back(mentry->mnt_dir); - return true; - }); + // Unmount all Magisk created mounts + parse_mnt("/proc/self/mounts", [&](mntent *mentry) { + if (strstr(mentry->mnt_fsname, BLOCKDIR)) + targets.emplace_back(mentry->mnt_dir); + return true; + }); - for (auto &s : reversed(targets)) - lazy_unmount(s.data()); + for (auto &s : reversed(targets)) + lazy_unmount(s.data()); } diff --git a/native/jni/magiskhide/hide_utils.cpp b/native/jni/magiskhide/hide_utils.cpp index 1296168d5..fccf7f224 100644 --- a/native/jni/magiskhide/hide_utils.cpp +++ b/native/jni/magiskhide/hide_utils.cpp @@ -24,169 +24,169 @@ static pthread_mutex_t hide_state_lock = PTHREAD_MUTEX_INITIALIZER; // Leave /proc fd opened as we're going to read from it repeatedly static DIR *procfp; void crawl_procfs(const function &fn) { - rewinddir(procfp); - crawl_procfs(procfp, fn); + rewinddir(procfp); + crawl_procfs(procfp, fn); } void crawl_procfs(DIR *dir, const function &fn) { - struct dirent *dp; - int pid; - while ((dp = readdir(dir))) { - pid = parse_int(dp->d_name); - if (pid > 0 && !fn(pid)) - break; - } + struct dirent *dp; + int pid; + while ((dp = readdir(dir))) { + pid = parse_int(dp->d_name); + if (pid > 0 && !fn(pid)) + break; + } } bool hide_enabled() { - mutex_guard g(hide_state_lock); - return hide_state; + mutex_guard g(hide_state_lock); + return hide_state; } void set_hide_state(bool state) { - mutex_guard g(hide_state_lock); - hide_state = state; + mutex_guard g(hide_state_lock); + hide_state = state; } template static bool proc_name_match(int pid, const char *name) { - char buf[4019]; - sprintf(buf, "/proc/%d/cmdline", pid); - if (auto fp = open_file(buf, "re")) { - fgets(buf, sizeof(buf), fp.get()); - if (str_op(buf, name)) { - LOGD("hide_utils: kill PID=[%d] (%s)\n", pid, buf); - return true; - } - } - return false; + char buf[4019]; + sprintf(buf, "/proc/%d/cmdline", pid); + if (auto fp = open_file(buf, "re")) { + fgets(buf, sizeof(buf), fp.get()); + if (str_op(buf, name)) { + LOGD("hide_utils: kill PID=[%d] (%s)\n", pid, buf); + return true; + } + } + return false; } static inline bool str_eql(string_view s, string_view ss) { return s == ss; } static void kill_process(const char *name, bool multi = false, - bool (*filter)(int, const char *) = proc_name_match<&str_eql>) { - crawl_procfs([=](int pid) -> bool { - if (filter(pid, name)) { - kill(pid, SIGTERM); - return multi; - } - return true; - }); + bool (*filter)(int, const char *) = proc_name_match<&str_eql>) { + crawl_procfs([=](int pid) -> bool { + if (filter(pid, name)) { + kill(pid, SIGTERM); + return multi; + } + return true; + }); } static bool validate(const char *s) { - if (strcmp(s, ISOLATED_MAGIC) == 0) - return true; - bool dot = false; - for (char c; (c = *s); ++s) { - if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || - (c >= '0' && c <= '9') || c == '_' || c == ':') { - continue; - } - if (c == '.') { - dot = true; - continue; - } - return false; - } - return dot; + if (strcmp(s, ISOLATED_MAGIC) == 0) + return true; + bool dot = false; + for (char c; (c = *s); ++s) { + if ((c >= 'A' && c <= 'Z') || (c >= 'a' && c <= 'z') || + (c >= '0' && c <= '9') || c == '_' || c == ':') { + continue; + } + if (c == '.') { + dot = true; + continue; + } + return false; + } + return dot; } static void add_hide_set(const char *pkg, const char *proc) { - LOGI("hide_list add: [%s/%s]\n", pkg, proc); - hide_set.emplace(pkg, proc); - if (strcmp(pkg, ISOLATED_MAGIC) == 0) { - // Kill all matching isolated processes - kill_process(proc, true, proc_name_match<&str_starts>); - } else { - kill_process(proc); - } + LOGI("hide_list add: [%s/%s]\n", pkg, proc); + hide_set.emplace(pkg, proc); + if (strcmp(pkg, ISOLATED_MAGIC) == 0) { + // Kill all matching isolated processes + kill_process(proc, true, proc_name_match<&str_starts>); + } else { + kill_process(proc); + } } static int add_list(const char *pkg, const char *proc) { - if (proc[0] == '\0') - proc = pkg; + if (proc[0] == '\0') + proc = pkg; - if (!validate(pkg) || !validate(proc)) - return HIDE_INVALID_PKG; + if (!validate(pkg) || !validate(proc)) + return HIDE_INVALID_PKG; - for (auto &hide : hide_set) - if (hide.first == pkg && hide.second == proc) - return HIDE_ITEM_EXIST; + for (auto &hide : hide_set) + if (hide.first == pkg && hide.second == proc) + return HIDE_ITEM_EXIST; - // Add to database - char sql[4096]; - snprintf(sql, sizeof(sql), - "INSERT INTO hidelist (package_name, process) VALUES('%s', '%s')", pkg, proc); - char *err = db_exec(sql); - db_err_cmd(err, return DAEMON_ERROR); + // Add to database + char sql[4096]; + snprintf(sql, sizeof(sql), + "INSERT INTO hidelist (package_name, process) VALUES('%s', '%s')", pkg, proc); + char *err = db_exec(sql); + db_err_cmd(err, return DAEMON_ERROR); - { - // Critical region - mutex_guard lock(monitor_lock); - add_hide_set(pkg, proc); - } + { + // Critical region + mutex_guard lock(monitor_lock); + add_hide_set(pkg, proc); + } - return DAEMON_SUCCESS; + return DAEMON_SUCCESS; } int add_list(int client) { - char *pkg = read_string(client); - char *proc = read_string(client); - int ret = add_list(pkg, proc); - free(pkg); - free(proc); - if (ret == DAEMON_SUCCESS) - update_uid_map(); - return ret; + char *pkg = read_string(client); + char *proc = read_string(client); + int ret = add_list(pkg, proc); + free(pkg); + free(proc); + if (ret == DAEMON_SUCCESS) + update_uid_map(); + return ret; } static int rm_list(const char *pkg, const char *proc) { - bool remove = false; - { - // Critical region - mutex_guard lock(monitor_lock); - for (auto it = hide_set.begin(); it != hide_set.end();) { - if (it->first == pkg && (proc[0] == '\0' || it->second == proc)) { - remove = true; - LOGI("hide_list rm: [%s/%s]\n", it->first.data(), it->second.data()); - it = hide_set.erase(it); - } else { - ++it; - } - } - } - if (!remove) - return HIDE_ITEM_NOT_EXIST; + bool remove = false; + { + // Critical region + mutex_guard lock(monitor_lock); + for (auto it = hide_set.begin(); it != hide_set.end();) { + if (it->first == pkg && (proc[0] == '\0' || it->second == proc)) { + remove = true; + LOGI("hide_list rm: [%s/%s]\n", it->first.data(), it->second.data()); + it = hide_set.erase(it); + } else { + ++it; + } + } + } + if (!remove) + return HIDE_ITEM_NOT_EXIST; - char sql[4096]; - if (proc[0] == '\0') - snprintf(sql, sizeof(sql), "DELETE FROM hidelist WHERE package_name='%s'", pkg); - else - snprintf(sql, sizeof(sql), - "DELETE FROM hidelist WHERE package_name='%s' AND process='%s'", pkg, proc); - char *err = db_exec(sql); - db_err(err); - return DAEMON_SUCCESS; + char sql[4096]; + if (proc[0] == '\0') + snprintf(sql, sizeof(sql), "DELETE FROM hidelist WHERE package_name='%s'", pkg); + else + snprintf(sql, sizeof(sql), + "DELETE FROM hidelist WHERE package_name='%s' AND process='%s'", pkg, proc); + char *err = db_exec(sql); + db_err(err); + return DAEMON_SUCCESS; } int rm_list(int client) { - char *pkg = read_string(client); - char *proc = read_string(client); - int ret = rm_list(pkg, proc); - free(pkg); - free(proc); - if (ret == DAEMON_SUCCESS) - update_uid_map(); - return ret; + char *pkg = read_string(client); + char *proc = read_string(client); + int ret = rm_list(pkg, proc); + free(pkg); + free(proc); + if (ret == DAEMON_SUCCESS) + update_uid_map(); + return ret; } static bool str_ends_safe(string_view s, string_view ss) { - // Never kill webview zygote - if (s == "webview_zygote") - return false; - return str_ends(s, ss); + // Never kill webview zygote + if (s == "webview_zygote") + return false; + return str_ends(s, ss); } #define SNET_PROC "com.google.android.gms.unstable" @@ -194,116 +194,116 @@ static bool str_ends_safe(string_view s, string_view ss) { #define MICROG_PKG "org.microg.gms.droidguard" static bool init_list() { - LOGD("hide_list: initialize\n"); + LOGD("hide_list: initialize\n"); - char *err = db_exec("SELECT * FROM hidelist", [](db_row &row) -> bool { - add_hide_set(row["package_name"].data(), row["process"].data()); - return true; - }); - db_err_cmd(err, return false); + char *err = db_exec("SELECT * FROM hidelist", [](db_row &row) -> bool { + add_hide_set(row["package_name"].data(), row["process"].data()); + return true; + }); + db_err_cmd(err, return false); - // If Android Q+, also kill blastula pool and all app zygotes - if (SDK_INT >= 29) { - kill_process("usap32", true); - kill_process("usap64", true); - kill_process("_zygote", true, proc_name_match<&str_ends_safe>); - } + // If Android Q+, also kill blastula pool and all app zygotes + if (SDK_INT >= 29) { + kill_process("usap32", true); + kill_process("usap64", true); + kill_process("_zygote", true, proc_name_match<&str_ends_safe>); + } - // Add SafetyNet by default - add_hide_set(GMS_PKG, SNET_PROC); - add_hide_set(MICROG_PKG, SNET_PROC); + // Add SafetyNet by default + add_hide_set(GMS_PKG, SNET_PROC); + add_hide_set(MICROG_PKG, SNET_PROC); - // We also need to hide the default GMS process if MAGISKTMP != /sbin - // The snet process communicates with the main process and get additional info - if (MAGISKTMP != "/sbin") - add_hide_set(GMS_PKG, GMS_PKG); + // We also need to hide the default GMS process if MAGISKTMP != /sbin + // The snet process communicates with the main process and get additional info + if (MAGISKTMP != "/sbin") + add_hide_set(GMS_PKG, GMS_PKG); - update_uid_map(); - return true; + update_uid_map(); + return true; } void ls_list(int client) { - FILE *out = fdopen(recv_fd(client), "a"); - for (auto &hide : hide_set) - fprintf(out, "%s|%s\n", hide.first.data(), hide.second.data()); - fclose(out); - write_int(client, DAEMON_SUCCESS); - close(client); + FILE *out = fdopen(recv_fd(client), "a"); + for (auto &hide : hide_set) + fprintf(out, "%s|%s\n", hide.first.data(), hide.second.data()); + fclose(out); + write_int(client, DAEMON_SUCCESS); + close(client); } static void update_hide_config() { - char sql[64]; - sprintf(sql, "REPLACE INTO settings (key,value) VALUES('%s',%d)", - DB_SETTING_KEYS[HIDE_CONFIG], hide_state); - char *err = db_exec(sql); - db_err(err); + char sql[64]; + sprintf(sql, "REPLACE INTO settings (key,value) VALUES('%s',%d)", + DB_SETTING_KEYS[HIDE_CONFIG], hide_state); + char *err = db_exec(sql); + db_err(err); } int launch_magiskhide() { - mutex_guard g(hide_state_lock); + mutex_guard g(hide_state_lock); - if (SDK_INT < 19) - return DAEMON_ERROR; + if (SDK_INT < 19) + return DAEMON_ERROR; - if (hide_state) - return HIDE_IS_ENABLED; + if (hide_state) + return HIDE_IS_ENABLED; - if (access("/proc/1/ns/mnt", F_OK) != 0) - return HIDE_NO_NS; + if (access("/proc/1/ns/mnt", F_OK) != 0) + return HIDE_NO_NS; - if (procfp == nullptr && (procfp = opendir("/proc")) == nullptr) - return DAEMON_ERROR; + if (procfp == nullptr && (procfp = opendir("/proc")) == nullptr) + return DAEMON_ERROR; - LOGI("* Starting MagiskHide\n"); + LOGI("* Starting MagiskHide\n"); - // Initialize the mutex lock - pthread_mutex_init(&monitor_lock, nullptr); + // Initialize the mutex lock + pthread_mutex_init(&monitor_lock, nullptr); - // Initialize the hide list - if (!init_list()) - return DAEMON_ERROR; + // Initialize the hide list + if (!init_list()) + return DAEMON_ERROR; - hide_sensitive_props(); - if (DAEMON_STATE >= STATE_BOOT_COMPLETE || DAEMON_STATE == STATE_NONE) - hide_late_sensitive_props(); + hide_sensitive_props(); + if (DAEMON_STATE >= STATE_BOOT_COMPLETE || DAEMON_STATE == STATE_NONE) + hide_late_sensitive_props(); - // Start monitoring - void *(*start)(void*) = [](void*) -> void* { proc_monitor(); }; - if (xpthread_create(&proc_monitor_thread, nullptr, start, nullptr)) - return DAEMON_ERROR; + // Start monitoring + void *(*start)(void*) = [](void*) -> void* { proc_monitor(); }; + if (xpthread_create(&proc_monitor_thread, nullptr, start, nullptr)) + return DAEMON_ERROR; - hide_state = true; - update_hide_config(); - return DAEMON_SUCCESS; + hide_state = true; + update_hide_config(); + return DAEMON_SUCCESS; } int stop_magiskhide() { - mutex_guard g(hide_state_lock); + mutex_guard g(hide_state_lock); - if (hide_state) { - LOGI("* Stopping MagiskHide\n"); - pthread_kill(proc_monitor_thread, SIGTERMTHRD); - } + if (hide_state) { + LOGI("* Stopping MagiskHide\n"); + pthread_kill(proc_monitor_thread, SIGTERMTHRD); + } - hide_state = false; - update_hide_config(); - return DAEMON_SUCCESS; + hide_state = false; + update_hide_config(); + return DAEMON_SUCCESS; } void auto_start_magiskhide() { - if (hide_enabled()) { - pthread_kill(proc_monitor_thread, SIGALRM); - hide_late_sensitive_props(); - } else if (SDK_INT >= 19) { - db_settings dbs; - get_db_settings(dbs, HIDE_CONFIG); - if (dbs[HIDE_CONFIG]) - launch_magiskhide(); - } + if (hide_enabled()) { + pthread_kill(proc_monitor_thread, SIGALRM); + hide_late_sensitive_props(); + } else if (SDK_INT >= 19) { + db_settings dbs; + get_db_settings(dbs, HIDE_CONFIG); + if (dbs[HIDE_CONFIG]) + launch_magiskhide(); + } } void test_proc_monitor() { - if (procfp == nullptr && (procfp = opendir("/proc")) == nullptr) - exit(1); - proc_monitor(); + if (procfp == nullptr && (procfp = opendir("/proc")) == nullptr) + exit(1); + proc_monitor(); } diff --git a/native/jni/magiskhide/magiskhide.cpp b/native/jni/magiskhide/magiskhide.cpp index 7859ed8da..f29c77ee3 100644 --- a/native/jni/magiskhide/magiskhide.cpp +++ b/native/jni/magiskhide/magiskhide.cpp @@ -16,144 +16,144 @@ using namespace std::literals; [[noreturn]] static void usage(char *arg0) { - fprintf(stderr, - "MagiskHide - Hide Config CLI\n\n" - "Usage: %s [action [arguments...] ]\n\n" - "Actions:\n" - " status Return the status of magiskhide\n" - " enable Start magiskhide\n" - " disable Stop magiskhide\n" - " add PKG [PROC] Add a new target to the hide list\n" - " rm PKG [PROC] Remove target(s) from the hide list\n" - " ls Print the current hide list\n" - " exec CMDs... Execute commands in isolated mount\n" - " namespace and do all hide unmounts\n" + fprintf(stderr, + "MagiskHide - Hide Config CLI\n\n" + "Usage: %s [action [arguments...] ]\n\n" + "Actions:\n" + " status Return the status of magiskhide\n" + " enable Start magiskhide\n" + " disable Stop magiskhide\n" + " add PKG [PROC] Add a new target to the hide list\n" + " rm PKG [PROC] Remove target(s) from the hide list\n" + " ls Print the current hide list\n" + " exec CMDs... Execute commands in isolated mount\n" + " namespace and do all hide unmounts\n" #ifdef MAGISK_DEBUG - " test Run process monitor test\n" + " test Run process monitor test\n" #endif - , arg0); - exit(1); + , arg0); + exit(1); } void magiskhide_handler(int client) { - int req = read_int(client); - int res = DAEMON_ERROR; + int req = read_int(client); + int res = DAEMON_ERROR; - switch (req) { - case STOP_MAGISKHIDE: - case ADD_HIDELIST: - case RM_HIDELIST: - case LS_HIDELIST: - if (!hide_enabled()) { - write_int(client, HIDE_NOT_ENABLED); - close(client); - return; - } - } + switch (req) { + case STOP_MAGISKHIDE: + case ADD_HIDELIST: + case RM_HIDELIST: + case LS_HIDELIST: + if (!hide_enabled()) { + write_int(client, HIDE_NOT_ENABLED); + close(client); + return; + } + } - switch (req) { - case LAUNCH_MAGISKHIDE: - res = launch_magiskhide(); - break; - case STOP_MAGISKHIDE: - res = stop_magiskhide(); - break; - case ADD_HIDELIST: - res = add_list(client); - break; - case RM_HIDELIST: - res = rm_list(client); - break; - case LS_HIDELIST: - ls_list(client); - return; - case HIDE_STATUS: - res = hide_enabled() ? HIDE_IS_ENABLED : HIDE_NOT_ENABLED; - break; - } + switch (req) { + case LAUNCH_MAGISKHIDE: + res = launch_magiskhide(); + break; + case STOP_MAGISKHIDE: + res = stop_magiskhide(); + break; + case ADD_HIDELIST: + res = add_list(client); + break; + case RM_HIDELIST: + res = rm_list(client); + break; + case LS_HIDELIST: + ls_list(client); + return; + case HIDE_STATUS: + res = hide_enabled() ? HIDE_IS_ENABLED : HIDE_NOT_ENABLED; + break; + } - write_int(client, res); - close(client); + write_int(client, res); + close(client); } int magiskhide_main(int argc, char *argv[]) { - if (argc < 2) - usage(argv[0]); + if (argc < 2) + usage(argv[0]); - // CLI backwards compatibility - const char *opt = argv[1]; - if (opt[0] == '-' && opt[1] == '-') - opt += 2; + // CLI backwards compatibility + const char *opt = argv[1]; + if (opt[0] == '-' && opt[1] == '-') + opt += 2; - int req; - if (opt == "enable"sv) - req = LAUNCH_MAGISKHIDE; - else if (opt == "disable"sv) - req = STOP_MAGISKHIDE; - else if (opt == "add"sv) - req = ADD_HIDELIST; - else if (opt == "rm"sv) - req = RM_HIDELIST; - else if (opt == "ls"sv) - req = LS_HIDELIST; - else if (opt == "status"sv) - req = HIDE_STATUS; - else if (opt == "exec"sv && argc > 2) { - xunshare(CLONE_NEWNS); - xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr); - hide_unmount(); - execvp(argv[2], argv + 2); - exit(1); - } + int req; + if (opt == "enable"sv) + req = LAUNCH_MAGISKHIDE; + else if (opt == "disable"sv) + req = STOP_MAGISKHIDE; + else if (opt == "add"sv) + req = ADD_HIDELIST; + else if (opt == "rm"sv) + req = RM_HIDELIST; + else if (opt == "ls"sv) + req = LS_HIDELIST; + else if (opt == "status"sv) + req = HIDE_STATUS; + else if (opt == "exec"sv && argc > 2) { + xunshare(CLONE_NEWNS); + xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr); + hide_unmount(); + execvp(argv[2], argv + 2); + exit(1); + } #if 0 - else if (opt == "test"sv) - test_proc_monitor(); + else if (opt == "test"sv) + test_proc_monitor(); #endif - else - usage(argv[0]); + else + usage(argv[0]); - // Send request - int fd = connect_daemon(); - write_int(fd, MAGISKHIDE); - write_int(fd, req); - if (req == ADD_HIDELIST || req == RM_HIDELIST) { - write_string(fd, argv[2]); - write_string(fd, argv[3] ? argv[3] : ""); - } - if (req == LS_HIDELIST) - send_fd(fd, STDOUT_FILENO); + // Send request + int fd = connect_daemon(); + write_int(fd, MAGISKHIDE); + write_int(fd, req); + if (req == ADD_HIDELIST || req == RM_HIDELIST) { + write_string(fd, argv[2]); + write_string(fd, argv[3] ? argv[3] : ""); + } + if (req == LS_HIDELIST) + send_fd(fd, STDOUT_FILENO); - // Get response - int code = read_int(fd); - switch (code) { - case DAEMON_SUCCESS: - break; - case HIDE_NOT_ENABLED: - fprintf(stderr, "MagiskHide is not enabled\n"); - break; - case HIDE_IS_ENABLED: - fprintf(stderr, "MagiskHide is enabled\n"); - break; - case HIDE_ITEM_EXIST: - fprintf(stderr, "Target already exists in hide list\n"); - break; - case HIDE_ITEM_NOT_EXIST: - fprintf(stderr, "Target does not exist in hide list\n"); - break; - case HIDE_NO_NS: - fprintf(stderr, "Your kernel doesn't support mount namespace\n"); - break; - case HIDE_INVALID_PKG: - fprintf(stderr, "Invalid package / process name\n"); - break; - case ROOT_REQUIRED: - fprintf(stderr, "Root is required for this operation\n"); - break; - case DAEMON_ERROR: - default: - fprintf(stderr, "Daemon error\n"); - return DAEMON_ERROR; - } + // Get response + int code = read_int(fd); + switch (code) { + case DAEMON_SUCCESS: + break; + case HIDE_NOT_ENABLED: + fprintf(stderr, "MagiskHide is not enabled\n"); + break; + case HIDE_IS_ENABLED: + fprintf(stderr, "MagiskHide is enabled\n"); + break; + case HIDE_ITEM_EXIST: + fprintf(stderr, "Target already exists in hide list\n"); + break; + case HIDE_ITEM_NOT_EXIST: + fprintf(stderr, "Target does not exist in hide list\n"); + break; + case HIDE_NO_NS: + fprintf(stderr, "Your kernel doesn't support mount namespace\n"); + break; + case HIDE_INVALID_PKG: + fprintf(stderr, "Invalid package / process name\n"); + break; + case ROOT_REQUIRED: + fprintf(stderr, "Root is required for this operation\n"); + break; + case DAEMON_ERROR: + default: + fprintf(stderr, "Daemon error\n"); + return DAEMON_ERROR; + } - return req == HIDE_STATUS ? (code == HIDE_IS_ENABLED ? 0 : 1) : code != DAEMON_SUCCESS; + return req == HIDE_STATUS ? (code == HIDE_IS_ENABLED ? 0 : 1) : code != DAEMON_SUCCESS; } diff --git a/native/jni/magiskhide/magiskhide.hpp b/native/jni/magiskhide/magiskhide.hpp index df0620c73..1769d4976 100644 --- a/native/jni/magiskhide/magiskhide.hpp +++ b/native/jni/magiskhide/magiskhide.hpp @@ -43,19 +43,19 @@ extern pthread_mutex_t monitor_lock; extern std::set> hide_set; enum { - LAUNCH_MAGISKHIDE, - STOP_MAGISKHIDE, - ADD_HIDELIST, - RM_HIDELIST, - LS_HIDELIST, - HIDE_STATUS, + LAUNCH_MAGISKHIDE, + STOP_MAGISKHIDE, + ADD_HIDELIST, + RM_HIDELIST, + LS_HIDELIST, + HIDE_STATUS, }; enum { - HIDE_IS_ENABLED = DAEMON_LAST, - HIDE_NOT_ENABLED, - HIDE_ITEM_EXIST, - HIDE_ITEM_NOT_EXIST, - HIDE_NO_NS, - HIDE_INVALID_PKG + HIDE_IS_ENABLED = DAEMON_LAST, + HIDE_NOT_ENABLED, + HIDE_ITEM_EXIST, + HIDE_ITEM_NOT_EXIST, + HIDE_NO_NS, + HIDE_INVALID_PKG }; diff --git a/native/jni/magiskhide/proc_monitor.cpp b/native/jni/magiskhide/proc_monitor.cpp index 377b0356b..6b8810338 100644 --- a/native/jni/magiskhide/proc_monitor.cpp +++ b/native/jni/magiskhide/proc_monitor.cpp @@ -33,11 +33,11 @@ pthread_mutex_t monitor_lock; #define PID_MAX 32768 struct pid_set { - bitset::const_reference operator[](size_t pos) const { return set[pos - 1]; } - bitset::reference operator[](size_t pos) { return set[pos - 1]; } - void reset() { set.reset(); } + bitset::const_reference operator[](size_t pos) const { return set[pos - 1]; } + bitset::reference operator[](size_t pos) { return set[pos - 1]; } + void reset() { set.reset(); } private: - bitset set; + bitset set; }; // true if pid is monitored @@ -48,122 +48,122 @@ pid_set attaches; ********/ static inline int read_ns(const int pid, struct stat *st) { - char path[32]; - sprintf(path, "/proc/%d/ns/mnt", pid); - return stat(path, st); + char path[32]; + sprintf(path, "/proc/%d/ns/mnt", pid); + return stat(path, st); } static int parse_ppid(int pid) { - char path[32]; - int ppid; + char path[32]; + int ppid; - sprintf(path, "/proc/%d/stat", pid); + sprintf(path, "/proc/%d/stat", pid); - auto stat = open_file(path, "re"); - if (!stat) - return -1; + auto stat = open_file(path, "re"); + if (!stat) + return -1; - // PID COMM STATE PPID ..... - fscanf(stat.get(), "%*d %*s %*c %d", &ppid); + // PID COMM STATE PPID ..... + fscanf(stat.get(), "%*d %*s %*c %d", &ppid); - return ppid; + return ppid; } static inline long xptrace(int request, pid_t pid, void *addr, void *data) { - long ret = ptrace(request, pid, addr, data); - if (ret < 0) - PLOGE("ptrace %d", pid); - return ret; + long ret = ptrace(request, pid, addr, data); + if (ret < 0) + PLOGE("ptrace %d", pid); + return ret; } static inline long xptrace(int request, pid_t pid, void *addr = nullptr, intptr_t data = 0) { - return xptrace(request, pid, addr, reinterpret_cast(data)); + return xptrace(request, pid, addr, reinterpret_cast(data)); } void update_uid_map() { - mutex_guard lock(monitor_lock); - uid_proc_map.clear(); - string data_path(APP_DATA_DIR); - size_t len = data_path.length(); - auto dir = open_dir(APP_DATA_DIR); - bool first_iter = true; - for (dirent *entry; (entry = xreaddir(dir.get()));) { - data_path.resize(len); - data_path += '/'; - data_path += entry->d_name; // multiuser user id - data_path += '/'; - size_t user_len = data_path.length(); - struct stat st; - for (auto &hide : hide_set) { - if (hide.first == ISOLATED_MAGIC) { - if (!first_iter) continue; - // Setup isolated processes - uid_proc_map[-1].emplace_back(hide.second); - } - data_path.resize(user_len); - data_path += hide.first; - if (stat(data_path.data(), &st)) - continue; - uid_proc_map[st.st_uid].emplace_back(hide.second); - } - first_iter = false; - } + mutex_guard lock(monitor_lock); + uid_proc_map.clear(); + string data_path(APP_DATA_DIR); + size_t len = data_path.length(); + auto dir = open_dir(APP_DATA_DIR); + bool first_iter = true; + for (dirent *entry; (entry = xreaddir(dir.get()));) { + data_path.resize(len); + data_path += '/'; + data_path += entry->d_name; // multiuser user id + data_path += '/'; + size_t user_len = data_path.length(); + struct stat st; + for (auto &hide : hide_set) { + if (hide.first == ISOLATED_MAGIC) { + if (!first_iter) continue; + // Setup isolated processes + uid_proc_map[-1].emplace_back(hide.second); + } + data_path.resize(user_len); + data_path += hide.first; + if (stat(data_path.data(), &st)) + continue; + uid_proc_map[st.st_uid].emplace_back(hide.second); + } + first_iter = false; + } } static bool is_zygote_done() { #ifdef __LP64__ - return zygote_map.size() >= 2; + return zygote_map.size() >= 2; #else - return zygote_map.size() >= 1; + return zygote_map.size() >= 1; #endif } static void check_zygote() { - crawl_procfs([](int pid) -> bool { - char buf[512]; - snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); - if (FILE *f = fopen(buf, "re")) { - fgets(buf, sizeof(buf), f); - if (strncmp(buf, "zygote", 6) == 0 && parse_ppid(pid) == 1) - new_zygote(pid); - fclose(f); - } - return true; - }); - if (is_zygote_done()) { - // Stop periodic scanning - timeval val { .tv_sec = 0, .tv_usec = 0 }; - itimerval interval { .it_interval = val, .it_value = val }; - setitimer(ITIMER_REAL, &interval, nullptr); - } + crawl_procfs([](int pid) -> bool { + char buf[512]; + snprintf(buf, sizeof(buf), "/proc/%d/cmdline", pid); + if (FILE *f = fopen(buf, "re")) { + fgets(buf, sizeof(buf), f); + if (strncmp(buf, "zygote", 6) == 0 && parse_ppid(pid) == 1) + new_zygote(pid); + fclose(f); + } + return true; + }); + if (is_zygote_done()) { + // Stop periodic scanning + timeval val { .tv_sec = 0, .tv_usec = 0 }; + itimerval interval { .it_interval = val, .it_value = val }; + setitimer(ITIMER_REAL, &interval, nullptr); + } } #define APP_PROC "/system/bin/app_process" static void setup_inotify() { - inotify_fd = xinotify_init1(IN_CLOEXEC); - if (inotify_fd < 0) - term_thread(); + inotify_fd = xinotify_init1(IN_CLOEXEC); + if (inotify_fd < 0) + term_thread(); - // Setup inotify asynchronous I/O - fcntl(inotify_fd, F_SETFL, O_ASYNC); - struct f_owner_ex ex = { - .type = F_OWNER_TID, - .pid = gettid() - }; - fcntl(inotify_fd, F_SETOWN_EX, &ex); + // Setup inotify asynchronous I/O + fcntl(inotify_fd, F_SETFL, O_ASYNC); + struct f_owner_ex ex = { + .type = F_OWNER_TID, + .pid = gettid() + }; + fcntl(inotify_fd, F_SETOWN_EX, &ex); - // Monitor packages.xml - inotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE); + // Monitor packages.xml + inotify_add_watch(inotify_fd, "/data/system", IN_CLOSE_WRITE); - // Monitor app_process - if (access(APP_PROC "32", F_OK) == 0) { - inotify_add_watch(inotify_fd, APP_PROC "32", IN_ACCESS); - if (access(APP_PROC "64", F_OK) == 0) - inotify_add_watch(inotify_fd, APP_PROC "64", IN_ACCESS); - } else { - inotify_add_watch(inotify_fd, APP_PROC, IN_ACCESS); - } + // Monitor app_process + if (access(APP_PROC "32", F_OK) == 0) { + inotify_add_watch(inotify_fd, APP_PROC "32", IN_ACCESS); + if (access(APP_PROC "64", F_OK) == 0) + inotify_add_watch(inotify_fd, APP_PROC "64", IN_ACCESS); + } else { + inotify_add_watch(inotify_fd, APP_PROC, IN_ACCESS); + } } /************************ @@ -171,37 +171,37 @@ static void setup_inotify() { ************************/ static void inotify_event(int) { - /* Make sure we can actually read stuffs - * or else the whole thread will be blocked.*/ - struct pollfd pfd = { - .fd = inotify_fd, - .events = POLLIN, - .revents = 0 - }; - if (poll(&pfd, 1, 0) <= 0) - return; // Nothing to read - char buf[512]; - auto event = reinterpret_cast(buf); - read(inotify_fd, buf, sizeof(buf)); - if ((event->mask & IN_CLOSE_WRITE) && event->name == "packages.xml"sv) - update_uid_map(); - check_zygote(); + /* Make sure we can actually read stuffs + * or else the whole thread will be blocked.*/ + struct pollfd pfd = { + .fd = inotify_fd, + .events = POLLIN, + .revents = 0 + }; + if (poll(&pfd, 1, 0) <= 0) + return; // Nothing to read + char buf[512]; + auto event = reinterpret_cast(buf); + read(inotify_fd, buf, sizeof(buf)); + if ((event->mask & IN_CLOSE_WRITE) && event->name == "packages.xml"sv) + update_uid_map(); + check_zygote(); } // Workaround for the lack of pthread_cancel static void term_thread(int) { - LOGD("proc_monitor: cleaning up\n"); - uid_proc_map.clear(); - zygote_map.clear(); - hide_set.clear(); - attaches.reset(); - // Misc - set_hide_state(false); - pthread_mutex_destroy(&monitor_lock); - close(inotify_fd); - inotify_fd = -1; - LOGD("proc_monitor: terminate\n"); - pthread_exit(nullptr); + LOGD("proc_monitor: cleaning up\n"); + uid_proc_map.clear(); + zygote_map.clear(); + hide_set.clear(); + attaches.reset(); + // Misc + set_hide_state(false); + pthread_mutex_destroy(&monitor_lock); + close(inotify_fd); + inotify_fd = -1; + LOGD("proc_monitor: terminate\n"); + pthread_exit(nullptr); } /****************** @@ -216,246 +216,246 @@ static void term_thread(int) { #define PTRACE_LOG(...) static void detach_pid(int pid, int signal = 0) { - attaches[pid] = false; - ptrace(PTRACE_DETACH, pid, 0, signal); - PTRACE_LOG("detach\n"); + attaches[pid] = false; + ptrace(PTRACE_DETACH, pid, 0, signal); + PTRACE_LOG("detach\n"); } static bool check_pid(int pid) { - char path[128]; - char cmdline[1024]; - struct stat st; + char path[128]; + char cmdline[1024]; + struct stat st; - sprintf(path, "/proc/%d", pid); - if (stat(path, &st)) { - // Process died unexpectedly, ignore - detach_pid(pid); - return true; - } + sprintf(path, "/proc/%d", pid); + if (stat(path, &st)) { + // Process died unexpectedly, ignore + detach_pid(pid); + return true; + } - // UID hasn't changed - if (st.st_uid == 0) - return false; + // UID hasn't changed + if (st.st_uid == 0) + return false; - sprintf(path, "/proc/%d/cmdline", pid); - if (auto f = open_file(path, "re")) { - fgets(cmdline, sizeof(cmdline), f.get()); - } else { - // Process died unexpectedly, ignore - detach_pid(pid); - return true; - } + sprintf(path, "/proc/%d/cmdline", pid); + if (auto f = open_file(path, "re")) { + fgets(cmdline, sizeof(cmdline), f.get()); + } else { + // Process died unexpectedly, ignore + detach_pid(pid); + return true; + } - if (cmdline == "zygote"sv || cmdline == "zygote32"sv || cmdline == "zygote64"sv || - cmdline == "usap32"sv || cmdline == "usap64"sv) - return false; + if (cmdline == "zygote"sv || cmdline == "zygote32"sv || cmdline == "zygote64"sv || + cmdline == "usap32"sv || cmdline == "usap64"sv) + return false; - int uid = st.st_uid; - auto it = uid_proc_map.end(); + int uid = st.st_uid; + auto it = uid_proc_map.end(); - if (uid % 100000 > 90000) { - // Isolated process - it = uid_proc_map.find(-1); - if (it == uid_proc_map.end()) - goto not_target; - for (auto &s : it->second) { - if (str_starts(cmdline, s)) { - LOGI("proc_monitor: (isolated) [%s] PID=[%d] UID=[%d]\n", cmdline, pid, uid); - goto inject_and_hide; - } - } - } + if (uid % 100000 > 90000) { + // Isolated process + it = uid_proc_map.find(-1); + if (it == uid_proc_map.end()) + goto not_target; + for (auto &s : it->second) { + if (str_starts(cmdline, s)) { + LOGI("proc_monitor: (isolated) [%s] PID=[%d] UID=[%d]\n", cmdline, pid, uid); + goto inject_and_hide; + } + } + } - it = uid_proc_map.find(uid); - if (it == uid_proc_map.end()) - goto not_target; - for (auto &s : it->second) { - if (s != cmdline) - continue; + it = uid_proc_map.find(uid); + if (it == uid_proc_map.end()) + goto not_target; + for (auto &s : it->second) { + if (s != cmdline) + continue; - if (str_ends(s, "_zygote")) { - LOGI("proc_monitor: (app zygote) [%s] PID=[%d] UID=[%d]\n", cmdline, pid, uid); - goto inject_and_hide; - } + if (str_ends(s, "_zygote")) { + LOGI("proc_monitor: (app zygote) [%s] PID=[%d] UID=[%d]\n", cmdline, pid, uid); + goto inject_and_hide; + } - // Double check whether ns is separated - read_ns(pid, &st); - for (auto &zit : zygote_map) { - if (zit.second.st_ino == st.st_ino && - zit.second.st_dev == st.st_dev) { - // For some reason ns is not separated, abort - goto not_target; - } - } + // Double check whether ns is separated + read_ns(pid, &st); + for (auto &zit : zygote_map) { + if (zit.second.st_ino == st.st_ino && + zit.second.st_dev == st.st_dev) { + // For some reason ns is not separated, abort + goto not_target; + } + } - // Finally this is our target! - // Detach from ptrace but should still remain stopped. - // The hide daemon will resume the process. - LOGI("proc_monitor: [%s] PID=[%d] UID=[%d]\n", cmdline, pid, uid); - detach_pid(pid, SIGSTOP); - hide_daemon(pid); - return true; - } + // Finally this is our target! + // Detach from ptrace but should still remain stopped. + // The hide daemon will resume the process. + LOGI("proc_monitor: [%s] PID=[%d] UID=[%d]\n", cmdline, pid, uid); + detach_pid(pid, SIGSTOP); + hide_daemon(pid); + return true; + } not_target: - PTRACE_LOG("[%s] is not our target\n", cmdline); - detach_pid(pid); - return true; + PTRACE_LOG("[%s] is not our target\n", cmdline); + detach_pid(pid); + return true; inject_and_hide: - // TODO: handle isolated processes and app zygotes - detach_pid(pid); - return true; + // TODO: handle isolated processes and app zygotes + detach_pid(pid); + return true; } static bool is_process(int pid) { - char buf[128]; - char key[32]; - int tgid; - sprintf(buf, "/proc/%d/status", pid); - auto fp = open_file(buf, "re"); - // PID is dead - if (!fp) - return false; - while (fgets(buf, sizeof(buf), fp.get())) { - sscanf(buf, "%s", key); - if (key == "Tgid:"sv) { - sscanf(buf, "%*s %d", &tgid); - return tgid == pid; - } - } - return false; + char buf[128]; + char key[32]; + int tgid; + sprintf(buf, "/proc/%d/status", pid); + auto fp = open_file(buf, "re"); + // PID is dead + if (!fp) + return false; + while (fgets(buf, sizeof(buf), fp.get())) { + sscanf(buf, "%s", key); + if (key == "Tgid:"sv) { + sscanf(buf, "%*s %d", &tgid); + return tgid == pid; + } + } + return false; } static void new_zygote(int pid) { - struct stat st; - if (read_ns(pid, &st)) - return; + struct stat st; + if (read_ns(pid, &st)) + return; - auto it = zygote_map.find(pid); - if (it != zygote_map.end()) { - // Update namespace info - it->second = st; - return; - } + auto it = zygote_map.find(pid); + if (it != zygote_map.end()) { + // Update namespace info + it->second = st; + return; + } - LOGD("proc_monitor: ptrace zygote PID=[%d]\n", pid); - zygote_map[pid] = st; + LOGD("proc_monitor: ptrace zygote PID=[%d]\n", pid); + zygote_map[pid] = st; - xptrace(PTRACE_ATTACH, pid); + xptrace(PTRACE_ATTACH, pid); - waitpid(pid, nullptr, __WALL | __WNOTHREAD); - xptrace(PTRACE_SETOPTIONS, pid, nullptr, - PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXIT); - xptrace(PTRACE_CONT, pid); + waitpid(pid, nullptr, __WALL | __WNOTHREAD); + xptrace(PTRACE_SETOPTIONS, pid, nullptr, + PTRACE_O_TRACEFORK | PTRACE_O_TRACEVFORK | PTRACE_O_TRACEEXIT); + xptrace(PTRACE_CONT, pid); } #define WEVENT(s) (((s) & 0xffff0000) >> 16) #define DETACH_AND_CONT { detach_pid(pid); continue; } void proc_monitor() { - // Unblock some signals - sigset_t block_set; - sigemptyset(&block_set); - sigaddset(&block_set, SIGTERMTHRD); - sigaddset(&block_set, SIGIO); - sigaddset(&block_set, SIGALRM); - pthread_sigmask(SIG_UNBLOCK, &block_set, nullptr); + // Unblock some signals + sigset_t block_set; + sigemptyset(&block_set); + sigaddset(&block_set, SIGTERMTHRD); + sigaddset(&block_set, SIGIO); + sigaddset(&block_set, SIGALRM); + pthread_sigmask(SIG_UNBLOCK, &block_set, nullptr); - struct sigaction act{}; - act.sa_handler = term_thread; - sigaction(SIGTERMTHRD, &act, nullptr); - act.sa_handler = inotify_event; - sigaction(SIGIO, &act, nullptr); - act.sa_handler = [](int){ check_zygote(); }; - sigaction(SIGALRM, &act, nullptr); + struct sigaction act{}; + act.sa_handler = term_thread; + sigaction(SIGTERMTHRD, &act, nullptr); + act.sa_handler = inotify_event; + sigaction(SIGIO, &act, nullptr); + act.sa_handler = [](int){ check_zygote(); }; + sigaction(SIGALRM, &act, nullptr); - setup_inotify(); + setup_inotify(); - // First try find existing zygotes - check_zygote(); - if (!is_zygote_done()) { - // Periodic scan every 250ms - timeval val { .tv_sec = 0, .tv_usec = 250000 }; - itimerval interval { .it_interval = val, .it_value = val }; - setitimer(ITIMER_REAL, &interval, nullptr); - } + // First try find existing zygotes + check_zygote(); + if (!is_zygote_done()) { + // Periodic scan every 250ms + timeval val { .tv_sec = 0, .tv_usec = 250000 }; + itimerval interval { .it_interval = val, .it_value = val }; + setitimer(ITIMER_REAL, &interval, nullptr); + } - for (int status;;) { - const int pid = waitpid(-1, &status, __WALL | __WNOTHREAD); - if (pid < 0) { - if (errno == ECHILD) { - // Nothing to wait yet, sleep and wait till signal interruption - LOGD("proc_monitor: nothing to monitor, wait for signal\n"); - struct timespec ts = { - .tv_sec = INT_MAX, - .tv_nsec = 0 - }; - nanosleep(&ts, nullptr); - } - continue; - } + for (int status;;) { + const int pid = waitpid(-1, &status, __WALL | __WNOTHREAD); + if (pid < 0) { + if (errno == ECHILD) { + // Nothing to wait yet, sleep and wait till signal interruption + LOGD("proc_monitor: nothing to monitor, wait for signal\n"); + struct timespec ts = { + .tv_sec = INT_MAX, + .tv_nsec = 0 + }; + nanosleep(&ts, nullptr); + } + continue; + } - if (!WIFSTOPPED(status) /* Ignore if not ptrace-stop */) - DETACH_AND_CONT; + if (!WIFSTOPPED(status) /* Ignore if not ptrace-stop */) + DETACH_AND_CONT; - int event = WEVENT(status); - int signal = WSTOPSIG(status); + int event = WEVENT(status); + int signal = WSTOPSIG(status); - if (signal == SIGTRAP && event) { - unsigned long msg; - xptrace(PTRACE_GETEVENTMSG, pid, nullptr, &msg); - if (zygote_map.count(pid)) { - // Zygote event - switch (event) { - case PTRACE_EVENT_FORK: - case PTRACE_EVENT_VFORK: - PTRACE_LOG("zygote forked: [%lu]\n", msg); - attaches[msg] = true; - break; - case PTRACE_EVENT_EXIT: - PTRACE_LOG("zygote exited with status: [%lu]\n", msg); - [[fallthrough]]; - default: - zygote_map.erase(pid); - DETACH_AND_CONT; - } - } else { - switch (event) { - case PTRACE_EVENT_CLONE: - PTRACE_LOG("create new threads: [%lu]\n", msg); - if (attaches[pid] && check_pid(pid)) - continue; - break; - case PTRACE_EVENT_EXEC: - case PTRACE_EVENT_EXIT: - PTRACE_LOG("exit or execve\n"); - [[fallthrough]]; - default: - DETACH_AND_CONT; - } - } - xptrace(PTRACE_CONT, pid); - } else if (signal == SIGSTOP) { - if (!attaches[pid]) { - // Double check if this is actually a process - attaches[pid] = is_process(pid); - } - if (attaches[pid]) { - // This is a process, continue monitoring - PTRACE_LOG("SIGSTOP from child\n"); - xptrace(PTRACE_SETOPTIONS, pid, nullptr, - PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT); - xptrace(PTRACE_CONT, pid); - } else { - // This is a thread, do NOT monitor - PTRACE_LOG("SIGSTOP from thread\n"); - DETACH_AND_CONT; - } - } else { - // Not caused by us, resend signal - xptrace(PTRACE_CONT, pid, nullptr, signal); - PTRACE_LOG("signal [%d]\n", signal); - } - } + if (signal == SIGTRAP && event) { + unsigned long msg; + xptrace(PTRACE_GETEVENTMSG, pid, nullptr, &msg); + if (zygote_map.count(pid)) { + // Zygote event + switch (event) { + case PTRACE_EVENT_FORK: + case PTRACE_EVENT_VFORK: + PTRACE_LOG("zygote forked: [%lu]\n", msg); + attaches[msg] = true; + break; + case PTRACE_EVENT_EXIT: + PTRACE_LOG("zygote exited with status: [%lu]\n", msg); + [[fallthrough]]; + default: + zygote_map.erase(pid); + DETACH_AND_CONT; + } + } else { + switch (event) { + case PTRACE_EVENT_CLONE: + PTRACE_LOG("create new threads: [%lu]\n", msg); + if (attaches[pid] && check_pid(pid)) + continue; + break; + case PTRACE_EVENT_EXEC: + case PTRACE_EVENT_EXIT: + PTRACE_LOG("exit or execve\n"); + [[fallthrough]]; + default: + DETACH_AND_CONT; + } + } + xptrace(PTRACE_CONT, pid); + } else if (signal == SIGSTOP) { + if (!attaches[pid]) { + // Double check if this is actually a process + attaches[pid] = is_process(pid); + } + if (attaches[pid]) { + // This is a process, continue monitoring + PTRACE_LOG("SIGSTOP from child\n"); + xptrace(PTRACE_SETOPTIONS, pid, nullptr, + PTRACE_O_TRACECLONE | PTRACE_O_TRACEEXEC | PTRACE_O_TRACEEXIT); + xptrace(PTRACE_CONT, pid); + } else { + // This is a thread, do NOT monitor + PTRACE_LOG("SIGSTOP from thread\n"); + DETACH_AND_CONT; + } + } else { + // Not caused by us, resend signal + xptrace(PTRACE_CONT, pid, nullptr, signal); + PTRACE_LOG("signal [%d]\n", signal); + } + } } diff --git a/native/jni/magiskpolicy/magiskpolicy.cpp b/native/jni/magiskpolicy/magiskpolicy.cpp index 9897364d5..4e999503d 100644 --- a/native/jni/magiskpolicy/magiskpolicy.cpp +++ b/native/jni/magiskpolicy/magiskpolicy.cpp @@ -6,7 +6,7 @@ using namespace std::literals; [[noreturn]] static void usage(char *arg0) { - fprintf(stderr, + fprintf(stderr, R"EOF(MagiskPolicy - Sepolicy Patch Tool Usage: %s [--options...] [policy statements...] @@ -28,93 +28,93 @@ If neither --load or --compile-split is specified, it will load from current live policies (/sys/fs/selinux/policy) )EOF", arg0); - exit(1); + exit(1); } int magiskpolicy_main(int argc, char *argv[]) { - cmdline_logging(); - const char *out_file = nullptr; - const char *rule_file = nullptr; - sepolicy *sepol = nullptr; - bool magisk = false; - bool live = false; + cmdline_logging(); + const char *out_file = nullptr; + const char *rule_file = nullptr; + sepolicy *sepol = nullptr; + bool magisk = false; + bool live = false; - if (argc < 2) usage(argv[0]); - int i = 1; - for (; i < argc; ++i) { - // Parse options - if (argv[i][0] == '-' && argv[i][1] == '-') { - auto option = argv[i] + 2; - if (option == "live"sv) - live = true; - else if (option == "magisk"sv) - magisk = true; - else if (option == "load"sv) { - if (argv[i + 1] == nullptr) - usage(argv[0]); - sepol = sepolicy::from_file(argv[i + 1]); - if (!sepol) { - fprintf(stderr, "Cannot load policy from %s\n", argv[i + 1]); - return 1; - } - ++i; - } else if (option == "load-split"sv) { - sepol = sepolicy::from_split(); - if (!sepol) { - fprintf(stderr, "Cannot load split cil\n"); - return 1; - } - } else if (option == "compile-split"sv) { - sepol = sepolicy::compile_split(); - if (!sepol) { - fprintf(stderr, "Cannot compile split cil\n"); - return 1; - } - } else if (option == "save"sv) { - if (argv[i + 1] == nullptr) - usage(argv[0]); - out_file = argv[i + 1]; - ++i; - } else if (option == "apply"sv) { - if (argv[i + 1] == nullptr) - usage(argv[0]); - rule_file = argv[i + 1]; - ++i; - } else if (option == "help"sv) { - statement_help(); - } else { - usage(argv[0]); - } - } else { - break; - } - } + if (argc < 2) usage(argv[0]); + int i = 1; + for (; i < argc; ++i) { + // Parse options + if (argv[i][0] == '-' && argv[i][1] == '-') { + auto option = argv[i] + 2; + if (option == "live"sv) + live = true; + else if (option == "magisk"sv) + magisk = true; + else if (option == "load"sv) { + if (argv[i + 1] == nullptr) + usage(argv[0]); + sepol = sepolicy::from_file(argv[i + 1]); + if (!sepol) { + fprintf(stderr, "Cannot load policy from %s\n", argv[i + 1]); + return 1; + } + ++i; + } else if (option == "load-split"sv) { + sepol = sepolicy::from_split(); + if (!sepol) { + fprintf(stderr, "Cannot load split cil\n"); + return 1; + } + } else if (option == "compile-split"sv) { + sepol = sepolicy::compile_split(); + if (!sepol) { + fprintf(stderr, "Cannot compile split cil\n"); + return 1; + } + } else if (option == "save"sv) { + if (argv[i + 1] == nullptr) + usage(argv[0]); + out_file = argv[i + 1]; + ++i; + } else if (option == "apply"sv) { + if (argv[i + 1] == nullptr) + usage(argv[0]); + rule_file = argv[i + 1]; + ++i; + } else if (option == "help"sv) { + statement_help(); + } else { + usage(argv[0]); + } + } else { + break; + } + } - // Use current policy if nothing is loaded - if (sepol == nullptr && !(sepol = sepolicy::from_file(SELINUX_POLICY))) { - fprintf(stderr, "Cannot load policy from " SELINUX_POLICY "\n"); - return 1; - } + // Use current policy if nothing is loaded + if (sepol == nullptr && !(sepol = sepolicy::from_file(SELINUX_POLICY))) { + fprintf(stderr, "Cannot load policy from " SELINUX_POLICY "\n"); + return 1; + } - if (magisk) - sepol->magisk_rules(); + if (magisk) + sepol->magisk_rules(); - if (rule_file) - sepol->load_rule_file(rule_file); + if (rule_file) + sepol->load_rule_file(rule_file); - for (; i < argc; ++i) - sepol->parse_statement(argv[i]); + for (; i < argc; ++i) + sepol->parse_statement(argv[i]); - if (live && !sepol->to_file(SELINUX_LOAD)) { - fprintf(stderr, "Cannot apply policy\n"); - return 1; - } + if (live && !sepol->to_file(SELINUX_LOAD)) { + fprintf(stderr, "Cannot apply policy\n"); + return 1; + } - if (out_file && !sepol->to_file(out_file)) { - fprintf(stderr, "Cannot dump policy to %s\n", out_file); - return 1; - } + if (out_file && !sepol->to_file(out_file)) { + fprintf(stderr, "Cannot dump policy to %s\n", out_file); + return 1; + } - delete sepol; - return 0; + delete sepol; + return 0; } diff --git a/native/jni/magiskpolicy/policydb.cpp b/native/jni/magiskpolicy/policydb.cpp index d444d1ccd..8a838769e 100644 --- a/native/jni/magiskpolicy/policydb.cpp +++ b/native/jni/magiskpolicy/policydb.cpp @@ -13,218 +13,218 @@ #define SHALEN 64 static bool cmp_sha256(const char *a, const char *b) { - char id_a[SHALEN] = {0}; - char id_b[SHALEN] = {0}; - if (int fd = xopen(a, O_RDONLY | O_CLOEXEC); fd >= 0) { - xread(fd, id_a, SHALEN); - close(fd); - } else { - return false; - } + char id_a[SHALEN] = {0}; + char id_b[SHALEN] = {0}; + if (int fd = xopen(a, O_RDONLY | O_CLOEXEC); fd >= 0) { + xread(fd, id_a, SHALEN); + close(fd); + } else { + return false; + } - if (int fd = xopen(b, O_RDONLY | O_CLOEXEC); fd >= 0) { - xread(fd, id_b, SHALEN); - close(fd); - } else { - return false; - } - LOGD("%s=[%.*s]\n", a, SHALEN, id_a); - LOGD("%s=[%.*s]\n", b, SHALEN, id_b); - return memcmp(id_a, id_b, SHALEN) == 0; + if (int fd = xopen(b, O_RDONLY | O_CLOEXEC); fd >= 0) { + xread(fd, id_b, SHALEN); + close(fd); + } else { + return false; + } + LOGD("%s=[%.*s]\n", a, SHALEN, id_a); + LOGD("%s=[%.*s]\n", b, SHALEN, id_b); + return memcmp(id_a, id_b, SHALEN) == 0; } static bool check_precompiled(const char *precompiled) { - bool ok = false; - const char *actual_sha; - char compiled_sha[128]; + bool ok = false; + const char *actual_sha; + char compiled_sha[128]; - actual_sha = PLAT_POLICY_DIR "plat_and_mapping_sepolicy.cil.sha256"; - if (access(actual_sha, R_OK) == 0) { - ok = true; - sprintf(compiled_sha, "%s.plat_and_mapping.sha256", precompiled); - if (!cmp_sha256(actual_sha, compiled_sha)) - return false; - } + actual_sha = PLAT_POLICY_DIR "plat_and_mapping_sepolicy.cil.sha256"; + if (access(actual_sha, R_OK) == 0) { + ok = true; + sprintf(compiled_sha, "%s.plat_and_mapping.sha256", precompiled); + if (!cmp_sha256(actual_sha, compiled_sha)) + return false; + } - actual_sha = PLAT_POLICY_DIR "plat_sepolicy_and_mapping.sha256"; - if (access(actual_sha, R_OK) == 0) { - ok = true; - sprintf(compiled_sha, "%s.plat_sepolicy_and_mapping.sha256", precompiled); - if (!cmp_sha256(actual_sha, compiled_sha)) - return false; - } + actual_sha = PLAT_POLICY_DIR "plat_sepolicy_and_mapping.sha256"; + if (access(actual_sha, R_OK) == 0) { + ok = true; + sprintf(compiled_sha, "%s.plat_sepolicy_and_mapping.sha256", precompiled); + if (!cmp_sha256(actual_sha, compiled_sha)) + return false; + } - actual_sha = PROD_POLICY_DIR "product_sepolicy_and_mapping.sha256"; - if (access(actual_sha, R_OK) == 0) { - ok = true; - sprintf(compiled_sha, "%s.product_sepolicy_and_mapping.sha256", precompiled); - if (!cmp_sha256(actual_sha, compiled_sha) != 0) - return false; - } + actual_sha = PROD_POLICY_DIR "product_sepolicy_and_mapping.sha256"; + if (access(actual_sha, R_OK) == 0) { + ok = true; + sprintf(compiled_sha, "%s.product_sepolicy_and_mapping.sha256", precompiled); + if (!cmp_sha256(actual_sha, compiled_sha) != 0) + return false; + } - actual_sha = SYSEXT_POLICY_DIR "system_ext_sepolicy_and_mapping.sha256"; - if (access(actual_sha, R_OK) == 0) { - ok = true; - sprintf(compiled_sha, "%s.system_ext_sepolicy_and_mapping.sha256", precompiled); - if (!cmp_sha256(actual_sha, compiled_sha) != 0) - return false; - } + actual_sha = SYSEXT_POLICY_DIR "system_ext_sepolicy_and_mapping.sha256"; + if (access(actual_sha, R_OK) == 0) { + ok = true; + sprintf(compiled_sha, "%s.system_ext_sepolicy_and_mapping.sha256", precompiled); + if (!cmp_sha256(actual_sha, compiled_sha) != 0) + return false; + } - return ok; + return ok; } static void load_cil(struct cil_db *db, const char *file) { - char *addr; - size_t size; - mmap_ro(file, addr, size); - cil_add_file(db, (char *) file, addr, size); - LOGD("cil_add [%s]\n", file); - munmap(addr, size); + char *addr; + size_t size; + mmap_ro(file, addr, size); + cil_add_file(db, (char *) file, addr, size); + LOGD("cil_add [%s]\n", file); + munmap(addr, size); } sepolicy *sepolicy::from_file(const char *file) { - LOGD("Load policy from: %s\n", file); + LOGD("Load policy from: %s\n", file); - policy_file_t pf; - policy_file_init(&pf); - auto fp = xopen_file(file, "re"); - pf.fp = fp.get(); - pf.type = PF_USE_STDIO; + policy_file_t pf; + policy_file_init(&pf); + auto fp = xopen_file(file, "re"); + pf.fp = fp.get(); + pf.type = PF_USE_STDIO; - auto db = static_cast(xmalloc(sizeof(policydb_t))); - if (policydb_init(db) || policydb_read(db, &pf, 0)) { - LOGE("Fail to load policy from %s\n", file); - free(db); - return nullptr; - } + auto db = static_cast(xmalloc(sizeof(policydb_t))); + if (policydb_init(db) || policydb_read(db, &pf, 0)) { + LOGE("Fail to load policy from %s\n", file); + free(db); + return nullptr; + } - auto sepol = new sepolicy(); - sepol->db = db; - return sepol; + auto sepol = new sepolicy(); + sepol->db = db; + return sepol; } sepolicy *sepolicy::compile_split() { - char path[128], plat_ver[10]; - cil_db_t *db = nullptr; - sepol_policydb_t *pdb = nullptr; - FILE *f; - int policy_ver; - const char *cil_file; + char path[128], plat_ver[10]; + cil_db_t *db = nullptr; + sepol_policydb_t *pdb = nullptr; + FILE *f; + int policy_ver; + const char *cil_file; - cil_db_init(&db); - run_finally fin([db_ptr = &db]{ cil_db_destroy(db_ptr); }); - cil_set_mls(db, 1); - cil_set_multiple_decls(db, 1); - cil_set_disable_neverallow(db, 1); - cil_set_target_platform(db, SEPOL_TARGET_SELINUX); - cil_set_attrs_expand_generated(db, 0); + cil_db_init(&db); + run_finally fin([db_ptr = &db]{ cil_db_destroy(db_ptr); }); + cil_set_mls(db, 1); + cil_set_multiple_decls(db, 1); + cil_set_disable_neverallow(db, 1); + cil_set_target_platform(db, SEPOL_TARGET_SELINUX); + cil_set_attrs_expand_generated(db, 0); - f = xfopen(SELINUX_VERSION, "re"); - fscanf(f, "%d", &policy_ver); - fclose(f); - cil_set_policy_version(db, policy_ver); + f = xfopen(SELINUX_VERSION, "re"); + fscanf(f, "%d", &policy_ver); + fclose(f); + cil_set_policy_version(db, policy_ver); - // Get mapping version - f = xfopen(VEND_POLICY_DIR "plat_sepolicy_vers.txt", "re"); - fscanf(f, "%s", plat_ver); - fclose(f); + // Get mapping version + f = xfopen(VEND_POLICY_DIR "plat_sepolicy_vers.txt", "re"); + fscanf(f, "%s", plat_ver); + fclose(f); - // plat - load_cil(db, SPLIT_PLAT_CIL); + // plat + load_cil(db, SPLIT_PLAT_CIL); - sprintf(path, PLAT_POLICY_DIR "mapping/%s.cil", plat_ver); - load_cil(db, path); + sprintf(path, PLAT_POLICY_DIR "mapping/%s.cil", plat_ver); + load_cil(db, path); - sprintf(path, PLAT_POLICY_DIR "mapping/%s.compat.cil", plat_ver); - if (access(path, R_OK) == 0) - load_cil(db, path); + sprintf(path, PLAT_POLICY_DIR "mapping/%s.compat.cil", plat_ver); + if (access(path, R_OK) == 0) + load_cil(db, path); - // system_ext - sprintf(path, SYSEXT_POLICY_DIR "mapping/%s.cil", plat_ver); - if (access(path, R_OK) == 0) - load_cil(db, path); + // system_ext + sprintf(path, SYSEXT_POLICY_DIR "mapping/%s.cil", plat_ver); + if (access(path, R_OK) == 0) + load_cil(db, path); - cil_file = SYSEXT_POLICY_DIR "system_ext_sepolicy.cil"; - if (access(cil_file, R_OK) == 0) - load_cil(db, cil_file); + cil_file = SYSEXT_POLICY_DIR "system_ext_sepolicy.cil"; + if (access(cil_file, R_OK) == 0) + load_cil(db, cil_file); - // product - sprintf(path, PROD_POLICY_DIR "mapping/%s.cil", plat_ver); - if (access(path, R_OK) == 0) - load_cil(db, path); + // product + sprintf(path, PROD_POLICY_DIR "mapping/%s.cil", plat_ver); + if (access(path, R_OK) == 0) + load_cil(db, path); - cil_file = PROD_POLICY_DIR "product_sepolicy.cil"; - if (access(cil_file, R_OK) == 0) - load_cil(db, cil_file); + cil_file = PROD_POLICY_DIR "product_sepolicy.cil"; + if (access(cil_file, R_OK) == 0) + load_cil(db, cil_file); - // vendor - cil_file = VEND_POLICY_DIR "nonplat_sepolicy.cil"; - if (access(cil_file, R_OK) == 0) - load_cil(db, cil_file); + // vendor + cil_file = VEND_POLICY_DIR "nonplat_sepolicy.cil"; + if (access(cil_file, R_OK) == 0) + load_cil(db, cil_file); - cil_file = VEND_POLICY_DIR "plat_pub_versioned.cil"; - if (access(cil_file, R_OK) == 0) - load_cil(db, cil_file); + cil_file = VEND_POLICY_DIR "plat_pub_versioned.cil"; + if (access(cil_file, R_OK) == 0) + load_cil(db, cil_file); - cil_file = VEND_POLICY_DIR "vendor_sepolicy.cil"; - if (access(cil_file, R_OK) == 0) - load_cil(db, cil_file); + cil_file = VEND_POLICY_DIR "vendor_sepolicy.cil"; + if (access(cil_file, R_OK) == 0) + load_cil(db, cil_file); - // odm - cil_file = ODM_POLICY_DIR "odm_sepolicy.cil"; - if (access(cil_file, R_OK) == 0) - load_cil(db, cil_file); + // odm + cil_file = ODM_POLICY_DIR "odm_sepolicy.cil"; + if (access(cil_file, R_OK) == 0) + load_cil(db, cil_file); - if (cil_compile(db)) - return nullptr; - if (cil_build_policydb(db, &pdb)) - return nullptr; + if (cil_compile(db)) + return nullptr; + if (cil_build_policydb(db, &pdb)) + return nullptr; - auto sepol = new sepolicy(); - sepol->db = &pdb->p; - return sepol; + auto sepol = new sepolicy(); + sepol->db = &pdb->p; + return sepol; } sepolicy *sepolicy::from_split() { - const char *odm_pre = ODM_POLICY_DIR "precompiled_sepolicy"; - const char *vend_pre = VEND_POLICY_DIR "precompiled_sepolicy"; - if (access(odm_pre, R_OK) == 0 && check_precompiled(odm_pre)) - return sepolicy::from_file(odm_pre); - else if (access(vend_pre, R_OK) == 0 && check_precompiled(vend_pre)) - return sepolicy::from_file(vend_pre); - else - return sepolicy::compile_split(); + const char *odm_pre = ODM_POLICY_DIR "precompiled_sepolicy"; + const char *vend_pre = VEND_POLICY_DIR "precompiled_sepolicy"; + if (access(odm_pre, R_OK) == 0 && check_precompiled(odm_pre)) + return sepolicy::from_file(odm_pre); + else if (access(vend_pre, R_OK) == 0 && check_precompiled(vend_pre)) + return sepolicy::from_file(vend_pre); + else + return sepolicy::compile_split(); } sepolicy::~sepolicy() { - policydb_destroy(db); - free(db); + policydb_destroy(db); + free(db); } bool sepolicy::to_file(const char *file) { - uint8_t *data; - size_t len; + uint8_t *data; + size_t len; - /* No partial writes are allowed to /sys/fs/selinux/load, thus the reason why we - * first dump everything into memory, then directly call write system call */ + /* No partial writes are allowed to /sys/fs/selinux/load, thus the reason why we + * first dump everything into memory, then directly call write system call */ - auto fp = make_stream_fp(data, len); - run_finally fin([=]{ free(data); }); + auto fp = make_stream_fp(data, len); + run_finally fin([=]{ free(data); }); - policy_file_t pf; - policy_file_init(&pf); - pf.type = PF_USE_STDIO; - pf.fp = fp.get(); - if (policydb_write(db, &pf)) { - LOGE("Fail to create policy image\n"); - return false; - } + policy_file_t pf; + policy_file_init(&pf); + pf.type = PF_USE_STDIO; + pf.fp = fp.get(); + if (policydb_write(db, &pf)) { + LOGE("Fail to create policy image\n"); + return false; + } - int fd = xopen(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); - if (fd < 0) - return false; - xwrite(fd, data, len); + int fd = xopen(file, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0644); + if (fd < 0) + return false; + xwrite(fd, data, len); - close(fd); - return true; + close(fd); + return true; } diff --git a/native/jni/magiskpolicy/rules.cpp b/native/jni/magiskpolicy/rules.cpp index 3592a995f..6732d1e04 100644 --- a/native/jni/magiskpolicy/rules.cpp +++ b/native/jni/magiskpolicy/rules.cpp @@ -6,220 +6,220 @@ using namespace std; void sepolicy::magisk_rules() { - // Temp suppress warnings - auto bak = log_cb.w; - log_cb.w = nop_log; + // Temp suppress warnings + auto bak = log_cb.w; + log_cb.w = nop_log; - // This indicates API 26+ - bool new_rules = exists("untrusted_app_25"); + // This indicates API 26+ + bool new_rules = exists("untrusted_app_25"); - // Prevent anything to change sepolicy except ourselves - deny(ALL, "kernel", "security", "load_policy"); + // Prevent anything to change sepolicy except ourselves + deny(ALL, "kernel", "security", "load_policy"); - type(SEPOL_PROC_DOMAIN, "domain"); - permissive(SEPOL_PROC_DOMAIN); /* Just in case something is missing */ - typeattribute(SEPOL_PROC_DOMAIN, "mlstrustedsubject"); - typeattribute(SEPOL_PROC_DOMAIN, "netdomain"); - typeattribute(SEPOL_PROC_DOMAIN, "bluetoothdomain"); - type(SEPOL_FILE_TYPE, "file_type"); - typeattribute(SEPOL_FILE_TYPE, "mlstrustedobject"); + type(SEPOL_PROC_DOMAIN, "domain"); + permissive(SEPOL_PROC_DOMAIN); /* Just in case something is missing */ + typeattribute(SEPOL_PROC_DOMAIN, "mlstrustedsubject"); + typeattribute(SEPOL_PROC_DOMAIN, "netdomain"); + typeattribute(SEPOL_PROC_DOMAIN, "bluetoothdomain"); + type(SEPOL_FILE_TYPE, "file_type"); + typeattribute(SEPOL_FILE_TYPE, "mlstrustedobject"); - // Make our root domain unconstrained - allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL); - // Allow us to do any ioctl - if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) { - allowxperm(SEPOL_PROC_DOMAIN, ALL, "blk_file", ALL); - allowxperm(SEPOL_PROC_DOMAIN, ALL, "fifo_file", ALL); - } + // Make our root domain unconstrained + allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL); + // Allow us to do any ioctl + if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) { + allowxperm(SEPOL_PROC_DOMAIN, ALL, "blk_file", ALL); + allowxperm(SEPOL_PROC_DOMAIN, ALL, "fifo_file", ALL); + } - // Create unconstrained file type - allow(ALL, SEPOL_FILE_TYPE, "file", ALL); - allow(ALL, SEPOL_FILE_TYPE, "dir", ALL); - allow(ALL, SEPOL_FILE_TYPE, "fifo_file", ALL); - allow(ALL, SEPOL_FILE_TYPE, "chr_file", ALL); + // Create unconstrained file type + allow(ALL, SEPOL_FILE_TYPE, "file", ALL); + allow(ALL, SEPOL_FILE_TYPE, "dir", ALL); + allow(ALL, SEPOL_FILE_TYPE, "fifo_file", ALL); + allow(ALL, SEPOL_FILE_TYPE, "chr_file", ALL); - if (new_rules) { - // Make client type literally untrusted_app - type(SEPOL_CLIENT_DOMAIN, "domain"); - typeattribute(SEPOL_CLIENT_DOMAIN, "coredomain"); - typeattribute(SEPOL_CLIENT_DOMAIN, "appdomain"); - typeattribute(SEPOL_CLIENT_DOMAIN, "untrusted_app_all"); - typeattribute(SEPOL_CLIENT_DOMAIN, "netdomain"); - typeattribute(SEPOL_CLIENT_DOMAIN, "bluetoothdomain"); + if (new_rules) { + // Make client type literally untrusted_app + type(SEPOL_CLIENT_DOMAIN, "domain"); + typeattribute(SEPOL_CLIENT_DOMAIN, "coredomain"); + typeattribute(SEPOL_CLIENT_DOMAIN, "appdomain"); + typeattribute(SEPOL_CLIENT_DOMAIN, "untrusted_app_all"); + typeattribute(SEPOL_CLIENT_DOMAIN, "netdomain"); + typeattribute(SEPOL_CLIENT_DOMAIN, "bluetoothdomain"); - type(SEPOL_EXEC_TYPE, "file_type"); - typeattribute(SEPOL_EXEC_TYPE, "exec_type"); + type(SEPOL_EXEC_TYPE, "file_type"); + typeattribute(SEPOL_EXEC_TYPE, "exec_type"); - // Basic su client needs - allow(SEPOL_CLIENT_DOMAIN, SEPOL_EXEC_TYPE, "file", ALL); - allow(SEPOL_CLIENT_DOMAIN, SEPOL_CLIENT_DOMAIN, ALL, ALL); + // Basic su client needs + allow(SEPOL_CLIENT_DOMAIN, SEPOL_EXEC_TYPE, "file", ALL); + allow(SEPOL_CLIENT_DOMAIN, SEPOL_CLIENT_DOMAIN, ALL, ALL); - const char *pts[] { - "devpts", "untrusted_app_devpts", - "untrusted_app_25_devpts", "untrusted_app_all_devpts" }; - for (auto type : pts) { - allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "open"); - allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "getattr"); - allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "read"); - allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "write"); - allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "ioctl"); - allowxperm(SEPOL_CLIENT_DOMAIN, type, "chr_file", "0x5400-0x54FF"); - } + const char *pts[] { + "devpts", "untrusted_app_devpts", + "untrusted_app_25_devpts", "untrusted_app_all_devpts" }; + for (auto type : pts) { + allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "open"); + allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "getattr"); + allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "read"); + allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "write"); + allow(SEPOL_CLIENT_DOMAIN, type, "chr_file", "ioctl"); + allowxperm(SEPOL_CLIENT_DOMAIN, type, "chr_file", "0x5400-0x54FF"); + } - // Allow these processes to access MagiskSU - vector clients{ "init", "shell", "update_engine", "appdomain" }; - for (auto type : clients) { - if (!exists(type)) - continue; - // exec magisk - allow(type, SEPOL_EXEC_TYPE, "file", "read"); - allow(type, SEPOL_EXEC_TYPE, "file", "open"); - allow(type, SEPOL_EXEC_TYPE, "file", "getattr"); - allow(type, SEPOL_EXEC_TYPE, "file", "execute"); - allow(SEPOL_CLIENT_DOMAIN, type, "process", "sigchld"); + // Allow these processes to access MagiskSU + vector clients{ "init", "shell", "update_engine", "appdomain" }; + for (auto type : clients) { + if (!exists(type)) + continue; + // exec magisk + allow(type, SEPOL_EXEC_TYPE, "file", "read"); + allow(type, SEPOL_EXEC_TYPE, "file", "open"); + allow(type, SEPOL_EXEC_TYPE, "file", "getattr"); + allow(type, SEPOL_EXEC_TYPE, "file", "execute"); + allow(SEPOL_CLIENT_DOMAIN, type, "process", "sigchld"); - // Auto transit to client domain - allow(type, SEPOL_CLIENT_DOMAIN, "process", "transition"); - dontaudit(type, SEPOL_CLIENT_DOMAIN, "process", "siginh"); - dontaudit(type, SEPOL_CLIENT_DOMAIN, "process", "rlimitinh"); - dontaudit(type, SEPOL_CLIENT_DOMAIN, "process", "noatsecure"); + // Auto transit to client domain + allow(type, SEPOL_CLIENT_DOMAIN, "process", "transition"); + dontaudit(type, SEPOL_CLIENT_DOMAIN, "process", "siginh"); + dontaudit(type, SEPOL_CLIENT_DOMAIN, "process", "rlimitinh"); + dontaudit(type, SEPOL_CLIENT_DOMAIN, "process", "noatsecure"); - // Kill client process - allow(type, SEPOL_CLIENT_DOMAIN, "process", "signal"); - } + // Kill client process + allow(type, SEPOL_CLIENT_DOMAIN, "process", "signal"); + } - // type transition require actual types, not attributes - const char *app_types[] { - "system_app", "priv_app", "platform_app", "untrusted_app", - "untrusted_app_25", "untrusted_app_27", "untrusted_app_29" }; - clients.pop_back(); - clients.insert(clients.end(), app_types, app_types + std::size(app_types)); - for (auto type : clients) { - // Auto transit to client domain - type_transition(type, SEPOL_EXEC_TYPE, "process", SEPOL_CLIENT_DOMAIN); - } + // type transition require actual types, not attributes + const char *app_types[] { + "system_app", "priv_app", "platform_app", "untrusted_app", + "untrusted_app_25", "untrusted_app_27", "untrusted_app_29" }; + clients.pop_back(); + clients.insert(clients.end(), app_types, app_types + std::size(app_types)); + for (auto type : clients) { + // Auto transit to client domain + type_transition(type, SEPOL_EXEC_TYPE, "process", SEPOL_CLIENT_DOMAIN); + } - // Allow system_server to manage magisk_client - allow("system_server", SEPOL_CLIENT_DOMAIN, "process", "getpgid"); - allow("system_server", SEPOL_CLIENT_DOMAIN, "process", "sigkill"); + // Allow system_server to manage magisk_client + allow("system_server", SEPOL_CLIENT_DOMAIN, "process", "getpgid"); + allow("system_server", SEPOL_CLIENT_DOMAIN, "process", "sigkill"); - // Don't allow pesky processes to monitor audit deny logs when poking magisk daemon socket - dontaudit(ALL, SEPOL_PROC_DOMAIN, "unix_stream_socket", ALL); + // Don't allow pesky processes to monitor audit deny logs when poking magisk daemon socket + dontaudit(ALL, SEPOL_PROC_DOMAIN, "unix_stream_socket", ALL); - // Only allow client processes to connect to magisk daemon socket - allow(SEPOL_CLIENT_DOMAIN, SEPOL_PROC_DOMAIN, "unix_stream_socket", ALL); - } else { - // Fallback to poking holes in sandbox as Android 4.3 to 7.1 set PR_SET_NO_NEW_PRIVS + // Only allow client processes to connect to magisk daemon socket + allow(SEPOL_CLIENT_DOMAIN, SEPOL_PROC_DOMAIN, "unix_stream_socket", ALL); + } else { + // Fallback to poking holes in sandbox as Android 4.3 to 7.1 set PR_SET_NO_NEW_PRIVS - // Allow these processes to access MagiskSU - const char *clients[] { "init", "shell", "appdomain" }; - for (auto type : clients) { - if (!exists(type)) - continue; - allow(type, SEPOL_PROC_DOMAIN, "unix_stream_socket", "connectto"); - allow(type, SEPOL_PROC_DOMAIN, "unix_stream_socket", "getopt"); + // Allow these processes to access MagiskSU + const char *clients[] { "init", "shell", "appdomain" }; + for (auto type : clients) { + if (!exists(type)) + continue; + allow(type, SEPOL_PROC_DOMAIN, "unix_stream_socket", "connectto"); + allow(type, SEPOL_PROC_DOMAIN, "unix_stream_socket", "getopt"); - // Allow termios ioctl - const char *pts[] { "devpts", "untrusted_app_devpts" }; - for (auto pts_type : pts) { - allow(type, pts_type, "chr_file", "ioctl"); - if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) - allowxperm(type, pts_type, "chr_file", "0x5400-0x54FF"); - } - } - } + // Allow termios ioctl + const char *pts[] { "devpts", "untrusted_app_devpts" }; + for (auto pts_type : pts) { + allow(type, pts_type, "chr_file", "ioctl"); + if (db->policyvers >= POLICYDB_VERSION_XPERMS_IOCTL) + allowxperm(type, pts_type, "chr_file", "0x5400-0x54FF"); + } + } + } - // Let everyone access tmpfs files (for SAR sbin overlay) - allow(ALL, "tmpfs", "file", ALL); + // Let everyone access tmpfs files (for SAR sbin overlay) + allow(ALL, "tmpfs", "file", ALL); - // For relabelling files - allow("rootfs", "labeledfs", "filesystem", "associate"); - allow(SEPOL_FILE_TYPE, "pipefs", "filesystem", "associate"); - allow(SEPOL_FILE_TYPE, "devpts", "filesystem", "associate"); + // For relabelling files + allow("rootfs", "labeledfs", "filesystem", "associate"); + allow(SEPOL_FILE_TYPE, "pipefs", "filesystem", "associate"); + allow(SEPOL_FILE_TYPE, "devpts", "filesystem", "associate"); - // Let init transit to SEPOL_PROC_DOMAIN - allow("kernel", "kernel", "process", "setcurrent"); - allow("kernel", SEPOL_PROC_DOMAIN, "process", "dyntransition"); + // Let init transit to SEPOL_PROC_DOMAIN + allow("kernel", "kernel", "process", "setcurrent"); + allow("kernel", SEPOL_PROC_DOMAIN, "process", "dyntransition"); - // Let init run stuffs - allow("kernel", SEPOL_PROC_DOMAIN, "fd", "use"); - allow("init", SEPOL_PROC_DOMAIN, "process", ALL); - allow("init", "tmpfs", "file", "getattr"); - allow("init", "tmpfs", "file", "execute"); + // Let init run stuffs + allow("kernel", SEPOL_PROC_DOMAIN, "fd", "use"); + allow("init", SEPOL_PROC_DOMAIN, "process", ALL); + allow("init", "tmpfs", "file", "getattr"); + allow("init", "tmpfs", "file", "execute"); - // suRights - allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "search"); - allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "read"); - allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "open"); - allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "read"); - allow("servicemanager", SEPOL_PROC_DOMAIN, "process", "getattr"); - allow("servicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer"); - allow(ALL, SEPOL_PROC_DOMAIN, "process", "sigchld"); + // suRights + allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "search"); + allow("servicemanager", SEPOL_PROC_DOMAIN, "dir", "read"); + allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "open"); + allow("servicemanager", SEPOL_PROC_DOMAIN, "file", "read"); + allow("servicemanager", SEPOL_PROC_DOMAIN, "process", "getattr"); + allow("servicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer"); + allow(ALL, SEPOL_PROC_DOMAIN, "process", "sigchld"); - // allowLog - allow("logd", SEPOL_PROC_DOMAIN, "dir", "search"); - allow("logd", SEPOL_PROC_DOMAIN, "file", "read"); - allow("logd", SEPOL_PROC_DOMAIN, "file", "open"); - allow("logd", SEPOL_PROC_DOMAIN, "file", "getattr"); + // allowLog + allow("logd", SEPOL_PROC_DOMAIN, "dir", "search"); + allow("logd", SEPOL_PROC_DOMAIN, "file", "read"); + allow("logd", SEPOL_PROC_DOMAIN, "file", "open"); + allow("logd", SEPOL_PROC_DOMAIN, "file", "getattr"); - // suBackL6 - allow("surfaceflinger", "app_data_file", "dir", ALL); - allow("surfaceflinger", "app_data_file", "file", ALL); - allow("surfaceflinger", "app_data_file", "lnk_file", ALL); - typeattribute("surfaceflinger", "mlstrustedsubject"); + // suBackL6 + allow("surfaceflinger", "app_data_file", "dir", ALL); + allow("surfaceflinger", "app_data_file", "file", ALL); + allow("surfaceflinger", "app_data_file", "lnk_file", ALL); + typeattribute("surfaceflinger", "mlstrustedsubject"); - // suMiscL6 - allow("audioserver", "audioserver", "process", "execmem"); + // suMiscL6 + allow("audioserver", "audioserver", "process", "execmem"); - // Liveboot - allow("surfaceflinger", SEPOL_PROC_DOMAIN, "process", "ptrace"); - allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "transfer"); - allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "call"); - allow("surfaceflinger", SEPOL_PROC_DOMAIN, "fd", "use"); - allow("debuggerd", SEPOL_PROC_DOMAIN, "process", "ptrace"); + // Liveboot + allow("surfaceflinger", SEPOL_PROC_DOMAIN, "process", "ptrace"); + allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "transfer"); + allow("surfaceflinger", SEPOL_PROC_DOMAIN, "binder", "call"); + allow("surfaceflinger", SEPOL_PROC_DOMAIN, "fd", "use"); + allow("debuggerd", SEPOL_PROC_DOMAIN, "process", "ptrace"); - // dumpsys - allow(ALL, SEPOL_PROC_DOMAIN, "fd", "use"); - allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "write"); - allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "read"); - allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "open"); - allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "getattr"); + // dumpsys + allow(ALL, SEPOL_PROC_DOMAIN, "fd", "use"); + allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "write"); + allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "read"); + allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "open"); + allow(ALL, SEPOL_PROC_DOMAIN, "fifo_file", "getattr"); - // bootctl - allow("hwservicemanager", SEPOL_PROC_DOMAIN, "dir", "search"); - allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "read"); - allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "open"); - allow("hwservicemanager", SEPOL_PROC_DOMAIN, "process", "getattr"); - allow("hwservicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer"); + // bootctl + allow("hwservicemanager", SEPOL_PROC_DOMAIN, "dir", "search"); + allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "read"); + allow("hwservicemanager", SEPOL_PROC_DOMAIN, "file", "open"); + allow("hwservicemanager", SEPOL_PROC_DOMAIN, "process", "getattr"); + allow("hwservicemanager", SEPOL_PROC_DOMAIN, "binder", "transfer"); - // For mounting loop devices, mirrors, tmpfs - allow("kernel", ALL, "file", "read"); - allow("kernel", ALL, "file", "write"); + // For mounting loop devices, mirrors, tmpfs + allow("kernel", ALL, "file", "read"); + allow("kernel", ALL, "file", "write"); - // Allow all binder transactions - allow(ALL, SEPOL_PROC_DOMAIN, "binder", ALL); + // Allow all binder transactions + allow(ALL, SEPOL_PROC_DOMAIN, "binder", ALL); - // For changing file context - allow("rootfs", "tmpfs", "filesystem", "associate"); + // For changing file context + allow("rootfs", "tmpfs", "filesystem", "associate"); - // Xposed - allow("untrusted_app", "untrusted_app", "capability", "setgid"); - allow("system_server", "dex2oat_exec", "file", ALL); + // Xposed + allow("untrusted_app", "untrusted_app", "capability", "setgid"); + allow("system_server", "dex2oat_exec", "file", ALL); - // Support deodexed ROM on Oreo - allow("zygote", "dalvikcache_data_file", "file", "execute"); + // Support deodexed ROM on Oreo + allow("zygote", "dalvikcache_data_file", "file", "execute"); - // Support deodexed ROM on Pie (Samsung) - allow("system_server", "dalvikcache_data_file", "file", "write"); - allow("system_server", "dalvikcache_data_file", "file", "execute"); + // Support deodexed ROM on Pie (Samsung) + allow("system_server", "dalvikcache_data_file", "file", "write"); + allow("system_server", "dalvikcache_data_file", "file", "execute"); - // Allow update_engine/addon.d-v2 to run permissive on all ROMs - permissive("update_engine"); + // Allow update_engine/addon.d-v2 to run permissive on all ROMs + permissive("update_engine"); #if 0 - // Remove all dontaudit in debug mode - impl->strip_dontaudit(); + // Remove all dontaudit in debug mode + impl->strip_dontaudit(); #endif - log_cb.w = bak; + log_cb.w = bak; } diff --git a/native/jni/magiskpolicy/sepolicy.cpp b/native/jni/magiskpolicy/sepolicy.cpp index a7d6aa31c..a16639969 100644 --- a/native/jni/magiskpolicy/sepolicy.cpp +++ b/native/jni/magiskpolicy/sepolicy.cpp @@ -9,10 +9,10 @@ // Print out all rules going through public API for debugging template static void dprint(const char *action, Args ...args) { - std::string s(action); - for (int i = 0; i < sizeof...(args); ++i) s += " %s"; - s += "\n"; - LOGD(s.data(), (args ? args : "*")...); + std::string s(action); + for (int i = 0; i < sizeof...(args); ++i) s += " %s"; + s += "\n"; + LOGD(s.data(), (args ? args : "*")...); } #else #define dprint(...) @@ -27,687 +27,687 @@ int policydb_index_decls(sepol_handle_t * handle, policydb_t * p); int avtab_hash(struct avtab_key *keyp, uint32_t mask); int type_set_expand(type_set_t * set, ebitmap_t * t, policydb_t * p, unsigned char alwaysexpand); int context_from_string( - sepol_handle_t * handle, - const policydb_t * policydb, - context_struct_t ** cptr, - const char *con_str, size_t con_str_len); + sepol_handle_t * handle, + const policydb_t * policydb, + context_struct_t ** cptr, + const char *con_str, size_t con_str_len); __END_DECLS template struct auto_cast_wrapper { - auto_cast_wrapper(T *ptr) : ptr(ptr) {} - template - operator U*() const { return static_cast(ptr); } + auto_cast_wrapper(T *ptr) : ptr(ptr) {} + template + operator U*() const { return static_cast(ptr); } private: - T *ptr; + T *ptr; }; template static auto_cast_wrapper auto_cast(T *p) { - return auto_cast_wrapper(p); + return auto_cast_wrapper(p); } static auto hashtab_find(hashtab_t h, const_hashtab_key_t key) { - return auto_cast(hashtab_search(h, key)); + return auto_cast(hashtab_search(h, key)); } template static void hash_for_each(Node **node_ptr, int n_slot, const Func &fn) { - for (int i = 0; i < n_slot; ++i) { - for (Node *cur = node_ptr[i]; cur; cur = cur->next) { - fn(cur); - } - } + for (int i = 0; i < n_slot; ++i) { + for (Node *cur = node_ptr[i]; cur; cur = cur->next) { + fn(cur); + } + } } template static void hashtab_for_each(hashtab_t htab, const Func &fn) { - hash_for_each(htab->htable, htab->size, fn); + hash_for_each(htab->htable, htab->size, fn); } template static void avtab_for_each(avtab_t *avtab, const Func &fn) { - hash_for_each(avtab->htable, avtab->nslot, fn); + hash_for_each(avtab->htable, avtab->nslot, fn); } template static void for_each_attr(hashtab_t htab, const Func &fn) { - hashtab_for_each(htab, [&](hashtab_ptr_t node) { - auto type = static_cast(node->datum); - if (type->flavor == TYPE_ATTRIB) - fn(type); - }); + hashtab_for_each(htab, [&](hashtab_ptr_t node) { + auto type = static_cast(node->datum); + if (type->flavor == TYPE_ATTRIB) + fn(type); + }); } static int avtab_remove_node(avtab_t *h, avtab_ptr_t node) { - if (!h || !h->htable) - return SEPOL_ENOMEM; - int hvalue = avtab_hash(&node->key, h->mask); - avtab_ptr_t prev, cur; - for (prev = nullptr, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { - if (cur == node) - break; - } - if (cur == nullptr) - return SEPOL_ENOENT; + if (!h || !h->htable) + return SEPOL_ENOMEM; + int hvalue = avtab_hash(&node->key, h->mask); + avtab_ptr_t prev, cur; + for (prev = nullptr, cur = h->htable[hvalue]; cur; prev = cur, cur = cur->next) { + if (cur == node) + break; + } + if (cur == nullptr) + return SEPOL_ENOENT; - // Detach from hash table - if (prev) - prev->next = node->next; - else - h->htable[hvalue] = node->next; - h->nel--; + // Detach from hash table + if (prev) + prev->next = node->next; + else + h->htable[hvalue] = node->next; + h->nel--; - // Free memory - if (node->key.specified & AVTAB_XPERMS) - free(node->datum.xperms); - free(node); - return 0; + // Free memory + if (node->key.specified & AVTAB_XPERMS) + free(node->datum.xperms); + free(node); + return 0; } void sepol_impl::check_avtab_node(avtab_ptr_t node) { - bool redundant; - if (node->key.specified == AVTAB_AUDITDENY) - redundant = node->datum.data == ~0U; - else if (node->key.specified & AVTAB_XPERMS) - redundant = node->datum.xperms == nullptr; - else - redundant = node->datum.data == 0U; - if (redundant) - avtab_remove_node(&db->te_avtab, node); + bool redundant; + if (node->key.specified == AVTAB_AUDITDENY) + redundant = node->datum.data == ~0U; + else if (node->key.specified & AVTAB_XPERMS) + redundant = node->datum.xperms == nullptr; + else + redundant = node->datum.data == 0U; + if (redundant) + avtab_remove_node(&db->te_avtab, node); } avtab_ptr_t sepol_impl::get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms) { - avtab_ptr_t node; + avtab_ptr_t node; - /* AVTAB_XPERMS entries are not necessarily unique */ - if (key->specified & AVTAB_XPERMS) { - bool match = false; - node = avtab_search_node(&db->te_avtab, key); - while (node) { - if ((node->datum.xperms->specified == xperms->specified) && - (node->datum.xperms->driver == xperms->driver)) { - match = true; - break; - } - node = avtab_search_node_next(node, key->specified); - } - if (!match) - node = nullptr; - } else { - node = avtab_search_node(&db->te_avtab, key); - } + /* AVTAB_XPERMS entries are not necessarily unique */ + if (key->specified & AVTAB_XPERMS) { + bool match = false; + node = avtab_search_node(&db->te_avtab, key); + while (node) { + if ((node->datum.xperms->specified == xperms->specified) && + (node->datum.xperms->driver == xperms->driver)) { + match = true; + break; + } + node = avtab_search_node_next(node, key->specified); + } + if (!match) + node = nullptr; + } else { + node = avtab_search_node(&db->te_avtab, key); + } - if (!node) { - avtab_datum_t avdatum{}; - /* - * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for - * others. Initialize the data accordingly. - */ - avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0U : 0U; - /* this is used to get the node - insertion is actually unique */ - node = avtab_insert_nonunique(&db->te_avtab, key, &avdatum); - } + if (!node) { + avtab_datum_t avdatum{}; + /* + * AUDITDENY, aka DONTAUDIT, are &= assigned, versus |= for + * others. Initialize the data accordingly. + */ + avdatum.data = key->specified == AVTAB_AUDITDENY ? ~0U : 0U; + /* this is used to get the node - insertion is actually unique */ + node = avtab_insert_nonunique(&db->te_avtab, key, &avdatum); + } - return node; + return node; } void sepol_impl::add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, perm_datum_t *perm, int effect, bool invert) { - if (src == nullptr) { - if (strip_av(effect, invert)) { - // Stripping av, have to go through all types for correct results - hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { - add_rule(auto_cast(node->datum), tgt, cls, perm, effect, invert); - }); - } else { - // If we are not stripping av, go through all attributes instead of types for optimization - for_each_attr(db->p_types.table, [&](type_datum_t *type) { - add_rule(type, tgt, cls, perm, effect, invert); - }); - } - } else if (tgt == nullptr) { - if (strip_av(effect, invert)) { - hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { - add_rule(src, auto_cast(node->datum), cls, perm, effect, invert); - }); - } else { - for_each_attr(db->p_types.table, [&](type_datum_t *type) { - add_rule(src, type, cls, perm, effect, invert); - }); - } - } else if (cls == nullptr) { - hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) { - add_rule(src, tgt, auto_cast(node->datum), perm, effect, invert); - }); - } else { - avtab_key_t key; - key.source_type = src->s.value; - key.target_type = tgt->s.value; - key.target_class = cls->s.value; - key.specified = effect; + if (src == nullptr) { + if (strip_av(effect, invert)) { + // Stripping av, have to go through all types for correct results + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + add_rule(auto_cast(node->datum), tgt, cls, perm, effect, invert); + }); + } else { + // If we are not stripping av, go through all attributes instead of types for optimization + for_each_attr(db->p_types.table, [&](type_datum_t *type) { + add_rule(type, tgt, cls, perm, effect, invert); + }); + } + } else if (tgt == nullptr) { + if (strip_av(effect, invert)) { + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + add_rule(src, auto_cast(node->datum), cls, perm, effect, invert); + }); + } else { + for_each_attr(db->p_types.table, [&](type_datum_t *type) { + add_rule(src, type, cls, perm, effect, invert); + }); + } + } else if (cls == nullptr) { + hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) { + add_rule(src, tgt, auto_cast(node->datum), perm, effect, invert); + }); + } else { + avtab_key_t key; + key.source_type = src->s.value; + key.target_type = tgt->s.value; + key.target_class = cls->s.value; + key.specified = effect; - avtab_ptr_t node = get_avtab_node(&key, nullptr); - if (invert) { - if (perm) - node->datum.data &= ~(1U << (perm->s.value - 1)); - else - node->datum.data = 0U; - } else { - if (perm) - node->datum.data |= 1U << (perm->s.value - 1); - else - node->datum.data = ~0U; - } - check_avtab_node(node); - } + avtab_ptr_t node = get_avtab_node(&key, nullptr); + if (invert) { + if (perm) + node->datum.data &= ~(1U << (perm->s.value - 1)); + else + node->datum.data = 0U; + } else { + if (perm) + node->datum.data |= 1U << (perm->s.value - 1); + else + node->datum.data = ~0U; + } + check_avtab_node(node); + } } bool sepol_impl::add_rule(const char *s, const char *t, const char *c, const char *p, int effect, bool invert) { - type_datum_t *src = nullptr, *tgt = nullptr; - class_datum_t *cls = nullptr; - perm_datum_t *perm = nullptr; + type_datum_t *src = nullptr, *tgt = nullptr; + class_datum_t *cls = nullptr; + perm_datum_t *perm = nullptr; - if (s) { - src = hashtab_find(db->p_types.table, s); - if (src == nullptr) { - LOGW("source type %s does not exist\n", s); - return false; - } - } + if (s) { + src = hashtab_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return false; + } + } - if (t) { - tgt = hashtab_find(db->p_types.table, t); - if (tgt == nullptr) { - LOGW("target type %s does not exist\n", t); - return false; - } - } + if (t) { + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return false; + } + } - if (c) { - cls = hashtab_find(db->p_classes.table, c); - if (cls == nullptr) { - LOGW("class %s does not exist\n", c); - return false; - } - } + if (c) { + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return false; + } + } - if (p) { - if (c == nullptr) { - LOGW("No class is specified, cannot add perm [%s] \n", p); - return false; - } + if (p) { + if (c == nullptr) { + LOGW("No class is specified, cannot add perm [%s] \n", p); + return false; + } - perm = hashtab_find(cls->permissions.table, p); - if (perm == nullptr && cls->comdatum != nullptr) { - perm = hashtab_find(cls->comdatum->permissions.table, p); - } - if (perm == nullptr) { - LOGW("perm %s does not exist in class %s\n", p, c); - return false; - } - } - add_rule(src, tgt, cls, perm, effect, invert); - return true; + perm = hashtab_find(cls->permissions.table, p); + if (perm == nullptr && cls->comdatum != nullptr) { + perm = hashtab_find(cls->comdatum->permissions.table, p); + } + if (perm == nullptr) { + LOGW("perm %s does not exist in class %s\n", p, c); + return false; + } + } + add_rule(src, tgt, cls, perm, effect, invert); + return true; } #define ioctl_driver(x) (x>>8 & 0xFF) #define ioctl_func(x) (x & 0xFF) void sepol_impl::add_xperm_rule(type_datum_t *src, type_datum_t *tgt, - class_datum_t *cls, uint16_t low, uint16_t high, int effect, bool invert) { - if (src == nullptr) { - for_each_attr(db->p_types.table, [&](type_datum_t *type) { - add_xperm_rule(type, tgt, cls, low, high, effect, invert); - }); - } else if (tgt == nullptr) { - for_each_attr(db->p_types.table, [&](type_datum_t *type) { - add_xperm_rule(src, type, cls, low, high, effect, invert); - }); - } else if (cls == nullptr) { - hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) { - add_xperm_rule(src, tgt, auto_cast(node->datum), low, high, effect, invert); - }); - } else { - avtab_key_t key; - key.source_type = src->s.value; - key.target_type = tgt->s.value; - key.target_class = cls->s.value; - key.specified = effect; + class_datum_t *cls, uint16_t low, uint16_t high, int effect, bool invert) { + if (src == nullptr) { + for_each_attr(db->p_types.table, [&](type_datum_t *type) { + add_xperm_rule(type, tgt, cls, low, high, effect, invert); + }); + } else if (tgt == nullptr) { + for_each_attr(db->p_types.table, [&](type_datum_t *type) { + add_xperm_rule(src, type, cls, low, high, effect, invert); + }); + } else if (cls == nullptr) { + hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node) { + add_xperm_rule(src, tgt, auto_cast(node->datum), low, high, effect, invert); + }); + } else { + avtab_key_t key; + key.source_type = src->s.value; + key.target_type = tgt->s.value; + key.target_class = cls->s.value; + key.specified = effect; - avtab_datum_t *datum; - avtab_extended_perms_t xperms; + avtab_datum_t *datum; + avtab_extended_perms_t xperms; - memset(&xperms, 0, sizeof(xperms)); - if (ioctl_driver(low) != ioctl_driver(high)) { - xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; - xperms.driver = 0; - } else { - xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; - xperms.driver = ioctl_driver(low); - } + memset(&xperms, 0, sizeof(xperms)); + if (ioctl_driver(low) != ioctl_driver(high)) { + xperms.specified = AVTAB_XPERMS_IOCTLDRIVER; + xperms.driver = 0; + } else { + xperms.specified = AVTAB_XPERMS_IOCTLFUNCTION; + xperms.driver = ioctl_driver(low); + } - if (xperms.specified == AVTAB_XPERMS_IOCTLDRIVER) { - for (int i = ioctl_driver(low); i <= ioctl_driver(high); ++i) { - if (invert) - xperm_clear(i, xperms.perms); - else - xperm_set(i, xperms.perms); - } - } else { - for (int i = ioctl_func(low); i <= ioctl_func(high); ++i) { - if (invert) - xperm_clear(i, xperms.perms); - else - xperm_set(i, xperms.perms); - } - } + if (xperms.specified == AVTAB_XPERMS_IOCTLDRIVER) { + for (int i = ioctl_driver(low); i <= ioctl_driver(high); ++i) { + if (invert) + xperm_clear(i, xperms.perms); + else + xperm_set(i, xperms.perms); + } + } else { + for (int i = ioctl_func(low); i <= ioctl_func(high); ++i) { + if (invert) + xperm_clear(i, xperms.perms); + else + xperm_set(i, xperms.perms); + } + } - datum = &get_avtab_node(&key, &xperms)->datum; + datum = &get_avtab_node(&key, &xperms)->datum; - if (datum->xperms == nullptr) - datum->xperms = auto_cast(xmalloc(sizeof(xperms))); + if (datum->xperms == nullptr) + datum->xperms = auto_cast(xmalloc(sizeof(xperms))); - memcpy(datum->xperms, &xperms, sizeof(xperms)); - } + memcpy(datum->xperms, &xperms, sizeof(xperms)); + } } bool sepol_impl::add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect, bool invert) { - type_datum_t *src = nullptr, *tgt = nullptr; - class_datum_t *cls = nullptr; + type_datum_t *src = nullptr, *tgt = nullptr; + class_datum_t *cls = nullptr; - if (s) { - src = hashtab_find(db->p_types.table, s); - if (src == nullptr) { - LOGW("source type %s does not exist\n", s); - return false; - } - } + if (s) { + src = hashtab_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return false; + } + } - if (t) { - tgt = hashtab_find(db->p_types.table, t); - if (tgt == nullptr) { - LOGW("target type %s does not exist\n", t); - return false; - } - } + if (t) { + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return false; + } + } - if (c) { - cls = hashtab_find(db->p_classes.table, c); - if (cls == nullptr) { - LOGW("class %s does not exist\n", c); - return false; - } - } + if (c) { + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return false; + } + } - uint16_t low, high; + uint16_t low, high; - if (range) { - if (strchr(range, '-')){ - sscanf(range, "%hx-%hx", &low, &high); - } else { - sscanf(range, "%hx", &low); - high = low; - } - } else { - low = 0; - high = 0xFFFF; - } + if (range) { + if (strchr(range, '-')){ + sscanf(range, "%hx-%hx", &low, &high); + } else { + sscanf(range, "%hx", &low); + high = low; + } + } else { + low = 0; + high = 0xFFFF; + } - add_xperm_rule(src, tgt, cls, low, high, effect, invert); - return true; + add_xperm_rule(src, tgt, cls, low, high, effect, invert); + return true; } bool sepol_impl::add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect) { - type_datum_t *src, *tgt, *def; - class_datum_t *cls; + type_datum_t *src, *tgt, *def; + class_datum_t *cls; - src = hashtab_find(db->p_types.table, s); - if (src == nullptr) { - LOGW("source type %s does not exist\n", s); - return false; - } - tgt = hashtab_find(db->p_types.table, t); - if (tgt == nullptr) { - LOGW("target type %s does not exist\n", t); - return false; - } - cls = hashtab_find(db->p_classes.table, c); - if (cls == nullptr) { - LOGW("class %s does not exist\n", c); - return false; - } - def = hashtab_find(db->p_types.table, d); - if (def == nullptr) { - LOGW("default type %s does not exist\n", d); - return false; - } + src = hashtab_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return false; + } + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return false; + } + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return false; + } + def = hashtab_find(db->p_types.table, d); + if (def == nullptr) { + LOGW("default type %s does not exist\n", d); + return false; + } - avtab_key_t key; - key.source_type = src->s.value; - key.target_type = tgt->s.value; - key.target_class = cls->s.value; - key.specified = effect; + avtab_key_t key; + key.source_type = src->s.value; + key.target_type = tgt->s.value; + key.target_class = cls->s.value; + key.specified = effect; - avtab_ptr_t node = get_avtab_node(&key, nullptr); - node->datum.data = def->s.value; + avtab_ptr_t node = get_avtab_node(&key, nullptr); + node->datum.data = def->s.value; - return true; + return true; } bool sepol_impl::add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o) { - type_datum_t *src, *tgt, *def; - class_datum_t *cls; + type_datum_t *src, *tgt, *def; + class_datum_t *cls; - src = hashtab_find(db->p_types.table, s); - if (src == nullptr) { - LOGW("source type %s does not exist\n", s); - return false; - } - tgt = hashtab_find(db->p_types.table, t); - if (tgt == nullptr) { - LOGW("target type %s does not exist\n", t); - return false; - } - cls = hashtab_find(db->p_classes.table, c); - if (cls == nullptr) { - LOGW("class %s does not exist\n", c); - return false; - } - def = hashtab_find(db->p_types.table, d); - if (def == nullptr) { - LOGW("default type %s does not exist\n", d); - return false; - } + src = hashtab_find(db->p_types.table, s); + if (src == nullptr) { + LOGW("source type %s does not exist\n", s); + return false; + } + tgt = hashtab_find(db->p_types.table, t); + if (tgt == nullptr) { + LOGW("target type %s does not exist\n", t); + return false; + } + cls = hashtab_find(db->p_classes.table, c); + if (cls == nullptr) { + LOGW("class %s does not exist\n", c); + return false; + } + def = hashtab_find(db->p_types.table, d); + if (def == nullptr) { + LOGW("default type %s does not exist\n", d); + return false; + } - filename_trans_key_t key; - key.ttype = tgt->s.value; - key.tclass = cls->s.value; - key.name = (char *) o; + filename_trans_key_t key; + key.ttype = tgt->s.value; + key.tclass = cls->s.value; + key.name = (char *) o; - filename_trans_datum_t *last = nullptr; - filename_trans_datum_t *trans = hashtab_find(db->filename_trans, (hashtab_key_t) &key); - while (trans) { - if (ebitmap_get_bit(&trans->stypes, src->s.value - 1)) { - // Duplicate, overwrite existing data and return - trans->otype = def->s.value; - return true; - } - if (trans->otype == def->s.value) - break; - last = trans; - trans = trans->next; - } + filename_trans_datum_t *last = nullptr; + filename_trans_datum_t *trans = hashtab_find(db->filename_trans, (hashtab_key_t) &key); + while (trans) { + if (ebitmap_get_bit(&trans->stypes, src->s.value - 1)) { + // Duplicate, overwrite existing data and return + trans->otype = def->s.value; + return true; + } + if (trans->otype == def->s.value) + break; + last = trans; + trans = trans->next; + } - if (trans == nullptr) { - trans = auto_cast(xcalloc(sizeof(*trans), 1)); - filename_trans_key_t *new_key = auto_cast(malloc(sizeof(*new_key))); - *new_key = key; - new_key->name = strdup(key.name); - trans->next = last; - trans->otype = def->s.value; - hashtab_insert(db->filename_trans, (hashtab_key_t) new_key, trans); - } + if (trans == nullptr) { + trans = auto_cast(xcalloc(sizeof(*trans), 1)); + filename_trans_key_t *new_key = auto_cast(malloc(sizeof(*new_key))); + *new_key = key; + new_key->name = strdup(key.name); + trans->next = last; + trans->otype = def->s.value; + hashtab_insert(db->filename_trans, (hashtab_key_t) new_key, trans); + } - db->filename_trans_count++; - return ebitmap_set_bit(&trans->stypes, src->s.value - 1, 1) == 0; + db->filename_trans_count++; + return ebitmap_set_bit(&trans->stypes, src->s.value - 1, 1) == 0; } bool sepol_impl::add_genfscon(const char *fs_name, const char *path, const char *context) { - // First try to create context - context_struct_t *ctx; - if (context_from_string(nullptr, db, &ctx, context, strlen(context))) { - LOGW("Failed to create context from string [%s]\n", context); - return false; - } + // First try to create context + context_struct_t *ctx; + if (context_from_string(nullptr, db, &ctx, context, strlen(context))) { + LOGW("Failed to create context from string [%s]\n", context); + return false; + } - // Allocate genfs context - ocontext_t *newc = auto_cast(xcalloc(sizeof(*newc), 1)); - newc->u.name = strdup(path); - memcpy(&newc->context[0], ctx, sizeof(*ctx)); - free(ctx); + // Allocate genfs context + ocontext_t *newc = auto_cast(xcalloc(sizeof(*newc), 1)); + newc->u.name = strdup(path); + memcpy(&newc->context[0], ctx, sizeof(*ctx)); + free(ctx); - // Find or allocate genfs - genfs_t *last_gen = nullptr; - genfs_t *newfs = nullptr; - for (genfs_t *node = db->genfs; node; node = node->next) { - if (strcmp(node->fstype, fs_name) == 0) { - newfs = node; - break; - } - last_gen = node; - } - if (newfs == nullptr) { - newfs = auto_cast(xcalloc(sizeof(*newfs), 1)); - newfs->fstype = strdup(fs_name); - // Insert - if (last_gen) - last_gen->next = newfs; - else - db->genfs = newfs; - } + // Find or allocate genfs + genfs_t *last_gen = nullptr; + genfs_t *newfs = nullptr; + for (genfs_t *node = db->genfs; node; node = node->next) { + if (strcmp(node->fstype, fs_name) == 0) { + newfs = node; + break; + } + last_gen = node; + } + if (newfs == nullptr) { + newfs = auto_cast(xcalloc(sizeof(*newfs), 1)); + newfs->fstype = strdup(fs_name); + // Insert + if (last_gen) + last_gen->next = newfs; + else + db->genfs = newfs; + } - // Insert or replace genfs context - ocontext_t *last_ctx = nullptr; - for (ocontext_t *node = newfs->head; node; node = node->next) { - if (strcmp(node->u.name, path) == 0) { - // Unlink - if (last_ctx) - last_ctx->next = node->next; - else - newfs->head = nullptr; - // Destroy old node - free(node->u.name); - context_destroy(&node->context[0]); - free(node); - break; - } - last_ctx = node; - } - // Insert - if (last_ctx) - last_ctx->next = newc; - else - newfs->head = newc; + // Insert or replace genfs context + ocontext_t *last_ctx = nullptr; + for (ocontext_t *node = newfs->head; node; node = node->next) { + if (strcmp(node->u.name, path) == 0) { + // Unlink + if (last_ctx) + last_ctx->next = node->next; + else + newfs->head = nullptr; + // Destroy old node + free(node->u.name); + context_destroy(&node->context[0]); + free(node); + break; + } + last_ctx = node; + } + // Insert + if (last_ctx) + last_ctx->next = newc; + else + newfs->head = newc; - return true; + return true; } bool sepol_impl::add_type(const char *type_name, uint32_t flavor) { - type_datum_t *type = hashtab_find(db->p_types.table, type_name); - if (type) { - LOGW("Type %s already exists\n", type_name); - return true; - } + type_datum_t *type = hashtab_find(db->p_types.table, type_name); + if (type) { + LOGW("Type %s already exists\n", type_name); + return true; + } - type = auto_cast(xmalloc(sizeof(type_datum_t))); - type_datum_init(type); - type->primary = 1; - type->flavor = flavor; + type = auto_cast(xmalloc(sizeof(type_datum_t))); + type_datum_init(type); + type->primary = 1; + type->flavor = flavor; - uint32_t value = 0; - if (symtab_insert(db, SYM_TYPES, strdup(type_name), type, SCOPE_DECL, 1, &value)) - return false; - type->s.value = value; - ebitmap_set_bit(&db->global->branch_list->declared.p_types_scope, value - 1, 1); + uint32_t value = 0; + if (symtab_insert(db, SYM_TYPES, strdup(type_name), type, SCOPE_DECL, 1, &value)) + return false; + type->s.value = value; + ebitmap_set_bit(&db->global->branch_list->declared.p_types_scope, value - 1, 1); - auto new_size = sizeof(ebitmap_t) * db->p_types.nprim; - db->type_attr_map = auto_cast(xrealloc(db->type_attr_map, new_size)); - db->attr_type_map = auto_cast(xrealloc(db->attr_type_map, new_size)); - ebitmap_init(&db->type_attr_map[value - 1]); - ebitmap_init(&db->attr_type_map[value - 1]); - ebitmap_set_bit(&db->type_attr_map[value - 1], value - 1, 1); + auto new_size = sizeof(ebitmap_t) * db->p_types.nprim; + db->type_attr_map = auto_cast(xrealloc(db->type_attr_map, new_size)); + db->attr_type_map = auto_cast(xrealloc(db->attr_type_map, new_size)); + ebitmap_init(&db->type_attr_map[value - 1]); + ebitmap_init(&db->attr_type_map[value - 1]); + ebitmap_set_bit(&db->type_attr_map[value - 1], value - 1, 1); - // Re-index stuffs - if (policydb_index_decls(nullptr, db) || - policydb_index_classes(db) || policydb_index_others(nullptr, db, 0)) - return false; + // Re-index stuffs + if (policydb_index_decls(nullptr, db) || + policydb_index_classes(db) || policydb_index_others(nullptr, db, 0)) + return false; - // Add the type to all roles - for (int i = 0; i < db->p_roles.nprim; ++i) { - // Not sure all those three calls are needed - ebitmap_set_bit(&db->role_val_to_struct[i]->types.negset, value - 1, 0); - ebitmap_set_bit(&db->role_val_to_struct[i]->types.types, value - 1, 1); - type_set_expand(&db->role_val_to_struct[i]->types, &db->role_val_to_struct[i]->cache, db, 0); - } + // Add the type to all roles + for (int i = 0; i < db->p_roles.nprim; ++i) { + // Not sure all those three calls are needed + ebitmap_set_bit(&db->role_val_to_struct[i]->types.negset, value - 1, 0); + ebitmap_set_bit(&db->role_val_to_struct[i]->types.types, value - 1, 1); + type_set_expand(&db->role_val_to_struct[i]->types, &db->role_val_to_struct[i]->cache, db, 0); + } - return true; + return true; } bool sepol_impl::set_type_state(const char *type_name, bool permissive) { - type_datum_t *type; - if (type_name == nullptr) { - hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { - type = auto_cast(node->datum); - if (ebitmap_set_bit(&db->permissive_map, type->s.value, permissive)) - LOGW("Could not set bit in permissive map\n"); - }); - } else { - type = hashtab_find(db->p_types.table, type_name); - if (type == nullptr) { - LOGW("type %s does not exist\n", type_name); - return false; - } - if (ebitmap_set_bit(&db->permissive_map, type->s.value, permissive)) { - LOGW("Could not set bit in permissive map\n"); - return false; - } - } - return true; + type_datum_t *type; + if (type_name == nullptr) { + hashtab_for_each(db->p_types.table, [&](hashtab_ptr_t node) { + type = auto_cast(node->datum); + if (ebitmap_set_bit(&db->permissive_map, type->s.value, permissive)) + LOGW("Could not set bit in permissive map\n"); + }); + } else { + type = hashtab_find(db->p_types.table, type_name); + if (type == nullptr) { + LOGW("type %s does not exist\n", type_name); + return false; + } + if (ebitmap_set_bit(&db->permissive_map, type->s.value, permissive)) { + LOGW("Could not set bit in permissive map\n"); + return false; + } + } + return true; } void sepol_impl::add_typeattribute(type_datum_t *type, type_datum_t *attr) { - ebitmap_set_bit(&db->type_attr_map[type->s.value - 1], attr->s.value - 1, 1); - ebitmap_set_bit(&db->attr_type_map[attr->s.value - 1], type->s.value - 1, 1); + ebitmap_set_bit(&db->type_attr_map[type->s.value - 1], attr->s.value - 1, 1); + ebitmap_set_bit(&db->attr_type_map[attr->s.value - 1], type->s.value - 1, 1); - hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node){ - auto cls = static_cast(node->datum); - for (constraint_node_t *n = cls->constraints; n ; n = n->next) { - for (constraint_expr_t *e = n->expr; e; e = e->next) { - if (e->expr_type == CEXPR_NAMES && - ebitmap_get_bit(&e->type_names->types, attr->s.value - 1)) { - ebitmap_set_bit(&e->names, type->s.value - 1, 1); - } - } - } - }); + hashtab_for_each(db->p_classes.table, [&](hashtab_ptr_t node){ + auto cls = static_cast(node->datum); + for (constraint_node_t *n = cls->constraints; n ; n = n->next) { + for (constraint_expr_t *e = n->expr; e; e = e->next) { + if (e->expr_type == CEXPR_NAMES && + ebitmap_get_bit(&e->type_names->types, attr->s.value - 1)) { + ebitmap_set_bit(&e->names, type->s.value - 1, 1); + } + } + } + }); } bool sepol_impl::add_typeattribute(const char *type, const char *attr) { - type_datum_t *type_d = hashtab_find(db->p_types.table, type); - if (type_d == nullptr) { - LOGW("type %s does not exist\n", type); - return false; - } else if (type_d->flavor == TYPE_ATTRIB) { - LOGW("type %s is an attribute\n", attr); - return false; - } + type_datum_t *type_d = hashtab_find(db->p_types.table, type); + if (type_d == nullptr) { + LOGW("type %s does not exist\n", type); + return false; + } else if (type_d->flavor == TYPE_ATTRIB) { + LOGW("type %s is an attribute\n", attr); + return false; + } - type_datum *attr_d = hashtab_find(db->p_types.table, attr); - if (attr_d == nullptr) { - LOGW("attribute %s does not exist\n", type); - return false; - } else if (attr_d->flavor != TYPE_ATTRIB) { - LOGW("type %s is not an attribute \n", attr); - return false; - } + type_datum *attr_d = hashtab_find(db->p_types.table, attr); + if (attr_d == nullptr) { + LOGW("attribute %s does not exist\n", type); + return false; + } else if (attr_d->flavor != TYPE_ATTRIB) { + LOGW("type %s is not an attribute \n", attr); + return false; + } - add_typeattribute(type_d, attr_d); - return true; + add_typeattribute(type_d, attr_d); + return true; } void sepol_impl::strip_dontaudit() { - avtab_for_each(&db->te_avtab, [=](avtab_ptr_t node) { - if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT) - avtab_remove_node(&db->te_avtab, node); - }); + avtab_for_each(&db->te_avtab, [=](avtab_ptr_t node) { + if (node->key.specified == AVTAB_AUDITDENY || node->key.specified == AVTAB_XPERMS_DONTAUDIT) + avtab_remove_node(&db->te_avtab, node); + }); } bool sepolicy::allow(const char *s, const char *t, const char *c, const char *p) { - dprint(__FUNCTION__, s, t, c, p); - return impl->add_rule(s, t, c, p, AVTAB_ALLOWED, false); + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_ALLOWED, false); } bool sepolicy::deny(const char *s, const char *t, const char *c, const char *p) { - dprint(__FUNCTION__, s, t, c, p); - return impl->add_rule(s, t, c, p, AVTAB_ALLOWED, true); + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_ALLOWED, true); } bool sepolicy::auditallow(const char *s, const char *t, const char *c, const char *p) { - dprint(__FUNCTION__, s, t, c, p); - return impl->add_rule(s, t, c, p, AVTAB_AUDITALLOW, false); + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_AUDITALLOW, false); } bool sepolicy::dontaudit(const char *s, const char *t, const char *c, const char *p) { - dprint(__FUNCTION__, s, t, c, p); - return impl->add_rule(s, t, c, p, AVTAB_AUDITDENY, true); + dprint(__FUNCTION__, s, t, c, p); + return impl->add_rule(s, t, c, p, AVTAB_AUDITDENY, true); } bool sepolicy::allowxperm(const char *s, const char *t, const char *c, const char *range) { - dprint(__FUNCTION__, s, t, c, "ioctl", range); - return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_ALLOWED, false); + dprint(__FUNCTION__, s, t, c, "ioctl", range); + return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_ALLOWED, false); } bool sepolicy::auditallowxperm(const char *s, const char *t, const char *c, const char *range) { - dprint(__FUNCTION__, s, t, c, "ioctl", range); - return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_AUDITALLOW, false); + dprint(__FUNCTION__, s, t, c, "ioctl", range); + return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_AUDITALLOW, false); } bool sepolicy::dontauditxperm(const char *s, const char *t, const char *c, const char *range) { - dprint(__FUNCTION__, s, t, c, "ioctl", range); - return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_DONTAUDIT, false); + dprint(__FUNCTION__, s, t, c, "ioctl", range); + return impl->add_xperm_rule(s, t, c, range, AVTAB_XPERMS_DONTAUDIT, false); } bool sepolicy::type_change(const char *s, const char *t, const char *c, const char *d) { - dprint(__FUNCTION__, s, t, c, d); - return impl->add_type_rule(s, t, c, d, AVTAB_CHANGE); + dprint(__FUNCTION__, s, t, c, d); + return impl->add_type_rule(s, t, c, d, AVTAB_CHANGE); } bool sepolicy::type_member(const char *s, const char *t, const char *c, const char *d) { - dprint(__FUNCTION__, s, t, c, d); - return impl->add_type_rule(s, t, c, d, AVTAB_MEMBER); + dprint(__FUNCTION__, s, t, c, d); + return impl->add_type_rule(s, t, c, d, AVTAB_MEMBER); } bool sepolicy::type_transition(const char *s, const char *t, const char *c, const char *d, const char *o) { - if (o) { - dprint(__FUNCTION__, s, t, c, d, o); - return impl->add_filename_trans(s, t, c, d, o); - } else { - dprint(__FUNCTION__, s, t, c, d); - return impl->add_type_rule(s, t, c, d, AVTAB_TRANSITION); - } + if (o) { + dprint(__FUNCTION__, s, t, c, d, o); + return impl->add_filename_trans(s, t, c, d, o); + } else { + dprint(__FUNCTION__, s, t, c, d); + return impl->add_type_rule(s, t, c, d, AVTAB_TRANSITION); + } } bool sepolicy::permissive(const char *s) { - dprint(__FUNCTION__, s); - return impl->set_type_state(s, true); + dprint(__FUNCTION__, s); + return impl->set_type_state(s, true); } bool sepolicy::enforce(const char *s) { - dprint(__FUNCTION__, s); - return impl->set_type_state(s, false); + dprint(__FUNCTION__, s); + return impl->set_type_state(s, false); } bool sepolicy::type(const char *name, const char *attr) { - dprint(__FUNCTION__, name, attr); - return impl->add_type(name, TYPE_TYPE) && impl->add_typeattribute(name, attr); + dprint(__FUNCTION__, name, attr); + return impl->add_type(name, TYPE_TYPE) && impl->add_typeattribute(name, attr); } bool sepolicy::attribute(const char *name) { - dprint(__FUNCTION__, name); - return impl->add_type(name, TYPE_ATTRIB); + dprint(__FUNCTION__, name); + return impl->add_type(name, TYPE_ATTRIB); } bool sepolicy::typeattribute(const char *type, const char *attr) { - dprint(__FUNCTION__, type, attr); - return impl->add_typeattribute(type, attr); + dprint(__FUNCTION__, type, attr); + return impl->add_typeattribute(type, attr); } bool sepolicy::genfscon(const char *fs_name, const char *path, const char *ctx) { - dprint(__FUNCTION__, fs_name, path, ctx); - return impl->add_genfscon(fs_name, path, ctx); + dprint(__FUNCTION__, fs_name, path, ctx); + return impl->add_genfscon(fs_name, path, ctx); } bool sepolicy::exists(const char *source) { - return hashtab_search(db->p_types.table, source) != nullptr; + return hashtab_search(db->p_types.table, source) != nullptr; } diff --git a/native/jni/magiskpolicy/sepolicy.hpp b/native/jni/magiskpolicy/sepolicy.hpp index bf8b35887..c4df9c0f0 100644 --- a/native/jni/magiskpolicy/sepolicy.hpp +++ b/native/jni/magiskpolicy/sepolicy.hpp @@ -5,21 +5,21 @@ // Internal APIs, do not use directly struct sepol_impl : public sepolicy { - void check_avtab_node(avtab_ptr_t node); - avtab_ptr_t get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms); - bool add_rule(const char *s, const char *t, const char *c, const char *p, int effect, bool invert); - void add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, perm_datum_t *perm, int effect, bool invert); - void add_xperm_rule(type_datum_t *src, type_datum_t *tgt, - class_datum_t *cls, uint16_t low, uint16_t high, int effect, bool invert); - bool add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect, bool invert); - bool add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect); - bool add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o); - bool add_genfscon(const char *fs_name, const char *path, const char *context); - bool add_type(const char *type_name, uint32_t flavor); - bool set_type_state(const char *type_name, bool permissive); - void add_typeattribute(type_datum_t *type, type_datum_t *attr); - bool add_typeattribute(const char *type, const char *attr); - void strip_dontaudit(); + void check_avtab_node(avtab_ptr_t node); + avtab_ptr_t get_avtab_node(avtab_key_t *key, avtab_extended_perms_t *xperms); + bool add_rule(const char *s, const char *t, const char *c, const char *p, int effect, bool invert); + void add_rule(type_datum_t *src, type_datum_t *tgt, class_datum_t *cls, perm_datum_t *perm, int effect, bool invert); + void add_xperm_rule(type_datum_t *src, type_datum_t *tgt, + class_datum_t *cls, uint16_t low, uint16_t high, int effect, bool invert); + bool add_xperm_rule(const char *s, const char *t, const char *c, const char *range, int effect, bool invert); + bool add_type_rule(const char *s, const char *t, const char *c, const char *d, int effect); + bool add_filename_trans(const char *s, const char *t, const char *c, const char *d, const char *o); + bool add_genfscon(const char *fs_name, const char *path, const char *context); + bool add_type(const char *type_name, uint32_t flavor); + bool set_type_state(const char *type_name, bool permissive); + void add_typeattribute(type_datum_t *type, type_datum_t *attr); + bool add_typeattribute(const char *type, const char *attr); + void strip_dontaudit(); }; #define impl static_cast(this) diff --git a/native/jni/magiskpolicy/statement.cpp b/native/jni/magiskpolicy/statement.cpp index 1b03b02bb..19c4c55a6 100644 --- a/native/jni/magiskpolicy/statement.cpp +++ b/native/jni/magiskpolicy/statement.cpp @@ -59,7 +59,7 @@ R"EOF("genfscon fs_name partial_path fs_context" )EOF"; void statement_help() { - fprintf(stderr, + fprintf(stderr, R"EOF(One policy statement should be treated as one parameter; this means each policy statement should be enclosed in quotes. Multiple policy statements can be provided in a single command. @@ -91,65 +91,65 @@ Supported policy statements: %s )EOF", type_msg_1, type_msg_2, type_msg_3, type_msg_4, type_msg_5, type_msg_6, type_msg_7, type_msg_8, type_msg_9); - exit(0); + exit(0); } using parsed_tokens = vector>; static bool tokenize_string(char *stmt, parsed_tokens &arr) { - // cur is the pointer to where the top level is parsing - char *cur = stmt; - for (char *tok; (tok = strtok_r(nullptr, " ", &cur)) != nullptr;) { - vector token; - if (tok[0] == '{') { - // cur could point to somewhere in the braces, restore the string - if (cur) - cur[-1] = ' '; - ++tok; - char *end = strchr(tok, '}'); - if (end == nullptr) { - // Bracket not closed, syntax error - return false; - } - *end = '\0'; - for (char *sub_tok; (sub_tok = strtok_r(nullptr, " ", &tok)) != nullptr;) - token.push_back(sub_tok); - cur = end + 1; - } else if (tok[0] == '*') { - token.push_back(nullptr); - } else { - token.push_back(tok); - } - arr.push_back(std::move(token)); - } - return true; + // cur is the pointer to where the top level is parsing + char *cur = stmt; + for (char *tok; (tok = strtok_r(nullptr, " ", &cur)) != nullptr;) { + vector token; + if (tok[0] == '{') { + // cur could point to somewhere in the braces, restore the string + if (cur) + cur[-1] = ' '; + ++tok; + char *end = strchr(tok, '}'); + if (end == nullptr) { + // Bracket not closed, syntax error + return false; + } + *end = '\0'; + for (char *sub_tok; (sub_tok = strtok_r(nullptr, " ", &tok)) != nullptr;) + token.push_back(sub_tok); + cur = end + 1; + } else if (tok[0] == '*') { + token.push_back(nullptr); + } else { + token.push_back(tok); + } + arr.push_back(std::move(token)); + } + return true; } // Check array size and all args listed in 'ones' have size = 1 (no multiple entries) template static bool check_tokens(parsed_tokens &arr) { - if (arr.size() != size) - return false; - initializer_list list{ones...}; - for (int i : list) - if (arr[i].size() != 1) - return false; - return true; + if (arr.size() != size) + return false; + initializer_list list{ones...}; + for (int i : list) + if (arr[i].size() != 1) + return false; + return true; } template static bool tokenize_and_check(char *stmt, parsed_tokens &arr) { - return tokenize_string(stmt, arr) && check_tokens(arr); + return tokenize_string(stmt, arr) && check_tokens(arr); } template static void run_and_check(const Func &fn, const char *action, Args ...args) { - if (!fn(args...)) { - string s = "Error in: %s"; - for (int i = 0; i < sizeof...(args); ++i) s += " %s"; - s += "\n"; - LOGW(s.data(), action, (args ? args : "*")...); - } + if (!fn(args...)) { + string s = "Error in: %s"; + for (int i = 0; i < sizeof...(args); ++i) s += " %s"; + s += "\n"; + LOGW(s.data(), action, (args ? args : "*")...); + } } #define run_fn(...) run_and_check(fn, action, __VA_ARGS__) @@ -157,166 +157,166 @@ static void run_and_check(const Func &fn, const char *action, Args ...args) { // Pattern 1: allow { source } { target } { class } { permission } template static bool parse_pattern_1(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_and_check<4>(stmt, arr)) - return false; - for (auto src : arr[0]) - for (auto tgt : arr[1]) - for (auto cls : arr[2]) - for (auto perm : arr[3]) - run_fn(src, tgt, cls, perm); - return true; + parsed_tokens arr; + if (!tokenize_and_check<4>(stmt, arr)) + return false; + for (auto src : arr[0]) + for (auto tgt : arr[1]) + for (auto cls : arr[2]) + for (auto perm : arr[3]) + run_fn(src, tgt, cls, perm); + return true; } // Pattern 2: allowxperm { source } { target } { class } ioctl range template static bool parse_pattern_2(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_and_check<5, 3, 4>(stmt, arr) || arr[3][0] != "ioctl"sv) - return false; - auto range = arr[4][0]; - for (auto src : arr[0]) - for (auto tgt : arr[1]) - for (auto cls : arr[2]) - run_fn(src, tgt, cls, range); - return true; + parsed_tokens arr; + if (!tokenize_and_check<5, 3, 4>(stmt, arr) || arr[3][0] != "ioctl"sv) + return false; + auto range = arr[4][0]; + for (auto src : arr[0]) + for (auto tgt : arr[1]) + for (auto cls : arr[2]) + run_fn(src, tgt, cls, range); + return true; } // Pattern 3: permissive { type } template static bool parse_pattern_3(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_and_check<1>(stmt, arr)) - return false; - for (auto type : arr[0]) - run_fn(type); - return true; + parsed_tokens arr; + if (!tokenize_and_check<1>(stmt, arr)) + return false; + for (auto type : arr[0]) + run_fn(type); + return true; } // Pattern 4: typeattribute { type } { attribute } template static bool parse_pattern_4(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_and_check<2>(stmt, arr)) - return false; - for (auto type : arr[0]) - for (auto attr : arr[1]) - run_fn(type, attr); - return true; + parsed_tokens arr; + if (!tokenize_and_check<2>(stmt, arr)) + return false; + for (auto type : arr[0]) + for (auto attr : arr[1]) + run_fn(type, attr); + return true; } // Pattern 5: type name { attribute } template static bool parse_pattern_5(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - string tmp_str; - if (!tokenize_string(stmt, arr)) - return false; - if (arr.size() == 1) { - arr.emplace_back(initializer_list{ "domain" }); - } - if (!check_tokens<2, 0>(arr)) - return false; - for (auto attr : arr[1]) - run_fn(arr[0][0], attr); - return true; + parsed_tokens arr; + string tmp_str; + if (!tokenize_string(stmt, arr)) + return false; + if (arr.size() == 1) { + arr.emplace_back(initializer_list{ "domain" }); + } + if (!check_tokens<2, 0>(arr)) + return false; + for (auto attr : arr[1]) + run_fn(arr[0][0], attr); + return true; } // Pattern 6: attribute name template static bool parse_pattern_6(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_and_check<1, 0>(stmt, arr)) - return false; - run_fn(arr[0][1]); - return true; + parsed_tokens arr; + if (!tokenize_and_check<1, 0>(stmt, arr)) + return false; + run_fn(arr[0][1]); + return true; } // Pattern 7: type_transition source target class default (filename) template static bool parse_pattern_7(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_string(stmt, arr)) - return false; - if (arr.size() == 4) - arr.emplace_back(initializer_list{nullptr}); - if (!check_tokens<5, 0, 1, 2, 3, 4>(arr)) - return false; - run_fn(arr[0][0], arr[1][0], arr[2][0], arr[3][0], arr[4][0]); - return true; + parsed_tokens arr; + if (!tokenize_string(stmt, arr)) + return false; + if (arr.size() == 4) + arr.emplace_back(initializer_list{nullptr}); + if (!check_tokens<5, 0, 1, 2, 3, 4>(arr)) + return false; + run_fn(arr[0][0], arr[1][0], arr[2][0], arr[3][0], arr[4][0]); + return true; } // Pattern 8: type_change source target class default template static bool parse_pattern_8(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_and_check<4, 0, 1, 2, 3>(stmt, arr)) - return false; - run_fn(arr[0][0], arr[1][0], arr[2][0], arr[3][0]); - return true; + parsed_tokens arr; + if (!tokenize_and_check<4, 0, 1, 2, 3>(stmt, arr)) + return false; + run_fn(arr[0][0], arr[1][0], arr[2][0], arr[3][0]); + return true; } // Pattern 9: genfscon name path context template static bool parse_pattern_9(const Func &fn, const char *action, char *stmt) { - parsed_tokens arr; - if (!tokenize_and_check<3, 0, 1, 2>(stmt, arr)) - return false; - run_fn(arr[0][0], arr[1][0], arr[2][0]); - return true; + parsed_tokens arr; + if (!tokenize_and_check<3, 0, 1, 2>(stmt, arr)) + return false; + run_fn(arr[0][0], arr[1][0], arr[2][0]); + return true; } #define add_action_func(name, type, fn) \ else if (strcmp(name, action) == 0) { \ - auto __fn = [=](auto && ...args){ return (fn)(args...); };\ - if (!parse_pattern_##type(__fn, name, remain)) \ - LOGW("Syntax error in '%s'\n\n%s\n", stmt, type_msg_##type); \ + auto __fn = [=](auto && ...args){ return (fn)(args...); };\ + if (!parse_pattern_##type(__fn, name, remain)) \ + LOGW("Syntax error in '%s'\n\n%s\n", stmt, type_msg_##type); \ } #define add_action(act, type) add_action_func(#act, type, act) void sepolicy::parse_statement(const char *stmt) { - // strtok modify strings, create a copy - string cpy(stmt); + // strtok modify strings, create a copy + string cpy(stmt); - char *remain; - char *action = strtok_r(cpy.data(), " ", &remain); - if (remain == nullptr) { - LOGW("Syntax error in '%s'\n\n", stmt); - return; - } + char *remain; + char *action = strtok_r(cpy.data(), " ", &remain); + if (remain == nullptr) { + LOGW("Syntax error in '%s'\n\n", stmt); + return; + } - if (0) {} - add_action(allow, 1) - add_action(deny, 1) - add_action(auditallow, 1) - add_action(dontaudit, 1) - add_action(allowxperm, 2) - add_action(auditallowxperm, 2) - add_action(dontauditxperm, 2) - add_action(permissive, 3) - add_action(enforce, 3) - add_action(typeattribute, 4) - add_action(type, 5) - add_action(attribute, 6) - add_action(type_transition, 7) - add_action(type_change, 8) - add_action(type_member, 8) - add_action(genfscon, 9) + if (0) {} + add_action(allow, 1) + add_action(deny, 1) + add_action(auditallow, 1) + add_action(dontaudit, 1) + add_action(allowxperm, 2) + add_action(auditallowxperm, 2) + add_action(dontauditxperm, 2) + add_action(permissive, 3) + add_action(enforce, 3) + add_action(typeattribute, 4) + add_action(type, 5) + add_action(attribute, 6) + add_action(type_transition, 7) + add_action(type_change, 8) + add_action(type_member, 8) + add_action(genfscon, 9) - // Backwards compatible syntax - add_action(create, 3) - add_action_func("attradd", 4, typeattribute) - add_action_func("name_transition", 7, type_transition) + // Backwards compatible syntax + add_action(create, 3) + add_action_func("attradd", 4, typeattribute) + add_action_func("name_transition", 7, type_transition) - else { LOGW("Unknown action: '%s'\n\n", action); } + else { LOGW("Unknown action: '%s'\n\n", action); } } void sepolicy::load_rule_file(const char *file) { - file_readline(true, file, [=](string_view line) -> bool { - if (line.empty() || line[0] == '#') - return true; - parse_statement(line.data()); - return true; - }); + file_readline(true, file, [=](string_view line) -> bool { + if (line.empty() || line[0] == '#') + return true; + parse_statement(line.data()); + return true; + }); } diff --git a/native/jni/resetprop/_resetprop.hpp b/native/jni/resetprop/_resetprop.hpp index e400ba96d..6835ad13a 100644 --- a/native/jni/resetprop/_resetprop.hpp +++ b/native/jni/resetprop/_resetprop.hpp @@ -8,12 +8,12 @@ #define PERSISTENT_PROPERTY_DIR "/data/property" struct prop_cb { - virtual void exec(const char *name, const char *value) { - exec(std::string(name), value); - } - virtual void exec(std::string &&name, const char *value) { - exec(name.data(), value); - } + virtual void exec(const char *name, const char *value) { + exec(std::string(name), value); + } + virtual void exec(std::string &&name, const char *value) { + exec(name.data(), value); + } }; extern bool use_pb; @@ -21,15 +21,15 @@ extern bool use_pb; using prop_list = std::map; struct prop_collector : prop_cb { - explicit prop_collector(prop_list &list) : list(list) {} - void exec(const char *name, const char *value) override { - list.insert_or_assign(name, value); - } - void exec(std::string &&name, const char *value) override { - list.insert_or_assign(std::move(name), value); - } + explicit prop_collector(prop_list &list) : list(list) {} + void exec(const char *name, const char *value) override { + list.insert_or_assign(name, value); + } + void exec(std::string &&name, const char *value) override { + list.insert_or_assign(std::move(name), value); + } private: - prop_list &list; + prop_list &list; }; std::string persist_getprop(const char *name); diff --git a/native/jni/resetprop/persist_properties.cpp b/native/jni/resetprop/persist_properties.cpp index abc3ec303..ad0acd51b 100644 --- a/native/jni/resetprop/persist_properties.cpp +++ b/native/jni/resetprop/persist_properties.cpp @@ -23,13 +23,13 @@ using namespace std; /* Struct definitions */ struct PersistentProperties { - pb_callback_t properties; + pb_callback_t properties; }; struct PersistentProperties_PersistentPropertyRecord { - pb_callback_t name; - bool has_value; - char value[92]; + pb_callback_t name; + bool has_value; + char value[92]; }; /* Initializer values for message structs */ @@ -78,163 +78,163 @@ PB_BIND(PersistentProperties_PersistentPropertyRecord, PersistentProperties_Pers bool use_pb = false; static bool name_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { - string &name = *static_cast(*arg); - name.resize(stream->bytes_left); - return pb_read(stream, (pb_byte_t *)(name.data()), stream->bytes_left); + string &name = *static_cast(*arg); + name.resize(stream->bytes_left); + return pb_read(stream, (pb_byte_t *)(name.data()), stream->bytes_left); } static bool name_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { - return pb_encode_tag_for_field(stream, field) && - pb_encode_string(stream, (const pb_byte_t *) *arg, strlen((const char *) *arg)); + return pb_encode_tag_for_field(stream, field) && + pb_encode_string(stream, (const pb_byte_t *) *arg, strlen((const char *) *arg)); } static bool prop_decode(pb_istream_t *stream, const pb_field_t *field, void **arg) { - PersistentProperties_PersistentPropertyRecord prop{}; - string name; - prop.name.funcs.decode = name_decode; - prop.name.arg = &name; - if (!pb_decode(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop)) - return false; - auto cb = static_cast(*arg); - cb->exec(std::move(name), prop.value); - return true; + PersistentProperties_PersistentPropertyRecord prop{}; + string name; + prop.name.funcs.decode = name_decode; + prop.name.arg = &name; + if (!pb_decode(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop)) + return false; + auto cb = static_cast(*arg); + cb->exec(std::move(name), prop.value); + return true; } static bool prop_encode(pb_ostream_t *stream, const pb_field_t *field, void * const *arg) { - PersistentProperties_PersistentPropertyRecord prop{}; - prop.name.funcs.encode = name_encode; - prop.has_value = true; - auto &list = *static_cast(*arg); - for (auto &p : list) { - if (!pb_encode_tag_for_field(stream, field)) - return false; - prop.name.arg = (void *) p.first.data(); - strcpy(prop.value, p.second.data()); - if (!pb_encode_submessage(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop)) - return false; - } - return true; + PersistentProperties_PersistentPropertyRecord prop{}; + prop.name.funcs.encode = name_encode; + prop.has_value = true; + auto &list = *static_cast(*arg); + for (auto &p : list) { + if (!pb_encode_tag_for_field(stream, field)) + return false; + prop.name.arg = (void *) p.first.data(); + strcpy(prop.value, p.second.data()); + if (!pb_encode_submessage(stream, &PersistentProperties_PersistentPropertyRecord_msg, &prop)) + return false; + } + return true; } static bool write_callback(pb_ostream_t *stream, const uint8_t *buf, size_t count) { - int fd = (intptr_t)stream->state; - return xwrite(fd, buf, count) == count; + int fd = (intptr_t)stream->state; + return xwrite(fd, buf, count) == count; } static pb_ostream_t create_ostream(const char *filename) { - int fd = creat(filename, 0644); - pb_ostream_t o = { - .callback = write_callback, - .state = (void*)(intptr_t)fd, - .max_size = SIZE_MAX, - .bytes_written = 0, - }; - return o; + int fd = creat(filename, 0644); + pb_ostream_t o = { + .callback = write_callback, + .state = (void*)(intptr_t)fd, + .max_size = SIZE_MAX, + .bytes_written = 0, + }; + return o; } static void pb_getprop(prop_cb *prop_cb) { - LOGD("resetprop: decode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n"); - PersistentProperties props = {}; - props.properties.funcs.decode = prop_decode; - props.properties.arg = prop_cb; - pb_byte_t *buf; - size_t size; - mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", buf, size); - pb_istream_t stream = pb_istream_from_buffer(buf, size); - pb_decode(&stream, &PersistentProperties_msg, &props); - munmap(buf, size); + LOGD("resetprop: decode with protobuf [" PERSISTENT_PROPERTY_DIR "/persistent_properties]\n"); + PersistentProperties props = {}; + props.properties.funcs.decode = prop_decode; + props.properties.arg = prop_cb; + pb_byte_t *buf; + size_t size; + mmap_ro(PERSISTENT_PROPERTY_DIR "/persistent_properties", buf, size); + pb_istream_t stream = pb_istream_from_buffer(buf, size); + pb_decode(&stream, &PersistentProperties_msg, &props); + munmap(buf, size); } static bool file_getprop(const char *name, char *value) { - char path[4096]; - snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); - int fd = open(path, O_RDONLY | O_CLOEXEC); - if (fd < 0) - return false; - LOGD("resetprop: read prop from [%s]\n", path); - value[read(fd, value, PROP_VALUE_MAX - 1)] = '\0'; // Null terminate the read value - close(fd); - return value[0] != '\0'; + char path[4096]; + snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); + int fd = open(path, O_RDONLY | O_CLOEXEC); + if (fd < 0) + return false; + LOGD("resetprop: read prop from [%s]\n", path); + value[read(fd, value, PROP_VALUE_MAX - 1)] = '\0'; // Null terminate the read value + close(fd); + return value[0] != '\0'; } void persist_getprops(prop_cb *prop_cb) { - if (use_pb) { - pb_getprop(prop_cb); - } else { - auto dir = open_dir(PERSISTENT_PROPERTY_DIR); - if (!dir) return; - for (dirent *entry; (entry = xreaddir(dir.get()));) { - char value[PROP_VALUE_MAX]; - if (file_getprop(entry->d_name, value)) - prop_cb->exec(entry->d_name, value); - } - } + if (use_pb) { + pb_getprop(prop_cb); + } else { + auto dir = open_dir(PERSISTENT_PROPERTY_DIR); + if (!dir) return; + for (dirent *entry; (entry = xreaddir(dir.get()));) { + char value[PROP_VALUE_MAX]; + if (file_getprop(entry->d_name, value)) + prop_cb->exec(entry->d_name, value); + } + } } struct match_prop_name : prop_cb { - explicit match_prop_name(const char *name) : _name(name) { value[0] = '\0'; } - void exec(string &&name, const char *val) override { - if (name == _name) - strcpy(value, val); - } - char value[PROP_VALUE_MAX]; + explicit match_prop_name(const char *name) : _name(name) { value[0] = '\0'; } + void exec(string &&name, const char *val) override { + if (name == _name) + strcpy(value, val); + } + char value[PROP_VALUE_MAX]; private: - const char *_name; + const char *_name; }; string persist_getprop(const char *name) { - if (use_pb) { - auto prop = match_prop_name(name); - pb_getprop(&prop); - if (prop.value[0]) { - LOGD("resetprop: getprop (persist) [%s]: [%s]\n", name, prop.value); - return prop.value; - } - } else { - // Try to read from file - char value[PROP_VALUE_MAX]; - if (file_getprop(name, value)) { - LOGD("resetprop: getprop (persist) [%s]: [%s]\n", name, value); - return value; - } - } - return string(); + if (use_pb) { + auto prop = match_prop_name(name); + pb_getprop(&prop); + if (prop.value[0]) { + LOGD("resetprop: getprop (persist) [%s]: [%s]\n", name, prop.value); + return prop.value; + } + } else { + // Try to read from file + char value[PROP_VALUE_MAX]; + if (file_getprop(name, value)) { + LOGD("resetprop: getprop (persist) [%s]: [%s]\n", name, value); + return value; + } + } + return string(); } bool persist_deleteprop(const char *name) { - if (use_pb) { - prop_list list; - prop_collector collector(list); - persist_getprops(&collector); + if (use_pb) { + prop_list list; + prop_collector collector(list); + persist_getprops(&collector); - for (auto it = list.begin(); it != list.end(); ++it) { - if (it->first == name) { - list.erase(it); - // Dump the props back - PersistentProperties props{}; - pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR - "/persistent_properties.tmp"); - props.properties.funcs.encode = prop_encode; - props.properties.arg = &list; - LOGD("resetprop: encode with protobuf [" PERSISTENT_PROPERTY_DIR - "/persistent_properties.tmp]\n"); - if (!pb_encode(&ostream, &PersistentProperties_msg, &props)) - return false; - clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties", - PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); - rename(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp", - PERSISTENT_PROPERTY_DIR "/persistent_properties"); - return true; - } - } - return false; - } else { - char path[4096]; - snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); - if (unlink(path) == 0) { - LOGD("resetprop: unlink [%s]\n", path); - return true; - } - } - return false; + for (auto it = list.begin(); it != list.end(); ++it) { + if (it->first == name) { + list.erase(it); + // Dump the props back + PersistentProperties props{}; + pb_ostream_t ostream = create_ostream(PERSISTENT_PROPERTY_DIR + "/persistent_properties.tmp"); + props.properties.funcs.encode = prop_encode; + props.properties.arg = &list; + LOGD("resetprop: encode with protobuf [" PERSISTENT_PROPERTY_DIR + "/persistent_properties.tmp]\n"); + if (!pb_encode(&ostream, &PersistentProperties_msg, &props)) + return false; + clone_attr(PERSISTENT_PROPERTY_DIR "/persistent_properties", + PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp"); + rename(PERSISTENT_PROPERTY_DIR "/persistent_properties.tmp", + PERSISTENT_PROPERTY_DIR "/persistent_properties"); + return true; + } + } + return false; + } else { + char path[4096]; + snprintf(path, sizeof(path), PERSISTENT_PROPERTY_DIR "/%s", name); + if (unlink(path) == 0) { + LOGD("resetprop: unlink [%s]\n", path); + return true; + } + } + return false; } diff --git a/native/jni/resetprop/resetprop.cpp b/native/jni/resetprop/resetprop.cpp index 026798d12..f8596e127 100644 --- a/native/jni/resetprop/resetprop.cpp +++ b/native/jni/resetprop/resetprop.cpp @@ -26,24 +26,24 @@ static int (*system_property_set)(const char*, const char*); static int (*system_property_read)(const prop_info*, char*, char*); static const prop_info *(*system_property_find)(const char*); static void (*system_property_read_callback)( - const prop_info*, void (*)(void*, const char*, const char*, uint32_t), void*); + const prop_info*, void (*)(void*, const char*, const char*, uint32_t), void*); static int (*system_property_foreach)(void (*)(const prop_info*, void*), void*); #define DLOAD(name) \ *(void **) &name = dlsym(RTLD_DEFAULT, "__" #name) static void load_functions() { - DLOAD(system_property_set); - DLOAD(system_property_read); - DLOAD(system_property_find); - DLOAD(system_property_read_callback); - DLOAD(system_property_foreach); + DLOAD(system_property_set); + DLOAD(system_property_read); + DLOAD(system_property_find); + DLOAD(system_property_read_callback); + DLOAD(system_property_foreach); } #undef DLOAD #endif [[noreturn]] static void usage(char* arg0) { - fprintf(stderr, + fprintf(stderr, R"EOF(resetprop - System Property Manipulation Tool Usage: %s [flags] [options...] @@ -64,187 +64,187 @@ Flags: (this flag only affects getprop and delprop) )EOF", arg0); - exit(1); + exit(1); } static bool check_legal_property_name(const char *name) { - int namelen = strlen(name); + int namelen = strlen(name); - if (namelen < 1) goto illegal; - if (name[0] == '.') goto illegal; - if (name[namelen - 1] == '.') goto illegal; + if (namelen < 1) goto illegal; + if (name[0] == '.') goto illegal; + if (name[namelen - 1] == '.') goto illegal; - /* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */ - /* Don't allow ".." to appear in a property name */ - for (size_t i = 0; i < namelen; i++) { - if (name[i] == '.') { - // i=0 is guaranteed to never have a dot. See above. - if (name[i-1] == '.') goto illegal; - continue; - } - if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue; - if (name[i] >= 'a' && name[i] <= 'z') continue; - if (name[i] >= 'A' && name[i] <= 'Z') continue; - if (name[i] >= '0' && name[i] <= '9') continue; - goto illegal; - } + /* Only allow alphanumeric, plus '.', '-', '@', ':', or '_' */ + /* Don't allow ".." to appear in a property name */ + for (size_t i = 0; i < namelen; i++) { + if (name[i] == '.') { + // i=0 is guaranteed to never have a dot. See above. + if (name[i-1] == '.') goto illegal; + continue; + } + if (name[i] == '_' || name[i] == '-' || name[i] == '@' || name[i] == ':') continue; + if (name[i] >= 'a' && name[i] <= 'z') continue; + if (name[i] >= 'A' && name[i] <= 'Z') continue; + if (name[i] >= '0' && name[i] <= '9') continue; + goto illegal; + } - return true; + return true; illegal: - LOGE("Illegal property name: [%s]\n", name); - return false; + LOGE("Illegal property name: [%s]\n", name); + return false; } static void read_prop(const prop_info *pi, void *cb) { - if (system_property_read_callback) { - auto callback = [](void *cb, const char *name, const char *value, uint32_t) { - static_cast(cb)->exec(name, value); - }; - system_property_read_callback(pi, callback, cb); - } else { - char name[PROP_NAME_MAX]; - char value[PROP_VALUE_MAX]; - name[0] = '\0'; - value[0] = '\0'; - system_property_read(pi, name, value); - static_cast(cb)->exec(name, value); - } + if (system_property_read_callback) { + auto callback = [](void *cb, const char *name, const char *value, uint32_t) { + static_cast(cb)->exec(name, value); + }; + system_property_read_callback(pi, callback, cb); + } else { + char name[PROP_NAME_MAX]; + char value[PROP_VALUE_MAX]; + name[0] = '\0'; + value[0] = '\0'; + system_property_read(pi, name, value); + static_cast(cb)->exec(name, value); + } } struct sysprop_stub { - virtual int setprop(const char *name, const char *value, bool trigger) { return 1; } - virtual string getprop(const char *name, bool persist) { return string(); } - virtual void getprops(void (*callback)(const char *, const char *, void *), - void *cookie, bool persist) {} - virtual int delprop(const char *name, bool persist) { return 1; } + virtual int setprop(const char *name, const char *value, bool trigger) { return 1; } + virtual string getprop(const char *name, bool persist) { return string(); } + virtual void getprops(void (*callback)(const char *, const char *, void *), + void *cookie, bool persist) {} + virtual int delprop(const char *name, bool persist) { return 1; } }; struct sysprop : public sysprop_stub { - int setprop(const char *name, const char *value, bool) override { - if (!check_legal_property_name(name)) - return 1; - return system_property_set(name, value); - } + int setprop(const char *name, const char *value, bool) override { + if (!check_legal_property_name(name)) + return 1; + return system_property_set(name, value); + } - struct prop_to_string : prop_cb { - explicit prop_to_string(string &s) : val(s) {} - void exec(const char *, const char *value) override { - val = value; - } - private: - string &val; - }; + struct prop_to_string : prop_cb { + explicit prop_to_string(string &s) : val(s) {} + void exec(const char *, const char *value) override { + val = value; + } + private: + string &val; + }; - string getprop(const char *name, bool) override { - string val; - if (!check_legal_property_name(name)) - return val; - auto pi = system_property_find(name); - if (pi == nullptr) - return val; - auto prop = prop_to_string(val); - read_prop(pi, &prop); - LOGD("resetprop: getprop [%s]: [%s]\n", name, val.data()); - return val; - } + string getprop(const char *name, bool) override { + string val; + if (!check_legal_property_name(name)) + return val; + auto pi = system_property_find(name); + if (pi == nullptr) + return val; + auto prop = prop_to_string(val); + read_prop(pi, &prop); + LOGD("resetprop: getprop [%s]: [%s]\n", name, val.data()); + return val; + } - void getprops(void (*callback)(const char*, const char*, void*), void *cookie, bool) override { - prop_list list; - prop_collector collector(list); - system_property_foreach(read_prop, &collector); - for (auto &[key, val] : list) - callback(key.data(), val.data(), cookie); - } + void getprops(void (*callback)(const char*, const char*, void*), void *cookie, bool) override { + prop_list list; + prop_collector collector(list); + system_property_foreach(read_prop, &collector); + for (auto &[key, val] : list) + callback(key.data(), val.data(), cookie); + } }; struct resetprop : public sysprop { - int setprop(const char *name, const char *value, bool prop_svc) override { - if (!check_legal_property_name(name)) - return 1; + int setprop(const char *name, const char *value, bool prop_svc) override { + if (!check_legal_property_name(name)) + return 1; - const char *msg = prop_svc ? "property_service" : "modifying prop data structure"; + const char *msg = prop_svc ? "property_service" : "modifying prop data structure"; - int ret; - auto pi = const_cast(__system_property_find(name)); - if (pi != nullptr) { - if (prop_svc) { - if (strncmp(name, "ro.", 3) == 0) - delprop(name, false); - ret = system_property_set(name, value); - } else { - ret = __system_property_update(pi, value, strlen(value)); - } - LOGD("resetprop: update prop [%s]: [%s] by %s\n", name, value, msg); - } else { - if (prop_svc) { - ret = system_property_set(name, value); - } else { - ret = __system_property_add(name, strlen(name), value, strlen(value)); - } - LOGD("resetprop: create prop [%s]: [%s] by %s\n", name, value, msg); - } + int ret; + auto pi = const_cast(__system_property_find(name)); + if (pi != nullptr) { + if (prop_svc) { + if (strncmp(name, "ro.", 3) == 0) + delprop(name, false); + ret = system_property_set(name, value); + } else { + ret = __system_property_update(pi, value, strlen(value)); + } + LOGD("resetprop: update prop [%s]: [%s] by %s\n", name, value, msg); + } else { + if (prop_svc) { + ret = system_property_set(name, value); + } else { + ret = __system_property_add(name, strlen(name), value, strlen(value)); + } + LOGD("resetprop: create prop [%s]: [%s] by %s\n", name, value, msg); + } - if (ret) - LOGW("resetprop: setprop error\n"); + if (ret) + LOGW("resetprop: setprop error\n"); - return ret; - } + return ret; + } - string getprop(const char *name, bool persist) override { - string val = sysprop::getprop(name, persist); - if (val.empty() && persist && strncmp(name, "persist.", 8) == 0) - val = persist_getprop(name); - if (val.empty()) - LOGD("resetprop: prop [%s] does not exist\n", name); - return val; - } + string getprop(const char *name, bool persist) override { + string val = sysprop::getprop(name, persist); + if (val.empty() && persist && strncmp(name, "persist.", 8) == 0) + val = persist_getprop(name); + if (val.empty()) + LOGD("resetprop: prop [%s] does not exist\n", name); + return val; + } - void getprops(void (*callback)(const char *, const char *, void *), - void *cookie, bool persist) override { - prop_list list; - prop_collector collector(list); - system_property_foreach(read_prop, &collector); - if (persist) - persist_getprops(&collector); - for (auto &[key, val] : list) - callback(key.data(), val.data(), cookie); - } + void getprops(void (*callback)(const char *, const char *, void *), + void *cookie, bool persist) override { + prop_list list; + prop_collector collector(list); + system_property_foreach(read_prop, &collector); + if (persist) + persist_getprops(&collector); + for (auto &[key, val] : list) + callback(key.data(), val.data(), cookie); + } - int delprop(const char *name, bool persist) override { - if (!check_legal_property_name(name)) - return 1; - LOGD("resetprop: delete prop [%s]\n", name); - if (persist && strncmp(name, "persist.", 8) == 0) - persist = persist_deleteprop(name); - return __system_property_delete(name) && !(persist && strncmp(name, "persist.", 8) == 0); - } + int delprop(const char *name, bool persist) override { + if (!check_legal_property_name(name)) + return 1; + LOGD("resetprop: delete prop [%s]\n", name); + if (persist && strncmp(name, "persist.", 8) == 0) + persist = persist_deleteprop(name); + return __system_property_delete(name) && !(persist && strncmp(name, "persist.", 8) == 0); + } }; static sysprop_stub *get_impl() { - static sysprop_stub *impl = nullptr; - if (impl == nullptr) { - use_pb = access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0; + static sysprop_stub *impl = nullptr; + if (impl == nullptr) { + use_pb = access(PERSISTENT_PROPERTY_DIR "/persistent_properties", R_OK) == 0; #ifdef APPLET_STUB_MAIN - if (__system_properties_init()) { - LOGE("resetprop: __system_properties_init error\n"); - exit(1); - } - impl = new resetprop(); + if (__system_properties_init()) { + LOGE("resetprop: __system_properties_init error\n"); + exit(1); + } + impl = new resetprop(); #else - // Load platform implementations - load_functions(); - if (__system_properties_init()) { - LOGW("resetprop: __system_properties_init error\n"); - impl = new sysprop(); - } else { - impl = new resetprop(); - } + // Load platform implementations + load_functions(); + if (__system_properties_init()) { + LOGW("resetprop: __system_properties_init error\n"); + impl = new sysprop(); + } else { + impl = new resetprop(); + } #endif - } - return impl; + } + return impl; } /*********************************** @@ -252,94 +252,94 @@ static sysprop_stub *get_impl() { ***********************************/ static void print_props(bool persist) { - getprops([](const char *name, const char *value, auto) { - printf("[%s]: [%s]\n", name, value); - }, nullptr, persist); + getprops([](const char *name, const char *value, auto) { + printf("[%s]: [%s]\n", name, value); + }, nullptr, persist); } string getprop(const char *name, bool persist) { - return get_impl()->getprop(name, persist); + return get_impl()->getprop(name, persist); } void getprops(void (*callback)(const char *, const char *, void *), void *cookie, bool persist) { - get_impl()->getprops(callback, cookie, persist); + get_impl()->getprops(callback, cookie, persist); } int setprop(const char *name, const char *value, bool prop_svc) { - return get_impl()->setprop(name, value, prop_svc); + return get_impl()->setprop(name, value, prop_svc); } int delprop(const char *name, bool persist) { - return get_impl()->delprop(name, persist); + return get_impl()->delprop(name, persist); } void load_prop_file(const char *filename, bool prop_svc) { - auto impl = get_impl(); - LOGD("resetprop: Parse prop file [%s]\n", filename); - parse_prop_file(filename, [=](auto key, auto val) -> bool { - impl->setprop(key.data(), val.data(), prop_svc); - return true; - }); + auto impl = get_impl(); + LOGD("resetprop: Parse prop file [%s]\n", filename); + parse_prop_file(filename, [=](auto key, auto val) -> bool { + impl->setprop(key.data(), val.data(), prop_svc); + return true; + }); } int resetprop_main(int argc, char *argv[]) { - log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; }; + log_cb.d = [](auto fmt, auto ap) -> int { return verbose ? vfprintf(stderr, fmt, ap) : 0; }; - bool prop_svc = true; - bool persist = false; - char *argv0 = argv[0]; + bool prop_svc = true; + bool persist = false; + char *argv0 = argv[0]; - --argc; - ++argv; + --argc; + ++argv; - // Parse flags and -- options - while (argc && argv[0][0] == '-') { - for (int idx = 1; true; ++idx) { - switch (argv[0][idx]) { - case '-': - if (strcmp(argv[0], "--file") == 0 && argc == 2) { - load_prop_file(argv[1], prop_svc); - return 0; - } else if (strcmp(argv[0], "--delete") == 0 && argc == 2) { - return delprop(argv[1], persist); - } else if (strcmp(argv[0], "--help") == 0) { - usage(argv0); - } - case 'v': - verbose = true; - continue; - case 'p': - persist = true; - continue; - case 'n': - prop_svc = false; - continue; - case '\0': - break; - case 'h': - default: - usage(argv0); - } - break; - } - --argc; - ++argv; - } + // Parse flags and -- options + while (argc && argv[0][0] == '-') { + for (int idx = 1; true; ++idx) { + switch (argv[0][idx]) { + case '-': + if (strcmp(argv[0], "--file") == 0 && argc == 2) { + load_prop_file(argv[1], prop_svc); + return 0; + } else if (strcmp(argv[0], "--delete") == 0 && argc == 2) { + return delprop(argv[1], persist); + } else if (strcmp(argv[0], "--help") == 0) { + usage(argv0); + } + case 'v': + verbose = true; + continue; + case 'p': + persist = true; + continue; + case 'n': + prop_svc = false; + continue; + case '\0': + break; + case 'h': + default: + usage(argv0); + } + break; + } + --argc; + ++argv; + } - switch (argc) { - case 0: - print_props(persist); - return 0; - case 1: { - string prop = getprop(argv[0], persist); - if (prop.empty()) - return 1; - printf("%s\n", prop.data()); - return 0; - } - case 2: - return setprop(argv[0], argv[1], prop_svc); - default: - usage(argv0); - } + switch (argc) { + case 0: + print_props(persist); + return 0; + case 1: { + string prop = getprop(argv[0], persist); + if (prop.empty()) + return 1; + printf("%s\n", prop.data()); + return 0; + } + case 2: + return setprop(argv[0], argv[1], prop_svc); + default: + usage(argv0); + } } diff --git a/native/jni/su/connect.cpp b/native/jni/su/connect.cpp index 5e5b4908c..c1a829487 100644 --- a/native/jni/su/connect.cpp +++ b/native/jni/su/connect.cpp @@ -10,9 +10,9 @@ using namespace std; enum { - NAMED_ACTIVITY, - PKG_ACTIVITY, - CONTENT_PROVIDER + NAMED_ACTIVITY, + PKG_ACTIVITY, + CONTENT_PROVIDER }; #define CALL_PROVIDER \ @@ -34,179 +34,179 @@ enum { (to.command[0] ? to.command : to.shell[0] ? to.shell : DEFAULT_SHELL) class Extra { - const char *key; - enum { - INT, - BOOL, - STRING - } type; - union { - int int_val; - bool bool_val; - const char * str_val; - }; - char buf[32]; + const char *key; + enum { + INT, + BOOL, + STRING + } type; + union { + int int_val; + bool bool_val; + const char * str_val; + }; + char buf[32]; public: - Extra(const char *k, int v): key(k), type(INT), int_val(v) {} - Extra(const char *k, bool v): key(k), type(BOOL), bool_val(v) {} - Extra(const char *k, const char *v): key(k), type(STRING), str_val(v) {} + Extra(const char *k, int v): key(k), type(INT), int_val(v) {} + Extra(const char *k, bool v): key(k), type(BOOL), bool_val(v) {} + Extra(const char *k, const char *v): key(k), type(STRING), str_val(v) {} - void add_intent(vector &vec) { - const char *val; - switch (type) { - case INT: - vec.push_back("--ei"); - sprintf(buf, "%d", int_val); - val = buf; - break; - case BOOL: - vec.push_back("--ez"); - val = bool_val ? "true" : "false"; - break; - case STRING: - vec.push_back("--es"); - val = str_val; - break; - } - vec.push_back(key); - vec.push_back(val); - } + void add_intent(vector &vec) { + const char *val; + switch (type) { + case INT: + vec.push_back("--ei"); + sprintf(buf, "%d", int_val); + val = buf; + break; + case BOOL: + vec.push_back("--ez"); + val = bool_val ? "true" : "false"; + break; + case STRING: + vec.push_back("--es"); + val = str_val; + break; + } + vec.push_back(key); + vec.push_back(val); + } - void add_bind(vector &vec) { - switch (type) { - case INT: - sprintf(buf, "%s:i:%d", key, int_val); - break; - case BOOL: - sprintf(buf, "%s:b:%s", key, bool_val ? "true" : "false"); - break; - case STRING: - sprintf(buf, "%s:s:%s", key, str_val); - break; - } - vec.push_back("--extra"); - vec.push_back(buf); - } + void add_bind(vector &vec) { + switch (type) { + case INT: + sprintf(buf, "%s:i:%d", key, int_val); + break; + case BOOL: + sprintf(buf, "%s:b:%s", key, bool_val ? "true" : "false"); + break; + case STRING: + sprintf(buf, "%s:s:%s", key, str_val); + break; + } + vec.push_back("--extra"); + vec.push_back(buf); + } }; static bool check_no_error(int fd) { - char buf[1024]; - auto out = xopen_file(fd, "r"); - while (fgets(buf, sizeof(buf), out.get())) { - if (strncmp(buf, "Error", 5) == 0) - return false; - } - return true; + char buf[1024]; + auto out = xopen_file(fd, "r"); + while (fgets(buf, sizeof(buf), out.get())) { + if (strncmp(buf, "Error", 5) == 0) + return false; + } + return true; } static void exec_cmd(const char *action, vector &data, - const shared_ptr &info, int mode = CONTENT_PROVIDER) { - char target[128]; - char user[4]; - sprintf(user, "%d", get_user(info)); + const shared_ptr &info, int mode = CONTENT_PROVIDER) { + char target[128]; + char user[4]; + sprintf(user, "%d", get_user(info)); - // First try content provider call method - if (mode >= CONTENT_PROVIDER) { - sprintf(target, "content://%s.provider", info->str[SU_MANAGER].data()); - vector args{ CALL_PROVIDER }; - for (auto &e : data) { - e.add_bind(args); - } - args.push_back(nullptr); - exec_t exec { - .err = true, - .fd = -1, - .pre_exec = [] { setenv("CLASSPATH", "/system/framework/content.jar", 1); }, - .argv = args.data() - }; - exec_command_sync(exec); - if (check_no_error(exec.fd)) - return; - } + // First try content provider call method + if (mode >= CONTENT_PROVIDER) { + sprintf(target, "content://%s.provider", info->str[SU_MANAGER].data()); + vector args{ CALL_PROVIDER }; + for (auto &e : data) { + e.add_bind(args); + } + args.push_back(nullptr); + exec_t exec { + .err = true, + .fd = -1, + .pre_exec = [] { setenv("CLASSPATH", "/system/framework/content.jar", 1); }, + .argv = args.data() + }; + exec_command_sync(exec); + if (check_no_error(exec.fd)) + return; + } - vector args{ START_ACTIVITY }; - for (auto &e : data) { - e.add_intent(args); - } - args.push_back(nullptr); - exec_t exec { - .err = true, - .fd = -1, - .pre_exec = [] { setenv("CLASSPATH", "/system/framework/am.jar", 1); }, - .argv = args.data() - }; + vector args{ START_ACTIVITY }; + for (auto &e : data) { + e.add_intent(args); + } + args.push_back(nullptr); + exec_t exec { + .err = true, + .fd = -1, + .pre_exec = [] { setenv("CLASSPATH", "/system/framework/am.jar", 1); }, + .argv = args.data() + }; - if (mode >= PKG_ACTIVITY) { - // Then try start activity without component name - strcpy(target, info->str[SU_MANAGER].data()); - exec_command_sync(exec); - if (check_no_error(exec.fd)) - return; - } + if (mode >= PKG_ACTIVITY) { + // Then try start activity without component name + strcpy(target, info->str[SU_MANAGER].data()); + exec_command_sync(exec); + if (check_no_error(exec.fd)) + return; + } - // Finally, fallback to start activity with component name - args[4] = "-n"; - sprintf(target, "%s/a.m", info->str[SU_MANAGER].data()); - exec.fd = -2; - exec.fork = fork_dont_care; - exec_command(exec); + // Finally, fallback to start activity with component name + args[4] = "-n"; + sprintf(target, "%s/a.m", info->str[SU_MANAGER].data()); + exec.fd = -2; + exec.fork = fork_dont_care; + exec_command(exec); } void app_log(const su_context &ctx) { - if (fork_dont_care() == 0) { - vector extras; - extras.reserve(6); - extras.emplace_back("from.uid", ctx.info->uid); - extras.emplace_back("to.uid", ctx.req.uid); - extras.emplace_back("pid", ctx.pid); - extras.emplace_back("policy", ctx.info->access.policy); - extras.emplace_back("command", get_cmd(ctx.req)); - extras.emplace_back("notify", (bool) ctx.info->access.notify); + if (fork_dont_care() == 0) { + vector extras; + extras.reserve(6); + extras.emplace_back("from.uid", ctx.info->uid); + extras.emplace_back("to.uid", ctx.req.uid); + extras.emplace_back("pid", ctx.pid); + extras.emplace_back("policy", ctx.info->access.policy); + extras.emplace_back("command", get_cmd(ctx.req)); + extras.emplace_back("notify", (bool) ctx.info->access.notify); - exec_cmd("log", extras, ctx.info); - exit(0); - } + exec_cmd("log", extras, ctx.info); + exit(0); + } } void app_notify(const su_context &ctx) { - if (fork_dont_care() == 0) { - vector extras; - extras.reserve(2); - extras.emplace_back("from.uid", ctx.info->uid); - extras.emplace_back("policy", ctx.info->access.policy); + if (fork_dont_care() == 0) { + vector extras; + extras.reserve(2); + extras.emplace_back("from.uid", ctx.info->uid); + extras.emplace_back("policy", ctx.info->access.policy); - exec_cmd("notify", extras, ctx.info); - exit(0); - } + exec_cmd("notify", extras, ctx.info); + exit(0); + } } int app_request(const shared_ptr &info) { - // Create FIFO - char fifo[64]; - strcpy(fifo, "/dev/socket/"); - gen_rand_str(fifo + 12, 32, true); - mkfifo(fifo, 0600); - chown(fifo, info->mgr_st.st_uid, info->mgr_st.st_gid); - setfilecon(fifo, "u:object_r:" SEPOL_FILE_TYPE ":s0"); + // Create FIFO + char fifo[64]; + strcpy(fifo, "/dev/socket/"); + gen_rand_str(fifo + 12, 32, true); + mkfifo(fifo, 0600); + chown(fifo, info->mgr_st.st_uid, info->mgr_st.st_gid); + setfilecon(fifo, "u:object_r:" SEPOL_FILE_TYPE ":s0"); - // Send request - vector extras; - extras.reserve(2); - extras.emplace_back("fifo", fifo); - extras.emplace_back("uid", info->uid); - exec_cmd("request", extras, info, PKG_ACTIVITY); + // Send request + vector extras; + extras.reserve(2); + extras.emplace_back("fifo", fifo); + extras.emplace_back("uid", info->uid); + exec_cmd("request", extras, info, PKG_ACTIVITY); - // Wait for data input for at most 70 seconds - int fd = xopen(fifo, O_RDONLY | O_CLOEXEC); - struct pollfd pfd = { - .fd = fd, - .events = POLL_IN - }; - if (xpoll(&pfd, 1, 70 * 1000) <= 0) { - close(fd); - fd = -1; - } + // Wait for data input for at most 70 seconds + int fd = xopen(fifo, O_RDONLY | O_CLOEXEC); + struct pollfd pfd = { + .fd = fd, + .events = POLL_IN + }; + if (xpoll(&pfd, 1, 70 * 1000) <= 0) { + close(fd); + fd = -1; + } - unlink(fifo); - return fd; + unlink(fifo); + return fd; } diff --git a/native/jni/su/pts.cpp b/native/jni/su/pts.cpp index 7000cc881..32e2aa5be 100644 --- a/native/jni/su/pts.cpp +++ b/native/jni/su/pts.cpp @@ -26,16 +26,16 @@ */ // Ensures all the data is written out static int write_blocking(int fd, char *buf, ssize_t bufsz) { - ssize_t ret, written; + ssize_t ret, written; - written = 0; - do { - ret = write(fd, buf + written, bufsz - written); - if (ret == -1) return -1; - written += ret; - } while (written < bufsz); + written = 0; + do { + ret = write(fd, buf + written, bufsz - written); + if (ret == -1) return -1; + written += ret; + } while (written < bufsz); - return 0; + return 0; } /** @@ -43,28 +43,28 @@ static int write_blocking(int fd, char *buf, ssize_t bufsz) { * true, then close the output FD when we're done. */ static void pump(int input, int output, bool close_output = true) { - char buf[4096]; - int len; - while ((len = read(input, buf, 4096)) > 0) { - if (write_blocking(output, buf, len) == -1) break; - } - close(input); - if (close_output) close(output); + char buf[4096]; + int len; + while ((len = read(input, buf, 4096)) > 0) { + if (write_blocking(output, buf, len) == -1) break; + } + close(input); + if (close_output) close(output); } static void* pump_thread(void* data) { - int *fds = (int*) data; - pump(fds[0], fds[1]); - delete[] fds; - return nullptr; + int *fds = (int*) data; + pump(fds[0], fds[1]); + delete[] fds; + return nullptr; } static void pump_async(int input, int output) { - pthread_t writer; - int *fds = new int[2]; - fds[0] = input; - fds[1] = output; - pthread_create(&writer, nullptr, pump_thread, fds); + pthread_t writer; + int *fds = new int[2]; + fds[0] = input; + fds[1] = output; + pthread_create(&writer, nullptr, pump_thread, fds); } @@ -82,31 +82,31 @@ static void pump_async(int input, int output) { * on success, the file descriptor of the master device is returned. */ int pts_open(char *slave_name, size_t slave_name_size) { - int fdm; + int fdm; - // Open master ptmx device - fdm = open("/dev/ptmx", O_RDWR); - if (fdm == -1) - goto error; + // Open master ptmx device + fdm = open("/dev/ptmx", O_RDWR); + if (fdm == -1) + goto error; - // Get the slave name - if (ptsname_r(fdm, slave_name, slave_name_size-1)) - goto error; + // Get the slave name + if (ptsname_r(fdm, slave_name, slave_name_size-1)) + goto error; - slave_name[slave_name_size - 1] = '\0'; + slave_name[slave_name_size - 1] = '\0'; - // Grant, then unlock - if (grantpt(fdm) == -1) - goto error; + // Grant, then unlock + if (grantpt(fdm) == -1) + goto error; - if (unlockpt(fdm) == -1) - goto error; + if (unlockpt(fdm) == -1) + goto error; - return fdm; + return fdm; error: - close(fdm); - PLOGE("pts_open"); - return -1; + close(fdm); + PLOGE("pts_open"); + return -1; } // Stores the previous termios of stdin @@ -124,31 +124,31 @@ static int stdin_is_raw = 0; * on success 0 */ int set_stdin_raw(void) { - struct termios new_termios; + struct termios new_termios; - // Save the current stdin termios - if (tcgetattr(STDIN_FILENO, &old_stdin) < 0) { - return -1; - } + // Save the current stdin termios + if (tcgetattr(STDIN_FILENO, &old_stdin) < 0) { + return -1; + } - // Start from the current settings - new_termios = old_stdin; + // Start from the current settings + new_termios = old_stdin; - // Make the terminal like an SSH or telnet client - new_termios.c_iflag |= IGNPAR; - new_termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); - new_termios.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); - new_termios.c_oflag &= ~OPOST; - new_termios.c_cc[VMIN] = 1; - new_termios.c_cc[VTIME] = 0; + // Make the terminal like an SSH or telnet client + new_termios.c_iflag |= IGNPAR; + new_termios.c_iflag &= ~(ISTRIP | INLCR | IGNCR | ICRNL | IXON | IXANY | IXOFF); + new_termios.c_lflag &= ~(ISIG | ICANON | ECHO | ECHOE | ECHOK | ECHONL); + new_termios.c_oflag &= ~OPOST; + new_termios.c_cc[VMIN] = 1; + new_termios.c_cc[VTIME] = 0; - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_termios) < 0) { - return -1; - } + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &new_termios) < 0) { + return -1; + } - stdin_is_raw = 1; + stdin_is_raw = 1; - return 0; + return 0; } /** @@ -165,15 +165,15 @@ int set_stdin_raw(void) { * on success, 0 */ int restore_stdin(void) { - if (!stdin_is_raw) return 0; + if (!stdin_is_raw) return 0; - if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_stdin) < 0) { - return -1; - } + if (tcsetattr(STDIN_FILENO, TCSAFLUSH, &old_stdin) < 0) { + return -1; + } - stdin_is_raw = 0; + stdin_is_raw = 0; - return 0; + return 0; } // Flag indicating whether the sigwinch watcher should terminate. @@ -184,30 +184,30 @@ static volatile bool close_sigwinch_watcher = false; * the terminal size. */ static void *watch_sigwinch(void *data) { - sigset_t winch; - int *fds = (int *)data; - int sig; + sigset_t winch; + int *fds = (int *)data; + int sig; - sigemptyset(&winch); - sigaddset(&winch, SIGWINCH); - pthread_sigmask(SIG_UNBLOCK, &winch, nullptr); + sigemptyset(&winch); + sigaddset(&winch, SIGWINCH); + pthread_sigmask(SIG_UNBLOCK, &winch, nullptr); - do { - if (close_sigwinch_watcher) - break; + do { + if (close_sigwinch_watcher) + break; - // Get the new terminal size - struct winsize w; - if (ioctl(fds[0], TIOCGWINSZ, &w) == -1) - continue; + // Get the new terminal size + struct winsize w; + if (ioctl(fds[0], TIOCGWINSZ, &w) == -1) + continue; - // Set the new terminal size - ioctl(fds[1], TIOCSWINSZ, &w); + // Set the new terminal size + ioctl(fds[1], TIOCSWINSZ, &w); - } while (sigwait(&winch, &sig) == 0); - delete[] fds; + } while (sigwait(&winch, &sig) == 0); + delete[] fds; - return nullptr; + return nullptr; } /** @@ -233,30 +233,30 @@ static void *watch_sigwinch(void *data) { * on success, 0 */ int watch_sigwinch_async(int master, int slave) { - pthread_t watcher; - int *fds = new int[2]; + pthread_t watcher; + int *fds = new int[2]; - // Block SIGWINCH so sigwait can later receive it - sigset_t winch; - sigemptyset(&winch); - sigaddset(&winch, SIGWINCH); - if (pthread_sigmask(SIG_BLOCK, &winch, nullptr) == -1) { - delete[] fds; - return -1; - } + // Block SIGWINCH so sigwait can later receive it + sigset_t winch; + sigemptyset(&winch); + sigaddset(&winch, SIGWINCH); + if (pthread_sigmask(SIG_BLOCK, &winch, nullptr) == -1) { + delete[] fds; + return -1; + } - // Initialize some variables, then start the thread - close_sigwinch_watcher = 0; - fds[0] = master; - fds[1] = slave; - int ret = pthread_create(&watcher, nullptr, &watch_sigwinch, fds); - if (ret != 0) { - delete[] fds; - errno = ret; - return -1; - } + // Initialize some variables, then start the thread + close_sigwinch_watcher = 0; + fds[0] = master; + fds[1] = slave; + int ret = pthread_create(&watcher, nullptr, &watch_sigwinch, fds); + if (ret != 0) { + delete[] fds; + errno = ret; + return -1; + } - return 0; + return 0; } /** @@ -266,11 +266,11 @@ int watch_sigwinch_async(int master, int slave) { * in a seperate thread */ void pump_stdin_async(int outfd) { - // Put stdin into raw mode - set_stdin_raw(); + // Put stdin into raw mode + set_stdin_raw(); - // Pump data from stdin to the PTY - pump_async(STDIN_FILENO, outfd); + // Pump data from stdin to the PTY + pump_async(STDIN_FILENO, outfd); } /** @@ -282,11 +282,11 @@ void pump_stdin_async(int outfd) { * Before returning, restores stdin settings. */ void pump_stdout_blocking(int infd) { - // Pump data from stdout to PTY - pump(infd, STDOUT_FILENO, false /* Don't close output when done */); + // Pump data from stdout to PTY + pump(infd, STDOUT_FILENO, false /* Don't close output when done */); - // Cleanup - restore_stdin(); - close_sigwinch_watcher = true; - raise(SIGWINCH); + // Cleanup + restore_stdin(); + close_sigwinch_watcher = true; + raise(SIGWINCH); } diff --git a/native/jni/su/su.cpp b/native/jni/su/su.cpp index 6769362b0..3be8512c6 100644 --- a/native/jni/su/su.cpp +++ b/native/jni/su/su.cpp @@ -31,200 +31,200 @@ int quit_signals[] = { SIGALRM, SIGABRT, SIGHUP, SIGPIPE, SIGQUIT, SIGTERM, SIGINT, 0 }; static void usage(int status) { - FILE *stream = (status == EXIT_SUCCESS) ? stdout : stderr; + FILE *stream = (status == EXIT_SUCCESS) ? stdout : stderr; - fprintf(stream, - "MagiskSU\n\n" - "Usage: su [options] [-] [user [argument...]]\n\n" - "Options:\n" - " -c, --command COMMAND pass COMMAND to the invoked shell\n" - " -h, --help display this help message and exit\n" - " -, -l, --login pretend the shell to be a login shell\n" - " -m, -p,\n" - " --preserve-environment preserve the entire environment\n" - " -s, --shell SHELL use SHELL instead of the default " DEFAULT_SHELL "\n" - " -v, --version display version number and exit\n" - " -V display version code and exit\n" - " -mm, -M,\n" - " --mount-master force run in the global mount namespace\n"); - exit(status); + fprintf(stream, + "MagiskSU\n\n" + "Usage: su [options] [-] [user [argument...]]\n\n" + "Options:\n" + " -c, --command COMMAND pass COMMAND to the invoked shell\n" + " -h, --help display this help message and exit\n" + " -, -l, --login pretend the shell to be a login shell\n" + " -m, -p,\n" + " --preserve-environment preserve the entire environment\n" + " -s, --shell SHELL use SHELL instead of the default " DEFAULT_SHELL "\n" + " -v, --version display version number and exit\n" + " -V display version code and exit\n" + " -mm, -M,\n" + " --mount-master force run in the global mount namespace\n"); + exit(status); } static char *concat_commands(int argc, char *argv[]) { - char command[ARG_MAX]; - command[0] = '\0'; - for (int i = optind - 1; i < argc; ++i) { - if (command[0]) - sprintf(command, "%s %s", command, argv[i]); - else - strcpy(command, argv[i]); - } - return strdup(command); + char command[ARG_MAX]; + command[0] = '\0'; + for (int i = optind - 1; i < argc; ++i) { + if (command[0]) + sprintf(command, "%s %s", command, argv[i]); + else + strcpy(command, argv[i]); + } + return strdup(command); } static void sighandler(int sig) { - restore_stdin(); + restore_stdin(); - // Assume we'll only be called before death - // See note before sigaction() in set_stdin_raw() - // - // Now, close all standard I/O to cause the pumps - // to exit so we can continue and retrieve the exit - // code - close(STDIN_FILENO); - close(STDOUT_FILENO); - close(STDERR_FILENO); + // Assume we'll only be called before death + // See note before sigaction() in set_stdin_raw() + // + // Now, close all standard I/O to cause the pumps + // to exit so we can continue and retrieve the exit + // code + close(STDIN_FILENO); + close(STDOUT_FILENO); + close(STDERR_FILENO); - // Put back all the default handlers - struct sigaction act; + // Put back all the default handlers + struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_handler = SIG_DFL; - for (int i = 0; quit_signals[i]; ++i) { - sigaction(quit_signals[i], &act, nullptr); - } + memset(&act, 0, sizeof(act)); + act.sa_handler = SIG_DFL; + for (int i = 0; quit_signals[i]; ++i) { + sigaction(quit_signals[i], &act, nullptr); + } } static void setup_sighandlers(void (*handler)(int)) { - struct sigaction act; - memset(&act, 0, sizeof(act)); - act.sa_handler = handler; - for (int i = 0; quit_signals[i]; ++i) { - sigaction(quit_signals[i], &act, nullptr); - } + struct sigaction act; + memset(&act, 0, sizeof(act)); + act.sa_handler = handler; + for (int i = 0; quit_signals[i]; ++i) { + sigaction(quit_signals[i], &act, nullptr); + } } int su_client_main(int argc, char *argv[]) { - int c; - struct option long_opts[] = { - { "command", required_argument, nullptr, 'c' }, - { "help", no_argument, nullptr, 'h' }, - { "login", no_argument, nullptr, 'l' }, - { "preserve-environment", no_argument, nullptr, 'p' }, - { "shell", required_argument, nullptr, 's' }, - { "version", no_argument, nullptr, 'v' }, - { "context", required_argument, nullptr, 'z' }, - { "mount-master", no_argument, nullptr, 'M' }, - { nullptr, 0, nullptr, 0 }, - }; + int c; + struct option long_opts[] = { + { "command", required_argument, nullptr, 'c' }, + { "help", no_argument, nullptr, 'h' }, + { "login", no_argument, nullptr, 'l' }, + { "preserve-environment", no_argument, nullptr, 'p' }, + { "shell", required_argument, nullptr, 's' }, + { "version", no_argument, nullptr, 'v' }, + { "context", required_argument, nullptr, 'z' }, + { "mount-master", no_argument, nullptr, 'M' }, + { nullptr, 0, nullptr, 0 }, + }; - su_request su_req; + su_request su_req; - for (int i = 0; i < argc; i++) { - // Replace -cn with -z, -mm with -M for supporting getopt_long - if (strcmp(argv[i], "-cn") == 0) - strcpy(argv[i], "-z"); - else if (strcmp(argv[i], "-mm") == 0) - strcpy(argv[i], "-M"); - } + for (int i = 0; i < argc; i++) { + // Replace -cn with -z, -mm with -M for supporting getopt_long + if (strcmp(argv[i], "-cn") == 0) + strcpy(argv[i], "-z"); + else if (strcmp(argv[i], "-mm") == 0) + strcpy(argv[i], "-M"); + } - while ((c = getopt_long(argc, argv, "c:hlmps:Vvuz:M", long_opts, nullptr)) != -1) { - switch (c) { - case 'c': - su_req.command = concat_commands(argc, argv); - optind = argc; - break; - case 'h': - usage(EXIT_SUCCESS); - break; - case 'l': - su_req.login = true; - break; - case 'm': - case 'p': - su_req.keepenv = true; - break; - case 's': - su_req.shell = optarg; - break; - case 'V': - printf("%d\n", MAGISK_VER_CODE); - exit(EXIT_SUCCESS); - case 'v': - printf("%s\n", MAGISK_VERSION ":MAGISKSU"); - exit(EXIT_SUCCESS); - case 'z': - // Do nothing, placed here for legacy support :) - break; - case 'M': - su_req.mount_master = true; - break; - default: - /* Bionic getopt_long doesn't terminate its error output by newline */ - fprintf(stderr, "\n"); - usage(2); - } - } + while ((c = getopt_long(argc, argv, "c:hlmps:Vvuz:M", long_opts, nullptr)) != -1) { + switch (c) { + case 'c': + su_req.command = concat_commands(argc, argv); + optind = argc; + break; + case 'h': + usage(EXIT_SUCCESS); + break; + case 'l': + su_req.login = true; + break; + case 'm': + case 'p': + su_req.keepenv = true; + break; + case 's': + su_req.shell = optarg; + break; + case 'V': + printf("%d\n", MAGISK_VER_CODE); + exit(EXIT_SUCCESS); + case 'v': + printf("%s\n", MAGISK_VERSION ":MAGISKSU"); + exit(EXIT_SUCCESS); + case 'z': + // Do nothing, placed here for legacy support :) + break; + case 'M': + su_req.mount_master = true; + break; + default: + /* Bionic getopt_long doesn't terminate its error output by newline */ + fprintf(stderr, "\n"); + usage(2); + } + } - if (optind < argc && strcmp(argv[optind], "-") == 0) { - su_req.login = true; - optind++; - } - /* username or uid */ - if (optind < argc) { - struct passwd *pw; - pw = getpwnam(argv[optind]); - if (pw) - su_req.uid = pw->pw_uid; - else - su_req.uid = parse_int(argv[optind]); - optind++; - } + if (optind < argc && strcmp(argv[optind], "-") == 0) { + su_req.login = true; + optind++; + } + /* username or uid */ + if (optind < argc) { + struct passwd *pw; + pw = getpwnam(argv[optind]); + if (pw) + su_req.uid = pw->pw_uid; + else + su_req.uid = parse_int(argv[optind]); + optind++; + } - char pts_slave[PATH_MAX]; - int ptmx, fd; + char pts_slave[PATH_MAX]; + int ptmx, fd; - // Connect to client - fd = connect_daemon(); + // Connect to client + fd = connect_daemon(); - // Tell the daemon we are su - write_int(fd, SUPERUSER); + // Tell the daemon we are su + write_int(fd, SUPERUSER); - // Send su_request - xwrite(fd, &su_req, sizeof(su_req_base)); - write_string(fd, su_req.shell); - write_string(fd, su_req.command); + // Send su_request + xwrite(fd, &su_req, sizeof(su_req_base)); + write_string(fd, su_req.shell); + write_string(fd, su_req.command); - // Wait for ack from daemon - if (read_int(fd)) { - // Fast fail - fprintf(stderr, "%s\n", strerror(EACCES)); - return EACCES; - } + // Wait for ack from daemon + if (read_int(fd)) { + // Fast fail + fprintf(stderr, "%s\n", strerror(EACCES)); + return EACCES; + } - // Determine which one of our streams are attached to a TTY - int atty = 0; - if (isatty(STDIN_FILENO)) atty |= ATTY_IN; - if (isatty(STDOUT_FILENO)) atty |= ATTY_OUT; - if (isatty(STDERR_FILENO)) atty |= ATTY_ERR; + // Determine which one of our streams are attached to a TTY + int atty = 0; + if (isatty(STDIN_FILENO)) atty |= ATTY_IN; + if (isatty(STDOUT_FILENO)) atty |= ATTY_OUT; + if (isatty(STDERR_FILENO)) atty |= ATTY_ERR; - if (atty) { - // We need a PTY. Get one. - ptmx = pts_open(pts_slave, sizeof(pts_slave)); - } else { - pts_slave[0] = '\0'; - } + if (atty) { + // We need a PTY. Get one. + ptmx = pts_open(pts_slave, sizeof(pts_slave)); + } else { + pts_slave[0] = '\0'; + } - // Send pts_slave - write_string(fd, pts_slave); + // Send pts_slave + write_string(fd, pts_slave); - // Send stdin - send_fd(fd, (atty & ATTY_IN) ? -1 : STDIN_FILENO); - // Send stdout - send_fd(fd, (atty & ATTY_OUT) ? -1 : STDOUT_FILENO); - // Send stderr - send_fd(fd, (atty & ATTY_ERR) ? -1 : STDERR_FILENO); + // Send stdin + send_fd(fd, (atty & ATTY_IN) ? -1 : STDIN_FILENO); + // Send stdout + send_fd(fd, (atty & ATTY_OUT) ? -1 : STDOUT_FILENO); + // Send stderr + send_fd(fd, (atty & ATTY_ERR) ? -1 : STDERR_FILENO); - if (atty) { - setup_sighandlers(sighandler); - watch_sigwinch_async(STDOUT_FILENO, ptmx); - pump_stdin_async(ptmx); - pump_stdout_blocking(ptmx); - } + if (atty) { + setup_sighandlers(sighandler); + watch_sigwinch_async(STDOUT_FILENO, ptmx); + pump_stdin_async(ptmx); + pump_stdout_blocking(ptmx); + } - // Get the exit code - int code = read_int(fd); - close(fd); + // Get the exit code + int code = read_int(fd); + close(fd); - return code; + return code; } diff --git a/native/jni/su/su.hpp b/native/jni/su/su.hpp index 7220dd020..fd9c51c79 100644 --- a/native/jni/su/su.hpp +++ b/native/jni/su/su.hpp @@ -16,54 +16,54 @@ class su_info { public: - /* Unique key */ - const int uid; + /* Unique key */ + const int uid; - /* These should be guarded with internal lock */ - db_settings cfg; - db_strings str; - su_access access; - struct stat mgr_st; + /* These should be guarded with internal lock */ + db_settings cfg; + db_strings str; + su_access access; + struct stat mgr_st; - /* This should be guarded with global cache lock */ - long timestamp; + /* This should be guarded with global cache lock */ + long timestamp; - su_info(unsigned uid = 0); - ~su_info(); - mutex_guard lock(); - bool is_fresh(); - void refresh(); + su_info(unsigned uid = 0); + ~su_info(); + mutex_guard lock(); + bool is_fresh(); + void refresh(); private: - pthread_mutex_t _lock; /* Internal lock */ + pthread_mutex_t _lock; /* Internal lock */ }; struct su_req_base { - int uid = UID_ROOT; - bool login = false; - bool keepenv = false; - bool mount_master = false; + int uid = UID_ROOT; + bool login = false; + bool keepenv = false; + bool mount_master = false; } __attribute__((packed)); struct su_request : public su_req_base { - const char *shell = DEFAULT_SHELL; - const char *command = ""; - su_request(bool dyn = false) : dyn(dyn) {} - ~su_request() { - if (dyn) { - free(const_cast(shell)); - free(const_cast(command)); - } - } + const char *shell = DEFAULT_SHELL; + const char *command = ""; + su_request(bool dyn = false) : dyn(dyn) {} + ~su_request() { + if (dyn) { + free(const_cast(shell)); + free(const_cast(command)); + } + } private: - bool dyn; + bool dyn; } __attribute__((packed)); struct su_context { - std::shared_ptr info; - su_request req; - int pid; + std::shared_ptr info; + su_request req; + int pid; }; void app_log(const su_context &ctx); diff --git a/native/jni/su/su_daemon.cpp b/native/jni/su/su_daemon.cpp index ee4c0d884..0960dd498 100644 --- a/native/jni/su/su_daemon.cpp +++ b/native/jni/su/su_daemon.cpp @@ -25,319 +25,319 @@ static pthread_mutex_t cache_lock = PTHREAD_MUTEX_INITIALIZER; static shared_ptr cached; su_info::su_info(unsigned uid) : - uid(uid), access(DEFAULT_SU_ACCESS), mgr_st({}), - timestamp(0), _lock(PTHREAD_MUTEX_INITIALIZER) {} + uid(uid), access(DEFAULT_SU_ACCESS), mgr_st({}), + timestamp(0), _lock(PTHREAD_MUTEX_INITIALIZER) {} su_info::~su_info() { - pthread_mutex_destroy(&_lock); + pthread_mutex_destroy(&_lock); } mutex_guard su_info::lock() { - return mutex_guard(_lock); + return mutex_guard(_lock); } bool su_info::is_fresh() { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - long current = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L; - return current - timestamp < 3000; /* 3 seconds */ + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + long current = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L; + return current - timestamp < 3000; /* 3 seconds */ } void su_info::refresh() { - timespec ts; - clock_gettime(CLOCK_MONOTONIC, &ts); - timestamp = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L; + timespec ts; + clock_gettime(CLOCK_MONOTONIC, &ts); + timestamp = ts.tv_sec * 1000L + ts.tv_nsec / 1000000L; } static void database_check(const shared_ptr &info) { - int uid = info->uid; - get_db_settings(info->cfg); - get_db_strings(info->str); + int uid = info->uid; + get_db_settings(info->cfg); + get_db_strings(info->str); - // Check multiuser settings - switch (info->cfg[SU_MULTIUSER_MODE]) { - case MULTIUSER_MODE_OWNER_ONLY: - if (info->uid / 100000) { - uid = -1; - info->access = NO_SU_ACCESS; - } - break; - case MULTIUSER_MODE_OWNER_MANAGED: - uid = info->uid % 100000; - break; - case MULTIUSER_MODE_USER: - default: - break; - } + // Check multiuser settings + switch (info->cfg[SU_MULTIUSER_MODE]) { + case MULTIUSER_MODE_OWNER_ONLY: + if (info->uid / 100000) { + uid = -1; + info->access = NO_SU_ACCESS; + } + break; + case MULTIUSER_MODE_OWNER_MANAGED: + uid = info->uid % 100000; + break; + case MULTIUSER_MODE_USER: + default: + break; + } - if (uid > 0) - get_uid_policy(info->access, uid); + if (uid > 0) + get_uid_policy(info->access, uid); - // We need to check our manager - if (info->access.log || info->access.notify) - validate_manager(info->str[SU_MANAGER], uid / 100000, &info->mgr_st); + // We need to check our manager + if (info->access.log || info->access.notify) + validate_manager(info->str[SU_MANAGER], uid / 100000, &info->mgr_st); } static shared_ptr get_su_info(unsigned uid) { - LOGD("su: request from uid=[%d]\n", uid); + LOGD("su: request from uid=[%d]\n", uid); - shared_ptr info; + shared_ptr info; - { - mutex_guard lock(cache_lock); - if (!cached || cached->uid != uid || !cached->is_fresh()) - cached = make_shared(uid); - cached->refresh(); - info = cached; - } + { + mutex_guard lock(cache_lock); + if (!cached || cached->uid != uid || !cached->is_fresh()) + cached = make_shared(uid); + cached->refresh(); + info = cached; + } - mutex_guard lock = info->lock(); + mutex_guard lock = info->lock(); - if (info->access.policy == QUERY) { - // Not cached, get data from database - database_check(info); + if (info->access.policy == QUERY) { + // Not cached, get data from database + database_check(info); - // If it's root or the manager, allow it silently - if (info->uid == UID_ROOT || (info->uid % 100000) == (info->mgr_st.st_uid % 100000)) { - info->access = SILENT_SU_ACCESS; - return info; - } + // If it's root or the manager, allow it silently + if (info->uid == UID_ROOT || (info->uid % 100000) == (info->mgr_st.st_uid % 100000)) { + info->access = SILENT_SU_ACCESS; + return info; + } - // Check su access settings - switch (info->cfg[ROOT_ACCESS]) { - case ROOT_ACCESS_DISABLED: - LOGW("Root access is disabled!\n"); - info->access = NO_SU_ACCESS; - break; - case ROOT_ACCESS_ADB_ONLY: - if (info->uid != UID_SHELL) { - LOGW("Root access limited to ADB only!\n"); - info->access = NO_SU_ACCESS; - } - break; - case ROOT_ACCESS_APPS_ONLY: - if (info->uid == UID_SHELL) { - LOGW("Root access is disabled for ADB!\n"); - info->access = NO_SU_ACCESS; - } - break; - case ROOT_ACCESS_APPS_AND_ADB: - default: - break; - } + // Check su access settings + switch (info->cfg[ROOT_ACCESS]) { + case ROOT_ACCESS_DISABLED: + LOGW("Root access is disabled!\n"); + info->access = NO_SU_ACCESS; + break; + case ROOT_ACCESS_ADB_ONLY: + if (info->uid != UID_SHELL) { + LOGW("Root access limited to ADB only!\n"); + info->access = NO_SU_ACCESS; + } + break; + case ROOT_ACCESS_APPS_ONLY: + if (info->uid == UID_SHELL) { + LOGW("Root access is disabled for ADB!\n"); + info->access = NO_SU_ACCESS; + } + break; + case ROOT_ACCESS_APPS_AND_ADB: + default: + break; + } - if (info->access.policy != QUERY) - return info; + if (info->access.policy != QUERY) + return info; - // If still not determined, check if manager exists - if (info->str[SU_MANAGER].empty()) { - info->access = NO_SU_ACCESS; - return info; - } - } else { - return info; - } + // If still not determined, check if manager exists + if (info->str[SU_MANAGER].empty()) { + info->access = NO_SU_ACCESS; + return info; + } + } else { + return info; + } - // If still not determined, ask manager - int fd = app_request(info); - if (fd < 0) { - info->access.policy = DENY; - } else { - int ret = read_int_be(fd); - info->access.policy = ret < 0 ? DENY : static_cast(ret); - close(fd); - } + // If still not determined, ask manager + int fd = app_request(info); + if (fd < 0) { + info->access.policy = DENY; + } else { + int ret = read_int_be(fd); + info->access.policy = ret < 0 ? DENY : static_cast(ret); + close(fd); + } - return info; + return info; } // Set effective uid back to root, otherwise setres[ug]id will fail if uid isn't root static void set_identity(unsigned uid) { - if (seteuid(0)) { - PLOGE("seteuid (root)"); - } - if (setresgid(uid, uid, uid)) { - PLOGE("setresgid (%u)", uid); - } - if (setresuid(uid, uid, uid)) { - PLOGE("setresuid (%u)", uid); - } + if (seteuid(0)) { + PLOGE("seteuid (root)"); + } + if (setresgid(uid, uid, uid)) { + PLOGE("setresgid (%u)", uid); + } + if (setresuid(uid, uid, uid)) { + PLOGE("setresuid (%u)", uid); + } } void su_daemon_handler(int client, struct ucred *credential) { - LOGD("su: request from pid=[%d], client=[%d]\n", credential->pid, client); + LOGD("su: request from pid=[%d], client=[%d]\n", credential->pid, client); - su_context ctx = { - .info = get_su_info(credential->uid), - .req = su_request(true), - .pid = credential->pid - }; + su_context ctx = { + .info = get_su_info(credential->uid), + .req = su_request(true), + .pid = credential->pid + }; - // Read su_request - xxread(client, &ctx.req, sizeof(su_req_base)); - ctx.req.shell = read_string(client); - ctx.req.command = read_string(client); + // Read su_request + xxread(client, &ctx.req, sizeof(su_req_base)); + ctx.req.shell = read_string(client); + ctx.req.command = read_string(client); - if (ctx.info->access.log) - app_log(ctx); - else if (ctx.info->access.notify) - app_notify(ctx); + if (ctx.info->access.log) + app_log(ctx); + else if (ctx.info->access.notify) + app_notify(ctx); - // Fail fast - if (ctx.info->access.policy == DENY) { - LOGW("su: request rejected (%u)\n", ctx.info->uid); - ctx.info.reset(); - write_int(client, DENY); - close(client); - return; - } + // Fail fast + if (ctx.info->access.policy == DENY) { + LOGW("su: request rejected (%u)\n", ctx.info->uid); + ctx.info.reset(); + write_int(client, DENY); + close(client); + return; + } - // Fork a child root process - // - // The child process will need to setsid, open a pseudo-terminal - // if needed, and eventually exec shell. - // The parent process will wait for the result and - // send the return code back to our client. + // Fork a child root process + // + // The child process will need to setsid, open a pseudo-terminal + // if needed, and eventually exec shell. + // The parent process will wait for the result and + // send the return code back to our client. - if (int child = xfork(); child) { - ctx.info.reset(); + if (int child = xfork(); child) { + ctx.info.reset(); - // Wait result - LOGD("su: waiting child pid=[%d]\n", child); - int status, code; + // Wait result + LOGD("su: waiting child pid=[%d]\n", child); + int status, code; - if (waitpid(child, &status, 0) > 0) - code = WEXITSTATUS(status); - else - code = -1; + if (waitpid(child, &status, 0) > 0) + code = WEXITSTATUS(status); + else + code = -1; - LOGD("su: return code=[%d]\n", code); - write(client, &code, sizeof(code)); - close(client); - return; - } + LOGD("su: return code=[%d]\n", code); + write(client, &code, sizeof(code)); + close(client); + return; + } - LOGD("su: fork handler\n"); + LOGD("su: fork handler\n"); - // Abort upon any error occurred - log_cb.ex = exit; + // Abort upon any error occurred + log_cb.ex = exit; - // ack - write_int(client, 0); + // ack + write_int(client, 0); - // Become session leader - xsetsid(); + // Become session leader + xsetsid(); - // Get pts_slave - char *pts_slave = read_string(client); + // Get pts_slave + char *pts_slave = read_string(client); - // The FDs for each of the streams - int infd = recv_fd(client); - int outfd = recv_fd(client); - int errfd = recv_fd(client); + // The FDs for each of the streams + int infd = recv_fd(client); + int outfd = recv_fd(client); + int errfd = recv_fd(client); - if (pts_slave[0]) { - LOGD("su: pts_slave=[%s]\n", pts_slave); - // Check pts_slave file is owned by daemon_from_uid - struct stat st; - xstat(pts_slave, &st); + if (pts_slave[0]) { + LOGD("su: pts_slave=[%s]\n", pts_slave); + // Check pts_slave file is owned by daemon_from_uid + struct stat st; + xstat(pts_slave, &st); - // If caller is not root, ensure the owner of pts_slave is the caller - if(st.st_uid != ctx.info->uid && ctx.info->uid != 0) - LOGE("su: Wrong permission of pts_slave\n"); + // If caller is not root, ensure the owner of pts_slave is the caller + if(st.st_uid != ctx.info->uid && ctx.info->uid != 0) + LOGE("su: Wrong permission of pts_slave\n"); - // Opening the TTY has to occur after the - // fork() and setsid() so that it becomes - // our controlling TTY and not the daemon's - int ptsfd = xopen(pts_slave, O_RDWR); + // Opening the TTY has to occur after the + // fork() and setsid() so that it becomes + // our controlling TTY and not the daemon's + int ptsfd = xopen(pts_slave, O_RDWR); - if (infd < 0) - infd = ptsfd; - if (outfd < 0) - outfd = ptsfd; - if (errfd < 0) - errfd = ptsfd; - } + if (infd < 0) + infd = ptsfd; + if (outfd < 0) + outfd = ptsfd; + if (errfd < 0) + errfd = ptsfd; + } - free(pts_slave); + free(pts_slave); - // Swap out stdin, stdout, stderr - xdup2(infd, STDIN_FILENO); - xdup2(outfd, STDOUT_FILENO); - xdup2(errfd, STDERR_FILENO); + // Swap out stdin, stdout, stderr + xdup2(infd, STDIN_FILENO); + xdup2(outfd, STDOUT_FILENO); + xdup2(errfd, STDERR_FILENO); - // Unleash all streams from SELinux hell - setfilecon("/proc/self/fd/0", "u:object_r:" SEPOL_FILE_TYPE ":s0"); - setfilecon("/proc/self/fd/1", "u:object_r:" SEPOL_FILE_TYPE ":s0"); - setfilecon("/proc/self/fd/2", "u:object_r:" SEPOL_FILE_TYPE ":s0"); + // Unleash all streams from SELinux hell + setfilecon("/proc/self/fd/0", "u:object_r:" SEPOL_FILE_TYPE ":s0"); + setfilecon("/proc/self/fd/1", "u:object_r:" SEPOL_FILE_TYPE ":s0"); + setfilecon("/proc/self/fd/2", "u:object_r:" SEPOL_FILE_TYPE ":s0"); - close(infd); - close(outfd); - close(errfd); - close(client); + close(infd); + close(outfd); + close(errfd); + close(client); - // Handle namespaces - if (ctx.req.mount_master) - ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_GLOBAL; - switch (ctx.info->cfg[SU_MNT_NS]) { - case NAMESPACE_MODE_GLOBAL: - LOGD("su: use global namespace\n"); - break; - case NAMESPACE_MODE_REQUESTER: - LOGD("su: use namespace of pid=[%d]\n", ctx.pid); - if (switch_mnt_ns(ctx.pid)) - LOGD("su: setns failed, fallback to global\n"); - break; - case NAMESPACE_MODE_ISOLATE: - LOGD("su: use new isolated namespace\n"); - switch_mnt_ns(ctx.pid); - xunshare(CLONE_NEWNS); - xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr); - break; - } + // Handle namespaces + if (ctx.req.mount_master) + ctx.info->cfg[SU_MNT_NS] = NAMESPACE_MODE_GLOBAL; + switch (ctx.info->cfg[SU_MNT_NS]) { + case NAMESPACE_MODE_GLOBAL: + LOGD("su: use global namespace\n"); + break; + case NAMESPACE_MODE_REQUESTER: + LOGD("su: use namespace of pid=[%d]\n", ctx.pid); + if (switch_mnt_ns(ctx.pid)) + LOGD("su: setns failed, fallback to global\n"); + break; + case NAMESPACE_MODE_ISOLATE: + LOGD("su: use new isolated namespace\n"); + switch_mnt_ns(ctx.pid); + xunshare(CLONE_NEWNS); + xmount(nullptr, "/", nullptr, MS_PRIVATE | MS_REC, nullptr); + break; + } - const char *argv[] = { nullptr, nullptr, nullptr, nullptr }; + const char *argv[] = { nullptr, nullptr, nullptr, nullptr }; - argv[0] = ctx.req.login ? "-" : ctx.req.shell; + argv[0] = ctx.req.login ? "-" : ctx.req.shell; - if (ctx.req.command[0]) { - argv[1] = "-c"; - argv[2] = ctx.req.command; - } + if (ctx.req.command[0]) { + argv[1] = "-c"; + argv[2] = ctx.req.command; + } - // Setup environment - umask(022); - char path[32]; - snprintf(path, sizeof(path), "/proc/%d/cwd", ctx.pid); - chdir(path); - snprintf(path, sizeof(path), "/proc/%d/environ", ctx.pid); - char buf[4096] = { 0 }; - int fd = xopen(path, O_RDONLY); - read(fd, buf, sizeof(buf)); - close(fd); - clearenv(); - for (size_t pos = 0; buf[pos];) { - putenv(buf + pos); - pos += strlen(buf + pos) + 1; - } - if (!ctx.req.keepenv) { - struct passwd *pw; - pw = getpwuid(ctx.req.uid); - if (pw) { - setenv("HOME", pw->pw_dir, 1); - setenv("USER", pw->pw_name, 1); - setenv("LOGNAME", pw->pw_name, 1); - setenv("SHELL", ctx.req.shell, 1); - } - } + // Setup environment + umask(022); + char path[32]; + snprintf(path, sizeof(path), "/proc/%d/cwd", ctx.pid); + chdir(path); + snprintf(path, sizeof(path), "/proc/%d/environ", ctx.pid); + char buf[4096] = { 0 }; + int fd = xopen(path, O_RDONLY); + read(fd, buf, sizeof(buf)); + close(fd); + clearenv(); + for (size_t pos = 0; buf[pos];) { + putenv(buf + pos); + pos += strlen(buf + pos) + 1; + } + if (!ctx.req.keepenv) { + struct passwd *pw; + pw = getpwuid(ctx.req.uid); + if (pw) { + setenv("HOME", pw->pw_dir, 1); + setenv("USER", pw->pw_name, 1); + setenv("LOGNAME", pw->pw_name, 1); + setenv("SHELL", ctx.req.shell, 1); + } + } - // Unblock all signals - sigset_t block_set; - sigemptyset(&block_set); - sigprocmask(SIG_SETMASK, &block_set, nullptr); - set_identity(ctx.req.uid); - execvp(ctx.req.shell, (char **) argv); - fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell, strerror(errno)); - PLOGE("exec"); - exit(EXIT_FAILURE); + // Unblock all signals + sigset_t block_set; + sigemptyset(&block_set); + sigprocmask(SIG_SETMASK, &block_set, nullptr); + set_identity(ctx.req.uid); + execvp(ctx.req.shell, (char **) argv); + fprintf(stderr, "Cannot execute %s: %s\n", ctx.req.shell, strerror(errno)); + PLOGE("exec"); + exit(EXIT_FAILURE); } diff --git a/native/jni/utils/Android.mk b/native/jni/utils/Android.mk index 8f6f0b2c8..d0bcf23ce 100644 --- a/native/jni/utils/Android.mk +++ b/native/jni/utils/Android.mk @@ -5,13 +5,13 @@ LOCAL_MODULE:= libutils LOCAL_C_INCLUDES := jni/include $(LOCAL_PATH)/include LOCAL_EXPORT_C_INCLUDES := $(LOCAL_PATH)/include LOCAL_SRC_FILES := \ - missing.cpp \ - new.cpp \ - files.cpp \ - misc.cpp \ - selinux.cpp \ - logging.cpp \ - xwrap.cpp \ - stream.cpp + missing.cpp \ + new.cpp \ + files.cpp \ + misc.cpp \ + selinux.cpp \ + logging.cpp \ + xwrap.cpp \ + stream.cpp include $(BUILD_STATIC_LIBRARY) diff --git a/native/jni/utils/cpio.cpp b/native/jni/utils/cpio.cpp index 187fd1826..0eb1430c7 100644 --- a/native/jni/utils/cpio.cpp +++ b/native/jni/utils/cpio.cpp @@ -10,264 +10,264 @@ using namespace std; struct cpio_newc_header { - char magic[6]; - char ino[8]; - char mode[8]; - char uid[8]; - char gid[8]; - char nlink[8]; - char mtime[8]; - char filesize[8]; - char devmajor[8]; - char devminor[8]; - char rdevmajor[8]; - char rdevminor[8]; - char namesize[8]; - char check[8]; + char magic[6]; + char ino[8]; + char mode[8]; + char uid[8]; + char gid[8]; + char nlink[8]; + char mtime[8]; + char filesize[8]; + char devmajor[8]; + char devminor[8]; + char rdevmajor[8]; + char rdevminor[8]; + char namesize[8]; + char check[8]; } __attribute__((packed)); static uint32_t x8u(const char *hex) { - uint32_t val, inpos = 8, outpos; - char pattern[6]; + uint32_t val, inpos = 8, outpos; + char pattern[6]; - while (*hex == '0') { - hex++; - if (!--inpos) return 0; - } - // Because scanf gratuitously treats %*X differently than printf does. - sprintf(pattern, "%%%dx%%n", inpos); - sscanf(hex, pattern, &val, &outpos); - if (inpos != outpos) - LOGE("bad cpio header\n"); + while (*hex == '0') { + hex++; + if (!--inpos) return 0; + } + // Because scanf gratuitously treats %*X differently than printf does. + sprintf(pattern, "%%%dx%%n", inpos); + sscanf(hex, pattern, &val, &outpos); + if (inpos != outpos) + LOGE("bad cpio header\n"); - return val; + return val; } cpio_entry_base::cpio_entry_base(const cpio_newc_header *h) : mode(x8u(h->mode)), uid(x8u(h->uid)), gid(x8u(h->gid)), filesize(x8u(h->filesize)) {}; void cpio::dump(const char *file) { - fprintf(stderr, "Dump cpio: [%s]\n", file); - dump(xfopen(file, "we")); + fprintf(stderr, "Dump cpio: [%s]\n", file); + dump(xfopen(file, "we")); } void cpio::rm(entry_map::iterator &it) { - fprintf(stderr, "Remove [%s]\n", it->first.data()); - entries.erase(it); + fprintf(stderr, "Remove [%s]\n", it->first.data()); + entries.erase(it); } void cpio::rm(const char *name, bool r) { - size_t len = strlen(name); - for (auto it = entries.begin(); it != entries.end();) { - if (it->first.compare(0, len, name) == 0 && - ((r && it->first[len] == '/') || it->first[len] == '\0')) { - auto tmp = it; - ++it; - rm(tmp); - if (!r) return; - } else { - ++it; - } - } + size_t len = strlen(name); + for (auto it = entries.begin(); it != entries.end();) { + if (it->first.compare(0, len, name) == 0 && + ((r && it->first[len] == '/') || it->first[len] == '\0')) { + auto tmp = it; + ++it; + rm(tmp); + if (!r) return; + } else { + ++it; + } + } } static void extract_entry(const entry_map::value_type &e, const char *file) { - fprintf(stderr, "Extract [%s] to [%s]\n", e.first.data(), file); - unlink(file); - rmdir(file); - if (S_ISDIR(e.second->mode)) { - mkdir(file, e.second->mode & 0777); - } else if (S_ISREG(e.second->mode)) { - int fd = creat(file, e.second->mode & 0777); - xwrite(fd, e.second->data, e.second->filesize); - fchown(fd, e.second->uid, e.second->gid); - close(fd); - } else if (S_ISLNK(e.second->mode)) { - auto target = strndup((char *) e.second->data, e.second->filesize); - symlink(target, file); - free(target); - } + fprintf(stderr, "Extract [%s] to [%s]\n", e.first.data(), file); + unlink(file); + rmdir(file); + if (S_ISDIR(e.second->mode)) { + mkdir(file, e.second->mode & 0777); + } else if (S_ISREG(e.second->mode)) { + int fd = creat(file, e.second->mode & 0777); + xwrite(fd, e.second->data, e.second->filesize); + fchown(fd, e.second->uid, e.second->gid); + close(fd); + } else if (S_ISLNK(e.second->mode)) { + auto target = strndup((char *) e.second->data, e.second->filesize); + symlink(target, file); + free(target); + } } void cpio::extract() { - for (auto &e : entries) - extract_entry(e, e.first.data()); + for (auto &e : entries) + extract_entry(e, e.first.data()); } bool cpio::extract(const char *name, const char *file) { - auto it = entries.find(name); - if (it != entries.end()) { - extract_entry(*it, file); - return true; - } - fprintf(stderr, "Cannot find the file entry [%s]\n", name); - return false; + auto it = entries.find(name); + if (it != entries.end()) { + extract_entry(*it, file); + return true; + } + fprintf(stderr, "Cannot find the file entry [%s]\n", name); + return false; } bool cpio::exists(const char *name) { - return entries.count(name) != 0; + return entries.count(name) != 0; } #define do_out(buf, len) pos += fwrite(buf, 1, len, out); #define out_align() do_out(zeros, align_off(pos, 4)) void cpio::dump(FILE *out) { - size_t pos = 0; - unsigned inode = 300000; - char header[111]; - char zeros[4] = {0}; - for (auto &e : entries) { - sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", - inode++, // e->ino - e.second->mode, - e.second->uid, - e.second->gid, - 1, // e->nlink - 0, // e->mtime - e.second->filesize, - 0, // e->devmajor - 0, // e->devminor - 0, // e->rdevmajor - 0, // e->rdevminor - (uint32_t) e.first.size() + 1, - 0 // e->check - ); - do_out(header, 110); - do_out(e.first.data(), e.first.size() + 1); - out_align(); - if (e.second->filesize) { - do_out(e.second->data, e.second->filesize); - out_align(); - } - } - // Write trailer - sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", - inode++, 0755, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0); - do_out(header, 110); - do_out("TRAILER!!!\0", 11); - out_align(); - fclose(out); + size_t pos = 0; + unsigned inode = 300000; + char header[111]; + char zeros[4] = {0}; + for (auto &e : entries) { + sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", + inode++, // e->ino + e.second->mode, + e.second->uid, + e.second->gid, + 1, // e->nlink + 0, // e->mtime + e.second->filesize, + 0, // e->devmajor + 0, // e->devminor + 0, // e->rdevmajor + 0, // e->rdevminor + (uint32_t) e.first.size() + 1, + 0 // e->check + ); + do_out(header, 110); + do_out(e.first.data(), e.first.size() + 1); + out_align(); + if (e.second->filesize) { + do_out(e.second->data, e.second->filesize); + out_align(); + } + } + // Write trailer + sprintf(header, "070701%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x%08x", + inode++, 0755, 0, 0, 1, 0, 0, 0, 0, 0, 0, 11, 0); + do_out(header, 110); + do_out("TRAILER!!!\0", 11); + out_align(); + fclose(out); } cpio_rw::cpio_rw(const char *file) { - load_cpio(file); + load_cpio(file); } void cpio_rw::load_cpio(const char *file) { - char *buf; - size_t sz; - mmap_ro(file, buf, sz); - fprintf(stderr, "Loading cpio: [%s]\n", file); - load_cpio(buf, sz); - munmap(buf, sz); + char *buf; + size_t sz; + mmap_ro(file, buf, sz); + fprintf(stderr, "Loading cpio: [%s]\n", file); + load_cpio(buf, sz); + munmap(buf, sz); } void cpio_rw::insert(cpio_entry *e) { - auto ex = entries.extract(e->filename); - if (!ex) { - entries[e->filename].reset(e); - } else { - ex.key() = e->filename; - ex.mapped().reset(e); - entries.insert(std::move(ex)); - } + auto ex = entries.extract(e->filename); + if (!ex) { + entries[e->filename].reset(e); + } else { + ex.key() = e->filename; + ex.mapped().reset(e); + entries.insert(std::move(ex)); + } } void cpio_rw::add(mode_t mode, const char *name, const char *file) { - void *buf; - size_t sz; - mmap_ro(file, buf, sz); - auto e = new cpio_entry(name, S_IFREG | mode); - e->filesize = sz; - e->data = xmalloc(sz); - memcpy(e->data, buf, sz); - munmap(buf, sz); - insert(e); - fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode); + void *buf; + size_t sz; + mmap_ro(file, buf, sz); + auto e = new cpio_entry(name, S_IFREG | mode); + e->filesize = sz; + e->data = xmalloc(sz); + memcpy(e->data, buf, sz); + munmap(buf, sz); + insert(e); + fprintf(stderr, "Add entry [%s] (%04o)\n", name, mode); } void cpio_rw::mkdir(mode_t mode, const char *name) { - insert(new cpio_entry(name, S_IFDIR | mode)); - fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode); + insert(new cpio_entry(name, S_IFDIR | mode)); + fprintf(stderr, "Create directory [%s] (%04o)\n", name, mode); } void cpio_rw::ln(const char *target, const char *name) { - auto e = new cpio_entry(name, S_IFLNK); - e->filesize = strlen(target); - e->data = strdup(target); - insert(e); - fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target); + auto e = new cpio_entry(name, S_IFLNK); + e->filesize = strlen(target); + e->data = strdup(target); + insert(e); + fprintf(stderr, "Create symlink [%s] -> [%s]\n", name, target); } void cpio_rw::mv(entry_map::iterator &it, const char *to) { - fprintf(stderr, "Move [%s] -> [%s]\n", it->first.data(), to); - auto ex = entries.extract(it); - auto &name = static_cast(ex.mapped().get())->filename; - name = to; - ex.key() = name; - entries.erase(name); - entries.insert(std::move(ex)); + fprintf(stderr, "Move [%s] -> [%s]\n", it->first.data(), to); + auto ex = entries.extract(it); + auto &name = static_cast(ex.mapped().get())->filename; + name = to; + ex.key() = name; + entries.erase(name); + entries.insert(std::move(ex)); } bool cpio_rw::mv(const char *from, const char *to) { - auto it = entries.find(from); - if (it != entries.end()) { - mv(it, to); - return true; - } - fprintf(stderr, "Cannot find entry %s\n", from); - return false; + auto it = entries.find(from); + if (it != entries.end()) { + mv(it, to); + return true; + } + fprintf(stderr, "Cannot find entry %s\n", from); + return false; } #define pos_align(p) p = do_align(p, 4) void cpio_rw::load_cpio(const char *buf, size_t sz) { - size_t pos = 0; - const cpio_newc_header *header; - unique_ptr entry; - while (pos < sz) { - header = reinterpret_cast(buf + pos); - entry = make_unique(header); - pos += sizeof(*header); - string_view name_view(buf + pos); - pos += x8u(header->namesize); - pos_align(pos); - if (name_view == "." || name_view == "..") - continue; - if (name_view == "TRAILER!!!") - break; - entry->filename = name_view; - entry->data = xmalloc(entry->filesize); - memcpy(entry->data, buf + pos, entry->filesize); - pos += entry->filesize; - entries[entry->filename] = std::move(entry); - pos_align(pos); - } + size_t pos = 0; + const cpio_newc_header *header; + unique_ptr entry; + while (pos < sz) { + header = reinterpret_cast(buf + pos); + entry = make_unique(header); + pos += sizeof(*header); + string_view name_view(buf + pos); + pos += x8u(header->namesize); + pos_align(pos); + if (name_view == "." || name_view == "..") + continue; + if (name_view == "TRAILER!!!") + break; + entry->filename = name_view; + entry->data = xmalloc(entry->filesize); + memcpy(entry->data, buf + pos, entry->filesize); + pos += entry->filesize; + entries[entry->filename] = std::move(entry); + pos_align(pos); + } } cpio_mmap::cpio_mmap(const char *file) { - mmap_ro(file, buf, sz); - fprintf(stderr, "Loading cpio: [%s]\n", file); - size_t pos = 0; - cpio_newc_header *header; - unique_ptr entry; - while (pos < sz) { - header = (cpio_newc_header *)(buf + pos); - entry = make_unique(header); - pos += sizeof(*header); - string_view name_view(buf + pos); - pos += x8u(header->namesize); - pos_align(pos); - if (name_view == "." || name_view == "..") - continue; - if (name_view == "TRAILER!!!") - break; - entry->data = buf + pos; - pos += entry->filesize; - entries[name_view] = std::move(entry); - pos_align(pos); - } + mmap_ro(file, buf, sz); + fprintf(stderr, "Loading cpio: [%s]\n", file); + size_t pos = 0; + cpio_newc_header *header; + unique_ptr entry; + while (pos < sz) { + header = (cpio_newc_header *)(buf + pos); + entry = make_unique(header); + pos += sizeof(*header); + string_view name_view(buf + pos); + pos += x8u(header->namesize); + pos_align(pos); + if (name_view == "." || name_view == "..") + continue; + if (name_view == "TRAILER!!!") + break; + entry->data = buf + pos; + pos += entry->filesize; + entries[name_view] = std::move(entry); + pos_align(pos); + } } cpio_mmap::~cpio_mmap() { - munmap(buf, sz); + munmap(buf, sz); } diff --git a/native/jni/utils/files.cpp b/native/jni/utils/files.cpp index 685038a51..ff98df7fa 100644 --- a/native/jni/utils/files.cpp +++ b/native/jni/utils/files.cpp @@ -13,427 +13,427 @@ using namespace std; ssize_t fd_path(int fd, char *path, size_t size) { - snprintf(path, size, "/proc/self/fd/%d", fd); - return xreadlink(path, path, size); + snprintf(path, size, "/proc/self/fd/%d", fd); + return xreadlink(path, path, size); } int fd_pathat(int dirfd, const char *name, char *path, size_t size) { - if (fd_path(dirfd, path, size) < 0) - return -1; - auto len = strlen(path); - path[len] = '/'; - strlcpy(path + len + 1, name, size - len - 1); - return 0; + if (fd_path(dirfd, path, size) < 0) + return -1; + auto len = strlen(path); + path[len] = '/'; + strlcpy(path + len + 1, name, size - len - 1); + return 0; } int mkdirs(string path, mode_t mode) { - errno = 0; - for (char *p = path.data() + 1; *p; ++p) { - if (*p == '/') { - *p = '\0'; - if (mkdir(path.data(), mode) == -1) { - if (errno != EEXIST) - return -1; - } - *p = '/'; - } - } - if (mkdir(path.data(), mode) == -1) { - if (errno != EEXIST) - return -1; - } - return 0; + errno = 0; + for (char *p = path.data() + 1; *p; ++p) { + if (*p == '/') { + *p = '\0'; + if (mkdir(path.data(), mode) == -1) { + if (errno != EEXIST) + return -1; + } + *p = '/'; + } + } + if (mkdir(path.data(), mode) == -1) { + if (errno != EEXIST) + return -1; + } + return 0; } template static void post_order_walk(int dirfd, const Func &fn) { - auto dir = xopen_dir(dirfd); - if (!dir) return; + auto dir = xopen_dir(dirfd); + if (!dir) return; - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (entry->d_type == DT_DIR) - post_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn); - fn(dirfd, entry); - } + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (entry->d_type == DT_DIR) + post_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn); + fn(dirfd, entry); + } } template static void pre_order_walk(int dirfd, const Func &fn) { - auto dir = xopen_dir(dirfd); - if (!dir) return; + auto dir = xopen_dir(dirfd); + if (!dir) return; - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (!fn(dirfd, entry)) - continue; - if (entry->d_type == DT_DIR) - pre_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn); - } + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (!fn(dirfd, entry)) + continue; + if (entry->d_type == DT_DIR) + pre_order_walk(xopenat(dirfd, entry->d_name, O_RDONLY | O_CLOEXEC), fn); + } } static void remove_at(int dirfd, struct dirent *entry) { - unlinkat(dirfd, entry->d_name, entry->d_type == DT_DIR ? AT_REMOVEDIR : 0); + unlinkat(dirfd, entry->d_name, entry->d_type == DT_DIR ? AT_REMOVEDIR : 0); } void rm_rf(const char *path) { - struct stat st; - if (lstat(path, &st) < 0) - return; - if (S_ISDIR(st.st_mode)) - frm_rf(xopen(path, O_RDONLY | O_CLOEXEC)); - remove(path); + struct stat st; + if (lstat(path, &st) < 0) + return; + if (S_ISDIR(st.st_mode)) + frm_rf(xopen(path, O_RDONLY | O_CLOEXEC)); + remove(path); } void frm_rf(int dirfd) { - post_order_walk(dirfd, remove_at); + post_order_walk(dirfd, remove_at); } void mv_path(const char *src, const char *dest) { - file_attr attr; - getattr(src, &attr); - if (S_ISDIR(attr.st.st_mode)) { - if (access(dest, F_OK) != 0) { - xmkdirs(dest, 0); - setattr(dest, &attr); - } - mv_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC)); - } else{ - xrename(src, dest); - } - rmdir(src); + file_attr attr; + getattr(src, &attr); + if (S_ISDIR(attr.st.st_mode)) { + if (access(dest, F_OK) != 0) { + xmkdirs(dest, 0); + setattr(dest, &attr); + } + mv_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC)); + } else{ + xrename(src, dest); + } + rmdir(src); } void mv_dir(int src, int dest) { - auto dir = xopen_dir(src); - run_finally f([=]{ close(dest); }); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - switch (entry->d_type) { - case DT_DIR: - if (faccessat(dest, entry->d_name, F_OK, 0) == 0) { - // Destination folder exists, needs recursive move - int newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); - int newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); - mv_dir(newsrc, newdest); - unlinkat(src, entry->d_name, AT_REMOVEDIR); - break; - } - // Else fall through - case DT_LNK: - case DT_REG: - renameat(src, entry->d_name, dest, entry->d_name); - break; - } - } + auto dir = xopen_dir(src); + run_finally f([=]{ close(dest); }); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + switch (entry->d_type) { + case DT_DIR: + if (faccessat(dest, entry->d_name, F_OK, 0) == 0) { + // Destination folder exists, needs recursive move + int newsrc = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); + int newdest = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); + mv_dir(newsrc, newdest); + unlinkat(src, entry->d_name, AT_REMOVEDIR); + break; + } + // Else fall through + case DT_LNK: + case DT_REG: + renameat(src, entry->d_name, dest, entry->d_name); + break; + } + } } void cp_afc(const char *src, const char *dest) { - file_attr a; - getattr(src, &a); + file_attr a; + getattr(src, &a); - if (S_ISDIR(a.st.st_mode)) { - xmkdirs(dest, 0); - clone_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC)); - } else{ - unlink(dest); - if (S_ISREG(a.st.st_mode)) { - int sfd = xopen(src, O_RDONLY | O_CLOEXEC); - int dfd = xopen(dest, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0); - xsendfile(dfd, sfd, nullptr, a.st.st_size); - close(sfd); - close(dfd); - } else if (S_ISLNK(a.st.st_mode)) { - char buf[4096]; - xreadlink(src, buf, sizeof(buf)); - xsymlink(buf, dest); - } - } - setattr(dest, &a); + if (S_ISDIR(a.st.st_mode)) { + xmkdirs(dest, 0); + clone_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC)); + } else{ + unlink(dest); + if (S_ISREG(a.st.st_mode)) { + int sfd = xopen(src, O_RDONLY | O_CLOEXEC); + int dfd = xopen(dest, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0); + xsendfile(dfd, sfd, nullptr, a.st.st_size); + close(sfd); + close(dfd); + } else if (S_ISLNK(a.st.st_mode)) { + char buf[4096]; + xreadlink(src, buf, sizeof(buf)); + xsymlink(buf, dest); + } + } + setattr(dest, &a); } void clone_dir(int src, int dest) { - auto dir = xopen_dir(src); - run_finally f([&]{ close(dest); }); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - file_attr a; - getattrat(src, entry->d_name, &a); - switch (entry->d_type) { - case DT_DIR: { - xmkdirat(dest, entry->d_name, 0); - setattrat(dest, entry->d_name, &a); - int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); - int dst = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); - clone_dir(sfd, dst); - break; - } - case DT_REG: { - int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); - int dfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0); - xsendfile(dfd, sfd, nullptr, a.st.st_size); - fsetattr(dfd, &a); - close(dfd); - close(sfd); - break; - } - case DT_LNK: { - char buf[4096]; - xreadlinkat(src, entry->d_name, buf, sizeof(buf)); - xsymlinkat(buf, dest, entry->d_name); - setattrat(dest, entry->d_name, &a); - break; - } - } - } + auto dir = xopen_dir(src); + run_finally f([&]{ close(dest); }); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + file_attr a; + getattrat(src, entry->d_name, &a); + switch (entry->d_type) { + case DT_DIR: { + xmkdirat(dest, entry->d_name, 0); + setattrat(dest, entry->d_name, &a); + int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); + int dst = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); + clone_dir(sfd, dst); + break; + } + case DT_REG: { + int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); + int dfd = xopenat(dest, entry->d_name, O_WRONLY | O_CREAT | O_TRUNC | O_CLOEXEC, 0); + xsendfile(dfd, sfd, nullptr, a.st.st_size); + fsetattr(dfd, &a); + close(dfd); + close(sfd); + break; + } + case DT_LNK: { + char buf[4096]; + xreadlinkat(src, entry->d_name, buf, sizeof(buf)); + xsymlinkat(buf, dest, entry->d_name); + setattrat(dest, entry->d_name, &a); + break; + } + } + } } void link_path(const char *src, const char *dest) { - link_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC)); + link_dir(xopen(src, O_RDONLY | O_CLOEXEC), xopen(dest, O_RDONLY | O_CLOEXEC)); } void link_dir(int src, int dest) { - auto dir = xopen_dir(src); - run_finally f([&]{ close(dest); }); - for (dirent *entry; (entry = xreaddir(dir.get()));) { - if (entry->d_type == DT_DIR) { - file_attr a; - getattrat(src, entry->d_name, &a); - xmkdirat(dest, entry->d_name, 0); - setattrat(dest, entry->d_name, &a); - int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); - int dfd = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); - link_dir(sfd, dfd); - } else { - xlinkat(src, entry->d_name, dest, entry->d_name, 0); - } - } + auto dir = xopen_dir(src); + run_finally f([&]{ close(dest); }); + for (dirent *entry; (entry = xreaddir(dir.get()));) { + if (entry->d_type == DT_DIR) { + file_attr a; + getattrat(src, entry->d_name, &a); + xmkdirat(dest, entry->d_name, 0); + setattrat(dest, entry->d_name, &a); + int sfd = xopenat(src, entry->d_name, O_RDONLY | O_CLOEXEC); + int dfd = xopenat(dest, entry->d_name, O_RDONLY | O_CLOEXEC); + link_dir(sfd, dfd); + } else { + xlinkat(src, entry->d_name, dest, entry->d_name, 0); + } + } } int getattr(const char *path, file_attr *a) { - if (xlstat(path, &a->st) == -1) - return -1; - char *con; - if (lgetfilecon(path, &con) == -1) - return -1; - strcpy(a->con, con); - freecon(con); - return 0; + if (xlstat(path, &a->st) == -1) + return -1; + char *con; + if (lgetfilecon(path, &con) == -1) + return -1; + strcpy(a->con, con); + freecon(con); + return 0; } int getattrat(int dirfd, const char *name, file_attr *a) { - char path[4096]; - fd_pathat(dirfd, name, path, sizeof(path)); - return getattr(path, a); + char path[4096]; + fd_pathat(dirfd, name, path, sizeof(path)); + return getattr(path, a); } int fgetattr(int fd, file_attr *a) { - if (xfstat(fd, &a->st) < 0) - return -1; - char *con; - if (fgetfilecon(fd, &con) < 0) - return -1; - strcpy(a->con, con); - freecon(con); - return 0; + if (xfstat(fd, &a->st) < 0) + return -1; + char *con; + if (fgetfilecon(fd, &con) < 0) + return -1; + strcpy(a->con, con); + freecon(con); + return 0; } int setattr(const char *path, 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] && lsetfilecon(path, a->con) < 0) - return -1; - return 0; + 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] && lsetfilecon(path, a->con) < 0) + return -1; + return 0; } int setattrat(int dirfd, const char *name, file_attr *a) { - char path[4096]; - fd_pathat(dirfd, name, path, sizeof(path)); - return setattr(path, a); + char path[4096]; + fd_pathat(dirfd, name, path, sizeof(path)); + return setattr(path, a); } int fsetattr(int fd, file_attr *a) { - if (fchmod(fd, a->st.st_mode & 0777) < 0) - return -1; - if (fchown(fd, a->st.st_uid, a->st.st_gid) < 0) - return -1; - if (a->con[0] && fsetfilecon(fd, a->con) < 0) - return -1; - return 0; + if (fchmod(fd, a->st.st_mode & 0777) < 0) + return -1; + if (fchown(fd, a->st.st_uid, a->st.st_gid) < 0) + return -1; + if (a->con[0] && fsetfilecon(fd, a->con) < 0) + return -1; + return 0; } void clone_attr(const char *src, const char *dest) { - file_attr a; - getattr(src, &a); - setattr(dest, &a); + file_attr a; + getattr(src, &a); + setattr(dest, &a); } void fclone_attr(int src, int dest) { - file_attr a; - fgetattr(src, &a); - fsetattr(dest, &a); + file_attr a; + fgetattr(src, &a); + fsetattr(dest, &a); } void *__mmap(const char *filename, size_t *size, bool rw) { - int fd = xopen(filename, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC); - if (fd < 0) { - *size = 0; - return nullptr; - } - struct stat st; - void *buf; - if (fstat(fd, &st)) { - *size = 0; - return nullptr; - } - if (S_ISBLK(st.st_mode)) - ioctl(fd, BLKGETSIZE64, size); - else - *size = st.st_size; - buf = *size > 0 ? xmmap(nullptr, *size, PROT_READ | (rw ? PROT_WRITE : 0), MAP_SHARED, fd, 0) : nullptr; - close(fd); - return buf; + int fd = xopen(filename, (rw ? O_RDWR : O_RDONLY) | O_CLOEXEC); + if (fd < 0) { + *size = 0; + return nullptr; + } + struct stat st; + void *buf; + if (fstat(fd, &st)) { + *size = 0; + return nullptr; + } + if (S_ISBLK(st.st_mode)) + ioctl(fd, BLKGETSIZE64, size); + else + *size = st.st_size; + buf = *size > 0 ? xmmap(nullptr, *size, PROT_READ | (rw ? PROT_WRITE : 0), MAP_SHARED, fd, 0) : nullptr; + close(fd); + return buf; } void fd_full_read(int fd, void **buf, size_t *size) { - *size = lseek(fd, 0, SEEK_END); - lseek(fd, 0, SEEK_SET); - *buf = xmalloc(*size + 1); - xxread(fd, *buf, *size); - ((char *) *buf)[*size] = '\0'; + *size = lseek(fd, 0, SEEK_END); + lseek(fd, 0, SEEK_SET); + *buf = xmalloc(*size + 1); + xxread(fd, *buf, *size); + ((char *) *buf)[*size] = '\0'; } void full_read(const char *filename, void **buf, size_t *size) { - int fd = xopen(filename, O_RDONLY | O_CLOEXEC); - if (fd < 0) { - *buf = nullptr; - *size = 0; - return; - } - fd_full_read(fd, buf, size); - close(fd); + int fd = xopen(filename, O_RDONLY | O_CLOEXEC); + if (fd < 0) { + *buf = nullptr; + *size = 0; + return; + } + fd_full_read(fd, buf, size); + close(fd); } string fd_full_read(int fd) { - char buf[4096]; - string str; - for (ssize_t len; (len = xread(fd, buf, sizeof(buf))) > 0;) - str.insert(str.end(), buf, buf + len); - return str; + char buf[4096]; + string str; + for (ssize_t len; (len = xread(fd, buf, sizeof(buf))) > 0;) + str.insert(str.end(), buf, buf + len); + return str; } string full_read(const char *filename) { - int fd = xopen(filename, O_RDONLY | O_CLOEXEC); - run_finally f([=]{ close(fd); }); - return fd < 0 ? "" : fd_full_read(fd); + int fd = xopen(filename, O_RDONLY | O_CLOEXEC); + run_finally f([=]{ close(fd); }); + return fd < 0 ? "" : fd_full_read(fd); } void write_zero(int fd, size_t size) { - char buf[4096] = {0}; - size_t len; - while (size > 0) { - len = sizeof(buf) > size ? size : sizeof(buf); - write(fd, buf, len); - size -= len; - } + char buf[4096] = {0}; + size_t len; + while (size > 0) { + len = sizeof(buf) > size ? size : sizeof(buf); + write(fd, buf, len); + size -= len; + } } void file_readline(bool trim, const char *file, const function &fn) { - FILE *fp = xfopen(file, "re"); - if (fp == nullptr) - return; - size_t len = 1024; - char *buf = (char *) malloc(len); - char *start; - ssize_t read; - while ((read = getline(&buf, &len, fp)) >= 0) { - start = buf; - if (trim) { - while (read && "\n\r "sv.find(buf[read - 1]) != string::npos) - --read; - buf[read] = '\0'; - while (*start == ' ') - ++start; - } - if (!fn(start)) - break; - } - fclose(fp); - free(buf); + FILE *fp = xfopen(file, "re"); + if (fp == nullptr) + return; + size_t len = 1024; + char *buf = (char *) malloc(len); + char *start; + ssize_t read; + while ((read = getline(&buf, &len, fp)) >= 0) { + start = buf; + if (trim) { + while (read && "\n\r "sv.find(buf[read - 1]) != string::npos) + --read; + buf[read] = '\0'; + while (*start == ' ') + ++start; + } + if (!fn(start)) + break; + } + fclose(fp); + free(buf); } void parse_prop_file(const char *file, const function &fn) { - file_readline(true, file, [&](string_view line_view) -> bool { - char *line = (char *) line_view.data(); - if (line[0] == '#') - return true; - char *eql = strchr(line, '='); - if (eql == nullptr || eql == line) - return true; - *eql = '\0'; - return fn(line, eql + 1); - }); + file_readline(true, file, [&](string_view line_view) -> bool { + char *line = (char *) line_view.data(); + if (line[0] == '#') + return true; + char *eql = strchr(line, '='); + if (eql == nullptr || eql == line) + return true; + *eql = '\0'; + return fn(line, eql + 1); + }); } void parse_mnt(const char *file, const function &fn) { - auto fp = sFILE(setmntent(file, "re"), endmntent); - if (fp) { - mntent mentry{}; - char buf[4096]; - while (getmntent_r(fp.get(), &mentry, buf, sizeof(buf))) { - if (!fn(&mentry)) - break; - } - } + auto fp = sFILE(setmntent(file, "re"), endmntent); + if (fp) { + mntent mentry{}; + char buf[4096]; + while (getmntent_r(fp.get(), &mentry, buf, sizeof(buf))) { + if (!fn(&mentry)) + break; + } + } } void backup_folder(const char *dir, vector &files) { - char path[4096]; - xrealpath(dir, path); - int len = strlen(path); - pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> bool { - int fd = xopenat(dfd, entry->d_name, O_RDONLY); - if (fd < 0) - return false; - run_finally f([&]{ close(fd); }); - if (fd_path(fd, path, sizeof(path)) < 0) - return false; - raw_file file; - file.path = path + len + 1; - if (fgetattr(fd, &file.attr) < 0) - return false; - if (entry->d_type == DT_REG) { - fd_full_read(fd, file.buf, file.sz); - } else if (entry->d_type == DT_LNK) { - xreadlinkat(dfd, entry->d_name, path, sizeof(path)); - file.sz = strlen(path) + 1; - file.buf = (uint8_t *) xmalloc(file.sz); - memcpy(file.buf, path, file.sz); - } - files.emplace_back(std::move(file)); - return true; - }); + char path[4096]; + xrealpath(dir, path); + int len = strlen(path); + pre_order_walk(xopen(dir, O_RDONLY), [&](int dfd, dirent *entry) -> bool { + int fd = xopenat(dfd, entry->d_name, O_RDONLY); + if (fd < 0) + return false; + run_finally f([&]{ close(fd); }); + if (fd_path(fd, path, sizeof(path)) < 0) + return false; + raw_file file; + file.path = path + len + 1; + if (fgetattr(fd, &file.attr) < 0) + return false; + if (entry->d_type == DT_REG) { + fd_full_read(fd, file.buf, file.sz); + } else if (entry->d_type == DT_LNK) { + xreadlinkat(dfd, entry->d_name, path, sizeof(path)); + file.sz = strlen(path) + 1; + file.buf = (uint8_t *) xmalloc(file.sz); + memcpy(file.buf, path, file.sz); + } + files.emplace_back(std::move(file)); + return true; + }); } void restore_folder(const char *dir, vector &files) { - string base(dir); - // Pre-order means folders will always be first - for (raw_file &file : files) { - string path = base + "/" + file.path; - if (S_ISDIR(file.attr.st.st_mode)) { - mkdirs(path.data(), 0); - } else if (S_ISREG(file.attr.st.st_mode)) { - auto fp = xopen_file(path.data(), "we"); - fwrite(file.buf, 1, file.sz, fp.get()); - } else if (S_ISLNK(file.attr.st.st_mode)) { - symlink((char *)file.buf, path.data()); - } - setattr(path.data(), &file.attr); - } + string base(dir); + // Pre-order means folders will always be first + for (raw_file &file : files) { + string path = base + "/" + file.path; + if (S_ISDIR(file.attr.st.st_mode)) { + mkdirs(path.data(), 0); + } else if (S_ISREG(file.attr.st.st_mode)) { + auto fp = xopen_file(path.data(), "we"); + fwrite(file.buf, 1, file.sz, fp.get()); + } else if (S_ISLNK(file.attr.st.st_mode)) { + symlink((char *)file.buf, path.data()); + } + setattr(path.data(), &file.attr); + } } sDIR make_dir(DIR *dp) { - return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; }); + return sDIR(dp, [](DIR *dp){ return dp ? closedir(dp) : 1; }); } sFILE make_file(FILE *fp) { - return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; }); + return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; }); } diff --git a/native/jni/utils/files.hpp b/native/jni/utils/files.hpp index bf6b766ed..465f176b4 100644 --- a/native/jni/utils/files.hpp +++ b/native/jni/utils/files.hpp @@ -14,29 +14,29 @@ #define align_off(p, a) (do_align(p, a) - (p)) struct file_attr { - struct stat st; - char con[128]; + struct stat st; + char con[128]; }; struct raw_file { - std::string path; - file_attr attr; - uint8_t *buf = nullptr; - size_t sz = 0; + std::string path; + file_attr attr; + uint8_t *buf = nullptr; + size_t sz = 0; - raw_file() = default; - raw_file(const raw_file&) = delete; - raw_file(raw_file &&d) { - path = std::move(d.path); - attr = d.attr; - buf = d.buf; - sz = d.sz; - d.buf = nullptr; - d.sz = 0; - } - ~raw_file() { - free(buf); - } + raw_file() = default; + raw_file(const raw_file&) = delete; + raw_file(raw_file &&d) { + path = std::move(d.path); + attr = d.attr; + buf = d.buf; + sz = d.sz; + d.buf = nullptr; + d.sz = 0; + } + ~raw_file() { + free(buf); + } }; ssize_t fd_path(int fd, char *path, size_t size); @@ -63,11 +63,11 @@ std::string full_read(const char *filename); void write_zero(int fd, size_t size); void file_readline(bool trim, const char *file, const std::function &fn); static inline void file_readline(const char *file, - const std::function &fn) { - file_readline(false, file, fn); + const std::function &fn) { + file_readline(false, file, fn); } void parse_prop_file(const char *file, - const std::function &fn); + const std::function &fn); void *__mmap(const char *filename, size_t *size, bool rw); void frm_rf(int dirfd); void clone_dir(int src, int dest); @@ -77,38 +77,38 @@ void restore_folder(const char *dir, std::vector &files); template void full_read(const char *filename, T &buf, size_t &size) { - static_assert(std::is_pointer::value); - full_read(filename, reinterpret_cast(&buf), &size); + static_assert(std::is_pointer::value); + full_read(filename, reinterpret_cast(&buf), &size); } template void fd_full_read(int fd, T &buf, size_t &size) { - static_assert(std::is_pointer::value); - fd_full_read(fd, reinterpret_cast(&buf), &size); + static_assert(std::is_pointer::value); + fd_full_read(fd, reinterpret_cast(&buf), &size); } template void mmap_ro(const char *filename, B &buf, size_t &sz) { - buf = (B) __mmap(filename, &sz, false); + buf = (B) __mmap(filename, &sz, false); } template void mmap_ro(const char *filename, B &buf, L &sz) { - size_t __sz; - buf = (B) __mmap(filename, &__sz, false); - sz = __sz; + size_t __sz; + buf = (B) __mmap(filename, &__sz, false); + sz = __sz; } template void mmap_rw(const char *filename, B &buf, size_t &sz) { - buf = (B) __mmap(filename, &sz, true); + buf = (B) __mmap(filename, &sz, true); } template void mmap_rw(const char *filename, B &buf, L &sz) { - size_t __sz; - buf = (B) __mmap(filename, &__sz, true); - sz = __sz; + size_t __sz; + buf = (B) __mmap(filename, &__sz, true); + sz = __sz; } using sFILE = std::unique_ptr; @@ -117,25 +117,25 @@ sDIR make_dir(DIR *dp); sFILE make_file(FILE *fp); static inline sDIR open_dir(const char *path) { - return make_dir(opendir(path)); + return make_dir(opendir(path)); } static inline sDIR xopen_dir(const char *path) { - return make_dir(xopendir(path)); + return make_dir(xopendir(path)); } static inline sDIR xopen_dir(int dirfd) { - return make_dir(xfdopendir(dirfd)); + return make_dir(xfdopendir(dirfd)); } static inline sFILE open_file(const char *path, const char *mode) { - return make_file(fopen(path, mode)); + return make_file(fopen(path, mode)); } static inline sFILE xopen_file(const char *path, const char *mode) { - return make_file(xfopen(path, mode)); + return make_file(xfopen(path, mode)); } static inline sFILE xopen_file(int fd, const char *mode) { - return make_file(xfdopen(fd, mode)); + return make_file(xfdopen(fd, mode)); } diff --git a/native/jni/utils/include/cpio.hpp b/native/jni/utils/include/cpio.hpp index dd877d904..47e8d62f7 100644 --- a/native/jni/utils/include/cpio.hpp +++ b/native/jni/utils/include/cpio.hpp @@ -11,67 +11,67 @@ struct cpio_newc_header; struct cpio_entry_base { - uint32_t mode = 0; - uint32_t uid = 0; - uint32_t gid = 0; - uint32_t filesize = 0; + uint32_t mode = 0; + uint32_t uid = 0; + uint32_t gid = 0; + uint32_t filesize = 0; - void *data = nullptr; + void *data = nullptr; - cpio_entry_base() : mode(0), uid(0), gid(0), filesize(0) {}; - explicit cpio_entry_base(const cpio_newc_header *h); - virtual ~cpio_entry_base() = default; + cpio_entry_base() : mode(0), uid(0), gid(0), filesize(0) {}; + explicit cpio_entry_base(const cpio_newc_header *h); + virtual ~cpio_entry_base() = default; }; struct cpio_entry : public cpio_entry_base { - std::string filename; + std::string filename; - cpio_entry() = default; - explicit cpio_entry(const char *name, uint32_t mode) : filename(name) { - this->mode = mode; - } - explicit cpio_entry(const cpio_newc_header *h) : cpio_entry_base(h) {} + cpio_entry() = default; + explicit cpio_entry(const char *name, uint32_t mode) : filename(name) { + this->mode = mode; + } + explicit cpio_entry(const cpio_newc_header *h) : cpio_entry_base(h) {} - ~cpio_entry() override { free(data); }; + ~cpio_entry() override { free(data); }; }; typedef std::map> entry_map; class cpio { public: - void dump(const char *file); - void rm(const char *name, bool r = false); - void extract(); - bool extract(const char *name, const char *file); - bool exists(const char *name); + void dump(const char *file); + void rm(const char *name, bool r = false); + void extract(); + bool extract(const char *name, const char *file); + bool exists(const char *name); protected: - entry_map entries; - void rm(entry_map::iterator &it); - void dump(FILE *out); + entry_map entries; + void rm(entry_map::iterator &it); + void dump(FILE *out); }; class cpio_rw : public cpio { public: - cpio_rw() = default; - explicit cpio_rw(const char *file); - void load_cpio(const char *file); - void add(mode_t mode, const char *name, const char *file); - void mkdir(mode_t mode, const char *name); - void ln(const char *target, const char *name); - bool mv(const char *from, const char *to); + cpio_rw() = default; + explicit cpio_rw(const char *file); + void load_cpio(const char *file); + void add(mode_t mode, const char *name, const char *file); + void mkdir(mode_t mode, const char *name); + void ln(const char *target, const char *name); + bool mv(const char *from, const char *to); protected: - void insert(cpio_entry *e); - void mv(entry_map::iterator &it, const char *to); - void load_cpio(const char *buf, size_t sz); + void insert(cpio_entry *e); + void mv(entry_map::iterator &it, const char *to); + void load_cpio(const char *buf, size_t sz); }; class cpio_mmap : public cpio { public: - explicit cpio_mmap(const char *file); - ~cpio_mmap(); + explicit cpio_mmap(const char *file); + ~cpio_mmap(); private: - char *buf; - size_t sz; + char *buf; + size_t sz; }; diff --git a/native/jni/utils/include/stream.hpp b/native/jni/utils/include/stream.hpp index 3ee6d5d82..210a908b4 100644 --- a/native/jni/utils/include/stream.hpp +++ b/native/jni/utils/include/stream.hpp @@ -7,10 +7,10 @@ class stream { public: - virtual int read(void *buf, size_t len); - virtual int write(const void *buf, size_t len); - virtual off_t seek(off_t off, int whence); - virtual ~stream() = default; + virtual int read(void *buf, size_t len); + virtual int write(const void *buf, size_t len); + virtual off_t seek(off_t off, int whence); + virtual ~stream() = default; }; using stream_ptr = std::unique_ptr; @@ -18,44 +18,44 @@ using stream_ptr = std::unique_ptr; // Delegates all operations to base stream class filter_stream : public stream { public: - filter_stream(stream_ptr &&base) : base(std::move(base)) {} + filter_stream(stream_ptr &&base) : base(std::move(base)) {} - int read(void *buf, size_t len) override; - int write(const void *buf, size_t len) override; + int read(void *buf, size_t len) override; + int write(const void *buf, size_t len) override; protected: - stream_ptr base; + stream_ptr base; }; // Byte stream that dynamically allocates memory class byte_stream : public stream { public: - byte_stream(uint8_t *&buf, size_t &len); - template - byte_stream(byte *&buf, size_t &len) : byte_stream(reinterpret_cast(buf), len) {} - int read(void *buf, size_t len) override; - int write(const void *buf, size_t len) override; - off_t seek(off_t off, int whence) override; + byte_stream(uint8_t *&buf, size_t &len); + template + byte_stream(byte *&buf, size_t &len) : byte_stream(reinterpret_cast(buf), len) {} + int read(void *buf, size_t len) override; + int write(const void *buf, size_t len) override; + off_t seek(off_t off, int whence) override; private: - uint8_t *&_buf; - size_t &_len; - size_t _pos = 0; - size_t _cap = 0; + uint8_t *&_buf; + size_t &_len; + size_t _pos = 0; + size_t _cap = 0; - void resize(size_t new_pos, bool zero = false); + void resize(size_t new_pos, bool zero = false); }; // File stream but does not close the file descriptor at any time class fd_stream : public stream { public: - fd_stream(int fd) : fd(fd) {} - int read(void *buf, size_t len) override; - int write(const void *buf, size_t len) override; - off_t seek(off_t off, int whence) override; + fd_stream(int fd) : fd(fd) {} + int read(void *buf, size_t len) override; + int write(const void *buf, size_t len) override; + off_t seek(off_t off, int whence) override; private: - int fd; + int fd; }; /* **************************************** @@ -65,14 +65,14 @@ private: // sFILE -> stream_ptr class fp_stream final : public stream { public: - fp_stream(FILE *fp = nullptr) : fp(fp, fclose) {} - fp_stream(sFILE &&fp) : fp(std::move(fp)) {} - int read(void *buf, size_t len) override; - int write(const void *buf, size_t len) override; - off_t seek(off_t off, int whence) override; + fp_stream(FILE *fp = nullptr) : fp(fp, fclose) {} + fp_stream(sFILE &&fp) : fp(std::move(fp)) {} + int read(void *buf, size_t len) override; + int write(const void *buf, size_t len) override; + off_t seek(off_t off, int whence) override; private: - sFILE fp; + sFILE fp; }; // stream_ptr -> sFILE @@ -80,5 +80,5 @@ sFILE make_stream_fp(stream_ptr &&strm); template sFILE make_stream_fp(Args &&... args) { - return make_stream_fp(stream_ptr(new T(std::forward(args)...))); + return make_stream_fp(stream_ptr(new T(std::forward(args)...))); } diff --git a/native/jni/utils/logging.cpp b/native/jni/utils/logging.cpp index dedf846bd..c35f802e0 100644 --- a/native/jni/utils/logging.cpp +++ b/native/jni/utils/logging.cpp @@ -11,48 +11,48 @@ int nop_log(const char *, va_list) { return 0; } void nop_ex(int) {} log_callback log_cb = { - .d = nop_log, - .i = nop_log, - .w = nop_log, - .e = nop_log, - .ex = nop_ex + .d = nop_log, + .i = nop_log, + .w = nop_log, + .e = nop_log, + .ex = nop_ex }; void no_logging() { - log_cb.d = nop_log; - log_cb.i = nop_log; - log_cb.w = nop_log; - log_cb.e = nop_log; - log_cb.ex = nop_ex; + log_cb.d = nop_log; + log_cb.i = nop_log; + log_cb.w = nop_log; + log_cb.e = nop_log; + log_cb.ex = nop_ex; } static int vprintfe(const char *fmt, va_list ap) { - return vfprintf(stderr, fmt, ap); + return vfprintf(stderr, fmt, ap); } void cmdline_logging() { - log_cb.d = vprintfe; - log_cb.i = vprintf; - log_cb.w = vprintfe; - log_cb.e = vprintfe; - log_cb.ex = exit; + log_cb.d = vprintfe; + log_cb.i = vprintf; + log_cb.w = vprintfe; + log_cb.e = vprintfe; + log_cb.ex = exit; } template void log_handler(const char *fmt, ...) { - va_list argv; - va_start(argv, fmt); - if constexpr (type == L_DEBUG) { - log_cb.d(fmt, argv); - } else if constexpr (type == L_INFO) { - log_cb.i(fmt, argv); - } else if constexpr (type == L_WARN) { - log_cb.w(fmt, argv); - } else if constexpr (type == L_ERR) { - log_cb.e(fmt, argv); - log_cb.ex(1); - } - va_end(argv); + va_list argv; + va_start(argv, fmt); + if constexpr (type == L_DEBUG) { + log_cb.d(fmt, argv); + } else if constexpr (type == L_INFO) { + log_cb.i(fmt, argv); + } else if constexpr (type == L_WARN) { + log_cb.w(fmt, argv); + } else if constexpr (type == L_ERR) { + log_cb.e(fmt, argv); + log_cb.ex(1); + } + va_end(argv); } template void log_handler(const char *fmt, ...); diff --git a/native/jni/utils/logging.hpp b/native/jni/utils/logging.hpp index 0e58b0513..be0857fae 100644 --- a/native/jni/utils/logging.hpp +++ b/native/jni/utils/logging.hpp @@ -5,18 +5,18 @@ #include enum { - L_DEBUG, - L_INFO, - L_WARN, - L_ERR + L_DEBUG, + L_INFO, + L_WARN, + L_ERR }; struct log_callback { - int (*d)(const char* fmt, va_list ap); - int (*i)(const char* fmt, va_list ap); - int (*w)(const char* fmt, va_list ap); - int (*e)(const char* fmt, va_list ap); - void (*ex)(int code); + int (*d)(const char* fmt, va_list ap); + int (*i)(const char* fmt, va_list ap); + int (*w)(const char* fmt, va_list ap); + int (*e)(const char* fmt, va_list ap); + void (*ex)(int code); }; extern log_callback log_cb; diff --git a/native/jni/utils/misc.cpp b/native/jni/utils/misc.cpp index aed1ff63d..88884f6c5 100644 --- a/native/jni/utils/misc.cpp +++ b/native/jni/utils/misc.cpp @@ -14,23 +14,23 @@ using namespace std; int fork_dont_care() { - if (int pid = xfork()) { - waitpid(pid, nullptr, 0); - return pid; - } else if (xfork()) { - exit(0); - } - return 0; + if (int pid = xfork()) { + waitpid(pid, nullptr, 0); + return pid; + } else if (xfork()) { + exit(0); + } + return 0; } int fork_no_orphan() { - int pid = xfork(); - if (pid) - return pid; - prctl(PR_SET_PDEATHSIG, SIGTERM); - if (getppid() == 1) - exit(1); - return 0; + int pid = xfork(); + if (pid) + return pid; + prctl(PR_SET_PDEATHSIG, SIGTERM); + if (getppid() == 1) + exit(1); + return 0; } constexpr char ALPHANUM[] = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789"; @@ -38,111 +38,111 @@ static bool seeded = false; static std::mt19937 gen; static std::uniform_int_distribution dist(0, sizeof(ALPHANUM) - 2); int gen_rand_str(char *buf, int len, bool varlen) { - if (!seeded) { - if (access("/dev/urandom", F_OK) != 0) - mknod("/dev/urandom", 0600 | S_IFCHR, makedev(1, 9)); - int fd = xopen("/dev/urandom", O_RDONLY | O_CLOEXEC); - unsigned seed; - xxread(fd, &seed, sizeof(seed)); - gen.seed(seed); - close(fd); - seeded = true; - } - if (varlen) { - std::uniform_int_distribution len_dist(len / 2, len); - len = len_dist(gen); - } - for (int i = 0; i < len - 1; ++i) - buf[i] = ALPHANUM[dist(gen)]; - buf[len - 1] = '\0'; - return len - 1; + if (!seeded) { + if (access("/dev/urandom", F_OK) != 0) + mknod("/dev/urandom", 0600 | S_IFCHR, makedev(1, 9)); + int fd = xopen("/dev/urandom", O_RDONLY | O_CLOEXEC); + unsigned seed; + xxread(fd, &seed, sizeof(seed)); + gen.seed(seed); + close(fd); + seeded = true; + } + if (varlen) { + std::uniform_int_distribution len_dist(len / 2, len); + len = len_dist(gen); + } + for (int i = 0; i < len - 1; ++i) + buf[i] = ALPHANUM[dist(gen)]; + buf[len - 1] = '\0'; + return len - 1; } int exec_command(exec_t &exec) { - int pipefd[] = {-1, -1}; - int outfd = -1; + int pipefd[] = {-1, -1}; + int outfd = -1; - if (exec.fd == -1) { - if (xpipe2(pipefd, O_CLOEXEC) == -1) - return -1; - outfd = pipefd[1]; - } else if (exec.fd >= 0) { - outfd = exec.fd; - } + if (exec.fd == -1) { + if (xpipe2(pipefd, O_CLOEXEC) == -1) + return -1; + outfd = pipefd[1]; + } else if (exec.fd >= 0) { + outfd = exec.fd; + } - int pid = exec.fork(); - if (pid < 0) { - close(pipefd[0]); - close(pipefd[1]); - return -1; - } else if (pid) { - if (exec.fd == -1) { - exec.fd = pipefd[0]; - close(pipefd[1]); - } - return pid; - } + int pid = exec.fork(); + if (pid < 0) { + close(pipefd[0]); + close(pipefd[1]); + return -1; + } else if (pid) { + if (exec.fd == -1) { + exec.fd = pipefd[0]; + close(pipefd[1]); + } + return pid; + } - // Unblock all signals - sigset_t set; - sigfillset(&set); - pthread_sigmask(SIG_UNBLOCK, &set, nullptr); + // Unblock all signals + sigset_t set; + sigfillset(&set); + pthread_sigmask(SIG_UNBLOCK, &set, nullptr); - if (outfd >= 0) { - xdup2(outfd, STDOUT_FILENO); - if (exec.err) - xdup2(outfd, STDERR_FILENO); - close(outfd); - } + if (outfd >= 0) { + xdup2(outfd, STDOUT_FILENO); + if (exec.err) + xdup2(outfd, STDERR_FILENO); + close(outfd); + } - // Call the pre-exec callback - if (exec.pre_exec) - exec.pre_exec(); + // Call the pre-exec callback + if (exec.pre_exec) + exec.pre_exec(); - execve(exec.argv[0], (char **) exec.argv, environ); - PLOGE("execve %s", exec.argv[0]); - exit(-1); + execve(exec.argv[0], (char **) exec.argv, environ); + PLOGE("execve %s", exec.argv[0]); + exit(-1); } int exec_command_sync(exec_t &exec) { - int pid = exec_command(exec); - if (pid < 0) - return -1; - int status; - waitpid(pid, &status, 0); - return WEXITSTATUS(status); + int pid = exec_command(exec); + if (pid < 0) + return -1; + int status; + waitpid(pid, &status, 0); + return WEXITSTATUS(status); } int new_daemon_thread(thread_entry entry, void *arg, const pthread_attr_t *attr) { - pthread_t thread; - int ret = xpthread_create(&thread, attr, entry, arg); - if (ret == 0) - pthread_detach(thread); - return ret; + pthread_t thread; + int ret = xpthread_create(&thread, attr, entry, arg); + if (ret == 0) + pthread_detach(thread); + return ret; } static void *proxy_routine(void *fp) { - auto fn = reinterpret_cast*>(fp); - (*fn)(); - delete fn; - return nullptr; + auto fn = reinterpret_cast*>(fp); + (*fn)(); + delete fn; + return nullptr; } int new_daemon_thread(std::function &&entry) { - return new_daemon_thread(proxy_routine, new std::function(std::move(entry))); + return new_daemon_thread(proxy_routine, new std::function(std::move(entry))); } static char *argv0; static size_t name_len; void init_argv0(int argc, char **argv) { - argv0 = argv[0]; - name_len = (argv[argc - 1] - argv[0]) + strlen(argv[argc - 1]) + 1; + argv0 = argv[0]; + name_len = (argv[argc - 1] - argv[0]) + strlen(argv[argc - 1]) + 1; } void set_nice_name(const char *name) { - memset(argv0, 0, name_len); - strlcpy(argv0, name, name_len); - prctl(PR_SET_NAME, name); + memset(argv0, 0, name_len); + strlcpy(argv0, name, name_len); + prctl(PR_SET_NAME, name); } /* @@ -150,52 +150,52 @@ void set_nice_name(const char *name) { * Use our own implementation for faster conversion. */ int parse_int(const char *s) { - int val = 0; - char c; - while ((c = *(s++))) { - if (c > '9' || c < '0') - return -1; - val = val * 10 + c - '0'; - } - return val; + int val = 0; + char c; + while ((c = *(s++))) { + if (c > '9' || c < '0') + return -1; + val = val * 10 + c - '0'; + } + return val; } uint32_t binary_gcd(uint32_t u, uint32_t v) { - if (u == 0) return v; - if (v == 0) return u; - auto shift = __builtin_ctz(u | v); - u >>= __builtin_ctz(u); - do { - v >>= __builtin_ctz(v); - if (u > v) { - auto t = v; - v = u; - u = t; - } - v -= u; - } while (v != 0); - return u << shift; + if (u == 0) return v; + if (v == 0) return u; + auto shift = __builtin_ctz(u | v); + u >>= __builtin_ctz(u); + do { + v >>= __builtin_ctz(v); + if (u > v) { + auto t = v; + v = u; + u = t; + } + v -= u; + } while (v != 0); + return u << shift; } int switch_mnt_ns(int pid) { - char mnt[32]; - snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid); - if (access(mnt, R_OK) == -1) return 1; // Maybe process died.. + char mnt[32]; + snprintf(mnt, sizeof(mnt), "/proc/%d/ns/mnt", pid); + if (access(mnt, R_OK) == -1) return 1; // Maybe process died.. - int fd, ret; - fd = xopen(mnt, O_RDONLY); - if (fd < 0) return 1; - // Switch to its namespace - ret = xsetns(fd, 0); - close(fd); - return ret; + int fd, ret; + fd = xopen(mnt, O_RDONLY); + if (fd < 0) return 1; + // Switch to its namespace + ret = xsetns(fd, 0); + close(fd); + return ret; } string &replace_all(string &str, string_view from, string_view to) { - size_t pos = 0; - while((pos = str.find(from, pos)) != string::npos) { - str.replace(pos, from.length(), to); - pos += to.length(); - } - return str; + size_t pos = 0; + while((pos = str.find(from, pos)) != string::npos) { + str.replace(pos, from.length(), to); + pos += to.length(); + } + return str; } diff --git a/native/jni/utils/misc.hpp b/native/jni/utils/misc.hpp index 995c78f80..65e06cec7 100644 --- a/native/jni/utils/misc.hpp +++ b/native/jni/utils/misc.hpp @@ -10,48 +10,48 @@ class mutex_guard { public: - explicit mutex_guard(pthread_mutex_t &m): mutex(&m) { - pthread_mutex_lock(mutex); - } + explicit mutex_guard(pthread_mutex_t &m): mutex(&m) { + pthread_mutex_lock(mutex); + } - explicit mutex_guard(pthread_mutex_t *m): mutex(m) { - pthread_mutex_lock(mutex); - } + explicit mutex_guard(pthread_mutex_t *m): mutex(m) { + pthread_mutex_lock(mutex); + } - ~mutex_guard() { - pthread_mutex_unlock(mutex); - } + ~mutex_guard() { + pthread_mutex_unlock(mutex); + } private: - pthread_mutex_t *mutex; + pthread_mutex_t *mutex; }; template class run_finally { public: - explicit run_finally(const Func &fn) : fn(fn) {} - ~run_finally() { fn(); } + explicit run_finally(const Func &fn) : fn(fn) {} + ~run_finally() { fn(); } private: - const Func &fn; + const Func &fn; }; template class reversed_container { public: - reversed_container(T &base) : base(base) {} - decltype(std::declval().rbegin()) begin() { return base.rbegin(); } - decltype(std::declval().crbegin()) begin() const { return base.crbegin(); } - decltype(std::declval().crbegin()) cbegin() const { return base.crbegin(); } - decltype(std::declval().rend()) end() { return base.rend(); } - decltype(std::declval().crend()) end() const { return base.crend(); } - decltype(std::declval().crend()) cend() const { return base.crend(); } + reversed_container(T &base) : base(base) {} + decltype(std::declval().rbegin()) begin() { return base.rbegin(); } + decltype(std::declval().crbegin()) begin() const { return base.crbegin(); } + decltype(std::declval().crbegin()) cbegin() const { return base.crbegin(); } + decltype(std::declval().rend()) end() { return base.rend(); } + decltype(std::declval().crend()) end() const { return base.crend(); } + decltype(std::declval().crend()) cend() const { return base.crend(); } private: - T &base; + T &base; }; template reversed_container reversed(T &base) { - return reversed_container(base); + return reversed_container(base); } int parse_int(const char *s); @@ -63,13 +63,13 @@ int new_daemon_thread(thread_entry entry, void *arg = nullptr, const pthread_att int new_daemon_thread(std::function &&entry); static inline bool str_contains(std::string_view s, std::string_view ss) { - return s.find(ss) != std::string::npos; + return s.find(ss) != std::string::npos; } static inline bool str_starts(std::string_view s, std::string_view ss) { - return s.rfind(ss, 0) == 0; + return s.rfind(ss, 0) == 0; } static inline bool str_ends(std::string_view s, std::string_view ss) { - return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string::npos, ss) == 0; + return s.size() >= ss.size() && s.compare(s.size() - ss.size(), std::string::npos, ss) == 0; } int fork_dont_care(); @@ -82,38 +82,38 @@ int gen_rand_str(char *buf, int len, bool varlen = true); std::string &replace_all(std::string &str, std::string_view from, std::string_view to); struct exec_t { - bool err = false; - int fd = -2; - void (*pre_exec)() = nullptr; - int (*fork)() = xfork; - const char **argv = nullptr; + bool err = false; + int fd = -2; + void (*pre_exec)() = nullptr; + int (*fork)() = xfork; + const char **argv = nullptr; }; int exec_command(exec_t &exec); template int exec_command(exec_t &exec, Args &&...args) { - const char *argv[] = {args..., nullptr}; - exec.argv = argv; - return exec_command(exec); + const char *argv[] = {args..., nullptr}; + exec.argv = argv; + return exec_command(exec); } int exec_command_sync(exec_t &exec); template int exec_command_sync(exec_t &exec, Args &&...args) { - const char *argv[] = {args..., nullptr}; - exec.argv = argv; - return exec_command_sync(exec); + const char *argv[] = {args..., nullptr}; + exec.argv = argv; + return exec_command_sync(exec); } template int exec_command_sync(Args &&...args) { - exec_t exec{}; - return exec_command_sync(exec, args...); + exec_t exec{}; + return exec_command_sync(exec, args...); } template void exec_command_async(Args &&...args) { - const char *argv[] = {args..., nullptr}; - exec_t exec { - .argv = argv, - .fork = fork_dont_care - }; - exec_command(exec); + const char *argv[] = {args..., nullptr}; + exec_t exec { + .argv = argv, + .fork = fork_dont_care + }; + exec_command(exec); } diff --git a/native/jni/utils/missing.cpp b/native/jni/utils/missing.cpp index dfcf271d4..20ec85cc3 100644 --- a/native/jni/utils/missing.cpp +++ b/native/jni/utils/missing.cpp @@ -14,96 +14,96 @@ * License: BSD, full copyright notice please check original source */ ssize_t compat_getdelim(char **buf, size_t *bufsiz, int delimiter, FILE *fp) { - char *ptr, *eptr; + char *ptr, *eptr; - if (*buf == nullptr || *bufsiz == 0) { - *bufsiz = BUFSIZ; - if ((*buf = (char *) malloc(*bufsiz)) == nullptr) - return -1; - } + if (*buf == nullptr || *bufsiz == 0) { + *bufsiz = BUFSIZ; + if ((*buf = (char *) malloc(*bufsiz)) == nullptr) + return -1; + } - for (ptr = *buf, eptr = *buf + *bufsiz;;) { - int c = fgetc(fp); - if (c == -1) { - if (feof(fp)) - return ptr == *buf ? -1 : ptr - *buf; - else - return -1; - } - *ptr++ = c; - if (c == delimiter) { - *ptr = '\0'; - return ptr - *buf; - } - if (ptr + 2 >= eptr) { - char *nbuf; - size_t nbufsiz = *bufsiz * 2; - ssize_t d = ptr - *buf; - if ((nbuf = (char *) realloc(*buf, nbufsiz)) == nullptr) - return -1; - *buf = nbuf; - *bufsiz = nbufsiz; - eptr = nbuf + nbufsiz; - ptr = nbuf + d; - } - } + for (ptr = *buf, eptr = *buf + *bufsiz;;) { + int c = fgetc(fp); + if (c == -1) { + if (feof(fp)) + return ptr == *buf ? -1 : ptr - *buf; + else + return -1; + } + *ptr++ = c; + if (c == delimiter) { + *ptr = '\0'; + return ptr - *buf; + } + if (ptr + 2 >= eptr) { + char *nbuf; + size_t nbufsiz = *bufsiz * 2; + ssize_t d = ptr - *buf; + if ((nbuf = (char *) realloc(*buf, nbufsiz)) == nullptr) + return -1; + *buf = nbuf; + *bufsiz = nbufsiz; + eptr = nbuf + nbufsiz; + ptr = nbuf + d; + } + } } ssize_t compat_getline(char **buf, size_t *bufsiz, FILE *fp) { - return getdelim(buf, bufsiz, '\n', fp); + return getdelim(buf, bufsiz, '\n', fp); } /* Original source: https://android.googlesource.com/platform/bionic/+/master/libc/bionic/mntent.cpp * License: AOSP, full copyright notice please check original source */ struct mntent *compat_getmntent_r(FILE* fp, struct mntent* e, char* buf, int buf_len) { - memset(e, 0, sizeof(*e)); - while (fgets(buf, buf_len, fp) != nullptr) { - // Entries look like "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0". - // That is: mnt_fsname mnt_dir mnt_type mnt_opts 0 0. - int fsname0, fsname1, dir0, dir1, type0, type1, opts0, opts1; - if (sscanf(buf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", - &fsname0, &fsname1, &dir0, &dir1, &type0, &type1, &opts0, &opts1, - &e->mnt_freq, &e->mnt_passno) == 2) { - e->mnt_fsname = &buf[fsname0]; - buf[fsname1] = '\0'; - e->mnt_dir = &buf[dir0]; - buf[dir1] = '\0'; - e->mnt_type = &buf[type0]; - buf[type1] = '\0'; - e->mnt_opts = &buf[opts0]; - buf[opts1] = '\0'; - return e; - } - } - return nullptr; + memset(e, 0, sizeof(*e)); + while (fgets(buf, buf_len, fp) != nullptr) { + // Entries look like "proc /proc proc rw,nosuid,nodev,noexec,relatime 0 0". + // That is: mnt_fsname mnt_dir mnt_type mnt_opts 0 0. + int fsname0, fsname1, dir0, dir1, type0, type1, opts0, opts1; + if (sscanf(buf, " %n%*s%n %n%*s%n %n%*s%n %n%*s%n %d %d", + &fsname0, &fsname1, &dir0, &dir1, &type0, &type1, &opts0, &opts1, + &e->mnt_freq, &e->mnt_passno) == 2) { + e->mnt_fsname = &buf[fsname0]; + buf[fsname1] = '\0'; + e->mnt_dir = &buf[dir0]; + buf[dir1] = '\0'; + e->mnt_type = &buf[type0]; + buf[type1] = '\0'; + e->mnt_opts = &buf[opts0]; + buf[opts1] = '\0'; + return e; + } + } + return nullptr; } FILE *compat_setmntent(const char* path, const char* mode) { - return fopen(path, mode); + return fopen(path, mode); } int compat_endmntent(FILE* fp) { - if (fp != nullptr) { - fclose(fp); - } - return 1; + if (fp != nullptr) { + fclose(fp); + } + return 1; } char *compat_hasmntopt(const struct mntent* mnt, const char* opt) { - char* token = mnt->mnt_opts; - char* const end = mnt->mnt_opts + strlen(mnt->mnt_opts); - const size_t optLen = strlen(opt); - while (token) { - char* const tokenEnd = token + optLen; - if (tokenEnd > end) break; - if (memcmp(token, opt, optLen) == 0 && - (*tokenEnd == '\0' || *tokenEnd == ',' || *tokenEnd == '=')) { - return token; - } - token = strchr(token, ','); - if (token) token++; - } - return nullptr; + char* token = mnt->mnt_opts; + char* const end = mnt->mnt_opts + strlen(mnt->mnt_opts); + const size_t optLen = strlen(opt); + while (token) { + char* const tokenEnd = token + optLen; + if (tokenEnd > end) break; + if (memcmp(token, opt, optLen) == 0 && + (*tokenEnd == '\0' || *tokenEnd == ',' || *tokenEnd == '=')) { + return token; + } + token = strchr(token, ','); + if (token) token++; + } + return nullptr; } diff --git a/native/jni/utils/missing.hpp b/native/jni/utils/missing.hpp index 14dc7f012..83f82cddb 100644 --- a/native/jni/utils/missing.hpp +++ b/native/jni/utils/missing.hpp @@ -31,38 +31,38 @@ int compat_endmntent(FILE* fp); char *compat_hasmntopt(const struct mntent* mnt, const char* opt); static inline int compat_setns(int fd, int nstype) { - return syscall(__NR_setns, fd, nstype); + return syscall(__NR_setns, fd, nstype); } static inline int compat_unshare(int flags) { - return syscall(__NR_unshare, flags); + return syscall(__NR_unshare, flags); } static inline int compat_accept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { - return syscall(__NR_accept4, sockfd, addr, addrlen, flags); + return syscall(__NR_accept4, sockfd, addr, addrlen, flags); } static inline int compat_dup3(int oldfd, int newfd, int flags) { - return syscall(__NR_dup3, oldfd, newfd, flags); + return syscall(__NR_dup3, oldfd, newfd, flags); } static inline ssize_t compat_readlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { - return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz); + return syscall(__NR_readlinkat, dirfd, pathname, buf, bufsiz); } static inline int compat_symlinkat(const char *target, int newdirfd, const char *linkpath) { - return syscall(__NR_symlinkat, target, newdirfd, linkpath); + return syscall(__NR_symlinkat, target, newdirfd, linkpath); } static inline int compat_linkat(int olddirfd, const char *oldpath, - int newdirfd, const char *newpath, int flags) { - return syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags); + int newdirfd, const char *newpath, int flags) { + return syscall(__NR_linkat, olddirfd, oldpath, newdirfd, newpath, flags); } static inline int compat_inotify_init1(int flags) { - return syscall(__NR_inotify_init1, flags); + return syscall(__NR_inotify_init1, flags); } static inline int compat_faccessat(int dirfd, const char *pathname, int mode, int flags) { - return syscall(__NR_faccessat, dirfd, pathname, mode, flags); + return syscall(__NR_faccessat, dirfd, pathname, mode, flags); } diff --git a/native/jni/utils/selinux.cpp b/native/jni/utils/selinux.cpp index 01eba7947..9a84a7bc8 100644 --- a/native/jni/utils/selinux.cpp +++ b/native/jni/utils/selinux.cpp @@ -12,67 +12,67 @@ static int stub(const char *) { return 0; } static int stub(const char *, const char *) { return 0; } static int stub(const char *, char **ctx) { - *ctx = strdup(""); - return 0; + *ctx = strdup(""); + return 0; } static int stub(int, const char *) { return 0; } static int stub(int, char **ctx) { - *ctx = strdup(""); - return 0; + *ctx = strdup(""); + return 0; } // Builtin implementation static void __freecon(char *s) { - free(s); + free(s); } static int __setcon(const char *ctx) { - int fd = open("/proc/self/attr/current", O_WRONLY | O_CLOEXEC); - if (fd < 0) - return fd; - size_t len = strlen(ctx) + 1; - int rc = write(fd, ctx, len); - close(fd); - return rc != len; + int fd = open("/proc/self/attr/current", O_WRONLY | O_CLOEXEC); + if (fd < 0) + return fd; + size_t len = strlen(ctx) + 1; + int rc = write(fd, ctx, len); + close(fd); + return rc != len; } static int __getfilecon(const char *path, char **ctx) { - char buf[1024]; - int rc = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1); - if (rc >= 0) - *ctx = strdup(buf); - return rc; + char buf[1024]; + int rc = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1); + if (rc >= 0) + *ctx = strdup(buf); + return rc; } static int __lgetfilecon(const char *path, char **ctx) { - char buf[1024]; - int rc = syscall(__NR_lgetxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1); - if (rc >= 0) - *ctx = strdup(buf); - return rc; + char buf[1024]; + int rc = syscall(__NR_lgetxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1); + if (rc >= 0) + *ctx = strdup(buf); + return rc; } static int __fgetfilecon(int fd, char **ctx) { - char buf[1024]; - int rc = syscall(__NR_fgetxattr, fd, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1); - if (rc >= 0) - *ctx = strdup(buf); - return rc; + char buf[1024]; + int rc = syscall(__NR_fgetxattr, fd, XATTR_NAME_SELINUX, buf, sizeof(buf) - 1); + if (rc >= 0) + *ctx = strdup(buf); + return rc; } static int __setfilecon(const char *path, const char *ctx) { - return syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0); + return syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0); } static int __lsetfilecon(const char *path, const char *ctx) { - return syscall(__NR_lsetxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0); + return syscall(__NR_lsetxattr, path, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0); } static int __fsetfilecon(int fd, const char *ctx) { - return syscall(__NR_fsetxattr, fd, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0); + return syscall(__NR_fsetxattr, fd, XATTR_NAME_SELINUX, ctx, strlen(ctx) + 1, 0); } // Function pointers @@ -87,34 +87,34 @@ int (*lsetfilecon)(const char *, const char *) = stub; int (*fsetfilecon)(int, const char *) = stub; void getfilecon_at(int dirfd, const char *name, char **con) { - char path[4096]; - fd_pathat(dirfd, name, path, sizeof(path)); - if (lgetfilecon(path, con)) - *con = strdup(""); + char path[4096]; + fd_pathat(dirfd, name, path, sizeof(path)); + if (lgetfilecon(path, con)) + *con = strdup(""); } void setfilecon_at(int dirfd, const char *name, const char *con) { - char path[4096]; - fd_pathat(dirfd, name, path, sizeof(path)); - lsetfilecon(path, con); + char path[4096]; + fd_pathat(dirfd, name, path, sizeof(path)); + lsetfilecon(path, con); } void selinux_builtin_impl() { - setcon = __setcon; - getfilecon = __getfilecon; - lgetfilecon = __lgetfilecon; - fgetfilecon = __fgetfilecon; - setfilecon = __setfilecon; - lsetfilecon = __lsetfilecon; - fsetfilecon = __fsetfilecon; + setcon = __setcon; + getfilecon = __getfilecon; + lgetfilecon = __lgetfilecon; + fgetfilecon = __fgetfilecon; + setfilecon = __setfilecon; + lsetfilecon = __lsetfilecon; + fsetfilecon = __fsetfilecon; } void dload_selinux() { - if (access("/system/lib/libselinux.so", F_OK)) - return; - /* We only check whether libselinux.so exists but don't dlopen. - * For some reason calling symbols returned from dlsym - * will result to SEGV_ACCERR on some devices. - * Always use builtin implementations for SELinux stuffs. */ - selinux_builtin_impl(); + if (access("/system/lib/libselinux.so", F_OK)) + return; + /* We only check whether libselinux.so exists but don't dlopen. + * For some reason calling symbols returned from dlsym + * will result to SEGV_ACCERR on some devices. + * Always use builtin implementations for SELinux stuffs. */ + selinux_builtin_impl(); } diff --git a/native/jni/utils/stream.cpp b/native/jni/utils/stream.cpp index 3e0d4a64c..ae00d56d5 100644 --- a/native/jni/utils/stream.cpp +++ b/native/jni/utils/stream.cpp @@ -2,128 +2,128 @@ #include static int strm_read(void *v, char *buf, int len) { - auto strm = reinterpret_cast(v); - return strm->read(buf, len); + auto strm = reinterpret_cast(v); + return strm->read(buf, len); } static int strm_write(void *v, const char *buf, int len) { - auto strm = reinterpret_cast(v); - return strm->write(buf, len); + auto strm = reinterpret_cast(v); + return strm->write(buf, len); } static fpos_t strm_seek(void *v, fpos_t off, int whence) { - auto strm = reinterpret_cast(v); - return strm->seek(off, whence); + auto strm = reinterpret_cast(v); + return strm->seek(off, whence); } static int strm_close(void *v) { - auto strm = reinterpret_cast(v); - delete strm; - return 0; + auto strm = reinterpret_cast(v); + delete strm; + return 0; } sFILE make_stream_fp(stream_ptr &&strm) { - auto fp = make_file(funopen(strm.release(), strm_read, strm_write, strm_seek, strm_close)); - setbuf(fp.get(), nullptr); - return fp; + auto fp = make_file(funopen(strm.release(), strm_read, strm_write, strm_seek, strm_close)); + setbuf(fp.get(), nullptr); + return fp; } int stream::read(void *buf, size_t len) { - LOGE("This stream does not support read\n"); - return -1; + LOGE("This stream does not support read\n"); + return -1; } int stream::write(const void *buf, size_t len) { - LOGE("This stream does not support write\n"); - return -1; + LOGE("This stream does not support write\n"); + return -1; } off_t stream::seek(off_t off, int whence) { - LOGE("This stream does not support seek\n"); - return -1; + LOGE("This stream does not support seek\n"); + return -1; } int fp_stream::read(void *buf, size_t len) { - return fread(buf, 1, len, fp.get()); + return fread(buf, 1, len, fp.get()); } int fp_stream::write(const void *buf, size_t len) { - return fwrite(buf, 1, len, fp.get()); + return fwrite(buf, 1, len, fp.get()); } off_t fp_stream::seek(off_t off, int whence) { - return fseek(fp.get(), off, whence); + return fseek(fp.get(), off, whence); } int filter_stream::read(void *buf, size_t len) { - return base->read(buf, len); + return base->read(buf, len); } int filter_stream::write(const void *buf, size_t len) { - return base->write(buf, len); + return base->write(buf, len); } byte_stream::byte_stream(uint8_t *&buf, size_t &len) : _buf(buf), _len(len) { - buf = nullptr; - len = 0; + buf = nullptr; + len = 0; } int byte_stream::read(void *buf, size_t len) { - len = std::min(len, _len - _pos); - memcpy(buf, _buf + _pos, len); - return len; + len = std::min(len, _len - _pos); + memcpy(buf, _buf + _pos, len); + return len; } int byte_stream::write(const void *buf, size_t len) { - resize(_pos + len); - memcpy(_buf + _pos, buf, len); - _pos += len; - _len = std::max(_len, _pos); - return len; + resize(_pos + len); + memcpy(_buf + _pos, buf, len); + _pos += len; + _len = std::max(_len, _pos); + return len; } off_t byte_stream::seek(off_t off, int whence) { - off_t np; - switch (whence) { - case SEEK_CUR: - np = _pos + off; - break; - case SEEK_END: - np = _len + off; - break; - case SEEK_SET: - np = off; - break; - default: - return -1; - } - resize(np, true); - _pos = np; - return np; + off_t np; + switch (whence) { + case SEEK_CUR: + np = _pos + off; + break; + case SEEK_END: + np = _len + off; + break; + case SEEK_SET: + np = off; + break; + default: + return -1; + } + resize(np, true); + _pos = np; + return np; } void byte_stream::resize(size_t new_pos, bool zero) { - bool resize = false; - size_t old_cap = _cap; - while (new_pos > _cap) { - _cap = _cap ? (_cap << 1) - (_cap >> 1) : 1 << 12; - resize = true; - } - if (resize) { - _buf = (uint8_t *) xrealloc(_buf, _cap); - if (zero) - memset(_buf + old_cap, 0, _cap - old_cap); - } + bool resize = false; + size_t old_cap = _cap; + while (new_pos > _cap) { + _cap = _cap ? (_cap << 1) - (_cap >> 1) : 1 << 12; + resize = true; + } + if (resize) { + _buf = (uint8_t *) xrealloc(_buf, _cap); + if (zero) + memset(_buf + old_cap, 0, _cap - old_cap); + } } int fd_stream::read(void *buf, size_t len) { - return ::read(fd, buf, len); + return ::read(fd, buf, len); } int fd_stream::write(const void *buf, size_t len) { - return ::write(fd, buf, len); + return ::write(fd, buf, len); } off_t fd_stream::seek(off_t off, int whence) { - return lseek(fd, off, whence); + return lseek(fd, off, whence); } diff --git a/native/jni/utils/xwrap.cpp b/native/jni/utils/xwrap.cpp index 2c53335f9..a4698678e 100644 --- a/native/jni/utils/xwrap.cpp +++ b/native/jni/utils/xwrap.cpp @@ -15,458 +15,458 @@ using namespace std; FILE *xfopen(const char *pathname, const char *mode) { - FILE *fp = fopen(pathname, mode); - if (fp == nullptr) { - PLOGE("fopen: %s", pathname); - } - return fp; + FILE *fp = fopen(pathname, mode); + if (fp == nullptr) { + PLOGE("fopen: %s", pathname); + } + return fp; } FILE *xfdopen(int fd, const char *mode) { - FILE *fp = fdopen(fd, mode); - if (fp == nullptr) { - PLOGE("fopen"); - } - return fp; + FILE *fp = fdopen(fd, mode); + if (fp == nullptr) { + PLOGE("fopen"); + } + return fp; } int xopen(const char *pathname, int flags) { - int fd = open(pathname, flags); - if (fd < 0) { - PLOGE("open: %s", pathname); - } - return fd; + int fd = open(pathname, flags); + if (fd < 0) { + PLOGE("open: %s", pathname); + } + return fd; } int xopen(const char *pathname, int flags, mode_t mode) { - int fd = open(pathname, flags, mode); - if (fd < 0) { - PLOGE("open: %s", pathname); - } - return fd; + int fd = open(pathname, flags, mode); + if (fd < 0) { + PLOGE("open: %s", pathname); + } + return fd; } int xopenat(int dirfd, const char *pathname, int flags) { - int fd = openat(dirfd, pathname, flags); - if (fd < 0) { - PLOGE("openat: %s", pathname); - } - return fd; + int fd = openat(dirfd, pathname, flags); + if (fd < 0) { + PLOGE("openat: %s", pathname); + } + return fd; } int xopenat(int dirfd, const char *pathname, int flags, mode_t mode) { - int fd = openat(dirfd, pathname, flags, mode); - if (fd < 0) { - PLOGE("openat: %s", pathname); - } - return fd; + int fd = openat(dirfd, pathname, flags, mode); + if (fd < 0) { + PLOGE("openat: %s", pathname); + } + return fd; } ssize_t xwrite(int fd, const void *buf, size_t count) { - int ret = write(fd, buf, count); - if (count != ret) { - PLOGE("write"); - } - return ret; + int ret = write(fd, buf, count); + if (count != ret) { + PLOGE("write"); + } + return ret; } // Read error other than EOF ssize_t xread(int fd, void *buf, size_t count) { - int ret = read(fd, buf, count); - if (ret < 0) { - PLOGE("read"); - } - return ret; + int ret = read(fd, buf, count); + if (ret < 0) { + PLOGE("read"); + } + return ret; } // Read exact same size as count ssize_t xxread(int fd, void *buf, size_t count) { - int ret = read(fd, buf, count); - if (count != ret) { - PLOGE("read (%zu != %d)", count, ret); - } - return ret; + int ret = read(fd, buf, count); + if (count != ret) { + PLOGE("read (%zu != %d)", count, ret); + } + return ret; } int xpipe2(int pipefd[2], int flags) { - int ret = pipe2(pipefd, flags); - if (ret < 0) { - PLOGE("pipe2"); - } - return ret; + int ret = pipe2(pipefd, flags); + if (ret < 0) { + PLOGE("pipe2"); + } + return ret; } int xsetns(int fd, int nstype) { - int ret = setns(fd, nstype); - if (ret < 0) { - PLOGE("setns"); - } - return ret; + int ret = setns(fd, nstype); + if (ret < 0) { + PLOGE("setns"); + } + return ret; } int xunshare(int flags) { - int ret = unshare(flags); - if (ret < 0) { - PLOGE("unshare"); - } - return ret; + int ret = unshare(flags); + if (ret < 0) { + PLOGE("unshare"); + } + return ret; } DIR *xopendir(const char *name) { - DIR *d = opendir(name); - if (d == nullptr) { - PLOGE("opendir: %s", name); - } - return d; + DIR *d = opendir(name); + if (d == nullptr) { + PLOGE("opendir: %s", name); + } + return d; } DIR *xfdopendir(int fd) { - DIR *d = fdopendir(fd); - if (d == nullptr) { - PLOGE("fdopendir"); - } - return d; + DIR *d = fdopendir(fd); + if (d == nullptr) { + PLOGE("fdopendir"); + } + return d; } struct dirent *xreaddir(DIR *dirp) { - errno = 0; - for (dirent *e;;) { - e = readdir(dirp); - if (e == nullptr) { - if (errno) - PLOGE("readdir"); - return nullptr; - } else if (e->d_name == "."sv || e->d_name == ".."sv) { - // Filter . and .. for users - continue; - } - return e; - } + errno = 0; + for (dirent *e;;) { + e = readdir(dirp); + if (e == nullptr) { + if (errno) + PLOGE("readdir"); + return nullptr; + } else if (e->d_name == "."sv || e->d_name == ".."sv) { + // Filter . and .. for users + continue; + } + return e; + } } pid_t xsetsid() { - pid_t pid = setsid(); - if (pid < 0) { - PLOGE("setsid"); - } - return pid; + pid_t pid = setsid(); + if (pid < 0) { + PLOGE("setsid"); + } + return pid; } int xsocket(int domain, int type, int protocol) { - int fd = socket(domain, type, protocol); - if (fd < 0) { - PLOGE("socket"); - } - return fd; + int fd = socket(domain, type, protocol); + if (fd < 0) { + PLOGE("socket"); + } + return fd; } int xbind(int sockfd, const struct sockaddr *addr, socklen_t addrlen) { - int ret = bind(sockfd, addr, addrlen); - if (ret < 0) { - PLOGE("bind"); - } - return ret; + int ret = bind(sockfd, addr, addrlen); + if (ret < 0) { + PLOGE("bind"); + } + return ret; } int xlisten(int sockfd, int backlog) { - int ret = listen(sockfd, backlog); - if (ret < 0) { - PLOGE("listen"); - } - return ret; + int ret = listen(sockfd, backlog); + if (ret < 0) { + PLOGE("listen"); + } + return ret; } static int accept4_compat(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { - int fd = accept(sockfd, addr, addrlen); - if (fd < 0) { - PLOGE("accept"); - } else { - if (flags & SOCK_CLOEXEC) - fcntl(fd, F_SETFD, FD_CLOEXEC); - if (flags & SOCK_NONBLOCK) { - int i = fcntl(fd, F_GETFL); - fcntl(fd, F_SETFL, i | O_NONBLOCK); - } - } - return fd; + int fd = accept(sockfd, addr, addrlen); + if (fd < 0) { + PLOGE("accept"); + } else { + if (flags & SOCK_CLOEXEC) + fcntl(fd, F_SETFD, FD_CLOEXEC); + if (flags & SOCK_NONBLOCK) { + int i = fcntl(fd, F_GETFL); + fcntl(fd, F_SETFL, i | O_NONBLOCK); + } + } + return fd; } int xaccept4(int sockfd, struct sockaddr *addr, socklen_t *addrlen, int flags) { - int fd = accept4(sockfd, addr, addrlen, flags); - if (fd < 0) { - if (errno == ENOSYS) - return accept4_compat(sockfd, addr, addrlen, flags); - PLOGE("accept4"); - } - return fd; + int fd = accept4(sockfd, addr, addrlen, flags); + if (fd < 0) { + if (errno == ENOSYS) + return accept4_compat(sockfd, addr, addrlen, flags); + PLOGE("accept4"); + } + return fd; } void *xmalloc(size_t size) { - void *p = malloc(size); - if (p == nullptr) { - PLOGE("malloc"); - } - return p; + void *p = malloc(size); + if (p == nullptr) { + PLOGE("malloc"); + } + return p; } void *xcalloc(size_t nmemb, size_t size) { - void *p = calloc(nmemb, size); - if (p == nullptr) { - PLOGE("calloc"); - } - return p; + void *p = calloc(nmemb, size); + if (p == nullptr) { + PLOGE("calloc"); + } + return p; } void *xrealloc(void *ptr, size_t size) { - void *p = realloc(ptr, size); - if (p == nullptr) { - PLOGE("realloc"); - } - return p; + void *p = realloc(ptr, size); + if (p == nullptr) { + PLOGE("realloc"); + } + return p; } ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags) { - int sent = sendmsg(sockfd, msg, flags); - if (sent < 0) { - PLOGE("sendmsg"); - } - return sent; + int sent = sendmsg(sockfd, msg, flags); + if (sent < 0) { + PLOGE("sendmsg"); + } + return sent; } ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags) { - int rec = recvmsg(sockfd, msg, flags); - if (rec < 0) { - PLOGE("recvmsg"); - } - return rec; + int rec = recvmsg(sockfd, msg, flags); + if (rec < 0) { + PLOGE("recvmsg"); + } + return rec; } int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine) (void *), void *arg) { - errno = pthread_create(thread, attr, start_routine, arg); - if (errno) { - PLOGE("pthread_create"); - } - return errno; + void *(*start_routine) (void *), void *arg) { + errno = pthread_create(thread, attr, start_routine, arg); + if (errno) { + PLOGE("pthread_create"); + } + return errno; } int xstat(const char *pathname, struct stat *buf) { - int ret = stat(pathname, buf); - if (ret < 0) { - PLOGE("stat %s", pathname); - } - return ret; + int ret = stat(pathname, buf); + if (ret < 0) { + PLOGE("stat %s", pathname); + } + return ret; } int xlstat(const char *pathname, struct stat *buf) { - int ret = lstat(pathname, buf); - if (ret < 0) { - PLOGE("lstat %s", pathname); - } - return ret; + int ret = lstat(pathname, buf); + if (ret < 0) { + PLOGE("lstat %s", pathname); + } + return ret; } int xfstat(int fd, struct stat *buf) { - int ret = fstat(fd, buf); - if (ret < 0) { - PLOGE("fstat %d", fd); - } - return ret; + int ret = fstat(fd, buf); + if (ret < 0) { + PLOGE("fstat %d", fd); + } + return ret; } int xdup(int fd) { - int ret = dup(fd); - if (ret < 0) { - PLOGE("dup"); - } - return ret; + int ret = dup(fd); + if (ret < 0) { + PLOGE("dup"); + } + return ret; } int xdup2(int oldfd, int newfd) { - int ret = dup2(oldfd, newfd); - if (ret < 0) { - PLOGE("dup2"); - } - return ret; + int ret = dup2(oldfd, newfd); + if (ret < 0) { + PLOGE("dup2"); + } + return ret; } int xdup3(int oldfd, int newfd, int flags) { - int ret = dup3(oldfd, newfd, flags); - if (ret < 0) { - PLOGE("dup3"); - } - return ret; + int ret = dup3(oldfd, newfd, flags); + if (ret < 0) { + PLOGE("dup3"); + } + return ret; } ssize_t xreadlink(const char *pathname, char *buf, size_t bufsiz) { - ssize_t ret = readlink(pathname, buf, bufsiz); - if (ret < 0) { - PLOGE("readlink %s", pathname); - } else { - buf[ret] = '\0'; - } - return ret; + ssize_t ret = readlink(pathname, buf, bufsiz); + if (ret < 0) { + PLOGE("readlink %s", pathname); + } else { + buf[ret] = '\0'; + } + return ret; } ssize_t xreadlinkat(int dirfd, const char *pathname, char *buf, size_t bufsiz) { - // readlinkat() may fail on x86 platform, returning random value - // instead of number of bytes placed in buf (length of link) + // readlinkat() may fail on x86 platform, returning random value + // instead of number of bytes placed in buf (length of link) #if defined(__i386__) || defined(__x86_64__) - memset(buf, 0, bufsiz); - ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz); - if (ret < 0) { - PLOGE("readlinkat %s", pathname); - } - return ret; + memset(buf, 0, bufsiz); + ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz); + if (ret < 0) { + PLOGE("readlinkat %s", pathname); + } + return ret; #else - ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz); - if (ret < 0) { - PLOGE("readlinkat %s", pathname); - } else { - buf[ret] = '\0'; - } - return ret; + ssize_t ret = readlinkat(dirfd, pathname, buf, bufsiz); + if (ret < 0) { + PLOGE("readlinkat %s", pathname); + } else { + buf[ret] = '\0'; + } + return ret; #endif } int xsymlink(const char *target, const char *linkpath) { - int ret = symlink(target, linkpath); - if (ret < 0) { - PLOGE("symlink %s->%s", target, linkpath); - } - return ret; + int ret = symlink(target, linkpath); + if (ret < 0) { + PLOGE("symlink %s->%s", target, linkpath); + } + return ret; } int xsymlinkat(const char *target, int newdirfd, const char *linkpath) { - int ret = symlinkat(target, newdirfd, linkpath); - if (ret < 0) { - PLOGE("symlinkat %s->%s", target, linkpath); - } - return ret; + int ret = symlinkat(target, newdirfd, linkpath); + if (ret < 0) { + PLOGE("symlinkat %s->%s", target, linkpath); + } + return ret; } int xlinkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags) { - int ret = linkat(olddirfd, oldpath, newdirfd, newpath, flags); - if (ret < 0) { - PLOGE("linkat %s->%s", oldpath, newpath); - } - return ret; + int ret = linkat(olddirfd, oldpath, newdirfd, newpath, flags); + if (ret < 0) { + PLOGE("linkat %s->%s", oldpath, newpath); + } + return ret; } int xmount(const char *source, const char *target, - const char *filesystemtype, unsigned long mountflags, - const void *data) { - int ret = mount(source, target, filesystemtype, mountflags, data); - if (ret < 0) { - PLOGE("mount %s->%s", source, target); - } - return ret; + const char *filesystemtype, unsigned long mountflags, + const void *data) { + int ret = mount(source, target, filesystemtype, mountflags, data); + if (ret < 0) { + PLOGE("mount %s->%s", source, target); + } + return ret; } int xumount(const char *target) { - int ret = umount(target); - if (ret < 0) { - PLOGE("umount %s", target); - } - return ret; + int ret = umount(target); + if (ret < 0) { + PLOGE("umount %s", target); + } + return ret; } int xumount2(const char *target, int flags) { - int ret = umount2(target, flags); - if (ret < 0) { - PLOGE("umount2 %s", target); - } - return ret; + int ret = umount2(target, flags); + if (ret < 0) { + PLOGE("umount2 %s", target); + } + return ret; } int xrename(const char *oldpath, const char *newpath) { - int ret = rename(oldpath, newpath); - if (ret < 0) { - PLOGE("rename %s->%s", oldpath, newpath); - } - return ret; + int ret = rename(oldpath, newpath); + if (ret < 0) { + PLOGE("rename %s->%s", oldpath, newpath); + } + return ret; } int xmkdir(const char *pathname, mode_t mode) { - int ret = mkdir(pathname, mode); - if (ret < 0 && errno != EEXIST) { - PLOGE("mkdir %s %u", pathname, mode); - } - return ret; + int ret = mkdir(pathname, mode); + if (ret < 0 && errno != EEXIST) { + PLOGE("mkdir %s %u", pathname, mode); + } + return ret; } int xmkdirs(const char *pathname, mode_t mode) { - int ret = mkdirs(pathname, mode); - if (ret < 0) { - PLOGE("mkdirs %s", pathname); - } - return ret; + int ret = mkdirs(pathname, mode); + if (ret < 0) { + PLOGE("mkdirs %s", pathname); + } + return ret; } int xmkdirat(int dirfd, const char *pathname, mode_t mode) { - int ret = mkdirat(dirfd, pathname, mode); - if (ret < 0 && errno != EEXIST) { - PLOGE("mkdirat %s %u", pathname, mode); - } - return ret; + int ret = mkdirat(dirfd, pathname, mode); + if (ret < 0 && errno != EEXIST) { + PLOGE("mkdirat %s %u", pathname, mode); + } + return ret; } void *xmmap(void *addr, size_t length, int prot, int flags, - int fd, off_t offset) { - void *ret = mmap(addr, length, prot, flags, fd, offset); - if (ret == MAP_FAILED) { - PLOGE("mmap"); - } - return ret; + int fd, off_t offset) { + void *ret = mmap(addr, length, prot, flags, fd, offset); + if (ret == MAP_FAILED) { + PLOGE("mmap"); + } + return ret; } ssize_t xsendfile(int out_fd, int in_fd, off_t *offset, size_t count) { - ssize_t ret = sendfile(out_fd, in_fd, offset, count); - if (count != ret) { - PLOGE("sendfile"); - } - return ret; + ssize_t ret = sendfile(out_fd, in_fd, offset, count); + if (count != ret) { + PLOGE("sendfile"); + } + return ret; } pid_t xfork() { - int ret = fork(); - if (ret < 0) { - PLOGE("fork"); - } - return ret; + int ret = fork(); + if (ret < 0) { + PLOGE("fork"); + } + return ret; } int xpoll(struct pollfd *fds, nfds_t nfds, int timeout) { - int ret = poll(fds, nfds, timeout); - if (ret < 0) { - PLOGE("poll"); - } - return ret; + int ret = poll(fds, nfds, timeout); + if (ret < 0) { + PLOGE("poll"); + } + return ret; } int xinotify_init1(int flags) { - int ret = inotify_init1(flags); - if (ret < 0) { - PLOGE("inotify_init1"); - } - return ret; + int ret = inotify_init1(flags); + if (ret < 0) { + PLOGE("inotify_init1"); + } + return ret; } char *xrealpath(const char *path, char *resolved_path) { - char buf[PATH_MAX]; - char *ret = realpath(path, buf); - if (ret == nullptr) { - PLOGE("xrealpath"); - } else { - strcpy(resolved_path, buf); - } - return ret; + char buf[PATH_MAX]; + char *ret = realpath(path, buf); + if (ret == nullptr) { + PLOGE("xrealpath"); + } else { + strcpy(resolved_path, buf); + } + return ret; } int xmknod(const char *pathname, mode_t mode, dev_t dev) { - int ret = mknod(pathname, mode, dev); - if (ret < 0) { - PLOGE("mknod"); - } - return ret; + int ret = mknod(pathname, mode, dev); + if (ret < 0) { + PLOGE("mknod"); + } + return ret; } diff --git a/native/jni/utils/xwrap.hpp b/native/jni/utils/xwrap.hpp index d982f0985..f853b0c08 100644 --- a/native/jni/utils/xwrap.hpp +++ b/native/jni/utils/xwrap.hpp @@ -32,7 +32,7 @@ extern "C" void *xrealloc(void *ptr, size_t size); ssize_t xsendmsg(int sockfd, const struct msghdr *msg, int flags); ssize_t xrecvmsg(int sockfd, struct msghdr *msg, int flags); int xpthread_create(pthread_t *thread, const pthread_attr_t *attr, - void *(*start_routine) (void *), void *arg); + void *(*start_routine) (void *), void *arg); int xstat(const char *pathname, struct stat *buf); int xlstat(const char *pathname, struct stat *buf); int xfstat(int fd, struct stat *buf); @@ -45,8 +45,8 @@ int xsymlink(const char *target, const char *linkpath); int xsymlinkat(const char *target, int newdirfd, const char *linkpath); int xlinkat(int olddirfd, const char *oldpath, int newdirfd, const char *newpath, int flags); int xmount(const char *source, const char *target, - const char *filesystemtype, unsigned long mountflags, - const void *data); + const char *filesystemtype, unsigned long mountflags, + const void *data); int xumount(const char *target); int xumount2(const char *target, int flags); int xrename(const char *oldpath, const char *newpath);