You've already forked Zygisk-Assistant
mirror of
https://github.com/snake-4/Zygisk-Assistant.git
synced 2025-09-06 06:37:02 +00:00
@@ -3,7 +3,7 @@ LOCAL_PATH := $(call my-dir)
|
|||||||
include $(CLEAR_VARS)
|
include $(CLEAR_VARS)
|
||||||
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
LOCAL_C_INCLUDES := $(LOCAL_PATH)/include
|
||||||
LOCAL_MODULE := zygisk
|
LOCAL_MODULE := zygisk
|
||||||
LOCAL_SRC_FILES := mount_parser.cpp unmount.cpp main.cpp
|
LOCAL_SRC_FILES := mount_parser.cpp mountinfo_parser.cpp unmount.cpp main.cpp
|
||||||
LOCAL_STATIC_LIBRARIES := libcxx
|
LOCAL_STATIC_LIBRARIES := libcxx
|
||||||
LOCAL_LDLIBS := -llog
|
LOCAL_LDLIBS := -llog
|
||||||
include $(BUILD_SHARED_LIBRARY)
|
include $(BUILD_SHARED_LIBRARY)
|
||||||
|
|||||||
@@ -16,14 +16,10 @@ public:
|
|||||||
int getPassNumber() const;
|
int getPassNumber() const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
void parseMountOptions(const std::string &input);
|
std::string fsname, dir, type;
|
||||||
|
|
||||||
std::string fsname;
|
|
||||||
std::string dir;
|
|
||||||
std::string type;
|
|
||||||
std::unordered_map<std::string, std::string> opts_map;
|
std::unordered_map<std::string, std::string> opts_map;
|
||||||
int freq;
|
int freq, passno;
|
||||||
int passno;
|
|
||||||
};
|
};
|
||||||
|
|
||||||
std::vector<mount_entry_t> parseMountsFromPath(const char *path);
|
std::vector<mount_entry_t> parseMountsFromPath(const char *path);
|
||||||
|
std::unordered_map<std::string, std::string> parseMountOptions(const std::string &input);
|
||||||
|
|||||||
32
module/jni/include/mountinfo_parser.hpp
Normal file
32
module/jni/include/mountinfo_parser.hpp
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
class mountinfo_entry_t
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
mountinfo_entry_t(int mount_id, int parent_id, int major, int minor,
|
||||||
|
const std::string &root, const std::string &mount_point,
|
||||||
|
const std::string &mount_options, const std::string &optional_fields,
|
||||||
|
const std::string &filesystem_type, const std::string &mount_source,
|
||||||
|
const std::string &super_options);
|
||||||
|
|
||||||
|
const int &getMountId() const;
|
||||||
|
const int &getParentId() const;
|
||||||
|
const int &getMajor() const;
|
||||||
|
const int &getMinor() const;
|
||||||
|
const std::string &getRoot() const;
|
||||||
|
const std::string &getMountPoint() const;
|
||||||
|
const std::unordered_map<std::string, std::string> &getMountOptions() const;
|
||||||
|
const std::string &getOptionalFields() const;
|
||||||
|
const std::string &getFilesystemType() const;
|
||||||
|
const std::string &getMountSource() const;
|
||||||
|
const std::unordered_map<std::string, std::string> &getSuperOptions() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
int mount_id, parent_id, major, minor;
|
||||||
|
std::string root, mount_point, optional_fields, filesystem_type, mount_source;
|
||||||
|
std::unordered_map<std::string, std::string> mount_options, super_options;
|
||||||
|
};
|
||||||
|
|
||||||
|
std::vector<mountinfo_entry_t> parseMountinfosFromPath(const char *path);
|
||||||
@@ -11,55 +11,15 @@
|
|||||||
mount_entry_t::mount_entry_t(::mntent *entry)
|
mount_entry_t::mount_entry_t(::mntent *entry)
|
||||||
: fsname(entry->mnt_fsname), dir(entry->mnt_dir), type(entry->mnt_type), freq(entry->mnt_freq), passno(entry->mnt_passno)
|
: fsname(entry->mnt_fsname), dir(entry->mnt_dir), type(entry->mnt_type), freq(entry->mnt_freq), passno(entry->mnt_passno)
|
||||||
{
|
{
|
||||||
parseMountOptions(entry->mnt_opts);
|
opts_map = parseMountOptions(entry->mnt_opts);
|
||||||
}
|
}
|
||||||
|
|
||||||
const std::string &mount_entry_t::getFsName() const
|
const std::string &mount_entry_t::getFsName() const { return fsname; }
|
||||||
{
|
const std::string &mount_entry_t::getMountPoint() const { return dir; }
|
||||||
return fsname;
|
const std::string &mount_entry_t::getType() const { return type; }
|
||||||
}
|
const std::unordered_map<std::string, std::string> &mount_entry_t::getOptions() const { return opts_map; }
|
||||||
|
int mount_entry_t::getDumpFrequency() const { return freq; }
|
||||||
const std::string &mount_entry_t::getMountPoint() const
|
int mount_entry_t::getPassNumber() const { return passno; }
|
||||||
{
|
|
||||||
return dir;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::string &mount_entry_t::getType() const
|
|
||||||
{
|
|
||||||
return type;
|
|
||||||
}
|
|
||||||
|
|
||||||
const std::unordered_map<std::string, std::string> &mount_entry_t::getOptions() const
|
|
||||||
{
|
|
||||||
return opts_map;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mount_entry_t::getDumpFrequency() const
|
|
||||||
{
|
|
||||||
return freq;
|
|
||||||
}
|
|
||||||
|
|
||||||
int mount_entry_t::getPassNumber() const
|
|
||||||
{
|
|
||||||
return passno;
|
|
||||||
}
|
|
||||||
|
|
||||||
void mount_entry_t::parseMountOptions(const std::string &input)
|
|
||||||
{
|
|
||||||
std::istringstream iss(input);
|
|
||||||
std::string token;
|
|
||||||
while (std::getline(iss, token, ','))
|
|
||||||
{
|
|
||||||
std::istringstream tokenStream(token);
|
|
||||||
std::string key, value;
|
|
||||||
|
|
||||||
if (std::getline(tokenStream, key, '='))
|
|
||||||
{
|
|
||||||
std::getline(tokenStream, value); // Put what's left in the stream to value, could be empty
|
|
||||||
opts_map[key] = value;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<mount_entry_t> parseMountsFromPath(const char *path)
|
std::vector<mount_entry_t> parseMountsFromPath(const char *path)
|
||||||
{
|
{
|
||||||
@@ -81,3 +41,22 @@ std::vector<mount_entry_t> parseMountsFromPath(const char *path)
|
|||||||
endmntent(file);
|
endmntent(file);
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::unordered_map<std::string, std::string> parseMountOptions(const std::string &input)
|
||||||
|
{
|
||||||
|
std::unordered_map<std::string, std::string> ret;
|
||||||
|
std::istringstream iss(input);
|
||||||
|
std::string token;
|
||||||
|
while (std::getline(iss, token, ','))
|
||||||
|
{
|
||||||
|
std::istringstream tokenStream(token);
|
||||||
|
std::string key, value;
|
||||||
|
|
||||||
|
if (std::getline(tokenStream, key, '='))
|
||||||
|
{
|
||||||
|
std::getline(tokenStream, value); // Put what's left in the stream to value, could be empty
|
||||||
|
ret[key] = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|||||||
90
module/jni/mountinfo_parser.cpp
Normal file
90
module/jni/mountinfo_parser.cpp
Normal file
@@ -0,0 +1,90 @@
|
|||||||
|
#include <string>
|
||||||
|
#include <sstream>
|
||||||
|
#include <fstream>
|
||||||
|
#include <vector>
|
||||||
|
#include <unordered_map>
|
||||||
|
|
||||||
|
#include "mountinfo_parser.hpp"
|
||||||
|
#include "mount_parser.hpp"
|
||||||
|
#include "logging.hpp"
|
||||||
|
|
||||||
|
mountinfo_entry_t::mountinfo_entry_t(int mount_id, int parent_id, int major, int minor,
|
||||||
|
const std::string &root, const std::string &mount_point,
|
||||||
|
const std::string &mount_options, const std::string &optional_fields,
|
||||||
|
const std::string &filesystem_type, const std::string &mount_source,
|
||||||
|
const std::string &super_options)
|
||||||
|
: mount_id(mount_id), parent_id(parent_id), major(major), minor(minor),
|
||||||
|
root(root), mount_point(mount_point),
|
||||||
|
optional_fields(optional_fields), filesystem_type(filesystem_type),
|
||||||
|
mount_source(mount_source)
|
||||||
|
{
|
||||||
|
this->mount_options = parseMountOptions(mount_options);
|
||||||
|
this->super_options = parseMountOptions(super_options);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int &mountinfo_entry_t::getMountId() const { return mount_id; }
|
||||||
|
const int &mountinfo_entry_t::getParentId() const { return parent_id; }
|
||||||
|
const int &mountinfo_entry_t::getMajor() const { return major; }
|
||||||
|
const int &mountinfo_entry_t::getMinor() const { return minor; }
|
||||||
|
const std::string &mountinfo_entry_t::getRoot() const { return root; }
|
||||||
|
const std::string &mountinfo_entry_t::getMountPoint() const { return mount_point; }
|
||||||
|
const std::unordered_map<std::string, std::string> &mountinfo_entry_t::getMountOptions() const { return mount_options; }
|
||||||
|
const std::string &mountinfo_entry_t::getOptionalFields() const { return optional_fields; }
|
||||||
|
const std::string &mountinfo_entry_t::getFilesystemType() const { return filesystem_type; }
|
||||||
|
const std::string &mountinfo_entry_t::getMountSource() const { return mount_source; }
|
||||||
|
const std::unordered_map<std::string, std::string> &mountinfo_entry_t::getSuperOptions() const { return super_options; }
|
||||||
|
|
||||||
|
std::vector<mountinfo_entry_t> parseMountinfosFromPath(const char *path)
|
||||||
|
{
|
||||||
|
std::vector<mountinfo_entry_t> ret;
|
||||||
|
|
||||||
|
std::ifstream ifs(path, std::ifstream::in);
|
||||||
|
if (!ifs)
|
||||||
|
{
|
||||||
|
LOGE("parseMountinfosFromPath could not open file \"%s\"", path);
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
for (std::string line; std::getline(ifs, line);)
|
||||||
|
{
|
||||||
|
std::istringstream iss(line);
|
||||||
|
|
||||||
|
int mount_id, parent_id, major, minor;
|
||||||
|
std::string root, mount_point, mount_options, optional_fields, filesystem_type, mount_source, super_options;
|
||||||
|
char colon;
|
||||||
|
|
||||||
|
// Read the first 6 fields (major, colon and minor are the same field)
|
||||||
|
iss >> mount_id >> parent_id >> major >> colon >> minor >> root >> mount_point >> mount_options;
|
||||||
|
if (iss.fail())
|
||||||
|
{
|
||||||
|
LOGE("parseMountinfosFromPath failed to parse the first 6 fields of line: %s", line.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string field;
|
||||||
|
while (iss >> field && field != "-")
|
||||||
|
{
|
||||||
|
optional_fields += " " + field;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (iss.fail())
|
||||||
|
{
|
||||||
|
LOGE("parseMountinfosFromPath failed to parse the optional fields of line: %s", line.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
iss >> filesystem_type >> mount_source >> super_options;
|
||||||
|
if (iss.fail())
|
||||||
|
{
|
||||||
|
LOGE("parseMountinfosFromPath failed to parse the last 3 fields of line: %s", line.c_str());
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
ret.emplace_back(mountinfo_entry_t(mount_id, parent_id, major, minor,
|
||||||
|
root, mount_point, mount_options,
|
||||||
|
optional_fields, filesystem_type, mount_source,
|
||||||
|
super_options));
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
@@ -7,21 +7,33 @@
|
|||||||
#include "zygisk.hpp"
|
#include "zygisk.hpp"
|
||||||
#include "logging.hpp"
|
#include "logging.hpp"
|
||||||
#include "mount_parser.hpp"
|
#include "mount_parser.hpp"
|
||||||
|
#include "mountinfo_parser.hpp"
|
||||||
|
|
||||||
constexpr std::array<const char *, 4> fsname_list = {"KSU", "APatch", "magisk", "worker"};
|
constexpr std::array<const char *, 4> fsname_list = {"KSU", "APatch", "magisk", "worker"};
|
||||||
|
|
||||||
static bool shouldUnmount(const mount_entry_t &info)
|
static bool shouldUnmount(const mountinfo_entry_t &mount_info)
|
||||||
{
|
{
|
||||||
const auto &mountPoint = info.getMountPoint();
|
const auto &root = mount_info.getRoot();
|
||||||
const auto &type = info.getType();
|
|
||||||
const auto &options = info.getOptions();
|
// Unmount all module bind mounts
|
||||||
|
if (root.rfind("/adb/modules", 0) == 0)
|
||||||
|
return true;
|
||||||
|
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool shouldUnmount(const mount_entry_t &mount)
|
||||||
|
{
|
||||||
|
const auto &mountPoint = mount.getMountPoint();
|
||||||
|
const auto &type = mount.getType();
|
||||||
|
const auto &options = mount.getOptions();
|
||||||
|
|
||||||
// Unmount everything mounted to /data/adb
|
// Unmount everything mounted to /data/adb
|
||||||
if (mountPoint.rfind("/data/adb", 0) == 0)
|
if (mountPoint.rfind("/data/adb", 0) == 0)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
// Unmount all module overlayfs and tmpfs
|
// Unmount all module overlayfs and tmpfs
|
||||||
bool doesFsnameMatch = std::find(fsname_list.begin(), fsname_list.end(), info.getFsName()) != fsname_list.end();
|
bool doesFsnameMatch = std::find(fsname_list.begin(), fsname_list.end(), mount.getFsName()) != fsname_list.end();
|
||||||
if ((type == "overlay" || type == "tmpfs") && doesFsnameMatch)
|
if ((type == "overlay" || type == "tmpfs") && doesFsnameMatch)
|
||||||
return true;
|
return true;
|
||||||
|
|
||||||
@@ -42,23 +54,28 @@ static bool shouldUnmount(const mount_entry_t &info)
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Unmount the bind mount of default Systemless Hosts module of Magisk
|
|
||||||
// It should've been an overlay instead but we'll make an exception for this one
|
|
||||||
// TODO: Maybe we can unmount all binds from userdata to system?
|
|
||||||
if (mountPoint == "/system/etc/hosts")
|
|
||||||
return true;
|
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
void do_unmount()
|
void do_unmount()
|
||||||
{
|
{
|
||||||
std::vector<std::string> mountPoints;
|
std::vector<std::string> mountPoints;
|
||||||
for (auto &info : parseMountsFromPath("/proc/self/mounts"))
|
|
||||||
|
// Check mounts first
|
||||||
|
for (auto &mount : parseMountsFromPath("/proc/self/mounts"))
|
||||||
{
|
{
|
||||||
if (shouldUnmount(info))
|
if (shouldUnmount(mount))
|
||||||
{
|
{
|
||||||
mountPoints.push_back(info.getMountPoint());
|
mountPoints.push_back(mount.getMountPoint());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Check mountinfos so that we can find bind mounts as well
|
||||||
|
for (auto &mount_info : parseMountinfosFromPath("/proc/self/mountinfo"))
|
||||||
|
{
|
||||||
|
if (shouldUnmount(mount_info))
|
||||||
|
{
|
||||||
|
mountPoints.push_back(mount_info.getMountPoint());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user