diff --git a/native/jni/Android.mk b/native/jni/Android.mk index d67b4f281..7430533bf 100644 --- a/native/jni/Android.mk +++ b/native/jni/Android.mk @@ -62,6 +62,7 @@ LOCAL_SRC_FILES := \ init/rootdir.cpp \ init/getinfo.cpp \ init/twostage.cpp \ + init/raw_data.cpp \ core/socket.cpp \ magiskpolicy/sepolicy.cpp \ magiskpolicy/magiskpolicy.cpp \ diff --git a/native/jni/init/getinfo.cpp b/native/jni/init/getinfo.cpp index a9da81a23..a413538ac 100644 --- a/native/jni/init/getinfo.cpp +++ b/native/jni/init/getinfo.cpp @@ -11,7 +11,8 @@ using namespace std; -static void parse_cmdline(const std::function &fn) { +template +static void parse_cmdline(Func fn) { char cmdline[4096]; int fd = xopen("/proc/cmdline", O_RDONLY | O_CLOEXEC); cmdline[read(fd, cmdline, sizeof(cmdline))] = '\0'; @@ -139,7 +140,7 @@ void load_kernel_info(cmdline *cmd) { // Log to kernel setup_klog(); - parse_cmdline([&](auto key, auto value) -> void { + parse_cmdline([=](auto key, auto value) -> void { if (key == "androidboot.slot_suffix") { strcpy(cmd->slot, value); } else if (key == "androidboot.slot") { diff --git a/native/jni/init/init.cpp b/native/jni/init/init.cpp index 1d7a8dbeb..b5cdf6bea 100644 --- a/native/jni/init/init.cpp +++ b/native/jni/init/init.cpp @@ -20,64 +20,12 @@ using namespace std; +// Debug toggle +#define ENABLE_TEST 0 + constexpr int (*init_applet_main[])(int, char *[]) = { magiskpolicy_main, magiskpolicy_main, nullptr }; -int data_holder::patch(str_pairs list) { - 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) { - for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) { - if (memcmp(p, pattern.data(), pattern.length() + 1) == 0) - return true; - } - return false; -} - -void data_holder::consume(data_holder &other) { - 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 raw_data::read(const char *name) { - 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 raw_data::mmap_ro(const char *name) { - auto_data data; - ::mmap_ro(name, data.buf, data.sz); - return data; -} - static bool unxz(int fd, const uint8_t *buf, size_t size) { uint8_t out[8192]; xz_crc32_init(); @@ -123,7 +71,7 @@ static int dump_manager(const char *path, mode_t mode) { class RecoveryInit : public BaseInit { public: - RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; + RecoveryInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {} void start() override { LOGD("Ramdisk is recovery, abort\n"); rename("/.backup/init", "/init"); @@ -132,6 +80,7 @@ public: } }; +#if ENABLE_TEST class TestInit : public BaseInit { public: TestInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}; @@ -140,7 +89,7 @@ public: } }; -[[maybe_unused]] static int test_main(int argc, char *argv[]) { +static int test_main(int argc, char *argv[]) { // Log to console cmdline_logging(); log_cb.ex = nop_ex; @@ -172,6 +121,14 @@ public: 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; +} int main(int argc, char *argv[]) { umask(0); @@ -184,7 +141,7 @@ int main(int argc, char *argv[]) { return (*init_applet_main[i])(argc, argv); } -#if 0 +#if ENABLE_TEST if (getenv("INIT_TEST") != nullptr) return test_main(argc, argv); #endif diff --git a/native/jni/init/init.hpp b/native/jni/init/init.hpp index 23eca9c9b..8459f2702 100644 --- a/native/jni/init/init.hpp +++ b/native/jni/init/init.hpp @@ -7,6 +7,8 @@ #include +#include "raw_data.hpp" + struct cmdline { bool skip_initramfs; bool force_normal_boot; @@ -17,35 +19,6 @@ struct cmdline { char hardware_plat[32]; }; -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); -protected: - 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; } -}; -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); -} - struct fstab_entry { std::string dev; std::string mnt_point; @@ -55,7 +28,7 @@ struct fstab_entry { fstab_entry() = default; fstab_entry(const fstab_entry &) = delete; - fstab_entry(fstab_entry &&o) = default; + fstab_entry(fstab_entry &&) = default; void to_file(FILE *fp); }; @@ -65,9 +38,7 @@ struct fstab_entry { void load_kernel_info(cmdline *cmd); bool check_two_stage(); int dump_magisk(const char *path, mode_t mode); -int magisk_proxy_main(int argc, char *argv[]); void setup_klog(); -void setup_tmp(const char *path, const data_holder &self, const data_holder &config); /*************** * Base classes @@ -85,31 +56,32 @@ protected: exit(1); } virtual void cleanup(); + 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; - void read_dt_fstab(std::vector &fstab); - void dt_early_mount(); }; class MagiskInit : public BaseInit { protected: auto_data self; + auto_data config; std::string persist_dir; - virtual void early_mount() = 0; + void mount_with_dt(); bool patch_sepolicy(const char *file); + void setup_tmp(const char *path); public: MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {} }; class SARBase : public MagiskInit { protected: - auto_data config; std::vector overlays; + virtual void early_mount() = 0; void backup_files(); void patch_rootdir(); void mount_system_root(); @@ -129,7 +101,6 @@ public: class FirstStageInit : public BaseInit { private: void prepare(); - public: FirstStageInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) { LOGD("%s\n", __FUNCTION__); @@ -140,22 +111,6 @@ public: } }; -class SARFirstStageInit : public SARBase { -private: - void prepare(); -protected: - void early_mount() override; -public: - SARFirstStageInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd) { - LOGD("%s\n", __FUNCTION__); - }; - void start() override { - early_mount(); - prepare(); - exec_init(); - } -}; - class SecondStageInit : public SARBase { protected: void early_mount() override; @@ -179,6 +134,24 @@ public: }; }; +// Special case for legacy SAR on Android 10+ +// Should be followed by normal 2SI SecondStageInit +class SARFirstStageInit : public SARBase { +private: + void prepare(); +protected: + void early_mount() override; +public: + SARFirstStageInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd) { + LOGD("%s\n", __FUNCTION__); + }; + void start() override { + early_mount(); + prepare(); + exec_init(); + } +}; + /************ * Initramfs ************/ @@ -186,8 +159,7 @@ public: class RootFSInit : public MagiskInit { private: void setup_rootfs(); -protected: - void early_mount() override; + void early_mount(); public: RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) { LOGD("%s\n", __FUNCTION__); @@ -199,3 +171,11 @@ public: exec_init(); } }; + +class MagiskProxy : public MagiskInit { +public: + 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 bf39ec6c4..3d6fd9a94 100644 --- a/native/jni/init/mount.cpp +++ b/native/jni/init/mount.cpp @@ -151,7 +151,7 @@ void BaseInit::read_dt_fstab(vector &fstab) { } } -void BaseInit::dt_early_mount() { +void MagiskInit::mount_with_dt() { vector fstab; read_dt_fstab(fstab); for (const auto &entry : fstab) { @@ -224,7 +224,7 @@ void RootFSInit::early_mount() { LOGD("Restoring /init\n"); rename("/.backup/init", "/init"); - dt_early_mount(); + mount_with_dt(); xmkdir("/dev/mnt", 0755); mount_persist("/dev/block", "/dev/mnt"); @@ -272,7 +272,7 @@ void SARInit::early_mount() { mount_system_root(); switch_root("/system_root"); - dt_early_mount(); + mount_with_dt(); } void SARFirstStageInit::early_mount() { @@ -308,7 +308,7 @@ static void patch_socket_name(const char *path) { bin.patch({ make_pair(MAIN_SOCKET, rstr) }); } -void setup_tmp(const char *path, const data_holder &self, const data_holder &config) { +void MagiskInit::setup_tmp(const char *path) { LOGD("Setup Magisk tmp at %s\n", path); xmount("tmpfs", path, "tmpfs", 0, "mode=755"); diff --git a/native/jni/init/raw_data.cpp b/native/jni/init/raw_data.cpp new file mode 100644 index 000000000..7f1d9bcc6 --- /dev/null +++ b/native/jni/init/raw_data.cpp @@ -0,0 +1,58 @@ +#include "raw_data.hpp" + +using namespace std; + +int data_holder::patch(str_pairs list) { + 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) { + for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) { + if (memcmp(p, pattern.data(), pattern.length() + 1) == 0) + return true; + } + return false; +} + +void data_holder::consume(data_holder &other) { + 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 raw_data::read(const char *name) { + 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 raw_data::mmap_ro(const char *name) { + 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 new file mode 100644 index 000000000..5fa63d74c --- /dev/null +++ b/native/jni/init/raw_data.hpp @@ -0,0 +1,32 @@ +#pragma once + +#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); +protected: + 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; } +}; +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); +} diff --git a/native/jni/init/rootdir.cpp b/native/jni/init/rootdir.cpp index d5edc681a..a7c5172d1 100644 --- a/native/jni/init/rootdir.cpp +++ b/native/jni/init/rootdir.cpp @@ -228,7 +228,7 @@ void SARBase::patch_rootdir() { sepol = "/dev/.se"; } - setup_tmp(tmp_dir, self, config); + setup_tmp(tmp_dir); persist_dir = MIRRDIR "/persist/magisk"; chdir(tmp_dir); @@ -317,24 +317,20 @@ void SARBase::patch_rootdir() { chdir("/"); } -int magisk_proxy_main(int argc, char *argv[]) { - setup_klog(); - - auto self = raw_data::read("/sbin/magisk"); - auto config = raw_data::read("/.backup/.magisk"); +void MagiskProxy::start() { + self = raw_data::read("/sbin/magisk"); + config = raw_data::read("/.backup/.magisk"); xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr); unlink("/sbin/magisk"); rm_rf("/.backup"); - setup_tmp("/sbin", self, config); + setup_tmp("/sbin"); // Create symlinks pointing back to /root recreate_sbin("/root", false); setenv("REMOUNT_ROOT", "1", 1); execv("/sbin/magisk", argv); - - return 1; }