Skip to content

Commit

Permalink
Integrate MAY-2022 ASB patches
Browse files Browse the repository at this point in the history
Tracked-On: OAM-101830
Signed-off-by: Senapati, Rasmiranjan <[email protected]>
  • Loading branch information
rrsenapati1 authored and sysopenci committed May 2, 2022
1 parent abd3d8e commit ae0eaeb
Show file tree
Hide file tree
Showing 10 changed files with 802 additions and 1 deletion.
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ index 13b85c0663..084f400e67 100644
# It must match one of the Android Security Patch Level strings of the Public Security Bulletins.
# If there is no $PLATFORM_SECURITY_PATCH set, keep it empty.
- PLATFORM_SECURITY_PATCH := 2021-10-01
+ PLATFORM_SECURITY_PATCH := 2022-04-01
+ PLATFORM_SECURITY_PATCH := 2022-05-01
endif
.KATI_READONLY := PLATFORM_SECURITY_PATCH

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,285 @@
From 8613ca36464c885ec9db1a1c5391fbcbdeb2ae06 Mon Sep 17 00:00:00 2001
From: Julia Reynolds <[email protected]>
Date: Fri, 11 Feb 2022 17:08:58 -0500
Subject: [PATCH] Filter notification APIs by user

Specifically getActiveNotifications and
getHistoricalNotifications

Test: atest NotificationManagerServiceTest
Bug: 214999128
Change-Id: I2eba0a592fa33ed25e1ac3919f1b2631e5db4258
Merged-In: I2eba0a592fa33ed25e1ac3919f1b2631e5db4258
(cherry picked from commit 3456555b7cfa84752b4dfa75191b7e87dc95b156)
Merged-In: I2eba0a592fa33ed25e1ac3919f1b2631e5db4258
---
.../NotificationManagerService.java | 37 ++++++++++++-----
.../server/notification/ArchiveTest.java | 40 ++++++++++++++++---
.../NotificationManagerServiceTest.java | 35 +++++++++++++++-
3 files changed, 96 insertions(+), 16 deletions(-)
mode change 100644 => 100755 services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java

diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index 0833d263d07..6e87babb69b 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -583,7 +583,14 @@ public class NotificationManagerService extends SystemService {
return mBuffer.descendingIterator();
}

