diff options
Diffstat (limited to 'hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java')
-rw-r--r-- | hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java | 148 |
1 files changed, 148 insertions, 0 deletions
diff --git a/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java new file mode 100644 index 00000000000..c0c1ce514df --- /dev/null +++ b/hostsidetests/securitybulletin/test-apps/CVE-2023-40120/src/android/security/cts/CVE_2023_40120/DeviceTest.java @@ -0,0 +1,148 @@ +/* + * Copyright (C) 2023 The Android Open Source Project + * + * Licensed under the Apache License, Version 2.0 (the "License"); + * you may not use this file except in compliance with the License. + * You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + */ + +package android.security.cts.CVE_2023_40120; + +import static android.provider.Settings.Global.SHOW_MEDIA_ON_QUICK_SETTINGS; + +import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation; + +import static com.android.sts.common.SystemUtil.poll; + +import static com.google.common.truth.Truth.assertWithMessage; +import static com.google.common.truth.TruthJUnit.assume; + +import android.app.Instrumentation; +import android.app.Notification; +import android.app.NotificationChannel; +import android.app.NotificationManager; +import android.content.Context; +import android.graphics.drawable.Icon; +import android.media.MediaMetadata; +import android.media.session.MediaSession; +import android.service.notification.StatusBarNotification; + +import androidx.test.runner.AndroidJUnit4; +import androidx.test.uiautomator.By; +import androidx.test.uiautomator.UiDevice; +import androidx.test.uiautomator.UiObject2; +import androidx.test.uiautomator.Until; + +import org.junit.Test; +import org.junit.runner.RunWith; + +@RunWith(AndroidJUnit4.class) +public class DeviceTest { + + @Test + public void testPocCVE_2023_40120() { + try { + Instrumentation instrumentation = getInstrumentation(); + Context context = instrumentation.getContext(); + + // Create a MediaSession + MediaSession session = + new MediaSession(context, "cve_2023_40120_session" /* session name */); + + // Create a MediaMetadata object, pass an empty 'METADATA_KEY_TITLE' and set metadata + // for session + String artistName = "testArtist"; + session.setMetadata( + new MediaMetadata.Builder() + .putString(MediaMetadata.METADATA_KEY_TITLE, "") + .putString(MediaMetadata.METADATA_KEY_ARTIST, artistName) + .build()); + + // Create notificationManager + NotificationManager notificationManager = + context.getSystemService(NotificationManager.class); + + // Create notificationChannel + String channelId = "cve_2023_40120_channel_id"; + notificationManager.createNotificationChannel( + new NotificationChannel( + channelId, + "cve_2023_40120_channel_name" /* notification channel name */, + NotificationManager.IMPORTANCE_DEFAULT)); + + // Post the Notification and check if any security exception is caught + notificationManager.notify( + 0 /* notification id */, + new Notification.Builder(context) + .setChannelId(channelId) + .setStyle( + new Notification.DecoratedMediaCustomViewStyle() + .setMediaSession(session.getSessionToken())) + .setSmallIcon( + Icon.createWithData( + new byte[0] /* data */, 0 /* offset */, 0 /* length */)) + .build()); + + // Check if notification gets posted or not + assume().withMessage("Notification was not posted") + .that( + poll( + () -> { + StatusBarNotification[] activeNotifications = + notificationManager.getActiveNotifications(); + for (StatusBarNotification notification : + activeNotifications) { + if (notification + .getPackageName() + .equals(context.getPackageName())) { + return true; + } + } + return false; + })) + .isTrue(); + + // Launch notification shade + UiDevice uiDevice = UiDevice.getInstance(instrumentation); + assume().withMessage("Unable to launch notification shade") + .that(uiDevice.openNotification()) + .isTrue(); + + // Wait for 'qs_media_controls' resource id to appear + String systemuiPackage = "com.android.systemui"; + UiObject2 resIdObj = + uiDevice.wait( + Until.findObject(By.res(systemuiPackage, SHOW_MEDIA_ON_QUICK_SETTINGS)), + 3000); + + // Assumption failure if 'resIdObj' is null + assume().withMessage("resource id qs_media_controls not found") + .that(resIdObj) + .isNotNull(); + + // Assumption failure if 'testArtist' text is not present in notification + assume().withMessage("testArtist text not found") + .that(resIdObj.getContentDescription().contains(artistName)) + .isTrue(); + + // Fail the test if either notification title is not present or notification title text + // is null + UiObject2 headerTitleObj = + resIdObj.getParent().findObject(By.res(systemuiPackage, "header_title")); + assertWithMessage("Device is vulnerable to b/274775190 hence foreground services can be" + + " started with an empty notification") + .that(headerTitleObj == null || headerTitleObj.getText() == null) + .isFalse(); + } catch (Exception e) { + assume().that(e).isNull(); + } + } +} |