init: reset overlay.d files context after sepolicy loaded

This commit is contained in:
5ec1cff 2024-12-02 13:30:14 +08:00 committed by John Wu
parent b6511a510d
commit 2b7be8b949
2 changed files with 59 additions and 0 deletions

View File

@ -1,6 +1,8 @@
#include <sys/mount.h>
#include <libgen.h>
#include <sys/sysmacros.h>
#include <syscall.h>
#include <sys/xattr.h>
#include <sepolicy.hpp>
#include <consts.hpp>
@ -14,6 +16,13 @@ using namespace std;
static vector<string> rc_list;
static string magic_mount_list;
struct FileContext {
std::string path;
std::string con;
};
static std::vector<FileContext> 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");

View File

@ -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.