frameworks/base
修订版 | eee0afbaeb7202dbd5a7cf80aac770a3c178119a (tree) |
---|---|
时间 | 2020-08-05 10:12:50 |
作者 | Christopher Tate <ctate@goog...> |
Commiter | Vasyl Gello |
DO NOT MERGE - Kill apps outright for API contract violations
...rather than relying on in-app code to perform the shutdown.
Backport of security fix.
Bug: 128649910
Bug: 140108616
Test: manual
Test: atest OsHostTests#testForegroundServiceBadNotification
[basilgello: back-port to 14.1:
- core/java/android/app/IActivityManager.aidl -> core/java/android/app/IActivityManager.java,
- no serviceForegroundCrash in services/core/java/com/android/server/am/ActiveServices.java,
- no runCrash in services/core/java/com/android/server/am/ActivityManagerShellCommand.java,
- add argument to ActivityManagerProxy,
- no mNotificationLock and ForegroundService,
- adjust args count (remove '-1') in killMisbehavingService]
Signed-off-by: Vasyl Gello <vasek.gello@gmail.com>
Change-Id: I94d9de50bb03c33666471e3dbd9c721e9278f7cb
Merged-In: I94d9de50bb03c33666471e3dbd9c721e9278f7cb
(cherry picked from commit a79b6ba5c59dc6aaa8adbe1ffa3ee4b761f45e7f)
@@ -1959,7 +1959,8 @@ public abstract class ActivityManagerNative extends Binder implements IActivityM | ||
1959 | 1959 | int initialPid = data.readInt(); |
1960 | 1960 | String packageName = data.readString(); |
1961 | 1961 | String message = data.readString(); |
1962 | - crashApplication(uid, initialPid, packageName, message); | |
1962 | + crashApplication(uid, initialPid, packageName, message, | |
1963 | + false /*force*/); | |
1963 | 1964 | reply.writeNoException(); |
1964 | 1965 | return true; |
1965 | 1966 | } |
@@ -5523,7 +5524,7 @@ class ActivityManagerProxy implements IActivityManager | ||
5523 | 5524 | } |
5524 | 5525 | |
5525 | 5526 | public void crashApplication(int uid, int initialPid, String packageName, |
5526 | - String message) throws RemoteException { | |
5527 | + String message, boolean force) throws RemoteException { | |
5527 | 5528 | Parcel data = Parcel.obtain(); |
5528 | 5529 | Parcel reply = Parcel.obtain(); |
5529 | 5530 | data.writeInterfaceToken(IActivityManager.descriptor); |
@@ -428,7 +428,7 @@ public interface IActivityManager extends IInterface { | ||
428 | 428 | public boolean isTopOfTask(IBinder token) throws RemoteException; |
429 | 429 | |
430 | 430 | public void crashApplication(int uid, int initialPid, String packageName, |
431 | - String message) throws RemoteException; | |
431 | + String message, boolean force) throws RemoteException; | |
432 | 432 | |
433 | 433 | public String getProviderMimeType(Uri uri, int userId) throws RemoteException; |
434 | 434 |
@@ -618,6 +618,15 @@ public final class ActiveServices { | ||
618 | 618 | } |
619 | 619 | } |
620 | 620 | |
621 | + void killMisbehavingService(ServiceRecord r, | |
622 | + int appUid, int appPid, String localPackageName) { | |
623 | + synchronized (mAm) { | |
624 | + stopServiceLocked(r); | |
625 | + mAm.crashApplication(appUid, appPid, localPackageName, | |
626 | + "Bad notification for startForeground", true /*force*/); | |
627 | + } | |
628 | + } | |
629 | + | |
621 | 630 | IBinder peekServiceLocked(Intent service, String resolvedType, String callingPackage) { |
622 | 631 | ServiceLookupResult r = retrieveServiceLocked(service, resolvedType, callingPackage, |
623 | 632 | Binder.getCallingPid(), Binder.getCallingUid(), |
@@ -5122,7 +5122,7 @@ public final class ActivityManagerService extends ActivityManagerNative | ||
5122 | 5122 | |
5123 | 5123 | @Override |
5124 | 5124 | public void crashApplication(int uid, int initialPid, String packageName, |
5125 | - String message) { | |
5125 | + String message, boolean force) { | |
5126 | 5126 | if (checkCallingPermission(android.Manifest.permission.FORCE_STOP_PACKAGES) |
5127 | 5127 | != PackageManager.PERMISSION_GRANTED) { |
5128 | 5128 | String msg = "Permission Denial: crashApplication() from pid=" |
@@ -5134,7 +5134,8 @@ public final class ActivityManagerService extends ActivityManagerNative | ||
5134 | 5134 | } |
5135 | 5135 | |
5136 | 5136 | synchronized(this) { |
5137 | - mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, message); | |
5137 | + mAppErrors.scheduleAppCrashLocked(uid, initialPid, packageName, | |
5138 | + message, force); | |
5138 | 5139 | } |
5139 | 5140 | } |
5140 | 5141 |
@@ -242,25 +242,29 @@ class AppErrors { | ||
242 | 242 | } |
243 | 243 | |
244 | 244 | void killAppAtUserRequestLocked(ProcessRecord app, Dialog fromDialog) { |
245 | - app.crashing = false; | |
246 | - app.crashingReport = null; | |
247 | - app.notResponding = false; | |
248 | - app.notRespondingReport = null; | |
249 | 245 | if (app.anrDialog == fromDialog) { |
250 | 246 | app.anrDialog = null; |
251 | 247 | } |
252 | 248 | if (app.waitDialog == fromDialog) { |
253 | 249 | app.waitDialog = null; |
254 | 250 | } |
251 | + killAppImmediateLocked(app, "user-terminated", "user request after error"); | |
252 | + } | |
253 | + | |
254 | + private void killAppImmediateLocked(ProcessRecord app, String reason, String killReason) { | |
255 | + app.crashing = false; | |
256 | + app.crashingReport = null; | |
257 | + app.notResponding = false; | |
258 | + app.notRespondingReport = null; | |
255 | 259 | if (app.pid > 0 && app.pid != MY_PID) { |
256 | - handleAppCrashLocked(app, "user-terminated" /*reason*/, | |
260 | + handleAppCrashLocked(app, reason, | |
257 | 261 | null /*shortMsg*/, null /*longMsg*/, null /*stackTrace*/, null /*data*/); |
258 | - app.kill("user request after error", true); | |
262 | + app.kill(killReason, true); | |
259 | 263 | } |
260 | 264 | } |
261 | 265 | |
262 | 266 | void scheduleAppCrashLocked(int uid, int initialPid, String packageName, |
263 | - String message) { | |
267 | + String message, boolean force) { | |
264 | 268 | ProcessRecord proc = null; |
265 | 269 | |
266 | 270 | // Figure out which process to kill. We don't trust that initialPid |
@@ -291,6 +295,14 @@ class AppErrors { | ||
291 | 295 | } |
292 | 296 | |
293 | 297 | proc.scheduleCrash(message); |
298 | + if (force) { | |
299 | + // If the app is responsive, the scheduled crash will happen as expected | |
300 | + // and then the delayed summary kill will be a no-op. | |
301 | + final ProcessRecord p = proc; | |
302 | + mService.mHandler.postDelayed( | |
303 | + () -> killAppImmediateLocked(p, "forced", "killed for invalid state"), | |
304 | + 5000L); | |
305 | + } | |
294 | 306 | } |
295 | 307 | |
296 | 308 | /** |
@@ -448,6 +448,7 @@ final class ServiceRecord extends Binder { | ||
448 | 448 | final String localPackageName = packageName; |
449 | 449 | final int localForegroundId = foregroundId; |
450 | 450 | final Notification _foregroundNoti = foregroundNoti; |
451 | + final ServiceRecord record = this; | |
451 | 452 | ams.mHandler.post(new Runnable() { |
452 | 453 | public void run() { |
453 | 454 | NotificationManagerInternal nm = LocalServices.getService( |
@@ -532,10 +533,8 @@ final class ServiceRecord extends Binder { | ||
532 | 533 | Slog.w(TAG, "Error showing notification for service", e); |
533 | 534 | // If it gave us a garbage notification, it doesn't |
534 | 535 | // get to be foreground. |
535 | - ams.setServiceForeground(name, ServiceRecord.this, | |
536 | - 0, null, 0); | |
537 | - ams.crashApplication(appUid, appPid, localPackageName, | |
538 | - "Bad notification for startForeground: " + e); | |
536 | + ams.mServices.killMisbehavingService(record, | |
537 | + appUid, appPid, localPackageName); | |
539 | 538 | } |
540 | 539 | } |
541 | 540 | }); |
@@ -639,7 +639,7 @@ public class NotificationManagerService extends SystemService { | ||
639 | 639 | try { |
640 | 640 | ActivityManagerNative.getDefault().crashApplication(uid, initialPid, pkg, |
641 | 641 | "Bad notification posted from package " + pkg |
642 | - + ": " + message); | |
642 | + + ": " + message, true /*force*/); | |
643 | 643 | } catch (RemoteException e) { |
644 | 644 | } finally { |
645 | 645 | Binder.restoreCallingIdentity(ident); |