From a80971a28168f2667a2821d008964ba001cad059 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Mat=C3=ADas=20Hern=C3=A1ndez?= Date: Thu, 15 Jun 2023 18:31:34 +0200 Subject: [PATCH] Forbid granting access to NLSes with too-long component names This makes the limitation, which was previously only checked on the Settings UI, enforced everywhere. Fixes: 260570119 Fixes: 286043036 Test: atest + manually (cherry picked from https://googleplex-android-review.googlesource.com/q/commit:6fcdbd0c6efc67b014b8e1b43c5ec233f912ee8b) Merged-In: I4c25d80978cb37a8fa1531f5045259d25ac64692 Change-Id: I4c25d80978cb37a8fa1531f5045259d25ac64692 --- .../java/android/app/NotificationManager.java | 6 +++++ .../RestrictedSwitchPreference.java | 8 ++++-- .../NotificationManagerService.java | 5 ++++ .../android/server/vr/VrManagerService.java | 6 ++++- .../NotificationManagerServiceTest.java | 25 +++++++++++++++++++ 5 files changed, 47 insertions(+), 3 deletions(-) diff --git a/core/java/android/app/NotificationManager.java b/core/java/android/app/NotificationManager.java index 3506c41310a3..2807b0b4b682 100644 --- a/core/java/android/app/NotificationManager.java +++ b/core/java/android/app/NotificationManager.java @@ -575,6 +575,12 @@ public class NotificationManager { */ public static final int BUBBLE_PREFERENCE_SELECTED = 2; + /** + * Maximum length of the component name of a registered NotificationListenerService. + * @hide + */ + public static int MAX_SERVICE_COMPONENT_NAME_LENGTH = 500; + @UnsupportedAppUsage private static INotificationManager sService; diff --git a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java index b5e4fa38d244..af06d7304160 100644 --- a/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java +++ b/packages/SettingsLib/src/com/android/settingslib/RestrictedSwitchPreference.java @@ -243,7 +243,9 @@ public String getPackageName() { return mHelper != null ? mHelper.packageName : null; } - public void updateState(@NonNull String packageName, int uid, boolean isEnabled) { + /** Updates enabled state based on associated package. */ + public void updateState( + @NonNull String packageName, int uid, boolean isEnableAllowed, boolean isEnabled) { mHelper.updatePackageDetails(packageName, uid); if (mAppOpsManager == null) { mAppOpsManager = getContext().getSystemService(AppOpsManager.class); @@ -254,7 +256,9 @@ public void updateState(@NonNull String packageName, int uid, boolean isEnabled) final boolean ecmEnabled = getContext().getResources().getBoolean( com.android.internal.R.bool.config_enhancedConfirmationModeEnabled); final boolean appOpsAllowed = !ecmEnabled || mode == AppOpsManager.MODE_ALLOWED; - if (isEnabled) { + if (!isEnableAllowed && !isEnabled) { + setEnabled(false); + } else if (isEnabled) { setEnabled(true); } else if (appOpsAllowed && isDisabledByAppOps()) { setEnabled(true); diff --git a/services/core/java/com/android/server/notification/NotificationManagerService.java b/services/core/java/com/android/server/notification/NotificationManagerService.java index 51db4b820aad..286782c60c66 100755 --- a/services/core/java/com/android/server/notification/NotificationManagerService.java +++ b/services/core/java/com/android/server/notification/NotificationManagerService.java @@ -5529,6 +5529,11 @@ public void setNotificationListenerAccessGrantedForUser(ComponentName listener, boolean granted, boolean userSet) { Objects.requireNonNull(listener); checkNotificationListenerAccess(); + if (granted && listener.flattenToString().length() + > NotificationManager.MAX_SERVICE_COMPONENT_NAME_LENGTH) { + throw new IllegalArgumentException( + "Component name too long: " + listener.flattenToString()); + } if (!userSet && isNotificationListenerAccessUserSet(listener)) { // Don't override user's choice return; diff --git a/services/core/java/com/android/server/vr/VrManagerService.java b/services/core/java/com/android/server/vr/VrManagerService.java index b296ef2a1443..1ff01a6c70bf 100644 --- a/services/core/java/com/android/server/vr/VrManagerService.java +++ b/services/core/java/com/android/server/vr/VrManagerService.java @@ -1049,7 +1049,11 @@ private void grantNotificationListenerAccess(String pkg, int userId) { for (ComponentName c : possibleServices) { if (Objects.equals(c.getPackageName(), pkg)) { - nm.setNotificationListenerAccessGrantedForUser(c, userId, true); + try { + nm.setNotificationListenerAccessGrantedForUser(c, userId, true); + } catch (Exception e) { + Slog.w(TAG, "Could not grant NLS access to package " + pkg, e); + } } } } 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 718d9c50c6b2..24fff1279a4e 100755 --- a/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java +++ b/services/tests/uiservicestests/src/com/android/server/notification/NotificationManagerServiceTest.java @@ -84,6 +84,7 @@ import static junit.framework.Assert.assertTrue; import static junit.framework.Assert.fail; +import static org.junit.Assert.assertThrows; import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Matchers.anyBoolean; import static org.mockito.Matchers.anyLong; @@ -3846,6 +3847,30 @@ public void testSetListenerAccessForUser() throws Exception { any(), anyInt(), anyBoolean(), anyBoolean(), anyBoolean()); } + @Test + public void testSetListenerAccessForUser_grantWithNameTooLong_throws() { + UserHandle user = UserHandle.of(mContext.getUserId() + 10); + ComponentName c = new ComponentName("com.example.package", + com.google.common.base.Strings.repeat("Blah", 150)); + + assertThrows(IllegalArgumentException.class, + () -> mBinderService.setNotificationListenerAccessGrantedForUser( + c, user.getIdentifier(), /* enabled= */ true, true)); + } + + @Test + public void testSetListenerAccessForUser_revokeWithNameTooLong_okay() throws Exception { + UserHandle user = UserHandle.of(mContext.getUserId() + 10); + ComponentName c = new ComponentName("com.example.package", + com.google.common.base.Strings.repeat("Blah", 150)); + + mBinderService.setNotificationListenerAccessGrantedForUser( + c, user.getIdentifier(), /* enabled= */ false, true); + + verify(mListeners).setPackageOrComponentEnabled( + c.flattenToString(), user.getIdentifier(), true, /* enabled= */ false, true); + } + @Test public void testSetAssistantAccessForUser() throws Exception { UserInfo ui = new UserInfo();