[core] Send app binder when requesting binder (#177)
This commit is contained in:
parent
065667df04
commit
6aed74acdd
|
|
@ -1,8 +1,6 @@
|
|||
package io.github.lsposed.lspd.service;
|
||||
|
||||
interface ILSPApplicationService {
|
||||
void registerHeartBeat(IBinder handle) = 1;
|
||||
|
||||
IBinder requestModuleBinder() = 2;
|
||||
|
||||
IBinder requestManagerBinder() = 3;
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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 {
|
||||
|
|
|
|||
|
|
@ -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()) {
|
||||
|
|
|
|||
|
|
@ -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");
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
|
|
|||
Loading…
Reference in New Issue