[core] Delete native config manager

This commit is contained in:
LoveSy 2021-02-16 20:09:51 +08:00 committed by tehcneko
parent 2890aec54f
commit 374c8cac11
53 changed files with 403 additions and 1273 deletions

View File

@ -3,9 +3,17 @@ package io.github.lsposed.lspd.service;
interface ILSPApplicationService { interface ILSPApplicationService {
void registerHeartBeat(IBinder handle) = 1; void registerHeartBeat(IBinder handle) = 1;
int getVariant() = 2; IBinder requestModuleBinder() = 2;
IBinder requestModuleBinder() = 3; IBinder requestManagerBinder() = 3;
IBinder requestManagerBinder() = 4; int getVariant() = 4;
boolean isResourcesHookEnabled() = 5;
List<String> getModulesList() = 6;
String getPrefsPath(String packageName) = 7;
String getCachePath(String fileName) = 8;
} }

View File

@ -21,7 +21,6 @@
#pragma once #pragma once
#include <base/object.h> #include <base/object.h>
#include <config_manager.h>
namespace art { namespace art {

View File

@ -51,6 +51,7 @@ inline constexpr bool is64 = Is64();
static const auto kEntryClassName = "io.github.lsposed.lspd.core.Main"s; static const auto kEntryClassName = "io.github.lsposed.lspd.core.Main"s;
static const auto kClassLinkerClassName = "io.github.lsposed.lspd.nativebridge.ClassLinker"s; static const auto kClassLinkerClassName = "io.github.lsposed.lspd.nativebridge.ClassLinker"s;
static const auto kBridgeServiceClassName = "io.github.lsposed.lspd.service.BridgeService"s; static const auto kBridgeServiceClassName = "io.github.lsposed.lspd.service.BridgeService"s;
static const auto kDexPath = "/data/adb/lspd/framework/lspd.dex"s;
static const auto kSandHookClassName = "com.swift.sandhook.SandHook"s; static const auto kSandHookClassName = "com.swift.sandhook.SandHook"s;
static const auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"s; static const auto kSandHookNeverCallClassName = "com.swift.sandhook.ClassNeverCall"s;

View File

@ -1,355 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#include <cstdio>
#include <dirent.h>
#include <unistd.h>
#include <jni.h>
#include <cstdlib>
#include <array>
#include <thread>
#include <vector>
#include <string>
#include <logging.h>
#include <climits>
#include <fstream>
#include <sstream>
#include "art/runtime/native/native_util.h"
#include "config_manager.h"
#include "utils.h"
#include "rirud_socket.h"
/*
* Logic:
* check if /data/adb/lspd 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.
*
* Permission:
* /data/adb/lspd 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:magisk_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 lspd
* because /data/misc/$misc_path is mounted by magisk.
*
* lspd 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 lspd {
namespace fs = std::filesystem;
fs::path ConfigManager::RetrieveBaseConfigPath() const {
if (!misc_path_.empty()) {
return misc_path_ / std::to_string(user_);
} else {
return {};
}
}
std::string ConfigManager::RetrieveInstallerPkgName() const {
std::string installer_pkg_name_path = GetConfigPath("installer");
if (!path_exists<true>(installer_pkg_name_path)) {
LOGW("installer not set, using default one %s", kPrimaryInstallerPkgName.c_str());
return kPrimaryInstallerPkgName;
}
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;
}
return {std::istream_iterator<char>(ifs), std::istream_iterator<char>()};
}
std::string ConfigManager::GetPackageNameFromBaseApkPath(const fs::path &path) {
std::vector<std::string> paths(path.begin(), path.end());
if (paths.empty()) return {};
auto base_apk = paths.back(); // base.apk
if (base_apk != "base.apk") return {};
paths.pop_back();
auto pkg_name_with_obfuscation = paths.back();
if (auto pos = pkg_name_with_obfuscation.find('-'); pos != std::string::npos) {
return pkg_name_with_obfuscation.substr(0, pos);
}
return {};
}
ConfigManager::ConfigManager(uid_t user, bool initialized) :
user_(user),
data_path_prefix_(fs::path("/data/user_de") /
std::to_string(user_)),
base_config_path_(RetrieveBaseConfigPath()),
initialized_(initialized || InitConfigPath()),
installer_pkg_name_(RetrieveInstallerPkgName()),
no_module_log_enabled_(path_exists(GetConfigPath("disable_modules_log"))),
resources_hook_enabled_(path_exists(GetConfigPath("enable_resources"))),
modules_list_(GetModuleList()),
last_write_time_(GetLastWriteTime()),
variant_(ReadInt(GetVariantPath())),
selinux_permissive_(ReadInt(GetSelinuxStatusPath()) != 1) {
LOGI("base config path: %s", base_config_path_.c_str());
LOGI(" using installer package name: %s", installer_pkg_name_.c_str());
LOGI(" no module log: %s", BoolToString(no_module_log_enabled_));
LOGI(" resources hook: %s", BoolToString(resources_hook_enabled_));
LOGI(" selinux permissive: %s", BoolToString(selinux_permissive_));
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());
}
int ConfigManager::ReadInt(const fs::path &dir) {
if (!path_exists(dir)) {
return 0;
}
std::ifstream ifs(dir);
if (!ifs.good()) {
return 0;
}
int result;
ifs >> result;
return result;
}
auto ConfigManager::GetModuleList() -> std::remove_const_t<decltype(modules_list_)> {
std::remove_const_t<decltype(modules_list_)> modules_list;
auto global_modules_list = GetConfigPath("modules.list");
if (!path_exists(global_modules_list)) {
LOGE("Cannot access path %s", global_modules_list.c_str());
return modules_list;
}
std::ifstream ifs(global_modules_list);
if (!ifs.good()) {
LOGE("Cannot access path %s", global_modules_list.c_str());
return modules_list;
}
std::string module;
while (std::getline(ifs, module)) {
const auto &module_pkg_name = GetPackageNameFromBaseApkPath(module);
auto &[module_path, scope] = modules_list[module_pkg_name];
scope.insert(module_pkg_name); // Always add module itself
module_path.assign(std::move(module));
const auto &module_scope_conf = GetConfigPath(module_pkg_name + ".conf");
if (!path_exists<true>(module_scope_conf)) {
LOGD("module scope is not set for %s", module_pkg_name.c_str());
continue;
}
std::ifstream ifs_c(module_scope_conf);
if (!ifs_c.good()) {
LOGE("Cannot access path %s", module_scope_conf.c_str());
continue;
}
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));
}
if (IsInstaller(module_pkg_name)) scope.erase("android");
LOGI("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 "));
return join.str();
})().c_str());
}
return modules_list;
}
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.second.count(pkg_name))
app_modules_list.push_back(scope.first);
}
return app_modules_list;
}
fs::file_time_type ConfigManager::GetLastWriteTime() const {
auto last_write_time = [](std::string_view path) __attribute__((always_inline)) {
return path_exists<true>(path) ? fs::last_write_time(path) : fs::file_time_type{};
};
std::string config_path = GetConfigPath();
std::string list_path = GetConfigPath("modules.list");
std::string variant_path = GetVariantPath();
return std::max({
last_write_time(config_path),
last_write_time(list_path),
last_write_time(variant_path)
});
}
bool ConfigManager::InitConfigPath() const {
if (base_config_path_.empty()) return false;
try {
fs::create_directories(base_config_path_);
fs::permissions(misc_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);
auto log_path = GetLogPath();
auto modules_log_path = GetModulesLogPath();
if (!fs::is_directory(log_path)) {
fs::remove(log_path);
}
if (!path_exists(log_path)) {
fs::create_directories(modules_log_path);
}
if (!path_exists<true>(modules_log_path)) {
std::ofstream(modules_log_path, std::ios::out);
}
fs::permissions(log_path,
fs::perms::owner_all | fs::perms::group_all | fs::perms::others_all);
recursive_permissions(log_path,
fs::perms::owner_read | fs::perms::owner_write |
fs::perms::group_read |
fs::perms::group_write | fs::perms::others_read |
fs::perms::others_write, fs::perm_options::add);
} 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<true>(prefs_path)) {
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 | fs::perms::set_gid);
if (const auto &[r_uid, r_gid] = path_own(prefs_path);
(uid != -1 && r_uid != uid) || r_gid != 1000u) {
path_chown(prefs_path, uid, 1000u, false);
}
}
if (IsInstaller(pkg_name) || pkg_name == "android") {
auto conf_path = GetConfigPath();
if (!path_exists<true>(conf_path)) {
fs::create_directories(conf_path);
}
recursive_permissions(conf_path, fs::perms::owner_all | fs::perms::group_all |
fs::perms::set_gid);
if (pkg_name == "android") uid = -1;
path_chown(conf_path, uid, 1000u, true);
if (current_user_ == 0) {
auto variant = GetVariantPath();
fs::permissions(variant, fs::perms::owner_all | fs::perms::group_all);
path_chown(variant, uid, 1000u);
auto disable_verbose_log = misc_path_ / "disable_verbose_log";
fs::permissions(disable_verbose_log,
fs::perms::owner_all | fs::perms::group_all);
path_chown(disable_verbose_log, uid, 1000u);
}
if (pkg_name == kPrimaryInstallerPkgName) {
umask(0007);
auto installer_pkg_name_path = GetConfigPath("installer");
if (path_exists<true>(installer_pkg_name_path)) {
fs::remove(installer_pkg_name_path);
}
}
}
} catch (const fs::filesystem_error &e) {
LOGE("%s", e.what());
}
}
void ConfigManager::Init() {
fs::path misc_path("/data/adb/lspd/misc_path");
try {
RirudSocket rirud_socket{};
auto path = rirud_socket.ReadFile(misc_path);
path.erase(std::find_if(path.rbegin(), path.rend(), [](unsigned char ch) {
return !std::isspace(ch);
}).base(), path.end());
misc_path_ = fs::path("/data/misc") / path;
inject_dex_path_ = GetFrameworkPath(kXposedInjectDexPath);
LOGI("Got base config path: %s", misc_path_.c_str());
} catch (const RirudSocket::RirudSocketException &e) {
LOGE("%s", e.what());
}
}
}

View File

@ -1,172 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#pragma once
#include <vector>
#include <string>
#include "JNIHelper.h"
#include <utility>
#include <art/runtime/native/native_util.h>
#include <filesystem>
#include <unordered_set>
#include <unordered_map>
#include "config.h"
#include "utils.h"
namespace lspd {
class ConfigManager {
private:
inline static const auto kPrimaryInstallerPkgName = "io.github.lsposed.manager"s;
inline static const auto kXposedInjectDexPath = "lspd.dex";
public:
static void Init();
inline static ConfigManager *GetInstance() {
return instances_[current_user_].get();
}
inline auto IsInitialized() const { return initialized_; }
inline static void SetCurrentUser(uid_t user) {
if (auto instance = instances_.find(user);
instance == instances_.end() || !instance->second) {
instances_[user] = std::make_unique<ConfigManager>(user);
} else if (instance->second->NeedUpdateConfig()) {
instances_[user] = std::make_unique<ConfigManager>(user,
instance->second->IsInitialized());
}
current_user_ = user;
}
inline static auto ReleaseInstances() {
return std::move(instances_);
}
inline const auto &GetVariant() const { return variant_; }
inline const auto &IsResourcesHookEnabled() const { return resources_hook_enabled_; }
inline const auto &IsNoModuleLogEnabled() const { return no_module_log_enabled_; }
inline const auto &GetInstallerPackageName() const { return installer_pkg_name_; }
inline const auto &GetDataPathPrefix() const { return data_path_prefix_; }
inline static const auto &GetMiscPath() { return misc_path_; }
inline static auto GetFrameworkPath(const std::string &suffix = {}) {
return misc_path_ / "framework" / suffix;
}
inline static auto GetCachePath(const std::string &suffix = {}) {
return misc_path_ / "cache" / suffix;
}
inline auto GetConfigPath(const std::string &suffix = {}) const {
return base_config_path_ / "conf" / suffix;
}
inline static auto GetLogPath(const std::string &suffix = {}) {
return misc_path_ / "log" / suffix;
}
inline const auto &GetBaseConfigPath() const { return base_config_path_; }
inline auto GetPrefsPath(const std::string &pkg_name) const {
return base_config_path_ / "prefs" / pkg_name;
}
inline static auto GetVariantPath() {
return misc_path_ / "variant";
}
inline static std::filesystem::path GetSelinuxStatusPath() {
return "/sys/fs/selinux/enforce";
}
inline static auto GetModulesLogPath() {
return GetLogPath("modules.log");
}
std::vector<std::string> GetAppModuleList(const std::string &pkg_name) const;
bool NeedUpdateConfig() const {
return last_write_time_ < GetLastWriteTime();
}
void EnsurePermission(const std::string &pkg_name, uid_t uid) const;
static const auto &GetInjectDexPath() { return inject_dex_path_; };
bool IsInstaller(const std::string &pkg_name) const {
return pkg_name == installer_pkg_name_ || pkg_name == kPrimaryInstallerPkgName;
}
bool IsPermissive() const {
return selinux_permissive_;
}
private:
inline static std::unordered_map<uid_t, std::unique_ptr<ConfigManager>> instances_{};
inline static uid_t current_user_ = 0u;
inline static std::filesystem::path misc_path_; // /data/misc/lspd_xxxx
inline static std::filesystem::path inject_dex_path_;
const uid_t user_;
const int variant_;
const std::filesystem::path data_path_prefix_; // /data/user_de/{user}
const std::filesystem::path base_config_path_; // /data/misc/lspd_xxxx/{user}
const bool initialized_ = false;
const std::filesystem::path installer_pkg_name_;
const bool no_module_log_enabled_ = false;
const bool resources_hook_enabled_ = false;
const bool selinux_permissive_ = false;
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_;
ConfigManager(uid_t uid, bool initialized = false);
std::string RetrieveInstallerPkgName() const;
static std::string GetPackageNameFromBaseApkPath(const std::filesystem::path &path);
std::remove_const_t<decltype(modules_list_)> GetModuleList();
std::filesystem::file_time_type GetLastWriteTime() const;
bool InitConfigPath() const;
friend std::unique_ptr<ConfigManager> std::make_unique<ConfigManager>(uid_t &);
friend std::unique_ptr<ConfigManager> std::make_unique<ConfigManager>(uid_t &, bool &&);
std::filesystem::path RetrieveBaseConfigPath() const;
static int ReadInt(const std::filesystem::path &dir);
};
} // namespace lspd

View File

@ -21,7 +21,6 @@
#include <jni.h> #include <jni.h>
#include <android-base/macros.h> #include <android-base/macros.h>
#include "JNIHelper.h" #include "JNIHelper.h"
#include "jni/config_manager.h"
#include "jni/art_class_linker.h" #include "jni/art_class_linker.h"
#include "jni/yahfa.h" #include "jni/yahfa.h"
#include "jni/resources_hook.h" #include "jni/resources_hook.h"
@ -32,12 +31,13 @@
#include <sandhook.h> #include <sandhook.h>
#include <fstream> #include <fstream>
#include <sstream> #include <sstream>
#include <nativehelper/scoped_local_ref.h>
#include "context.h" #include "context.h"
#include "config_manager.h"
#include "native_hook.h" #include "native_hook.h"
#include "jni/logger.h" #include "jni/logger.h"
#include "jni/native_api.h" #include "jni/native_api.h"
#include "service.h" #include "service.h"
#include "rirud_socket.h"
namespace lspd { namespace lspd {
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -66,13 +66,14 @@ namespace lspd {
void Context::PreLoadDex(const fs::path &dex_path) { void Context::PreLoadDex(const fs::path &dex_path) {
if (LIKELY(!dex.empty())) return; if (LIKELY(!dex.empty())) return;
std::ifstream is(dex_path, std::ios::binary); try {
if (!is.good()) { RirudSocket socket;
LOGE("Cannot load path %s", dex_path.c_str()); auto dex_content = socket.ReadFile(dex_path);
dex.assign(dex_content.begin(), dex_content.end());
} catch (RirudSocket::RirudSocketException &e) {
LOGE("%s", e.what());
return; return;
} }
dex.assign(std::istreambuf_iterator<char>(is),
std::istreambuf_iterator<char>());
LOGI("Loaded %s with size %zu", dex_path.c_str(), dex.size()); LOGI("Loaded %s with size %zu", dex_path.c_str(), dex.size());
} }
@ -108,9 +109,6 @@ namespace lspd {
env->DeleteLocalRef(my_cl); env->DeleteLocalRef(my_cl);
env->GetJavaVM(&vm_); env->GetJavaVM(&vm_);
// Make sure config manager is always working
RegisterConfigManagerMethods(env);
} }
void Context::Init(JNIEnv *env) { void Context::Init(JNIEnv *env) {
@ -193,7 +191,6 @@ namespace lspd {
void void
Context::OnNativeForkSystemServerPre(JNIEnv *env) { Context::OnNativeForkSystemServerPre(JNIEnv *env) {
Service::instance()->InitService(env); Service::instance()->InitService(env);
PreLoadDex(ConfigManager::GetInjectDexPath());
skip_ = false; skip_ = false;
} }
@ -226,7 +223,6 @@ namespace lspd {
jstring nice_name, jstring nice_name,
jboolean is_child_zygote, jboolean is_child_zygote,
jstring app_data_dir) { jstring app_data_dir) {
PreLoadDex(ConfigManager::GetInjectDexPath());
Service::instance()->InitService(env); Service::instance()->InitService(env);
const auto app_id = uid % PER_USER_RANGE; const auto app_id = uid % PER_USER_RANGE;
nice_name_ = nice_name; nice_name_ = nice_name;

View File

@ -64,6 +64,7 @@ namespace lspd {
void OnNativeForkSystemServerPre(JNIEnv *env); void OnNativeForkSystemServerPre(JNIEnv *env);
void PreLoadDex(const std::filesystem::path &dex_paths);
private: private:
inline static std::unique_ptr<Context> instance_ = std::make_unique<Context>(); inline static std::unique_ptr<Context> instance_ = std::make_unique<Context>();
@ -79,8 +80,6 @@ namespace lspd {
Context() {} Context() {}
void PreLoadDex(const std::filesystem::path &dex_paths);
void LoadDex(JNIEnv *env); void LoadDex(JNIEnv *env);
void Init(JNIEnv *env); void Init(JNIEnv *env);

View File

@ -24,6 +24,7 @@
#include <nativehelper/jni_macros.h> #include <nativehelper/jni_macros.h>
#include <vector> #include <vector>
#include <HookMain.h> #include <HookMain.h>
#include <unordered_set>
#include "art_class_linker.h" #include "art_class_linker.h"
namespace lspd { namespace lspd {

View File

@ -1,103 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#include <config_manager.h>
#include <nativehelper/jni_macros.h>
#include <native_util.h>
#include <sstream>
#include "config_manager.h"
namespace lspd {
LSP_DEF_NATIVE_METHOD(jboolean, ConfigManager, isResourcesHookEnabled) {
return (jboolean) ConfigManager::GetInstance()->IsResourcesHookEnabled();
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getInstallerPackageName) {
return env->NewStringUTF(ConfigManager::GetInstance()->GetInstallerPackageName().c_str());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getDataPathPrefix) {
return env->NewStringUTF(ConfigManager::GetInstance()->GetDataPathPrefix().c_str());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getLogPath) {
return env->NewStringUTF(ConfigManager::GetLogPath().c_str());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getConfigPath, 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());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getPrefsPath, jstring jSuffix) {
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
auto result = ConfigManager::GetInstance()->GetPrefsPath(suffix);
env->ReleaseStringUTFChars(jSuffix, suffix);
return env->NewStringUTF(result.c_str());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getCachePath, jstring jSuffix) {
const char *suffix = env->GetStringUTFChars(jSuffix, JNI_FALSE);
auto result = ConfigManager::GetCachePath(suffix);
env->ReleaseStringUTFChars(jSuffix, suffix);
return env->NewStringUTF(result.c_str());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getBaseConfigPath) {
auto result = ConfigManager::GetInstance()->GetBaseConfigPath();
return env->NewStringUTF(result.c_str());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getMiscPath) {
auto result = ConfigManager::GetMiscPath();
return env->NewStringUTF(result.c_str());
}
LSP_DEF_NATIVE_METHOD(jstring, ConfigManager, getModulesList) {
return nullptr;
}
LSP_DEF_NATIVE_METHOD(jboolean, ConfigManager, isPermissive) {
return ConfigManager::GetInstance()->IsPermissive();
}
static JNINativeMethod gMethods[] = {
LSP_NATIVE_METHOD(ConfigManager, isResourcesHookEnabled, "()Z"),
LSP_NATIVE_METHOD(ConfigManager, getInstallerPackageName, "()Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, getDataPathPrefix, "()Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, getMiscPath, "()Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, getLogPath, "()Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, getPrefsPath,
"(Ljava/lang/String;)Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, getCachePath,
"(Ljava/lang/String;)Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, getBaseConfigPath, "()Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, getModulesList, "()Ljava/lang/String;"),
LSP_NATIVE_METHOD(ConfigManager, isPermissive, "()Z"),
};
void RegisterConfigManagerMethods(JNIEnv *env) {
REGISTER_LSP_NATIVE_METHODS(ConfigManager);
}
}

View File

@ -1,29 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
#pragma once
#include "jni.h"
namespace lspd {
void RegisterConfigManagerMethods(JNIEnv *env);
}

View File

@ -22,22 +22,22 @@
#include "nativehelper/jni_macros.h" #include "nativehelper/jni_macros.h"
#include "native_util.h" #include "native_util.h"
#include "JNIHelper.h" #include "JNIHelper.h"
#include "../config_manager.h"
#include <fstream> #include <fstream>
#include <fcntl.h> #include <fcntl.h>
namespace lspd { namespace lspd {
LSP_DEF_NATIVE_METHOD(void, Logger, nativeLog, jstring jstr) { LSP_DEF_NATIVE_METHOD(void, Logger, nativeLog, jstring jstr) {
static int fd = open(ConfigManager::GetModulesLogPath().c_str(), O_APPEND | O_WRONLY); // TODO: get log path
if (fd < 0) { // static int fd = open(ConfigManager::GetModulesLogPath().c_str(), O_APPEND | O_WRONLY);
LOGD("Logger fail: %s", strerror(errno)); // if (fd < 0) {
return; // LOGD("Logger fail: %s", strerror(errno));
} // return;
JUTFString str(env, jstr); // }
int res = write(fd, str.get(), std::strlen(str.get())); // JUTFString str(env, jstr);
if (res < 0) { // int res = write(fd, str.get(), std::strlen(str.get()));
LOGD("Logger fail: %s", strerror(errno)); // if (res < 0) {
} // LOGD("Logger fail: %s", strerror(errno));
// }
} }
static JNINativeMethod gMethods[] = { static JNINativeMethod gMethods[] = {

View File

@ -26,15 +26,14 @@
#include "config.h" #include "config.h"
#include "context.h" #include "context.h"
#include <riru.h> #include <riru.h>
#include "config_manager.h"
#include "symbol_cache.h" #include "symbol_cache.h"
namespace lspd { namespace lspd {
static void onModuleLoaded() { static void onModuleLoaded() {
LOGI("onModuleLoaded: welcome to LSPosed!"); LOGI("onModuleLoaded: welcome to LSPosed!");
// rirud must be used in onModuleLoaded // rirud must be used in onModuleLoaded
Context::GetInstance()->PreLoadDex(kDexPath);
InitSymbolCache(); InitSymbolCache();
ConfigManager::Init();
} }
static int shouldSkipUid(int) { static int shouldSkipUid(int) {

View File

@ -21,7 +21,6 @@
#include <dlfcn.h> #include <dlfcn.h>
#include <string> #include <string>
#include <vector> #include <vector>
#include <config_manager.h>
#include <art/runtime/runtime.h> #include <art/runtime/runtime.h>
#include <dl_util.h> #include <dl_util.h>
#include <art/runtime/jni_env_ext.h> #include <art/runtime/jni_env_ext.h>

View File

@ -152,8 +152,10 @@ namespace lspd {
jobject service = nullptr; jobject service = nullptr;
if (res) { if (res) {
JNI_CallVoidMethod(env, reply, readExceptionMethod_); env->CallVoidMethod(reply, readExceptionMethod_);
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_); if (!ClearException(env)) {
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
}
} }
JNI_CallVoidMethod(env, data, recycleMethod_); JNI_CallVoidMethod(env, data, recycleMethod_);
JNI_CallVoidMethod(env, reply, recycleMethod_); JNI_CallVoidMethod(env, reply, recycleMethod_);

View File

@ -52,6 +52,8 @@ import java.util.Set;
import de.robv.android.xposed.services.FileResult; import de.robv.android.xposed.services.FileResult;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
/** /**
* This class is basically the same as SharedPreferencesImpl from AOSP, but * This class is basically the same as SharedPreferencesImpl from AOSP, but
* read-only and without listeners support. Instead, it is made to be * read-only and without listeners support. Instead, it is made to be
@ -180,8 +182,9 @@ public final class XSharedPreferences implements SharedPreferences {
newModule = isModule && (xposedminversion > 92 || xposedsharedprefs); newModule = isModule && (xposedminversion > 92 || xposedsharedprefs);
} }
} }
if (newModule && XposedInit.prefsBasePath != null) { if (newModule) {
mFile = new File(XposedInit.prefsBasePath, packageName + "/" + prefFileName + ".xml");
mFile = new File(serviceClient.getPrefsPath( packageName ), prefFileName + ".xml");
} else { } else {
mFile = new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/" + prefFileName + ".xml"); mFile = new File(Environment.getDataDirectory(), "data/" + packageName + "/shared_prefs/" + prefFileName + ".xml");
} }
@ -198,7 +201,8 @@ public final class XSharedPreferences implements SharedPreferences {
Path path = mFile.toPath(); Path path = mFile.toPath();
try { try {
if (sWatcher == null) { if (sWatcher == null) {
sWatcher = new File(XposedInit.prefsBasePath).toPath().getFileSystem().newWatchService(); // TODO
// sWatcher = new File(XposedInit.prefsBasePath).toPath().getFileSystem().newWatchService();
if (BuildConfig.DEBUG) Log.d(TAG, "Created WatchService instance"); if (BuildConfig.DEBUG) Log.d(TAG, "Created WatchService instance");
} }
mWatchKey = path.getParent().register(sWatcher, StandardWatchEventKinds.ENTRY_CREATE, mWatchKey = path.getParent().register(sWatcher, StandardWatchEventKinds.ENTRY_CREATE,

View File

@ -25,7 +25,6 @@ import android.content.res.TypedArray;
import android.util.Log; import android.util.Log;
import io.github.lsposed.lspd.BuildConfig; import io.github.lsposed.lspd.BuildConfig;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.config.LSPdConfigGlobal; import io.github.lsposed.lspd.config.LSPdConfigGlobal;
import java.lang.reflect.AccessibleObject; import java.lang.reflect.AccessibleObject;
@ -98,15 +97,6 @@ public final class XposedBridge {
private XposedBridge() {} private XposedBridge() {}
/**
* Called when native methods and other things are initialized, but before preloading classes etc.
* @hide
*/
@SuppressWarnings("deprecation")
public static void main(String[] args) {
// ed: moved
}
/** @hide */ /** @hide */
// protected static final class ToolEntryPoint { // protected static final class ToolEntryPoint {
// protected static void main(String[] args) { // protected static void main(String[] args) {

View File

@ -34,7 +34,6 @@ import android.util.Log;
import com.android.internal.os.ZygoteInit; import com.android.internal.os.ZygoteInit;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.config.LSPdConfigGlobal; import io.github.lsposed.lspd.config.LSPdConfigGlobal;
import java.io.BufferedReader; import java.io.BufferedReader;
@ -49,6 +48,7 @@ import java.lang.reflect.Method;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Arrays; import java.util.Arrays;
import java.util.HashSet; import java.util.HashSet;
import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Set; import java.util.Set;
import java.util.concurrent.atomic.AtomicBoolean; import java.util.concurrent.atomic.AtomicBoolean;
@ -77,6 +77,7 @@ import static de.robv.android.xposed.XposedHelpers.getParameterIndexByType;
import static de.robv.android.xposed.XposedHelpers.setStaticBooleanField; import static de.robv.android.xposed.XposedHelpers.setStaticBooleanField;
import static de.robv.android.xposed.XposedHelpers.setStaticLongField; import static de.robv.android.xposed.XposedHelpers.setStaticLongField;
import static de.robv.android.xposed.XposedHelpers.setStaticObjectField; import static de.robv.android.xposed.XposedHelpers.setStaticObjectField;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
public final class XposedInit { public final class XposedInit {
private static final String TAG = XposedBridge.TAG; private static final String TAG = XposedBridge.TAG;
@ -86,7 +87,6 @@ public final class XposedInit {
private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication"; private static final String INSTANT_RUN_CLASS = "com.android.tools.fd.runtime.BootstrapApplication";
public static volatile boolean disableResources = false; public static volatile boolean disableResources = false;
private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"}; private static final String[] XRESOURCES_CONFLICTING_PACKAGES = {"com.sygic.aura"};
public static String prefsBasePath = null;
private XposedInit() { private XposedInit() {
} }
@ -113,7 +113,7 @@ public final class XposedInit {
@ApiSensitive(Level.MIDDLE) @ApiSensitive(Level.MIDDLE)
private static void hookResources() throws Throwable { private static void hookResources() throws Throwable {
if (!ConfigManager.isResourcesHookEnabled() || disableResources) { if (!serviceClient.isResourcesHookEnabled() || disableResources) {
return; return;
} }
@ -353,12 +353,9 @@ public final class XposedInit {
topClassLoader = parent; topClassLoader = parent;
} }
String moduleList = ConfigManager.getModulesList(); List<String> moduleList = serviceClient.getModulesList();
InputStream stream = new ByteArrayInputStream(moduleList.getBytes());
BufferedReader apks = new BufferedReader(new InputStreamReader(stream));
ArraySet<String> newLoadedApk = new ArraySet<>(); ArraySet<String> newLoadedApk = new ArraySet<>();
String apk; for (String apk : moduleList)
while ((apk = apks.readLine()) != null) {
if (loadedModules.contains(apk)) { if (loadedModules.contains(apk)) {
newLoadedApk.add(apk); newLoadedApk.add(apk);
} else { } else {
@ -368,10 +365,9 @@ public final class XposedInit {
newLoadedApk.add(apk); newLoadedApk.add(apk);
} }
} }
}
loadedModules.clear(); loadedModules.clear();
loadedModules.addAll(newLoadedApk); loadedModules.addAll(newLoadedApk);
apks.close();
// refresh callback according to current loaded module list // refresh callback according to current loaded module list
pruneCallbacks(loadedModules); pruneCallbacks(loadedModules);

View File

@ -0,0 +1,121 @@
package io.github.lsposed.lspd.config;
import android.os.IBinder;
import android.os.RemoteException;
import java.io.File;
import java.util.Collections;
import java.util.List;
import io.github.lsposed.lspd.service.ILSPApplicationService;
import io.github.lsposed.lspd.util.Utils;
public class LSPApplicationServiceClient implements ILSPApplicationService {
static ILSPApplicationService service = null;
static IBinder serviceBinder = null;
static String baseCachePath = null;
static String basePrefsPath = null;
public static LSPApplicationServiceClient serviceClient = null;
public static void Init(IBinder binder) {
if (serviceClient == null && binder != null && serviceBinder == null && service == null) {
serviceBinder = binder;
try {
serviceBinder.linkToDeath(() -> {
serviceBinder = null;
service = null;
}, 0);
} catch (RemoteException e) {
Utils.logE("link to death error: ", e);
}
service = ILSPApplicationService.Stub.asInterface(binder);
serviceClient = new LSPApplicationServiceClient();
}
}
@Override
public void registerHeartBeat(IBinder handle) {
if (service == null || serviceBinder == null) {
Utils.logE("Register Failed: service is null");
}
try {
service.registerHeartBeat(handle);
} catch (RemoteException e) {
Utils.logE("register heart beat failed", e);
}
}
@Override
public IBinder requestModuleBinder() {
try {
return service.requestModuleBinder();
} catch (RemoteException | NullPointerException ignored) {
}
return null;
}
@Override
public IBinder requestManagerBinder() {
try {
return service.requestManagerBinder();
} catch (RemoteException | NullPointerException ignored) {
}
return null;
}
@Override
public int getVariant() {
try {
return service.getVariant();
} catch (RemoteException | NullPointerException ignored) {
}
return -1;
}
@Override
public boolean isResourcesHookEnabled() {
try {
return service.isResourcesHookEnabled();
} catch (RemoteException | NullPointerException ignored) {
}
return false;
}
@Override
public List<String> getModulesList() {
try {
return service.getModulesList();
} catch (RemoteException | NullPointerException ignored) {
}
return Collections.emptyList();
}
@Override
public String getPrefsPath(String packageName) {
try {
if (basePrefsPath == null)
basePrefsPath = service.getPrefsPath("");
return basePrefsPath + File.separator + packageName;
} catch (RemoteException | NullPointerException ignored) {
}
return null;
}
@Override
public String getCachePath(String fileName) {
try {
if (baseCachePath == null)
baseCachePath = service.getCachePath("");
return baseCachePath + File.separator + fileName;
} catch (RemoteException | NullPointerException ignored) {
}
return null;
}
@Override
public IBinder asBinder() {
return serviceBinder;
}
}

View File

@ -29,12 +29,14 @@ import android.util.Log;
import android.ddm.DdmHandleAppName; import android.ddm.DdmHandleAppName;
import io.github.lsposed.common.KeepAll; import io.github.lsposed.common.KeepAll;
import io.github.lsposed.lspd.config.LSPApplicationServiceClient;
import io.github.lsposed.lspd.service.ILSPApplicationService; import io.github.lsposed.lspd.service.ILSPApplicationService;
import io.github.lsposed.lspd.service.ServiceManager; import io.github.lsposed.lspd.service.ServiceManager;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
import java.util.concurrent.atomic.AtomicReference; import java.util.concurrent.atomic.AtomicReference;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
import static io.github.lsposed.lspd.service.ServiceManager.TAG; import static io.github.lsposed.lspd.service.ServiceManager.TAG;
@SuppressLint("DefaultLocale") @SuppressLint("DefaultLocale")
@ -43,15 +45,9 @@ public class Main implements KeepAll {
private static final Binder heartBeatBinder = new Binder(); private static final Binder heartBeatBinder = new Binder();
public static void forkAndSpecializePost(String appDataDir, String niceName, IBinder binder) { public static void forkAndSpecializePost(String appDataDir, String niceName, IBinder binder) {
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder); LSPApplicationServiceClient.Init(binder);
final int variant; serviceClient.registerHeartBeat(heartBeatBinder);
try { final int variant = serviceClient.getVariant();
service.registerHeartBeat(heartBeatBinder);
variant = service.getVariant();
} catch (RemoteException e) {
Utils.logW("Register fail", e);
return;
}
EdxpImpl lspd = getEdxpImpl(variant); EdxpImpl lspd = getEdxpImpl(variant);
if (lspd == null || !lspd.isInitialized()) { if (lspd == null || !lspd.isInitialized()) {
Utils.logE("Not started up"); Utils.logE("Not started up");
@ -61,15 +57,9 @@ public class Main implements KeepAll {
} }
public static void forkSystemServerPost(IBinder binder) { public static void forkSystemServerPost(IBinder binder) {
ILSPApplicationService service = ILSPApplicationService.Stub.asInterface(binder); LSPApplicationServiceClient.Init(binder);
final int variant; serviceClient.registerHeartBeat(heartBeatBinder);
try { final int variant = serviceClient.getVariant();
service.registerHeartBeat(heartBeatBinder);
variant = service.getVariant();
} catch (RemoteException e) {
Utils.logW("Register fail", e);
return;
}
EdxpImpl lspd = getEdxpImpl(variant); EdxpImpl lspd = getEdxpImpl(variant);
if (lspd == null || !lspd.isInitialized()) { if (lspd == null || !lspd.isInitialized()) {
return; return;

View File

@ -22,7 +22,6 @@ package io.github.lsposed.lspd.deopt;
import android.text.TextUtils; import android.text.TextUtils;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.config.LSPdConfigGlobal; import io.github.lsposed.lspd.config.LSPdConfigGlobal;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
@ -30,6 +29,7 @@ import java.util.Arrays;
import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedHelpers;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE; import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE;
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE_MIUI_RES; import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_BOOT_IMAGE_MIUI_RES;
import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_SYSTEM_SERVER; import static io.github.lsposed.lspd.deopt.InlinedMethodCallers.KEY_SYSTEM_SERVER;
@ -62,7 +62,7 @@ public class PrebuiltMethodsDeopter {
// todo check if has been done before // todo check if has been done before
deoptMethods(KEY_BOOT_IMAGE, null); deoptMethods(KEY_BOOT_IMAGE, null);
if (!TextUtils.isEmpty(Utils.getSysProp("ro.miui.ui.version.code")) if (!TextUtils.isEmpty(Utils.getSysProp("ro.miui.ui.version.code"))
&& ConfigManager.isResourcesHookEnabled()) { && serviceClient.isResourcesHookEnabled()) {
//deopt these only for MIUI with resources hook enabled //deopt these only for MIUI with resources hook enabled
deoptMethods(KEY_BOOT_IMAGE_MIUI_RES, null); deoptMethods(KEY_BOOT_IMAGE_MIUI_RES, null);
} }

View File

@ -18,7 +18,7 @@
* Copyright (C) 2021 LSPosed Contributors * Copyright (C) 2021 LSPosed Contributors
*/ */
package io.github.lsposed.lspd._hooker.impl; package io.github.lsposed.lspd.hooker;
import android.annotation.SuppressLint; import android.annotation.SuppressLint;
import android.app.ActivityThread; import android.app.ActivityThread;
@ -30,7 +30,6 @@ import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo; import android.content.res.CompatibilityInfo;
import android.content.res.XResources; import android.content.res.XResources;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.util.Hookers; import io.github.lsposed.lspd.util.Hookers;
import io.github.lsposed.lspd.util.MetaDataReader; import io.github.lsposed.lspd.util.MetaDataReader;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
@ -46,8 +45,15 @@ import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.XposedInit; import de.robv.android.xposed.XposedInit;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
// normal process initialization (for new Activity, Service, BroadcastReceiver etc.) // normal process initialization (for new Activity, Service, BroadcastReceiver etc.)
public class HandleBindApp extends XC_MethodHook { public class HandleBindAppHooker extends XC_MethodHook {
String appDataDir = null;
public HandleBindAppHooker(String appDataDir) {
this.appDataDir = appDataDir;
}
@Override @Override
protected void beforeHookedMethod(MethodHookParam param) { protected void beforeHookedMethod(MethodHookParam param) {
@ -57,10 +63,10 @@ public class HandleBindApp extends XC_MethodHook {
Object bindData = param.args[0]; Object bindData = param.args[0];
final ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo"); final ApplicationInfo appInfo = (ApplicationInfo) XposedHelpers.getObjectField(bindData, "appInfo");
// save app process name here for later use // save app process name here for later use
ConfigManager.appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName"); String appProcessName = (String) XposedHelpers.getObjectField(bindData, "processName");
String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName; String reportedPackageName = appInfo.packageName.equals("android") ? "system" : appInfo.packageName;
Utils.logD("processName=" + ConfigManager.appProcessName + Utils.logD("processName=" + appProcessName +
", packageName=" + reportedPackageName + ", appDataDir=" + ConfigManager.appDataDir); ", packageName=" + reportedPackageName + ", appDataDir=" + appDataDir);
ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName"); ComponentName instrumentationName = (ComponentName) XposedHelpers.getObjectField(bindData, "instrumentationName");
if (instrumentationName != null) { if (instrumentationName != null) {
@ -118,7 +124,7 @@ public class HandleBindApp extends XC_MethodHook {
XposedHelpers.findAndHookMethod(ContextImpl.class, "getPreferencesDir", new XC_MethodHook() { XposedHelpers.findAndHookMethod(ContextImpl.class, "getPreferencesDir", new XC_MethodHook() {
@Override @Override
protected void afterHookedMethod(MethodHookParam param) { protected void afterHookedMethod(MethodHookParam param) {
File newDir = new File(ConfigManager.getPrefsPath(appInfo.packageName)); File newDir = new File(serviceClient.getPrefsPath(appInfo.packageName));
if (migratePrefs) { if (migratePrefs) {
File oldDir = (File) param.getResult(); File oldDir = (File) param.getResult();
for (File oldFile : oldDir.listFiles()) { for (File oldFile : oldDir.listFiles()) {
@ -143,7 +149,7 @@ public class HandleBindApp extends XC_MethodHook {
} }
}); });
} }
LoadedApkGetCL hook = new LoadedApkGetCL(loadedApk, reportedPackageName, LoadedApkGetCLHooker hook = new LoadedApkGetCLHooker(loadedApk, reportedPackageName,
processName, true); processName, true);
hook.setUnhook(XposedHelpers.findAndHookMethod( hook.setUnhook(XposedHelpers.findAndHookMethod(
LoadedApk.class, "getClassLoader", hook)); LoadedApk.class, "getClassLoader", hook));

View File

@ -18,7 +18,7 @@
* Copyright (C) 2021 LSPosed Contributors * Copyright (C) 2021 LSPosed Contributors
*/ */
package io.github.lsposed.lspd._hooker.impl; package io.github.lsposed.lspd.hooker;
import android.app.AndroidAppHelper; import android.app.AndroidAppHelper;
import android.app.LoadedApk; import android.app.LoadedApk;
@ -33,7 +33,7 @@ import de.robv.android.xposed.XposedInit;
// when a package is loaded for an existing process, trigger the callbacks as well // when a package is loaded for an existing process, trigger the callbacks as well
// ed: remove resources related hooking // ed: remove resources related hooking
public class LoadedApkCstr extends XC_MethodHook { public class LoadedApkCstrHooker extends XC_MethodHook {
@Override @Override
protected void afterHookedMethod(MethodHookParam param) throws Throwable { protected void afterHookedMethod(MethodHookParam param) throws Throwable {
@ -70,7 +70,7 @@ public class LoadedApkCstr extends XC_MethodHook {
return; return;
} }
LoadedApkGetCL hook = new LoadedApkGetCL(loadedApk, packageName, LoadedApkGetCLHooker hook = new LoadedApkGetCLHooker(loadedApk, packageName,
AndroidAppHelper.currentProcessName(), false); AndroidAppHelper.currentProcessName(), false);
hook.setUnhook(XposedHelpers.findAndHookMethod( hook.setUnhook(XposedHelpers.findAndHookMethod(
LoadedApk.class, "getClassLoader", hook)); LoadedApk.class, "getClassLoader", hook));

View File

@ -18,20 +18,22 @@
* Copyright (C) 2021 LSPosed Contributors * Copyright (C) 2021 LSPosed Contributors
*/ */
package io.github.lsposed.lspd._hooker.impl; package io.github.lsposed.lspd.hooker;
import android.app.LoadedApk; import android.app.LoadedApk;
import android.os.IBinder;
import de.robv.android.xposed.XC_MethodHook; import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedHelpers;
import de.robv.android.xposed.callbacks.XC_LoadPackage; import de.robv.android.xposed.callbacks.XC_LoadPackage;
import io.github.lsposed.lspd.hooker.XposedInstallerHooker; import io.github.lsposed.lspd.hooker.XposedInstallerHooker;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.util.Hookers; import io.github.lsposed.lspd.util.Hookers;
import io.github.lsposed.lspd.util.InstallerVerifier; import io.github.lsposed.lspd.util.InstallerVerifier;
public class LoadedApkGetCL extends XC_MethodHook { import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
public class LoadedApkGetCLHooker extends XC_MethodHook {
private final LoadedApk loadedApk; private final LoadedApk loadedApk;
private final String packageName; private final String packageName;
@ -39,8 +41,8 @@ public class LoadedApkGetCL extends XC_MethodHook {
private final boolean isFirstApplication; private final boolean isFirstApplication;
private Unhook unhook; private Unhook unhook;
public LoadedApkGetCL(LoadedApk loadedApk, String packageName, String processName, public LoadedApkGetCLHooker(LoadedApk loadedApk, String packageName, String processName,
boolean isFirstApplication) { boolean isFirstApplication) {
this.loadedApk = loadedApk; this.loadedApk = loadedApk;
this.packageName = packageName; this.packageName = packageName;
this.processName = processName; this.processName = processName;
@ -76,9 +78,10 @@ public class LoadedApkGetCL extends XC_MethodHook {
lpparam.appInfo = loadedApk.getApplicationInfo(); lpparam.appInfo = loadedApk.getApplicationInfo();
lpparam.isFirstApplication = this.isFirstApplication; lpparam.isFirstApplication = this.isFirstApplication;
if (packageName.equals(ConfigManager.getInstallerPackageName())) { IBinder binder = serviceClient.requestManagerBinder();
if (binder != null) {
if (InstallerVerifier.verifyInstallerSignature(loadedApk.getApplicationInfo())) { if (InstallerVerifier.verifyInstallerSignature(loadedApk.getApplicationInfo())) {
XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader); XposedInstallerHooker.hookXposedInstaller(lpparam.classLoader, binder);
} else { } else {
InstallerVerifier.hookXposedInstaller(classLoader); InstallerVerifier.hookXposedInstaller(classLoader);
} }

View File

@ -18,7 +18,7 @@
* Copyright (C) 2021 LSPosed Contributors * Copyright (C) 2021 LSPosed Contributors
*/ */
package io.github.lsposed.lspd._hooker.impl; package io.github.lsposed.lspd.hooker;
import android.os.Build; import android.os.Build;
@ -34,7 +34,7 @@ import de.robv.android.xposed.callbacks.XC_LoadPackage;
import static io.github.lsposed.lspd.util.Utils.logD; import static io.github.lsposed.lspd.util.Utils.logD;
import static de.robv.android.xposed.XposedHelpers.findAndHookMethod; import static de.robv.android.xposed.XposedHelpers.findAndHookMethod;
public class StartBootstrapServices extends XC_MethodHook { public class StartBootstrapServicesHooker extends XC_MethodHook {
@Override @Override
protected void beforeHookedMethod(MethodHookParam param) throws Throwable { protected void beforeHookedMethod(MethodHookParam param) throws Throwable {
@ -50,7 +50,7 @@ public class StartBootstrapServices extends XC_MethodHook {
XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks); XC_LoadPackage.LoadPackageParam lpparam = new XC_LoadPackage.LoadPackageParam(XposedBridge.sLoadedPackageCallbacks);
lpparam.packageName = "android"; lpparam.packageName = "android";
lpparam.processName = "android"; // it's actually system_server, but other functions return this as well lpparam.processName = "android"; // it's actually system_server, but other functions return this as well
lpparam.classLoader = SystemMain.systemServerCL; lpparam.classLoader = SystemMainHooker.systemServerCL;
lpparam.appInfo = null; lpparam.appInfo = null;
lpparam.isFirstApplication = true; lpparam.isFirstApplication = true;
XC_LoadPackage.callAll(lpparam); XC_LoadPackage.callAll(lpparam);
@ -58,14 +58,14 @@ public class StartBootstrapServices extends XC_MethodHook {
// Huawei // Huawei
try { try {
findAndHookMethod("com.android.server.pm.HwPackageManagerService", findAndHookMethod("com.android.server.pm.HwPackageManagerService",
SystemMain.systemServerCL, "isOdexMode", SystemMainHooker.systemServerCL, "isOdexMode",
XC_MethodReplacement.returnConstant(false)); XC_MethodReplacement.returnConstant(false));
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {
} }
try { try {
String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService"); String className = "com.android.server.pm." + (Build.VERSION.SDK_INT >= 23 ? "PackageDexOptimizer" : "PackageManagerService");
findAndHookMethod(className, SystemMain.systemServerCL, findAndHookMethod(className, SystemMainHooker.systemServerCL,
"dexEntryExists", String.class, "dexEntryExists", String.class,
XC_MethodReplacement.returnConstant(true)); XC_MethodReplacement.returnConstant(true));
} catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) { } catch (XposedHelpers.ClassNotFoundError | NoSuchMethodError ignored) {

View File

@ -18,7 +18,7 @@
* Copyright (C) 2021 LSPosed Contributors * Copyright (C) 2021 LSPosed Contributors
*/ */
package io.github.lsposed.lspd._hooker.impl; package io.github.lsposed.lspd.hooker;
import io.github.lsposed.lspd.core.Main; import io.github.lsposed.lspd.core.Main;
import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter; import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
@ -29,7 +29,7 @@ import de.robv.android.xposed.XposedBridge;
// system_server initialization // system_server initialization
// ed: only support sdk >= 21 for now // ed: only support sdk >= 21 for now
public class SystemMain extends XC_MethodHook { public class SystemMainHooker extends XC_MethodHook {
public static volatile ClassLoader systemServerCL; public static volatile ClassLoader systemServerCL;

View File

@ -20,19 +20,16 @@
package io.github.lsposed.lspd.hooker; package io.github.lsposed.lspd.hooker;
import de.robv.android.xposed.XC_MethodReplacement; import android.os.IBinder;
import de.robv.android.xposed.XposedBridge;
import de.robv.android.xposed.XposedHelpers; import de.robv.android.xposed.XposedHelpers;
import io.github.lsposed.lspd.BuildConfig;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.core.EdxpImpl; import io.github.lsposed.lspd.core.EdxpImpl;
import io.github.lsposed.lspd.core.Main; import io.github.lsposed.lspd.core.Main;
import io.github.lsposed.lspd.service.BridgeService;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
public class XposedInstallerHooker { public class XposedInstallerHooker {
public static void hookXposedInstaller(final ClassLoader classLoader) { public static void hookXposedInstaller(final ClassLoader classLoader, IBinder binder) {
final String variant; final String variant;
switch (Main.getEdxpVariant()) { switch (Main.getEdxpVariant()) {
case EdxpImpl.YAHFA: case EdxpImpl.YAHFA:
@ -51,72 +48,8 @@ public class XposedInstallerHooker {
// LSPosed Manager R // LSPosed Manager R
try { try {
Class<?> ConstantsClass = XposedHelpers.findClass("io.github.lsposed.manager.Constants", classLoader);
try {
XposedHelpers.setStaticIntField(ConstantsClass, "xposedApiVersion", XposedBridge.getXposedVersion());
XposedHelpers.setStaticObjectField(ConstantsClass, "xposedVersion", BuildConfig.VERSION_NAME);
XposedHelpers.setStaticIntField(ConstantsClass, "xposedVersionCode", BuildConfig.VERSION_CODE);
XposedHelpers.setStaticObjectField(ConstantsClass, "xposedVariant", variant);
XposedHelpers.setStaticObjectField(ConstantsClass, "baseDir", ConfigManager.getBaseConfigPath() + "/");
XposedHelpers.setStaticObjectField(ConstantsClass, "logDir", ConfigManager.getLogPath());
XposedHelpers.setStaticObjectField(ConstantsClass, "miscDir", ConfigManager.getMiscPath());
XposedHelpers.setStaticBooleanField(ConstantsClass, "permissive", ConfigManager.isPermissive());
Utils.logI("Hooked LSPosed Manager");
return;
} catch (Throwable ignored) {
// fallback
}
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedApiVersion", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return XposedBridge.getXposedVersion();
}
});
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedVersion", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return BuildConfig.VERSION_NAME;
}
});
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedVersionCode", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return BuildConfig.VERSION_CODE;
}
});
XposedHelpers.findAndHookMethod(ConstantsClass, "getXposedVariant", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return variant;
}
});
XposedHelpers.findAndHookMethod(ConstantsClass, "getBaseDir", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return ConfigManager.getBaseConfigPath() + "/";
}
});
XposedHelpers.findAndHookMethod(ConstantsClass, "isPermissive", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return ConfigManager.isPermissive();
}
});
XposedHelpers.findAndHookMethod(ConstantsClass, "getLogDir", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return ConfigManager.getLogPath();
}
});
XposedHelpers.findAndHookMethod(ConstantsClass, "getMiscDir", new XC_MethodReplacement() {
@Override
protected Object replaceHookedMethod(MethodHookParam param) {
return ConfigManager.getMiscPath();
}
});
Class<?> serviceClass = XposedHelpers.findClass("io.github.lsposed.manager.receivers.LSPosedManagerServiceClient", classLoader); Class<?> serviceClass = XposedHelpers.findClass("io.github.lsposed.manager.receivers.LSPosedManagerServiceClient", classLoader);
// XposedHelpers.setStaticObjectField(serviceClass, "binder", BridgeService.requireBinder()); XposedHelpers.setStaticObjectField(serviceClass, "binder", binder);
Utils.logI("Hooked LSPosed Manager"); Utils.logI("Hooked LSPosed Manager");
} catch (Throwable t) { } catch (Throwable t) {

View File

@ -1,48 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
package io.github.lsposed.lspd.nativebridge;
public class ConfigManager {
public static String appDataDir = "";
public static String niceName = "";
public static String appProcessName = "";
public static native boolean isResourcesHookEnabled();
public static native String getInstallerPackageName();
public static native String getPrefsPath(String suffix);
public static native String getCachePath(String suffix);
public static native String getLogPath();
public static native String getMiscPath();
public static native String getBaseConfigPath();
public static native String getDataPathPrefix();
public static native String getModulesList();
public static native boolean isPermissive();
}

View File

@ -25,10 +25,10 @@ import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo; import android.content.res.CompatibilityInfo;
import android.text.TextUtils; import android.text.TextUtils;
import io.github.lsposed.lspd._hooker.impl.HandleBindApp; import io.github.lsposed.lspd.hooker.HandleBindAppHooker;
import io.github.lsposed.lspd._hooker.impl.LoadedApkCstr; import io.github.lsposed.lspd.hooker.LoadedApkCstrHooker;
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices; import io.github.lsposed.lspd.hooker.StartBootstrapServicesHooker;
import io.github.lsposed.lspd._hooker.impl.SystemMain; import io.github.lsposed.lspd.hooker.SystemMainHooker;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
import io.github.lsposed.lspd.util.Versions; import io.github.lsposed.lspd.util.Versions;
@ -53,13 +53,13 @@ public abstract class BaseRouter implements Router {
XposedInit.startsSystemServer = isSystem; XposedInit.startsSystemServer = isSystem;
} }
public void installBootstrapHooks(boolean isSystem) { public void installBootstrapHooks(boolean isSystem, String appDataDir) {
// Initialize the Xposed framework // Initialize the Xposed framework
try { try {
if (!bootstrapHooked.compareAndSet(false, true)) { if (!bootstrapHooked.compareAndSet(false, true)) {
return; return;
} }
startBootstrapHook(isSystem); startBootstrapHook(isSystem, appDataDir);
XposedInit.initForZygote(isSystem); XposedInit.initForZygote(isSystem);
} catch (Throwable t) { } catch (Throwable t) {
Utils.logE("error during Xposed initialization", t); Utils.logE("error during Xposed initialization", t);
@ -88,30 +88,30 @@ public abstract class BaseRouter implements Router {
@ApiSensitive(Level.LOW) @ApiSensitive(Level.LOW)
public void startBootstrapHook(boolean isSystem) { public void startBootstrapHook(boolean isSystem, String appDataDir) {
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem); Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);
ClassLoader classLoader = BaseRouter.class.getClassLoader(); ClassLoader classLoader = BaseRouter.class.getClassLoader();
if (isSystem) { if (isSystem) {
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader, XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
"systemMain", new SystemMain()); "systemMain", new SystemMainHooker());
} }
XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader, XposedHelpers.findAndHookMethod("android.app.ActivityThread", classLoader,
"handleBindApplication", "handleBindApplication",
"android.app.ActivityThread$AppBindData", "android.app.ActivityThread$AppBindData",
new HandleBindApp()); new HandleBindAppHooker(appDataDir));
XposedHelpers.findAndHookConstructor("android.app.LoadedApk", classLoader, XposedHelpers.findAndHookConstructor("android.app.LoadedApk", classLoader,
ActivityThread.class, ApplicationInfo.class, CompatibilityInfo.class, ActivityThread.class, ApplicationInfo.class, CompatibilityInfo.class,
ClassLoader.class, boolean.class, boolean.class, boolean.class, ClassLoader.class, boolean.class, boolean.class, boolean.class,
new LoadedApkCstr()); new LoadedApkCstrHooker());
} }
public void startSystemServerHook() { public void startSystemServerHook() {
StartBootstrapServices sbsHooker = new StartBootstrapServices(); StartBootstrapServicesHooker sbsHooker = new StartBootstrapServicesHooker();
Object[] paramTypesAndCallback = Versions.hasR() ? Object[] paramTypesAndCallback = Versions.hasR() ?
new Object[]{"com.android.server.utils.TimingsTraceAndSlog", sbsHooker} : new Object[]{"com.android.server.utils.TimingsTraceAndSlog", sbsHooker} :
new Object[]{sbsHooker}; new Object[]{sbsHooker};
XposedHelpers.findAndHookMethod("com.android.server.SystemServer", XposedHelpers.findAndHookMethod("com.android.server.SystemServer",
SystemMain.systemServerCL, SystemMainHooker.systemServerCL,
"startBootstrapServices", paramTypesAndCallback); "startBootstrapServices", paramTypesAndCallback);
} }
} }

View File

@ -20,15 +20,16 @@
package io.github.lsposed.lspd.proxy; package io.github.lsposed.lspd.proxy;
import io.github.lsposed.lspd.nativebridge.ConfigManager; import android.os.Environment;
import java.io.File;
import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter; import io.github.lsposed.lspd.deopt.PrebuiltMethodsDeopter;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
import de.robv.android.xposed.SELinuxHelper; import de.robv.android.xposed.SELinuxHelper;
import de.robv.android.xposed.XposedInit; import de.robv.android.xposed.XposedInit;
import static io.github.lsposed.lspd.util.FileUtils.getDataPathPrefix;
public class NormalProxy extends BaseProxy { public class NormalProxy extends BaseProxy {
public NormalProxy(Router router) { public NormalProxy(Router router) {
@ -41,7 +42,7 @@ public class NormalProxy extends BaseProxy {
public void forkSystemServerPost() { public void forkSystemServerPost() {
forkPostCommon(true, forkPostCommon(true,
getDataPathPrefix() + "android", "system_server"); new File(Environment.getDataDirectory(), "android").toString(), "system_server");
} }
@ -50,10 +51,7 @@ public class NormalProxy extends BaseProxy {
mRouter.initResourcesHook(); mRouter.initResourcesHook();
mRouter.prepare(isSystem); mRouter.prepare(isSystem);
PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote PrebuiltMethodsDeopter.deoptBootMethods(); // do it once for secondary zygote
ConfigManager.appDataDir = appDataDir; mRouter.installBootstrapHooks(isSystem, appDataDir);
ConfigManager.niceName = niceName;
mRouter.installBootstrapHooks(isSystem);
XposedInit.prefsBasePath = ConfigManager.getPrefsPath("");
mRouter.onEnterChildProcess(); mRouter.onEnterChildProcess();
Utils.logI("Loading modules for " + niceName); Utils.logI("Loading modules for " + niceName);
mRouter.loadModulesSafely(true); mRouter.loadModulesSafely(true);

View File

@ -26,13 +26,11 @@ public interface Router {
void prepare(boolean isSystem); void prepare(boolean isSystem);
String parsePackageName(String appDataDir); void installBootstrapHooks(boolean isSystem, String appDataDir);
void installBootstrapHooks(boolean isSystem);
void loadModulesSafely(boolean callInitZygote); void loadModulesSafely(boolean callInitZygote);
void startBootstrapHook(boolean isSystem); void startBootstrapHook(boolean isSystem, String appDataDir);
void startSystemServerHook(); void startSystemServerHook();

View File

@ -23,45 +23,13 @@ package io.github.lsposed.lspd.sandhook.core;
import io.github.lsposed.lspd.config.LSPdConfigGlobal; import io.github.lsposed.lspd.config.LSPdConfigGlobal;
import io.github.lsposed.lspd.proxy.BaseRouter; import io.github.lsposed.lspd.proxy.BaseRouter;
import io.github.lsposed.lspd.sandhook.config.SandHookProvider; import io.github.lsposed.lspd.sandhook.config.SandHookProvider;
import io.github.lsposed.lspd.sandhook.entry.AppBootstrapHookInfo;
import io.github.lsposed.lspd.sandhook.entry.SysBootstrapHookInfo;
import io.github.lsposed.lspd.sandhook.entry.SysInnerHookInfo;
import io.github.lsposed.lspd.sandhook.hooker.SystemMainHooker;
import io.github.lsposed.lspd.util.Utils;
import com.swift.sandhook.xposedcompat.XposedCompat;
import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge; import com.swift.sandhook.xposedcompat.methodgen.SandHookXposedBridge;
import de.robv.android.xposed.XposedBridge;
public class SandHookRouter extends BaseRouter { public class SandHookRouter extends BaseRouter {
public SandHookRouter() { public SandHookRouter() {
} }
private static boolean useSandHook = false;
public void startBootstrapHook(boolean isSystem) {
if (useSandHook) {
Utils.logD("startBootstrapHook starts: isSystem = " + isSystem);
ClassLoader classLoader = XposedBridge.BOOTCLASSLOADER;
if (isSystem) {
XposedCompat.addHookers(classLoader, SysBootstrapHookInfo.hookItems);
} else {
XposedCompat.addHookers(classLoader, AppBootstrapHookInfo.hookItems);
}
} else {
super.startBootstrapHook(isSystem);
}
}
public void startSystemServerHook() {
if (useSandHook) {
XposedCompat.addHookers(SystemMainHooker.systemServerCL, SysInnerHookInfo.hookItems);
} else {
super.startSystemServerHook();
}
}
public void onEnterChildProcess() { public void onEnterChildProcess() {
SandHookXposedBridge.onForkPost(); SandHookXposedBridge.onForkPost();
//enable compile in child process //enable compile in child process

View File

@ -1,37 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
package io.github.lsposed.lspd.sandhook.entry;
import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd.sandhook.hooker.HandleBindAppHooker;
import io.github.lsposed.lspd.sandhook.hooker.LoadedApkConstructorHooker;
public class AppBootstrapHookInfo implements KeepMembers {
public static String[] hookItemNames = {
HandleBindAppHooker.class.getName(),
LoadedApkConstructorHooker.class.getName(),
};
public static Class[] hookItems = {
HandleBindAppHooker.class,
LoadedApkConstructorHooker.class,
};
}

View File

@ -1,40 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
package io.github.lsposed.lspd.sandhook.entry;
import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd.sandhook.hooker.HandleBindAppHooker;
import io.github.lsposed.lspd.sandhook.hooker.LoadedApkConstructorHooker;
import io.github.lsposed.lspd.sandhook.hooker.SystemMainHooker;
public class SysBootstrapHookInfo implements KeepMembers {
public static String[] hookItemNames = {
HandleBindAppHooker.class.getName(),
SystemMainHooker.class.getName(),
LoadedApkConstructorHooker.class.getName()
};
public static Class[] hookItems = {
HandleBindAppHooker.class,
SystemMainHooker.class,
LoadedApkConstructorHooker.class,
};
}

View File

@ -1,43 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
package io.github.lsposed.lspd.sandhook.entry;
import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd.sandhook.hooker.StartBootstrapServicesHooker;
import io.github.lsposed.lspd.sandhook.hooker.StartBootstrapServicesHooker11;
import io.github.lsposed.lspd.util.Versions;
public class SysInnerHookInfo implements KeepMembers {
public static Class<?> getSysInnerHookerClass() {
return Versions.hasR() ?
StartBootstrapServicesHooker11.class :
StartBootstrapServicesHooker.class;
}
public static String[] hookItemNames = {
getSysInnerHookerClass().getName()
};
public static Class[] hookItems = {
getSysInnerHookerClass()
};
}

View File

@ -1,69 +0,0 @@
/*
* This file is part of LSPosed.
*
* LSPosed is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* LSPosed is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with LSPosed. If not, see <https://www.gnu.org/licenses/>.
*
* Copyright (C) 2020 EdXposed Contributors
* Copyright (C) 2021 LSPosed Contributors
*/
package io.github.lsposed.lspd.sandhook.hooker;
import android.app.ActivityThread;
import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd._hooker.impl.HandleBindApp;
import com.swift.sandhook.SandHook;
import com.swift.sandhook.annotation.HookClass;
import com.swift.sandhook.annotation.HookMethod;
import com.swift.sandhook.annotation.HookMethodBackup;
import com.swift.sandhook.annotation.Param;
import com.swift.sandhook.annotation.SkipParamCheck;
import com.swift.sandhook.annotation.ThisObject;
import java.lang.reflect.Method;
import de.robv.android.xposed.XC_MethodHook;
import de.robv.android.xposed.annotation.ApiSensitive;
import de.robv.android.xposed.annotation.Level;
@ApiSensitive(Level.LOW)
@HookClass(ActivityThread.class)
public class HandleBindAppHooker implements KeepMembers {
public static String className = "android.app.ActivityThread";
public static String methodName = "handleBindApplication";
public static String methodSig = "(Landroid/app/ActivityThread$AppBindData;)V";
@HookMethodBackup("handleBindApplication")
@SkipParamCheck
static Method backup;
@HookMethod("handleBindApplication")
public static void hook(@ThisObject ActivityThread thiz, @Param("android.app.ActivityThread$AppBindData") Object bindData) throws Throwable {
final XC_MethodHook methodHook = new HandleBindApp();
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
param.thisObject = thiz;
param.args = new Object[]{bindData};
methodHook.callBeforeHookedMethod(param);
if (!param.returnEarly) {
backup(thiz, bindData);
}
methodHook.callAfterHookedMethod(param);
}
public static void backup(Object thiz, Object bindData) throws Throwable {
SandHook.callOriginByBackup(backup, thiz, bindData);
}
}

View File

@ -26,7 +26,7 @@ import android.content.pm.ApplicationInfo;
import android.content.res.CompatibilityInfo; import android.content.res.CompatibilityInfo;
import io.github.lsposed.common.KeepMembers; import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd._hooker.impl.LoadedApkCstr; import io.github.lsposed.lspd.hooker.LoadedApkCstrHooker;
import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHook;
import com.swift.sandhook.annotation.HookClass; import com.swift.sandhook.annotation.HookClass;
import com.swift.sandhook.annotation.HookMethod; import com.swift.sandhook.annotation.HookMethod;
@ -59,7 +59,7 @@ public class LoadedApkConstructorHooker implements KeepMembers {
ApplicationInfo aInfo, CompatibilityInfo compatInfo, ApplicationInfo aInfo, CompatibilityInfo compatInfo,
ClassLoader baseLoader, boolean securityViolation, ClassLoader baseLoader, boolean securityViolation,
boolean includeCode, boolean registerPackage) throws Throwable { boolean includeCode, boolean registerPackage) throws Throwable {
final XC_MethodHook methodHook = new LoadedApkCstr(); final XC_MethodHook methodHook = new LoadedApkCstrHooker();
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
param.thisObject = thiz; param.thisObject = thiz;
param.args = new Object[]{activityThread, aInfo, compatInfo, baseLoader, securityViolation, param.args = new Object[]{activityThread, aInfo, compatInfo, baseLoader, securityViolation,

View File

@ -21,7 +21,7 @@
package io.github.lsposed.lspd.sandhook.hooker; package io.github.lsposed.lspd.sandhook.hooker;
import io.github.lsposed.common.KeepMembers; import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices;
import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHook;
import com.swift.sandhook.annotation.HookMethod; import com.swift.sandhook.annotation.HookMethod;
import com.swift.sandhook.annotation.HookMethodBackup; import com.swift.sandhook.annotation.HookMethodBackup;
@ -45,7 +45,7 @@ public class StartBootstrapServicesHooker implements KeepMembers {
@HookMethod("startBootstrapServices") @HookMethod("startBootstrapServices")
public static void hook(@ThisObject Object systemServer) throws Throwable { public static void hook(@ThisObject Object systemServer) throws Throwable {
final XC_MethodHook methodHook = new StartBootstrapServices(); final XC_MethodHook methodHook = new io.github.lsposed.lspd.hooker.StartBootstrapServicesHooker();
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
param.thisObject = systemServer; param.thisObject = systemServer;
param.args = new Object[]{}; param.args = new Object[]{};

View File

@ -21,7 +21,7 @@
package io.github.lsposed.lspd.sandhook.hooker; package io.github.lsposed.lspd.sandhook.hooker;
import io.github.lsposed.common.KeepMembers; import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd._hooker.impl.StartBootstrapServices; import io.github.lsposed.lspd.hooker.StartBootstrapServicesHooker;
import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHook;
import com.swift.sandhook.annotation.HookMethod; import com.swift.sandhook.annotation.HookMethod;
import com.swift.sandhook.annotation.HookMethodBackup; import com.swift.sandhook.annotation.HookMethodBackup;
@ -49,7 +49,7 @@ public class StartBootstrapServicesHooker11 implements KeepMembers {
@HookMethod("startBootstrapServices") @HookMethod("startBootstrapServices")
public static void hook(@ThisObject Object systemServer, @Param("com.android.server.utils.TimingsTraceAndSlog") Object traceAndSlog) throws Throwable { public static void hook(@ThisObject Object systemServer, @Param("com.android.server.utils.TimingsTraceAndSlog") Object traceAndSlog) throws Throwable {
final XC_MethodHook methodHook = new StartBootstrapServices(); final XC_MethodHook methodHook = new StartBootstrapServicesHooker();
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
param.thisObject = systemServer; param.thisObject = systemServer;
param.args = new Object[]{traceAndSlog}; param.args = new Object[]{traceAndSlog};

View File

@ -23,7 +23,7 @@ package io.github.lsposed.lspd.sandhook.hooker;
import android.app.ActivityThread; import android.app.ActivityThread;
import io.github.lsposed.common.KeepMembers; import io.github.lsposed.common.KeepMembers;
import io.github.lsposed.lspd._hooker.impl.SystemMain;
import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHook;
import com.swift.sandhook.annotation.HookClass; import com.swift.sandhook.annotation.HookClass;
import com.swift.sandhook.annotation.HookMethod; import com.swift.sandhook.annotation.HookMethod;
@ -53,7 +53,7 @@ public class SystemMainHooker implements KeepMembers {
@HookMethod("systemMain") @HookMethod("systemMain")
public static ActivityThread hook() throws Throwable { public static ActivityThread hook() throws Throwable {
final XC_MethodHook methodHook = new SystemMain(); final XC_MethodHook methodHook = new io.github.lsposed.lspd.hooker.SystemMainHooker();
final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam(); final XC_MethodHook.MethodHookParam param = new XC_MethodHook.MethodHookParam();
param.thisObject = null; param.thisObject = null;
param.args = new Object[]{}; param.args = new Object[]{};

View File

@ -29,7 +29,6 @@ import static io.github.lsposed.lspd.service.ServiceManager.TAG;
// This config manager assume uid won't change when our service is off. // This config manager assume uid won't change when our service is off.
// Otherwise, user should maintain it manually. // Otherwise, user should maintain it manually.
// TODO: manager package name supports
public class ConfigManager { public class ConfigManager {
static ConfigManager instance = null; static ConfigManager instance = null;
@ -52,6 +51,9 @@ public class ConfigManager {
private String manager = null; private String manager = null;
private int managerUid = -1; private int managerUid = -1;
final private File miscFile = new File(basePath, "misc_path");
private String miscPath = null;
final private File selinuxPath = new File("/sys/fs/selinux/enforce"); final private File selinuxPath = new File("/sys/fs/selinux/enforce");
// only check on boot // only check on boot
final private boolean isPermissive; final private boolean isPermissive;
@ -69,7 +71,7 @@ public class ConfigManager {
}; };
private String readText(@NonNull File file) throws IOException { private String readText(@NonNull File file) throws IOException {
return new String(Files.readAllBytes(file.toPath())); return new String(Files.readAllBytes(file.toPath())).trim();
} }
private String readText(@NonNull File file, String defaultValue) { private String readText(@NonNull File file, String defaultValue) {
@ -108,6 +110,7 @@ public class ConfigManager {
resourceHook = resourceHookSwitch.exists(); resourceHook = resourceHookSwitch.exists();
variant = readInt(variantSwitch, -1); variant = readInt(variantSwitch, -1);
verboseLog = readInt(verboseLogSwitch, 0) == 1; verboseLog = readInt(verboseLogSwitch, 0) == 1;
miscPath = "/data/misc/" + readText(miscFile, "lspd");
updateManager(); updateManager();
} }
@ -333,4 +336,12 @@ public class ConfigManager {
public boolean isManager(int uid) { public boolean isManager(int uid) {
return uid == managerUid; return uid == managerUid;
} }
public String getCachePath(String fileName) {
return miscPath + File.separator + "cache" + File.separator + fileName;
}
public String getPrefsPath(String fileName) {
return miscPath + File.separator + "prefs" + File.separator + fileName;
}
} }

View File

@ -6,6 +6,7 @@ import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import android.util.Pair; import android.util.Pair;
import java.util.List;
import java.util.Set; import java.util.Set;
import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentHashMap;
@ -35,6 +36,30 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
return ConfigManager.getInstance().variant(); return ConfigManager.getInstance().variant();
} }
@Override
public boolean isResourcesHookEnabled() throws RemoteException {
ensureRegistered();
return ConfigManager.getInstance().resourceHook();
}
@Override
public List<String> getModulesList() throws RemoteException {
ensureRegistered();
return ConfigManager.getInstance().getModulesPathForUid(Binder.getCallingUid());
}
@Override
public String getPrefsPath(String packageName) throws RemoteException {
ensureRegistered();
return ConfigManager.getInstance().getPrefsPath(packageName);
}
@Override
public String getCachePath(String fileName) throws RemoteException {
ensureRegistered();
return ConfigManager.getInstance().getCachePath(fileName);
}
// TODO: check if module // TODO: check if module
@Override @Override
public IBinder requestModuleBinder() throws RemoteException { public IBinder requestModuleBinder() throws RemoteException {
@ -42,7 +67,6 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
return ServiceManager.getModuleService(); return ServiceManager.getModuleService();
} }
// TODO: check if manager
@Override @Override
public IBinder requestManagerBinder() throws RemoteException { public IBinder requestManagerBinder() throws RemoteException {
ensureRegistered(); ensureRegistered();

View File

@ -36,7 +36,6 @@ import android.os.RemoteException;
import android.os.UserHandle; import android.os.UserHandle;
import android.widget.Toast; import android.widget.Toast;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
import java.io.File; import java.io.File;
@ -78,63 +77,65 @@ public class PackageReceiver {
private Map<String, String> loadEnabledModules(int uid) { private Map<String, String> loadEnabledModules(int uid) {
HashMap<String, String> result = new HashMap<>(); HashMap<String, String> result = new HashMap<>();
try { // TODO: FIXME
File enabledModules = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME); // try {
if (!enabledModules.exists()) return result; // File enabledModules = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
Scanner scanner = new Scanner(enabledModules); // if (!enabledModules.exists()) return result;
while (scanner.hasNextLine()) { // Scanner scanner = new Scanner(enabledModules);
String packageName = scanner.nextLine(); // while (scanner.hasNextLine()) {
PackageInfo info = getPackageInfo(packageName, 0); // String packageName = scanner.nextLine();
if (info != null && isXposedModule(info.applicationInfo)) // PackageInfo info = getPackageInfo(packageName, 0);
result.put(packageName, info.applicationInfo.sourceDir); // if (info != null && isXposedModule(info.applicationInfo))
else if (info == null) // result.put(packageName, info.applicationInfo.sourceDir);
result.put(packageName, null); // else if (info == null)
} // result.put(packageName, null);
} catch (Throwable e) { // }
Utils.logE("Unable to read enabled modules", e); // } catch (Throwable e) {
} // Utils.logE("Unable to read enabled modules", e);
// }
return result; return result;
} }
private boolean updateModuleList(int uid, String packageName) { private boolean updateModuleList(int uid, String packageName) {
Map<String, String> enabledModules = loadEnabledModules(uid); Map<String, String> enabledModules = loadEnabledModules(uid);
// TODO: FIXME
if (!enabledModules.containsKey(packageName)) return false; //
// if (!enabledModules.containsKey(packageName)) return false;
try { //
File moduleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + MODULES_LIST_FILENAME); // try {
File enabledModuleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME); // File moduleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + MODULES_LIST_FILENAME);
if (moduleListFile.exists() && !moduleListFile.canWrite()) { // File enabledModuleListFile = new File(ConfigManager.getMiscPath(), uid + "/" + ENABLED_MODULES_LIST_FILENAME);
moduleListFile.delete(); // if (moduleListFile.exists() && !moduleListFile.canWrite()) {
moduleListFile.createNewFile(); // moduleListFile.delete();
} // moduleListFile.createNewFile();
if (enabledModuleListFile.exists() && !enabledModuleListFile.canWrite()) { // }
enabledModuleListFile.delete(); // if (enabledModuleListFile.exists() && !enabledModuleListFile.canWrite()) {
enabledModuleListFile.createNewFile(); // enabledModuleListFile.delete();
} // enabledModuleListFile.createNewFile();
PrintWriter modulesList = new PrintWriter(moduleListFile); // }
PrintWriter enabledModulesList = new PrintWriter(enabledModuleListFile); // PrintWriter modulesList = new PrintWriter(moduleListFile);
for (Map.Entry<String, String> module : enabledModules.entrySet()) { // PrintWriter enabledModulesList = new PrintWriter(enabledModuleListFile);
String apkPath = module.getValue(); // for (Map.Entry<String, String> module : enabledModules.entrySet()) {
if (apkPath != null) { // String apkPath = module.getValue();
modulesList.println(module.getValue()); // if (apkPath != null) {
enabledModulesList.println(module.getKey()); // modulesList.println(module.getValue());
} else { // enabledModulesList.println(module.getKey());
Utils.logI(String.format("remove obsolete package %s", packageName)); // } else {
File prefsDir = new File(ConfigManager.getMiscPath(), uid + "/prefs/" + packageName); // Utils.logI(String.format("remove obsolete package %s", packageName));
File[] fileList = prefsDir.listFiles(); // File prefsDir = new File(ConfigManager.getMiscPath(), uid + "/prefs/" + packageName);
if (fileList != null) { // File[] fileList = prefsDir.listFiles();
for (File childFile : fileList) { // if (fileList != null) {
childFile.delete(); // for (File childFile : fileList) {
} // childFile.delete();
} // }
} // }
} // }
modulesList.close(); // }
enabledModulesList.close(); // modulesList.close();
} catch (Throwable e) { // enabledModulesList.close();
Utils.logE("Fail to update module list", e); // } catch (Throwable e) {
} // Utils.logE("Fail to update module list", e);
// }
return true; return true;
} }
@ -168,36 +169,37 @@ public class PackageReceiver {
PackageInfo pkgInfo = getPackageInfo(packageName, intent.getIntExtra(Intent.EXTRA_USER, 0)); PackageInfo pkgInfo = getPackageInfo(packageName, intent.getIntExtra(Intent.EXTRA_USER, 0));
if (pkgInfo != null && !isXposedModule(pkgInfo.applicationInfo)) return; if (pkgInfo != null && !isXposedModule(pkgInfo.applicationInfo)) return;
// TODO: FIXME
try { //
for (int uid : UserService.getUsers()) { // try {
Utils.logI("updating uid: " + uid); // for (int uid : UserService.getUsers()) {
boolean activated = updateModuleList(uid, packageName); // Utils.logI("updating uid: " + uid);
UserHandle userHandle = null; // boolean activated = updateModuleList(uid, packageName);
try { // UserHandle userHandle = null;
userHandle = (UserHandle) XposedHelpers.callStaticMethod(UserHandle.class, "of", uid); // try {
} catch (Throwable t) { // userHandle = (UserHandle) XposedHelpers.callStaticMethod(UserHandle.class, "of", uid);
Utils.logW("get user handle failed", t); // } catch (Throwable t) {
} // Utils.logW("get user handle failed", t);
if (userHandle != null) { // }
try { // if (userHandle != null) {
Intent broadCast = new Intent(activated ? MODULE_UPDATED : MODULE_NOT_ACTIVATAED); // try {
broadCast.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 0x01000000); // Intent broadCast = new Intent(activated ? MODULE_UPDATED : MODULE_NOT_ACTIVATAED);
broadCast.setData(intent.getData()); // broadCast.setFlags(Intent.FLAG_INCLUDE_STOPPED_PACKAGES | 0x01000000);
broadCast.setPackage(ConfigManager.getInstallerPackageName()); // broadCast.setData(intent.getData());
XposedHelpers.callMethod(context, "sendBroadcastAsUser", broadCast, userHandle); // broadCast.setPackage(ConfigManager.getInstallerPackageName());
Utils.logI("broadcast to " + ConfigManager.getInstallerPackageName()); // XposedHelpers.callMethod(context, "sendBroadcastAsUser", broadCast, userHandle);
} catch (Throwable t) { // Utils.logI("broadcast to " + ConfigManager.getInstallerPackageName());
Utils.logW("send broadcast failed", t); // } catch (Throwable t) {
Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show(); // Utils.logW("send broadcast failed", t);
} // Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show();
} else if (activated) { // }
Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show(); // } else if (activated) {
} // Toast.makeText(context, "LSPosed: Updated " + packageName, Toast.LENGTH_SHORT).show();
} // }
} catch (Throwable e) { // }
Utils.logW("update failed", e); // } catch (Throwable e) {
} // Utils.logW("update failed", e);
// }
} }
}; };

View File

@ -8,7 +8,6 @@ import android.os.ServiceManager;
import java.util.ArrayList; import java.util.ArrayList;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.utils.ParceledListSlice; import io.github.lsposed.lspd.utils.ParceledListSlice;
public class PackageService { public class PackageService {
@ -35,15 +34,6 @@ public class PackageService {
return pm.getPackagesForUid(uid); return pm.getPackagesForUid(uid);
} }
public static boolean isInstaller(int uid) throws RemoteException {
boolean res = false;
String InstallerPackageName = ConfigManager.getInstallerPackageName();
for (String pkg : getPackagesForUid(uid)) {
res = res || InstallerPackageName.equals(pkg);
}
return res;
}
public static ParceledListSlice<PackageInfo> getInstalledPackagesFromAllUsers(int flags) throws RemoteException { public static ParceledListSlice<PackageInfo> getInstalledPackagesFromAllUsers(int flags) throws RemoteException {
ArrayList<PackageInfo> res = new ArrayList<>(); ArrayList<PackageInfo> res = new ArrayList<>();
IPackageManager pm = getPackageManager(); IPackageManager pm = getPackageManager();

View File

@ -22,8 +22,6 @@ package io.github.lsposed.lspd.util;
import android.text.TextUtils; import android.text.TextUtils;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import java.io.BufferedReader; import java.io.BufferedReader;
import java.io.BufferedWriter; import java.io.BufferedWriter;
import java.io.File; import java.io.File;
@ -90,8 +88,4 @@ public class FileUtils {
} }
return dataDir.substring(lastIndex + 1); return dataDir.substring(lastIndex + 1);
} }
public static String getDataPathPrefix() {
return ConfigManager.getDataPathPrefix() + "/";
}
} }

View File

@ -20,7 +20,6 @@
package io.github.lsposed.lspd.yahfa.dexmaker; package io.github.lsposed.lspd.yahfa.dexmaker;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
import java.io.File; import java.io.File;
@ -33,15 +32,17 @@ import external.com.android.dx.Code;
import external.com.android.dx.Local; import external.com.android.dx.Local;
import external.com.android.dx.TypeId; import external.com.android.dx.TypeId;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
@SuppressWarnings({"rawtypes", "unchecked"}) @SuppressWarnings({"rawtypes", "unchecked"})
public class DexMakerUtils { public class DexMakerUtils {
public static boolean canCache = true; public static boolean canCache = true;
static { static {
File cacheDir = new File(ConfigManager.getCachePath("")); File cacheDir = new File(serviceClient.getCachePath(""));
if(!cacheDir.canRead() || !cacheDir.canWrite()) { if(!cacheDir.canRead() || !cacheDir.canWrite()) {
Utils.logW("Cache disabled"); Utils.logW("Cache disabled with path " + cacheDir.getAbsolutePath());
canCache = false; canCache = false;
} }
} }

View File

@ -24,7 +24,6 @@ import android.annotation.TargetApi;
import android.os.Build; import android.os.Build;
import io.github.lsposed.lspd.BuildConfig; import io.github.lsposed.lspd.BuildConfig;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.core.yahfa.HookMain; import io.github.lsposed.lspd.core.yahfa.HookMain;
import io.github.lsposed.lspd.util.ProxyClassLoader; import io.github.lsposed.lspd.util.ProxyClassLoader;
@ -46,6 +45,7 @@ import external.com.android.dx.Local;
import external.com.android.dx.MethodId; import external.com.android.dx.MethodId;
import external.com.android.dx.TypeId; import external.com.android.dx.TypeId;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoBoxIfNecessary; import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoBoxIfNecessary;
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoUnboxIfNecessary; import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.autoUnboxIfNecessary;
import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.canCache; import static io.github.lsposed.lspd.yahfa.dexmaker.DexMakerUtils.canCache;
@ -167,17 +167,17 @@ public class HookerDexMaker {
String suffix = DexMakerUtils.getSha1Hex(mMember.toString()); String suffix = DexMakerUtils.getSha1Hex(mMember.toString());
className = className + suffix; className = className + suffix;
String dexFileName = className + ".jar"; String dexFileName = className + ".jar";
File dexFile = new File(ConfigManager.getCachePath(dexFileName)); File dexFile = new File(serviceClient.getCachePath(dexFileName));
if (!dexFile.exists()) { if (!dexFile.exists()) {
// if file exists, reuse it and skip generating // if file exists, reuse it and skip generating
DexLog.d("Generating " + dexFileName); DexLog.d("Generating " + dexFileName);
doGenerate(className); doGenerate(className);
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName, false); loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexFileName, false);
dexFile.setWritable(true, false); dexFile.setWritable(true, false);
dexFile.setReadable(true, false); dexFile.setReadable(true, false);
} else { } else {
DexLog.d("Using cache " + dexFileName); DexLog.d("Using cache " + dexFileName);
loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexFileName); loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexFileName);
} }
usedCache = true; usedCache = true;
} catch (Throwable ignored) {} } catch (Throwable ignored) {}

View File

@ -3,7 +3,6 @@ package com.swift.sandhook.xposedcompat;
import android.os.Process; import android.os.Process;
import android.text.TextUtils; import android.text.TextUtils;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.util.FileUtils; import io.github.lsposed.lspd.util.FileUtils;
import io.github.lsposed.lspd.util.ProcessUtils; import io.github.lsposed.lspd.util.ProcessUtils;
import io.github.lsposed.lspd.util.ProxyClassLoader; import io.github.lsposed.lspd.util.ProxyClassLoader;
@ -16,8 +15,6 @@ import java.lang.reflect.Member;
import de.robv.android.xposed.XposedBridge; import de.robv.android.xposed.XposedBridge;
import static io.github.lsposed.lspd.util.FileUtils.getDataPathPrefix;
public class XposedCompat { public class XposedCompat {
// TODO initialize these variables // TODO initialize these variables
@ -49,11 +46,12 @@ public class XposedCompat {
} }
public static File getCacheDir() { public static File getCacheDir() {
if (cacheDir == null) { // TODO: cache path?
String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/"; // if (cacheDir == null) {
cacheDir = new File(fixedAppDataDir, "/cache/sandhook/" // String fixedAppDataDir = getDataPathPrefix() + getPackageName(ConfigManager.appDataDir) + "/";
+ ProcessUtils.getProcessName(Process.myPid()).replace(":", "_") + "/"); // cacheDir = new File(fixedAppDataDir, "/cache/sandhook/"
} // + ProcessUtils.getProcessName(Process.myPid()).replace(":", "_") + "/");
// }
return cacheDir; return cacheDir;
} }

View File

@ -1,6 +1,5 @@
package com.swift.sandhook.xposedcompat.methodgen; package com.swift.sandhook.xposedcompat.methodgen;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHook;
import com.swift.sandhook.SandHookMethodResolver; import com.swift.sandhook.SandHookMethodResolver;
import com.swift.sandhook.wrapper.HookWrapper; import com.swift.sandhook.wrapper.HookWrapper;
@ -34,6 +33,7 @@ import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.canCache;
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals;
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive;
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
public class HookerDexMaker implements HookMaker { public class HookerDexMaker implements HookMaker {
@ -187,7 +187,7 @@ public class HookerDexMaker implements HookMaker {
HookWrapper.HookEntity hookEntity = null; HookWrapper.HookEntity hookEntity = null;
//try load cache first //try load cache first
try { try {
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName); ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName);
if (loader != null) { if (loader != null) {
hookEntity = loadHookerClass(loader, className); hookEntity = loadHookerClass(loader, className);
} }
@ -215,8 +215,8 @@ public class HookerDexMaker implements HookMaker {
ClassLoader loader; ClassLoader loader;
if (canCache) { if (canCache) {
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true); loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName, true);
File dexFile = new File(ConfigManager.getCachePath(dexName)); File dexFile = new File(serviceClient.getCachePath(dexName));
dexFile.setWritable(true, false); dexFile.setWritable(true, false);
dexFile.setReadable(true, false); dexFile.setReadable(true, false);
} else { } else {

View File

@ -1,6 +1,5 @@
package com.swift.sandhook.xposedcompat.methodgen; package com.swift.sandhook.xposedcompat.methodgen;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import com.swift.sandhook.SandHook; import com.swift.sandhook.SandHook;
import com.swift.sandhook.wrapper.HookWrapper; import com.swift.sandhook.wrapper.HookWrapper;
import com.swift.sandhook.xposedcompat.hookstub.HookStubManager; import com.swift.sandhook.xposedcompat.hookstub.HookStubManager;
@ -30,6 +29,7 @@ import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.canCache;
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.createResultLocals;
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getObjTypeIdIfPrimitive;
import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex; import static com.swift.sandhook.xposedcompat.utils.DexMakerUtils.getSha1Hex;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
public class HookerDexMakerNew implements HookMaker { public class HookerDexMakerNew implements HookMaker {
@ -148,7 +148,7 @@ public class HookerDexMakerNew implements HookMaker {
HookWrapper.HookEntity hookEntity = null; HookWrapper.HookEntity hookEntity = null;
//try load cache first //try load cache first
try { try {
ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName); ClassLoader loader = mDexMaker.loadClassDirect(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName);
if (loader != null) { if (loader != null) {
hookEntity = loadHookerClass(loader, className); hookEntity = loadHookerClass(loader, className);
} }
@ -176,8 +176,8 @@ public class HookerDexMakerNew implements HookMaker {
} }
// Create the dex file and load it. // Create the dex file and load it.
try { try {
loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(ConfigManager.getCachePath("")), dexName, true); loader = mDexMaker.generateAndLoad(mAppClassLoader, new File(serviceClient.getCachePath("")), dexName, true);
File dexFile = new File(ConfigManager.getCachePath(dexName)); File dexFile = new File(serviceClient.getCachePath(dexName));
dexFile.setWritable(true, false); dexFile.setWritable(true, false);
dexFile.setReadable(true, false); dexFile.setReadable(true, false);
} catch (IOException e) { } catch (IOException e) {

View File

@ -4,7 +4,6 @@ import android.os.Build;
import android.os.Process; import android.os.Process;
import android.os.Trace; import android.os.Trace;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.nativebridge.Yahfa; import io.github.lsposed.lspd.nativebridge.Yahfa;
import io.github.lsposed.lspd.util.ClassLoaderUtils; import io.github.lsposed.lspd.util.ClassLoaderUtils;
import io.github.lsposed.lspd.util.FileUtils; import io.github.lsposed.lspd.util.FileUtils;

View File

@ -1,5 +1,4 @@
package com.swift.sandhook.xposedcompat.utils; package com.swift.sandhook.xposedcompat.utils;
import io.github.lsposed.lspd.nativebridge.ConfigManager;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;
import java.io.File; import java.io.File;
@ -15,12 +14,14 @@ import external.com.android.dx.Code;
import external.com.android.dx.Local; import external.com.android.dx.Local;
import external.com.android.dx.TypeId; import external.com.android.dx.TypeId;
import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceClient;
public class DexMakerUtils { public class DexMakerUtils {
public static boolean canCache = true; public static boolean canCache = true;
static { static {
File cacheDir = new File(ConfigManager.getCachePath("")); File cacheDir = new File(serviceClient.getCachePath(""));
if(!cacheDir.canRead() || !cacheDir.canWrite()) { if(!cacheDir.canRead() || !cacheDir.canWrite()) {
Utils.logW("Cache disabled"); Utils.logW("Cache disabled");
canCache = false; canCache = false;

View File

@ -223,6 +223,10 @@ else
fi fi
fi fi
touch /data/adb/lspd/new_install || abortC "! ${LANG_CUST_ERR_CONF_FIRST}" touch /data/adb/lspd/new_install || abortC "! ${LANG_CUST_ERR_CONF_FIRST}"
ui_print "- ${LANG_CUST_INST_COPY_LIB}"
mkdir -p /data/adb/lspd/config
rm -rf "/data/adb/lspd/framework"
mv "${MODPATH}/system/framework" "/data/adb/lspd/framework"
set_perm_recursive /data/adb/lspd root root 0700 0600 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}" set_perm_recursive /data/adb/lspd root root 0700 0600 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
mkdir -p /data/misc/$MISC_PATH/0/conf/ || abortC "! ${LANG_CUST_ERR_CONF_CREATE}" mkdir -p /data/misc/$MISC_PATH/0/conf/ || abortC "! ${LANG_CUST_ERR_CONF_CREATE}"
set_perm /data/misc/$MISC_PATH root root 0771 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}" set_perm /data/misc/$MISC_PATH root root 0771 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
@ -230,9 +234,9 @@ echo "rm -rf /data/misc/$MISC_PATH" >> "${MODPATH}/uninstall.sh" || abortC "! ${
echo "[[ -f /data/adb/lspd/new_install ]] || rm -rf /data/adb/lspd" >> "${MODPATH}/uninstall.sh" || abortC "! ${LANG_CUST_ERR_CONF_UNINST}" echo "[[ -f /data/adb/lspd/new_install ]] || rm -rf /data/adb/lspd" >> "${MODPATH}/uninstall.sh" || abortC "! ${LANG_CUST_ERR_CONF_UNINST}"
if [ $VARIANT == 17 ]; then # YAHFA if [ $VARIANT == 17 ]; then # YAHFA
echo "1" > /data/misc/$MISC_PATH/variant echo "1" > /data/adb/lspd/config/variant
elif [ $VARIANT == 18 ]; then # SandHook elif [ $VARIANT == 18 ]; then # SandHook
echo "2" > /data/misc/$MISC_PATH/variant echo "2" > /data/adb/lspd/config/variant
else else
abortC "${LANG_UTIL_ERR_VARIANT_UNSUPPORT} ${VARIANT}" abortC "${LANG_UTIL_ERR_VARIANT_UNSUPPORT} ${VARIANT}"
fi fi
@ -241,12 +245,6 @@ if [[ ! -e /data/misc/$MISC_PATH/disable_verbose_log ]]; then
echo "1" > /data/misc/$MISC_PATH/disable_verbose_log echo "1" > /data/misc/$MISC_PATH/disable_verbose_log
fi fi
ui_print "- ${LANG_CUST_INST_COPY_LIB}"
rm -rf "/data/misc/$MISC_PATH/framework"
mv "${MODPATH}/system/framework" "/data/misc/$MISC_PATH/framework"
set_perm_recursive /data/misc/$MISC_PATH/framework root root 0755 0644 "u:object_r:magisk_file:s0" || abortC "! ${LANG_CUST_ERR_PERM}"
mkdir -p /data/misc/$MISC_PATH/cache mkdir -p /data/misc/$MISC_PATH/cache
rm /data/misc/$MISC_PATH/cache/* rm /data/misc/$MISC_PATH/cache/*

View File

@ -27,7 +27,4 @@ if [[ -f "${MODDIR}/reboot_twice_flag" ]]; then
reboot reboot
fi fi
MISC_PATH=$(cat /data/adb/lspd/misc_path) /system/bin/app_process -Djava.class.path=/data/adb/lspd/framework/lspd.dex /system/bin --nice-name=lspd io.github.lsposed.lspd.core.Main
BASE_PATH="/data/misc/$MISC_PATH"
/system/bin/app_process -Djava.class.path=${BASE_PATH}/framework/lspd.dex /system/bin --nice-name=lspd io.github.lsposed.lspd.core.Main