mirror of
https://github.com/topjohnwu/Magisk.git
synced 2024-12-22 07:57:39 +00:00
Remove unnecessary mirror for magic mount
Mirror was previously used for accessing the original file during magic mount when we are using a tmpfs to cover the target. However, since we introduce atomic mount, we switch all tmpfs mount in worker and then move to the target at once. It means that we can still access the original file when we are constructing the tmpfs mount point. Thus we no longer need mirror.
This commit is contained in:
parent
d20b30c771
commit
92b305a389
@ -19,18 +19,10 @@ bool zygisk_enabled = false;
|
||||
/*********
|
||||
* Setup *
|
||||
*********/
|
||||
|
||||
static bool rec_mount(const std::string_view from, const std::string_view to) {
|
||||
return !xmkdirs(to.data(), 0755) &&
|
||||
// recursively bind mount to mirror dir, rootfs will fail before 3.12 kernel
|
||||
// because of MS_NOUSER
|
||||
!mount(from.data(), to.data(), nullptr, MS_BIND | MS_REC, nullptr);
|
||||
}
|
||||
|
||||
static void mount_mirrors() {
|
||||
LOGI("* Mounting mirrors\n");
|
||||
static void setup_mounts() {
|
||||
LOGI("* Magic mount setup\n");
|
||||
auto self_mount_info = parse_mount_info("self");
|
||||
char path[64];
|
||||
char path[PATH_MAX];
|
||||
|
||||
// Bind remount module root to clear nosuid
|
||||
if (access(SECURE_DIR, F_OK) == 0 || SDK_INT < 24) {
|
||||
@ -65,8 +57,9 @@ static void mount_mirrors() {
|
||||
if (!rw) continue;
|
||||
string preinit_dir = resolve_preinit_dir(info.target.data());
|
||||
xmkdir(preinit_dir.data(), 0700);
|
||||
if ((mounted = rec_mount(preinit_dir, path))) {
|
||||
xmount(nullptr, path, nullptr, MS_UNBINDABLE, nullptr);
|
||||
xmkdirs(path, 0755);
|
||||
mounted = xmount(preinit_dir.data(), path, nullptr, MS_BIND, nullptr) == 0;
|
||||
if (mounted) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -81,27 +74,6 @@ static void mount_mirrors() {
|
||||
ssprintf(path, sizeof(path), "%s/" WORKERDIR, get_magisk_tmp());
|
||||
xmount("worker", path, "tmpfs", 0, "mode=755");
|
||||
xmount(nullptr, path, nullptr, MS_PRIVATE, nullptr);
|
||||
// Recursively bind mount / to mirror dir
|
||||
// Keep mirror shared so that mounting during post-fs-data will be propagated
|
||||
if (auto mirror_dir = get_magisk_tmp() + "/"s MIRRDIR; !rec_mount("/", mirror_dir)) {
|
||||
LOGI("fallback to mount subtree\n");
|
||||
// create new a bind mount for easy make private
|
||||
xmount(mirror_dir.data(), mirror_dir.data(), nullptr, MS_BIND, nullptr);
|
||||
// rootfs may fail, fallback to bind mount each mount point
|
||||
set<string, greater<>> mounted_dirs {{ get_magisk_tmp() }};
|
||||
for (const auto &info: self_mount_info) {
|
||||
if (info.type == "rootfs"sv) continue;
|
||||
// the greatest mount point that less than info.target, which is possibly a parent
|
||||
if (auto last_mount = mounted_dirs.upper_bound(info.target);
|
||||
last_mount != mounted_dirs.end() && info.target.starts_with(*last_mount + '/')) {
|
||||
continue;
|
||||
}
|
||||
if (rec_mount(info.target, mirror_dir + info.target)) {
|
||||
LOGD("%-8s: %s <- %s\n", "rbind", (mirror_dir + info.target).data(), info.target.data());
|
||||
mounted_dirs.insert(info.target);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
string find_preinit_device() {
|
||||
@ -310,7 +282,7 @@ bool MagiskD::post_fs_data() const {
|
||||
LOGI("** post-fs-data mode running\n");
|
||||
|
||||
unlock_blocks();
|
||||
mount_mirrors();
|
||||
setup_mounts();
|
||||
prune_su_access();
|
||||
|
||||
bool safe_mode = false;
|
||||
@ -341,15 +313,7 @@ bool MagiskD::post_fs_data() const {
|
||||
}
|
||||
|
||||
early_abort:
|
||||
auto mirror_dir = get_magisk_tmp() + "/"s MIRRDIR;
|
||||
// make mirror dir as a private mount so that it won't be affected by magic mount
|
||||
LOGD("make %s private\n", mirror_dir.data());
|
||||
xmount(nullptr, mirror_dir.data(), nullptr, MS_PRIVATE | MS_REC, nullptr);
|
||||
// We still do magic mount because root itself might need it
|
||||
load_modules();
|
||||
// make mirror dir as a shared mount to make magisk --stop work for other ns
|
||||
xmount(nullptr, mirror_dir.data(), nullptr, MS_SHARED | MS_REC, nullptr);
|
||||
LOGD("make %s shared\n", mirror_dir.data());
|
||||
return safe_mode;
|
||||
}
|
||||
|
||||
|
@ -27,24 +27,18 @@ static int bind_mount(const char *reason, const char *from, const char *to) {
|
||||
*************************/
|
||||
|
||||
tmpfs_node::tmpfs_node(node_entry *node) : dir_node(node, this) {
|
||||
if (!skip_mirror()) {
|
||||
string mirror = mirror_path();
|
||||
if (auto dir = open_dir(mirror.data())) {
|
||||
if (!replace()) {
|
||||
if (auto dir = open_dir(node_path().data())) {
|
||||
set_exist(true);
|
||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||
if (entry->d_type == DT_DIR) {
|
||||
// create a dummy inter_node to upgrade later
|
||||
emplace<inter_node>(entry->d_name, entry->d_name);
|
||||
} else {
|
||||
// Insert mirror nodes
|
||||
emplace<mirror_node>(entry->d_name, entry);
|
||||
}
|
||||
// create a dummy inter_node to upgrade later
|
||||
emplace<inter_node>(entry->d_name, entry);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
for (auto it = children.begin(); it != children.end(); ++it) {
|
||||
// Need to upgrade all inter_node children to tmpfs_node
|
||||
// Upgrade resting inter_node children to tmpfs_node
|
||||
if (isa<inter_node>(it->second))
|
||||
it = upgrade<tmpfs_node>(it);
|
||||
}
|
||||
@ -52,7 +46,7 @@ tmpfs_node::tmpfs_node(node_entry *node) : dir_node(node, this) {
|
||||
|
||||
bool dir_node::prepare() {
|
||||
// If direct replace or not exist, mount ourselves as tmpfs
|
||||
bool upgrade_to_tmpfs = skip_mirror() || !exist();
|
||||
bool upgrade_to_tmpfs = replace() || !exist();
|
||||
|
||||
for (auto it = children.begin(); it != children.end();) {
|
||||
// We also need to upgrade to tmpfs node if any child:
|
||||
@ -77,9 +71,9 @@ bool dir_node::prepare() {
|
||||
upgrade_to_tmpfs = true;
|
||||
}
|
||||
if (auto dn = dyn_cast<dir_node>(it->second)) {
|
||||
if (skip_mirror()) {
|
||||
if (replace()) {
|
||||
// Propagate skip mirror state to all children
|
||||
dn->set_skip_mirror(true);
|
||||
dn->set_replace(true);
|
||||
}
|
||||
if (dn->prepare()) {
|
||||
// Upgrade child to tmpfs
|
||||
@ -98,7 +92,7 @@ void dir_node::collect_module_files(const char *module, int dfd) {
|
||||
|
||||
for (dirent *entry; (entry = xreaddir(dir.get()));) {
|
||||
if (entry->d_name == ".replace"sv) {
|
||||
set_skip_mirror(true);
|
||||
set_replace(true);
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -141,18 +135,12 @@ void node_entry::create_and_mount(const char *reason, const string &src, bool ro
|
||||
}
|
||||
}
|
||||
|
||||
void mirror_node::mount() {
|
||||
create_and_mount("mirror", mirror_path());
|
||||
}
|
||||
|
||||
void module_node::mount() {
|
||||
std::string path = module + (parent()->root()->prefix + node_path());
|
||||
string mnt_src = module_mnt + path;
|
||||
{
|
||||
string src = MODULEROOT "/" + path;
|
||||
if (exist()) clone_attr(mirror_path().data(), src.data());
|
||||
// special case for /system/etc/hosts to ensure it is writable
|
||||
if (node_path() == "/system/etc/hosts") mnt_src = std::move(src);
|
||||
if (exist()) clone_attr(node_path().data(), src.data());
|
||||
}
|
||||
if (isa<tmpfs_node>(parent())) {
|
||||
create_and_mount("module", mnt_src);
|
||||
@ -162,22 +150,23 @@ void module_node::mount() {
|
||||
}
|
||||
|
||||
void tmpfs_node::mount() {
|
||||
string src = mirror_path();
|
||||
const char *src_path = access(src.data(), F_OK) == 0 ? src.data() : nullptr;
|
||||
if (!is_dir()) {
|
||||
create_and_mount("mirror", node_path());
|
||||
return;
|
||||
}
|
||||
if (!isa<tmpfs_node>(parent())) {
|
||||
const string &dest = node_path();
|
||||
auto worker_dir = worker_path();
|
||||
mkdirs(worker_dir.data(), 0);
|
||||
bind_mount("tmpfs", worker_dir.data(), worker_dir.data());
|
||||
clone_attr(src_path ?: parent()->node_path().data(), worker_dir.data());
|
||||
clone_attr(exist() ? node_path().data() : parent()->node_path().data(), worker_dir.data());
|
||||
dir_node::mount();
|
||||
VLOGD(skip_mirror() ? "replace" : "move", worker_dir.data(), dest.data());
|
||||
xmount(worker_dir.data(), dest.data(), nullptr, MS_MOVE, nullptr);
|
||||
VLOGD(replace() ? "replace" : "move", worker_dir.data(), node_path().data());
|
||||
xmount(worker_dir.data(), node_path().data(), nullptr, MS_MOVE, nullptr);
|
||||
} else {
|
||||
const string dest = worker_path();
|
||||
// We don't need another layer of tmpfs if parent is tmpfs
|
||||
mkdir(dest.data(), 0);
|
||||
clone_attr(src_path ?: parent()->worker_path().data(), dest.data());
|
||||
clone_attr(exist() ? node_path().data() : parent()->worker_path().data(), dest.data());
|
||||
dir_node::mount();
|
||||
}
|
||||
}
|
||||
@ -265,7 +254,6 @@ static void inject_zygisk_libs(root_node *system) {
|
||||
vector<module_info> *module_list;
|
||||
|
||||
void load_modules() {
|
||||
node_entry::mirror_dir = get_magisk_tmp() + "/"s MIRRDIR;
|
||||
node_entry::module_mnt = get_magisk_tmp() + "/"s MODULEMNT "/";
|
||||
|
||||
auto root = make_unique<root_node>("");
|
||||
|
@ -5,18 +5,16 @@
|
||||
|
||||
using namespace std;
|
||||
|
||||
#define TYPE_MIRROR (1 << 0) /* mount from mirror */
|
||||
#define TYPE_INTER (1 << 1) /* intermediate node */
|
||||
#define TYPE_TMPFS (1 << 2) /* replace with tmpfs */
|
||||
#define TYPE_MODULE (1 << 3) /* mount from module */
|
||||
#define TYPE_ROOT (1 << 4) /* partition root */
|
||||
#define TYPE_CUSTOM (1 << 5) /* custom node type overrides all */
|
||||
#define TYPE_INTER (1 << 0) /* intermediate node */
|
||||
#define TYPE_TMPFS (1 << 1) /* replace with tmpfs */
|
||||
#define TYPE_MODULE (1 << 2) /* mount from module */
|
||||
#define TYPE_ROOT (1 << 3) /* partition root */
|
||||
#define TYPE_CUSTOM (1 << 4) /* custom node type overrides all */
|
||||
#define TYPE_DIR (TYPE_INTER|TYPE_TMPFS|TYPE_ROOT)
|
||||
|
||||
class node_entry;
|
||||
class dir_node;
|
||||
class inter_node;
|
||||
class mirror_node;
|
||||
class tmpfs_node;
|
||||
class module_node;
|
||||
class root_node;
|
||||
@ -27,7 +25,6 @@ template<class T> static T *dyn_cast(node_entry *node);
|
||||
template<class T> uint8_t type_id() { return TYPE_CUSTOM; }
|
||||
template<> uint8_t type_id<dir_node>() { return TYPE_DIR; }
|
||||
template<> uint8_t type_id<inter_node>() { return TYPE_INTER; }
|
||||
template<> uint8_t type_id<mirror_node>() { return TYPE_MIRROR; }
|
||||
template<> uint8_t type_id<tmpfs_node>() { return TYPE_TMPFS; }
|
||||
template<> uint8_t type_id<module_node>() { return TYPE_MODULE; }
|
||||
template<> uint8_t type_id<root_node>() { return TYPE_ROOT; }
|
||||
@ -47,12 +44,9 @@ public:
|
||||
const string &node_path();
|
||||
const string worker_path();
|
||||
|
||||
string mirror_path() { return mirror_dir + node_path(); }
|
||||
|
||||
virtual void mount() = 0;
|
||||
|
||||
inline static string module_mnt;
|
||||
inline static string mirror_dir;
|
||||
|
||||
protected:
|
||||
template<class T>
|
||||
@ -174,6 +168,12 @@ protected:
|
||||
_root = self;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
dir_node(dirent *entry, T *self) : node_entry(entry->d_name, entry->d_type, self) {
|
||||
if constexpr (std::is_same_v<T, root_node>)
|
||||
_root = self;
|
||||
}
|
||||
|
||||
template<class T>
|
||||
dir_node(node_entry *node, T *self) : node_entry(self) {
|
||||
if constexpr (std::is_same_v<T, root_node>)
|
||||
@ -192,8 +192,8 @@ protected:
|
||||
|
||||
// Use bit 6 of _file_type
|
||||
// Skip binding mirror for this directory
|
||||
bool skip_mirror() const { return static_cast<bool>(_file_type & (1 << 6)); }
|
||||
void set_skip_mirror(bool b) { if (b) _file_type |= (1 << 6); else _file_type &= ~(1 << 6); }
|
||||
bool replace() const { return static_cast<bool>(_file_type & (1 << 6)); }
|
||||
void set_replace(bool b) { if (b) _file_type |= (1 << 6); else _file_type &= ~(1 << 6); }
|
||||
|
||||
template<class T = node_entry>
|
||||
T *iterator_to_node(iterator it) {
|
||||
@ -273,6 +273,7 @@ public:
|
||||
class inter_node : public dir_node {
|
||||
public:
|
||||
inter_node(const char *name) : dir_node(name, this) {}
|
||||
inter_node(dirent *entry) : dir_node(entry, this) {}
|
||||
};
|
||||
|
||||
class module_node : public node_entry {
|
||||
@ -289,13 +290,7 @@ private:
|
||||
const char *module;
|
||||
};
|
||||
|
||||
// Don't create the following two nodes before prepare
|
||||
class mirror_node : public node_entry {
|
||||
public:
|
||||
explicit mirror_node(dirent *entry) : node_entry(entry->d_name, entry->d_type, this) {}
|
||||
void mount() override;
|
||||
};
|
||||
|
||||
// Don't create tmpfs_node before prepare
|
||||
class tmpfs_node : public dir_node {
|
||||
public:
|
||||
explicit tmpfs_node(node_entry *node);
|
||||
|
Loading…
x
Reference in New Issue
Block a user