OSDN Git Service

Make sure Notification#deleteIntent cannot be used to start
authorMichal Karpinski <mkarpinski@google.com>
Wed, 17 Apr 2019 15:01:10 +0000 (16:01 +0100)
committerMichal Karpinski <mkarpinski@google.com>
Wed, 17 Apr 2019 15:08:00 +0000 (16:08 +0100)
activities from background

Remove whitelisting privilege from deleteIntent before it's
sent in cancelNotificationLocked().

Bug: 130619912
Test: manual (with a custom built app that provides
      PendingIntent.getActivity() to
      Notification.Builder.setDeleteIntent())
Change-Id: I8a85b4c32717f958c4ee2fe040b73bceb96d7feb

core/java/android/app/ActivityManagerInternal.java
services/core/java/com/android/server/am/ActivityManagerService.java
services/core/java/com/android/server/am/PendingIntentRecord.java
services/core/java/com/android/server/notification/NotificationManagerService.java

index e8d3293..500a04f 100644 (file)
@@ -80,6 +80,13 @@ public abstract class ActivityManagerInternal {
             IIntentSender target, IBinder whitelistToken, int flags);
 
     /**
+     * Voids {@link PendingIntent}'s privilege to be whitelisted to start activities from
+     * background.
+     */
+    public abstract void clearPendingIntentAllowBgActivityStarts(IIntentSender target,
+            IBinder whitelistToken);
+
+    /**
      * Allow DeviceIdleController to tell us about what apps are whitelisted.
      */
     public abstract void setDeviceIdleWhitelist(int[] allAppids, int[] exceptIdleAppids);
index 3b6b404..d759a49 100644 (file)
@@ -17578,6 +17578,19 @@ public class ActivityManagerService extends IActivityManager.Stub
         }
 
         @Override
+        public void clearPendingIntentAllowBgActivityStarts(IIntentSender target,
+                IBinder whitelistToken) {
+            if (!(target instanceof PendingIntentRecord)) {
+                Slog.w(TAG, "clearPendingIntentAllowBgActivityStarts():"
+                        + " not a PendingIntentRecord: " + target);
+                return;
+            }
+            synchronized (ActivityManagerService.this) {
+                ((PendingIntentRecord) target).clearAllowBgActivityStarts(whitelistToken);
+            }
+        }
+
+        @Override
         public void setDeviceIdleWhitelist(int[] allAppids, int[] exceptIdleAppids) {
             synchronized (ActivityManagerService.this) {
                 mDeviceIdleWhitelist = allAppids;
index 588e05d..acddb47 100644 (file)
@@ -236,6 +236,13 @@ public final class PendingIntentRecord extends IIntentSender.Stub {
         }
     }
 
+    void clearAllowBgActivityStarts(IBinder token) {
+        if (token == null) return;
+        mAllowBgActivityStartsForActivitySender.remove(token);
+        mAllowBgActivityStartsForBroadcastSender.remove(token);
+        mAllowBgActivityStartsForServiceSender.remove(token);
+    }
+
     public void registerCancelListenerLocked(IResultReceiver receiver) {
         if (mCancelCallbacks == null) {
             mCancelCallbacks = new RemoteCallbackList<>();
index 042ac8c..24f513e 100644 (file)
@@ -6335,9 +6335,14 @@ public class NotificationManagerService extends SystemService {
 
         // tell the app
         if (sendDelete) {
-            if (r.getNotification().deleteIntent != null) {
+            final PendingIntent deleteIntent = r.getNotification().deleteIntent;
+            if (deleteIntent != null) {
                 try {
-                    r.getNotification().deleteIntent.send();
+                    // make sure deleteIntent cannot be used to start activities from background
+                    LocalServices.getService(ActivityManagerInternal.class)
+                            .clearPendingIntentAllowBgActivityStarts(deleteIntent.getTarget(),
+                            WHITELIST_TOKEN);
+                    deleteIntent.send();
                 } catch (PendingIntent.CanceledException ex) {
                     // do nothing - there's no relevant way to recover, and
                     //     no reason to let this propagate