[core] Workaround for binder: allow blocking
This commit is contained in:
parent
0ec8959235
commit
2890aec54f
|
|
@ -39,9 +39,6 @@
|
|||
#include "jni/native_api.h"
|
||||
#include "service.h"
|
||||
|
||||
#pragma clang diagnostic push
|
||||
#pragma clang diagnostic ignored "-Wunused-value"
|
||||
|
||||
namespace lspd {
|
||||
namespace fs = std::filesystem;
|
||||
|
||||
|
|
@ -132,6 +129,7 @@ namespace lspd {
|
|||
RegisterEdxpYahfa(env);
|
||||
RegisterPendingHooks(env);
|
||||
RegisterNativeAPI(env);
|
||||
// TODO: Recover this
|
||||
|
||||
// variant_ = Variant(ConfigManager::GetInstance()->GetVariant());
|
||||
// LOGI("LSP Variant: %d", variant_);
|
||||
|
|
@ -193,15 +191,7 @@ namespace lspd {
|
|||
}
|
||||
|
||||
void
|
||||
Context::OnNativeForkSystemServerPre([[maybe_unused]] JNIEnv *env,
|
||||
[[maybe_unused]] jclass clazz,
|
||||
[[maybe_unused]] uid_t uid,
|
||||
[[maybe_unused]] gid_t gid,
|
||||
[[maybe_unused]] jintArray gids,
|
||||
[[maybe_unused]] jint runtime_flags,
|
||||
[[maybe_unused]] jobjectArray rlimits,
|
||||
[[maybe_unused]] jlong permitted_capabilities,
|
||||
[[maybe_unused]] jlong effective_capabilities) {
|
||||
Context::OnNativeForkSystemServerPre(JNIEnv *env) {
|
||||
Service::instance()->InitService(env);
|
||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||
skip_ = false;
|
||||
|
|
@ -231,31 +221,24 @@ namespace lspd {
|
|||
Service::instance()->HookBridge(*this, env);
|
||||
}
|
||||
|
||||
void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz,
|
||||
jint uid, jint gid,
|
||||
jintArray gids,
|
||||
jint runtime_flags,
|
||||
jobjectArray rlimits,
|
||||
jint mount_external,
|
||||
jstring se_info,
|
||||
void Context::OnNativeForkAndSpecializePre(JNIEnv *env,
|
||||
jint uid,
|
||||
jstring nice_name,
|
||||
jintArray fds_to_close,
|
||||
jintArray fds_to_ignore,
|
||||
jboolean is_child_zygote,
|
||||
jstring instruction_set,
|
||||
jstring app_data_dir) {
|
||||
PreLoadDex(ConfigManager::GetInjectDexPath());
|
||||
Service::instance()->InitService(env);
|
||||
this->uid = uid;
|
||||
const auto app_id = uid % PER_USER_RANGE;
|
||||
nice_name_ = nice_name;
|
||||
JUTFString process_name(env, nice_name);
|
||||
skip_ = false;
|
||||
if (!skip_ && !app_data_dir) {
|
||||
LOGD("skip injecting into %d because it has no data dir", uid);
|
||||
LOGD("skip injecting into %s because it has no data dir", process_name.get());
|
||||
skip_ = true;
|
||||
}
|
||||
if (!skip_ && is_child_zygote) {
|
||||
skip_ = true;
|
||||
LOGD("skip injecting into %d because it's a child zygote", uid);
|
||||
LOGD("skip injecting into %s because it's a child zygote", process_name.get());
|
||||
}
|
||||
|
||||
if (!skip_ && ((app_id >= FIRST_ISOLATED_UID && app_id <= LAST_ISOLATED_UID) ||
|
||||
|
|
@ -263,7 +246,7 @@ namespace lspd {
|
|||
app_id <= LAST_APP_ZYGOTE_ISOLATED_UID) ||
|
||||
app_id == SHARED_RELRO_UID)) {
|
||||
skip_ = true;
|
||||
LOGI("skip injecting into %d because it's isolated", uid);
|
||||
LOGI("skip injecting into %s because it's isolated", process_name.get());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
@ -289,5 +272,3 @@ namespace lspd {
|
|||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma clang diagnostic pop
|
||||
|
|
@ -56,21 +56,13 @@ namespace lspd {
|
|||
return FindClassFromLoader(env, GetCurrentClassLoader(), className);
|
||||
};
|
||||
|
||||
void OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint uid, jint gid,
|
||||
jintArray gids, jint runtime_flags, jobjectArray rlimits,
|
||||
jint mount_external,
|
||||
jstring se_info, jstring se_name, jintArray fds_to_close,
|
||||
jintArray fds_to_ignore, jboolean is_child_zygote,
|
||||
jstring instruction_set, jstring app_data_dir);
|
||||
void OnNativeForkAndSpecializePre(JNIEnv *env, jint uid, jstring nice_name, jboolean is_child_zygote, jstring app_data_dir);
|
||||
|
||||
void OnNativeForkAndSpecializePost(JNIEnv *env);
|
||||
|
||||
void OnNativeForkSystemServerPost(JNIEnv *env, jint res);
|
||||
|
||||
void OnNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid,
|
||||
jintArray gids, jint runtime_flags, jobjectArray rlimits,
|
||||
jlong permitted_capabilities,
|
||||
jlong effective_capabilities);
|
||||
void OnNativeForkSystemServerPre(JNIEnv *env);
|
||||
|
||||
|
||||
private:
|
||||
|
|
@ -82,7 +74,6 @@ namespace lspd {
|
|||
JavaVM *vm_ = nullptr;
|
||||
jclass class_linker_class_ = nullptr;
|
||||
jmethodID post_fixup_static_mid_ = nullptr;
|
||||
jint uid = -1;
|
||||
bool skip_ = false;
|
||||
std::vector<signed char> dex{};
|
||||
|
||||
|
|
|
|||
|
|
@ -37,64 +37,58 @@ namespace lspd {
|
|||
ConfigManager::Init();
|
||||
}
|
||||
|
||||
static int shouldSkipUid(int uid) {
|
||||
static int shouldSkipUid(int) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void nativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint *_uid, jint *gid,
|
||||
jintArray *gids, jint *runtime_flags,
|
||||
jobjectArray *rlimits, jint *mount_external,
|
||||
jstring *se_info, jstring *nice_name,
|
||||
jintArray *fds_to_close, jintArray *fds_to_ignore,
|
||||
jboolean *start_child_zygote, jstring *instruction_set,
|
||||
jstring *app_data_dir, jboolean *is_top_app, jobjectArray *pkg_data_info_list,
|
||||
jobjectArray *whitelisted_data_info_list, jboolean *bind_mount_app_data_dirs,
|
||||
jboolean *bind_mount_app_storage_dirs) {
|
||||
Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *_uid, *gid, *gids,
|
||||
*runtime_flags, *rlimits,
|
||||
*mount_external, *se_info, *nice_name,
|
||||
*fds_to_close,
|
||||
*fds_to_ignore,
|
||||
*start_child_zygote, *instruction_set,
|
||||
static void nativeForkAndSpecializePre(JNIEnv *env, jclass, jint *_uid, jint *,
|
||||
jintArray *, jint *,
|
||||
jobjectArray *, jint *,
|
||||
jstring *, jstring *nice_name,
|
||||
jintArray *, jintArray *,
|
||||
jboolean *start_child_zygote, jstring *,
|
||||
jstring *app_data_dir, jboolean *,
|
||||
jobjectArray *,
|
||||
jobjectArray *,
|
||||
jboolean *,
|
||||
jboolean *) {
|
||||
Context::GetInstance()->OnNativeForkAndSpecializePre(env, *_uid,
|
||||
*nice_name,
|
||||
*start_child_zygote,
|
||||
*app_data_dir);
|
||||
}
|
||||
|
||||
static void nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) {
|
||||
Context::GetInstance()->OnNativeForkAndSpecializePost(env);
|
||||
static void nativeForkAndSpecializePost(JNIEnv *env, jclass, jint res) {
|
||||
if (res == 0)
|
||||
Context::GetInstance()->OnNativeForkAndSpecializePost(env);
|
||||
}
|
||||
|
||||
static void nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid,
|
||||
jintArray *gids, jint *runtime_flags,
|
||||
jobjectArray *rlimits, jlong *permitted_capabilities,
|
||||
jlong *effective_capabilities) {
|
||||
Context::GetInstance()->OnNativeForkSystemServerPre(env, clazz, *uid, *gid, *gids,
|
||||
*runtime_flags, *rlimits,
|
||||
*permitted_capabilities,
|
||||
*effective_capabilities
|
||||
);
|
||||
static void nativeForkSystemServerPre(JNIEnv *env, jclass, uid_t *, gid_t *,
|
||||
jintArray *, jint *,
|
||||
jobjectArray *, jlong *,
|
||||
jlong *) {
|
||||
Context::GetInstance()->OnNativeForkSystemServerPre(env);
|
||||
}
|
||||
|
||||
static void nativeForkSystemServerPost(JNIEnv *env, [[maybe_unused]] jclass clazz, jint res) {
|
||||
static void nativeForkSystemServerPost(JNIEnv *env, jclass, jint res) {
|
||||
Context::GetInstance()->OnNativeForkSystemServerPost(env, res);
|
||||
}
|
||||
|
||||
/* method added in Android Q */
|
||||
static void specializeAppProcessPre(JNIEnv *env, jclass clazz, jint *uid, jint *gid,
|
||||
jintArray *gids, jint *runtime_flags, jobjectArray *rlimits,
|
||||
jint *mount_external, jstring *se_info, jstring *nice_name,
|
||||
jboolean *start_child_zygote, jstring *instruction_set,
|
||||
jstring *app_data_dir, jboolean *is_top_app, jobjectArray *pkg_data_info_list,
|
||||
jobjectArray *whitelisted_data_info_list, jboolean *bind_mount_app_data_dirs,
|
||||
jboolean *bind_mount_app_storage_dirs) {
|
||||
Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *uid, *gid, *gids,
|
||||
*runtime_flags, *rlimits,
|
||||
*mount_external, *se_info, *nice_name,
|
||||
nullptr, nullptr,
|
||||
*start_child_zygote, *instruction_set,
|
||||
static void specializeAppProcessPre(JNIEnv *env, jclass, jint *uid, jint *,
|
||||
jintArray *, jint *, jobjectArray *,
|
||||
jint *, jstring *, jstring *nice_name,
|
||||
jboolean *start_child_zygote, jstring *,
|
||||
jstring *app_data_dir, jboolean *,
|
||||
jobjectArray *,
|
||||
jobjectArray *,
|
||||
jboolean *,
|
||||
jboolean *) {
|
||||
Context::GetInstance()->OnNativeForkAndSpecializePre(env, *uid, *nice_name, *start_child_zygote,
|
||||
*app_data_dir);
|
||||
}
|
||||
|
||||
static void specializeAppProcessPost(JNIEnv *env, [[maybe_unused]] jclass clazz) {
|
||||
static void specializeAppProcessPost(JNIEnv *env, jclass) {
|
||||
Context::GetInstance()->OnNativeForkAndSpecializePost(env);
|
||||
}
|
||||
}
|
||||
|
|
@ -110,7 +104,9 @@ RIRU_EXPORT void *init(void *arg) {
|
|||
switch (step) {
|
||||
case 1: {
|
||||
auto core_max_api_version = *(int *) arg;
|
||||
riru_api_version = core_max_api_version <= RIRU_MODULE_API_VERSION ? core_max_api_version : RIRU_MODULE_API_VERSION;
|
||||
riru_api_version =
|
||||
core_max_api_version <= RIRU_MODULE_API_VERSION ? core_max_api_version
|
||||
: RIRU_MODULE_API_VERSION;
|
||||
return &riru_api_version;
|
||||
}
|
||||
case 2: {
|
||||
|
|
|
|||
|
|
@ -154,12 +154,9 @@ namespace lspd {
|
|||
if (res) {
|
||||
JNI_CallVoidMethod(env, reply, readExceptionMethod_);
|
||||
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
|
||||
} else {
|
||||
LOGD("no reply");
|
||||
}
|
||||
|
||||
JNI_CallVoidMethod(env, data, recycleMethod_);
|
||||
JNI_CallObjectMethod(env, reply, recycleMethod_);
|
||||
JNI_CallVoidMethod(env, reply, recycleMethod_);
|
||||
|
||||
return service;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -36,9 +36,7 @@ namespace lspd {
|
|||
inline static std::unique_ptr<Service> instance_ = std::make_unique<Service>();
|
||||
bool initialized_ = false;
|
||||
|
||||
Service() {
|
||||
|
||||
}
|
||||
Service() = default;
|
||||
|
||||
static jboolean
|
||||
call_boolean_method_va_replace(JNIEnv *env, jobject obj, jmethodID methodId, va_list args);
|
||||
|
|
|
|||
|
|
@ -20,7 +20,6 @@
|
|||
|
||||
package io.github.lsposed.lspd.core.yahfa;
|
||||
|
||||
import io.github.lsposed.lspd.nativebridge.Heap;
|
||||
import io.github.lsposed.lspd.nativebridge.Yahfa;
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
|
|
|
|||
|
|
@ -1,39 +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.framework;
|
||||
|
||||
import io.github.lsposed.lspd.util.Utils;
|
||||
|
||||
import de.robv.android.xposed.XposedHelpers;
|
||||
import de.robv.android.xposed.annotation.ApiSensitive;
|
||||
import de.robv.android.xposed.annotation.Level;
|
||||
|
||||
@ApiSensitive(Level.LOW)
|
||||
public class Zygote {
|
||||
public static void allowFileAcrossFork(String path) {
|
||||
try {
|
||||
Class zygote = XposedHelpers.findClass("com.android.internal.os.Zygote", null);
|
||||
XposedHelpers.callStaticMethod(zygote, "nativeAllowFileAcrossFork", path);
|
||||
} catch (Throwable throwable) {
|
||||
Utils.logE("error when allowFileAcrossFork", throwable);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -1,25 +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 Heap {
|
||||
public static native int waitForGcToComplete();
|
||||
}
|
||||
|
|
@ -13,6 +13,7 @@ import androidx.annotation.Nullable;
|
|||
import java.lang.reflect.Field;
|
||||
import java.util.Map;
|
||||
|
||||
import static hidden.HiddenApiBridge.Binder_allowBlocking;
|
||||
import static io.github.lsposed.lspd.service.ServiceManager.TAG;
|
||||
|
||||
public class BridgeService {
|
||||
|
|
@ -21,6 +22,7 @@ public class BridgeService {
|
|||
private static final String SERVICE_NAME = "activity";
|
||||
|
||||
enum ACTION {
|
||||
ACTION_UNKNOWN,
|
||||
ACTION_SEND_BINDER,
|
||||
ACTION_GET_BINDER,
|
||||
}
|
||||
|
|
@ -149,7 +151,7 @@ public class BridgeService {
|
|||
serviceBinder.unlinkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0);
|
||||
}
|
||||
|
||||
serviceBinder = binder;
|
||||
serviceBinder = Binder_allowBlocking(binder);
|
||||
service = ILSPosedService.Stub.asInterface(serviceBinder);
|
||||
try {
|
||||
serviceBinder.linkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0);
|
||||
|
|
@ -171,7 +173,7 @@ public class BridgeService {
|
|||
}
|
||||
|
||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||
public static boolean onTransact(int code, @NonNull Parcel data, @Nullable Parcel reply, int flags) {
|
||||
public static boolean onTransact(@NonNull Parcel data, @Nullable Parcel reply, int flags) {
|
||||
data.enforceInterface(DESCRIPTOR);
|
||||
|
||||
ACTION action = ACTION.values()[data.readInt()];
|
||||
|
|
@ -209,13 +211,13 @@ public class BridgeService {
|
|||
|
||||
@SuppressWarnings({"unused", "RedundantSuppression"})
|
||||
public static boolean execTransact(int code, long dataObj, long replyObj, int flags) {
|
||||
Log.d(TAG, String.valueOf(code));
|
||||
if (code != TRANSACTION_CODE) return false;
|
||||
|
||||
Parcel data = ParcelUtils.fromNativePointer(dataObj);
|
||||
Parcel reply = ParcelUtils.fromNativePointer(replyObj);
|
||||
|
||||
if (data == null || reply == null) {
|
||||
Log.w(TAG, "Got transaction with null data or reply");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
@ -224,9 +226,8 @@ public class BridgeService {
|
|||
try {
|
||||
String descriptor = ParcelUtils.readInterfaceDescriptor(data);
|
||||
data.setDataPosition(0);
|
||||
|
||||
if (descriptor.equals(DESCRIPTOR)) {
|
||||
res = onTransact(code, data, reply, flags);
|
||||
res = onTransact(data, reply, flags);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
if ((flags & IBinder.FLAG_ONEWAY) != 0) {
|
||||
|
|
|
|||
|
|
@ -1,14 +1,17 @@
|
|||
package io.github.lsposed.lspd.service;
|
||||
|
||||
import android.content.ContentValues;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.database.Cursor;
|
||||
import android.database.sqlite.SQLiteQueryBuilder;
|
||||
import android.database.sqlite.SQLiteStatement;
|
||||
import android.database.sqlite.SQLiteDatabase;
|
||||
import android.os.FileObserver;
|
||||
import android.os.ParcelFileDescriptor;
|
||||
import android.os.RemoteException;
|
||||
import android.util.Log;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.annotation.Nullable;
|
||||
|
||||
import java.io.File;
|
||||
|
|
@ -43,6 +46,12 @@ public class ConfigManager {
|
|||
final private File verboseLogSwitch = new File(configPath, "verbose_log");
|
||||
private boolean verboseLog = false;
|
||||
|
||||
final private String DEFAULT_MANAGER_PACKAGE_NAME = "io.github.lsposed.manager";
|
||||
|
||||
final private File managerPath = new File(configPath, "manager");
|
||||
private String manager = null;
|
||||
private int managerUid = -1;
|
||||
|
||||
final private File selinuxPath = new File("/sys/fs/selinux/enforce");
|
||||
// only check on boot
|
||||
final private boolean isPermissive;
|
||||
|
|
@ -59,41 +68,77 @@ public class ConfigManager {
|
|||
}
|
||||
};
|
||||
|
||||
int readInt(File file, int defaultValue) {
|
||||
private String readText(@NonNull File file) throws IOException {
|
||||
return new String(Files.readAllBytes(file.toPath()));
|
||||
}
|
||||
|
||||
private String readText(@NonNull File file, String defaultValue) {
|
||||
try {
|
||||
return Integer.parseInt(new String(Files.readAllBytes(file.toPath())));
|
||||
if (!file.exists()) return defaultValue;
|
||||
return readText(file);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
private void writeText(@NonNull File file, String value) {
|
||||
try {
|
||||
Files.write(file.toPath(), value.getBytes(), StandardOpenOption.CREATE_NEW);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
}
|
||||
}
|
||||
|
||||
private int readInt(@NonNull File file, int defaultValue) {
|
||||
try {
|
||||
if (!file.exists()) return defaultValue;
|
||||
return Integer.parseInt(readText(file));
|
||||
} catch (IOException | NumberFormatException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
}
|
||||
return defaultValue;
|
||||
}
|
||||
|
||||
void writeInt(File file, int value) {
|
||||
try {
|
||||
Files.write(file.toPath(), String.valueOf(value).getBytes(), StandardOpenOption.CREATE_NEW);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, Log.getStackTraceString(e));
|
||||
}
|
||||
private void writeInt(@NonNull File file, int value) {
|
||||
writeText(file, String.valueOf(value));
|
||||
}
|
||||
|
||||
void updateConfig() {
|
||||
private synchronized void updateConfig() {
|
||||
resourceHook = resourceHookSwitch.exists();
|
||||
variant = readInt(variantSwitch, -1);
|
||||
verboseLog = readInt(verboseLogSwitch, 0) == 1;
|
||||
updateManager();
|
||||
}
|
||||
|
||||
SQLiteStatement createEnabledModulesTable = db.compileStatement("CREATE TABLE IF NOT EXISTS enabled_modules (" +
|
||||
"mid int PRIMARY KEY AUTOINCREMENT," +
|
||||
public synchronized void updateManager() {
|
||||
try {
|
||||
PackageInfo info = PackageService.getPackageInfo(readText(managerPath, DEFAULT_MANAGER_PACKAGE_NAME), 0, 0);
|
||||
if (info != null) {
|
||||
managerUid = info.applicationInfo.uid;
|
||||
manager = info.packageName;
|
||||
}
|
||||
} catch (RemoteException ignored) {
|
||||
}
|
||||
}
|
||||
|
||||
public synchronized void updateManager(@NonNull String packageName) {
|
||||
writeText(managerPath, packageName);
|
||||
updateManager();
|
||||
}
|
||||
|
||||
private final SQLiteStatement createEnabledModulesTable = db.compileStatement("CREATE TABLE IF NOT EXISTS enabled_modules (" +
|
||||
"mid integer PRIMARY KEY AUTOINCREMENT," +
|
||||
"package_name text NOT NULL UNIQUE," +
|
||||
"apk_path text NOT NULL" +
|
||||
");");
|
||||
SQLiteStatement createScopeTable = db.compileStatement("CREATE TABLE IF NOT EXISTS scope (" +
|
||||
"mid int," +
|
||||
"uid int," +
|
||||
private final SQLiteStatement createScopeTable = db.compileStatement("CREATE TABLE IF NOT EXISTS scope (" +
|
||||
"mid integer," +
|
||||
"uid integer," +
|
||||
"PRIMARY KEY (mid, uid)" +
|
||||
");");
|
||||
|
||||
ConcurrentHashMap<Integer, ArrayList<String>> modulesForUid;
|
||||
private final ConcurrentHashMap<Integer, ArrayList<String>> modulesForUid = new ConcurrentHashMap<>();
|
||||
|
||||
static ConfigManager getInstance() {
|
||||
if (instance == null)
|
||||
|
|
@ -105,6 +150,7 @@ public class ConfigManager {
|
|||
createTables();
|
||||
updateConfig();
|
||||
isPermissive = readInt(selinuxPath, 1) == 0;
|
||||
configObserver.startWatching();
|
||||
}
|
||||
|
||||
private void createTables() {
|
||||
|
|
@ -113,6 +159,7 @@ public class ConfigManager {
|
|||
}
|
||||
|
||||
private synchronized void cacheScopes() {
|
||||
modulesForUid.clear();
|
||||
SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
|
||||
builder.setTables("scope INNER JOIN enabled_modules ON scope.mid = enabled_modules.mid");
|
||||
Cursor cursor = builder.query(db, new String[]{"scope.uid", "enabled_modules.apk_path"},
|
||||
|
|
@ -132,13 +179,13 @@ public class ConfigManager {
|
|||
|
||||
// This is called when a new process created, use the cached result
|
||||
public List<String> getModulesPathForUid(int uid) {
|
||||
return modulesForUid.getOrDefault(uid, null);
|
||||
return isManager(uid) ? new ArrayList<>() : modulesForUid.getOrDefault(uid, null);
|
||||
}
|
||||
|
||||
// This is called when a new process created, use the cached result
|
||||
// The signature matches Riru's
|
||||
public boolean shouldSkipUid(int uid) {
|
||||
return !modulesForUid.containsKey(uid);
|
||||
return !modulesForUid.containsKey(uid) && !isManager(uid);
|
||||
}
|
||||
|
||||
// This should only be called by manager, so we don't need to cache it
|
||||
|
|
@ -278,4 +325,12 @@ public class ConfigManager {
|
|||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isManager(String package_name) {
|
||||
return package_name.equals(manager);
|
||||
}
|
||||
|
||||
public boolean isManager(int uid) {
|
||||
return uid == managerUid;
|
||||
}
|
||||
}
|
||||
|
|
|
|||
|
|
@ -46,7 +46,9 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
|
|||
@Override
|
||||
public IBinder requestManagerBinder() throws RemoteException {
|
||||
ensureRegistered();
|
||||
return ServiceManager.getManagerService();
|
||||
if (ConfigManager.getInstance().isManager(Binder.getCallingUid()))
|
||||
return ServiceManager.getManagerService();
|
||||
return null;
|
||||
}
|
||||
|
||||
public boolean hasRegister(int uid, int pid) {
|
||||
|
|
|
|||
|
|
@ -1,7 +1,6 @@
|
|||
package io.github.lsposed.lspd.service;
|
||||
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
import android.util.Log;
|
||||
|
||||
import static io.github.lsposed.lspd.service.ServiceManager.TAG;
|
||||
|
|
@ -28,14 +27,18 @@ public class LSPosedService extends ILSPosedService.Stub {
|
|||
@Override
|
||||
public ILSPApplicationService requestApplicationService(int uid, int pid) {
|
||||
if (Binder.getCallingUid() != 1000) {
|
||||
Log.w(TAG, "Someone else got my binder!?");
|
||||
return null;
|
||||
}
|
||||
if (ConfigManager.getInstance().shouldSkipUid(uid)) {
|
||||
Log.d(TAG, "Skipped uid " + uid);
|
||||
return null;
|
||||
}
|
||||
if (ServiceManager.getApplicationService().hasRegister(uid, pid)) {
|
||||
Log.d(TAG, "Skipped duplicated request for uid " + uid + " pid " + pid);
|
||||
return null;
|
||||
}
|
||||
Log.d(TAG, "returned service");
|
||||
return ServiceManager.getApplicationService();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -1,52 +1,15 @@
|
|||
package hidden;
|
||||
|
||||
//import android.annotation.NonNull;
|
||||
//import android.app.ActivityThread;
|
||||
//import android.content.pm.ApplicationInfo;
|
||||
//import android.content.pm.PackageInfo;
|
||||
//import android.content.pm.PackageManager;
|
||||
//import android.os.UserHandle;
|
||||
import android.annotation.NonNull;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.content.res.AssetManager;
|
||||
import android.os.UserManager;
|
||||
|
||||
import java.util.List;
|
||||
import android.os.Binder;
|
||||
import android.os.IBinder;
|
||||
|
||||
public class HiddenApiBridge {
|
||||
public static int AssetManager_addAssetPath(AssetManager am, String path) {
|
||||
return am.addAssetPath(path);
|
||||
}
|
||||
public static List<UserInfo> UserManager_getUsers(UserManager um) {
|
||||
return um.getUsers();
|
||||
|
||||
public static IBinder Binder_allowBlocking(IBinder binder) {
|
||||
return Binder.allowBlocking(binder);
|
||||
}
|
||||
// public static ApplicationInfo PackageManager_getApplicationInfoAsUser(PackageManager packageManager, @NonNull String packageName, int flags, int userId) throws android.content.pm.PackageManager.NameNotFoundException {
|
||||
// return packageManager.getApplicationInfoAsUser(packageName, flags, userId);
|
||||
// }
|
||||
//
|
||||
// public static PackageInfo PackageManager_getPackageInfoAsUser(PackageManager packageManager, @NonNull String packageName, int flags, int userId) throws android.content.pm.PackageManager.NameNotFoundException {
|
||||
// return packageManager.getPackageInfoAsUser(packageName, flags, userId);
|
||||
// }
|
||||
//
|
||||
// public static List<ApplicationInfo> PackageManager_getInstalledApplicationsAsUser(PackageManager packageManager, int flags, int userId) {
|
||||
// return packageManager.getInstalledApplicationsAsUser(flags, userId);
|
||||
// }
|
||||
//
|
||||
public static List<PackageInfo> PackageManager_getInstalledPackagesAsUser(PackageManager packageManager, int flags, int userId) {
|
||||
return packageManager.getInstalledPackagesAsUser(flags, userId);
|
||||
}
|
||||
//
|
||||
// public static UserHandle createUserHandle(int userId) {
|
||||
// return new UserHandle(userId);
|
||||
// }
|
||||
//
|
||||
// public static ActivityThread ActivityThread_systemMain() {
|
||||
// return ActivityThread.systemMain();
|
||||
// }
|
||||
//
|
||||
// public static String PackageInfo_overlayTarget(PackageInfo packageInfo) {
|
||||
// return packageInfo.overlayTarget;
|
||||
// }
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,4 +55,8 @@ public class Binder implements IBinder {
|
|||
int flags) throws RemoteException {
|
||||
throw new RuntimeException("STUB");
|
||||
}
|
||||
|
||||
public static IBinder allowBlocking(IBinder binder){
|
||||
throw new RuntimeException("STUB");
|
||||
}
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue