[core] Send app binder when requesting binder (#177)

This commit is contained in:
LoveSy 2021-02-23 18:31:52 +08:00 committed by GitHub
parent 065667df04
commit 6aed74acdd
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
11 changed files with 76 additions and 48 deletions

View File

@ -1,8 +1,6 @@
package io.github.lsposed.lspd.service;
interface ILSPApplicationService {
void registerHeartBeat(IBinder handle) = 1;
IBinder requestModuleBinder() = 2;
IBinder requestManagerBinder() = 3;

View File

@ -3,7 +3,7 @@ package io.github.lsposed.lspd.service;
import io.github.lsposed.lspd.service.ILSPApplicationService;
interface ILSPosedService {
ILSPApplicationService requestApplicationService(int uid, int pid, String processName) = 1;
ILSPApplicationService requestApplicationService(int uid, int pid, String processName, IBinder heartBeat) = 1;
oneway void dispatchPackageChanged(in Intent intent) = 2;
}

View File

@ -84,6 +84,10 @@ namespace lspd {
transact_method_ = env->GetMethodID(ibinder_class, "transact",
"(ILandroid/os/Parcel;Landroid/os/Parcel;I)Z");
binder_class_ = env->FindClass("android/os/Binder");
if (binder_class_) binder_class_ = (jclass)env->NewGlobalRef(binder_class_);
binder_ctor_ = env->GetMethodID(binder_class_, "<init>", "()V");
// Parcel
parcel_class_ = env->FindClass("android/os/Parcel");
if (parcel_class_) parcel_class_ = (jclass) env->NewGlobalRef(parcel_class_);
@ -93,7 +97,9 @@ namespace lspd {
"(Ljava/lang/String;)V");
write_int_method_ = env->GetMethodID(parcel_class_, "writeInt", "(I)V");
write_string_method_ = env->GetMethodID(parcel_class_, "writeString",
"(Ljava/lang/String;)V");
"(Ljava/lang/String;)V");
write_strong_binder_method_ = env->GetMethodID(parcel_class_, "writeStrongBinder",
"(Landroid/os/IBinder;)V");
read_exception_method_ = env->GetMethodID(parcel_class_, "readException", "()V");
read_strong_binder_method_ = env->GetMethodID(parcel_class_, "readStrongBinder",
"()Landroid/os/IBinder;");
@ -126,7 +132,7 @@ namespace lspd {
ScopedLocalRef<jclass> binderClass(env, env->FindClass("android/os/Binder"));
exec_transact_backup_methodID_ = JNI_GetMethodID(env, binderClass.get(), "execTransact",
"(IJJI)Z");
"(IJJI)Z");
auto set_table_override = reinterpret_cast<void (*)(
JNINativeInterface *)>(DobbySymbolResolver(nullptr,
"_ZN3art9JNIEnvExt16SetTableOverrideEPK18JNINativeInterface"));
@ -159,6 +165,8 @@ namespace lspd {
return nullptr;
}
auto heart_beat_binder = JNI_NewObject(env, binder_class_, binder_ctor_);
auto data = JNI_CallStaticObjectMethod(env, parcel_class_, obtain_method_);
auto reply = JNI_CallStaticObjectMethod(env, parcel_class_, obtain_method_);
@ -166,6 +174,7 @@ namespace lspd {
JNI_CallVoidMethod(env, data, write_interface_token_method_, descriptor);
JNI_CallVoidMethod(env, data, write_int_method_, BRIDGE_ACTION_GET_BINDER);
JNI_CallVoidMethod(env, data, write_string_method_, nice_name);
JNI_CallVoidMethod(env, data, write_strong_binder_method_, heart_beat_binder);
auto res = JNI_CallBooleanMethod(env, bridgeService, transact_method_,
BRIDGE_TRANSACTION_CODE,
@ -181,20 +190,38 @@ namespace lspd {
}
JNI_CallVoidMethod(env, data, recycleMethod_);
JNI_CallVoidMethod(env, reply, recycleMethod_);
if (service) {
env->NewGlobalRef(heart_beat_binder);
} else {
env->DeleteLocalRef(heart_beat_binder);
}
return service;
}
jobject Service::RequestBinderForSystemServer(JNIEnv *env) {
if (UNLIKELY(!initialized_)) {
LOGE("Service not initialized");
return nullptr;
}
auto bridgeServiceName = env->NewStringUTF(SYSTEM_SERVER_BRIDGE_SERVICE_NAME.data());
auto binder = JNI_CallStaticObjectMethod(env, service_manager_class_,
get_service_method_, bridgeServiceName);
if(!binder) {
get_service_method_, bridgeServiceName);
if (!binder) {
LOGD("Fail to get binder for system server");
return nullptr;
}
auto method = JNI_GetStaticMethodID(env, bridge_service_class_, "getApplicationServiceForSystemServer", "(Landroid/os/IBinder;)Landroid/os/IBinder;");
auto app_binder = JNI_CallStaticObjectMethod(env, bridge_service_class_, method, binder);
auto method = JNI_GetStaticMethodID(env, bridge_service_class_,
"getApplicationServiceForSystemServer",
"(Landroid/os/IBinder;Landroid/os/IBinder;)Landroid/os/IBinder;");
auto heart_beat_binder = JNI_NewObject(env, binder_class_, binder_ctor_);
auto app_binder = JNI_CallStaticObjectMethod(env, bridge_service_class_, method, binder,
heart_beat_binder);
if (app_binder) {
env->NewGlobalRef(heart_beat_binder);
} else {
env->DeleteLocalRef(heart_beat_binder);
}
return app_binder;
}
}

View File

@ -74,6 +74,9 @@ namespace lspd {
jclass bridge_service_class_ = nullptr;
jmethodID exec_transact_replace_methodID_ = nullptr;
jclass binder_class_ = nullptr;
jmethodID binder_ctor_ = nullptr;
jclass service_manager_class_ = nullptr;
jmethodID get_service_method_ = nullptr;
@ -87,6 +90,7 @@ namespace lspd {
jmethodID write_string_method_ = nullptr;
jmethodID read_exception_method_ = nullptr;
jmethodID read_strong_binder_method_ = nullptr;
jmethodID write_strong_binder_method_ = nullptr;
jclass deadObjectExceptionClass_ = nullptr;

View File

@ -60,18 +60,6 @@ public class LSPApplicationServiceClient implements ILSPApplicationService {
}
}
@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 {

View File

@ -39,11 +39,9 @@ import static io.github.lsposed.lspd.config.LSPApplicationServiceClient.serviceC
@Keep
public class Main {
private static final AtomicReference<Impl> lspdImplRef = new AtomicReference<>(null);
private static final Binder heartBeatBinder = new Binder();
public static void forkAndSpecializePost(String appDataDir, String niceName, IBinder binder) {
LSPApplicationServiceClient.Init(binder, niceName);
serviceClient.registerHeartBeat(heartBeatBinder);
final int variant = serviceClient.getVariant();
Impl lspd = getImpl(variant);
if (lspd == null || !lspd.isInitialized()) {
@ -55,7 +53,6 @@ public class Main {
public static void forkSystemServerPost(IBinder binder) {
LSPApplicationServiceClient.Init(binder, "android");
serviceClient.registerHeartBeat(heartBeatBinder);
final int variant = serviceClient.getVariant();
Impl lspd = getImpl(variant);
if (lspd == null || !lspd.isInitialized()) {

View File

@ -255,7 +255,8 @@ public class BridgeService {
IBinder binder = null;
try {
String processName = data.readString();
binder = service.requestApplicationService(Binder.getCallingUid(), Binder.getCallingPid(), processName).asBinder();
IBinder heartBeat = data.readStrongBinder();
binder = service.requestApplicationService(Binder.getCallingUid(), Binder.getCallingPid(), processName, heartBeat).asBinder();
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e));
}
@ -311,17 +312,18 @@ public class BridgeService {
}
@Keep
public static IBinder getApplicationServiceForSystemServer(IBinder binder) {
if (binder == null) return null;
public static IBinder getApplicationServiceForSystemServer(IBinder binder, IBinder heartBeat) {
if (binder == null || heartBeat == null) return null;
try {
ILSPosedService service = ILSPosedService.Stub.asInterface(binder);
ILSPApplicationService applicationService = service.requestApplicationService(Process.myUid(), Process.myPid(), "android");
ILSPApplicationService applicationService = service.requestApplicationService(Process.myUid(), Process.myPid(), "android", heartBeat);
if (applicationService != null) return applicationService.asBinder();
} catch (Throwable e) {
Log.e(TAG, Log.getStackTraceString(e));
}
return null;
}
private static void tryGetActivityManagerServiceInstance() {
try {
Log.e(TAG, "Trying to get the ams");

View File

@ -150,6 +150,7 @@ public class ConfigManager {
// for system server, cache is not yet ready, we need to query database for it
public boolean shouldSkipSystemServer() {
try (Cursor cursor = db.query("scope INNER JOIN modules ON scope.mid = modules.mid", new String[]{"modules.mid"}, "app_pkg_name=? AND enabled=1", new String[]{"android"}, null, null, null)) {
Log.e(TAG, "ZHEER2");
return cursor == null || !cursor.moveToNext();
}
}
@ -422,6 +423,7 @@ public class ConfigManager {
db.beginTransaction();
db.delete("scope", "mid = ?", new String[]{String.valueOf(mid)});
for (Application app : scopes) {
if (app.packageName.equals("android") && app.userId != 0) continue;
ContentValues values = new ContentValues();
values.put("mid", mid);
values.put("app_pkg_name", app.packageName);

View File

@ -36,22 +36,24 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
private final static Set<Pair<Integer, Integer>> cache = ConcurrentHashMap.newKeySet();
private final static Set<IBinder> handles = ConcurrentHashMap.newKeySet();
@Override
public void registerHeartBeat(IBinder handle) throws RemoteException {
handles.add(handle);
int uid = Binder.getCallingUid();
int pid = Binder.getCallingPid();
cache.add(new Pair<>(uid, pid));
handle.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Log.d(TAG, "pid=" + pid + " uid=" + uid + " is dead.");
cache.remove(new Pair<>(uid, pid));
handles.remove(handle);
handle.unlinkToDeath(this, 0);
}
}, 0);
public boolean registerHeartBeat(int uid, int pid, IBinder handle) {
try {
handle.linkToDeath(new DeathRecipient() {
@Override
public void binderDied() {
Log.d(TAG, "pid=" + pid + " uid=" + uid + " is dead.");
cache.remove(new Pair<>(uid, pid));
handles.remove(handle);
handle.unlinkToDeath(this, 0);
}
}, 0);
handles.add(handle);
cache.add(new Pair<>(uid, pid));
return true;
} catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e));
return false;
}
}
@Override

View File

@ -24,6 +24,7 @@ import android.content.pm.PackageInfo;
import android.content.pm.PackageManager;
import android.net.Uri;
import android.os.Binder;
import android.os.IBinder;
import android.os.RemoteException;
import android.util.Log;
@ -35,16 +36,17 @@ import static io.github.lsposed.lspd.service.ServiceManager.TAG;
public class LSPosedService extends ILSPosedService.Stub {
@Override
public ILSPApplicationService requestApplicationService(int uid, int pid, String processName) {
public ILSPApplicationService requestApplicationService(int uid, int pid, String processName, IBinder heartBeat) {
if (Binder.getCallingUid() != 1000) {
Log.w(TAG, "Someone else got my binder!?");
return null;
}
if (uid == 1000 && processName.equals("android")) {
Log.e(TAG, "ZHEER");
if (ConfigManager.getInstance().shouldSkipSystemServer())
return null;
else
return ServiceManager.getApplicationService();
return ServiceManager.requestApplicationService(uid, pid, heartBeat);
}
if (ConfigManager.getInstance().shouldSkipProcess(new ConfigManager.ProcessScope(processName, uid))) {
Log.d(TAG, "Skipped " + processName + "/" + uid);
@ -55,7 +57,7 @@ public class LSPosedService extends ILSPosedService.Stub {
return null;
}
Log.d(TAG, "returned service");
return ServiceManager.getApplicationService();
return ServiceManager.requestApplicationService(uid, pid, heartBeat);
}

View File

@ -50,7 +50,7 @@ public class ServiceManager {
public static void start() {
Log.i(TAG, "starting server...");
Thread.setDefaultUncaughtExceptionHandler((t, e)->{
Thread.setDefaultUncaughtExceptionHandler((t, e) -> {
Log.e(TAG, Log.getStackTraceString(e));
});
@ -114,6 +114,12 @@ public class ServiceManager {
return applicationService;
}
public static LSPApplicationService requestApplicationService(int uid, int pid, IBinder heartBeat) {
if (applicationService.registerHeartBeat(uid, pid, heartBeat))
return applicationService;
else return null;
}
public static LSPManagerService getManagerService() {
return managerService;
}