Move config path to /data/adb and /data/misc
This commit is contained in:
parent
8bde89c04c
commit
baf1d6b6bb
|
|
@ -5,8 +5,8 @@ import android.text.TextUtils;
|
|||
public class BaseEdxpConfig implements EdxpConfig {
|
||||
|
||||
@Override
|
||||
public String getInstallerConfigPath(String suffix) {
|
||||
return ConfigManager.getInstallerConfigPath(suffix != null ? suffix : "");
|
||||
public String getConfigPath(String suffix) {
|
||||
return ConfigManager.getConfigPath(suffix != null ? suffix : "");
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ public class ConfigManager {
|
|||
&& (result = compatModeCache.get(packageName)) != null) {
|
||||
return result;
|
||||
}
|
||||
result = isFileExists(getInstallerConfigPath("compatlist/" + packageName));
|
||||
result = isFileExists(getConfigPath("compatlist/" + packageName));
|
||||
compatModeCache.put(packageName, result);
|
||||
return result;
|
||||
}
|
||||
|
|
@ -41,7 +41,9 @@ public class ConfigManager {
|
|||
|
||||
public static native String getLibSandHookName();
|
||||
|
||||
public static native String getInstallerConfigPath(String suffix);
|
||||
public static native String getConfigPath(String suffix);
|
||||
|
||||
public static native String getBaseConfigPath();
|
||||
|
||||
public static native String getDataPathPrefix();
|
||||
|
||||
|
|
|
|||
|
|
@ -1,5 +1,8 @@
|
|||
package com.elderdrivers.riru.edxp.hooker;
|
||||
|
||||
import android.app.AndroidAppHelper;
|
||||
import android.view.View;
|
||||
|
||||
import com.elderdrivers.riru.edxp.config.ConfigManager;
|
||||
import com.elderdrivers.riru.edxp.util.Utils;
|
||||
|
||||
|
|
@ -16,7 +19,7 @@ public class XposedInstallerHooker {
|
|||
|
||||
private static final String LEGACY_INSTALLER_PACKAGE_NAME = "de.robv.android.xposed.installer";
|
||||
|
||||
public static void hookXposedInstaller(ClassLoader classLoader) {
|
||||
public static void hookXposedInstaller(final ClassLoader classLoader) {
|
||||
try {
|
||||
final String xposedAppClass = LEGACY_INSTALLER_PACKAGE_NAME + ".XposedApp";
|
||||
final Class InstallZipUtil = XposedHelpers.findClass(LEGACY_INSTALLER_PACKAGE_NAME
|
||||
|
|
@ -66,6 +69,31 @@ public class XposedInstallerHooker {
|
|||
}
|
||||
}
|
||||
});
|
||||
XposedHelpers.findAndHookMethod("org.meowcat.edxposed.manager.XposedApp", classLoader, "onCreate", new XC_MethodHook() {
|
||||
@Override
|
||||
protected void afterHookedMethod(MethodHookParam param) throws Throwable {
|
||||
XposedHelpers.setStaticObjectField(param.thisObject.getClass(), "BASE_DIR", ConfigManager.getBaseConfigPath() + "/");
|
||||
XposedHelpers.setStaticObjectField(param.thisObject.getClass(), "ENABLED_MODULES_LIST_FILE", ConfigManager.getConfigPath("enabled_modules.list"));
|
||||
}
|
||||
});
|
||||
XposedHelpers.findAndHookMethod("org.meowcat.edxposed.manager.util.ModuleUtil", classLoader, "updateModulesList", boolean.class, View.class, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
||||
final Object thisObject = param.thisObject;
|
||||
synchronized (thisObject) {
|
||||
XposedHelpers.setStaticObjectField(param.thisObject.getClass(), "MODULES_LIST_FILE", ConfigManager.getConfigPath("modules.list"));
|
||||
}
|
||||
}
|
||||
});
|
||||
XposedHelpers.findAndHookMethod("org.meowcat.edxposed.manager.StatusInstallerFragment", classLoader, "getCanonicalFile", File.class, new XC_MethodHook() {
|
||||
@Override
|
||||
protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
|
||||
File arg = (File)param.args[0];
|
||||
if(arg.equals(new File(AndroidAppHelper.currentApplicationInfo().deviceProtectedDataDir))) {
|
||||
param.args[0] = new File(ConfigManager.getBaseConfigPath());
|
||||
}
|
||||
}
|
||||
});
|
||||
} catch (Throwable t) {
|
||||
Utils.logE("Could not hook Xposed Installer", t);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -6,8 +6,9 @@
|
|||
#include <string>
|
||||
#include <filesystem>
|
||||
#include <sys/system_properties.h>
|
||||
#include <unistd.h>
|
||||
#include <sys/stat.h>
|
||||
#include "logging.h"
|
||||
#include <sys/system_properties.h>
|
||||
|
||||
namespace edxp {
|
||||
|
||||
|
|
@ -31,9 +32,24 @@ namespace edxp {
|
|||
}
|
||||
}
|
||||
|
||||
static inline int32_t GetAndroidApiLevel() {
|
||||
char prop_value[PROP_VALUE_MAX];
|
||||
__system_property_get("ro.build.version.sdk", prop_value);
|
||||
return std::atoi(prop_value);
|
||||
inline void path_chown(const std::filesystem::path &path, uid_t uid, gid_t gid, bool recursively=false) {
|
||||
if (chown(path.c_str(), uid, gid) != 0) {
|
||||
throw std::filesystem::filesystem_error(strerror(errno), path,
|
||||
{errno, std::system_category()});
|
||||
}
|
||||
if(recursively) {
|
||||
for(const auto &item : std::filesystem::recursive_directory_iterator(path)) {
|
||||
if (chown(item.path().c_str(), uid, gid) != 0) {
|
||||
throw std::filesystem::filesystem_error(strerror(errno), item.path(),
|
||||
{errno, std::system_category()});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
inline std::tuple<uid_t, gid_t> path_own(const std::filesystem::path& path) {
|
||||
struct stat sb;
|
||||
stat(path.c_str(), &sb);
|
||||
return {sb.st_uid, sb.st_gid};
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -20,23 +20,96 @@
|
|||
#include "config_manager.h"
|
||||
#include "utils.h"
|
||||
|
||||
/*
|
||||
* Logic:
|
||||
* check if /data/adb/edxp exists and is readable, if so, read misc_path and the config base path is
|
||||
* /data/misc/$misc_path; if not so, fall back to the installer's path
|
||||
* config manager is const. and it should be updated if the module list is updated
|
||||
* each user owns one config manager
|
||||
* before the process started, update current user
|
||||
* module list and modules scopes are preloaded
|
||||
* can get app module list by call a const function
|
||||
* for installer's pkg name, it's retrieved by /data/misc/$misc_path/$uid/conf/installer.
|
||||
* if not exists, fallback
|
||||
* blacklist and whitelist are instead set by blacklist.conf and whitelist.conf respectively
|
||||
* dynamic mode is always on
|
||||
*
|
||||
* Permission:
|
||||
* /data/adb/edxp should be accessible by zygote by sepolicy
|
||||
* /data/misc/$misc_path is random path, and mounted by magisk
|
||||
* it should have context `u:object_r:shell_data_file:s0`, which should be readable by normal app
|
||||
* and zygote
|
||||
*
|
||||
* /data/misc/$misc_path's owner should be root:root, with permission 771
|
||||
* so does /data/misc/$misc_path/$uid
|
||||
* /data/misc/$misc_path/$uid/conf should be um:root, with permission 770
|
||||
* where um is the user of manager
|
||||
* /data/misc/$misc_path/$uid/prefs should be root:root, with permission 771
|
||||
* /data/misc/$misc_path/$uid/prefs/$pkg should be up:root, with permission 771
|
||||
* this path is used for XSharePreference, where up is the user of package $pkg
|
||||
* other's permission is 5 because it should be read by all the other apps but not writable
|
||||
* it's only writeable by $pkg itself
|
||||
* root group's 7 permission's for updating the permission & deleting it
|
||||
*
|
||||
* Initialization:
|
||||
* This is only done for config path in /data/misc
|
||||
* check if /data/misc/$misc_path/$uid exists. if not create one with 771
|
||||
* check if /data/misc/$misc_path/$uid/conf exists. if not create one with 770
|
||||
* check if /data/misc/$misc_path/$uid/prefs exists. if not create one with 771
|
||||
*
|
||||
*
|
||||
* when the launching app is installer, change the user owner of /data/misc/$misc_path/$uid/conf
|
||||
* to be the installer, and change the permission to be 770
|
||||
*
|
||||
* when the launching app is in the module lists, ensure existence of
|
||||
* /data/misc/$misc_path/$uid/prefs/$pkg
|
||||
* with the owner the user of the pkg and permission 774
|
||||
* if this paths exists but with different owner, delete it recursively and create a new one
|
||||
* this is when package reinstalled
|
||||
* but I heard that some devices change uid when upgrading system, so I didn't do this
|
||||
*
|
||||
* Side effect:
|
||||
* data exists if the module uninstalled
|
||||
* One way to release the storage space is to uninstall edxp
|
||||
* because /data/misc/$misc_path is mounted by magisk.
|
||||
*
|
||||
* edxp works without manager
|
||||
*
|
||||
* uninstall removes all configs (this can be restored if manager store another copy
|
||||
* of the conf on its own data dir)
|
||||
*
|
||||
*/
|
||||
namespace edxp {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
fs::path ConfigManager::RetrieveBaseConfigPath() const {
|
||||
fs::path misc_path("/data/adb/edxp/misc_path");
|
||||
if (path_exists(misc_path)) {
|
||||
std::ifstream ifs(misc_path);
|
||||
if (ifs.good()) {
|
||||
return fs::path("/data/misc") /
|
||||
std::string{std::istream_iterator<char>(ifs),
|
||||
std::istream_iterator<char>()} /
|
||||
std::to_string(user_);
|
||||
}
|
||||
}
|
||||
LOGW("fallback because %s is not accessible", misc_path.c_str());
|
||||
return data_path_prefix_ / kPrimaryInstallerPkgName;
|
||||
}
|
||||
|
||||
std::string ConfigManager::RetrieveInstallerPkgName() const {
|
||||
std::string data_test_path = data_path_prefix_ / kPrimaryInstallerPkgName;
|
||||
if (path_exists(data_test_path, true)) {
|
||||
LOGI("using installer %s", kPrimaryInstallerPkgName.c_str());
|
||||
std::string installer_pkg_name_path = GetConfigPath("installer");
|
||||
if (!path_exists(installer_pkg_name_path, true)) {
|
||||
LOGW("installer not set, using default one %s", kPrimaryInstallerPkgName.c_str());
|
||||
return kPrimaryInstallerPkgName;
|
||||
}
|
||||
data_test_path = data_path_prefix_ / kLegacyInstallerPkgName;
|
||||
if (path_exists(data_test_path, true)) {
|
||||
LOGI("using installer %s", kLegacyInstallerPkgName.c_str());
|
||||
return kLegacyInstallerPkgName;
|
||||
std::ifstream ifs(installer_pkg_name_path);
|
||||
if (!ifs.good()) {
|
||||
LOGW("cannot access %s, using default one %s", installer_pkg_name_path.c_str(),
|
||||
kPrimaryInstallerPkgName.c_str());
|
||||
return kPrimaryInstallerPkgName;
|
||||
}
|
||||
LOGE("no supported installer app found, using default: %s",
|
||||
kPrimaryInstallerPkgName.c_str());
|
||||
return kPrimaryInstallerPkgName;
|
||||
return {std::istream_iterator<char>(ifs), std::istream_iterator<char>()};
|
||||
}
|
||||
|
||||
std::unordered_set<std::string> ConfigManager::GetAppList(const fs::path &dir) {
|
||||
|
|
@ -63,21 +136,17 @@ namespace edxp {
|
|||
|
||||
// TODO ignore unrelated processes
|
||||
bool ConfigManager::IsAppNeedHook(const std::string &package_name) const {
|
||||
if (!black_list_enable_ && !white_list_enable_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (package_name == installer_pkg_name_) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (white_list_enable_) {
|
||||
auto res = white_list_.count(package_name);
|
||||
LOGD("using whitelist, %s -> %d", package_name.c_str(), res);
|
||||
LOGD("using whitelist, %s -> %s", package_name.c_str(), BoolToString(res));
|
||||
return res;
|
||||
} else {
|
||||
auto res = black_list_.count(package_name);
|
||||
LOGD("using blacklist, %s -> %d", package_name.c_str(), res);
|
||||
LOGD("using blacklist, %s -> %s", package_name.c_str(), BoolToString(res));
|
||||
return res;
|
||||
}
|
||||
}
|
||||
|
|
@ -86,27 +155,46 @@ namespace edxp {
|
|||
user_(user),
|
||||
data_path_prefix_(fs::path(use_prot_storage_ ? "/data/user_de" : "/data/user") /
|
||||
std::to_string(user_)),
|
||||
base_config_path_(RetrieveBaseConfigPath()),
|
||||
initialized_(InitConfigPath()),
|
||||
installer_pkg_name_(RetrieveInstallerPkgName()),
|
||||
black_list_enable_(path_exists(GetConfigPath("blacklist"))),
|
||||
white_list_enable_(path_exists(GetConfigPath("whiltelist"))),
|
||||
white_list_enable_(path_exists(GetConfigPath("usewhitelist"))),
|
||||
deopt_boot_image_enabled_(path_exists(GetConfigPath("deoptbootimage"))),
|
||||
no_module_log_enabled_(path_exists(GetConfigPath("disable_modules_log"))),
|
||||
resources_hook_enabled_(path_exists(GetConfigPath("enable_resources"))),
|
||||
hidden_api_bypass_enabled_(!path_exists(GetConfigPath("disable_hidden_api_bypass"))),
|
||||
white_list_(white_list_enable_ ? GetAppList(GetConfigPath("whitelist/"))
|
||||
: std::unordered_set<std::string>{}),
|
||||
black_list_(black_list_enable_ ? GetAppList(GetConfigPath("blacklist/"))
|
||||
: std::unordered_set<std::string>{}),
|
||||
white_list_(GetAppList(GetConfigPath("whitelist/"))),
|
||||
black_list_(GetAppList(GetConfigPath("blacklist/"))),
|
||||
modules_list_(GetModuleList()),
|
||||
last_write_time_(GetLastWriteTime()){
|
||||
last_write_time_(GetLastWriteTime()) {
|
||||
// use_white_list snapshot
|
||||
LOGI("data path prefix: %s", data_path_prefix_.c_str());
|
||||
LOGI(" using blacklist: %s", BoolToString(black_list_enable_));
|
||||
LOGI("base config path: %s", base_config_path_.c_str());
|
||||
LOGI(" using installer package name: %s", installer_pkg_name_.c_str());
|
||||
LOGI(" using whitelist: %s", BoolToString(white_list_enable_));
|
||||
LOGI(" resources hook: %s", BoolToString(resources_hook_enabled_));
|
||||
LOGI(" deopt boot image: %s", BoolToString(deopt_boot_image_enabled_));
|
||||
LOGI(" no module log: %s", BoolToString(no_module_log_enabled_));
|
||||
LOGI(" hidden api bypass: %s", BoolToString(hidden_api_bypass_enabled_));
|
||||
LOGI(" resources hook: %s", BoolToString(resources_hook_enabled_));
|
||||
LOGI(" white list: \n %s", ([this]() {
|
||||
std::ostringstream join;
|
||||
std::copy(white_list_.begin(), white_list_.end(),
|
||||
std::ostream_iterator<std::string>(join, "\n"));
|
||||
return join.str();
|
||||
})().c_str());
|
||||
LOGI(" black list: \n %s", ([this]() {
|
||||
std::ostringstream join;
|
||||
std::copy(black_list_.begin(), black_list_.end(),
|
||||
std::ostream_iterator<std::string>(join, "\n"));
|
||||
return join.str();
|
||||
})().c_str());
|
||||
LOGI(" module list: \n %s", ([this]() {
|
||||
std::ostringstream join;
|
||||
std::vector<std::string> module_list;
|
||||
std::transform(modules_list_.begin(), modules_list_.end(),
|
||||
std::back_inserter(module_list),
|
||||
[](auto i) { return i.first; });
|
||||
std::copy(module_list.begin(), module_list.end(),
|
||||
std::ostream_iterator<std::string>(join, "\n"));
|
||||
return join.str();
|
||||
})().c_str());
|
||||
}
|
||||
|
||||
auto ConfigManager::GetModuleList() -> std::remove_const_t<decltype(modules_list_)> {
|
||||
|
|
@ -124,7 +212,8 @@ namespace edxp {
|
|||
std::string module;
|
||||
while (std::getline(ifs, module)) {
|
||||
const auto &module_pkg_name = GetPackageNameFromBaseApkPath(module);
|
||||
modules_list.emplace_back(std::move(module), std::unordered_set<std::string>{});
|
||||
auto &[module_path, scope] = modules_list[module_pkg_name];
|
||||
module_path.assign(std::move(module));
|
||||
const auto &module_scope_conf = GetConfigPath(module_pkg_name + ".conf");
|
||||
if (!path_exists(module_scope_conf, true)) {
|
||||
LOGD("module scope is not set for %s", module_pkg_name.c_str());
|
||||
|
|
@ -135,17 +224,16 @@ namespace edxp {
|
|||
LOGE("Cannot access path %s", module_scope_conf.c_str());
|
||||
continue;
|
||||
}
|
||||
auto &scope = modules_list.back().second;
|
||||
std::string app_pkg_name;
|
||||
while (std::getline(ifs_c, app_pkg_name)) {
|
||||
if (!app_pkg_name.empty())
|
||||
scope.emplace(std::move(app_pkg_name));
|
||||
}
|
||||
scope.insert(module_pkg_name); // Always add module itself
|
||||
LOGD("scope of %s is:\n%s", module_pkg_name.c_str(), ([&scope]() {
|
||||
LOGD("scope of %s is:\n%s", module_pkg_name.c_str(), ([&scope = scope]() {
|
||||
std::ostringstream join;
|
||||
std::copy(scope.begin(), scope.end(),
|
||||
std::ostream_iterator<std::string>(join, "\n"));
|
||||
std::ostream_iterator<std::string>(join, "\n "));
|
||||
return join.str();
|
||||
})().c_str());
|
||||
}
|
||||
|
|
@ -155,16 +243,81 @@ namespace edxp {
|
|||
std::vector<std::string> ConfigManager::GetAppModuleList(const std::string &pkg_name) const {
|
||||
std::vector<std::string> app_modules_list;
|
||||
for (const auto&[module, scope]: modules_list_) {
|
||||
if (scope.empty() || scope.count(pkg_name)) app_modules_list.push_back(module);
|
||||
if (scope.second.empty() || scope.second.count(pkg_name))
|
||||
app_modules_list.push_back(scope.first);
|
||||
}
|
||||
return app_modules_list;
|
||||
}
|
||||
|
||||
std::filesystem::file_time_type ConfigManager::GetLastWriteTime() const {
|
||||
auto dynamic_path = GetConfigPath("dynamic");
|
||||
if (!path_exists(dynamic_path, true))
|
||||
auto modules_list = GetConfigPath("modules.list");
|
||||
if (!path_exists(modules_list, true))
|
||||
return {};
|
||||
return fs::last_write_time(dynamic_path);
|
||||
return fs::last_write_time(modules_list);
|
||||
}
|
||||
|
||||
bool ConfigManager::InitConfigPath() const {
|
||||
if (base_config_path_.string().rfind("/data/misc") != 0) return true;
|
||||
try {
|
||||
fs::create_directories(base_config_path_);
|
||||
fs::permissions(base_config_path_.parent_path(),
|
||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
||||
fs::permissions(base_config_path_,
|
||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
||||
fs::create_directories(GetLogPath());
|
||||
fs::permissions(GetLogPath(),
|
||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
||||
fs::create_directories(GetConfigPath());
|
||||
fs::permissions(GetConfigPath(), fs::perms::owner_all | fs::perms::group_all);
|
||||
fs::create_directories(GetPrefsPath(""));
|
||||
fs::permissions(GetPrefsPath(""),
|
||||
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_exec);
|
||||
} catch (const fs::filesystem_error &e) {
|
||||
LOGE("init: %s", e.what());
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
void ConfigManager::EnsurePermission(const std::string &pkg_name, uid_t uid) const {
|
||||
if (!initialized_) return;
|
||||
try {
|
||||
if (modules_list_.count(pkg_name)) {
|
||||
auto prefs_path = GetPrefsPath(pkg_name);
|
||||
if (!path_exists(prefs_path, true)) {
|
||||
fs::create_directories(prefs_path);
|
||||
} else {
|
||||
const auto &[r_uid, r_gid] = path_own(prefs_path);
|
||||
if (r_uid != uid) {
|
||||
fs::remove_all(prefs_path);
|
||||
fs::create_directories(prefs_path);
|
||||
}
|
||||
}
|
||||
fs::permissions(prefs_path, fs::perms::owner_all | fs::perms::group_all |
|
||||
fs::perms::others_exec);
|
||||
path_chown(prefs_path, uid, 0);
|
||||
}
|
||||
if (pkg_name == installer_pkg_name_) {
|
||||
auto conf_path = GetConfigPath();
|
||||
if (!path_exists(conf_path, true)) {
|
||||
fs::create_directories(conf_path);
|
||||
}
|
||||
auto log_path = GetLogPath();
|
||||
if (!path_exists(log_path, true)) {
|
||||
fs::create_directories(log_path);
|
||||
}
|
||||
fs::permissions(conf_path, fs::perms::owner_all | fs::perms::group_all);
|
||||
fs::permissions(log_path, fs::perms::owner_all | fs::perms::group_all);
|
||||
if (const auto &[r_uid, r_gid] = path_own(conf_path); r_uid != uid) {
|
||||
path_chown(conf_path, uid, 0, true);
|
||||
}
|
||||
if (const auto &[r_uid, r_gid] = path_own(log_path); r_uid != uid) {
|
||||
path_chown(log_path, uid, 0, true);
|
||||
}
|
||||
}
|
||||
} catch (const fs::filesystem_error &e) {
|
||||
LOGE("%s", e.what());
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
|
@ -15,7 +15,6 @@
|
|||
namespace edxp {
|
||||
|
||||
static const std::string kPrimaryInstallerPkgName = "org.meowcat.edxposed.manager";
|
||||
static const std::string kLegacyInstallerPkgName = "de.robv.android.xposed.installer";
|
||||
static const std::string kXposedPropPath = "/system/framework/edconfig.jar";
|
||||
|
||||
class ConfigManager {
|
||||
|
|
@ -26,7 +25,7 @@ namespace edxp {
|
|||
|
||||
inline static void SetCurrentUser(uid_t user) {
|
||||
if (auto instance = instances_.find(user);
|
||||
!instance->second || instance->second->NeedUpdateConfig()) {
|
||||
instance == instances_.end() || !instance->second || instance->second->NeedUpdateConfig()) {
|
||||
instances_[user] = std::make_unique<ConfigManager>(user);
|
||||
}
|
||||
}
|
||||
|
|
@ -35,9 +34,8 @@ namespace edxp {
|
|||
return std::move(instances_);
|
||||
}
|
||||
|
||||
inline auto IsBlackWhiteListEnabled() const {
|
||||
return black_list_enable_ || white_list_enable_;
|
||||
}
|
||||
// Always true now
|
||||
inline auto IsBlackWhiteListEnabled() const { return true; }
|
||||
|
||||
inline auto IsResourcesHookEnabled() const { return resources_hook_enabled_; }
|
||||
|
||||
|
|
@ -45,8 +43,6 @@ namespace edxp {
|
|||
|
||||
inline auto IsNoModuleLogEnabled() const { return no_module_log_enabled_; }
|
||||
|
||||
inline auto IsHiddenAPIBypassEnabled() const { return hidden_api_bypass_enabled_; }
|
||||
|
||||
inline auto GetInstallerPackageName() const { return installer_pkg_name_; }
|
||||
|
||||
inline auto GetXposedPropPath() const { return kXposedPropPath; }
|
||||
|
|
@ -55,8 +51,18 @@ namespace edxp {
|
|||
|
||||
inline auto GetDataPathPrefix() const { return data_path_prefix_; }
|
||||
|
||||
inline auto GetConfigPath(const std::string &suffix) const {
|
||||
return data_path_prefix_ / installer_pkg_name_ / "conf" / suffix;
|
||||
inline auto GetConfigPath(const std::string &suffix = {}) const {
|
||||
return base_config_path_ / "conf" / suffix;
|
||||
}
|
||||
|
||||
inline auto GetLogPath(const std::string &suffix = {}) const {
|
||||
return base_config_path_ / "log" / suffix;
|
||||
}
|
||||
|
||||
inline auto GetBaseConfigPath() const { return base_config_path_; }
|
||||
|
||||
inline auto GetPrefsPath(const std::string &pkg_name) const {
|
||||
return base_config_path_ / "prefs" / pkg_name;
|
||||
}
|
||||
|
||||
std::vector<std::string> GetAppModuleList(const std::string &pkg_name) const;
|
||||
|
|
@ -67,26 +73,27 @@ namespace edxp {
|
|||
return last_write_time_ < GetLastWriteTime();
|
||||
}
|
||||
|
||||
void EnsurePermission(const std::string &pkg_name, uid_t uid) const;
|
||||
|
||||
private:
|
||||
inline static std::unordered_map<uid_t, std::unique_ptr<ConfigManager>> instances_{};
|
||||
inline static uid_t current_user = 0u;
|
||||
inline static bool use_prot_storage_ = GetAndroidApiLevel() >= __ANDROID_API_N__;
|
||||
inline static const bool use_prot_storage_ = GetAndroidApiLevel() >= __ANDROID_API_N__;
|
||||
|
||||
const uid_t user_;
|
||||
const std::filesystem::path data_path_prefix_;
|
||||
const std::filesystem::path base_config_path_;
|
||||
const bool initialized_ = false;
|
||||
const std::filesystem::path installer_pkg_name_;
|
||||
const bool black_list_enable_ = false;
|
||||
const bool white_list_enable_ = false;
|
||||
const bool deopt_boot_image_enabled_ = false;
|
||||
const bool no_module_log_enabled_ = false;
|
||||
const bool resources_hook_enabled_ = false;
|
||||
const bool hidden_api_bypass_enabled_ = false;
|
||||
// snapshot at boot
|
||||
const std::unordered_set<std::string> white_list_;
|
||||
const std::unordered_set<std::string> black_list_;
|
||||
|
||||
const std::vector<std::pair<std::string, std::unordered_set<std::string>>> modules_list_;
|
||||
const std::unordered_map<std::string, std::pair<std::string, std::unordered_set<std::string>>> modules_list_;
|
||||
|
||||
const std::filesystem::file_time_type last_write_time_;
|
||||
|
||||
|
|
@ -102,8 +109,11 @@ namespace edxp {
|
|||
|
||||
std::filesystem::file_time_type GetLastWriteTime() const;
|
||||
|
||||
bool InitConfigPath() const;
|
||||
|
||||
friend std::unique_ptr<ConfigManager> std::make_unique<ConfigManager>(uid_t &);
|
||||
|
||||
std::filesystem::path RetrieveBaseConfigPath() const;
|
||||
};
|
||||
|
||||
} // namespace edxp
|
||||
|
|
|
|||
|
|
@ -1,4 +1,3 @@
|
|||
|
||||
#include <jni.h>
|
||||
#include <android-base/macros.h>
|
||||
#include <JNIHelper.h>
|
||||
|
|
@ -354,6 +353,7 @@ namespace edxp {
|
|||
ConfigManager::SetCurrentUser(user);
|
||||
app_modules_list_ = ConfigManager::GetInstance()->GetAppModuleList(package_name);
|
||||
skip_ = ShouldSkipInject(package_name, user, uid, res, app_modules_list_, is_child_zygote);
|
||||
ConfigManager::GetInstance()->EnsurePermission(package_name, uid % PER_USER_RANGE);
|
||||
app_data_dir_ = app_data_dir;
|
||||
nice_name_ = nice_name;
|
||||
PreLoadDex(env, kInjectDexPath);
|
||||
|
|
@ -372,7 +372,7 @@ namespace edxp {
|
|||
res, app_data_dir_, nice_name_);
|
||||
LOGD("injected xposed into %s", process_name.get());
|
||||
} else {
|
||||
auto config_manager = ConfigManager::ReleaseInstances();
|
||||
[[maybe_unused]] auto config_manager = ConfigManager::ReleaseInstances();
|
||||
auto context = Context::ReleaseInstance();
|
||||
LOGD("skipped %s", process_name.get());
|
||||
}
|
||||
|
|
|
|||
|
|
@ -121,7 +121,6 @@ namespace edxp {
|
|||
static std::tuple<bool, uid_t, std::string> GetAppInfoFromDir(JNIEnv *env, jstring dir);
|
||||
|
||||
friend std::unique_ptr<Context> std::make_unique<Context>();
|
||||
|
||||
};
|
||||
|
||||
}
|
||||
|
|
|
|||
|
|
@ -39,12 +39,16 @@ namespace edxp {
|
|||
return env->NewStringUTF(ConfigManager::GetInstance()->GetDataPathPrefix().c_str());
|
||||
}
|
||||
|
||||
static jstring ConfigManager_getInstallerConfigPath(JNI_START, jstring jSuffix) {
|
||||
static jstring ConfigManager_getConfigPath(JNI_START, jstring jSuffix) {
|
||||
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
|
||||
auto result = ConfigManager::GetInstance()->GetConfigPath(suffix);
|
||||
env->ReleaseStringUTFChars(jSuffix, suffix);
|
||||
return env->NewStringUTF(result.c_str());
|
||||
}
|
||||
|
||||
static jstring ConfigManager_getBaseConfigPath(JNI_START) {
|
||||
auto result = ConfigManager::GetInstance()->GetBaseConfigPath();
|
||||
return env->NewStringUTF(result.c_str());
|
||||
}
|
||||
|
||||
static jstring ConfigManager_getModulesList(JNI_START) {
|
||||
|
|
@ -65,8 +69,9 @@ namespace edxp {
|
|||
NATIVE_METHOD(ConfigManager, getXposedPropPath, "()Ljava/lang/String;"),
|
||||
NATIVE_METHOD(ConfigManager, getLibSandHookName, "()Ljava/lang/String;"),
|
||||
NATIVE_METHOD(ConfigManager, getDataPathPrefix, "()Ljava/lang/String;"),
|
||||
NATIVE_METHOD(ConfigManager, getInstallerConfigPath,
|
||||
NATIVE_METHOD(ConfigManager, getConfigPath,
|
||||
"(Ljava/lang/String;)Ljava/lang/String;"),
|
||||
NATIVE_METHOD(ConfigManager, getBaseConfigPath,"()Ljava/lang/String;"),
|
||||
NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"),
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -11,11 +11,12 @@
|
|||
#include <utility>
|
||||
#include <string>
|
||||
#include <android-base/logging.h>
|
||||
#include "native_hook.h"
|
||||
#include "logging.h"
|
||||
#include "config.h"
|
||||
#include "edxp_context.h"
|
||||
#include "riru.h"
|
||||
#include "config_manager.h"
|
||||
#include "native_hook.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-value"
|
||||
|
|
|
|||
|
|
@ -353,6 +353,22 @@ cp "${MODPATH}/module.prop" "${RIRU_TARGET}/module.prop" || abort "! Can't creat
|
|||
|
||||
set_perm_recursive "${MODPATH}" 0 0 0755 0644
|
||||
|
||||
ui_print "- Creating configuration directories"
|
||||
if [[ -f /data/adb/edxp/misc_path ]]; then
|
||||
MISC_PATH=$(cat /data/adb/edxp/misc_path)
|
||||
ui_print "- Use previous path $MISC_PATH"
|
||||
else
|
||||
MISC_PATH="edxp_$(tr -cd 'A-Za-z0-9' < /dev/urandom | head -c16)"
|
||||
ui_print "- Use new path $MISC_PATH"
|
||||
mkdir -p /data/adb/edxp || abort "! Can't create adb path"
|
||||
echo "$MISC_PATH" > /data/adb/edxp/misc_path || abort "! Can't store configuration path"
|
||||
fi
|
||||
set_perm_recursive /data/adb/edxp root root 0700 0600 "u:object_r:magisk_file:s0" || abort "! Can't set permission"
|
||||
mkdir -p /data/misc/$MISC_PATH || abort "! Can't create configuration path"
|
||||
set_perm /data/misc/$MISC_PATH root root 0771 "u:object_r:magisk_file:s0" || abort "! Can't set permission"
|
||||
echo "rm -rf /data/misc/$MISC_PATH" >> "$MODPATH/uninstall.sh" || abort "! Can't write uninstall.sh"
|
||||
echo "rm -rf /data/adb/edxp" >> "$MODPATH/uninstall.sh" || abort "! Can't write uninstall.sh"
|
||||
|
||||
ui_print "- Welcome to EdXposed ${VERSION}!"
|
||||
|
||||
# before Magisk 16e4c67, sepolicy.rule is copied on the second reboot
|
||||
|
|
|
|||
|
|
@ -35,9 +35,9 @@ RIRU_APICODE=$(cat "${RIRU_PATH}/api_version")
|
|||
MAGISK_VERSION=$(su -v)
|
||||
MAGISK_VERCODE=$(su -V)
|
||||
|
||||
EDXP_MANAGER="org.meowcat.edxposed.manager"
|
||||
XP_INSTALLER="de.robv.android.xposed.installer"
|
||||
PATH_PREFIX="/data/user_de/0/"
|
||||
#EDXP_MANAGER="org.meowcat.edxposed.manager"
|
||||
#XP_INSTALLER="de.robv.android.xposed.installer"
|
||||
#PATH_PREFIX="/data/user_de/0/"
|
||||
#PATH_PREFIX_LEGACY="/data/user/0/"
|
||||
|
||||
sepolicy() {
|
||||
|
|
@ -55,14 +55,7 @@ sepolicy() {
|
|||
#fi
|
||||
|
||||
DEFAULT_BASE_PATH="${PATH_PREFIX}${EDXP_MANAGER}"
|
||||
BASE_PATH="${DEFAULT_BASE_PATH}"
|
||||
|
||||
if [[ ! -d ${BASE_PATH} ]]; then
|
||||
BASE_PATH="${PATH_PREFIX}${XP_INSTALLER}"
|
||||
if [[ ! -d ${BASE_PATH} ]]; then
|
||||
BASE_PATH="${DEFAULT_BASE_PATH}"
|
||||
fi
|
||||
fi
|
||||
BASE_PATH="/data/misc/$(cat /data/adb/edxp/misc_path)/0"
|
||||
|
||||
LOG_PATH="${BASE_PATH}/log"
|
||||
CONF_PATH="${BASE_PATH}/conf"
|
||||
|
|
@ -165,8 +158,8 @@ start_log_cather all "EdXposed:V XSharedPreferences:V EdXposed-Bridge:V EdXposed
|
|||
start_log_cather error "XSharedPreferences:V EdXposed-Bridge:V" true true
|
||||
|
||||
|
||||
if [[ -f "/data/misc/riru/modules/edxp.prop" ]]; then
|
||||
CONFIG=$(cat "/data/misc/riru/modules/edxp.prop")
|
||||
if [[ -f "/data/adb/riru/modules/edxp.prop" ]]; then
|
||||
CONFIG=$(cat "/data/adb/riru/modules/edxp.prop")
|
||||
[[ -d "${TARGET}/${CONFIG}" ]] || mkdir -p "${TARGET}/${CONFIG}"
|
||||
cp "${MODDIR}/module.prop" "${TARGET}/${CONFIG}/module.prop"
|
||||
fi
|
||||
|
|
|
|||
|
|
@ -1,4 +1,4 @@
|
|||
allow system_server system_server process execmem
|
||||
allow system_server system_server memprotect mmap_zero
|
||||
allow zygote app_data_file dir { getattr search read open }
|
||||
allow zygote app_data_file file { getattr read open }
|
||||
# TODO: use rirud
|
||||
allow zygote adb_data_file file { getattr read }
|
||||
|
|
|
|||
|
|
@ -25,5 +25,3 @@ if [[ "${REMOVE}" == true ]]; then
|
|||
rm "/data/misc/riru/modules/edxp.prop"
|
||||
fi
|
||||
fi
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -2,7 +2,7 @@ package com.elderdrivers.riru.edxp.config;
|
|||
|
||||
public interface EdxpConfig {
|
||||
|
||||
String getInstallerConfigPath(String suffix);
|
||||
String getConfigPath(String suffix);
|
||||
|
||||
String getDataPathPrefix();
|
||||
|
||||
|
|
|
|||
Loading…
Reference in New Issue