|
|
|
@@ -6,6 +6,7 @@
|
|
|
|
|
#include <fcntl.h>
|
|
|
|
|
#include <string.h>
|
|
|
|
|
#include <dirent.h>
|
|
|
|
|
#include <libgen.h>
|
|
|
|
|
#include <vector>
|
|
|
|
|
#include <string>
|
|
|
|
|
|
|
|
|
@@ -19,7 +20,6 @@
|
|
|
|
|
|
|
|
|
|
using namespace std;
|
|
|
|
|
|
|
|
|
|
static char buf[PATH_MAX], buf2[PATH_MAX];
|
|
|
|
|
static vector<string> module_list;
|
|
|
|
|
static bool no_secure_dir = false;
|
|
|
|
|
static bool pfs_done = false;
|
|
|
|
@@ -74,7 +74,6 @@ private:
|
|
|
|
|
string get_path();
|
|
|
|
|
void insert(node_entry *&);
|
|
|
|
|
void clone_skeleton();
|
|
|
|
|
int get_path(char *path);
|
|
|
|
|
};
|
|
|
|
|
|
|
|
|
|
bool node_entry::vendor_root = false;
|
|
|
|
@@ -97,16 +96,12 @@ bool node_entry::is_root() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
string node_entry::get_path() {
|
|
|
|
|
get_path(buf);
|
|
|
|
|
return buf;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
int node_entry::get_path(char *path) {
|
|
|
|
|
int len = 0;
|
|
|
|
|
string path;
|
|
|
|
|
if (parent)
|
|
|
|
|
len = parent->get_path(path);
|
|
|
|
|
len += sprintf(path + len, "/%s", name.c_str());
|
|
|
|
|
return len;
|
|
|
|
|
path = parent->get_path();
|
|
|
|
|
path += "/";
|
|
|
|
|
path += name;
|
|
|
|
|
return path;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
void node_entry::insert(node_entry *&node) {
|
|
|
|
@@ -129,9 +124,9 @@ void node_entry::insert(node_entry *&node) {
|
|
|
|
|
|
|
|
|
|
void node_entry::create_module_tree(const char *module) {
|
|
|
|
|
auto full_path = get_path();
|
|
|
|
|
snprintf(buf, PATH_MAX, "%s/%s%s", MODULEROOT, module, full_path.c_str());
|
|
|
|
|
auto cwd = MODULEROOT + "/"s + module + full_path;
|
|
|
|
|
|
|
|
|
|
auto dir = xopen_dir(buf);
|
|
|
|
|
auto dir = xopen_dir(cwd.data());
|
|
|
|
|
if (!dir)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
@@ -139,7 +134,7 @@ void node_entry::create_module_tree(const char *module) {
|
|
|
|
|
if (faccessat(dirfd(dir.get()), ".replace", F_OK, 0) == 0) {
|
|
|
|
|
if (is_root()) {
|
|
|
|
|
// Root nodes should not be replaced
|
|
|
|
|
rm_rf(buf);
|
|
|
|
|
rm_rf(cwd.data());
|
|
|
|
|
} else if (status < IS_MODULE) {
|
|
|
|
|
// Upgrade current node to current module
|
|
|
|
|
this->module = module;
|
|
|
|
@@ -154,9 +149,8 @@ void node_entry::create_module_tree(const char *module) {
|
|
|
|
|
// Create new node
|
|
|
|
|
auto node = new node_entry(this, module, entry->d_name, entry->d_type);
|
|
|
|
|
|
|
|
|
|
// buf = real path, buf2 = module path
|
|
|
|
|
snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), entry->d_name);
|
|
|
|
|
snprintf(buf2, PATH_MAX, MODULEROOT "/%s%s/%s", module, full_path.c_str(), entry->d_name);
|
|
|
|
|
auto dest = full_path + "/" + entry->d_name;
|
|
|
|
|
auto src = cwd + "/" + entry->d_name;
|
|
|
|
|
|
|
|
|
|
/*
|
|
|
|
|
* Clone current directory in one of the following conditions:
|
|
|
|
@@ -165,17 +159,17 @@ void node_entry::create_module_tree(const char *module) {
|
|
|
|
|
* - Target file is a symlink (exclude special nodes)
|
|
|
|
|
*/
|
|
|
|
|
bool clone = false;
|
|
|
|
|
if (IS_LNK(node) || access(buf, F_OK) != 0) {
|
|
|
|
|
if (IS_LNK(node) || access(dest.data(), F_OK) != 0) {
|
|
|
|
|
clone = true;
|
|
|
|
|
} else if (!node->is_special()) {
|
|
|
|
|
struct stat s;
|
|
|
|
|
xlstat(buf, &s);
|
|
|
|
|
xlstat(dest.data(), &s);
|
|
|
|
|
if (S_ISLNK(s.st_mode))
|
|
|
|
|
clone = true;
|
|
|
|
|
}
|
|
|
|
|
if (clone && is_root()) {
|
|
|
|
|
// Root nodes should not be cloned
|
|
|
|
|
rm_rf(buf2);
|
|
|
|
|
rm_rf(src.data());
|
|
|
|
|
delete node;
|
|
|
|
|
continue;
|
|
|
|
|
}
|
|
|
|
@@ -189,7 +183,7 @@ void node_entry::create_module_tree(const char *module) {
|
|
|
|
|
node->status = IS_INTER;
|
|
|
|
|
} else {
|
|
|
|
|
// Clone attributes from real path
|
|
|
|
|
clone_attr(buf, buf2);
|
|
|
|
|
clone_attr(dest.data(), src.data());
|
|
|
|
|
if (IS_DIR(node)) {
|
|
|
|
|
// First mark as an intermediate node
|
|
|
|
|
node->status = IS_INTER;
|
|
|
|
@@ -209,8 +203,9 @@ void node_entry::create_module_tree(const char *module) {
|
|
|
|
|
void node_entry::clone_skeleton() {
|
|
|
|
|
// Clone the structure
|
|
|
|
|
auto full_path = get_path();
|
|
|
|
|
snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.data());
|
|
|
|
|
if (auto dir = xopen_dir(buf); dir) {
|
|
|
|
|
auto mirror_path = MAGISKTMP + "/" MIRRDIR + full_path;
|
|
|
|
|
|
|
|
|
|
if (auto dir = xopen_dir(mirror_path.data()); dir) {
|
|
|
|
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
|
|
|
|
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
|
|
|
|
continue;
|
|
|
|
@@ -222,42 +217,41 @@ void node_entry::clone_skeleton() {
|
|
|
|
|
|
|
|
|
|
if (status & IS_SKEL) {
|
|
|
|
|
file_attr attr;
|
|
|
|
|
getattr(full_path.c_str(), &attr);
|
|
|
|
|
LOGI("mnt_tmpfs : %s\n", full_path.c_str());
|
|
|
|
|
xmount("tmpfs", full_path.c_str(), "tmpfs", 0, nullptr);
|
|
|
|
|
setattr(full_path.c_str(), &attr);
|
|
|
|
|
getattr(full_path.data(), &attr);
|
|
|
|
|
LOGI("mnt_tmpfs : %s\n", full_path.data());
|
|
|
|
|
xmount("tmpfs", full_path.data(), "tmpfs", 0, nullptr);
|
|
|
|
|
setattr(full_path.data(), &attr);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
for (auto &child : children) {
|
|
|
|
|
snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), child->name.c_str());
|
|
|
|
|
auto dest = full_path + "/" + child->name;
|
|
|
|
|
string src;
|
|
|
|
|
|
|
|
|
|
// Create the dummy file/directory
|
|
|
|
|
if (IS_DIR(child))
|
|
|
|
|
xmkdir(buf, 0755);
|
|
|
|
|
xmkdir(dest.data(), 0755);
|
|
|
|
|
else if (IS_REG(child))
|
|
|
|
|
close(creat(buf, 0644));
|
|
|
|
|
close(creat(dest.data(), 0644));
|
|
|
|
|
// Links will be handled later
|
|
|
|
|
|
|
|
|
|
if (child->status & IS_MODULE) {
|
|
|
|
|
// Mount from module file to dummy file
|
|
|
|
|
snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MODULEMNT,
|
|
|
|
|
child->module, full_path.c_str(), child->name.c_str());
|
|
|
|
|
src = MAGISKTMP + "/" MODULEMNT "/" + child->module + full_path + "/" + child->name;
|
|
|
|
|
} else if (child->status & (IS_SKEL | IS_INTER)) {
|
|
|
|
|
// It's an intermediate folder, recursive clone
|
|
|
|
|
child->clone_skeleton();
|
|
|
|
|
continue;
|
|
|
|
|
} else if (child->status & IS_DUMMY) {
|
|
|
|
|
// Mount from mirror to dummy file
|
|
|
|
|
snprintf(buf2, PATH_MAX, "%s%s/%s", MIRRDIR, full_path.c_str(), child->name.c_str());
|
|
|
|
|
src = MAGISKTMP + "/" MIRRDIR + full_path + "/" + child->name;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (IS_LNK(child)) {
|
|
|
|
|
// Copy symlinks directly
|
|
|
|
|
cp_afc(buf2, buf);
|
|
|
|
|
VLOGI("copy_link ", buf2, buf);
|
|
|
|
|
cp_afc(src.data(), dest.data());
|
|
|
|
|
VLOGI("copy_link ", src.data(), dest.data());
|
|
|
|
|
} else {
|
|
|
|
|
snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), child->name.c_str());
|
|
|
|
|
bind_mount(buf2, buf);
|
|
|
|
|
bind_mount(src.data(), dest.data());
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
@@ -265,9 +259,9 @@ void node_entry::clone_skeleton() {
|
|
|
|
|
void node_entry::magic_mount() {
|
|
|
|
|
if (status & IS_MODULE) {
|
|
|
|
|
// Mount module item
|
|
|
|
|
auto real_path = get_path();
|
|
|
|
|
snprintf(buf, PATH_MAX, "%s/%s%s", MODULEMNT, module, real_path.c_str());
|
|
|
|
|
bind_mount(buf, real_path.c_str());
|
|
|
|
|
auto dest = get_path();
|
|
|
|
|
auto src = MAGISKTMP + "/" MODULEMNT "/" + module + dest;
|
|
|
|
|
bind_mount(src.data(), dest.data());
|
|
|
|
|
} else if (status & IS_SKEL) {
|
|
|
|
|
// The node is labeled to be cloned with skeleton, lets do it
|
|
|
|
|
clone_skeleton();
|
|
|
|
@@ -302,16 +296,19 @@ static int bind_mount(const char *from, const char *to, bool log) {
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#define MIRRMNT(part) MIRRDIR "/" #part
|
|
|
|
|
#define PARTBLK(part) BLOCKDIR "/" #part
|
|
|
|
|
#define DIR_IS(part) (me->mnt_dir == "/" #part ""sv)
|
|
|
|
|
|
|
|
|
|
#define DIR_IS(part) (me->mnt_dir == "/" #part ""sv)
|
|
|
|
|
#define SETMIR(b, part) sprintf(b, "%s/" MIRRDIR "/" #part, MAGISKTMP.data())
|
|
|
|
|
#define SETBLK(b, part) sprintf(b, "%s/" BLOCKDIR "/" #part, MAGISKTMP.data())
|
|
|
|
|
|
|
|
|
|
#define mount_mirror(part, flag) { \
|
|
|
|
|
xstat(me->mnt_fsname, &st); \
|
|
|
|
|
mknod(PARTBLK(part), (st.st_mode & S_IFMT) | 0600, st.st_rdev); \
|
|
|
|
|
xmkdir(MIRRMNT(part), 0755); \
|
|
|
|
|
xmount(PARTBLK(part), MIRRMNT(part), me->mnt_type, flag, nullptr); \
|
|
|
|
|
VLOGI("mount", PARTBLK(part), MIRRMNT(part)); \
|
|
|
|
|
SETMIR(buf1, part); \
|
|
|
|
|
SETBLK(buf2, part); \
|
|
|
|
|
mknod(buf2, (st.st_mode & S_IFMT) | 0600, st.st_rdev); \
|
|
|
|
|
xmkdir(buf1, 0755); \
|
|
|
|
|
xmount(buf2, buf1, me->mnt_type, flag, nullptr); \
|
|
|
|
|
VLOGI("mount", buf2, buf1); \
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool magisk_env() {
|
|
|
|
@@ -320,11 +317,13 @@ static bool magisk_env() {
|
|
|
|
|
string pkg;
|
|
|
|
|
check_manager(&pkg);
|
|
|
|
|
|
|
|
|
|
char install_dir[128];
|
|
|
|
|
sprintf(install_dir, "%s/0/%s/install", APP_DATA_DIR, pkg.data());
|
|
|
|
|
char buf1[4096];
|
|
|
|
|
char buf2[4096];
|
|
|
|
|
|
|
|
|
|
sprintf(buf1, "%s/0/%s/install", APP_DATA_DIR, pkg.data());
|
|
|
|
|
|
|
|
|
|
// Alternative binaries paths
|
|
|
|
|
const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", install_dir };
|
|
|
|
|
const char *alt_bin[] = { "/cache/data_adb/magisk", "/data/magisk", buf1 };
|
|
|
|
|
for (auto alt : alt_bin) {
|
|
|
|
|
struct stat st;
|
|
|
|
|
if (lstat(alt, &st) != -1) {
|
|
|
|
@@ -348,14 +347,11 @@ static bool magisk_env() {
|
|
|
|
|
unlink("/data/magisk_merge.img");
|
|
|
|
|
unlink("/data/magisk_debug.log");
|
|
|
|
|
|
|
|
|
|
// Directories in tmpfs overlay
|
|
|
|
|
xmkdir(MIRRDIR, 0);
|
|
|
|
|
xmkdir(BLOCKDIR, 0);
|
|
|
|
|
xmkdir(BBPATH, 0755);
|
|
|
|
|
xmkdir(MODULEMNT, 0755);
|
|
|
|
|
|
|
|
|
|
// Backwards compatibility for old Magisk Manager
|
|
|
|
|
xsymlink("./modules", MAGISKTMP "/img");
|
|
|
|
|
sprintf(buf1, "%s/" MODULEMNT, MAGISKTMP.data());
|
|
|
|
|
xmkdir(buf1, 0755);
|
|
|
|
|
// TODO: Remove. Backwards compatibility for old manager
|
|
|
|
|
sprintf(buf1, "%s/" INTLROOT "/img", MAGISKTMP.data());
|
|
|
|
|
xsymlink("./modules", buf1);
|
|
|
|
|
|
|
|
|
|
// Directories in /data/adb
|
|
|
|
|
xmkdir(DATABIN, 0755);
|
|
|
|
@@ -369,8 +365,9 @@ static bool magisk_env() {
|
|
|
|
|
parse_mnt("/proc/mounts", [&](mntent *me) {
|
|
|
|
|
if (DIR_IS(system_root)) {
|
|
|
|
|
mount_mirror(system_root, MS_RDONLY);
|
|
|
|
|
xsymlink("./system_root/system", MIRRMNT(system));
|
|
|
|
|
VLOGI("link", MIRRMNT(system_root) "/system", MIRRMNT(system));
|
|
|
|
|
SETMIR(buf1, system);
|
|
|
|
|
xsymlink("./system_root/system", buf1);
|
|
|
|
|
VLOGI("link", "./system_root/system", buf1);
|
|
|
|
|
system_as_root = true;
|
|
|
|
|
} else if (!system_as_root && DIR_IS(system)) {
|
|
|
|
|
mount_mirror(system, MS_RDONLY);
|
|
|
|
@@ -385,18 +382,22 @@ static bool magisk_env() {
|
|
|
|
|
}
|
|
|
|
|
return true;
|
|
|
|
|
});
|
|
|
|
|
if (access(MIRRMNT(system), F_OK) != 0 && access(MIRRMNT(system_root), F_OK) == 0) {
|
|
|
|
|
SETMIR(buf1, system);
|
|
|
|
|
SETMIR(buf2, system_root);
|
|
|
|
|
if (access(buf1, F_OK) != 0 && access(buf2, F_OK) == 0) {
|
|
|
|
|
// Pre-init mirrors
|
|
|
|
|
xsymlink("./system_root/system", MIRRMNT(system));
|
|
|
|
|
VLOGI("link", MIRRMNT(system_root) "/system", MIRRMNT(system));
|
|
|
|
|
xsymlink("./system_root/system", buf1);
|
|
|
|
|
VLOGI("link", "./system_root/system", buf1);
|
|
|
|
|
}
|
|
|
|
|
if (access(MIRRMNT(vendor), F_OK) != 0) {
|
|
|
|
|
xsymlink("./system/vendor", MIRRMNT(vendor));
|
|
|
|
|
VLOGI("link", MIRRMNT(system) "/vendor", MIRRMNT(vendor));
|
|
|
|
|
SETMIR(buf1, vendor);
|
|
|
|
|
if (access(buf1, F_OK) != 0) {
|
|
|
|
|
xsymlink("./system/vendor", buf1);
|
|
|
|
|
VLOGI("link", "./system/vendor", buf1);
|
|
|
|
|
}
|
|
|
|
|
if (access("/system/product", F_OK) == 0 && access(MIRRMNT(product), F_OK) != 0) {
|
|
|
|
|
xsymlink("./system/product", MIRRMNT(product));
|
|
|
|
|
VLOGI("link", MIRRMNT(system) "/product", MIRRMNT(product));
|
|
|
|
|
SETMIR(buf1, product);
|
|
|
|
|
if (access("/system/product", F_OK) == 0 && access(buf1, F_OK) != 0) {
|
|
|
|
|
xsymlink("./system/product", buf1);
|
|
|
|
|
VLOGI("link", "./system/product", buf1);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Disable/remove magiskhide, resetprop
|
|
|
|
@@ -407,9 +408,13 @@ static bool magisk_env() {
|
|
|
|
|
|
|
|
|
|
if (access(DATABIN "/busybox", X_OK) == -1)
|
|
|
|
|
return false;
|
|
|
|
|
LOGI("* Setting up internal busybox");
|
|
|
|
|
cp_afc(DATABIN "/busybox", BBPATH "/busybox");
|
|
|
|
|
exec_command_sync(BBPATH "/busybox", "--install", "-s", BBPATH);
|
|
|
|
|
|
|
|
|
|
// TODO: Remove. Backwards compatibility for old manager
|
|
|
|
|
LOGI("* Setting up internal busybox\n");
|
|
|
|
|
sprintf(buf1, "%s/" BBPATH "/busybox", MAGISKTMP.data());
|
|
|
|
|
mkdir(dirname(buf1), 0755);
|
|
|
|
|
cp_afc(DATABIN "/busybox", buf1);
|
|
|
|
|
exec_command_sync(buf1, "--install", "-s", dirname(buf1));
|
|
|
|
|
|
|
|
|
|
return true;
|
|
|
|
|
}
|
|
|
|
@@ -417,22 +422,27 @@ static bool magisk_env() {
|
|
|
|
|
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) {
|
|
|
|
|
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
|
|
|
|
continue;
|
|
|
|
|
// Cleanup old module if exists
|
|
|
|
|
snprintf(buf, sizeof(buf), "%s/%s", MODULEROOT, entry->d_name);
|
|
|
|
|
if (access(buf, F_OK) == 0)
|
|
|
|
|
rm_rf(buf);
|
|
|
|
|
if (faccessat(mfd, entry->d_name, F_OK, 0) == 0) {
|
|
|
|
|
frm_rf(xopenat(mfd, entry->d_name, O_RDONLY | O_CLOEXEC));
|
|
|
|
|
unlinkat(mfd, entry->d_name, AT_REMOVEDIR);
|
|
|
|
|
}
|
|
|
|
|
LOGI("Upgrade / New module: %s\n", entry->d_name);
|
|
|
|
|
snprintf(buf2, sizeof(buf2), "%s/%s", MODULEUPGRADE, entry->d_name);
|
|
|
|
|
rename(buf2, buf);
|
|
|
|
|
renameat(ufd, entry->d_name, mfd, entry->d_name);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
close(mfd);
|
|
|
|
|
rm_rf(MODULEUPGRADE);
|
|
|
|
|
}
|
|
|
|
|
bind_mount(MIRRDIR MODULEROOT, MODULEMNT, false);
|
|
|
|
|
auto src = MAGISKTMP + "/" MIRRDIR "/" MODULEROOT;
|
|
|
|
|
auto dest = MAGISKTMP + "/" MODULEMNT;
|
|
|
|
|
bind_mount(src.data(), dest.data(), false);
|
|
|
|
|
|
|
|
|
|
restorecon();
|
|
|
|
|
chmod(SECURE_DIR, 0700);
|
|
|
|
@@ -475,9 +485,9 @@ static void collect_modules() {
|
|
|
|
|
|
|
|
|
|
if (faccessat(modfd, "remove", F_OK, 0) == 0) {
|
|
|
|
|
LOGI("%s: remove\n", entry->d_name);
|
|
|
|
|
fd_pathat(modfd, "uninstall.sh", buf, sizeof(buf));
|
|
|
|
|
if (access(buf, F_OK) == 0)
|
|
|
|
|
exec_script(buf);
|
|
|
|
|
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);
|
|
|
|
|
continue;
|
|
|
|
@@ -492,51 +502,56 @@ static void collect_modules() {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static bool load_modules(node_entry *root) {
|
|
|
|
|
LOGI("* Loading modules\n");
|
|
|
|
|
char buf1[4096];
|
|
|
|
|
char buf2[4096];
|
|
|
|
|
|
|
|
|
|
LOGI("* Loading modules\n");
|
|
|
|
|
bool has_modules = false;
|
|
|
|
|
for (const auto &m : module_list) {
|
|
|
|
|
const auto module = m.data();
|
|
|
|
|
char *name = buf + snprintf(buf, sizeof(buf), MODULEROOT "/%s/", module);
|
|
|
|
|
auto module = m.data();
|
|
|
|
|
char *b1 = buf1 + sprintf(buf1, MODULEROOT "/%s/", module);
|
|
|
|
|
|
|
|
|
|
// Read props
|
|
|
|
|
strcpy(name, "system.prop");
|
|
|
|
|
if (access(buf, F_OK) == 0) {
|
|
|
|
|
strcpy(b1, "system.prop");
|
|
|
|
|
if (access(buf1, F_OK) == 0) {
|
|
|
|
|
LOGI("%s: loading [system.prop]\n", module);
|
|
|
|
|
load_prop_file(buf, false);
|
|
|
|
|
load_prop_file(buf1, false);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Copy sepolicy rules
|
|
|
|
|
strcpy(name, "sepolicy.rule");
|
|
|
|
|
if (access(MIRRDIR "/persist", F_OK) == 0 && access(buf, F_OK) == 0) {
|
|
|
|
|
char *p = buf2 + snprintf(buf2, sizeof(buf2), MIRRDIR "/persist/magisk/%s", module);
|
|
|
|
|
strcpy(b1, "sepolicy.rule");
|
|
|
|
|
char *b2 = buf2 + sprintf(buf2, "%s/" MIRRDIR "/persist", MAGISKTMP.data());
|
|
|
|
|
if (access(buf2, F_OK) == 0 && access(buf1, F_OK) == 0) {
|
|
|
|
|
b2 += sprintf(b2, "/magisk/%s", module);
|
|
|
|
|
xmkdirs(buf2, 0755);
|
|
|
|
|
strcpy(p, "/sepolicy.rule");
|
|
|
|
|
cp_afc(buf, buf2);
|
|
|
|
|
strcpy(b2, "/sepolicy.rule");
|
|
|
|
|
cp_afc(buf1, buf2);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check whether skip mounting
|
|
|
|
|
strcpy(name, "skip_mount");
|
|
|
|
|
if (access(buf, F_OK) == 0)
|
|
|
|
|
strcpy(b1, "skip_mount");
|
|
|
|
|
if (access(buf1, F_OK) == 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Double check whether the system folder exists
|
|
|
|
|
strcpy(name, "system");
|
|
|
|
|
if (access(buf, F_OK) != 0)
|
|
|
|
|
strcpy(b1, "system");
|
|
|
|
|
if (access(buf1, F_OK) != 0)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
// Construct structure
|
|
|
|
|
has_modules = true;
|
|
|
|
|
LOGI("%s: constructing magic mount structure\n", module);
|
|
|
|
|
// If /system/vendor exists in module, create a link outside
|
|
|
|
|
strcpy(name, "system/vendor");
|
|
|
|
|
if (node_entry::vendor_root && access(buf, F_OK) == 0) {
|
|
|
|
|
snprintf(buf2, sizeof(buf2), "%s/%s/vendor", MODULEROOT, module);
|
|
|
|
|
strcpy(b1, "system/vendor");
|
|
|
|
|
if (node_entry::vendor_root && access(buf1, F_OK) == 0) {
|
|
|
|
|
sprintf(buf2, MODULEROOT "/%s/vendor", module);
|
|
|
|
|
unlink(buf2);
|
|
|
|
|
xsymlink("./system/vendor", buf2);
|
|
|
|
|
}
|
|
|
|
|
// If /system/product exists in module, create a link outside
|
|
|
|
|
strcpy(name, "system/product");
|
|
|
|
|
if (node_entry::product_root && access(buf, F_OK) == 0) {
|
|
|
|
|
snprintf(buf2, sizeof(buf2), "%s/%s/product", MODULEROOT, module);
|
|
|
|
|
strcpy(b1, "system/product");
|
|
|
|
|
if (node_entry::product_root && access(buf1, F_OK) == 0) {
|
|
|
|
|
sprintf(buf2, MODULEROOT "/%s/product", module);
|
|
|
|
|
unlink(buf2);
|
|
|
|
|
xsymlink("./system/product", buf2);
|
|
|
|
|
}
|
|
|
|
@@ -729,14 +744,6 @@ void late_start(int client) {
|
|
|
|
|
if (!pfs_done)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (access(BBPATH, F_OK) != 0){
|
|
|
|
|
LOGE("* post-fs-data mode is not triggered\n");
|
|
|
|
|
unlock_blocks();
|
|
|
|
|
magisk_env();
|
|
|
|
|
prepare_modules();
|
|
|
|
|
close(xopen(DISABLEFILE, O_RDONLY | O_CREAT | O_CLOEXEC, 0));
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
auto_start_magiskhide();
|
|
|
|
|
|
|
|
|
|
LOGI("* Running service.d scripts\n");
|
|
|
|
|