mirror of
https://github.com/microg/android_packages_apps_GmsCore
synced 2026-08-06 14:26:05 -04:00
DroidGuard: Allow blocking of dump() for services when missing permission
Also request permission for the future
This commit is contained in:
parent
5560a94031
commit
90d4d8e9c9
3 changed files with 97 additions and 0 deletions
|
|
@ -7,6 +7,8 @@
|
|||
xmlns:tools="http://schemas.android.com/tools">
|
||||
|
||||
<uses-permission android:name="android.permission.INTERNET" />
|
||||
<uses-permission android:name="android.permission.DUMP"
|
||||
tools:ignore="ProtectedPermissions" />
|
||||
|
||||
<application>
|
||||
<service
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ import org.microg.gms.droidguard.PingData;
|
|||
import org.microg.gms.droidguard.Request;
|
||||
import org.microg.gms.droidguard.core.HardwareAttestationBlockingProvider;
|
||||
import org.microg.gms.droidguard.core.SerialUnflaky;
|
||||
import org.microg.gms.droidguard.core.ServiceCallProxy;
|
||||
|
||||
import java.util.Collections;
|
||||
import java.util.concurrent.Executor;
|
||||
|
|
@ -117,6 +118,8 @@ public class DroidGuardChimeraService extends TracingIntentService {
|
|||
if (intent != null && intent.getAction() != null && intent.getAction().equals("com.google.android.gms.droidguard.service.START")) {
|
||||
HardwareAttestationBlockingProvider.ensureEnabled(DroidGuardPreferences.isHardwareAttestationBlocked(this));
|
||||
SerialUnflaky.INSTANCE.fetch();
|
||||
ServiceCallProxy.INSTANCE.maySetBlockDumpForService(this, "SurfaceFlinger");
|
||||
ServiceCallProxy.INSTANCE.maySetBlockDumpForService(this, "thermalservice");
|
||||
return new DroidGuardServiceBroker(this);
|
||||
}
|
||||
return null;
|
||||
|
|
@ -132,6 +135,8 @@ public class DroidGuardChimeraService extends TracingIntentService {
|
|||
this.d = new ThreadPoolExecutor(1, 1, 0, TimeUnit.NANOSECONDS, new LinkedBlockingQueue<>(1), new ThreadPoolExecutor.DiscardPolicy());
|
||||
HardwareAttestationBlockingProvider.ensureEnabled(DroidGuardPreferences.isHardwareAttestationBlocked(this));
|
||||
SerialUnflaky.INSTANCE.fetch();
|
||||
ServiceCallProxy.INSTANCE.maySetBlockDumpForService(this, "SurfaceFlinger");
|
||||
ServiceCallProxy.INSTANCE.maySetBlockDumpForService(this, "thermalservice");
|
||||
super.onCreate();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -0,0 +1,90 @@
|
|||
/*
|
||||
* SPDX-FileCopyrightText: 2026 microG Project Team
|
||||
* SPDX-License-Identifier: Apache-2.0
|
||||
*/
|
||||
|
||||
package org.microg.gms.droidguard.core
|
||||
|
||||
import android.annotation.SuppressLint
|
||||
import android.content.Context
|
||||
import android.content.pm.PackageManager
|
||||
import android.os.IBinder
|
||||
import android.util.Log
|
||||
import androidx.core.content.ContextCompat
|
||||
import java.lang.reflect.Field
|
||||
import java.lang.reflect.Method
|
||||
import java.lang.reflect.Proxy
|
||||
|
||||
private const val TAG = "DroidGuard"
|
||||
|
||||
/**
|
||||
* Helper to block the call to dump() on services
|
||||
*
|
||||
* We may want to extend this later to allow for arbitrary service call interceptions
|
||||
*/
|
||||
@SuppressLint("PrivateApi")
|
||||
object ServiceCallProxy {
|
||||
private var serviceManagerClass: Class<*>? = null
|
||||
private var getServiceMethod: Method? = null
|
||||
private var activeServices: MutableMap<String, IBinder?>? = null
|
||||
private val proxyEnabled: MutableMap<String, Boolean> = hashMapOf()
|
||||
private val originalServices: MutableMap<String, IBinder> = hashMapOf()
|
||||
|
||||
init {
|
||||
try {
|
||||
serviceManagerClass = Class.forName("android.os.ServiceManager")
|
||||
getServiceMethod =
|
||||
serviceManagerClass!!.getDeclaredMethod("getService", String::class.java)
|
||||
getServiceMethod!!.isAccessible = true
|
||||
val cacheField: Field = serviceManagerClass!!.getDeclaredField("sCache")
|
||||
cacheField.isAccessible = true
|
||||
@Suppress("UNCHECKED_CAST")
|
||||
activeServices = cacheField.get(null) as MutableMap<String, IBinder?>?
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, "Error configuring DumpBlockingProxy", e)
|
||||
}
|
||||
}
|
||||
|
||||
fun maySetBlockDumpForService(context: Context, systemServiceName: String) {
|
||||
val permissionResult =
|
||||
ContextCompat.checkSelfPermission(context, android.Manifest.permission.DUMP)
|
||||
if (permissionResult == PackageManager.PERMISSION_DENIED) {
|
||||
setBlockDumpForService(systemServiceName, true)
|
||||
} else if (permissionResult == PackageManager.PERMISSION_GRANTED) {
|
||||
setBlockDumpForService(systemServiceName, false)
|
||||
}
|
||||
}
|
||||
|
||||
fun setBlockDumpForService(systemServiceName: String, enabled: Boolean) {
|
||||
if (proxyEnabled.containsKey(systemServiceName) && proxyEnabled[systemServiceName] == enabled) return
|
||||
if (getServiceMethod == null || activeServices == null) return
|
||||
Log.d(TAG, "Configuring blocker for dump() on service $systemServiceName")
|
||||
if (enabled) {
|
||||
val originalService = try {
|
||||
getServiceMethod!!.invoke(null, systemServiceName) as IBinder
|
||||
} catch (e: Exception) {
|
||||
Log.w(TAG, e)
|
||||
return
|
||||
}
|
||||
val newService = Proxy.newProxyInstance(
|
||||
IBinder::class.java.getClassLoader(),
|
||||
arrayOf<Class<*>>(IBinder::class.java),
|
||||
{ _, method, args ->
|
||||
when (method.name) {
|
||||
"dump" -> {
|
||||
Log.d(TAG, "Blocking dump() call on $systemServiceName");
|
||||
null
|
||||
}
|
||||
|
||||
else -> method.invoke(originalService, args)
|
||||
}
|
||||
}) as IBinder
|
||||
originalServices[systemServiceName] = originalService
|
||||
activeServices!![systemServiceName] = newService
|
||||
proxyEnabled[systemServiceName] = true
|
||||
} else if (proxyEnabled[systemServiceName] == true) {
|
||||
activeServices!![systemServiceName] = originalServices[systemServiceName]
|
||||
proxyEnabled[systemServiceName] = false
|
||||
}
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue