From f2cb3c38fea6b66bbe6d836a44b290f38ddfc573 Mon Sep 17 00:00:00 2001 From: topjohnwu Date: Tue, 12 Jan 2021 22:50:55 -0800 Subject: [PATCH] Update mmap implementation Always map memory as writable, but private when read-only --- native/jni/init/getinfo.cpp | 2 +- native/jni/init/init.hpp | 4 ++-- native/jni/init/mount.cpp | 10 +++++----- native/jni/init/raw_data.cpp | 30 +++++++++--------------------- native/jni/init/raw_data.hpp | 34 +++++++++++++--------------------- native/jni/init/rootdir.cpp | 10 +++++----- native/jni/init/twostage.cpp | 4 ++-- native/jni/utils/files.cpp | 18 ++++++++++++++++-- native/jni/utils/files.hpp | 19 +++++-------------- 9 files changed, 58 insertions(+), 73 deletions(-) diff --git a/native/jni/init/getinfo.cpp b/native/jni/init/getinfo.cpp index 58524e82a..52d492736 100644 --- a/native/jni/init/getinfo.cpp +++ b/native/jni/init/getinfo.cpp @@ -213,6 +213,6 @@ bool check_two_stage() { 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"); + auto init = mmap_data::ro("/.backup/init"); return init.contains("selinux_setup"); } diff --git a/native/jni/init/init.hpp b/native/jni/init/init.hpp index 0642a5fd5..b1cbcb722 100644 --- a/native/jni/init/init.hpp +++ b/native/jni/init/init.hpp @@ -54,8 +54,8 @@ public: class MagiskInit : public BaseInit { protected: - auto_data self; - auto_data config; + mmap_data self; + mmap_data config; std::string custom_rules_dir; void mount_with_dt(); diff --git a/native/jni/init/mount.cpp b/native/jni/init/mount.cpp index a32da3754..e9f33c079 100644 --- a/native/jni/init/mount.cpp +++ b/native/jni/init/mount.cpp @@ -289,7 +289,7 @@ success: } void RootFSInit::early_mount() { - self = raw_data::read("/init"); + self = mmap_data::ro("/init"); LOGD("Restoring /init\n"); rename("/.backup/init", "/init"); @@ -301,9 +301,9 @@ void SARBase::backup_files() { if (access("/overlay.d", F_OK) == 0) backup_folder("/overlay.d", overlays); - self = raw_data::read("/proc/self/exe"); + self = mmap_data::ro("/proc/self/exe"); if (access("/.backup/.magisk", R_OK) == 0) - config = raw_data::read("/.backup/.magisk"); + config = mmap_data::ro("/.backup/.magisk"); } void SARBase::mount_system_root() { @@ -346,7 +346,7 @@ void SARInit::early_mount() { switch_root("/system_root"); { - auto init = raw_data::mmap_ro("/init"); + auto init = mmap_data::ro("/init"); is_two_stage = init.contains("selinux_setup"); } LOGD("is_two_stage: [%d]\n", is_two_stage); @@ -383,7 +383,7 @@ void BaseInit::exec_init() { static void patch_socket_name(const char *path) { char rstr[16]; gen_rand_str(rstr, sizeof(rstr)); - auto bin = raw_data::mmap_rw(path); + auto bin = mmap_data::rw(path); bin.patch({ make_pair(MAIN_SOCKET, rstr) }); } diff --git a/native/jni/init/raw_data.cpp b/native/jni/init/raw_data.cpp index 1164e1e18..3fa1027ee 100644 --- a/native/jni/init/raw_data.cpp +++ b/native/jni/init/raw_data.cpp @@ -2,7 +2,7 @@ using namespace std; -int data_holder::patch(str_pairs list) { +int mmap_data::patch(str_pairs list) { if (buf == nullptr) return 0; int count = 0; @@ -20,7 +20,7 @@ int data_holder::patch(str_pairs list) { return count; } -bool data_holder::contains(string_view pattern) { +bool mmap_data::contains(string_view pattern) { if (buf == nullptr) return false; for (uint8_t *p = buf, *eof = buf + sz; p < eof; ++p) { @@ -32,33 +32,21 @@ bool data_holder::contains(string_view pattern) { return false; } -void data_holder::consume(data_holder &other) { +void mmap_data::consume(mmap_data &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); +mmap_data mmap_data::rw(const char *name) { + mmap_data data; + mmap_rw(name, 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); +mmap_data mmap_data::ro(const char *name) { + mmap_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 049e05094..6732ea826 100644 --- a/native/jni/init/raw_data.hpp +++ b/native/jni/init/raw_data.hpp @@ -2,31 +2,23 @@ #include -struct data_holder { +struct mmap_data { uint8_t *buf = nullptr; size_t sz = 0; + + mmap_data() = default; + mmap_data(const mmap_data&) = delete; + mmap_data(mmap_data &&other) { consume(other); } + ~mmap_data() { if (buf) munmap(buf, sz); } + mmap_data& operator=(mmap_data &&other) { consume(other); return *this; } + 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); } + static mmap_data rw(const char *name); + static mmap_data ro(const char *name); -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); -} +private: + void consume(mmap_data &other); +}; diff --git a/native/jni/init/rootdir.cpp b/native/jni/init/rootdir.cpp index 807babb8c..a65771a6d 100644 --- a/native/jni/init/rootdir.cpp +++ b/native/jni/init/rootdir.cpp @@ -218,7 +218,7 @@ void SARBase::patch_rootdir() { int patch_count; { int src = xopen("/init", O_RDONLY | O_CLOEXEC); - auto init = raw_data::read(src); + auto init = mmap_data::ro("/init"); patch_count = init.patch({ make_pair(SPLIT_PLAT_CIL, "xxx"), /* Force loading monolithic sepolicy */ make_pair(MONOPOLICY, sepol) /* Redirect /sepolicy to custom path */ @@ -233,7 +233,7 @@ void SARBase::patch_rootdir() { if (patch_count != 2 && access(LIBSELINUX, F_OK) == 0) { // init is dynamically linked, need to patch libselinux - auto lib = raw_data::read(LIBSELINUX); + auto lib = mmap_data::ro(LIBSELINUX); lib.patch({make_pair(MONOPOLICY, sepol)}); xmkdirs(dirname(ROOTOVL LIBSELINUX), 0755); int dest = xopen(ROOTOVL LIBSELINUX, O_CREAT | O_WRONLY | O_CLOEXEC, 0); @@ -301,7 +301,7 @@ void RootFSInit::patch_rootfs() { } if (patch_sepolicy("/sepolicy")) { - auto init = raw_data::mmap_rw("/init"); + auto init = mmap_data::rw("/init"); init.patch({ make_pair(SPLIT_PLAT_CIL, "xxx") }); } @@ -331,8 +331,8 @@ void MagiskProxy::start() { xmount(nullptr, "/", nullptr, MS_REMOUNT, nullptr); // Backup stuffs before removing them - self = raw_data::read("/sbin/magisk"); - config = raw_data::read("/.backup/.magisk"); + self = mmap_data::ro("/sbin/magisk"); + config = mmap_data::ro("/.backup/.magisk"); char custom_rules_dir[64]; custom_rules_dir[0] = '\0'; xreadlink(TMP_RULESDIR, custom_rules_dir, sizeof(custom_rules_dir)); diff --git a/native/jni/init/twostage.cpp b/native/jni/init/twostage.cpp index 2d6f505c0..25265c0ca 100644 --- a/native/jni/init/twostage.cpp +++ b/native/jni/init/twostage.cpp @@ -114,7 +114,7 @@ void FirstStageInit::prepare() { } // Patch init to force IsDtFstabCompatible() return false - auto init = raw_data::mmap_rw("/init"); + auto init = mmap_data::rw("/init"); init.patch({ make_pair("android,fstab", "xxx") }); } @@ -150,7 +150,7 @@ void SARInit::first_stage_prep() { int src = xopen("/init", O_RDONLY); int dest = xopen("/dev/init", O_CREAT | O_WRONLY, 0); { - auto init = raw_data::read(src); + auto init = mmap_data::ro("/init"); init.patch({ make_pair(INIT_PATH, REDIR_PATH) }); write(dest, init.buf, init.sz); fclone_attr(src, dest); diff --git a/native/jni/utils/files.cpp b/native/jni/utils/files.cpp index ff98df7fa..f4657c876 100644 --- a/native/jni/utils/files.cpp +++ b/native/jni/utils/files.cpp @@ -279,7 +279,6 @@ void *__mmap(const char *filename, size_t *size, bool rw) { return nullptr; } struct stat st; - void *buf; if (fstat(fd, &st)) { *size = 0; return nullptr; @@ -288,7 +287,9 @@ void *__mmap(const char *filename, size_t *size, bool rw) { 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; + void *buf = *size > 0 ? + xmmap(nullptr, *size, PROT_READ | PROT_WRITE, rw ? MAP_SHARED : MAP_PRIVATE, fd, 0) : + nullptr; close(fd); return buf; } @@ -437,3 +438,16 @@ sDIR make_dir(DIR *dp) { sFILE make_file(FILE *fp) { return sFILE(fp, [](FILE *fp){ return fp ? fclose(fp) : 1; }); } + +raw_file::raw_file(raw_file &&o) { + path.swap(o.path); + attr = o.attr; + buf = o.buf; + sz = o.sz; + o.buf = nullptr; + o.sz = 0; +} + +raw_file::~raw_file() { + free(buf); +} diff --git a/native/jni/utils/files.hpp b/native/jni/utils/files.hpp index 465f176b4..e5e38f898 100644 --- a/native/jni/utils/files.hpp +++ b/native/jni/utils/files.hpp @@ -21,22 +21,13 @@ struct file_attr { struct raw_file { std::string path; file_attr attr; - uint8_t *buf = nullptr; - size_t sz = 0; + uint8_t *buf; + size_t sz; - raw_file() = default; + raw_file() : attr({}), buf(nullptr), sz(0) {} 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(raw_file &&o); + ~raw_file(); }; ssize_t fd_path(int fd, char *path, size_t size);