summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorValentin Iftime <valiiftime@google.com>2024-02-01 13:58:49 +0100
committerAndroid Build Coastguard Worker <android-build-coastguard-worker@google.com>2024-03-08 09:50:01 +0000
commit9ddd798c80948f18a112ef1241428e5d664fd8d3 (patch)
treeee9a4eeca7d9e9bd74863708078dad2dcb5a9487
parentbdbe384aee3dad5f233ac9b9328a1f4537a8a324 (diff)
downloadbase-9ddd798c80948f18a112ef1241428e5d664fd8d3.tar.gz
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
-rwxr-xr-xservices/core/java/com/android/server/notification/NotificationManagerService.java22
-rwxr-xr-xservices/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java67
2 files changed, 89 insertions, 0 deletions
diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java
index c4f8bac4e3cd..bcef4d2b6a44 100755
--- a/services/core/java/com/android/server/notification/NotificationManagerService.java
+++ b/services/core/java/com/android/server/notification/NotificationManagerService.java
@@ -5434,6 +5434,10 @@ public class NotificationManagerService extends SystemService {
Objects.requireNonNull(user);
verifyPrivilegedListener(token, user, false);
+
+ final NotificationChannel originalChannel = mPreferencesHelper.getNotificationChannel(
+ pkg, getUidForPackageAndUser(pkg, user), channel.getId(), true);
+ verifyPrivilegedListenerUriPermission(Binder.getCallingUid(), channel, originalChannel);
updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true);
}
@@ -5513,6 +5517,24 @@ public class NotificationManagerService extends SystemService {
}
}
+ 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 = INVALID_UID;
final 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
index 4bbdb5839aba..4b79f1674f2c 100755
--- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
+++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java
@@ -2635,6 +2635,73 @@ public class NotificationManagerServiceTest extends UiServiceTestCase {
}
@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);
List<String> associations = new ArrayList<>();