From 2b7be8b9492793c5b1835f60ca0aa70f8ac6c2fc Mon Sep 17 00:00:00 2001 From: 5ec1cff Date: Mon, 2 Dec 2024 13:30:14 +0800 Subject: [PATCH] init: reset overlay.d files context after sepolicy loaded --- native/src/init/rootdir.cpp | 55 +++++++++++++++++++++++++++++++++++++ native/src/init/selinux.cpp | 4 +++ 2 files changed, 59 insertions(+) diff --git a/native/src/init/rootdir.cpp b/native/src/init/rootdir.cpp index a640de3d3..fa2972812 100644 --- a/native/src/init/rootdir.cpp +++ b/native/src/init/rootdir.cpp @@ -1,6 +1,8 @@ #include #include #include +#include +#include #include #include @@ -14,6 +16,13 @@ using namespace std; static vector rc_list; static string magic_mount_list; +struct FileContext { + std::string path; + std::string con; +}; + +static std::vector mount_contexts; + #define NEW_INITRC_DIR "/system/etc/init/hw" #define INIT_RC "init.rc" @@ -29,6 +38,10 @@ static void magic_mount(const string &sdir, const string &ddir = "") { magic_mount(src, dest); } else { LOGD("Mount [%s] -> [%s]\n", src.data(), dest.data()); + struct stat st; + xstat(dest.data(), &st); + chmod(src.data(), st.st_mode & 0777); + chown(src.data(), st.st_uid, st.st_gid); xmount(src.data(), dest.data(), nullptr, MS_BIND, nullptr); magic_mount_list += dest; magic_mount_list += '\n'; @@ -37,6 +50,46 @@ static void magic_mount(const string &sdir, const string &ddir = "") { } } +static int setfilecon(const char* path, const char* con) { + int ret = syscall(__NR_setxattr, path, XATTR_NAME_SELINUX, con, strlen(con) + 1, 0); + if (ret == -1) PLOGE("setfilecon %s %s", path, con); + return ret; +} + +static std::string getfilecon(const char* path) { + char buf[1024]; + ssize_t sz = syscall(__NR_getxattr, path, XATTR_NAME_SELINUX, buf, sizeof(buf)); + if (sz == -1) { + PLOGE("getfilecon %s", path); + return ""; + } + return buf; +} + +static void collect_overlay_contexts(const string &sdir, const string &ddir = "") { + auto dir = xopen_dir(sdir.data()); + if (!dir) return; + 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 + collect_overlay_contexts(src, dest); + } else { + mount_contexts.emplace_back(dest, getfilecon(dest.data())); + } + } + } +} + +void reset_overlay_contexts() { + for (auto &attr: mount_contexts) { + LOGD("set %s -> %s", attr.path.c_str(), attr.con.c_str()); + setfilecon(attr.path.c_str(), attr.con.c_str()); + } +} + static void patch_rc_scripts(const char *src_path, const char *tmp_path, bool writable) { auto src_dir = xopen_dir(src_path); if (!src_dir) return; @@ -327,6 +380,8 @@ void MagiskInit::patch_ro_root() { // Extract overlay archives extract_files(false); + collect_overlay_contexts(ROOTOVL); + // Oculus Go will use a special sepolicy if unlocked if (access("/sepolicy.unlocked", F_OK) == 0) { patch_sepolicy("/sepolicy.unlocked", ROOTOVL "/sepolicy.unlocked"); diff --git a/native/src/init/selinux.cpp b/native/src/init/selinux.cpp index 5b0088d22..347475bd0 100644 --- a/native/src/init/selinux.cpp +++ b/native/src/init/selinux.cpp @@ -131,6 +131,10 @@ bool MagiskInit::hijack_sepolicy() { // Load patched policy into kernel sepol->to_file(SELINUX_LOAD); + // restore mounted files' context after sepolicy loaded + void reset_overlay_contexts(); + reset_overlay_contexts(); + // Write to the enforce node ONLY after sepolicy is loaded. We need to make sure // the actual init process is blocked until sepolicy is loaded, or else // restorecon will fail and re-exec won't change context, causing boot failure.