• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2023 The Android Open Source Project
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  *      http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  */
16 
17 package android.security.cts.CVE_2023_21107_test;
18 
19 import static androidx.test.platform.app.InstrumentationRegistry.getInstrumentation;
20 
21 import static com.android.sts.common.SystemUtil.poll;
22 
23 import static org.junit.Assert.assertFalse;
24 import static org.junit.Assume.assumeNoException;
25 import static org.junit.Assume.assumeNotNull;
26 
27 import android.app.Instrumentation;
28 import android.app.UiAutomation;
29 import android.content.Context;
30 import android.content.Intent;
31 import android.content.pm.UserInfo;
32 import android.os.UserHandle;
33 import android.os.UserManager;
34 import android.provider.Settings;
35 
36 import androidx.test.runner.AndroidJUnit4;
37 import androidx.test.uiautomator.UiDevice;
38 
39 import org.junit.Test;
40 import org.junit.runner.RunWith;
41 
42 import java.util.regex.Matcher;
43 import java.util.regex.Pattern;
44 
45 @RunWith(AndroidJUnit4.class)
46 public class DeviceTest {
47     @Test
testCVE_2023_21107()48     public void testCVE_2023_21107() {
49         UiAutomation uiAutomation = null;
50         try {
51             Instrumentation instrumentation = getInstrumentation();
52             Context context = instrumentation.getContext();
53             uiAutomation = instrumentation.getUiAutomation();
54 
55             UserHandle workUserHandle = null;
56             uiAutomation.adoptShellPermissionIdentity(android.Manifest.permission.CREATE_USERS);
57             for (UserInfo info : context.getSystemService(UserManager.class).getUsers()) {
58                 if (info.toString().contains("CVE_2023_21107_TestUser")) {
59                     workUserHandle = info.getUserHandle();
60                     break;
61                 }
62             }
63             assumeNotNull(workUserHandle);
64 
65             // NotificationAccessDetailsActivity should not launch for another
66             // user id without android.permission.INTERACT_ACROSS_USERS_FULL
67             Intent intent = new Intent(Settings.ACTION_NOTIFICATION_LISTENER_DETAIL_SETTINGS);
68             String helperAppPackage = "android.security.cts.CVE_2023_21107_helper";
69             intent.putExtra(
70                     Settings.EXTRA_NOTIFICATION_LISTENER_COMPONENT_NAME,
71                     helperAppPackage + "/" + helperAppPackage + ".TestListener");
72             intent.putExtra(Intent.EXTRA_USER_HANDLE, workUserHandle);
73             context.startActivity(intent.addFlags(Intent.FLAG_ACTIVITY_NEW_TASK));
74 
75             // Test fails if NotificationAccessDetailsActivity is launched
76             assertFalse(
77                     "Vulnerable to b/259385017",
78                     checkActivityLaunched(UiDevice.getInstance(instrumentation)));
79         } catch (Exception e) {
80             assumeNoException(e);
81         } finally {
82             try {
83                 uiAutomation.dropShellPermissionIdentity();
84             } catch (Exception ignored) {
85                 // Ignore all exceptiions
86             }
87         }
88     }
89 
checkActivityLaunched(final UiDevice device)90     private boolean checkActivityLaunched(final UiDevice device) throws Exception {
91         final Pattern resumedPattern = Pattern.compile("mResumed=(?<value>(true|false))");
92         return poll(
93                 () -> {
94                     try {
95                         String dumpsys =
96                                 device.executeShellCommand(
97                                         String.format(
98                                                 "dumpsys activity "
99                                                         + "NotificationAccessDetailsActivity"));
100                         Matcher matcher = resumedPattern.matcher(dumpsys);
101                         if (matcher.find() && matcher.group("value").equals("true")) {
102                             return true;
103                         }
104                     } catch (Exception e) {
105                         assumeNoException(e);
106                     }
107                     return false;
108                 },
109                 1_000L /* pollingTime */,
110                 5_000L /* maxPollingTime */);
111     }
112 }
113