Loading services/core/java/com/android/server/notification/NotificationManagerService.java +22 −0 Original line number Original line Diff line number Diff line Loading @@ -6309,6 +6309,10 @@ public class NotificationManagerService extends SystemService { Objects.requireNonNull(user); Objects.requireNonNull(user); verifyPrivilegedListener(token, user, false); 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); updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true); } } Loading Loading @@ -6406,6 +6410,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 { private int getUidForPackageAndUser(String pkg, UserHandle user) throws RemoteException { int uid = INVALID_UID; int uid = INVALID_UID; final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +63 −0 Original line number Original line Diff line number Diff line Loading @@ -4001,6 +4001,69 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } } @Test public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); when(mCompanionMgr.getAssociations(PKG, mUserId)) .thenReturn(singletonList(mock(AssociationInfo.class))); 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(), anyInt(), 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); when(mCompanionMgr.getAssociations(PKG, mUserId)) .thenReturn(singletonList(mock(AssociationInfo.class))); 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(), anyInt(), anyBoolean()); verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } @Test @Test public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); mService.setPreferencesHelper(mPreferencesHelper); Loading Loading
services/core/java/com/android/server/notification/NotificationManagerService.java +22 −0 Original line number Original line Diff line number Diff line Loading @@ -6309,6 +6309,10 @@ public class NotificationManagerService extends SystemService { Objects.requireNonNull(user); Objects.requireNonNull(user); verifyPrivilegedListener(token, user, false); 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); updateNotificationChannelInt(pkg, getUidForPackageAndUser(pkg, user), channel, true); } } Loading Loading @@ -6406,6 +6410,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 { private int getUidForPackageAndUser(String pkg, UserHandle user) throws RemoteException { int uid = INVALID_UID; int uid = INVALID_UID; final long identity = Binder.clearCallingIdentity(); final long identity = Binder.clearCallingIdentity(); Loading
services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +63 −0 Original line number Original line Diff line number Diff line Loading @@ -4001,6 +4001,69 @@ public class NotificationManagerServiceTest extends UiServiceTestCase { eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } } @Test public void testUpdateNotificationChannelFromPrivilegedListener_noSoundUriPermission() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); when(mCompanionMgr.getAssociations(PKG, mUserId)) .thenReturn(singletonList(mock(AssociationInfo.class))); 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(), anyInt(), 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); when(mCompanionMgr.getAssociations(PKG, mUserId)) .thenReturn(singletonList(mock(AssociationInfo.class))); 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(), anyInt(), anyBoolean()); verify(mListeners, never()).notifyNotificationChannelChanged(eq(PKG), eq(Process.myUserHandle()), eq(mTestNotificationChannel), eq(NotificationListenerService.NOTIFICATION_CHANNEL_OR_GROUP_UPDATED)); } @Test @Test public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { public void testGetNotificationChannelFromPrivilegedListener_cdm_success() throws Exception { mService.setPreferencesHelper(mPreferencesHelper); mService.setPreferencesHelper(mPreferencesHelper); Loading