Prevent apps from impersonating others in CarrierConfigLoader#dump.
If we detect such impersonation, we throw a SecurityException. However,
we always allow the shell's UID to pass any --requesting-package
argument because that's where bug reports are generated, and apps can
request bug reports using BugreportManager, so the system knows the true
caller's information.
Test: manual with test app holding DUMP + executing shell commands
Test: take bug report with BugreportManager, see caller dumped from CCL
Bug: 146521742
Fix: 152125550
Change-Id: Ib998bdec988cb4ff369a766fb3867570d39c7ccc
Merged-In: Ib998bdec988cb4ff369a766fb3867570d39c7ccc
(cherry picked from commit 54e11bee2f193b5599c2242ad071198f467de7cb)
diff --git a/src/com/android/phone/CarrierConfigLoader.java b/src/com/android/phone/CarrierConfigLoader.java
index 2268d7e..1ccfe7b 100644
--- a/src/com/android/phone/CarrierConfigLoader.java
+++ b/src/com/android/phone/CarrierConfigLoader.java
@@ -21,6 +21,7 @@
import android.annotation.NonNull;
import android.annotation.Nullable;
+import android.app.AppOpsManager;
import android.content.BroadcastReceiver;
import android.content.ComponentName;
import android.content.Context;
@@ -37,6 +38,7 @@
import android.os.IBinder;
import android.os.Message;
import android.os.PersistableBundle;
+import android.os.Process;
import android.os.RemoteException;
import android.os.ResultReceiver;
import android.os.ServiceManager;
@@ -1121,6 +1123,9 @@
&& !TextUtils.isEmpty(args[requestingPackageIndex + 1])) {
String requestingPackage = args[requestingPackageIndex + 1];
indentPW.println("");
+ // Throws a SecurityException if the caller is impersonating another app in an effort to
+ // dump extra info (which may contain PII the caller doesn't have a right to).
+ enforceCallerIsSystemOrRequestingPackage(requestingPackage);
logd("Including default and requesting package " + requestingPackage
+ " carrier services in dump");
indentPW.println("Connected services");
@@ -1160,6 +1165,32 @@
indentPW.println("");
}
+ /**
+ * Passes without problem when one of these conditions is true:
+ * - The caller is a privileged UID (e.g. for dumpstate.cpp generating a bug report, where the
+ * system knows the true caller plumbed in through the {@link android.os.BugreportManager} API).
+ * - The caller's UID matches the supplied package.
+ *
+ * @throws SecurityException if none of the above conditions are met.
+ */
+ private void enforceCallerIsSystemOrRequestingPackage(String requestingPackage)
+ throws SecurityException {
+ final int callingUid = Binder.getCallingUid();
+ if (callingUid == Process.ROOT_UID || callingUid == Process.SYSTEM_UID
+ || callingUid == Process.SHELL_UID || callingUid == Process.PHONE_UID) {
+ // Bug reports (dumpstate.cpp) run as SHELL, and let some other privileged UIDs through
+ // as well.
+ return;
+ }
+ // An app is trying to dump extra detail, block it if they aren't who they claim to be.
+ AppOpsManager appOps = mContext.getSystemService(AppOpsManager.class);
+ if (appOps == null) {
+ throw new SecurityException("No AppOps");
+ }
+ // Will throw a SecurityException if the UID and package don't match.
+ appOps.checkPackage(callingUid, requestingPackage);
+ }
+
private void dumpCarrierServiceIfBound(FileDescriptor fd, IndentingPrintWriter indentPW,
String prefix, String pkgName) {
// Null package is possible if it's early in the boot process, there was a recent crash, we