- public StatusBarNotification[] getArray(int count, boolean includeSnoozed) {
+ public StatusBarNotification[] getArray(UserManager um, int count, boolean includeSnoozed) {
+ ArrayList<Integer> currentUsers = new ArrayList<>();
+ currentUsers.add(UserHandle.USER_ALL);
+ Binder.withCleanCallingIdentity(() -> {
+ for (int user : um.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+ currentUsers.add(user);
+ }
+ });
if (count == 0) count = mBufferSize;
List<StatusBarNotification> a = new ArrayList();
Iterator<Pair<StatusBarNotification, Integer>> iter = descendingIterator();
@@ -591,8 +598,10 @@ public class NotificationManagerService extends SystemService {
while (iter.hasNext() && i < count) {
Pair<StatusBarNotification, Integer> pair = iter.next();
if (pair.second != REASON_SNOOZED || includeSnoozed) {
- i++;
- a.add(pair.first);
+ if (currentUsers.contains(pair.first.getUserId())) {
+ i++;
+ a.add(pair.first);
+ }
}
}
return a.toArray(new StatusBarNotification[a.size()]);
@@ -3781,22 +3790,32 @@ public class NotificationManagerService extends SystemService {
android.Manifest.permission.ACCESS_NOTIFICATIONS,
"NotificationManagerService.getActiveNotifications");

- StatusBarNotification[] tmp = null;
+ ArrayList<StatusBarNotification> tmp = new ArrayList<>();
int uid = Binder.getCallingUid();

+ ArrayList<Integer> currentUsers = new ArrayList<>();
+ currentUsers.add(UserHandle.USER_ALL);
+ Binder.withCleanCallingIdentity(() -> {
+ for (int user : mUm.getProfileIds(ActivityManager.getCurrentUser(), false)) {
+ currentUsers.add(user);
+ }
+ });
+
// noteOp will check to make sure the callingPkg matches the uid
if (mAppOps.noteOpNoThrow(AppOpsManager.OP_ACCESS_NOTIFICATIONS, uid, callingPkg,
callingAttributionTag, null)
== AppOpsManager.MODE_ALLOWED) {
synchronized (mNotificationLock) {
- tmp = new StatusBarNotification[mNotificationList.size()];
final int N = mNotificationList.size();
- for (int i=0; i<N; i++) {
- tmp[i] = mNotificationList.get(i).getSbn();
+ for (int i = 0; i < N; i++) {
+ final StatusBarNotification sbn = mNotificationList.get(i).getSbn();
+ if (currentUsers.contains(sbn.getUserId())) {
+ tmp.add(sbn);
+ }
}
}
}
- return tmp;
+ return tmp.toArray(new StatusBarNotification[tmp.size()]);
}

/**
@@ -3905,7 +3924,7 @@ public class NotificationManagerService extends SystemService {
callingAttributionTag, null)
== AppOpsManager.MODE_ALLOWED) {
synchronized (mArchive) {
- tmp = mArchive.getArray(count, includeSnoozed);
+ tmp = mArchive.getArray(mUm, count, includeSnoozed);
}
}
return tmp;
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
index c69ef8d9328..c4e0fa0cc1e 100644
--- a/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/ArchiveTest.java
@@ -15,14 +15,22 @@
*/
package com.android.server.notification;

+import static android.os.UserHandle.USER_ALL;
import static android.os.UserHandle.USER_CURRENT;
+import static android.os.UserHandle.USER_NULL;
import static android.os.UserHandle.USER_SYSTEM;
import static android.service.notification.NotificationListenerService.REASON_CANCEL;

import static com.google.common.truth.Truth.assertThat;

+import static org.junit.Assert.fail;
+import static org.mockito.ArgumentMatchers.anyBoolean;
+import static org.mockito.ArgumentMatchers.anyInt;
+import static org.mockito.Mockito.when;
+
import android.app.Notification;
import android.os.UserHandle;
+import android.os.UserManager;
import android.service.notification.StatusBarNotification;
import android.test.suitebuilder.annotation.SmallTest;

@@ -33,6 +41,7 @@ import com.android.server.UiServiceTestCase;
import org.junit.Before;
import org.junit.Test;
import org.junit.runner.RunWith;
+import org.mockito.Mock;
import org.mockito.MockitoAnnotations;

import java.util.ArrayList;
@@ -45,6 +54,8 @@ public class ArchiveTest extends UiServiceTestCase {
private static final int SIZE = 5;

private NotificationManagerService.Archive mArchive;
+ @Mock
+ private UserManager mUm;

@Before
public void setUp() {
@@ -53,6 +64,9 @@ public class ArchiveTest extends UiServiceTestCase {
mArchive = new NotificationManagerService.Archive(SIZE);
mArchive.updateHistoryEnabled(USER_SYSTEM, true);
mArchive.updateHistoryEnabled(USER_CURRENT, true);
+
+ when(mUm.getProfileIds(anyInt(), anyBoolean())).thenReturn(
+ new int[] {USER_CURRENT, USER_SYSTEM});
}

private StatusBarNotification getNotification(String pkg, int id, UserHandle user) {
@@ -64,7 +78,6 @@ public class ArchiveTest extends UiServiceTestCase {
pkg, pkg, id, null, 0, 0, n, user, null, System.currentTimeMillis());
}

-
@Test
public void testRecordAndRead() {
List<String> expected = new ArrayList<>();
@@ -75,13 +88,29 @@ public class ArchiveTest extends UiServiceTestCase {
mArchive.record(sbn, REASON_CANCEL);
}

- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
}
}

+ @Test
+ public void testCrossUser() {
+ mArchive.record(getNotification("pkg", 1, UserHandle.of(USER_SYSTEM)), REASON_CANCEL);
+ mArchive.record(getNotification("pkg", 2, UserHandle.of(USER_CURRENT)), REASON_CANCEL);
+ mArchive.record(getNotification("pkg", 3, UserHandle.of(USER_ALL)), REASON_CANCEL);
+ mArchive.record(getNotification("pkg", 4, UserHandle.of(USER_NULL)), REASON_CANCEL);
+
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
+ assertThat(actual).hasSize(3);
+ for (StatusBarNotification sbn : actual) {
+ if (sbn.getUserId() == USER_NULL) {
+ fail("leaked notification from wrong user");
+ }
+ }
+ }
+
@Test
public void testRecordAndRead_overLimit() {
List<String> expected = new ArrayList<>();
@@ -93,7 +122,8 @@ public class ArchiveTest extends UiServiceTestCase {
}
}

- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray((SIZE * 2), true));
+ List<StatusBarNotification> actual = Arrays.asList(
+ mArchive.getArray(mUm, (SIZE * 2), true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
@@ -113,7 +143,7 @@ public class ArchiveTest extends UiServiceTestCase {
}
}

- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
@@ -134,7 +164,7 @@ public class ArchiveTest extends UiServiceTestCase {
}
mArchive.updateHistoryEnabled(USER_CURRENT, false);

- List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(SIZE, true));
+ List<StatusBarNotification> actual = Arrays.asList(mArchive.getArray(mUm, SIZE, true));
assertThat(actual).hasSize(expected.size());
for (StatusBarNotification sbn : actual) {
assertThat(expected).contains(sbn.getKey());
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
old mode 100644
new mode 100755
index 9394eb84007..62a423e3277
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -463,6 +463,7 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
when(mPackageManager.getPackagesForUid(mUid)).thenReturn(new String[]{PKG});
when(mPackageManagerClient.getPackagesForUid(anyInt())).thenReturn(new String[]{PKG});
mContext.addMockSystemService(AppOpsManager.class, mock(AppOpsManager.class));
+ when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0});

// write to a test file; the system file isn't readable from tests
mFile = new File(mContext.getCacheDir(), "test.xml");
@@ -6156,8 +6157,9 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
waitForIdle();

// A notification exists for the given record
- StatusBarNotification[] notifsBefore = mBinderService.getActiveNotifications(PKG);
- assertEquals(1, notifsBefore.length);
+ List<StatusBarNotification> notifsBefore =
+ mBinderService.getAppActiveNotifications(PKG, nr.getSbn().getUserId()).getList();
+ assertEquals(1, notifsBefore.size());

reset(mPackageManager);

@@ -7075,4 +7077,33 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
assertEquals(NotificationManagerService.MAX_PACKAGE_NOTIFICATIONS + 1,
mService.getNotificationRecordCount());
}
+
+ @Test
+ public void testGetActiveNotification_filtersUsers() throws Exception {
+ when(mUm.getProfileIds(0, false)).thenReturn(new int[]{0, 10});
+
+ NotificationRecord nr0 =
+ generateNotificationRecord(mTestNotificationChannel, 0);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag0",
+ nr0.getSbn().getId(), nr0.getSbn().getNotification(), nr0.getSbn().getUserId());
+
+ NotificationRecord nr10 =
+ generateNotificationRecord(mTestNotificationChannel, 10);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag10",
+ nr10.getSbn().getId(), nr10.getSbn().getNotification(), nr10.getSbn().getUserId());
+
+ NotificationRecord nr11 =
+ generateNotificationRecord(mTestNotificationChannel, 11);
+ mBinderService.enqueueNotificationWithTag(PKG, PKG, "tag11",
+ nr11.getSbn().getId(), nr11.getSbn().getNotification(), nr11.getSbn().getUserId());
+ waitForIdle();
+
+ StatusBarNotification[] notifs = mBinderService.getActiveNotifications(PKG);
+ assertEquals(2, notifs.length);
+ for (StatusBarNotification sbn : notifs) {
+ if (sbn.getUserId() == 11) {
+ fail("leaked data across users");
+ }
+ }
+ }
}
--
2.35.1.894.gb6a874cedc-goog

Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
From 580d482e426312e5e1069aa6350d56c45df02379 Mon Sep 17 00:00:00 2001
From: Jeff Chang <[email protected]>
Date: Tue, 8 Feb 2022 14:06:14 +0800
Subject: [PATCH] Do not resume activity if behind a translucent task

