From b5e249963141b2ab00d1a9b5e4b76d5689d64f2e Mon Sep 17 00:00:00 2001 From: Mark Lu Date: Mon, 21 Nov 2016 15:38:13 +0800 Subject: [PATCH] [AM] Fix system server may killed when monkey crash. Symptom: monkey crash caused system server killed. Root Cause: when monkey crash or app crash before process bound, calling AppErrors.crashApplication will first clear binder identities, that will caused calling pid / uid will become with current process (i.e. system server), so in handleAppCrashInActivityController, when monkey registered activityController would like to kill crash process, but not found in AMS (monkey created by app_process) then using calling pid / uid will become to kill system server. Solution: add calling pid / uid parameters for handleAppCrashInActivityController to prevent binder identities cleared case. Test: To simulate monkey or app crash before process bound may not easy by using simple command, but we can write a sample program to simulate RuntimeInit to call handleApplicationCrash when met uncauchtException, Below is test steps in Android 7.1.1 emulator. 1. start emulator 2. after emulater started, use "adb shell am monitor" to set activityController & monitor process by console. 3. write a .jar program as monkey by below sample code to simulate null application binder to call handleApplicationCrash() as RuntimeInit: package com.android.test; import com.android.internal.os.BaseCommand; public class SimulateMonkeyCrash extends BaseCommand { public static void main(String[] args) { IActivityManager am = ActivityManagerNative.getDefault(); try { am.handleApplicationCrash(null, new ApplicationErrorReport.CrashInfo(new Throwable())); } catch (RemoteException e) { e.printStackTrace(); } } 4. write a .sh file named SimulateMonkeyCrash.sh as below: # base=/system export CLASSPATH=$base/framework/SimulateMonkeyCrash.jar exec app_process $base/bin com.android.test.SimulateMonkeyCrash "$@" 5. let .sh file is executable by "chomod 755". 6. push .jar file into /system/framework & .sh file into /system/bin 7 execute .sh file. 8. activityController will detected program crash in console as below, press k: Waiting after crash... available commands: (c)ontinue: show crash dialog (k)ill: immediately kill app (q)uit: finish monitoring 9 you can see system server is crash. Change-Id: Ibac4d88872f24af109d8e8522ecf5ac72fac0ce0 --- .../java/com/android/server/am/AppErrors.java | 17 +++++++++++------ 1 file changed, 11 insertions(+), 6 deletions(-) diff --git a/services/core/java/com/android/server/am/AppErrors.java b/services/core/java/com/android/server/am/AppErrors.java index ba799f2ca3d18..96a804b753f93 100644 --- a/services/core/java/com/android/server/am/AppErrors.java +++ b/services/core/java/com/android/server/am/AppErrors.java @@ -304,15 +304,19 @@ class AppErrors { * @param crashInfo describing the failure */ void crashApplication(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { + final int callingPid = Binder.getCallingPid(); + final int callingUid = Binder.getCallingUid(); + final long origId = Binder.clearCallingIdentity(); try { - crashApplicationInner(r, crashInfo); + crashApplicationInner(r, crashInfo, callingPid, callingUid); } finally { Binder.restoreCallingIdentity(origId); } } - void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo) { + void crashApplicationInner(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, + int callingPid, int callingUid) { long timeMillis = System.currentTimeMillis(); String shortMsg = crashInfo.exceptionClassName; String longMsg = crashInfo.exceptionMessage; @@ -331,7 +335,7 @@ class AppErrors { * finish now and don't show the app error dialog. */ if (handleAppCrashInActivityController(r, crashInfo, shortMsg, longMsg, stackTrace, - timeMillis)) { + timeMillis, callingPid, callingUid)) { return; } @@ -433,15 +437,16 @@ class AppErrors { private boolean handleAppCrashInActivityController(ProcessRecord r, ApplicationErrorReport.CrashInfo crashInfo, String shortMsg, String longMsg, - String stackTrace, long timeMillis) { + String stackTrace, long timeMillis, + int callingPid, int callingUid) { if (mService.mController == null) { return false; } try { String name = r != null ? r.processName : null; - int pid = r != null ? r.pid : Binder.getCallingPid(); - int uid = r != null ? r.info.uid : Binder.getCallingUid(); + int pid = r != null ? r.pid : callingPid; + int uid = r != null ? r.info.uid : callingUid; if (!mService.mController.appCrashed(name, pid, shortMsg, longMsg, timeMillis, crashInfo.stackTrace)) { if ("1".equals(SystemProperties.get(SYSTEM_DEBUGGABLE, "0"))