[core] Workaround for binder: allow blocking

This commit is contained in:
LoveSy 2021-02-16 15:49:59 +08:00 committed by tehcneko
parent 0ec8959235
commit 2890aec54f
14 changed files with 145 additions and 219 deletions

View File

@ -39,9 +39,6 @@
#include "jni/native_api.h" #include "jni/native_api.h"
#include "service.h" #include "service.h"
#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Wunused-value"
namespace lspd { namespace lspd {
namespace fs = std::filesystem; namespace fs = std::filesystem;
@ -132,6 +129,7 @@ namespace lspd {
RegisterEdxpYahfa(env); RegisterEdxpYahfa(env);
RegisterPendingHooks(env); RegisterPendingHooks(env);
RegisterNativeAPI(env); RegisterNativeAPI(env);
// TODO: Recover this
// variant_ = Variant(ConfigManager::GetInstance()->GetVariant()); // variant_ = Variant(ConfigManager::GetInstance()->GetVariant());
// LOGI("LSP Variant: %d", variant_); // LOGI("LSP Variant: %d", variant_);
@ -193,15 +191,7 @@ namespace lspd {
} }
void void
Context::OnNativeForkSystemServerPre([[maybe_unused]] JNIEnv *env, Context::OnNativeForkSystemServerPre(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) {
Service::instance()->InitService(env); Service::instance()->InitService(env);
PreLoadDex(ConfigManager::GetInjectDexPath()); PreLoadDex(ConfigManager::GetInjectDexPath());
skip_ = false; skip_ = false;
@ -231,31 +221,24 @@ namespace lspd {
Service::instance()->HookBridge(*this, env); Service::instance()->HookBridge(*this, env);
} }
void Context::OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, void Context::OnNativeForkAndSpecializePre(JNIEnv *env,
jint uid, jint gid, jint uid,
jintArray gids,
jint runtime_flags,
jobjectArray rlimits,
jint mount_external,
jstring se_info,
jstring nice_name, jstring nice_name,
jintArray fds_to_close,
jintArray fds_to_ignore,
jboolean is_child_zygote, jboolean is_child_zygote,
jstring instruction_set,
jstring app_data_dir) { jstring app_data_dir) {
PreLoadDex(ConfigManager::GetInjectDexPath()); PreLoadDex(ConfigManager::GetInjectDexPath());
Service::instance()->InitService(env); Service::instance()->InitService(env);
this->uid = uid;
const auto app_id = uid % PER_USER_RANGE; const auto app_id = uid % PER_USER_RANGE;
nice_name_ = nice_name;
JUTFString process_name(env, nice_name);
skip_ = false; skip_ = false;
if (!skip_ && !app_data_dir) { 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; skip_ = true;
} }
if (!skip_ && is_child_zygote) { if (!skip_ && is_child_zygote) {
skip_ = true; 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) || 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 <= LAST_APP_ZYGOTE_ISOLATED_UID) ||
app_id == SHARED_RELRO_UID)) { app_id == SHARED_RELRO_UID)) {
skip_ = true; 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

View File

@ -56,21 +56,13 @@ namespace lspd {
return FindClassFromLoader(env, GetCurrentClassLoader(), className); return FindClassFromLoader(env, GetCurrentClassLoader(), className);
}; };
void OnNativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint uid, jint gid, void OnNativeForkAndSpecializePre(JNIEnv *env, jint uid, jstring nice_name, jboolean is_child_zygote, jstring app_data_dir);
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 OnNativeForkAndSpecializePost(JNIEnv *env); void OnNativeForkAndSpecializePost(JNIEnv *env);
void OnNativeForkSystemServerPost(JNIEnv *env, jint res); void OnNativeForkSystemServerPost(JNIEnv *env, jint res);
void OnNativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t uid, gid_t gid, void OnNativeForkSystemServerPre(JNIEnv *env);
jintArray gids, jint runtime_flags, jobjectArray rlimits,
jlong permitted_capabilities,
jlong effective_capabilities);
private: private:
@ -82,7 +74,6 @@ namespace lspd {
JavaVM *vm_ = nullptr; JavaVM *vm_ = nullptr;
jclass class_linker_class_ = nullptr; jclass class_linker_class_ = nullptr;
jmethodID post_fixup_static_mid_ = nullptr; jmethodID post_fixup_static_mid_ = nullptr;
jint uid = -1;
bool skip_ = false; bool skip_ = false;
std::vector<signed char> dex{}; std::vector<signed char> dex{};

View File

@ -37,64 +37,58 @@ namespace lspd {
ConfigManager::Init(); ConfigManager::Init();
} }
static int shouldSkipUid(int uid) { static int shouldSkipUid(int) {
return 0; return 0;
} }
static void nativeForkAndSpecializePre(JNIEnv *env, jclass clazz, jint *_uid, jint *gid, static void nativeForkAndSpecializePre(JNIEnv *env, jclass, jint *_uid, jint *,
jintArray *gids, jint *runtime_flags, jintArray *, jint *,
jobjectArray *rlimits, jint *mount_external, jobjectArray *, jint *,
jstring *se_info, jstring *nice_name, jstring *, jstring *nice_name,
jintArray *fds_to_close, jintArray *fds_to_ignore, jintArray *, jintArray *,
jboolean *start_child_zygote, jstring *instruction_set, jboolean *start_child_zygote, jstring *,
jstring *app_data_dir, jboolean *is_top_app, jobjectArray *pkg_data_info_list, jstring *app_data_dir, jboolean *,
jobjectArray *whitelisted_data_info_list, jboolean *bind_mount_app_data_dirs, jobjectArray *,
jboolean *bind_mount_app_storage_dirs) { jobjectArray *,
Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *_uid, *gid, *gids, jboolean *,
*runtime_flags, *rlimits, jboolean *) {
*mount_external, *se_info, *nice_name, Context::GetInstance()->OnNativeForkAndSpecializePre(env, *_uid,
*fds_to_close, *nice_name,
*fds_to_ignore, *start_child_zygote,
*start_child_zygote, *instruction_set,
*app_data_dir); *app_data_dir);
} }
static void nativeForkAndSpecializePost(JNIEnv *env, jclass clazz, jint res) { static void nativeForkAndSpecializePost(JNIEnv *env, jclass, jint res) {
Context::GetInstance()->OnNativeForkAndSpecializePost(env); if (res == 0)
Context::GetInstance()->OnNativeForkAndSpecializePost(env);
} }
static void nativeForkSystemServerPre(JNIEnv *env, jclass clazz, uid_t *uid, gid_t *gid, static void nativeForkSystemServerPre(JNIEnv *env, jclass, uid_t *, gid_t *,
jintArray *gids, jint *runtime_flags, jintArray *, jint *,
jobjectArray *rlimits, jlong *permitted_capabilities, jobjectArray *, jlong *,
jlong *effective_capabilities) { jlong *) {
Context::GetInstance()->OnNativeForkSystemServerPre(env, clazz, *uid, *gid, *gids, Context::GetInstance()->OnNativeForkSystemServerPre(env);
*runtime_flags, *rlimits,
*permitted_capabilities,
*effective_capabilities
);
} }
static void nativeForkSystemServerPost(JNIEnv *env, [[maybe_unused]] jclass clazz, jint res) { static void nativeForkSystemServerPost(JNIEnv *env, jclass, jint res) {
Context::GetInstance()->OnNativeForkSystemServerPost(env, res); Context::GetInstance()->OnNativeForkSystemServerPost(env, res);
} }
/* method added in Android Q */ /* method added in Android Q */
static void specializeAppProcessPre(JNIEnv *env, jclass clazz, jint *uid, jint *gid, static void specializeAppProcessPre(JNIEnv *env, jclass, jint *uid, jint *,
jintArray *gids, jint *runtime_flags, jobjectArray *rlimits, jintArray *, jint *, jobjectArray *,
jint *mount_external, jstring *se_info, jstring *nice_name, jint *, jstring *, jstring *nice_name,
jboolean *start_child_zygote, jstring *instruction_set, jboolean *start_child_zygote, jstring *,
jstring *app_data_dir, jboolean *is_top_app, jobjectArray *pkg_data_info_list, jstring *app_data_dir, jboolean *,
jobjectArray *whitelisted_data_info_list, jboolean *bind_mount_app_data_dirs, jobjectArray *,
jboolean *bind_mount_app_storage_dirs) { jobjectArray *,
Context::GetInstance()->OnNativeForkAndSpecializePre(env, clazz, *uid, *gid, *gids, jboolean *,
*runtime_flags, *rlimits, jboolean *) {
*mount_external, *se_info, *nice_name, Context::GetInstance()->OnNativeForkAndSpecializePre(env, *uid, *nice_name, *start_child_zygote,
nullptr, nullptr,
*start_child_zygote, *instruction_set,
*app_data_dir); *app_data_dir);
} }
static void specializeAppProcessPost(JNIEnv *env, [[maybe_unused]] jclass clazz) { static void specializeAppProcessPost(JNIEnv *env, jclass) {
Context::GetInstance()->OnNativeForkAndSpecializePost(env); Context::GetInstance()->OnNativeForkAndSpecializePost(env);
} }
} }
@ -110,7 +104,9 @@ RIRU_EXPORT void *init(void *arg) {
switch (step) { switch (step) {
case 1: { case 1: {
auto core_max_api_version = *(int *) arg; 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; return &riru_api_version;
} }
case 2: { case 2: {

View File

@ -154,12 +154,9 @@ namespace lspd {
if (res) { if (res) {
JNI_CallVoidMethod(env, reply, readExceptionMethod_); JNI_CallVoidMethod(env, reply, readExceptionMethod_);
service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_); service = JNI_CallObjectMethod(env, reply, readStrongBinderMethod_);
} else {
LOGD("no reply");
} }
JNI_CallVoidMethod(env, data, recycleMethod_); JNI_CallVoidMethod(env, data, recycleMethod_);
JNI_CallObjectMethod(env, reply, recycleMethod_); JNI_CallVoidMethod(env, reply, recycleMethod_);
return service; return service;
} }

View File

@ -36,9 +36,7 @@ namespace lspd {
inline static std::unique_ptr<Service> instance_ = std::make_unique<Service>(); inline static std::unique_ptr<Service> instance_ = std::make_unique<Service>();
bool initialized_ = false; bool initialized_ = false;
Service() { Service() = default;
}
static jboolean static jboolean
call_boolean_method_va_replace(JNIEnv *env, jobject obj, jmethodID methodId, va_list args); call_boolean_method_va_replace(JNIEnv *env, jobject obj, jmethodID methodId, va_list args);

View File

@ -20,7 +20,6 @@
package io.github.lsposed.lspd.core.yahfa; 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.nativebridge.Yahfa;
import io.github.lsposed.lspd.util.Utils; import io.github.lsposed.lspd.util.Utils;

View File

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

View File

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

View File

@ -13,6 +13,7 @@ import androidx.annotation.Nullable;
import java.lang.reflect.Field; import java.lang.reflect.Field;
import java.util.Map; import java.util.Map;
import static hidden.HiddenApiBridge.Binder_allowBlocking;
import static io.github.lsposed.lspd.service.ServiceManager.TAG; import static io.github.lsposed.lspd.service.ServiceManager.TAG;
public class BridgeService { public class BridgeService {
@ -21,6 +22,7 @@ public class BridgeService {
private static final String SERVICE_NAME = "activity"; private static final String SERVICE_NAME = "activity";
enum ACTION { enum ACTION {
ACTION_UNKNOWN,
ACTION_SEND_BINDER, ACTION_SEND_BINDER,
ACTION_GET_BINDER, ACTION_GET_BINDER,
} }
@ -149,7 +151,7 @@ public class BridgeService {
serviceBinder.unlinkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0); serviceBinder.unlinkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0);
} }
serviceBinder = binder; serviceBinder = Binder_allowBlocking(binder);
service = ILSPosedService.Stub.asInterface(serviceBinder); service = ILSPosedService.Stub.asInterface(serviceBinder);
try { try {
serviceBinder.linkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0); serviceBinder.linkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0);
@ -171,7 +173,7 @@ public class BridgeService {
} }
@SuppressWarnings({"unused", "RedundantSuppression"}) @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); data.enforceInterface(DESCRIPTOR);
ACTION action = ACTION.values()[data.readInt()]; ACTION action = ACTION.values()[data.readInt()];
@ -209,13 +211,13 @@ public class BridgeService {
@SuppressWarnings({"unused", "RedundantSuppression"}) @SuppressWarnings({"unused", "RedundantSuppression"})
public static boolean execTransact(int code, long dataObj, long replyObj, int flags) { public static boolean execTransact(int code, long dataObj, long replyObj, int flags) {
Log.d(TAG, String.valueOf(code));
if (code != TRANSACTION_CODE) return false; if (code != TRANSACTION_CODE) return false;
Parcel data = ParcelUtils.fromNativePointer(dataObj); Parcel data = ParcelUtils.fromNativePointer(dataObj);
Parcel reply = ParcelUtils.fromNativePointer(replyObj); Parcel reply = ParcelUtils.fromNativePointer(replyObj);
if (data == null || reply == null) { if (data == null || reply == null) {
Log.w(TAG, "Got transaction with null data or reply");
return false; return false;
} }
@ -224,9 +226,8 @@ public class BridgeService {
try { try {
String descriptor = ParcelUtils.readInterfaceDescriptor(data); String descriptor = ParcelUtils.readInterfaceDescriptor(data);
data.setDataPosition(0); data.setDataPosition(0);
if (descriptor.equals(DESCRIPTOR)) { if (descriptor.equals(DESCRIPTOR)) {
res = onTransact(code, data, reply, flags); res = onTransact(data, reply, flags);
} }
} catch (Exception e) { } catch (Exception e) {
if ((flags & IBinder.FLAG_ONEWAY) != 0) { if ((flags & IBinder.FLAG_ONEWAY) != 0) {

View File

@ -1,14 +1,17 @@
package io.github.lsposed.lspd.service; package io.github.lsposed.lspd.service;
import android.content.ContentValues; import android.content.ContentValues;
import android.content.pm.PackageInfo;
import android.database.Cursor; import android.database.Cursor;
import android.database.sqlite.SQLiteQueryBuilder; import android.database.sqlite.SQLiteQueryBuilder;
import android.database.sqlite.SQLiteStatement; import android.database.sqlite.SQLiteStatement;
import android.database.sqlite.SQLiteDatabase; import android.database.sqlite.SQLiteDatabase;
import android.os.FileObserver; import android.os.FileObserver;
import android.os.ParcelFileDescriptor; import android.os.ParcelFileDescriptor;
import android.os.RemoteException;
import android.util.Log; import android.util.Log;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable; import androidx.annotation.Nullable;
import java.io.File; import java.io.File;
@ -43,6 +46,12 @@ public class ConfigManager {
final private File verboseLogSwitch = new File(configPath, "verbose_log"); final private File verboseLogSwitch = new File(configPath, "verbose_log");
private boolean verboseLog = false; 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"); 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;
@ -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 { 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) { } catch (IOException | NumberFormatException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }
return defaultValue; return defaultValue;
} }
void writeInt(File file, int value) { private void writeInt(@NonNull File file, int value) {
try { writeText(file, String.valueOf(value));
Files.write(file.toPath(), String.valueOf(value).getBytes(), StandardOpenOption.CREATE_NEW);
} catch (IOException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
} }
void updateConfig() { private synchronized void updateConfig() {
resourceHook = resourceHookSwitch.exists(); resourceHook = resourceHookSwitch.exists();
variant = readInt(variantSwitch, -1); variant = readInt(variantSwitch, -1);
verboseLog = readInt(verboseLogSwitch, 0) == 1; verboseLog = readInt(verboseLogSwitch, 0) == 1;
updateManager();
} }
SQLiteStatement createEnabledModulesTable = db.compileStatement("CREATE TABLE IF NOT EXISTS enabled_modules (" + public synchronized void updateManager() {
"mid int PRIMARY KEY AUTOINCREMENT," + 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," + "package_name text NOT NULL UNIQUE," +
"apk_path text NOT NULL" + "apk_path text NOT NULL" +
");"); ");");
SQLiteStatement createScopeTable = db.compileStatement("CREATE TABLE IF NOT EXISTS scope (" + private final SQLiteStatement createScopeTable = db.compileStatement("CREATE TABLE IF NOT EXISTS scope (" +
"mid int," + "mid integer," +
"uid int," + "uid integer," +
"PRIMARY KEY (mid, uid)" + "PRIMARY KEY (mid, uid)" +
");"); ");");
ConcurrentHashMap<Integer, ArrayList<String>> modulesForUid; private final ConcurrentHashMap<Integer, ArrayList<String>> modulesForUid = new ConcurrentHashMap<>();
static ConfigManager getInstance() { static ConfigManager getInstance() {
if (instance == null) if (instance == null)
@ -105,6 +150,7 @@ public class ConfigManager {
createTables(); createTables();
updateConfig(); updateConfig();
isPermissive = readInt(selinuxPath, 1) == 0; isPermissive = readInt(selinuxPath, 1) == 0;
configObserver.startWatching();
} }
private void createTables() { private void createTables() {
@ -113,6 +159,7 @@ public class ConfigManager {
} }
private synchronized void cacheScopes() { private synchronized void cacheScopes() {
modulesForUid.clear();
SQLiteQueryBuilder builder = new SQLiteQueryBuilder(); SQLiteQueryBuilder builder = new SQLiteQueryBuilder();
builder.setTables("scope INNER JOIN enabled_modules ON scope.mid = enabled_modules.mid"); 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"}, 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 // This is called when a new process created, use the cached result
public List<String> getModulesPathForUid(int uid) { 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 // This is called when a new process created, use the cached result
// The signature matches Riru's // The signature matches Riru's
public boolean shouldSkipUid(int uid) { 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 // This should only be called by manager, so we don't need to cache it
@ -278,4 +325,12 @@ public class ConfigManager {
return null; return null;
} }
} }
public boolean isManager(String package_name) {
return package_name.equals(manager);
}
public boolean isManager(int uid) {
return uid == managerUid;
}
} }

View File

@ -46,7 +46,9 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
@Override @Override
public IBinder requestManagerBinder() throws RemoteException { public IBinder requestManagerBinder() throws RemoteException {
ensureRegistered(); ensureRegistered();
return ServiceManager.getManagerService(); if (ConfigManager.getInstance().isManager(Binder.getCallingUid()))
return ServiceManager.getManagerService();
return null;
} }
public boolean hasRegister(int uid, int pid) { public boolean hasRegister(int uid, int pid) {

View File

@ -1,7 +1,6 @@
package io.github.lsposed.lspd.service; package io.github.lsposed.lspd.service;
import android.os.Binder; import android.os.Binder;
import android.os.IBinder;
import android.util.Log; import android.util.Log;
import static io.github.lsposed.lspd.service.ServiceManager.TAG; import static io.github.lsposed.lspd.service.ServiceManager.TAG;
@ -28,14 +27,18 @@ public class LSPosedService extends ILSPosedService.Stub {
@Override @Override
public ILSPApplicationService requestApplicationService(int uid, int pid) { public ILSPApplicationService requestApplicationService(int uid, int pid) {
if (Binder.getCallingUid() != 1000) { if (Binder.getCallingUid() != 1000) {
Log.w(TAG, "Someone else got my binder!?");
return null; return null;
} }
if (ConfigManager.getInstance().shouldSkipUid(uid)) { if (ConfigManager.getInstance().shouldSkipUid(uid)) {
Log.d(TAG, "Skipped uid " + uid);
return null; return null;
} }
if (ServiceManager.getApplicationService().hasRegister(uid, pid)) { if (ServiceManager.getApplicationService().hasRegister(uid, pid)) {
Log.d(TAG, "Skipped duplicated request for uid " + uid + " pid " + pid);
return null; return null;
} }
Log.d(TAG, "returned service");
return ServiceManager.getApplicationService(); return ServiceManager.getApplicationService();
} }

View File

@ -1,52 +1,15 @@
package hidden; 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.content.res.AssetManager;
import android.os.UserManager; import android.os.Binder;
import android.os.IBinder;
import java.util.List;
public class HiddenApiBridge { public class HiddenApiBridge {
public static int AssetManager_addAssetPath(AssetManager am, String path) { public static int AssetManager_addAssetPath(AssetManager am, String path) {
return am.addAssetPath(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;
// }
} }

View File

@ -55,4 +55,8 @@ public class Binder implements IBinder {
int flags) throws RemoteException { int flags) throws RemoteException {
throw new RuntimeException("STUB"); throw new RuntimeException("STUB");
} }
public static IBinder allowBlocking(IBinder binder){
throw new RuntimeException("STUB");
}
} }