The top-focusable activity resides in the RESUMED state while the app
process is newly created and attached. The behavior may enable UI
hijacking attacks against apps implementing authentication.

This CL disallows the system to resume the activity for the case if it
is not visible or is occluded by other translucent tasks.

Bug: 211481342
Test: atest CtsWindowManagerDeviceTestCases:ActivityLifecycleTests
Change-Id: I7903494cf928b5b5613700262b7c5fff10f3c5a0
(cherry picked from commit 43b8bcc01474bce480642acae2c554393c3bfb6a)
Merged-In: I7903494cf928b5b5613700262b7c5fff10f3c5a0
---
.../server/wm/EnsureActivitiesVisibleHelper.java | 2 +-
.../com/android/server/wm/RootWindowContainer.java | 5 +++--
services/core/java/com/android/server/wm/Task.java | 11 +++++++++++
3 files changed, 15 insertions(+), 3 deletions(-)

diff --git a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
index aa76a07bc9c7..7b7fcc4e8f8b 100644
--- a/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
+++ b/services/core/java/com/android/server/wm/EnsureActivitiesVisibleHelper.java
@@ -93,7 +93,7 @@ class EnsureActivitiesVisibleHelper {
// activities are actually behind other fullscreen activities, but still required
// to be visible (such as performing Recents animation).
final boolean resumeTopActivity = mTop != null && !mTop.mLaunchTaskBehind
- && mContiner.isTopActivityFocusable()
+ && mContiner.canBeResumed(starting)
&& (starting == null || !starting.isDescendantOf(mContiner));

final PooledConsumer f = PooledLambda.obtainConsumer(
diff --git a/services/core/java/com/android/server/wm/RootWindowContainer.java b/services/core/java/com/android/server/wm/RootWindowContainer.java
index 1c1360f6f389..de60546db038 100644
--- a/services/core/java/com/android/server/wm/RootWindowContainer.java
+++ b/services/core/java/com/android/server/wm/RootWindowContainer.java
@@ -1971,8 +1971,9 @@ class RootWindowContainer extends WindowContainer<DisplayContent>

try {
if (mStackSupervisor.realStartActivityLocked(r, app,
- top == r && r.isFocusable() /*andResume*/, true /*checkConfig*/)) {
- mTmpBoolean = true;
+ top == r && r.getTask().canBeResumed(r) /*andResume*/,
+ true /*checkConfig*/)) {
+ mTmpBoolean = true;
}
} catch (RemoteException e) {
Slog.w(TAG, "Exception in new application when starting activity "
diff --git a/services/core/java/com/android/server/wm/Task.java b/services/core/java/com/android/server/wm/Task.java
index b19b8c1ce10b..2da9c8db9ff8 100644
--- a/services/core/java/com/android/server/wm/Task.java
+++ b/services/core/java/com/android/server/wm/Task.java
@@ -3660,6 +3660,17 @@ class Task extends WindowContainer<WindowContainer> {
return getVisibility(starting) != STACK_VISIBILITY_INVISIBLE;
}

+ /**
+ * Returns {@code true} is the activity in this Task can be resumed.
+ *
+ * @param starting The currently starting activity or {@code null} if there is none.
+ */
+ boolean canBeResumed(@Nullable ActivityRecord starting) {
+ // No need to resume activity in Task that is not visible.
+ return isTopActivityFocusable()
+ && getVisibility(starting) == STACK_VISIBILITY_VISIBLE;
+ }
+
/**
* Returns true if the task should be visible.
*
--
2.33.1

Loading

0 comments on commit ae0eaeb

Please sign in to comment.