Preparation for dynamic tmpfs path
This commit is contained in:
parent
d739dcac2b
commit
e0a281583d
@ -61,6 +61,7 @@ LOCAL_SRC_FILES := \
|
|||||||
init/rootdir.cpp \
|
init/rootdir.cpp \
|
||||||
init/getinfo.cpp \
|
init/getinfo.cpp \
|
||||||
init/twostage.cpp \
|
init/twostage.cpp \
|
||||||
|
core/socket.cpp \
|
||||||
magiskpolicy/api.cpp \
|
magiskpolicy/api.cpp \
|
||||||
magiskpolicy/magiskpolicy.cpp \
|
magiskpolicy/magiskpolicy.cpp \
|
||||||
magiskpolicy/rules.cpp \
|
magiskpolicy/rules.cpp \
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <dirent.h>
|
#include <dirent.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include <string>
|
#include <string>
|
||||||
|
|
||||||
@ -19,7 +20,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static char buf[PATH_MAX], buf2[PATH_MAX];
|
|
||||||
static vector<string> module_list;
|
static vector<string> module_list;
|
||||||
static bool no_secure_dir = false;
|
static bool no_secure_dir = false;
|
||||||
static bool pfs_done = false;
|
static bool pfs_done = false;
|
||||||
@ -74,7 +74,6 @@ private:
|
|||||||
string get_path();
|
string get_path();
|
||||||
void insert(node_entry *&);
|
void insert(node_entry *&);
|
||||||
void clone_skeleton();
|
void clone_skeleton();
|
||||||
int get_path(char *path);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
bool node_entry::vendor_root = false;
|
bool node_entry::vendor_root = false;
|
||||||
@ -97,16 +96,12 @@ bool node_entry::is_root() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
string node_entry::get_path() {
|
string node_entry::get_path() {
|
||||||
get_path(buf);
|
string path;
|
||||||
return buf;
|
|
||||||
}
|
|
||||||
|
|
||||||
int node_entry::get_path(char *path) {
|
|
||||||
int len = 0;
|
|
||||||
if (parent)
|
if (parent)
|
||||||
len = parent->get_path(path);
|
path = parent->get_path();
|
||||||
len += sprintf(path + len, "/%s", name.c_str());
|
path += "/";
|
||||||
return len;
|
path += name;
|
||||||
|
return path;
|
||||||
}
|
}
|
||||||
|
|
||||||
void node_entry::insert(node_entry *&node) {
|
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) {
|
void node_entry::create_module_tree(const char *module) {
|
||||||
auto full_path = get_path();
|
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)
|
if (!dir)
|
||||||
return;
|
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 (faccessat(dirfd(dir.get()), ".replace", F_OK, 0) == 0) {
|
||||||
if (is_root()) {
|
if (is_root()) {
|
||||||
// Root nodes should not be replaced
|
// Root nodes should not be replaced
|
||||||
rm_rf(buf);
|
rm_rf(cwd.data());
|
||||||
} else if (status < IS_MODULE) {
|
} else if (status < IS_MODULE) {
|
||||||
// Upgrade current node to current module
|
// Upgrade current node to current module
|
||||||
this->module = module;
|
this->module = module;
|
||||||
@ -154,9 +149,8 @@ void node_entry::create_module_tree(const char *module) {
|
|||||||
// Create new node
|
// Create new node
|
||||||
auto node = new node_entry(this, module, entry->d_name, entry->d_type);
|
auto node = new node_entry(this, module, entry->d_name, entry->d_type);
|
||||||
|
|
||||||
// buf = real path, buf2 = module path
|
auto dest = full_path + "/" + entry->d_name;
|
||||||
snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), entry->d_name);
|
auto src = cwd + "/" + entry->d_name;
|
||||||
snprintf(buf2, PATH_MAX, MODULEROOT "/%s%s/%s", module, full_path.c_str(), entry->d_name);
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* Clone current directory in one of the following conditions:
|
* 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)
|
* - Target file is a symlink (exclude special nodes)
|
||||||
*/
|
*/
|
||||||
bool clone = false;
|
bool clone = false;
|
||||||
if (IS_LNK(node) || access(buf, F_OK) != 0) {
|
if (IS_LNK(node) || access(dest.data(), F_OK) != 0) {
|
||||||
clone = true;
|
clone = true;
|
||||||
} else if (!node->is_special()) {
|
} else if (!node->is_special()) {
|
||||||
struct stat s;
|
struct stat s;
|
||||||
xlstat(buf, &s);
|
xlstat(dest.data(), &s);
|
||||||
if (S_ISLNK(s.st_mode))
|
if (S_ISLNK(s.st_mode))
|
||||||
clone = true;
|
clone = true;
|
||||||
}
|
}
|
||||||
if (clone && is_root()) {
|
if (clone && is_root()) {
|
||||||
// Root nodes should not be cloned
|
// Root nodes should not be cloned
|
||||||
rm_rf(buf2);
|
rm_rf(src.data());
|
||||||
delete node;
|
delete node;
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
@ -189,7 +183,7 @@ void node_entry::create_module_tree(const char *module) {
|
|||||||
node->status = IS_INTER;
|
node->status = IS_INTER;
|
||||||
} else {
|
} else {
|
||||||
// Clone attributes from real path
|
// Clone attributes from real path
|
||||||
clone_attr(buf, buf2);
|
clone_attr(dest.data(), src.data());
|
||||||
if (IS_DIR(node)) {
|
if (IS_DIR(node)) {
|
||||||
// First mark as an intermediate node
|
// First mark as an intermediate node
|
||||||
node->status = IS_INTER;
|
node->status = IS_INTER;
|
||||||
@ -209,8 +203,9 @@ void node_entry::create_module_tree(const char *module) {
|
|||||||
void node_entry::clone_skeleton() {
|
void node_entry::clone_skeleton() {
|
||||||
// Clone the structure
|
// Clone the structure
|
||||||
auto full_path = get_path();
|
auto full_path = get_path();
|
||||||
snprintf(buf, PATH_MAX, "%s%s", MIRRDIR, full_path.data());
|
auto mirror_path = MAGISKTMP + "/" MIRRDIR + full_path;
|
||||||
if (auto dir = xopen_dir(buf); dir) {
|
|
||||||
|
if (auto dir = xopen_dir(mirror_path.data()); dir) {
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||||
continue;
|
continue;
|
||||||
@ -222,42 +217,41 @@ void node_entry::clone_skeleton() {
|
|||||||
|
|
||||||
if (status & IS_SKEL) {
|
if (status & IS_SKEL) {
|
||||||
file_attr attr;
|
file_attr attr;
|
||||||
getattr(full_path.c_str(), &attr);
|
getattr(full_path.data(), &attr);
|
||||||
LOGI("mnt_tmpfs : %s\n", full_path.c_str());
|
LOGI("mnt_tmpfs : %s\n", full_path.data());
|
||||||
xmount("tmpfs", full_path.c_str(), "tmpfs", 0, nullptr);
|
xmount("tmpfs", full_path.data(), "tmpfs", 0, nullptr);
|
||||||
setattr(full_path.c_str(), &attr);
|
setattr(full_path.data(), &attr);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (auto &child : children) {
|
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
|
// Create the dummy file/directory
|
||||||
if (IS_DIR(child))
|
if (IS_DIR(child))
|
||||||
xmkdir(buf, 0755);
|
xmkdir(dest.data(), 0755);
|
||||||
else if (IS_REG(child))
|
else if (IS_REG(child))
|
||||||
close(creat(buf, 0644));
|
close(creat(dest.data(), 0644));
|
||||||
// Links will be handled later
|
// Links will be handled later
|
||||||
|
|
||||||
if (child->status & IS_MODULE) {
|
if (child->status & IS_MODULE) {
|
||||||
// Mount from module file to dummy file
|
// Mount from module file to dummy file
|
||||||
snprintf(buf2, PATH_MAX, "%s/%s%s/%s", MODULEMNT,
|
src = MAGISKTMP + "/" MODULEMNT "/" + child->module + full_path + "/" + child->name;
|
||||||
child->module, full_path.c_str(), child->name.c_str());
|
|
||||||
} else if (child->status & (IS_SKEL | IS_INTER)) {
|
} else if (child->status & (IS_SKEL | IS_INTER)) {
|
||||||
// It's an intermediate folder, recursive clone
|
// It's an intermediate folder, recursive clone
|
||||||
child->clone_skeleton();
|
child->clone_skeleton();
|
||||||
continue;
|
continue;
|
||||||
} else if (child->status & IS_DUMMY) {
|
} else if (child->status & IS_DUMMY) {
|
||||||
// Mount from mirror to dummy file
|
// 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)) {
|
if (IS_LNK(child)) {
|
||||||
// Copy symlinks directly
|
// Copy symlinks directly
|
||||||
cp_afc(buf2, buf);
|
cp_afc(src.data(), dest.data());
|
||||||
VLOGI("copy_link ", buf2, buf);
|
VLOGI("copy_link ", src.data(), dest.data());
|
||||||
} else {
|
} else {
|
||||||
snprintf(buf, PATH_MAX, "%s/%s", full_path.c_str(), child->name.c_str());
|
bind_mount(src.data(), dest.data());
|
||||||
bind_mount(buf2, buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -265,9 +259,9 @@ void node_entry::clone_skeleton() {
|
|||||||
void node_entry::magic_mount() {
|
void node_entry::magic_mount() {
|
||||||
if (status & IS_MODULE) {
|
if (status & IS_MODULE) {
|
||||||
// Mount module item
|
// Mount module item
|
||||||
auto real_path = get_path();
|
auto dest = get_path();
|
||||||
snprintf(buf, PATH_MAX, "%s/%s%s", MODULEMNT, module, real_path.c_str());
|
auto src = MAGISKTMP + "/" MODULEMNT "/" + module + dest;
|
||||||
bind_mount(buf, real_path.c_str());
|
bind_mount(src.data(), dest.data());
|
||||||
} else if (status & IS_SKEL) {
|
} else if (status & IS_SKEL) {
|
||||||
// The node is labeled to be cloned with skeleton, lets do it
|
// The node is labeled to be cloned with skeleton, lets do it
|
||||||
clone_skeleton();
|
clone_skeleton();
|
||||||
@ -302,16 +296,19 @@ static int bind_mount(const char *from, const char *to, bool log) {
|
|||||||
return ret;
|
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) { \
|
#define mount_mirror(part, flag) { \
|
||||||
xstat(me->mnt_fsname, &st); \
|
xstat(me->mnt_fsname, &st); \
|
||||||
mknod(PARTBLK(part), (st.st_mode & S_IFMT) | 0600, st.st_rdev); \
|
SETMIR(buf1, part); \
|
||||||
xmkdir(MIRRMNT(part), 0755); \
|
SETBLK(buf2, part); \
|
||||||
xmount(PARTBLK(part), MIRRMNT(part), me->mnt_type, flag, nullptr); \
|
mknod(buf2, (st.st_mode & S_IFMT) | 0600, st.st_rdev); \
|
||||||
VLOGI("mount", PARTBLK(part), MIRRMNT(part)); \
|
xmkdir(buf1, 0755); \
|
||||||
|
xmount(buf2, buf1, me->mnt_type, flag, nullptr); \
|
||||||
|
VLOGI("mount", buf2, buf1); \
|
||||||
}
|
}
|
||||||
|
|
||||||
static bool magisk_env() {
|
static bool magisk_env() {
|
||||||
@ -320,11 +317,13 @@ static bool magisk_env() {
|
|||||||
string pkg;
|
string pkg;
|
||||||
check_manager(&pkg);
|
check_manager(&pkg);
|
||||||
|
|
||||||
char install_dir[128];
|
char buf1[4096];
|
||||||
sprintf(install_dir, "%s/0/%s/install", APP_DATA_DIR, pkg.data());
|
char buf2[4096];
|
||||||
|
|
||||||
|
sprintf(buf1, "%s/0/%s/install", APP_DATA_DIR, pkg.data());
|
||||||
|
|
||||||
// Alternative binaries paths
|
// 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) {
|
for (auto alt : alt_bin) {
|
||||||
struct stat st;
|
struct stat st;
|
||||||
if (lstat(alt, &st) != -1) {
|
if (lstat(alt, &st) != -1) {
|
||||||
@ -348,14 +347,11 @@ static bool magisk_env() {
|
|||||||
unlink("/data/magisk_merge.img");
|
unlink("/data/magisk_merge.img");
|
||||||
unlink("/data/magisk_debug.log");
|
unlink("/data/magisk_debug.log");
|
||||||
|
|
||||||
// Directories in tmpfs overlay
|
sprintf(buf1, "%s/" MODULEMNT, MAGISKTMP.data());
|
||||||
xmkdir(MIRRDIR, 0);
|
xmkdir(buf1, 0755);
|
||||||
xmkdir(BLOCKDIR, 0);
|
// TODO: Remove. Backwards compatibility for old manager
|
||||||
xmkdir(BBPATH, 0755);
|
sprintf(buf1, "%s/" INTLROOT "/img", MAGISKTMP.data());
|
||||||
xmkdir(MODULEMNT, 0755);
|
xsymlink("./modules", buf1);
|
||||||
|
|
||||||
// Backwards compatibility for old Magisk Manager
|
|
||||||
xsymlink("./modules", MAGISKTMP "/img");
|
|
||||||
|
|
||||||
// Directories in /data/adb
|
// Directories in /data/adb
|
||||||
xmkdir(DATABIN, 0755);
|
xmkdir(DATABIN, 0755);
|
||||||
@ -369,8 +365,9 @@ static bool magisk_env() {
|
|||||||
parse_mnt("/proc/mounts", [&](mntent *me) {
|
parse_mnt("/proc/mounts", [&](mntent *me) {
|
||||||
if (DIR_IS(system_root)) {
|
if (DIR_IS(system_root)) {
|
||||||
mount_mirror(system_root, MS_RDONLY);
|
mount_mirror(system_root, MS_RDONLY);
|
||||||
xsymlink("./system_root/system", MIRRMNT(system));
|
SETMIR(buf1, system);
|
||||||
VLOGI("link", MIRRMNT(system_root) "/system", MIRRMNT(system));
|
xsymlink("./system_root/system", buf1);
|
||||||
|
VLOGI("link", "./system_root/system", buf1);
|
||||||
system_as_root = true;
|
system_as_root = true;
|
||||||
} else if (!system_as_root && DIR_IS(system)) {
|
} else if (!system_as_root && DIR_IS(system)) {
|
||||||
mount_mirror(system, MS_RDONLY);
|
mount_mirror(system, MS_RDONLY);
|
||||||
@ -385,18 +382,22 @@ static bool magisk_env() {
|
|||||||
}
|
}
|
||||||
return true;
|
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
|
// Pre-init mirrors
|
||||||
xsymlink("./system_root/system", MIRRMNT(system));
|
xsymlink("./system_root/system", buf1);
|
||||||
VLOGI("link", MIRRMNT(system_root) "/system", MIRRMNT(system));
|
VLOGI("link", "./system_root/system", buf1);
|
||||||
}
|
}
|
||||||
if (access(MIRRMNT(vendor), F_OK) != 0) {
|
SETMIR(buf1, vendor);
|
||||||
xsymlink("./system/vendor", MIRRMNT(vendor));
|
if (access(buf1, F_OK) != 0) {
|
||||||
VLOGI("link", MIRRMNT(system) "/vendor", MIRRMNT(vendor));
|
xsymlink("./system/vendor", buf1);
|
||||||
|
VLOGI("link", "./system/vendor", buf1);
|
||||||
}
|
}
|
||||||
if (access("/system/product", F_OK) == 0 && access(MIRRMNT(product), F_OK) != 0) {
|
SETMIR(buf1, product);
|
||||||
xsymlink("./system/product", MIRRMNT(product));
|
if (access("/system/product", F_OK) == 0 && access(buf1, F_OK) != 0) {
|
||||||
VLOGI("link", MIRRMNT(system) "/product", MIRRMNT(product));
|
xsymlink("./system/product", buf1);
|
||||||
|
VLOGI("link", "./system/product", buf1);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Disable/remove magiskhide, resetprop
|
// Disable/remove magiskhide, resetprop
|
||||||
@ -407,9 +408,13 @@ static bool magisk_env() {
|
|||||||
|
|
||||||
if (access(DATABIN "/busybox", X_OK) == -1)
|
if (access(DATABIN "/busybox", X_OK) == -1)
|
||||||
return false;
|
return false;
|
||||||
LOGI("* Setting up internal busybox");
|
|
||||||
cp_afc(DATABIN "/busybox", BBPATH "/busybox");
|
// TODO: Remove. Backwards compatibility for old manager
|
||||||
exec_command_sync(BBPATH "/busybox", "--install", "-s", BBPATH);
|
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;
|
return true;
|
||||||
}
|
}
|
||||||
@ -417,22 +422,27 @@ static bool magisk_env() {
|
|||||||
static void prepare_modules() {
|
static void prepare_modules() {
|
||||||
// Upgrade modules
|
// Upgrade modules
|
||||||
if (auto dir = open_dir(MODULEUPGRADE); dir) {
|
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()));) {
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
if (entry->d_type == DT_DIR) {
|
if (entry->d_type == DT_DIR) {
|
||||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||||
continue;
|
continue;
|
||||||
// Cleanup old module if exists
|
// Cleanup old module if exists
|
||||||
snprintf(buf, sizeof(buf), "%s/%s", MODULEROOT, entry->d_name);
|
if (faccessat(mfd, entry->d_name, F_OK, 0) == 0) {
|
||||||
if (access(buf, F_OK) == 0)
|
frm_rf(xopenat(mfd, entry->d_name, O_RDONLY | O_CLOEXEC));
|
||||||
rm_rf(buf);
|
unlinkat(mfd, entry->d_name, AT_REMOVEDIR);
|
||||||
|
}
|
||||||
LOGI("Upgrade / New module: %s\n", entry->d_name);
|
LOGI("Upgrade / New module: %s\n", entry->d_name);
|
||||||
snprintf(buf2, sizeof(buf2), "%s/%s", MODULEUPGRADE, entry->d_name);
|
renameat(ufd, entry->d_name, mfd, entry->d_name);
|
||||||
rename(buf2, buf);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
close(mfd);
|
||||||
rm_rf(MODULEUPGRADE);
|
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();
|
restorecon();
|
||||||
chmod(SECURE_DIR, 0700);
|
chmod(SECURE_DIR, 0700);
|
||||||
@ -475,9 +485,9 @@ static void collect_modules() {
|
|||||||
|
|
||||||
if (faccessat(modfd, "remove", F_OK, 0) == 0) {
|
if (faccessat(modfd, "remove", F_OK, 0) == 0) {
|
||||||
LOGI("%s: remove\n", entry->d_name);
|
LOGI("%s: remove\n", entry->d_name);
|
||||||
fd_pathat(modfd, "uninstall.sh", buf, sizeof(buf));
|
auto uninstaller = MODULEROOT + "/"s + entry->d_name + "/uninstall.sh";
|
||||||
if (access(buf, F_OK) == 0)
|
if (access(uninstaller.data(), F_OK) == 0)
|
||||||
exec_script(buf);
|
exec_script(uninstaller.data());
|
||||||
frm_rf(xdup(modfd));
|
frm_rf(xdup(modfd));
|
||||||
unlinkat(dfd, entry->d_name, AT_REMOVEDIR);
|
unlinkat(dfd, entry->d_name, AT_REMOVEDIR);
|
||||||
continue;
|
continue;
|
||||||
@ -492,51 +502,56 @@ static void collect_modules() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
static bool load_modules(node_entry *root) {
|
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;
|
bool has_modules = false;
|
||||||
for (const auto &m : module_list) {
|
for (const auto &m : module_list) {
|
||||||
const auto module = m.data();
|
auto module = m.data();
|
||||||
char *name = buf + snprintf(buf, sizeof(buf), MODULEROOT "/%s/", module);
|
char *b1 = buf1 + sprintf(buf1, MODULEROOT "/%s/", module);
|
||||||
|
|
||||||
// Read props
|
// Read props
|
||||||
strcpy(name, "system.prop");
|
strcpy(b1, "system.prop");
|
||||||
if (access(buf, F_OK) == 0) {
|
if (access(buf1, F_OK) == 0) {
|
||||||
LOGI("%s: loading [system.prop]\n", module);
|
LOGI("%s: loading [system.prop]\n", module);
|
||||||
load_prop_file(buf, false);
|
load_prop_file(buf1, false);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Copy sepolicy rules
|
// Copy sepolicy rules
|
||||||
strcpy(name, "sepolicy.rule");
|
strcpy(b1, "sepolicy.rule");
|
||||||
if (access(MIRRDIR "/persist", F_OK) == 0 && access(buf, F_OK) == 0) {
|
char *b2 = buf2 + sprintf(buf2, "%s/" MIRRDIR "/persist", MAGISKTMP.data());
|
||||||
char *p = buf2 + snprintf(buf2, sizeof(buf2), MIRRDIR "/persist/magisk/%s", module);
|
if (access(buf2, F_OK) == 0 && access(buf1, F_OK) == 0) {
|
||||||
|
b2 += sprintf(b2, "/magisk/%s", module);
|
||||||
xmkdirs(buf2, 0755);
|
xmkdirs(buf2, 0755);
|
||||||
strcpy(p, "/sepolicy.rule");
|
strcpy(b2, "/sepolicy.rule");
|
||||||
cp_afc(buf, buf2);
|
cp_afc(buf1, buf2);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check whether skip mounting
|
// Check whether skip mounting
|
||||||
strcpy(name, "skip_mount");
|
strcpy(b1, "skip_mount");
|
||||||
if (access(buf, F_OK) == 0)
|
if (access(buf1, F_OK) == 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Double check whether the system folder exists
|
// Double check whether the system folder exists
|
||||||
strcpy(name, "system");
|
strcpy(b1, "system");
|
||||||
if (access(buf, F_OK) != 0)
|
if (access(buf1, F_OK) != 0)
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
// Construct structure
|
// Construct structure
|
||||||
has_modules = true;
|
has_modules = true;
|
||||||
LOGI("%s: constructing magic mount structure\n", module);
|
LOGI("%s: constructing magic mount structure\n", module);
|
||||||
// If /system/vendor exists in module, create a link outside
|
// If /system/vendor exists in module, create a link outside
|
||||||
strcpy(name, "system/vendor");
|
strcpy(b1, "system/vendor");
|
||||||
if (node_entry::vendor_root && access(buf, F_OK) == 0) {
|
if (node_entry::vendor_root && access(buf1, F_OK) == 0) {
|
||||||
snprintf(buf2, sizeof(buf2), "%s/%s/vendor", MODULEROOT, module);
|
sprintf(buf2, MODULEROOT "/%s/vendor", module);
|
||||||
unlink(buf2);
|
unlink(buf2);
|
||||||
xsymlink("./system/vendor", buf2);
|
xsymlink("./system/vendor", buf2);
|
||||||
}
|
}
|
||||||
// If /system/product exists in module, create a link outside
|
// If /system/product exists in module, create a link outside
|
||||||
strcpy(name, "system/product");
|
strcpy(b1, "system/product");
|
||||||
if (node_entry::product_root && access(buf, F_OK) == 0) {
|
if (node_entry::product_root && access(buf1, F_OK) == 0) {
|
||||||
snprintf(buf2, sizeof(buf2), "%s/%s/product", MODULEROOT, module);
|
sprintf(buf2, MODULEROOT "/%s/product", module);
|
||||||
unlink(buf2);
|
unlink(buf2);
|
||||||
xsymlink("./system/product", buf2);
|
xsymlink("./system/product", buf2);
|
||||||
}
|
}
|
||||||
@ -729,14 +744,6 @@ void late_start(int client) {
|
|||||||
if (!pfs_done)
|
if (!pfs_done)
|
||||||
return;
|
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();
|
auto_start_magiskhide();
|
||||||
|
|
||||||
LOGI("* Running service.d scripts\n");
|
LOGI("* Running service.d scripts\n");
|
||||||
|
@ -4,6 +4,7 @@
|
|||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <signal.h>
|
#include <signal.h>
|
||||||
|
#include <libgen.h>
|
||||||
#include <sys/un.h>
|
#include <sys/un.h>
|
||||||
#include <sys/types.h>
|
#include <sys/types.h>
|
||||||
#include <sys/mount.h>
|
#include <sys/mount.h>
|
||||||
@ -16,8 +17,11 @@
|
|||||||
#include <resetprop.hpp>
|
#include <resetprop.hpp>
|
||||||
#include <flags.h>
|
#include <flags.h>
|
||||||
|
|
||||||
|
using namespace std;
|
||||||
|
|
||||||
int SDK_INT = -1;
|
int SDK_INT = -1;
|
||||||
bool RECOVERY_MODE = false;
|
bool RECOVERY_MODE = false;
|
||||||
|
string MAGISKTMP;
|
||||||
static struct stat self_st;
|
static struct stat self_st;
|
||||||
|
|
||||||
static void verify_client(int client, pid_t pid) {
|
static void verify_client(int client, pid_t pid) {
|
||||||
@ -91,6 +95,10 @@ static void *request_handler(void *args) {
|
|||||||
}
|
}
|
||||||
close(client);
|
close(client);
|
||||||
break;
|
break;
|
||||||
|
case GET_PATH:
|
||||||
|
write_string(client, MAGISKTMP.data());
|
||||||
|
close(client);
|
||||||
|
break;
|
||||||
default:
|
default:
|
||||||
close(client);
|
close(client);
|
||||||
break;
|
break;
|
||||||
@ -114,11 +122,19 @@ static void main_daemon() {
|
|||||||
|
|
||||||
setsid();
|
setsid();
|
||||||
setcon("u:r:" SEPOL_PROC_DOMAIN ":s0");
|
setcon("u:r:" SEPOL_PROC_DOMAIN ":s0");
|
||||||
|
|
||||||
|
// Get self stat
|
||||||
|
char path[4096];
|
||||||
|
xreadlink("/proc/self/exe", path, sizeof(path));
|
||||||
|
MAGISKTMP = dirname(path);
|
||||||
|
xstat("/proc/self/exe", &self_st);
|
||||||
|
|
||||||
restore_rootcon();
|
restore_rootcon();
|
||||||
|
|
||||||
// Unmount pre-init patches
|
// Unmount pre-init patches
|
||||||
if (access(ROOTMNT, F_OK) == 0) {
|
auto mount_list = MAGISKTMP + "/" ROOTMNT;
|
||||||
file_readline(true, ROOTMNT, [](auto line) -> bool {
|
if (access(mount_list.data(), F_OK) == 0) {
|
||||||
|
file_readline(true, mount_list.data(), [](string_view line) -> bool {
|
||||||
umount2(line.data(), MNT_DETACH);
|
umount2(line.data(), MNT_DETACH);
|
||||||
return true;
|
return true;
|
||||||
});
|
});
|
||||||
@ -126,9 +142,6 @@ static void main_daemon() {
|
|||||||
|
|
||||||
LOGI(NAME_WITH_VER(Magisk) " daemon started\n");
|
LOGI(NAME_WITH_VER(Magisk) " daemon started\n");
|
||||||
|
|
||||||
// Get server stat
|
|
||||||
stat("/proc/self/exe", &self_st);
|
|
||||||
|
|
||||||
// Get API level
|
// Get API level
|
||||||
parse_prop_file("/system/build.prop", [](auto key, auto val) -> bool {
|
parse_prop_file("/system/build.prop", [](auto key, auto val) -> bool {
|
||||||
if (key == "ro.build.version.sdk") {
|
if (key == "ro.build.version.sdk") {
|
||||||
@ -148,7 +161,8 @@ static void main_daemon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Load config status
|
// Load config status
|
||||||
parse_prop_file(MAGISKTMP "/config", [](auto key, auto val) -> bool {
|
auto config = MAGISKTMP + "/" INTLROOT "/config";
|
||||||
|
parse_prop_file(config.data(), [](auto key, auto val) -> bool {
|
||||||
if (key == "RECOVERYMODE" && val == "true")
|
if (key == "RECOVERYMODE" && val == "true")
|
||||||
RECOVERY_MODE = true;
|
RECOVERY_MODE = true;
|
||||||
return true;
|
return true;
|
||||||
|
@ -37,7 +37,7 @@ Advanced Options (Internal APIs):
|
|||||||
--clone-attr SRC DEST clone permission, owner, and selinux context
|
--clone-attr SRC DEST clone permission, owner, and selinux context
|
||||||
--clone SRC DEST clone SRC to DEST
|
--clone SRC DEST clone SRC to DEST
|
||||||
--sqlite SQL exec SQL commands to Magisk database
|
--sqlite SQL exec SQL commands to Magisk database
|
||||||
--path print internal tmpfs mount path
|
--path print Magisk tmpfs mount path
|
||||||
|
|
||||||
Available applets:
|
Available applets:
|
||||||
)EOF");
|
)EOF");
|
||||||
@ -116,8 +116,10 @@ int magisk_main(int argc, char *argv[]) {
|
|||||||
write_int(fd, REMOVE_MODULES);
|
write_int(fd, REMOVE_MODULES);
|
||||||
return read_int(fd);
|
return read_int(fd);
|
||||||
} else if (argv[1] == "--path"sv) {
|
} else if (argv[1] == "--path"sv) {
|
||||||
// TODO: hardcode /sbin for now, actual logic will be used for Android 11
|
int fd = connect_daemon();
|
||||||
printf("/sbin\n");
|
write_int(fd, GET_PATH);
|
||||||
|
char *path = read_string(fd);
|
||||||
|
printf("%s\n", path);
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#if 0
|
#if 0
|
||||||
|
@ -81,20 +81,17 @@ void restorecon() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
void restore_rootcon() {
|
void restore_rootcon() {
|
||||||
setfilecon("/sbin", ROOT_CON);
|
setfilecon(MAGISKTMP.data(), ROOT_CON);
|
||||||
setfilecon(MAGISKTMP, ROOT_CON);
|
|
||||||
setfilecon(MIRRDIR, ROOT_CON);
|
|
||||||
setfilecon(BLOCKDIR, ROOT_CON);
|
|
||||||
|
|
||||||
auto dir = xopen_dir("/sbin");
|
auto dir = xopen_dir(MAGISKTMP.data());
|
||||||
int dfd = dirfd(dir.get());
|
int dfd = dirfd(dir.get());
|
||||||
|
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||||
continue;
|
continue;
|
||||||
setfilecon_at(dfd, entry->d_name, ROOT_CON);
|
if (entry->d_name == "magisk"sv || entry->d_name == "magiskinit"sv)
|
||||||
|
setfilecon_at(dfd, entry->d_name, MAGISK_CON);
|
||||||
|
else
|
||||||
|
setfilecon_at(dfd, entry->d_name, ROOT_CON);
|
||||||
}
|
}
|
||||||
|
|
||||||
setfilecon("/sbin/magisk", MAGISK_CON);
|
|
||||||
setfilecon("/sbin/magiskinit", MAGISK_CON);
|
|
||||||
}
|
}
|
||||||
|
@ -1,12 +1,9 @@
|
|||||||
/* socket.c - All socket related operations
|
|
||||||
*/
|
|
||||||
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <fcntl.h>
|
#include <fcntl.h>
|
||||||
#include <endian.h>
|
#include <endian.h>
|
||||||
|
|
||||||
#include <daemon.hpp>
|
#include <socket.hpp>
|
||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
#include <logging.hpp>
|
#include <logging.hpp>
|
||||||
|
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <pthread.h>
|
#include <pthread.h>
|
||||||
#include <sys/un.h>
|
|
||||||
#include <sys/socket.h>
|
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include <socket.hpp>
|
||||||
|
|
||||||
// Commands require connecting to daemon
|
// Commands require connecting to daemon
|
||||||
enum {
|
enum {
|
||||||
DO_NOTHING = 0,
|
DO_NOTHING = 0,
|
||||||
@ -18,6 +18,7 @@ enum {
|
|||||||
MAGISKHIDE,
|
MAGISKHIDE,
|
||||||
SQLITE_CMD,
|
SQLITE_CMD,
|
||||||
REMOVE_MODULES,
|
REMOVE_MODULES,
|
||||||
|
GET_PATH,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Return codes for daemon
|
// Return codes for daemon
|
||||||
@ -32,25 +33,6 @@ enum {
|
|||||||
|
|
||||||
int connect_daemon(bool create = false);
|
int connect_daemon(bool create = false);
|
||||||
|
|
||||||
// socket.cpp
|
|
||||||
|
|
||||||
socklen_t setup_sockaddr(struct sockaddr_un *sun, const char *name);
|
|
||||||
int create_rand_socket(struct sockaddr_un *sun);
|
|
||||||
int socket_accept(int sockfd, int timeout);
|
|
||||||
void get_client_cred(int fd, struct ucred *cred);
|
|
||||||
int recv_fd(int sockfd);
|
|
||||||
void send_fd(int sockfd, int fd);
|
|
||||||
int read_int(int fd);
|
|
||||||
int read_int_be(int fd);
|
|
||||||
void write_int(int fd, int val);
|
|
||||||
void write_int_be(int fd, int val);
|
|
||||||
char *read_string(int fd);
|
|
||||||
char *read_string_be(int fd);
|
|
||||||
void write_string(int fd, const char *val);
|
|
||||||
void write_string_be(int fd, const char *val);
|
|
||||||
void write_key_value(int fd, const char *key, const char *val);
|
|
||||||
void write_key_token(int fd, const char *key, int tok);
|
|
||||||
|
|
||||||
/***************
|
/***************
|
||||||
* Boot Stages *
|
* Boot Stages *
|
||||||
***************/
|
***************/
|
||||||
|
@ -1,19 +1,13 @@
|
|||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <logging.hpp>
|
#include <logging.hpp>
|
||||||
|
#include <string>
|
||||||
|
|
||||||
#define MAIN_SOCKET "d30138f2310a9fb9c54a3e0c21f58591"
|
#define MAIN_SOCKET "d30138f2310a9fb9c54a3e0c21f58591"
|
||||||
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
|
#define JAVA_PACKAGE_NAME "com.topjohnwu.magisk"
|
||||||
#define LOGFILE "/cache/magisk.log"
|
#define LOGFILE "/cache/magisk.log"
|
||||||
#define UNBLOCKFILE "/dev/.magisk_unblock"
|
#define UNBLOCKFILE "/dev/.magisk_unblock"
|
||||||
#define DISABLEFILE "/cache/.disable_magisk"
|
#define DISABLEFILE "/cache/.disable_magisk"
|
||||||
#define MAGISKTMP "/sbin/.magisk"
|
|
||||||
#define MIRRDIR MAGISKTMP "/mirror"
|
|
||||||
#define BLOCKDIR MAGISKTMP "/block"
|
|
||||||
#define BBPATH MAGISKTMP "/busybox"
|
|
||||||
#define MODULEMNT MAGISKTMP "/modules"
|
|
||||||
#define ROOTOVL MAGISKTMP "/rootdir"
|
|
||||||
#define ROOTMNT ROOTOVL "/.mount_list"
|
|
||||||
#define SECURE_DIR "/data/adb"
|
#define SECURE_DIR "/data/adb"
|
||||||
#define MODULEROOT SECURE_DIR "/modules"
|
#define MODULEROOT SECURE_DIR "/modules"
|
||||||
#define MODULEUPGRADE SECURE_DIR "/modules_update"
|
#define MODULEUPGRADE SECURE_DIR "/modules_update"
|
||||||
@ -21,6 +15,16 @@
|
|||||||
#define MAGISKDB SECURE_DIR "/magisk.db"
|
#define MAGISKDB SECURE_DIR "/magisk.db"
|
||||||
#define MANAGERAPK DATABIN "/magisk.apk"
|
#define MANAGERAPK DATABIN "/magisk.apk"
|
||||||
|
|
||||||
|
// tmpfs paths
|
||||||
|
extern std::string MAGISKTMP;
|
||||||
|
#define INTLROOT ".magisk"
|
||||||
|
#define MIRRDIR INTLROOT "/mirror"
|
||||||
|
#define BLOCKDIR INTLROOT "/block"
|
||||||
|
#define MODULEMNT INTLROOT "/modules"
|
||||||
|
#define BBPATH INTLROOT "/busybox"
|
||||||
|
#define ROOTOVL INTLROOT "/rootdir"
|
||||||
|
#define ROOTMNT ROOTOVL "/.mount_list"
|
||||||
|
|
||||||
constexpr const char *applet_names[] = { "su", "resetprop", "magiskhide", nullptr };
|
constexpr const char *applet_names[] = { "su", "resetprop", "magiskhide", nullptr };
|
||||||
|
|
||||||
// Multi-call entrypoints
|
// Multi-call entrypoints
|
||||||
|
21
native/jni/include/socket.hpp
Normal file
21
native/jni/include/socket.hpp
Normal file
@ -0,0 +1,21 @@
|
|||||||
|
#pragma once
|
||||||
|
|
||||||
|
#include <sys/un.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
|
||||||
|
socklen_t setup_sockaddr(struct sockaddr_un *sun, const char *name);
|
||||||
|
int create_rand_socket(struct sockaddr_un *sun);
|
||||||
|
int socket_accept(int sockfd, int timeout);
|
||||||
|
void get_client_cred(int fd, struct ucred *cred);
|
||||||
|
int recv_fd(int sockfd);
|
||||||
|
void send_fd(int sockfd, int fd);
|
||||||
|
int read_int(int fd);
|
||||||
|
int read_int_be(int fd);
|
||||||
|
void write_int(int fd, int val);
|
||||||
|
void write_int_be(int fd, int val);
|
||||||
|
char *read_string(int fd);
|
||||||
|
char *read_string_be(int fd);
|
||||||
|
void write_string(int fd, const char *val);
|
||||||
|
void write_string_be(int fd, const char *val);
|
||||||
|
void write_key_value(int fd, const char *key, const char *val);
|
||||||
|
void write_key_token(int fd, const char *key, int tok);
|
@ -5,7 +5,7 @@
|
|||||||
#include <stdlib.h>
|
#include <stdlib.h>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include <magisk.hpp>
|
#include <logging.hpp>
|
||||||
|
|
||||||
struct cmdline {
|
struct cmdline {
|
||||||
bool skip_initramfs;
|
bool skip_initramfs;
|
||||||
@ -57,26 +57,25 @@ public:
|
|||||||
class MagiskInit : public BaseInit {
|
class MagiskInit : public BaseInit {
|
||||||
protected:
|
protected:
|
||||||
raw_data self;
|
raw_data self;
|
||||||
const char *persist_dir;
|
std::string persist_dir;
|
||||||
|
|
||||||
virtual void early_mount() = 0;
|
virtual void early_mount() = 0;
|
||||||
bool patch_sepolicy(const char *file = "/sepolicy");
|
bool patch_sepolicy(const char *file = "/sepolicy");
|
||||||
public:
|
public:
|
||||||
MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {};
|
MagiskInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {}
|
||||||
};
|
};
|
||||||
|
|
||||||
class SARBase : public MagiskInit {
|
class SARBase : public MagiskInit {
|
||||||
protected:
|
protected:
|
||||||
raw_data config;
|
raw_data config;
|
||||||
std::vector<raw_file> overlays;
|
std::vector<raw_file> overlays;
|
||||||
|
std::string tmp_dir;
|
||||||
|
|
||||||
void backup_files();
|
void backup_files();
|
||||||
void patch_rootdir();
|
void patch_rootdir();
|
||||||
void mount_system_root();
|
void mount_system_root();
|
||||||
public:
|
public:
|
||||||
SARBase(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {
|
SARBase(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {}
|
||||||
persist_dir = MIRRDIR "/persist/magisk";
|
|
||||||
}
|
|
||||||
void start() override {
|
void start() override {
|
||||||
early_mount();
|
early_mount();
|
||||||
patch_rootdir();
|
patch_rootdir();
|
||||||
@ -92,7 +91,9 @@ class ForcedFirstStageInit : public BaseInit {
|
|||||||
private:
|
private:
|
||||||
void prepare();
|
void prepare();
|
||||||
public:
|
public:
|
||||||
ForcedFirstStageInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {};
|
ForcedFirstStageInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {
|
||||||
|
LOGD("%s\n", __FUNCTION__);
|
||||||
|
};
|
||||||
void start() override {
|
void start() override {
|
||||||
prepare();
|
prepare();
|
||||||
exec_init("/system/bin/init");
|
exec_init("/system/bin/init");
|
||||||
@ -103,7 +104,9 @@ class FirstStageInit : public BaseInit {
|
|||||||
private:
|
private:
|
||||||
void prepare();
|
void prepare();
|
||||||
public:
|
public:
|
||||||
FirstStageInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {};
|
FirstStageInit(char *argv[], cmdline *cmd) : BaseInit(argv, cmd) {
|
||||||
|
LOGD("%s\n", __FUNCTION__);
|
||||||
|
};
|
||||||
void start() override {
|
void start() override {
|
||||||
prepare();
|
prepare();
|
||||||
exec_init();
|
exec_init();
|
||||||
@ -116,7 +119,9 @@ private:
|
|||||||
protected:
|
protected:
|
||||||
void early_mount() override;
|
void early_mount() override;
|
||||||
public:
|
public:
|
||||||
SARFirstStageInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd) {};
|
SARFirstStageInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd) {
|
||||||
|
LOGD("%s\n", __FUNCTION__);
|
||||||
|
};
|
||||||
void start() override {
|
void start() override {
|
||||||
early_mount();
|
early_mount();
|
||||||
traced_exec_init();
|
traced_exec_init();
|
||||||
@ -128,7 +133,9 @@ protected:
|
|||||||
void early_mount() override;
|
void early_mount() override;
|
||||||
void cleanup() override { /* Do not do any cleanup */ }
|
void cleanup() override { /* Do not do any cleanup */ }
|
||||||
public:
|
public:
|
||||||
SecondStageInit(char *argv[]) : SARBase(argv, nullptr) {};
|
SecondStageInit(char *argv[]) : SARBase(argv, nullptr) {
|
||||||
|
LOGD("%s\n", __FUNCTION__);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* ***********
|
/* ***********
|
||||||
@ -139,7 +146,9 @@ class SARInit : public SARBase {
|
|||||||
protected:
|
protected:
|
||||||
void early_mount() override;
|
void early_mount() override;
|
||||||
public:
|
public:
|
||||||
SARInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd) {};
|
SARInit(char *argv[], cmdline *cmd) : SARBase(argv, cmd) {
|
||||||
|
LOGD("%s\n", __FUNCTION__);
|
||||||
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
/* **********
|
/* **********
|
||||||
@ -148,13 +157,12 @@ public:
|
|||||||
|
|
||||||
class RootFSInit : public MagiskInit {
|
class RootFSInit : public MagiskInit {
|
||||||
private:
|
private:
|
||||||
int root = -1;
|
|
||||||
void setup_rootfs();
|
void setup_rootfs();
|
||||||
protected:
|
protected:
|
||||||
void early_mount() override;
|
void early_mount() override;
|
||||||
public:
|
public:
|
||||||
RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {
|
RootFSInit(char *argv[], cmdline *cmd) : MagiskInit(argv, cmd) {
|
||||||
persist_dir = "/dev/mnt/persist/magisk";
|
LOGD("%s\n", __FUNCTION__);
|
||||||
}
|
}
|
||||||
|
|
||||||
void start() override {
|
void start() override {
|
||||||
@ -164,9 +172,10 @@ public:
|
|||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#define INIT_SOCKET "MAGISKINIT"
|
||||||
|
|
||||||
void load_kernel_info(cmdline *cmd);
|
void load_kernel_info(cmdline *cmd);
|
||||||
int dump_magisk(const char *path, mode_t mode);
|
int dump_magisk(const char *path, mode_t mode);
|
||||||
int magisk_proxy_main(int argc, char *argv[]);
|
int magisk_proxy_main(int argc, char *argv[]);
|
||||||
void setup_klog();
|
void setup_klog();
|
||||||
void mount_sbin();
|
void setup_tmp(const char *path, const raw_data &self, const raw_data &config);
|
||||||
socklen_t setup_sockaddr(struct sockaddr_un *sun);
|
|
||||||
|
@ -175,7 +175,6 @@ void RootFSInit::early_mount() {
|
|||||||
full_read("/init", self.buf, self.sz);
|
full_read("/init", self.buf, self.sz);
|
||||||
|
|
||||||
LOGD("Reverting /init\n");
|
LOGD("Reverting /init\n");
|
||||||
root = xopen("/", O_RDONLY | O_CLOEXEC);
|
|
||||||
rename("/.backup/init", "/init");
|
rename("/.backup/init", "/init");
|
||||||
|
|
||||||
mount_root(system);
|
mount_root(system);
|
||||||
@ -186,7 +185,7 @@ void RootFSInit::early_mount() {
|
|||||||
xmkdir("/dev/mnt", 0755);
|
xmkdir("/dev/mnt", 0755);
|
||||||
mount_persist("/dev/block", "/dev/mnt");
|
mount_persist("/dev/block", "/dev/mnt");
|
||||||
mount_list.emplace_back("/dev/mnt/persist");
|
mount_list.emplace_back("/dev/mnt/persist");
|
||||||
mount_list.emplace_back("/dev/mnt/cache");
|
persist_dir = "/dev/mnt/persist/magisk";
|
||||||
}
|
}
|
||||||
|
|
||||||
void SARBase::backup_files() {
|
void SARBase::backup_files() {
|
||||||
@ -261,13 +260,45 @@ void BaseInit::cleanup() {
|
|||||||
mount_list.shrink_to_fit();
|
mount_list.shrink_to_fit();
|
||||||
}
|
}
|
||||||
|
|
||||||
void mount_sbin() {
|
static void patch_socket_name(const char *path) {
|
||||||
LOGD("Mount /sbin tmpfs overlay\n");
|
char *buf;
|
||||||
xmount("tmpfs", "/sbin", "tmpfs", 0, "mode=755");
|
size_t size;
|
||||||
|
mmap_rw(path, buf, size);
|
||||||
|
for (int i = 0; i < size; ++i) {
|
||||||
|
if (memcmp(buf + i, MAIN_SOCKET, sizeof(MAIN_SOCKET)) == 0) {
|
||||||
|
gen_rand_str(buf + i, 16);
|
||||||
|
i += sizeof(MAIN_SOCKET);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
munmap(buf, size);
|
||||||
|
}
|
||||||
|
|
||||||
xmkdir(MAGISKTMP, 0755);
|
void setup_tmp(const char *path, const raw_data &self, const raw_data &config) {
|
||||||
|
LOGD("Setup Magisk tmp at %s\n", path);
|
||||||
|
xmount("tmpfs", path, "tmpfs", 0, "mode=755");
|
||||||
|
|
||||||
|
chdir(path);
|
||||||
|
|
||||||
|
xmkdir(INTLROOT, 0755);
|
||||||
xmkdir(MIRRDIR, 0);
|
xmkdir(MIRRDIR, 0);
|
||||||
xmkdir(BLOCKDIR, 0);
|
xmkdir(BLOCKDIR, 0);
|
||||||
|
|
||||||
mount_persist(BLOCKDIR, MIRRDIR);
|
mount_persist(BLOCKDIR, MIRRDIR);
|
||||||
|
|
||||||
|
int fd = xopen(INTLROOT "/config", O_WRONLY | O_CREAT, 0);
|
||||||
|
xwrite(fd, config.buf, config.sz);
|
||||||
|
close(fd);
|
||||||
|
fd = xopen("magiskinit", O_WRONLY | O_CREAT, 0755);
|
||||||
|
xwrite(fd, self.buf, self.sz);
|
||||||
|
close(fd);
|
||||||
|
dump_magisk("magisk", 0755);
|
||||||
|
patch_socket_name("magisk");
|
||||||
|
|
||||||
|
// Create applet symlinks
|
||||||
|
for (int i = 0; applet_names[i]; ++i)
|
||||||
|
xsymlink("./magisk", applet_names[i]);
|
||||||
|
xsymlink("./magiskinit", "magiskpolicy");
|
||||||
|
xsymlink("./magiskinit", "supolicy");
|
||||||
|
|
||||||
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
@ -6,6 +6,7 @@
|
|||||||
#include <magisk.hpp>
|
#include <magisk.hpp>
|
||||||
#include <magiskpolicy.hpp>
|
#include <magiskpolicy.hpp>
|
||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
|
#include <socket.hpp>
|
||||||
|
|
||||||
#include "init.hpp"
|
#include "init.hpp"
|
||||||
#include "magiskrc.inc"
|
#include "magiskrc.inc"
|
||||||
@ -18,19 +19,6 @@
|
|||||||
|
|
||||||
using namespace std;
|
using namespace std;
|
||||||
|
|
||||||
static void patch_socket_name(const char *path) {
|
|
||||||
char *buf;
|
|
||||||
size_t size;
|
|
||||||
mmap_rw(path, buf, size);
|
|
||||||
for (int i = 0; i < size; ++i) {
|
|
||||||
if (memcmp(buf + i, MAIN_SOCKET, sizeof(MAIN_SOCKET)) == 0) {
|
|
||||||
gen_rand_str(buf + i, 16);
|
|
||||||
i += sizeof(MAIN_SOCKET);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
munmap(buf, size);
|
|
||||||
}
|
|
||||||
|
|
||||||
static vector<raw_data> rc_list;
|
static vector<raw_data> rc_list;
|
||||||
|
|
||||||
static void patch_init_rc(FILE *rc) {
|
static void patch_init_rc(FILE *rc) {
|
||||||
@ -153,15 +141,14 @@ bool MagiskInit::patch_sepolicy(const char *file) {
|
|||||||
sepol_allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
|
sepol_allow(SEPOL_PROC_DOMAIN, ALL, ALL, ALL);
|
||||||
|
|
||||||
// Custom rules
|
// Custom rules
|
||||||
if (auto dir = xopen_dir(persist_dir); dir) {
|
if (auto dir = xopen_dir(persist_dir.data()); dir) {
|
||||||
char path[4096];
|
|
||||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||||
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
if (entry->d_name == "."sv || entry->d_name == ".."sv)
|
||||||
continue;
|
continue;
|
||||||
snprintf(path, sizeof(path), "%s/%s/sepolicy.rule", persist_dir, entry->d_name);
|
auto rule = persist_dir + "/" + entry->d_name + "/sepolicy.rule";
|
||||||
if (access(path, R_OK) == 0) {
|
if (access(rule.data(), R_OK) == 0) {
|
||||||
LOGD("Loading custom sepolicy patch: %s\n", path);
|
LOGD("Loading custom sepolicy patch: %s\n", rule.data());
|
||||||
load_rule_file(path);
|
load_rule_file(rule.data());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -178,30 +165,6 @@ bool MagiskInit::patch_sepolicy(const char *file) {
|
|||||||
return patch_init;
|
return patch_init;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void sbin_overlay(const raw_data &self, const raw_data &config) {
|
|
||||||
mount_sbin();
|
|
||||||
|
|
||||||
// Dump binaries
|
|
||||||
xmkdir(MAGISKTMP, 0755);
|
|
||||||
int fd = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000);
|
|
||||||
xwrite(fd, config.buf, config.sz);
|
|
||||||
close(fd);
|
|
||||||
fd = xopen("/sbin/magiskinit", O_WRONLY | O_CREAT, 0755);
|
|
||||||
xwrite(fd, self.buf, self.sz);
|
|
||||||
close(fd);
|
|
||||||
dump_magisk("/sbin/magisk", 0755);
|
|
||||||
patch_socket_name("/sbin/magisk");
|
|
||||||
|
|
||||||
// Create applet symlinks
|
|
||||||
char path[64];
|
|
||||||
for (int i = 0; applet_names[i]; ++i) {
|
|
||||||
sprintf(path, "/sbin/%s", applet_names[i]);
|
|
||||||
xsymlink("./magisk", path);
|
|
||||||
}
|
|
||||||
xsymlink("./magiskinit", "/sbin/magiskpolicy");
|
|
||||||
xsymlink("./magiskinit", "/sbin/supolicy");
|
|
||||||
}
|
|
||||||
|
|
||||||
static void recreate_sbin(const char *mirror, bool use_bind_mount) {
|
static void recreate_sbin(const char *mirror, bool use_bind_mount) {
|
||||||
auto dp = xopen_dir(mirror);
|
auto dp = xopen_dir(mirror);
|
||||||
int src = dirfd(dp.get());
|
int src = dirfd(dp.get());
|
||||||
@ -233,12 +196,6 @@ static void recreate_sbin(const char *mirror, bool use_bind_mount) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#define ROOTMIR MIRRDIR "/system_root"
|
|
||||||
#define ROOTBLK BLOCKDIR "/system_root"
|
|
||||||
#define MONOPOLICY "/sepolicy"
|
|
||||||
#define PATCHPOLICY "/sbin/.se"
|
|
||||||
#define LIBSELINUX "/system/" LIBNAME "/libselinux.so"
|
|
||||||
|
|
||||||
static string magic_mount_list;
|
static string magic_mount_list;
|
||||||
|
|
||||||
static void magic_mount(const string &sdir, const string &ddir = "") {
|
static void magic_mount(const string &sdir, const string &ddir = "") {
|
||||||
@ -262,8 +219,20 @@ static void magic_mount(const string &sdir, const string &ddir = "") {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#define ROOTMIR MIRRDIR "/system_root"
|
||||||
|
#define ROOTBLK BLOCKDIR "/system_root"
|
||||||
|
#define MONOPOLICY "/sepolicy"
|
||||||
|
#define PATCHPOLICY "/sbin/.se"
|
||||||
|
#define LIBSELINUX "/system/" LIBNAME "/libselinux.so"
|
||||||
|
|
||||||
void SARBase::patch_rootdir() {
|
void SARBase::patch_rootdir() {
|
||||||
sbin_overlay(self, config);
|
// TODO: dynamic paths
|
||||||
|
tmp_dir = "/sbin";
|
||||||
|
|
||||||
|
setup_tmp(tmp_dir.data(), self, config);
|
||||||
|
persist_dir = tmp_dir + "/" MIRRDIR "/persist";
|
||||||
|
|
||||||
|
chdir(tmp_dir.data());
|
||||||
|
|
||||||
// Mount system_root mirror
|
// Mount system_root mirror
|
||||||
struct stat st;
|
struct stat st;
|
||||||
@ -273,8 +242,9 @@ void SARBase::patch_rootdir() {
|
|||||||
if (xmount(ROOTBLK, ROOTMIR, "ext4", MS_RDONLY, nullptr))
|
if (xmount(ROOTBLK, ROOTMIR, "ext4", MS_RDONLY, nullptr))
|
||||||
xmount(ROOTBLK, ROOTMIR, "erofs", MS_RDONLY, nullptr);
|
xmount(ROOTBLK, ROOTMIR, "erofs", MS_RDONLY, nullptr);
|
||||||
|
|
||||||
// Recreate original sbin structure
|
// Recreate original sbin structure if necessary
|
||||||
recreate_sbin(ROOTMIR "/sbin", true);
|
if (tmp_dir == "/sbin")
|
||||||
|
recreate_sbin(ROOTMIR "/sbin", true);
|
||||||
|
|
||||||
// Patch init
|
// Patch init
|
||||||
raw_data init;
|
raw_data init;
|
||||||
@ -332,20 +302,21 @@ void SARBase::patch_rootdir() {
|
|||||||
patch_sepolicy(PATCHPOLICY);
|
patch_sepolicy(PATCHPOLICY);
|
||||||
|
|
||||||
// Handle overlay
|
// Handle overlay
|
||||||
struct sockaddr_un sun{};
|
struct sockaddr_un sun;
|
||||||
socklen_t len = setup_sockaddr(&sun);
|
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
int socketfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
if (connect(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET)) == 0) {
|
||||||
if (connect(socketfd, (struct sockaddr*) &sun, len) == 0) {
|
|
||||||
LOGD("ACK init tracer to write backup files\n");
|
LOGD("ACK init tracer to write backup files\n");
|
||||||
|
// Let tracer know where tmp_dir is
|
||||||
|
write_string(sockfd, tmp_dir.data());
|
||||||
|
// Wait for tracer to finish copying files
|
||||||
int ack;
|
int ack;
|
||||||
// Wait for init tracer finish copying files
|
read(sockfd, &ack, sizeof(ack));
|
||||||
read(socketfd, &ack, sizeof(ack));
|
|
||||||
} else {
|
} else {
|
||||||
LOGD("Restore backup files locally\n");
|
LOGD("Restore backup files locally\n");
|
||||||
restore_folder(ROOTOVL, overlays);
|
restore_folder(ROOTOVL, overlays);
|
||||||
overlays.clear();
|
overlays.clear();
|
||||||
}
|
}
|
||||||
close(socketfd);
|
close(sockfd);
|
||||||
if (access(ROOTOVL "/sbin", F_OK) == 0) {
|
if (access(ROOTOVL "/sbin", F_OK) == 0) {
|
||||||
file_attr a;
|
file_attr a;
|
||||||
getattr("/sbin", &a);
|
getattr("/sbin", &a);
|
||||||
@ -362,9 +333,11 @@ void SARBase::patch_rootdir() {
|
|||||||
|
|
||||||
// Mount rootdir
|
// Mount rootdir
|
||||||
magic_mount(ROOTOVL);
|
magic_mount(ROOTOVL);
|
||||||
dest = xopen(ROOTMNT, O_WRONLY | O_CREAT | O_CLOEXEC);
|
dest = xopen(ROOTMNT, O_WRONLY | O_CREAT | O_CLOEXEC, 0);
|
||||||
write(dest, magic_mount_list.data(), magic_mount_list.length());
|
write(dest, magic_mount_list.data(), magic_mount_list.length());
|
||||||
close(dest);
|
close(dest);
|
||||||
|
|
||||||
|
chdir("/");
|
||||||
}
|
}
|
||||||
|
|
||||||
int magisk_proxy_main(int argc, char *argv[]) {
|
int magisk_proxy_main(int argc, char *argv[]) {
|
||||||
@ -381,7 +354,7 @@ int magisk_proxy_main(int argc, char *argv[]) {
|
|||||||
unlink("/sbin/magisk");
|
unlink("/sbin/magisk");
|
||||||
rm_rf("/.backup");
|
rm_rf("/.backup");
|
||||||
|
|
||||||
sbin_overlay(self, config);
|
setup_tmp("/sbin", self, config);
|
||||||
|
|
||||||
// Create symlinks pointing back to /root
|
// Create symlinks pointing back to /root
|
||||||
recreate_sbin("/root", false);
|
recreate_sbin("/root", false);
|
||||||
|
@ -1,8 +1,10 @@
|
|||||||
#include <sys/ptrace.h>
|
#include <sys/ptrace.h>
|
||||||
#include <sys/wait.h>
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <magisk.hpp>
|
||||||
#include <utils.hpp>
|
#include <utils.hpp>
|
||||||
#include <logging.hpp>
|
#include <logging.hpp>
|
||||||
|
#include <socket.hpp>
|
||||||
|
|
||||||
#include "init.hpp"
|
#include "init.hpp"
|
||||||
|
|
||||||
@ -103,14 +105,6 @@ static inline long xptrace(int request, pid_t pid, void *addr = nullptr, intptr_
|
|||||||
return xptrace(request, pid, addr, reinterpret_cast<void *>(data));
|
return xptrace(request, pid, addr, reinterpret_cast<void *>(data));
|
||||||
}
|
}
|
||||||
|
|
||||||
#define INIT_SOCKET "MAGISKINIT"
|
|
||||||
|
|
||||||
socklen_t setup_sockaddr(struct sockaddr_un *sun) {
|
|
||||||
sun->sun_family = AF_LOCAL;
|
|
||||||
strcpy(sun->sun_path + 1, INIT_SOCKET);
|
|
||||||
return sizeof(sa_family_t) + sizeof(INIT_SOCKET);
|
|
||||||
}
|
|
||||||
|
|
||||||
void SARFirstStageInit::traced_exec_init() {
|
void SARFirstStageInit::traced_exec_init() {
|
||||||
int pid = getpid();
|
int pid = getpid();
|
||||||
|
|
||||||
@ -132,11 +126,6 @@ void SARFirstStageInit::traced_exec_init() {
|
|||||||
// Re-exec init
|
// Re-exec init
|
||||||
exec_init();
|
exec_init();
|
||||||
} else {
|
} else {
|
||||||
// Close all file descriptors and stop logging
|
|
||||||
no_logging();
|
|
||||||
for (int i = 0; i < 20; ++i)
|
|
||||||
close(i);
|
|
||||||
|
|
||||||
// Attach to parent to trace exec
|
// Attach to parent to trace exec
|
||||||
xptrace(PTRACE_ATTACH, pid);
|
xptrace(PTRACE_ATTACH, pid);
|
||||||
waitpid(pid, nullptr, __WALL | __WNOTHREAD);
|
waitpid(pid, nullptr, __WALL | __WNOTHREAD);
|
||||||
@ -155,18 +144,22 @@ void SARFirstStageInit::traced_exec_init() {
|
|||||||
xumount2("/dev", MNT_DETACH);
|
xumount2("/dev", MNT_DETACH);
|
||||||
|
|
||||||
// Establish socket for 2nd stage ack
|
// Establish socket for 2nd stage ack
|
||||||
struct sockaddr_un sun{};
|
struct sockaddr_un sun;
|
||||||
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
int sockfd = xsocket(AF_LOCAL, SOCK_STREAM | SOCK_CLOEXEC, 0);
|
||||||
xbind(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun));
|
xbind(sockfd, (struct sockaddr*) &sun, setup_sockaddr(&sun, INIT_SOCKET));
|
||||||
xlisten(sockfd, 1);
|
xlisten(sockfd, 1);
|
||||||
|
|
||||||
|
// Resume init
|
||||||
xptrace(PTRACE_DETACH, pid);
|
xptrace(PTRACE_DETACH, pid);
|
||||||
|
|
||||||
// Wait for second stage ack
|
// Wait for second stage ack
|
||||||
int client = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
|
int client = xaccept4(sockfd, nullptr, nullptr, SOCK_CLOEXEC);
|
||||||
|
|
||||||
// Write backup files
|
// Write backup files
|
||||||
int cfg = xopen(MAGISKTMP "/config", O_WRONLY | O_CREAT, 0000);
|
char *tmp_dir = read_string(client);
|
||||||
|
chdir(tmp_dir);
|
||||||
|
free(tmp_dir);
|
||||||
|
int cfg = xopen(INTLROOT "/config", O_WRONLY | O_CREAT, 0);
|
||||||
xwrite(cfg, config.buf, config.sz);
|
xwrite(cfg, config.buf, config.sz);
|
||||||
close(cfg);
|
close(cfg);
|
||||||
restore_folder(ROOTOVL, overlays);
|
restore_folder(ROOTOVL, overlays);
|
||||||
|
Loading…
Reference in New Issue
Block a user