2024-08-17 12:35:07 -04:00
|
|
|
From 0000000000000000000000000000000000000000 Mon Sep 17 00:00:00 2001
|
2024-06-19 18:14:14 -04:00
|
|
|
From: Valentin Iftime <valiiftime@google.com>
|
|
|
|
Date: Thu, 1 Feb 2024 13:58:49 +0100
|
|
|
|
Subject: [PATCH] Verify URI permission for channel sound update from
|
|
|
|
NotificationListenerService
|
|
|
|
|
|
|
|
Check that a privileged NotificationListenerService (CDM) has the permission to access the sound URI
|
|
|
|
when updating a notification channel.
|
|
|
|
|
|
|
|
Test: atest com.android.server.notification.NotificationManagerServiceTest#testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission
|
|
|
|
Bug: 317357401
|
|
|
|
(cherry picked from commit 9b7bbbf5ad542ecf9ecbf8cd819b468791b443c0)
|
|
|
|
(cherry picked from https://googleplex-android-review.googlesource.com/q/commit:f090c0538a27d8658d8a860046d5c5e931302341)
|
|
|
|
Merged-In: Ic7d2e96e43565e98d2aa29b8f2ba35c142387ba9
|
|
|
|
Change-Id: Ic7d2e96e43565e98d2aa29b8f2ba35c142387ba9
|
|
|
|
---
|
2024-08-05 16:03:46 -04:00
|
|
|
.../NotificationManagerService.java | 22 ++++++
|
2024-06-19 18:14:14 -04:00
|
|
|
.../NotificationManagerServiceTest.java | 67 +++++++++++++++++++
|
2024-08-05 16:03:46 -04:00
|
|
|
2 files changed, 89 insertions(+)
|
2024-06-19 18:14:14 -04:00
|
|
|
|
|
|
|
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
2024-08-17 12:35:07 -04:00
|
|
|
index 7b1c0ac27ab3..110cfe190ef5 100755
|
2024-06-19 18:14:14 -04:00
|
|
|
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
|
|
|
|
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
|
2024-08-17 12:35:07 -04:00
|
|
|
@@ -4333,6 +4333,10 @@ public class NotificationManagerService extends SystemService {
|
2024-06-19 18:14:14 -04:00
|
|
|
Preconditions.checkNotNull(user);
|
|
|
|
|
|
|
|
verifyPrivilegedListener(token, user, false);
|
2024-08-05 16:03:46 -04:00
|
|
|
+
|
2024-06-19 18:14:14 -04:00
|
|
|
+ final NotificationChannel originalChannel = mPreferencesHelper.getNotificationChannel(
|
|
|
|
+ pkg, getUidForPackageAndUser(pkg, user), channel.getId(), true);
|
|
|
|
+ verifyPrivilegedListenerUriPermission(Binder.getCallingUid(), channel, originalChannel);
|
|
|
|
updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
|
|
|
|
}
|
|
|
|
|
2024-08-17 12:35:07 -04:00
|
|
|
@@ -4412,6 +4416,24 @@ public class NotificationManagerService extends SystemService {
|
2024-06-19 18:14:14 -04:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
+ private void verifyPrivilegedListenerUriPermission(int sourceUid,
|
|
|
|
+ @NonNull NotificationChannel updateChannel,
|
|
|
|
+ @Nullable NotificationChannel originalChannel) {
|
|
|
|
+ // Check that the NLS has the required permissions to access the channel
|
|
|
|
+ final Uri soundUri = updateChannel.getSound();
|
|
|
|
+ final Uri originalSoundUri =
|
|
|
|
+ (originalChannel != null) ? originalChannel.getSound() : null;
|
|
|
|
+ if (soundUri != null && !Objects.equals(originalSoundUri, soundUri)) {
|
|
|
|
+ Binder.withCleanCallingIdentity(() -> {
|
|
|
|
+ mUgmInternal.checkGrantUriPermission(sourceUid, null,
|
|
|
|
+ ContentProvider.getUriWithoutUserId(soundUri),
|
|
|
|
+ Intent.FLAG_GRANT_READ_URI_PERMISSION,
|
|
|
|
+ ContentProvider.getUserIdFromUri(soundUri,
|
|
|
|
+ UserHandle.getUserId(sourceUid)));
|
|
|
|
+ });
|
|
|
|
+ }
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
private int getUidForPackageAndUser(String pkg, UserHandle user) throws RemoteException {
|
|
|
|
int uid = 0;
|
|
|
|
long identity = Binder.clearCallingIdentity();
|
|
|
|
diff --git a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
2024-08-17 12:35:07 -04:00
|
|
|
index 0e8cea43063b..403772d0f875 100755
|
2024-06-19 18:14:14 -04:00
|
|
|
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
|
|
|
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
|
2024-08-17 12:35:07 -04:00
|
|
|
@@ -2037,6 +2037,73 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
|
2024-06-19 18:14:14 -04:00
|
|
|
eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
|
|
|
|
}
|
|
|
|
|
|
|
|
+ @Test
|
|
|
|
+ public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission()
|
|
|
|
+ throws Exception {
|
|
|
|
+ mService.setPreferencesHelper(mPreferencesHelper);
|
|
|
|
+ List<String> associations = new ArrayList<>();
|
|
|
|
+ associations.add("a");
|
|
|
|
+ when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
|
|
|
|
+ .thenReturn(associations);
|
|
|
|
+ when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
|
|
|
|
+ eq(mTestNotificationChannel.getId()), anyBoolean()))
|
|
|
|
+ .thenReturn(mTestNotificationChannel);
|
|
|
|
+
|
|
|
|
+ final Uri soundUri = Uri.parse("content://media/test/sound/uri");
|
|
|
|
+ final NotificationChannel updatedNotificationChannel = new NotificationChannel(
|
|
|
|
+ TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
|
|
|
|
+ updatedNotificationChannel.setSound(soundUri,
|
|
|
|
+ updatedNotificationChannel.getAudioAttributes());
|
|
|
|
+
|
|
|
|
+ doThrow(new SecurityException("no access")).when(mUgmInternal)
|
|
|
|
+ .checkGrantUriPermission(eq(Process.myUid()), any(), eq(soundUri),
|
|
|
|
+ anyInt(), eq(Process.myUserHandle().getIdentifier()));
|
|
|
|
+
|
|
|
|
+ assertThrows(SecurityException.class,
|
|
|
|
+ () -> mBinderService.updateNotificationChannelFromPrivilegedListener(null, PKG,
|
|
|
|
+ Process.myUserHandle(), updatedNotificationChannel));
|
|
|
|
+
|
|
|
|
+ verify(mPreferencesHelper, never()).updateNotificationChannel(
|
|
|
|
+ anyString(), anyInt(), any(), anyBoolean());
|
|
|
|
+
|
|
|
|
+ verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
|
|
|
|
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
|
|
|
|
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
+ @Test
|
|
|
|
+ public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission_sameSound()
|
|
|
|
+ throws Exception {
|
|
|
|
+ mService.setPreferencesHelper(mPreferencesHelper);
|
|
|
|
+ List<String> associations = new ArrayList<>();
|
|
|
|
+ associations.add("a");
|
|
|
|
+ when(mCompanionMgr.getAssociations(PKG, UserHandle.getUserId(mUid)))
|
|
|
|
+ .thenReturn(associations);
|
|
|
|
+ when(mPreferencesHelper.getNotificationChannel(eq(PKG), anyInt(),
|
|
|
|
+ eq(mTestNotificationChannel.getId()), anyBoolean()))
|
|
|
|
+ .thenReturn(mTestNotificationChannel);
|
|
|
|
+
|
|
|
|
+ final Uri soundUri = Settings.System.DEFAULT_NOTIFICATION_URI;
|
|
|
|
+ final NotificationChannel updatedNotificationChannel = new NotificationChannel(
|
|
|
|
+ TEST_CHANNEL_ID, TEST_CHANNEL_ID, IMPORTANCE_DEFAULT);
|
|
|
|
+ updatedNotificationChannel.setSound(soundUri,
|
|
|
|
+ updatedNotificationChannel.getAudioAttributes());
|
|
|
|
+
|
|
|
|
+ doThrow(new SecurityException("no access")).when(mUgmInternal)
|
|
|
|
+ .checkGrantUriPermission(eq(Process.myUid()), any(), eq(soundUri),
|
|
|
|
+ anyInt(), eq(Process.myUserHandle().getIdentifier()));
|
|
|
|
+
|
|
|
|
+ mBinderService.updateNotificationChannelFromPrivilegedListener(
|
|
|
|
+ null, PKG, Process.myUserHandle(), updatedNotificationChannel);
|
|
|
|
+
|
|
|
|
+ verify(mPreferencesHelper, times(1)).updateNotificationChannel(
|
|
|
|
+ anyString(), anyInt(), any(), anyBoolean());
|
|
|
|
+
|
|
|
|
+ verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG),
|
|
|
|
+ eq(Process.myUserHandle()), eq(mTestNotificationChannel),
|
|
|
|
+ eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED));
|
|
|
|
+ }
|
|
|
|
+
|
|
|
|
@Test
|
|
|
|
public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception {
|
|
|
|
mService.setPreferencesHelper(mPreferencesHelper);
|