OSDN Git Service

Work on issue #36427964: SecurityException: Unable to find app...
authorDianne Hackborn <hackbod@google.com>
Tue, 11 Apr 2017 22:37:03 +0000 (15:37 -0700)
committerDianne Hackborn <hackbod@google.com>
Tue, 11 Apr 2017 22:39:16 +0000 (15:39 -0700)
...for caller android.app.IApplicationThread

Verify, if we don't find the caller on the LRU process list, that
it isn't actually on the main list.  (And if it is on the main list,
we can now recover from that.)  Also fix the error message when this
fails for startService() to print the correct calling pid.

Test: booted and ran

Change-Id: I0a81c679bb7e6eb15b854ed4b457d01b386d5dba

services/core/java/com/android/server/am/ActiveServices.java
services/core/java/com/android/server/am/ActivityManagerService.java

index 7dd75df..c77820b 100644 (file)
@@ -324,7 +324,7 @@ public final class ActiveServices {
             if (callerApp == null) {
                 throw new SecurityException(
                         "Unable to find app for caller " + caller
-                        + " (pid=" + Binder.getCallingPid()
+                        + " (pid=" + callingPid
                         + ") when starting service " + service);
             }
             callerFg = callerApp.setSchedGroup != ProcessList.SCHED_GROUP_BACKGROUND;
@@ -353,29 +353,24 @@ public final class ActiveServices {
         // If this isn't a direct-to-foreground start, check our ability to kick off an
         // arbitrary service
         if (!r.startRequested && !fgRequired) {
-            final long token = Binder.clearCallingIdentity();
-            try {
-                // Before going further -- if this app is not allowed to start services in the
-                // background, then at this point we aren't going to let it period.
-                final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
-                        r.appInfo.targetSdkVersion, callingPid, false, false);
-                if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
-                    Slog.w(TAG, "Background start not allowed: service "
-                            + service + " to " + r.name.flattenToShortString()
-                            + " from pid=" + callingPid + " uid=" + callingUid
-                            + " pkg=" + callingPackage);
-                    if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
-                        // In this case we are silently disabling the app, to disrupt as
-                        // little as possible existing apps.
-                        return null;
-                    }
-                    // This app knows it is in the new model where this operation is not
-                    // allowed, so tell it what has happened.
-                    UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
-                    return new ComponentName("?", "app is in background uid " + uidRec);
-                }
-            } finally {
-                Binder.restoreCallingIdentity(token);
+            // Before going further -- if this app is not allowed to start services in the
+            // background, then at this point we aren't going to let it period.
+            final int allowed = mAm.getAppStartModeLocked(r.appInfo.uid, r.packageName,
+                    r.appInfo.targetSdkVersion, callingPid, false, false);
+            if (allowed != ActivityManager.APP_START_MODE_NORMAL) {
+                Slog.w(TAG, "Background start not allowed: service "
+                        + service + " to " + r.name.flattenToShortString()
+                        + " from pid=" + callingPid + " uid=" + callingUid
+                        + " pkg=" + callingPackage);
+                if (allowed == ActivityManager.APP_START_MODE_DELAYED) {
+                    // In this case we are silently disabling the app, to disrupt as
+                    // little as possible existing apps.
+                    return null;
+                }
+                // This app knows it is in the new model where this operation is not
+                // allowed, so tell it what has happened.
+                UidRecord uidRec = mAm.mActiveUids.get(r.appInfo.uid);
+                return new ComponentName("?", "app is in background uid " + uidRec);
             }
         }
 
index 35654d7..8587cfb 100644 (file)
@@ -5243,10 +5243,10 @@ public class ActivityManagerService extends IActivityManager.Stub
     }
 
     private final int getLRURecordIndexForAppLocked(IApplicationThread thread) {
-        IBinder threadBinder = thread.asBinder();
+        final IBinder threadBinder = thread.asBinder();
         // Find the application record.
         for (int i=mLruProcesses.size()-1; i>=0; i--) {
-            ProcessRecord rec = mLruProcesses.get(i);
+            final ProcessRecord rec = mLruProcesses.get(i);
             if (rec.thread != null && rec.thread.asBinder() == threadBinder) {
                 return i;
             }
@@ -5261,7 +5261,27 @@ public class ActivityManagerService extends IActivityManager.Stub
         }
 
         int appIndex = getLRURecordIndexForAppLocked(thread);
-        return appIndex >= 0 ? mLruProcesses.get(appIndex) : null;
+        if (appIndex >= 0) {
+            return mLruProcesses.get(appIndex);
+        }
+
+        // Validation: if it isn't in the LRU list, it shouldn't exist, but let's
+        // double-check that.
+        final IBinder threadBinder = thread.asBinder();
+        final ArrayMap<String, SparseArray<ProcessRecord>> pmap = mProcessNames.getMap();
+        for (int i = pmap.size()-1; i >= 0; i--) {
+            final SparseArray<ProcessRecord> procs = pmap.valueAt(i);
+            for (int j = procs.size()-1; j >= 0; j--) {
+                final ProcessRecord proc = procs.valueAt(j);
+                if (proc.thread != null && proc.thread.asBinder() == threadBinder) {
+                    Slog.wtf(TAG, "getRecordForApp: exists in name list but not in LRU list: "
+                            + proc);
+                    return proc;
+                }
+            }
+        }
+
+        return null;
     }
 
     final void doLowMemReportIfNeededLocked(ProcessRecord dyingProc) {
@@ -17861,10 +17881,14 @@ public class ActivityManagerService extends IActivityManager.Stub
             final int callingPid = Binder.getCallingPid();
             final int callingUid = Binder.getCallingUid();
             final long origId = Binder.clearCallingIdentity();
-            ComponentName res = mServices.startServiceLocked(caller, service,
-                    resolvedType, id, notification, callingPid, callingUid,
-                    requireForeground, callingPackage, userId);
-            Binder.restoreCallingIdentity(origId);
+            ComponentName res;
+            try {
+                res = mServices.startServiceLocked(caller, service,
+                        resolvedType, id, notification, callingPid, callingUid,
+                        requireForeground, callingPackage, userId);
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
             return res;
         }
     }
@@ -17876,9 +17900,13 @@ public class ActivityManagerService extends IActivityManager.Stub
             if (DEBUG_SERVICE) Slog.v(TAG_SERVICE,
                     "startServiceInPackage: " + service + " type=" + resolvedType);
             final long origId = Binder.clearCallingIdentity();
-            ComponentName res = mServices.startServiceLocked(null, service,
-                    resolvedType, 0, null, -1, uid, fgRequired, callingPackage, userId);
-            Binder.restoreCallingIdentity(origId);
+            ComponentName res;
+            try {
+                res = mServices.startServiceLocked(null, service,
+                        resolvedType, 0, null, -1, uid, fgRequired, callingPackage, userId);
+            } finally {
+                Binder.restoreCallingIdentity(origId);
+            }
             return res;
         }
     }