[core] Workaround for service manager overwritten on Android R (#581)

This commit is contained in:
LoveSy 2021-05-15 03:05:04 +08:00 committed by GitHub
parent d9f95d1280
commit 0df0a14808
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 209 additions and 79 deletions

View File

@ -0,0 +1,7 @@
package org.lsposed.lspd.service;
import org.lsposed.lspd.service.ILSPApplicationService;
interface ILSPSystemServerService {
ILSPApplicationService requestApplicationService(int uid, int pid, String processName, IBinder heartBeat) = 1;
}

View File

@ -36,21 +36,21 @@ public class LSPApplicationServiceClient implements ILSPApplicationService {
static String processName = null; static String processName = null;
public static LSPApplicationServiceClient serviceClient = null; public static LSPApplicationServiceClient serviceClient = null;
private static final IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
serviceBinder.unlinkToDeath(this, 0);
serviceBinder = null;
service = null;
}
};
public static void Init(IBinder binder, String niceName) { public static void Init(IBinder binder, String niceName) {
if (serviceClient == null && binder != null && serviceBinder == null && service == null) { if (serviceClient == null && binder != null && serviceBinder == null && service == null) {
serviceBinder = binder; serviceBinder = binder;
processName = niceName; processName = niceName;
try { try {
serviceBinder.linkToDeath( serviceBinder.linkToDeath(recipient, 0);
new IBinder.DeathRecipient() {
@Override
public void binderDied() {
serviceBinder.unlinkToDeath(this, 0);
serviceBinder = null;
service = null;
}
}, 0);
} catch (RemoteException e) { } catch (RemoteException e) {
Utils.logE("link to death error: ", e); Utils.logE("link to death error: ", e);
} }

View File

@ -34,22 +34,25 @@ import static org.lsposed.lspd.service.ServiceManager.TAG;
public class ActivityManagerService { public class ActivityManagerService {
private static IActivityManager am = null; private static IActivityManager am = null;
private static IBinder binder = null; private static IBinder binder = null;
private static final IBinder.DeathRecipient deathRecipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "am is dead");
binder.unlinkToDeath(this, 0);
binder = null;
am = null;
}
};
public static IActivityManager getActivityManager() { public static IActivityManager getActivityManager() {
if (binder == null && am == null) { if (binder == null && am == null) {
binder = ServiceManager.getService("activity"); binder = ServiceManager.getService("activity");
if (binder == null) return null; if (binder == null) return null;
try { try {
binder.linkToDeath(new IBinder.DeathRecipient() { binder.linkToDeath(deathRecipient, 0);
@Override
public void binderDied() {
Log.w(TAG, "am is dead");
binder.unlinkToDeath(this, 0);
binder = null;
am = null;
}
}, 0);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }

View File

@ -64,13 +64,8 @@ public class BridgeService {
private static ILSPosedService service = null; private static ILSPosedService service = null;
// for service // for service
static class BridgeServiceDeathRecipient implements IBinder.DeathRecipient { private static IBinder bridgeService;
private final IBinder bridgeService; private static final IBinder.DeathRecipient bridgeRecipient = new IBinder.DeathRecipient() {
BridgeServiceDeathRecipient(IBinder bridgeService) throws RemoteException {
this.bridgeService = bridgeService;
bridgeService.linkToDeath(this, 0);
}
@Override @Override
public void binderDied() { public void binderDied() {
@ -96,16 +91,21 @@ public class BridgeService {
} }
bridgeService.unlinkToDeath(this, 0); bridgeService.unlinkToDeath(this, 0);
bridgeService = null;
listener.onSystemServerDied(); listener.onSystemServerDied();
sendToBridge(serviceBinder, true); sendToBridge(serviceBinder, true);
} }
} };
// for client // for client
private static final IBinder.DeathRecipient LSPSERVICE_DEATH_RECIPIENT = () -> { private static final IBinder.DeathRecipient serviceRecipient = new IBinder.DeathRecipient() {
serviceBinder = null; @Override
service = null; public void binderDied() {
Log.e(TAG, "service is dead"); serviceBinder.unlinkToDeath(this, 0);
serviceBinder = null;
service = null;
Log.e(TAG, "service is dead");
}
}; };
public interface Listener { public interface Listener {
@ -121,7 +121,6 @@ public class BridgeService {
// For service // For service
private static void sendToBridge(IBinder binder, boolean isRestart) { private static void sendToBridge(IBinder binder, boolean isRestart) {
IBinder bridgeService;
do { do {
bridgeService = ServiceManager.getService(SERVICE_NAME); bridgeService = ServiceManager.getService(SERVICE_NAME);
if (bridgeService != null && bridgeService.pingBinder()) { if (bridgeService != null && bridgeService.pingBinder()) {
@ -143,7 +142,7 @@ public class BridgeService {
} }
try { try {
new BridgeServiceDeathRecipient(bridgeService); bridgeService.linkToDeath(bridgeRecipient, 0);
} catch (Throwable e) { } catch (Throwable e) {
Log.w(TAG, "linkToDeath " + Log.getStackTraceString(e)); Log.w(TAG, "linkToDeath " + Log.getStackTraceString(e));
sendToBridge(binder, false); sendToBridge(binder, false);
@ -218,15 +217,16 @@ public class BridgeService {
} }
}); });
} else { } else {
serviceBinder.unlinkToDeath(LSPSERVICE_DEATH_RECIPIENT, 0); serviceBinder.unlinkToDeath(serviceRecipient, 0);
} }
Binder.restoreCallingIdentity(token); Binder.restoreCallingIdentity(token);
serviceBinder = Binder_allowBlocking(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(serviceRecipient, 0);
} catch (RemoteException ignored) { } catch (Throwable e) {
Log.e(TAG, "service link to death: ", e);
} }
Log.i(TAG, "binder received"); Log.i(TAG, "binder received");
@ -324,8 +324,8 @@ public class BridgeService {
public static IBinder getApplicationServiceForSystemServer(IBinder binder, IBinder heartBeat) { public static IBinder getApplicationServiceForSystemServer(IBinder binder, IBinder heartBeat) {
if (binder == null || heartBeat == null) return null; if (binder == null || heartBeat == null) return null;
try { try {
ILSPosedService service = ILSPosedService.Stub.asInterface(binder); var service = ILSPSystemServerService.Stub.asInterface(binder);
ILSPApplicationService applicationService = service.requestApplicationService(Process.myUid(), Process.myPid(), "android", heartBeat); var applicationService = service.requestApplicationService(Process.myUid(), Process.myPid(), "android", heartBeat);
if (applicationService != null) return applicationService.asBinder(); if (applicationService != null) return applicationService.asBinder();
} catch (Throwable e) { } catch (Throwable e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));

View File

@ -35,18 +35,22 @@ public class LSPApplicationService extends ILSPApplicationService.Stub {
// <uid, pid> // <uid, pid>
private final static Set<Pair<Integer, Integer>> cache = ConcurrentHashMap.newKeySet(); private final static Set<Pair<Integer, Integer>> cache = ConcurrentHashMap.newKeySet();
private final static Set<IBinder> handles = ConcurrentHashMap.newKeySet(); private final static Set<IBinder> handles = ConcurrentHashMap.newKeySet();
private final static Set<IBinder.DeathRecipient> recipients = ConcurrentHashMap.newKeySet();
public boolean registerHeartBeat(int uid, int pid, IBinder handle) { public boolean registerHeartBeat(int uid, int pid, IBinder handle) {
try { try {
handle.linkToDeath(new DeathRecipient() { var recipient = new DeathRecipient() {
@Override @Override
public void binderDied() { public void binderDied() {
Log.d(TAG, "pid=" + pid + " uid=" + uid + " is dead."); Log.d(TAG, "pid=" + pid + " uid=" + uid + " is dead.");
cache.remove(new Pair<>(uid, pid)); cache.remove(new Pair<>(uid, pid));
handles.remove(handle); handles.remove(handle);
handle.unlinkToDeath(this, 0); handle.unlinkToDeath(this, 0);
recipients.remove(this);
} }
}, 0); };
recipients.add(recipient);
handle.linkToDeath(recipient, 0);
handles.add(handle); handles.add(handle);
cache.add(new Pair<>(uid, pid)); cache.add(new Pair<>(uid, pid));
return true; return true;

View File

@ -0,0 +1,82 @@
package org.lsposed.lspd.service;
import static org.lsposed.lspd.service.ServiceManager.TAG;
import static org.lsposed.lspd.service.ServiceManager.getSystemServiceManager;
import android.os.Build;
import android.os.IBinder;
import android.os.IServiceCallback;
import android.os.Parcel;
import android.os.RemoteException;
import android.util.Log;
public class LSPSystemServerService extends ILSPSystemServerService.Stub implements IBinder.DeathRecipient {
public static final String PROXY_SERVICE_NAME = "serial";
private IBinder originService = null;
public void putBinderForSystemServer() {
android.os.ServiceManager.addService(PROXY_SERVICE_NAME, this);
binderDied();
}
private final IServiceCallback serviceCallback = new IServiceCallback.Stub() {
@Override
public void onRegistration(String name, IBinder binder) {
if (name.equals(PROXY_SERVICE_NAME) && binder != null && binder != LSPSystemServerService.this) {
Log.d(TAG, "Register " + name + " " + binder);
originService = binder;
LSPSystemServerService.this.linkToDeath();
}
}
@Override
public IBinder asBinder() {
return this;
}
};
public LSPSystemServerService() {
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
try {
getSystemServiceManager().registerForNotifications(PROXY_SERVICE_NAME, serviceCallback);
} catch (Throwable e) {
Log.e(TAG, "unregister: ", e);
}
}
}
@Override
public ILSPApplicationService requestApplicationService(int uid, int pid, String processName, IBinder heartBeat) throws RemoteException {
if (ConfigManager.getInstance().shouldSkipSystemServer() || uid != 1000 || heartBeat == null || !"android".equals(processName))
return null;
else
return ServiceManager.requestApplicationService(uid, pid, heartBeat);
}
@Override
public boolean onTransact(int code, Parcel data, Parcel reply, int flags) throws RemoteException {
if (originService != null) {
return originService.transact(code, data, reply, flags);
}
return super.onTransact(code, data, reply, flags);
}
public void linkToDeath() {
try {
originService.linkToDeath(this, 0);
} catch (Throwable e) {
Log.e(TAG, "system server service: link to death", e);
}
}
@Override
public void binderDied() {
if (originService != null) {
originService.unlinkToDeath(this, 0);
originService = null;
}
}
}

View File

@ -42,12 +42,6 @@ public class LSPosedService extends ILSPosedService.Stub {
Log.w(TAG, "Someone else got my binder!?"); Log.w(TAG, "Someone else got my binder!?");
return null; return null;
} }
if (uid == 1000 && processName.equals("android")) {
if (ConfigManager.getInstance().shouldSkipSystemServer())
return null;
else
return ServiceManager.requestApplicationService(uid, pid, heartBeat);
}
if (ConfigManager.getInstance().shouldSkipProcess(new ConfigManager.ProcessScope(processName, uid))) { if (ConfigManager.getInstance().shouldSkipProcess(new ConfigManager.ProcessScope(processName, uid))) {
Log.d(TAG, "Skipped " + processName + "/" + uid); Log.d(TAG, "Skipped " + processName + "/" + uid);
return null; return null;
@ -60,7 +54,6 @@ public class LSPosedService extends ILSPosedService.Stub {
return ServiceManager.requestApplicationService(uid, pid, heartBeat); return ServiceManager.requestApplicationService(uid, pid, heartBeat);
} }
@Override @Override
public void dispatchPackageChanged(Intent intent) throws RemoteException { public void dispatchPackageChanged(Intent intent) throws RemoteException {
if (Binder.getCallingUid() != 1000 || intent == null) return; if (Binder.getCallingUid() != 1000 || intent == null) return;

View File

@ -67,21 +67,22 @@ import hidden.HiddenApiBridge;
public class PackageService { public class PackageService {
private static IPackageManager pm = null; private static IPackageManager pm = null;
private static IBinder binder = null; private static IBinder binder = null;
private static final IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
};
public static IPackageManager getPackageManager() { public static IPackageManager getPackageManager() {
if (binder == null && pm == null) { if (binder == null && pm == null) {
binder = ServiceManager.getService("package"); binder = ServiceManager.getService("package");
if (binder == null) return null; if (binder == null) return null;
try { try {
binder.linkToDeath(new IBinder.DeathRecipient() { binder.linkToDeath(recipient, 0);
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
}, 0);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }

View File

@ -11,21 +11,22 @@ import static org.lsposed.lspd.service.ServiceManager.TAG;
public class PowerService { public class PowerService {
private static IPowerManager pm = null; private static IPowerManager pm = null;
private static IBinder binder = null; private static IBinder binder = null;
private static final IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
};
public static IPowerManager getPowerManager() { public static IPowerManager getPowerManager() {
if (binder == null && pm == null) { if (binder == null && pm == null) {
binder = ServiceManager.getService("power"); binder = ServiceManager.getService("power");
if (binder == null) return null; if (binder == null) return null;
try { try {
binder.linkToDeath(new IBinder.DeathRecipient() { binder.linkToDeath(recipient, 0);
@Override
public void binderDied() {
Log.w(TAG, "pm is dead");
binder.unlinkToDeath(this, 0);
binder = null;
pm = null;
}
}, 0);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }

View File

@ -20,18 +20,23 @@
package org.lsposed.lspd.service; package org.lsposed.lspd.service;
import android.content.Context; import android.content.Context;
import android.os.Build;
import android.os.IBinder; import android.os.IBinder;
import android.os.IServiceManager;
import android.os.Looper; import android.os.Looper;
import android.util.Log; import android.util.Log;
import com.android.internal.os.BinderInternal;
import org.lsposed.lspd.BuildConfig; import org.lsposed.lspd.BuildConfig;
import hidden.HiddenApiBridge;
public class ServiceManager { public class ServiceManager {
private static LSPosedService mainService = null; private static LSPosedService mainService = null;
private static LSPModuleService moduleService = null; private static LSPModuleService moduleService = null;
private static LSPApplicationService applicationService = null; private static LSPApplicationService applicationService = null;
private static LSPManagerService managerService = null; private static LSPManagerService managerService = null;
private static LSPSystemServerService systemServerService = null;
public static final String TAG = "LSPosedService"; public static final String TAG = "LSPosedService";
private static void waitSystemService(String name) { private static void waitSystemService(String name) {
@ -45,8 +50,8 @@ public class ServiceManager {
} }
} }
private static void putBinderForSystemServer() { public static IServiceManager getSystemServiceManager() {
android.os.ServiceManager.addService("serial", mainService); return IServiceManager.Stub.asInterface(HiddenApiBridge.Binder_allowBlocking(BinderInternal.getContextObject()));
} }
// call by ourselves // call by ourselves
@ -63,8 +68,9 @@ public class ServiceManager {
moduleService = new LSPModuleService(); moduleService = new LSPModuleService();
applicationService = new LSPApplicationService(); applicationService = new LSPApplicationService();
managerService = new LSPManagerService(); managerService = new LSPManagerService();
systemServerService = new LSPSystemServerService();
putBinderForSystemServer(); systemServerService.putBinderForSystemServer();
waitSystemService("package"); waitSystemService("package");
waitSystemService("activity"); waitSystemService("activity");
@ -89,7 +95,7 @@ public class ServiceManager {
@Override @Override
public void onSystemServerDied() { public void onSystemServerDied() {
Log.w(TAG, "system server died"); Log.w(TAG, "system server died");
putBinderForSystemServer(); systemServerService.putBinderForSystemServer();
} }
}); });

View File

@ -34,21 +34,22 @@ import static org.lsposed.lspd.service.ServiceManager.TAG;
public class UserService { public class UserService {
private static IUserManager um = null; private static IUserManager um = null;
private static IBinder binder = null; private static IBinder binder = null;
private static IBinder.DeathRecipient recipient = new IBinder.DeathRecipient() {
@Override
public void binderDied() {
Log.w(TAG, "um is dead");
binder.unlinkToDeath(this, 0);
binder = null;
um = null;
}
};
public static IUserManager getUserManager() { public static IUserManager getUserManager() {
if (binder == null && um == null) { if (binder == null && um == null) {
binder = ServiceManager.getService("user"); binder = ServiceManager.getService("user");
if (binder == null) return null; if (binder == null) return null;
try { try {
binder.linkToDeath(new IBinder.DeathRecipient() { binder.linkToDeath(recipient, 0);
@Override
public void binderDied() {
Log.w(TAG, "um is dead");
binder.unlinkToDeath(this, 0);
binder = null;
um = null;
}
}, 0);
} catch (RemoteException e) { } catch (RemoteException e) {
Log.e(TAG, Log.getStackTraceString(e)); Log.e(TAG, Log.getStackTraceString(e));
} }

View File

@ -0,0 +1,13 @@
package android.os;
public interface IServiceCallback extends IInterface
{
public static abstract class Stub extends android.os.Binder implements android.os.IServiceCallback {
}
/**
* Called when a service is registered.
*
* @param name the service name that has been registered with
* @param binder the binder that is registered
*/
public void onRegistration(java.lang.String name, android.os.IBinder binder) throws android.os.RemoteException;
}

View File

@ -1,4 +1,16 @@
package android.os; package android.os;
public interface IServiceManager { public interface IServiceManager extends IInterface {
void tryUnregisterService(java.lang.String name, android.os.IBinder service);
IBinder getService(String name);
public void registerForNotifications(String name, IServiceCallback cb);
abstract class Stub extends Binder implements IServiceManager {
public static IServiceManager asInterface(IBinder obj) {
throw new UnsupportedOperationException();
}
}
} }

View File

@ -0,0 +1,7 @@
package com.android.internal.os;
import android.os.IBinder;
public class BinderInternal {
public static final native IBinder getContextObject();
}