Move config path to /data/adb and /data/misc

This commit is contained in:
LoveSy 2020-11-30 22:51:48 +08:00 committed by solohsu
parent 8bde89c04c
commit baf1d6b6bb
15 changed files with 304 additions and 83 deletions

View File

@ -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

View File

@ -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();

View File

@ -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);
}

View File

@ -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};
}
}

View File

@ -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());
}
}
}

View File

@ -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

View File

@ -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());
}

View File

@ -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>();
};
}

View File

@ -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;"),
};

View File

@ -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"

View File

@ -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

View File

@ -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

View File

@ -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 }

View File

@ -25,5 +25,3 @@ if [[ "${REMOVE}" == true ]]; then
rm "/data/misc/riru/modules/edxp.prop"
fi
fi

View File

@ -2,7 +2,7 @@ package com.elderdrivers.riru.edxp.config;
public interface EdxpConfig {
String getInstallerConfigPath(String suffix);
String getConfigPath(String suffix);
String getDataPathPrefix();