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 com.android.server; 18 19 import static android.net.BpfNetMapsConstants.ALLOW_CHAINS; 20 import static android.net.BpfNetMapsConstants.BACKGROUND_MATCH; 21 import static android.net.BpfNetMapsConstants.CURRENT_STATS_MAP_CONFIGURATION_KEY; 22 import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED_KEY; 23 import static android.net.BpfNetMapsConstants.DATA_SAVER_DISABLED; 24 import static android.net.BpfNetMapsConstants.DATA_SAVER_ENABLED; 25 import static android.net.BpfNetMapsConstants.DENY_CHAINS; 26 import static android.net.BpfNetMapsConstants.DOZABLE_MATCH; 27 import static android.net.BpfNetMapsConstants.HAPPY_BOX_MATCH; 28 import static android.net.BpfNetMapsConstants.IIF_MATCH; 29 import static android.net.BpfNetMapsConstants.LOCKDOWN_VPN_MATCH; 30 import static android.net.BpfNetMapsConstants.LOW_POWER_STANDBY_MATCH; 31 import static android.net.BpfNetMapsConstants.NO_MATCH; 32 import static android.net.BpfNetMapsConstants.OEM_DENY_1_MATCH; 33 import static android.net.BpfNetMapsConstants.OEM_DENY_2_MATCH; 34 import static android.net.BpfNetMapsConstants.OEM_DENY_3_MATCH; 35 import static android.net.BpfNetMapsConstants.PENALTY_BOX_ADMIN_MATCH; 36 import static android.net.BpfNetMapsConstants.PENALTY_BOX_USER_MATCH; 37 import static android.net.BpfNetMapsConstants.POWERSAVE_MATCH; 38 import static android.net.BpfNetMapsConstants.RESTRICTED_MATCH; 39 import static android.net.BpfNetMapsConstants.STANDBY_MATCH; 40 import static android.net.BpfNetMapsConstants.UID_RULES_CONFIGURATION_KEY; 41 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_ADMIN_DISABLED; 42 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_DATA_SAVER; 43 import static android.net.ConnectivityManager.BLOCKED_METERED_REASON_USER_RESTRICTED; 44 import static android.net.ConnectivityManager.BLOCKED_REASON_APP_BACKGROUND; 45 import static android.net.ConnectivityManager.BLOCKED_REASON_APP_STANDBY; 46 import static android.net.ConnectivityManager.BLOCKED_REASON_BATTERY_SAVER; 47 import static android.net.ConnectivityManager.BLOCKED_REASON_DOZE; 48 import static android.net.ConnectivityManager.BLOCKED_REASON_NONE; 49 import static android.net.ConnectivityManager.BLOCKED_REASON_OEM_DENY; 50 import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE; 51 import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY; 52 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_ALLOW; 53 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_ADMIN; 54 import static android.net.ConnectivityManager.FIREWALL_CHAIN_METERED_DENY_USER; 55 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1; 56 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2; 57 import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_3; 58 import static android.net.ConnectivityManager.FIREWALL_CHAIN_POWERSAVE; 59 import static android.net.ConnectivityManager.FIREWALL_CHAIN_RESTRICTED; 60 import static android.net.ConnectivityManager.FIREWALL_CHAIN_STANDBY; 61 import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW; 62 import static android.net.ConnectivityManager.FIREWALL_RULE_DENY; 63 import static android.net.INetd.PERMISSION_INTERNET; 64 import static android.net.INetd.PERMISSION_NONE; 65 import static android.net.INetd.PERMISSION_UNINSTALLED; 66 import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS; 67 import static android.system.OsConstants.EINVAL; 68 import static android.system.OsConstants.EPERM; 69 70 import static com.android.server.ConnectivityStatsLog.NETWORK_BPF_MAP_INFO; 71 72 import static org.junit.Assert.assertEquals; 73 import static org.junit.Assert.assertFalse; 74 import static org.junit.Assert.assertNotNull; 75 import static org.junit.Assert.assertNull; 76 import static org.junit.Assert.assertThrows; 77 import static org.junit.Assert.assertTrue; 78 import static org.junit.Assume.assumeFalse; 79 import static org.mockito.Mockito.any; 80 import static org.mockito.Mockito.doReturn; 81 import static org.mockito.Mockito.doThrow; 82 import static org.mockito.Mockito.spy; 83 import static org.mockito.Mockito.verify; 84 85 import android.app.StatsManager; 86 import android.content.Context; 87 import android.net.BpfNetMapsUtils; 88 import android.net.INetd; 89 import android.net.InetAddresses; 90 import android.net.UidOwnerValue; 91 import android.os.Build; 92 import android.os.Process; 93 import android.os.ServiceSpecificException; 94 import android.os.UserHandle; 95 import android.system.ErrnoException; 96 import android.util.ArraySet; 97 import android.util.IndentingPrintWriter; 98 99 import androidx.test.filters.SmallTest; 100 101 import com.android.modules.utils.build.SdkLevel; 102 import com.android.net.module.util.IBpfMap; 103 import com.android.net.module.util.Struct.Bool; 104 import com.android.net.module.util.Struct.S32; 105 import com.android.net.module.util.Struct.U32; 106 import com.android.net.module.util.Struct.U8; 107 import com.android.net.module.util.bpf.CookieTagMapKey; 108 import com.android.net.module.util.bpf.CookieTagMapValue; 109 import com.android.net.module.util.bpf.IngressDiscardKey; 110 import com.android.net.module.util.bpf.IngressDiscardValue; 111 import com.android.net.module.util.bpf.LocalNetAccessKey; 112 import com.android.server.connectivity.InterfaceTracker; 113 import com.android.testutils.DevSdkIgnoreRule; 114 import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter; 115 import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; 116 import com.android.testutils.DevSdkIgnoreRunner; 117 import com.android.testutils.TestBpfMap; 118 119 import org.junit.Before; 120 import org.junit.Rule; 121 import org.junit.Test; 122 import org.junit.runner.RunWith; 123 import org.mockito.Mock; 124 import org.mockito.MockitoAnnotations; 125 126 import java.io.FileDescriptor; 127 import java.io.StringWriter; 128 import java.net.Inet4Address; 129 import java.net.Inet6Address; 130 import java.util.ArrayList; 131 import java.util.List; 132 133 @RunWith(DevSdkIgnoreRunner.class) 134 @SmallTest 135 @DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R) 136 public final class BpfNetMapsTest { 137 private static final String TAG = "BpfNetMapsTest"; 138 139 @Rule 140 public final DevSdkIgnoreRule ignoreRule = new DevSdkIgnoreRule(); 141 142 private static final int TEST_UID = 10086; 143 private static final int[] TEST_UIDS = {10002, 10003}; 144 private static final int[] CORE_AIDS = { 145 Process.ROOT_UID, 146 Process.SYSTEM_UID, 147 Process.FIRST_APPLICATION_UID - 10, 148 Process.FIRST_APPLICATION_UID - 1, 149 }; 150 private static final String TEST_IF_NAME = "wlan0"; 151 private static final int TEST_IF_INDEX = 7; 152 private static final int NO_IIF = 0; 153 private static final int NULL_IIF = 0; 154 private static final Inet4Address TEST_V4_ADDRESS = 155 (Inet4Address) InetAddresses.parseNumericAddress("192.0.2.1"); 156 private static final Inet6Address TEST_V6_ADDRESS = 157 (Inet6Address) InetAddresses.parseNumericAddress("2001:db8::1"); 158 private static final String CHAINNAME = "fw_dozable"; 159 160 private static final long STATS_SELECT_MAP_A = 0; 161 private static final long STATS_SELECT_MAP_B = 1; 162 163 private static final List<Integer> FIREWALL_CHAINS = new ArrayList<>(); 164 static { 165 FIREWALL_CHAINS.addAll(ALLOW_CHAINS); 166 FIREWALL_CHAINS.addAll(DENY_CHAINS); 167 } 168 169 private BpfNetMaps mBpfNetMaps; 170 171 @Mock INetd mNetd; 172 @Mock BpfNetMaps.Dependencies mDeps; 173 @Mock Context mContext; 174 175 @Mock InterfaceTracker mInterfaceTracker; 176 private final IBpfMap<S32, U32> mConfigurationMap = new TestBpfMap<>(S32.class, U32.class); 177 private final IBpfMap<S32, UidOwnerValue> mUidOwnerMap = 178 new TestBpfMap<>(S32.class, UidOwnerValue.class); 179 private final IBpfMap<S32, U8> mUidPermissionMap = new TestBpfMap<>(S32.class, U8.class); 180 private final IBpfMap<U32, Bool> mLocalNetBlockedUidMap = 181 new TestBpfMap<>(U32.class, Bool.class); 182 private final IBpfMap<LocalNetAccessKey, Bool> mLocalNetAccessMap = 183 new TestBpfMap<>(LocalNetAccessKey.class, Bool.class); 184 private final IBpfMap<CookieTagMapKey, CookieTagMapValue> mCookieTagMap = 185 spy(new TestBpfMap<>(CookieTagMapKey.class, CookieTagMapValue.class)); 186 private final IBpfMap<S32, U8> mDataSaverEnabledMap = new TestBpfMap<>(S32.class, U8.class); 187 private final IBpfMap<IngressDiscardKey, IngressDiscardValue> mIngressDiscardMap = 188 new TestBpfMap<>(IngressDiscardKey.class, IngressDiscardValue.class); 189 190 @Before setUp()191 public void setUp() throws Exception { 192 MockitoAnnotations.initMocks(this); 193 doReturn(TEST_IF_INDEX).when(mDeps).getIfIndex(TEST_IF_NAME); 194 doReturn(TEST_IF_INDEX).when(mInterfaceTracker).getInterfaceIndex(TEST_IF_NAME); 195 doReturn(TEST_IF_NAME).when(mDeps).getIfName(TEST_IF_INDEX); 196 doReturn(0).when(mDeps).synchronizeKernelRCU(); 197 BpfNetMaps.setConfigurationMapForTest(mConfigurationMap); 198 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(0)); 199 mConfigurationMap.updateEntry( 200 CURRENT_STATS_MAP_CONFIGURATION_KEY, new U32(STATS_SELECT_MAP_A)); 201 BpfNetMaps.setUidOwnerMapForTest(mUidOwnerMap); 202 BpfNetMaps.setUidPermissionMapForTest(mUidPermissionMap); 203 BpfNetMaps.setLocalNetAccessMapForTest(mLocalNetAccessMap); 204 BpfNetMaps.setLocalNetBlockedUidMapForTest(mLocalNetBlockedUidMap); 205 BpfNetMaps.setCookieTagMapForTest(mCookieTagMap); 206 BpfNetMaps.setDataSaverEnabledMapForTest(mDataSaverEnabledMap); 207 mDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(DATA_SAVER_DISABLED)); 208 BpfNetMaps.setIngressDiscardMapForTest(mIngressDiscardMap); 209 mBpfNetMaps = new BpfNetMaps(mContext, mNetd, mDeps, mInterfaceTracker); 210 } 211 212 @Test testBpfNetMapsBeforeT()213 public void testBpfNetMapsBeforeT() throws Exception { 214 assumeFalse(SdkLevel.isAtLeastT()); 215 mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS); 216 verify(mNetd).firewallAddUidInterfaceRules(TEST_IF_NAME, TEST_UIDS); 217 mBpfNetMaps.removeUidInterfaceRules(TEST_UIDS); 218 verify(mNetd).firewallRemoveUidInterfaceRules(TEST_UIDS); 219 mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET, TEST_UIDS); 220 verify(mNetd).trafficSetNetPermForUids(PERMISSION_INTERNET, TEST_UIDS); 221 } 222 getMatch(final List<Integer> chains)223 private long getMatch(final List<Integer> chains) { 224 long match = 0; 225 for (final int chain: chains) { 226 match |= BpfNetMapsUtils.getMatchByFirewallChain(chain); 227 } 228 return match; 229 } 230 doTestIsChainEnabled(final List<Integer> enableChains)231 private void doTestIsChainEnabled(final List<Integer> enableChains) throws Exception { 232 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(getMatch(enableChains))); 233 234 for (final int chain: FIREWALL_CHAINS) { 235 final String testCase = "EnabledChains: " + enableChains + " CheckedChain: " + chain; 236 if (enableChains.contains(chain)) { 237 assertTrue("Expected isChainEnabled returns True, " + testCase, 238 mBpfNetMaps.isChainEnabled(chain)); 239 } else { 240 assertFalse("Expected isChainEnabled returns False, " + testCase, 241 mBpfNetMaps.isChainEnabled(chain)); 242 } 243 } 244 } 245 doTestIsChainEnabled(final int enableChain)246 private void doTestIsChainEnabled(final int enableChain) throws Exception { 247 doTestIsChainEnabled(List.of(enableChain)); 248 } 249 250 @Test 251 @IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM) testAddLocalNetAccessBeforeV()252 public void testAddLocalNetAccessBeforeV() { 253 assertThrows(UnsupportedOperationException.class, () -> 254 mBpfNetMaps.addLocalNetAccess(0, TEST_IF_NAME, Inet6Address.ANY, 0, 0, true)); 255 } 256 257 @Test 258 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testAddLocalNetAccessAfterV()259 public void testAddLocalNetAccessAfterV() throws Exception { 260 assertTrue(mLocalNetAccessMap.isEmpty()); 261 262 mBpfNetMaps.addLocalNetAccess(160, TEST_IF_NAME, 263 Inet4Address.getByName("196.68.0.0"), 0, 0, true); 264 265 assertNotNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 266 Inet4Address.getByName("196.68.0.0"), 0, 0))); 267 assertNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 268 Inet4Address.getByName("100.68.0.0"), 0, 0))); 269 } 270 271 @Test 272 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testAddLocalNetAccessWithNullInterfaceAfterV()273 public void testAddLocalNetAccessWithNullInterfaceAfterV() throws Exception { 274 assertTrue(mLocalNetAccessMap.isEmpty()); 275 276 mBpfNetMaps.addLocalNetAccess(160, null, 277 Inet4Address.getByName("196.68.0.0"), 0, 0, true); 278 279 // As we tried to add null interface, it would be skipped and map should be empty. 280 assertTrue(mLocalNetAccessMap.isEmpty()); 281 } 282 283 @Test 284 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testAddLocalNetAccessAfterVWithIncorrectInterface()285 public void testAddLocalNetAccessAfterVWithIncorrectInterface() throws Exception { 286 assertTrue(mLocalNetAccessMap.isEmpty()); 287 288 // wlan2 is an incorrect interface 289 mBpfNetMaps.addLocalNetAccess(160, "wlan2", 290 Inet4Address.getByName("196.68.0.0"), 0, 0, true); 291 292 // As we tried to add incorrect interface, it would be skipped and map should be empty. 293 assertTrue(mLocalNetAccessMap.isEmpty()); 294 } 295 296 @Test 297 @IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM) testGetLocalNetAccessBeforeV()298 public void testGetLocalNetAccessBeforeV() { 299 assertThrows(UnsupportedOperationException.class, () -> 300 mBpfNetMaps.getLocalNetAccess(0, TEST_IF_NAME, Inet6Address.ANY, 0, 0)); 301 } 302 303 @Test 304 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testGetLocalNetAccessAfterV()305 public void testGetLocalNetAccessAfterV() throws Exception { 306 assertTrue(mLocalNetAccessMap.isEmpty()); 307 308 mLocalNetAccessMap.updateEntry(new LocalNetAccessKey(160, TEST_IF_INDEX, 309 Inet4Address.getByName("196.68.0.0"), 0, 0), 310 new Bool(false)); 311 312 assertNotNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 313 Inet4Address.getByName("196.68.0.0"), 0, 0))); 314 315 assertFalse(mBpfNetMaps.getLocalNetAccess(160, TEST_IF_NAME, 316 Inet4Address.getByName("196.68.0.0"), 0, 0)); 317 assertTrue(mBpfNetMaps.getLocalNetAccess(160, TEST_IF_NAME, 318 Inet4Address.getByName("100.68.0.0"), 0, 0)); 319 } 320 321 @Test 322 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testGetLocalNetAccessWithNullInterfaceAfterV()323 public void testGetLocalNetAccessWithNullInterfaceAfterV() throws Exception { 324 assertTrue(mBpfNetMaps.getLocalNetAccess(160, null, 325 Inet4Address.getByName("100.68.0.0"), 0, 0)); 326 } 327 328 @Test 329 @IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM) testRemoveLocalNetAccessBeforeV()330 public void testRemoveLocalNetAccessBeforeV() { 331 assertThrows(UnsupportedOperationException.class, () -> 332 mBpfNetMaps.removeLocalNetAccess(0, TEST_IF_NAME, Inet6Address.ANY, 0, 0)); 333 } 334 335 @Test 336 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testRemoveLocalNetAccessAfterV()337 public void testRemoveLocalNetAccessAfterV() throws Exception { 338 assertTrue(mLocalNetAccessMap.isEmpty()); 339 340 mBpfNetMaps.addLocalNetAccess(160, TEST_IF_NAME, 341 Inet4Address.getByName("196.68.0.0"), 0, 0, true); 342 343 assertNotNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 344 Inet4Address.getByName("196.68.0.0"), 0, 0))); 345 assertNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 346 Inet4Address.getByName("100.68.0.0"), 0, 0))); 347 348 mBpfNetMaps.removeLocalNetAccess(160, TEST_IF_NAME, 349 Inet4Address.getByName("196.68.0.0"), 0, 0); 350 assertNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 351 Inet4Address.getByName("196.68.0.0"), 0, 0))); 352 assertNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 353 Inet4Address.getByName("100.68.0.0"), 0, 0))); 354 } 355 356 @Test 357 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testRemoveLocalNetAccessAfterVWithIncorrectInterface()358 public void testRemoveLocalNetAccessAfterVWithIncorrectInterface() throws Exception { 359 assertTrue(mLocalNetAccessMap.isEmpty()); 360 361 mBpfNetMaps.addLocalNetAccess(160, TEST_IF_NAME, 362 Inet4Address.getByName("196.68.0.0"), 0, 0, true); 363 364 assertNotNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 365 Inet4Address.getByName("196.68.0.0"), 0, 0))); 366 assertNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 367 Inet4Address.getByName("100.68.0.0"), 0, 0))); 368 369 mBpfNetMaps.removeLocalNetAccess(160, "wlan2", 370 Inet4Address.getByName("196.68.0.0"), 0, 0); 371 assertNotNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 372 Inet4Address.getByName("196.68.0.0"), 0, 0))); 373 } 374 375 @Test 376 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testRemoveLocalNetAccessAfterVWithNullInterface()377 public void testRemoveLocalNetAccessAfterVWithNullInterface() throws Exception { 378 assertTrue(mLocalNetAccessMap.isEmpty()); 379 380 mBpfNetMaps.addLocalNetAccess(160, TEST_IF_NAME, 381 Inet4Address.getByName("196.68.0.0"), 0, 0, true); 382 383 assertNotNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 384 Inet4Address.getByName("196.68.0.0"), 0, 0))); 385 assertNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 386 Inet4Address.getByName("100.68.0.0"), 0, 0))); 387 388 mBpfNetMaps.removeLocalNetAccess(160, null, 389 Inet4Address.getByName("196.68.0.0"), 0, 0); 390 assertNotNull(mLocalNetAccessMap.getValue(new LocalNetAccessKey(160, TEST_IF_INDEX, 391 Inet4Address.getByName("196.68.0.0"), 0, 0))); 392 } 393 394 @Test 395 @IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM) testAddUidToLocalNetBlockMapBeforeV()396 public void testAddUidToLocalNetBlockMapBeforeV() { 397 assertThrows(UnsupportedOperationException.class, () -> 398 mBpfNetMaps.addUidToLocalNetBlockMap(0)); 399 } 400 401 @Test 402 @IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM) testIsUidBlockedFromUsingLocalNetworkBeforeV()403 public void testIsUidBlockedFromUsingLocalNetworkBeforeV() { 404 assertThrows(UnsupportedOperationException.class, () -> 405 mBpfNetMaps.isUidBlockedFromUsingLocalNetwork(0)); 406 } 407 408 @Test 409 @IgnoreAfter(Build.VERSION_CODES.VANILLA_ICE_CREAM) testRemoveUidFromLocalNetBlockMapBeforeV()410 public void testRemoveUidFromLocalNetBlockMapBeforeV() { 411 assertThrows(UnsupportedOperationException.class, () -> 412 mBpfNetMaps.removeUidFromLocalNetBlockMap(0)); 413 } 414 415 @Test 416 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testAddUidFromLocalNetBlockMapAfterV()417 public void testAddUidFromLocalNetBlockMapAfterV() throws Exception { 418 final int uid0 = TEST_UIDS[0]; 419 final int uid1 = TEST_UIDS[1]; 420 421 assertTrue(mLocalNetAccessMap.isEmpty()); 422 423 mBpfNetMaps.addUidToLocalNetBlockMap(uid0); 424 assertTrue(mLocalNetBlockedUidMap.getValue(new U32(uid0)).val); 425 assertNull(mLocalNetBlockedUidMap.getValue(new U32(uid1))); 426 427 mBpfNetMaps.addUidToLocalNetBlockMap(uid1); 428 assertTrue(mLocalNetBlockedUidMap.getValue(new U32(uid1)).val); 429 } 430 431 @Test 432 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testIsUidBlockedFromUsingLocalNetworkAfterV()433 public void testIsUidBlockedFromUsingLocalNetworkAfterV() throws Exception { 434 final int uid0 = TEST_UIDS[0]; 435 final int uid1 = TEST_UIDS[1]; 436 437 assertTrue(mLocalNetAccessMap.isEmpty()); 438 439 mLocalNetBlockedUidMap.updateEntry(new U32(uid0), new Bool(true)); 440 assertTrue(mBpfNetMaps.isUidBlockedFromUsingLocalNetwork(uid0)); 441 assertFalse(mBpfNetMaps.isUidBlockedFromUsingLocalNetwork(uid1)); 442 443 mLocalNetBlockedUidMap.updateEntry(new U32(uid1), new Bool(true)); 444 assertTrue(mBpfNetMaps.isUidBlockedFromUsingLocalNetwork(uid1)); 445 } 446 447 @Test 448 @IgnoreUpTo(Build.VERSION_CODES.VANILLA_ICE_CREAM) testRemoveUidFromLocalNetBlockMapAfterV()449 public void testRemoveUidFromLocalNetBlockMapAfterV() throws Exception { 450 final int uid0 = TEST_UIDS[0]; 451 final int uid1 = TEST_UIDS[1]; 452 453 assertTrue(mLocalNetAccessMap.isEmpty()); 454 455 mLocalNetBlockedUidMap.updateEntry(new U32(uid0), new Bool(true)); 456 mLocalNetBlockedUidMap.updateEntry(new U32(uid1), new Bool(true)); 457 458 assertTrue(mLocalNetBlockedUidMap.getValue(new U32(uid0)).val); 459 assertTrue(mLocalNetBlockedUidMap.getValue(new U32(uid1)).val); 460 461 mBpfNetMaps.removeUidFromLocalNetBlockMap(uid0); 462 assertNull(mLocalNetBlockedUidMap.getValue(new U32(uid0))); 463 assertTrue(mLocalNetBlockedUidMap.getValue(new U32(uid1)).val); 464 465 mBpfNetMaps.removeUidFromLocalNetBlockMap(uid1); 466 assertNull(mLocalNetBlockedUidMap.getValue(new U32(uid1))); 467 } 468 469 @Test 470 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testIsChainEnabled()471 public void testIsChainEnabled() throws Exception { 472 doTestIsChainEnabled(FIREWALL_CHAIN_DOZABLE); 473 doTestIsChainEnabled(FIREWALL_CHAIN_STANDBY); 474 doTestIsChainEnabled(FIREWALL_CHAIN_POWERSAVE); 475 doTestIsChainEnabled(FIREWALL_CHAIN_RESTRICTED); 476 doTestIsChainEnabled(FIREWALL_CHAIN_LOW_POWER_STANDBY); 477 doTestIsChainEnabled(FIREWALL_CHAIN_OEM_DENY_1); 478 doTestIsChainEnabled(FIREWALL_CHAIN_OEM_DENY_2); 479 doTestIsChainEnabled(FIREWALL_CHAIN_OEM_DENY_3); 480 } 481 482 @Test 483 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testIsChainEnabledMultipleChainEnabled()484 public void testIsChainEnabledMultipleChainEnabled() throws Exception { 485 doTestIsChainEnabled(List.of( 486 FIREWALL_CHAIN_DOZABLE, 487 FIREWALL_CHAIN_STANDBY)); 488 doTestIsChainEnabled(List.of( 489 FIREWALL_CHAIN_DOZABLE, 490 FIREWALL_CHAIN_STANDBY, 491 FIREWALL_CHAIN_POWERSAVE, 492 FIREWALL_CHAIN_RESTRICTED)); 493 doTestIsChainEnabled(FIREWALL_CHAINS); 494 } 495 496 @Test 497 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testIsChainEnabledInvalidChain()498 public void testIsChainEnabledInvalidChain() { 499 final Class<ServiceSpecificException> expected = ServiceSpecificException.class; 500 assertThrows(expected, () -> mBpfNetMaps.isChainEnabled(-1 /* childChain */)); 501 assertThrows(expected, () -> mBpfNetMaps.isChainEnabled(1000 /* childChain */)); 502 } 503 504 @Test 505 @IgnoreAfter(Build.VERSION_CODES.S_V2) testIsChainEnabledBeforeT()506 public void testIsChainEnabledBeforeT() { 507 assertThrows(UnsupportedOperationException.class, 508 () -> mBpfNetMaps.isChainEnabled(FIREWALL_CHAIN_DOZABLE)); 509 } 510 doTestSetChildChain(final List<Integer> testChains)511 private void doTestSetChildChain(final List<Integer> testChains) throws Exception { 512 long expectedMatch = 0; 513 for (final int chain: testChains) { 514 expectedMatch |= BpfNetMapsUtils.getMatchByFirewallChain(chain); 515 } 516 517 assertEquals(0, mConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY).val); 518 519 for (final int chain: testChains) { 520 mBpfNetMaps.setChildChain(chain, true /* enable */); 521 } 522 assertEquals(expectedMatch, mConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY).val); 523 524 for (final int chain: testChains) { 525 mBpfNetMaps.setChildChain(chain, false /* enable */); 526 } 527 assertEquals(0, mConfigurationMap.getValue(UID_RULES_CONFIGURATION_KEY).val); 528 } 529 doTestSetChildChain(final int testChain)530 private void doTestSetChildChain(final int testChain) throws Exception { 531 doTestSetChildChain(List.of(testChain)); 532 } 533 534 @Test 535 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetChildChain()536 public void testSetChildChain() throws Exception { 537 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(0)); 538 doTestSetChildChain(FIREWALL_CHAIN_DOZABLE); 539 doTestSetChildChain(FIREWALL_CHAIN_STANDBY); 540 doTestSetChildChain(FIREWALL_CHAIN_POWERSAVE); 541 doTestSetChildChain(FIREWALL_CHAIN_RESTRICTED); 542 doTestSetChildChain(FIREWALL_CHAIN_LOW_POWER_STANDBY); 543 doTestSetChildChain(FIREWALL_CHAIN_OEM_DENY_1); 544 doTestSetChildChain(FIREWALL_CHAIN_OEM_DENY_2); 545 doTestSetChildChain(FIREWALL_CHAIN_OEM_DENY_3); 546 } 547 548 @Test 549 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetChildChainMultipleChain()550 public void testSetChildChainMultipleChain() throws Exception { 551 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(0)); 552 doTestSetChildChain(List.of( 553 FIREWALL_CHAIN_DOZABLE, 554 FIREWALL_CHAIN_STANDBY)); 555 doTestSetChildChain(List.of( 556 FIREWALL_CHAIN_DOZABLE, 557 FIREWALL_CHAIN_STANDBY, 558 FIREWALL_CHAIN_POWERSAVE, 559 FIREWALL_CHAIN_RESTRICTED)); 560 doTestSetChildChain(FIREWALL_CHAINS); 561 } 562 563 @Test 564 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetChildChainInvalidChain()565 public void testSetChildChainInvalidChain() { 566 final Class<ServiceSpecificException> expected = ServiceSpecificException.class; 567 assertThrows(expected, 568 () -> mBpfNetMaps.setChildChain(-1 /* childChain */, true /* enable */)); 569 assertThrows(expected, 570 () -> mBpfNetMaps.setChildChain(1000 /* childChain */, true /* enable */)); 571 } 572 573 @Test 574 @IgnoreAfter(Build.VERSION_CODES.S_V2) testSetChildChainBeforeT()575 public void testSetChildChainBeforeT() { 576 assertThrows(UnsupportedOperationException.class, 577 () -> mBpfNetMaps.setChildChain(FIREWALL_CHAIN_DOZABLE, true /* enable */)); 578 } 579 checkUidOwnerValue(final int uid, final int expectedIif, final long expectedMatch)580 private void checkUidOwnerValue(final int uid, final int expectedIif, 581 final long expectedMatch) throws Exception { 582 final UidOwnerValue config = mUidOwnerMap.getValue(new S32(uid)); 583 if (expectedMatch == 0) { 584 assertNull(config); 585 } else { 586 assertEquals(expectedIif, config.iif); 587 assertEquals(expectedMatch, config.rule); 588 } 589 } 590 doTestUpdateUidLockdownRule(final int iif, final long match, final boolean add)591 private void doTestUpdateUidLockdownRule(final int iif, final long match, final boolean add) 592 throws Exception { 593 if (match != NO_MATCH) { 594 mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(iif, match)); 595 } 596 597 mBpfNetMaps.updateUidLockdownRule(TEST_UID, add); 598 599 final long expectedMatch = add ? match | LOCKDOWN_VPN_MATCH : match & ~LOCKDOWN_VPN_MATCH; 600 checkUidOwnerValue(TEST_UID, iif, expectedMatch); 601 } 602 603 private static final boolean ADD = true; 604 private static final boolean REMOVE = false; 605 606 @Test 607 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testUpdateUidLockdownRuleAddLockdown()608 public void testUpdateUidLockdownRuleAddLockdown() throws Exception { 609 doTestUpdateUidLockdownRule(NO_IIF, NO_MATCH, ADD); 610 611 // Other matches are enabled 612 doTestUpdateUidLockdownRule( 613 NO_IIF, DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH, ADD); 614 615 // IIF_MATCH is enabled 616 doTestUpdateUidLockdownRule(TEST_IF_INDEX, DOZABLE_MATCH, ADD); 617 618 // LOCKDOWN_VPN_MATCH is already enabled 619 doTestUpdateUidLockdownRule(NO_IIF, LOCKDOWN_VPN_MATCH | DOZABLE_MATCH, ADD); 620 } 621 622 @Test 623 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testUpdateUidLockdownRuleRemoveLockdown()624 public void testUpdateUidLockdownRuleRemoveLockdown() throws Exception { 625 doTestUpdateUidLockdownRule(NO_IIF, LOCKDOWN_VPN_MATCH, REMOVE); 626 627 // LOCKDOWN_VPN_MATCH with other matches 628 doTestUpdateUidLockdownRule( 629 NO_IIF, LOCKDOWN_VPN_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH, REMOVE); 630 631 // LOCKDOWN_VPN_MATCH with IIF_MATCH 632 doTestUpdateUidLockdownRule(TEST_IF_INDEX, LOCKDOWN_VPN_MATCH | IIF_MATCH, REMOVE); 633 634 // LOCKDOWN_VPN_MATCH is not enabled 635 doTestUpdateUidLockdownRule(NO_IIF, POWERSAVE_MATCH | RESTRICTED_MATCH, REMOVE); 636 } 637 638 @Test 639 @IgnoreAfter(Build.VERSION_CODES.S_V2) testUpdateUidLockdownRuleBeforeT()640 public void testUpdateUidLockdownRuleBeforeT() { 641 assertThrows(UnsupportedOperationException.class, 642 () -> mBpfNetMaps.updateUidLockdownRule(TEST_UID, true /* add */)); 643 } 644 645 @Test 646 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testAddUidInterfaceRules()647 public void testAddUidInterfaceRules() throws Exception { 648 final int uid0 = TEST_UIDS[0]; 649 final int uid1 = TEST_UIDS[1]; 650 651 mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS); 652 653 checkUidOwnerValue(uid0, TEST_IF_INDEX, IIF_MATCH); 654 checkUidOwnerValue(uid1, TEST_IF_INDEX, IIF_MATCH); 655 } 656 657 @Test 658 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testAddUidInterfaceRulesWithOtherMatch()659 public void testAddUidInterfaceRulesWithOtherMatch() throws Exception { 660 final int uid0 = TEST_UIDS[0]; 661 final int uid1 = TEST_UIDS[1]; 662 final long match0 = DOZABLE_MATCH; 663 final long match1 = DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH; 664 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(NO_IIF, match0)); 665 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(NO_IIF, match1)); 666 667 mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS); 668 669 checkUidOwnerValue(uid0, TEST_IF_INDEX, match0 | IIF_MATCH); 670 checkUidOwnerValue(uid1, TEST_IF_INDEX, match1 | IIF_MATCH); 671 } 672 673 @Test 674 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testAddUidInterfaceRulesWithExistingIifMatch()675 public void testAddUidInterfaceRulesWithExistingIifMatch() throws Exception { 676 final int uid0 = TEST_UIDS[0]; 677 final int uid1 = TEST_UIDS[1]; 678 final long match0 = IIF_MATCH; 679 final long match1 = IIF_MATCH | DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH; 680 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(TEST_IF_INDEX + 1, match0)); 681 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(NULL_IIF, match1)); 682 683 mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS); 684 685 checkUidOwnerValue(uid0, TEST_IF_INDEX, match0); 686 checkUidOwnerValue(uid1, TEST_IF_INDEX, match1); 687 } 688 689 @Test 690 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testAddUidInterfaceRulesGetIfIndexFail()691 public void testAddUidInterfaceRulesGetIfIndexFail() { 692 doReturn(0).when(mDeps).getIfIndex(TEST_IF_NAME); 693 assertThrows(ServiceSpecificException.class, 694 () -> mBpfNetMaps.addUidInterfaceRules(TEST_IF_NAME, TEST_UIDS)); 695 } 696 697 @Test 698 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testAddUidInterfaceRulesWithNullInterface()699 public void testAddUidInterfaceRulesWithNullInterface() throws Exception { 700 final int uid0 = TEST_UIDS[0]; 701 final int uid1 = TEST_UIDS[1]; 702 final long match0 = IIF_MATCH; 703 final long match1 = IIF_MATCH | DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH; 704 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(TEST_IF_INDEX, match0)); 705 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(NULL_IIF, match1)); 706 707 mBpfNetMaps.addUidInterfaceRules(null /* ifName */, TEST_UIDS); 708 709 checkUidOwnerValue(uid0, NULL_IIF, match0); 710 checkUidOwnerValue(uid1, NULL_IIF, match1); 711 } 712 doTestRemoveUidInterfaceRules(final int iif0, final long match0, final int iif1, final long match1)713 private void doTestRemoveUidInterfaceRules(final int iif0, final long match0, 714 final int iif1, final long match1) throws Exception { 715 final int uid0 = TEST_UIDS[0]; 716 final int uid1 = TEST_UIDS[1]; 717 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(iif0, match0)); 718 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(iif1, match1)); 719 720 mBpfNetMaps.removeUidInterfaceRules(TEST_UIDS); 721 722 checkUidOwnerValue(uid0, NO_IIF, match0 & ~IIF_MATCH); 723 checkUidOwnerValue(uid1, NO_IIF, match1 & ~IIF_MATCH); 724 } 725 726 @Test 727 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testRemoveUidInterfaceRules()728 public void testRemoveUidInterfaceRules() throws Exception { 729 doTestRemoveUidInterfaceRules(TEST_IF_INDEX, IIF_MATCH, NULL_IIF, IIF_MATCH); 730 731 // IIF_MATCH and other matches are enabled 732 doTestRemoveUidInterfaceRules(TEST_IF_INDEX, IIF_MATCH | DOZABLE_MATCH, 733 NULL_IIF, IIF_MATCH | DOZABLE_MATCH | RESTRICTED_MATCH); 734 735 // IIF_MATCH is not enabled 736 doTestRemoveUidInterfaceRules(NO_IIF, DOZABLE_MATCH, 737 NO_IIF, DOZABLE_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH); 738 } 739 doTestSetUidRule(final List<Integer> testChains)740 private void doTestSetUidRule(final List<Integer> testChains) throws Exception { 741 mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(TEST_IF_INDEX, IIF_MATCH)); 742 743 for (final int chain: testChains) { 744 final int ruleToAddMatch = BpfNetMapsUtils.isFirewallAllowList(chain) 745 ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY; 746 mBpfNetMaps.setUidRule(chain, TEST_UID, ruleToAddMatch); 747 } 748 749 checkUidOwnerValue(TEST_UID, TEST_IF_INDEX, IIF_MATCH | getMatch(testChains)); 750 751 for (final int chain: testChains) { 752 final int ruleToRemoveMatch = BpfNetMapsUtils.isFirewallAllowList(chain) 753 ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW; 754 mBpfNetMaps.setUidRule(chain, TEST_UID, ruleToRemoveMatch); 755 } 756 757 checkUidOwnerValue(TEST_UID, TEST_IF_INDEX, IIF_MATCH); 758 } 759 doTestSetUidRule(final int testChain)760 private void doTestSetUidRule(final int testChain) throws Exception { 761 doTestSetUidRule(List.of(testChain)); 762 } 763 764 @Test 765 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetUidRule()766 public void testSetUidRule() throws Exception { 767 doTestSetUidRule(FIREWALL_CHAIN_DOZABLE); 768 doTestSetUidRule(FIREWALL_CHAIN_STANDBY); 769 doTestSetUidRule(FIREWALL_CHAIN_POWERSAVE); 770 doTestSetUidRule(FIREWALL_CHAIN_RESTRICTED); 771 doTestSetUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY); 772 doTestSetUidRule(FIREWALL_CHAIN_OEM_DENY_1); 773 doTestSetUidRule(FIREWALL_CHAIN_OEM_DENY_2); 774 doTestSetUidRule(FIREWALL_CHAIN_OEM_DENY_3); 775 doTestSetUidRule(FIREWALL_CHAIN_METERED_ALLOW); 776 doTestSetUidRule(FIREWALL_CHAIN_METERED_DENY_USER); 777 doTestSetUidRule(FIREWALL_CHAIN_METERED_DENY_ADMIN); 778 } 779 780 @Test 781 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetUidRuleMultipleChain()782 public void testSetUidRuleMultipleChain() throws Exception { 783 doTestSetUidRule(List.of( 784 FIREWALL_CHAIN_DOZABLE, 785 FIREWALL_CHAIN_STANDBY)); 786 doTestSetUidRule(List.of( 787 FIREWALL_CHAIN_DOZABLE, 788 FIREWALL_CHAIN_STANDBY, 789 FIREWALL_CHAIN_POWERSAVE, 790 FIREWALL_CHAIN_RESTRICTED)); 791 doTestSetUidRule(FIREWALL_CHAINS); 792 } 793 794 @Test 795 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetUidRuleRemoveRuleFromUidWithNoRule()796 public void testSetUidRuleRemoveRuleFromUidWithNoRule() { 797 final Class<ServiceSpecificException> expected = ServiceSpecificException.class; 798 assertThrows(expected, 799 () -> mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_DENY)); 800 } 801 802 @Test 803 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetUidRuleInvalidChain()804 public void testSetUidRuleInvalidChain() { 805 final Class<ServiceSpecificException> expected = ServiceSpecificException.class; 806 assertThrows(expected, 807 () -> mBpfNetMaps.setUidRule(-1 /* childChain */, TEST_UID, FIREWALL_RULE_ALLOW)); 808 assertThrows(expected, 809 () -> mBpfNetMaps.setUidRule(1000 /* childChain */, TEST_UID, FIREWALL_RULE_ALLOW)); 810 } 811 812 @Test 813 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetUidRuleInvalidRule()814 public void testSetUidRuleInvalidRule() { 815 final Class<ServiceSpecificException> expected = ServiceSpecificException.class; 816 assertThrows(expected, () -> 817 mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, -1 /* firewallRule */)); 818 assertThrows(expected, () -> 819 mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, 1000 /* firewallRule */)); 820 } 821 822 @Test 823 @IgnoreAfter(Build.VERSION_CODES.S_V2) testSetUidRuleBeforeT()824 public void testSetUidRuleBeforeT() { 825 assertThrows(UnsupportedOperationException.class, () -> 826 mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_ALLOW)); 827 } 828 doTestGetUidRule(final List<Integer> enableChains)829 private void doTestGetUidRule(final List<Integer> enableChains) throws Exception { 830 mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(0, getMatch(enableChains))); 831 832 for (final int chain: FIREWALL_CHAINS) { 833 final String testCase = "EnabledChains: " + enableChains + " CheckedChain: " + chain; 834 if (enableChains.contains(chain)) { 835 final int expectedRule = BpfNetMapsUtils.isFirewallAllowList(chain) 836 ? FIREWALL_RULE_ALLOW : FIREWALL_RULE_DENY; 837 assertEquals(testCase, expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID)); 838 } else { 839 final int expectedRule = BpfNetMapsUtils.isFirewallAllowList(chain) 840 ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW; 841 assertEquals(testCase, expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID)); 842 } 843 } 844 } 845 doTestGetUidRule(final int enableChain)846 private void doTestGetUidRule(final int enableChain) throws Exception { 847 doTestGetUidRule(List.of(enableChain)); 848 } 849 850 @Test 851 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testGetUidRule()852 public void testGetUidRule() throws Exception { 853 doTestGetUidRule(FIREWALL_CHAIN_DOZABLE); 854 doTestGetUidRule(FIREWALL_CHAIN_STANDBY); 855 doTestGetUidRule(FIREWALL_CHAIN_POWERSAVE); 856 doTestGetUidRule(FIREWALL_CHAIN_RESTRICTED); 857 doTestGetUidRule(FIREWALL_CHAIN_LOW_POWER_STANDBY); 858 doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_1); 859 doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_2); 860 doTestGetUidRule(FIREWALL_CHAIN_OEM_DENY_3); 861 } 862 863 @Test 864 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testGetUidRuleMultipleChainEnabled()865 public void testGetUidRuleMultipleChainEnabled() throws Exception { 866 doTestGetUidRule(List.of( 867 FIREWALL_CHAIN_DOZABLE, 868 FIREWALL_CHAIN_STANDBY)); 869 doTestGetUidRule(List.of( 870 FIREWALL_CHAIN_DOZABLE, 871 FIREWALL_CHAIN_STANDBY, 872 FIREWALL_CHAIN_POWERSAVE, 873 FIREWALL_CHAIN_RESTRICTED)); 874 doTestGetUidRule(FIREWALL_CHAINS); 875 } 876 877 @Test 878 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testGetUidRuleNoEntry()879 public void testGetUidRuleNoEntry() throws Exception { 880 mUidOwnerMap.clear(); 881 for (final int chain: FIREWALL_CHAINS) { 882 final int expectedRule = BpfNetMapsUtils.isFirewallAllowList(chain) 883 ? FIREWALL_RULE_DENY : FIREWALL_RULE_ALLOW; 884 assertEquals(expectedRule, mBpfNetMaps.getUidRule(chain, TEST_UID)); 885 } 886 } 887 888 @Test 889 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testGetUidRuleInvalidChain()890 public void testGetUidRuleInvalidChain() { 891 final Class<ServiceSpecificException> expected = ServiceSpecificException.class; 892 assertThrows(expected, () -> mBpfNetMaps.getUidRule(-1 /* childChain */, TEST_UID)); 893 assertThrows(expected, () -> mBpfNetMaps.getUidRule(1000 /* childChain */, TEST_UID)); 894 } 895 896 @Test 897 @IgnoreAfter(Build.VERSION_CODES.S_V2) testGetUidRuleBeforeT()898 public void testGetUidRuleBeforeT() { 899 assertThrows(UnsupportedOperationException.class, 900 () -> mBpfNetMaps.getUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID)); 901 } 902 903 @Test 904 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testReplaceUidChain()905 public void testReplaceUidChain() throws Exception { 906 final int uid0 = TEST_UIDS[0]; 907 final int uid1 = TEST_UIDS[1]; 908 909 mBpfNetMaps.replaceUidChain(FIREWALL_CHAIN_DOZABLE, TEST_UIDS); 910 911 checkUidOwnerValue(uid0, NO_IIF, DOZABLE_MATCH); 912 checkUidOwnerValue(uid1, NO_IIF, DOZABLE_MATCH); 913 } 914 915 @Test 916 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testReplaceUidChainWithOtherMatch()917 public void testReplaceUidChainWithOtherMatch() throws Exception { 918 final int uid0 = TEST_UIDS[0]; 919 final int uid1 = TEST_UIDS[1]; 920 final long match0 = POWERSAVE_MATCH; 921 final long match1 = POWERSAVE_MATCH | RESTRICTED_MATCH; 922 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(NO_IIF, match0)); 923 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(NO_IIF, match1)); 924 925 mBpfNetMaps.replaceUidChain(FIREWALL_CHAIN_DOZABLE, new int[]{uid1}); 926 927 checkUidOwnerValue(uid0, NO_IIF, match0); 928 checkUidOwnerValue(uid1, NO_IIF, match1 | DOZABLE_MATCH); 929 } 930 931 @Test 932 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testReplaceUidChainWithExistingIifMatch()933 public void testReplaceUidChainWithExistingIifMatch() throws Exception { 934 final int uid0 = TEST_UIDS[0]; 935 final int uid1 = TEST_UIDS[1]; 936 final long match0 = IIF_MATCH; 937 final long match1 = IIF_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH; 938 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(TEST_IF_INDEX, match0)); 939 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(NULL_IIF, match1)); 940 941 mBpfNetMaps.replaceUidChain(FIREWALL_CHAIN_DOZABLE, TEST_UIDS); 942 943 checkUidOwnerValue(uid0, TEST_IF_INDEX, match0 | DOZABLE_MATCH); 944 checkUidOwnerValue(uid1, NULL_IIF, match1 | DOZABLE_MATCH); 945 } 946 947 @Test 948 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testReplaceUidChainRemoveExistingMatch()949 public void testReplaceUidChainRemoveExistingMatch() throws Exception { 950 final int uid0 = TEST_UIDS[0]; 951 final int uid1 = TEST_UIDS[1]; 952 final long match0 = IIF_MATCH | DOZABLE_MATCH; 953 final long match1 = IIF_MATCH | POWERSAVE_MATCH | RESTRICTED_MATCH; 954 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(TEST_IF_INDEX, match0)); 955 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(NULL_IIF, match1)); 956 957 mBpfNetMaps.replaceUidChain(FIREWALL_CHAIN_DOZABLE, new int[]{uid1}); 958 959 checkUidOwnerValue(uid0, TEST_IF_INDEX, match0 & ~DOZABLE_MATCH); 960 checkUidOwnerValue(uid1, NULL_IIF, match1 | DOZABLE_MATCH); 961 } 962 963 @Test 964 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testReplaceUidChainInvalidChain()965 public void testReplaceUidChainInvalidChain() { 966 final Class<IllegalArgumentException> expected = IllegalArgumentException.class; 967 assertThrows(expected, () -> mBpfNetMaps.replaceUidChain(-1 /* chain */, TEST_UIDS)); 968 assertThrows(expected, () -> mBpfNetMaps.replaceUidChain(1000 /* chain */, TEST_UIDS)); 969 } 970 971 @Test 972 @IgnoreAfter(Build.VERSION_CODES.S_V2) testReplaceUidChainBeforeT()973 public void testReplaceUidChainBeforeT() { 974 assertThrows(UnsupportedOperationException.class, 975 () -> mBpfNetMaps.replaceUidChain(FIREWALL_CHAIN_DOZABLE, TEST_UIDS)); 976 } 977 978 @Test 979 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsGrantInternetPermission()980 public void testSetNetPermForUidsGrantInternetPermission() throws Exception { 981 mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET, TEST_UIDS); 982 983 assertTrue(mUidPermissionMap.isEmpty()); 984 } 985 986 @Test 987 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsGrantUpdateStatsPermission()988 public void testSetNetPermForUidsGrantUpdateStatsPermission() throws Exception { 989 mBpfNetMaps.setNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, TEST_UIDS); 990 991 final int uid0 = TEST_UIDS[0]; 992 final int uid1 = TEST_UIDS[1]; 993 assertEquals(PERMISSION_UPDATE_DEVICE_STATS, mUidPermissionMap.getValue(new S32(uid0)).val); 994 assertEquals(PERMISSION_UPDATE_DEVICE_STATS, mUidPermissionMap.getValue(new S32(uid1)).val); 995 } 996 997 @Test 998 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsGrantMultiplePermissions()999 public void testSetNetPermForUidsGrantMultiplePermissions() throws Exception { 1000 final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS; 1001 mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS); 1002 1003 final int uid0 = TEST_UIDS[0]; 1004 final int uid1 = TEST_UIDS[1]; 1005 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid0)).val); 1006 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid1)).val); 1007 } 1008 1009 @Test 1010 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsRevokeInternetPermission()1011 public void testSetNetPermForUidsRevokeInternetPermission() throws Exception { 1012 final int uid0 = TEST_UIDS[0]; 1013 final int uid1 = TEST_UIDS[1]; 1014 mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET, TEST_UIDS); 1015 mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, new int[]{uid0}); 1016 1017 assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new S32(uid0)).val); 1018 assertNull(mUidPermissionMap.getValue(new S32(uid1))); 1019 } 1020 1021 @Test 1022 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsRevokeUpdateDeviceStatsPermission()1023 public void testSetNetPermForUidsRevokeUpdateDeviceStatsPermission() throws Exception { 1024 final int uid0 = TEST_UIDS[0]; 1025 final int uid1 = TEST_UIDS[1]; 1026 mBpfNetMaps.setNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, TEST_UIDS); 1027 mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, new int[]{uid0}); 1028 1029 assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new S32(uid0)).val); 1030 assertEquals(PERMISSION_UPDATE_DEVICE_STATS, mUidPermissionMap.getValue(new S32(uid1)).val); 1031 } 1032 1033 @Test 1034 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsRevokeMultiplePermissions()1035 public void testSetNetPermForUidsRevokeMultiplePermissions() throws Exception { 1036 final int uid0 = TEST_UIDS[0]; 1037 final int uid1 = TEST_UIDS[1]; 1038 final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS; 1039 mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS); 1040 mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, new int[]{uid0}); 1041 1042 assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new S32(uid0)).val); 1043 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid1)).val); 1044 } 1045 1046 @Test 1047 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsPermissionUninstalled()1048 public void testSetNetPermForUidsPermissionUninstalled() throws Exception { 1049 final int uid0 = TEST_UIDS[0]; 1050 final int uid1 = TEST_UIDS[1]; 1051 final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS; 1052 mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS); 1053 mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED, new int[]{uid0}); 1054 1055 assertNull(mUidPermissionMap.getValue(new S32(uid0))); 1056 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid1)).val); 1057 } 1058 1059 @Test 1060 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetNetPermForUidsDuplicatedRequestSilentlyIgnored()1061 public void testSetNetPermForUidsDuplicatedRequestSilentlyIgnored() throws Exception { 1062 final int uid0 = TEST_UIDS[0]; 1063 final int uid1 = TEST_UIDS[1]; 1064 final int permission = PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS; 1065 1066 mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS); 1067 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid0)).val); 1068 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid1)).val); 1069 1070 mBpfNetMaps.setNetPermForUids(permission, TEST_UIDS); 1071 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid0)).val); 1072 assertEquals(permission, mUidPermissionMap.getValue(new S32(uid1)).val); 1073 1074 mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, TEST_UIDS); 1075 assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new S32(uid0)).val); 1076 assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new S32(uid1)).val); 1077 1078 mBpfNetMaps.setNetPermForUids(PERMISSION_NONE, TEST_UIDS); 1079 assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new S32(uid0)).val); 1080 assertEquals(PERMISSION_NONE, mUidPermissionMap.getValue(new S32(uid1)).val); 1081 1082 mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED, TEST_UIDS); 1083 assertNull(mUidPermissionMap.getValue(new S32(uid0))); 1084 assertNull(mUidPermissionMap.getValue(new S32(uid1))); 1085 1086 mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED, TEST_UIDS); 1087 assertNull(mUidPermissionMap.getValue(new S32(uid0))); 1088 assertNull(mUidPermissionMap.getValue(new S32(uid1))); 1089 } 1090 1091 @Test 1092 @IgnoreUpTo(Build.VERSION_CODES.TIRAMISU) testGetNetPermFoUid()1093 public void testGetNetPermFoUid() throws Exception { 1094 mUidPermissionMap.deleteEntry(new S32(TEST_UID)); 1095 assertEquals(PERMISSION_INTERNET, mBpfNetMaps.getNetPermForUid(TEST_UID)); 1096 1097 mUidPermissionMap.updateEntry(new S32(TEST_UID), new U8((short) PERMISSION_NONE)); 1098 assertEquals(PERMISSION_NONE, mBpfNetMaps.getNetPermForUid(TEST_UID)); 1099 1100 mUidPermissionMap.updateEntry(new S32(TEST_UID), 1101 new U8((short) (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS))); 1102 assertEquals(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, 1103 mBpfNetMaps.getNetPermForUid(TEST_UID)); 1104 } 1105 1106 @Test 1107 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSwapActiveStatsMap()1108 public void testSwapActiveStatsMap() throws Exception { 1109 mConfigurationMap.updateEntry( 1110 CURRENT_STATS_MAP_CONFIGURATION_KEY, new U32(STATS_SELECT_MAP_A)); 1111 1112 mBpfNetMaps.swapActiveStatsMap(); 1113 assertEquals(STATS_SELECT_MAP_B, 1114 mConfigurationMap.getValue(CURRENT_STATS_MAP_CONFIGURATION_KEY).val); 1115 1116 mBpfNetMaps.swapActiveStatsMap(); 1117 assertEquals(STATS_SELECT_MAP_A, 1118 mConfigurationMap.getValue(CURRENT_STATS_MAP_CONFIGURATION_KEY).val); 1119 } 1120 1121 @Test 1122 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSwapActiveStatsMapSynchronizeKernelRCUFail()1123 public void testSwapActiveStatsMapSynchronizeKernelRCUFail() throws Exception { 1124 doReturn(EPERM).when(mDeps).synchronizeKernelRCU(); 1125 mConfigurationMap.updateEntry( 1126 CURRENT_STATS_MAP_CONFIGURATION_KEY, new U32(STATS_SELECT_MAP_A)); 1127 1128 assertThrows(ServiceSpecificException.class, () -> mBpfNetMaps.swapActiveStatsMap()); 1129 } 1130 1131 @Test 1132 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testPullBpfMapInfo()1133 public void testPullBpfMapInfo() throws Exception { 1134 // mCookieTagMap has 1 entry 1135 mCookieTagMap.updateEntry(new CookieTagMapKey(0), new CookieTagMapValue(0, 0)); 1136 1137 // mUidOwnerMap has 2 entries 1138 mUidOwnerMap.updateEntry(new S32(0), new UidOwnerValue(0, 0)); 1139 mUidOwnerMap.updateEntry(new S32(1), new UidOwnerValue(0, 0)); 1140 1141 // mUidPermissionMap has 3 entries 1142 mUidPermissionMap.updateEntry(new S32(0), new U8((short) 0)); 1143 mUidPermissionMap.updateEntry(new S32(1), new U8((short) 0)); 1144 mUidPermissionMap.updateEntry(new S32(2), new U8((short) 0)); 1145 1146 final int ret = mBpfNetMaps.pullBpfMapInfoAtom(NETWORK_BPF_MAP_INFO, new ArrayList<>()); 1147 assertEquals(StatsManager.PULL_SUCCESS, ret); 1148 verify(mDeps).buildStatsEvent( 1149 1 /* cookieTagMapSize */, 2 /* uidOwnerMapSize */, 3 /* uidPermissionMapSize */); 1150 } 1151 1152 @Test 1153 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testPullBpfMapInfoGetMapSizeFailure()1154 public void testPullBpfMapInfoGetMapSizeFailure() throws Exception { 1155 doThrow(new ErrnoException("", EINVAL)).when(mCookieTagMap).forEach(any()); 1156 final int ret = mBpfNetMaps.pullBpfMapInfoAtom(NETWORK_BPF_MAP_INFO, new ArrayList<>()); 1157 assertEquals(StatsManager.PULL_SKIP, ret); 1158 } 1159 1160 @Test 1161 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testPullBpfMapInfoUnexpectedAtomTag()1162 public void testPullBpfMapInfoUnexpectedAtomTag() { 1163 final int ret = mBpfNetMaps.pullBpfMapInfoAtom(-1 /* atomTag */, new ArrayList<>()); 1164 assertEquals(StatsManager.PULL_SKIP, ret); 1165 } 1166 assertDumpContains(final String dump, final String message)1167 private void assertDumpContains(final String dump, final String message) { 1168 assertTrue(String.format("dump(%s) does not contain '%s'", dump, message), 1169 dump.contains(message)); 1170 } 1171 getDump()1172 private String getDump() throws Exception { 1173 final StringWriter sw = new StringWriter(); 1174 mBpfNetMaps.dump(new IndentingPrintWriter(sw), new FileDescriptor(), true /* verbose */); 1175 return sw.toString(); 1176 } 1177 doTestDumpUidPermissionMap(final int permission, final String permissionString)1178 private void doTestDumpUidPermissionMap(final int permission, final String permissionString) 1179 throws Exception { 1180 mUidPermissionMap.updateEntry(new S32(TEST_UID), new U8((short) permission)); 1181 assertDumpContains(getDump(), TEST_UID + " " + permissionString); 1182 } 1183 1184 @Test 1185 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpUidPermissionMap()1186 public void testDumpUidPermissionMap() throws Exception { 1187 doTestDumpUidPermissionMap(PERMISSION_NONE, "PERMISSION_NONE"); 1188 doTestDumpUidPermissionMap(PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, 1189 "PERMISSION_INTERNET PERMISSION_UPDATE_DEVICE_STATS"); 1190 } 1191 1192 @Test 1193 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpUidPermissionMapInvalidPermission()1194 public void testDumpUidPermissionMapInvalidPermission() throws Exception { 1195 doTestDumpUidPermissionMap(PERMISSION_UNINSTALLED, "PERMISSION_UNINSTALLED error!"); 1196 doTestDumpUidPermissionMap(PERMISSION_INTERNET | 1 << 6, 1197 "PERMISSION_INTERNET PERMISSION_UNKNOWN(64)"); 1198 } 1199 doTestDumpUidOwnerMap(final int iif, final long match, final String matchString)1200 void doTestDumpUidOwnerMap(final int iif, final long match, final String matchString) 1201 throws Exception { 1202 mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(iif, match)); 1203 assertDumpContains(getDump(), TEST_UID + " " + matchString); 1204 } 1205 doTestDumpUidOwnerMap(final long match, final String matchString)1206 void doTestDumpUidOwnerMap(final long match, final String matchString) throws Exception { 1207 doTestDumpUidOwnerMap(0 /* iif */, match, matchString); 1208 } 1209 1210 @Test 1211 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpUidOwnerMap()1212 public void testDumpUidOwnerMap() throws Exception { 1213 doTestDumpUidOwnerMap(HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH"); 1214 doTestDumpUidOwnerMap(PENALTY_BOX_USER_MATCH, "PENALTY_BOX_USER_MATCH"); 1215 doTestDumpUidOwnerMap(DOZABLE_MATCH, "DOZABLE_MATCH"); 1216 doTestDumpUidOwnerMap(STANDBY_MATCH, "STANDBY_MATCH"); 1217 doTestDumpUidOwnerMap(POWERSAVE_MATCH, "POWERSAVE_MATCH"); 1218 doTestDumpUidOwnerMap(RESTRICTED_MATCH, "RESTRICTED_MATCH"); 1219 doTestDumpUidOwnerMap(LOW_POWER_STANDBY_MATCH, "LOW_POWER_STANDBY_MATCH"); 1220 doTestDumpUidOwnerMap(LOCKDOWN_VPN_MATCH, "LOCKDOWN_VPN_MATCH"); 1221 doTestDumpUidOwnerMap(OEM_DENY_1_MATCH, "OEM_DENY_1_MATCH"); 1222 doTestDumpUidOwnerMap(OEM_DENY_2_MATCH, "OEM_DENY_2_MATCH"); 1223 doTestDumpUidOwnerMap(OEM_DENY_3_MATCH, "OEM_DENY_3_MATCH"); 1224 doTestDumpUidOwnerMap(PENALTY_BOX_ADMIN_MATCH, "PENALTY_BOX_ADMIN_MATCH"); 1225 1226 doTestDumpUidOwnerMap(HAPPY_BOX_MATCH | POWERSAVE_MATCH, 1227 "HAPPY_BOX_MATCH POWERSAVE_MATCH"); 1228 doTestDumpUidOwnerMap(DOZABLE_MATCH | LOCKDOWN_VPN_MATCH | OEM_DENY_1_MATCH, 1229 "DOZABLE_MATCH LOCKDOWN_VPN_MATCH OEM_DENY_1_MATCH"); 1230 } 1231 1232 @Test 1233 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpUidOwnerMapWithIifMatch()1234 public void testDumpUidOwnerMapWithIifMatch() throws Exception { 1235 doTestDumpUidOwnerMap(TEST_IF_INDEX, IIF_MATCH, "IIF_MATCH " + TEST_IF_INDEX); 1236 doTestDumpUidOwnerMap(TEST_IF_INDEX, 1237 IIF_MATCH | DOZABLE_MATCH | LOCKDOWN_VPN_MATCH | OEM_DENY_1_MATCH, 1238 "DOZABLE_MATCH IIF_MATCH LOCKDOWN_VPN_MATCH OEM_DENY_1_MATCH " + TEST_IF_INDEX); 1239 } 1240 1241 @Test 1242 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpUidOwnerMapWithInvalidMatch()1243 public void testDumpUidOwnerMapWithInvalidMatch() throws Exception { 1244 final long invalid_match = 1L << 31; 1245 doTestDumpUidOwnerMap(invalid_match, "UNKNOWN_MATCH(" + invalid_match + ")"); 1246 doTestDumpUidOwnerMap(DOZABLE_MATCH | invalid_match, 1247 "DOZABLE_MATCH UNKNOWN_MATCH(" + invalid_match + ")"); 1248 } 1249 1250 @Test 1251 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpCurrentStatsMapConfig()1252 public void testDumpCurrentStatsMapConfig() throws Exception { 1253 mConfigurationMap.updateEntry( 1254 CURRENT_STATS_MAP_CONFIGURATION_KEY, new U32(STATS_SELECT_MAP_A)); 1255 assertDumpContains(getDump(), "current statsMap configuration: 0 SELECT_MAP_A"); 1256 1257 mConfigurationMap.updateEntry( 1258 CURRENT_STATS_MAP_CONFIGURATION_KEY, new U32(STATS_SELECT_MAP_B)); 1259 assertDumpContains(getDump(), "current statsMap configuration: 1 SELECT_MAP_B"); 1260 } 1261 doTestDumpOwnerMatchConfig(final long match, final String matchString)1262 private void doTestDumpOwnerMatchConfig(final long match, final String matchString) 1263 throws Exception { 1264 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(match)); 1265 assertDumpContains(getDump(), 1266 "current ownerMatch configuration: " + match + " " + matchString); 1267 } 1268 1269 @Test 1270 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpUidOwnerMapConfig()1271 public void testDumpUidOwnerMapConfig() throws Exception { 1272 doTestDumpOwnerMatchConfig(HAPPY_BOX_MATCH, "HAPPY_BOX_MATCH"); 1273 doTestDumpOwnerMatchConfig(DOZABLE_MATCH, "DOZABLE_MATCH"); 1274 doTestDumpOwnerMatchConfig(STANDBY_MATCH, "STANDBY_MATCH"); 1275 doTestDumpOwnerMatchConfig(POWERSAVE_MATCH, "POWERSAVE_MATCH"); 1276 doTestDumpOwnerMatchConfig(RESTRICTED_MATCH, "RESTRICTED_MATCH"); 1277 doTestDumpOwnerMatchConfig(LOW_POWER_STANDBY_MATCH, "LOW_POWER_STANDBY_MATCH"); 1278 doTestDumpOwnerMatchConfig(IIF_MATCH, "IIF_MATCH"); 1279 doTestDumpOwnerMatchConfig(LOCKDOWN_VPN_MATCH, "LOCKDOWN_VPN_MATCH"); 1280 doTestDumpOwnerMatchConfig(OEM_DENY_1_MATCH, "OEM_DENY_1_MATCH"); 1281 doTestDumpOwnerMatchConfig(OEM_DENY_2_MATCH, "OEM_DENY_2_MATCH"); 1282 doTestDumpOwnerMatchConfig(OEM_DENY_3_MATCH, "OEM_DENY_3_MATCH"); 1283 1284 doTestDumpOwnerMatchConfig(HAPPY_BOX_MATCH | POWERSAVE_MATCH, 1285 "HAPPY_BOX_MATCH POWERSAVE_MATCH"); 1286 doTestDumpOwnerMatchConfig(DOZABLE_MATCH | LOCKDOWN_VPN_MATCH | OEM_DENY_1_MATCH, 1287 "DOZABLE_MATCH LOCKDOWN_VPN_MATCH OEM_DENY_1_MATCH"); 1288 } 1289 1290 @Test 1291 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpUidOwnerMapConfigWithInvalidMatch()1292 public void testDumpUidOwnerMapConfigWithInvalidMatch() throws Exception { 1293 final long invalid_match = 1L << 31; 1294 doTestDumpOwnerMatchConfig(invalid_match, "UNKNOWN_MATCH(" + invalid_match + ")"); 1295 doTestDumpOwnerMatchConfig(DOZABLE_MATCH | invalid_match, 1296 "DOZABLE_MATCH UNKNOWN_MATCH(" + invalid_match + ")"); 1297 } 1298 1299 @Test 1300 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpCookieTagMap()1301 public void testDumpCookieTagMap() throws Exception { 1302 mCookieTagMap.updateEntry(new CookieTagMapKey(123), new CookieTagMapValue(456, 0x789)); 1303 assertDumpContains(getDump(), "cookie=123 tag=0x789 uid=456"); 1304 } 1305 doTestDumpDataSaverConfig(final short value, final boolean expected)1306 private void doTestDumpDataSaverConfig(final short value, final boolean expected) 1307 throws Exception { 1308 mDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(value)); 1309 assertDumpContains(getDump(), 1310 "sDataSaverEnabledMap: " + expected); 1311 } 1312 1313 @Test 1314 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpDataSaverConfig()1315 public void testDumpDataSaverConfig() throws Exception { 1316 doTestDumpDataSaverConfig(DATA_SAVER_DISABLED, false); 1317 doTestDumpDataSaverConfig(DATA_SAVER_ENABLED, true); 1318 doTestDumpDataSaverConfig((short) 2, true); 1319 } 1320 1321 @Test testGetUids()1322 public void testGetUids() throws ErrnoException { 1323 final int uid0 = TEST_UIDS[0]; 1324 final int uid1 = TEST_UIDS[1]; 1325 final long match0 = DOZABLE_MATCH | POWERSAVE_MATCH; 1326 final long match1 = DOZABLE_MATCH | STANDBY_MATCH; 1327 mUidOwnerMap.updateEntry(new S32(uid0), new UidOwnerValue(NULL_IIF, match0)); 1328 mUidOwnerMap.updateEntry(new S32(uid1), new UidOwnerValue(NULL_IIF, match1)); 1329 1330 assertEquals(new ArraySet<>(List.of(uid0, uid1)), 1331 mBpfNetMaps.getUidsWithAllowRuleOnAllowListChain(FIREWALL_CHAIN_DOZABLE)); 1332 assertEquals(new ArraySet<>(List.of(uid0)), 1333 mBpfNetMaps.getUidsWithAllowRuleOnAllowListChain(FIREWALL_CHAIN_POWERSAVE)); 1334 1335 assertEquals(new ArraySet<>(List.of(uid1)), 1336 mBpfNetMaps.getUidsWithDenyRuleOnDenyListChain(FIREWALL_CHAIN_STANDBY)); 1337 assertEquals(new ArraySet<>(), 1338 mBpfNetMaps.getUidsWithDenyRuleOnDenyListChain(FIREWALL_CHAIN_OEM_DENY_1)); 1339 } 1340 1341 @Test testGetUidsIllegalArgument()1342 public void testGetUidsIllegalArgument() { 1343 final Class<IllegalArgumentException> expected = IllegalArgumentException.class; 1344 assertThrows(expected, 1345 () -> mBpfNetMaps.getUidsWithDenyRuleOnDenyListChain(FIREWALL_CHAIN_DOZABLE)); 1346 assertThrows(expected, 1347 () -> mBpfNetMaps.getUidsWithAllowRuleOnAllowListChain(FIREWALL_CHAIN_OEM_DENY_1)); 1348 } 1349 1350 @Test 1351 @IgnoreAfter(Build.VERSION_CODES.S_V2) testSetDataSaverEnabledBeforeT()1352 public void testSetDataSaverEnabledBeforeT() { 1353 for (boolean enable : new boolean[]{true, false}) { 1354 assertThrows(UnsupportedOperationException.class, 1355 () -> mBpfNetMaps.setDataSaverEnabled(enable)); 1356 } 1357 } 1358 1359 @Test 1360 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetDataSaverEnabled()1361 public void testSetDataSaverEnabled() throws Exception { 1362 for (boolean enable : new boolean[]{true, false}) { 1363 mBpfNetMaps.setDataSaverEnabled(enable); 1364 assertEquals(enable ? DATA_SAVER_ENABLED : DATA_SAVER_DISABLED, 1365 mDataSaverEnabledMap.getValue(DATA_SAVER_ENABLED_KEY).val); 1366 } 1367 } 1368 1369 @Test 1370 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetIngressDiscardRule_V4address()1371 public void testSetIngressDiscardRule_V4address() throws Exception { 1372 mBpfNetMaps.setIngressDiscardRule(TEST_V4_ADDRESS, TEST_IF_NAME); 1373 final IngressDiscardValue val = mIngressDiscardMap.getValue(new IngressDiscardKey( 1374 TEST_V4_ADDRESS)); 1375 assertEquals(TEST_IF_INDEX, val.iif1); 1376 assertEquals(TEST_IF_INDEX, val.iif2); 1377 } 1378 1379 @Test 1380 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testSetIngressDiscardRule_V6address()1381 public void testSetIngressDiscardRule_V6address() throws Exception { 1382 mBpfNetMaps.setIngressDiscardRule(TEST_V6_ADDRESS, TEST_IF_NAME); 1383 final IngressDiscardValue val = 1384 mIngressDiscardMap.getValue(new IngressDiscardKey(TEST_V6_ADDRESS)); 1385 assertEquals(TEST_IF_INDEX, val.iif1); 1386 assertEquals(TEST_IF_INDEX, val.iif2); 1387 } 1388 1389 @Test 1390 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testRemoveIngressDiscardRule()1391 public void testRemoveIngressDiscardRule() throws Exception { 1392 mBpfNetMaps.setIngressDiscardRule(TEST_V4_ADDRESS, TEST_IF_NAME); 1393 mBpfNetMaps.setIngressDiscardRule(TEST_V6_ADDRESS, TEST_IF_NAME); 1394 final IngressDiscardKey v4Key = new IngressDiscardKey(TEST_V4_ADDRESS); 1395 final IngressDiscardKey v6Key = new IngressDiscardKey(TEST_V6_ADDRESS); 1396 assertTrue(mIngressDiscardMap.containsKey(v4Key)); 1397 assertTrue(mIngressDiscardMap.containsKey(v6Key)); 1398 1399 mBpfNetMaps.removeIngressDiscardRule(TEST_V4_ADDRESS); 1400 assertFalse(mIngressDiscardMap.containsKey(v4Key)); 1401 assertTrue(mIngressDiscardMap.containsKey(v6Key)); 1402 1403 mBpfNetMaps.removeIngressDiscardRule(TEST_V6_ADDRESS); 1404 assertFalse(mIngressDiscardMap.containsKey(v4Key)); 1405 assertFalse(mIngressDiscardMap.containsKey(v6Key)); 1406 } 1407 1408 @Test 1409 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testDumpIngressDiscardRule()1410 public void testDumpIngressDiscardRule() throws Exception { 1411 mBpfNetMaps.setIngressDiscardRule(TEST_V4_ADDRESS, TEST_IF_NAME); 1412 mBpfNetMaps.setIngressDiscardRule(TEST_V6_ADDRESS, TEST_IF_NAME); 1413 final String dump = getDump(); 1414 assertDumpContains(dump, TEST_V4_ADDRESS.getHostAddress()); 1415 assertDumpContains(dump, TEST_V6_ADDRESS.getHostAddress()); 1416 assertDumpContains(dump, TEST_IF_INDEX + "(" + TEST_IF_NAME + ")"); 1417 } 1418 doTestGetUidNetworkingBlockedReasons( final long configurationMatches, final long uidRules, final short dataSaverStatus, final int expectedBlockedReasons )1419 private void doTestGetUidNetworkingBlockedReasons( 1420 final long configurationMatches, 1421 final long uidRules, 1422 final short dataSaverStatus, 1423 final int expectedBlockedReasons 1424 ) throws Exception { 1425 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(configurationMatches)); 1426 mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(NULL_IIF, uidRules)); 1427 mDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(dataSaverStatus)); 1428 1429 assertEquals(expectedBlockedReasons, mBpfNetMaps.getUidNetworkingBlockedReasons(TEST_UID)); 1430 } 1431 1432 @Test 1433 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testGetUidNetworkingBlockedReasons()1434 public void testGetUidNetworkingBlockedReasons() throws Exception { 1435 doTestGetUidNetworkingBlockedReasons( 1436 NO_MATCH, 1437 NO_MATCH, 1438 DATA_SAVER_DISABLED, 1439 BLOCKED_REASON_NONE 1440 ); 1441 doTestGetUidNetworkingBlockedReasons( 1442 DOZABLE_MATCH, 1443 NO_MATCH, 1444 DATA_SAVER_DISABLED, 1445 BLOCKED_REASON_DOZE 1446 ); 1447 doTestGetUidNetworkingBlockedReasons( 1448 DOZABLE_MATCH | POWERSAVE_MATCH | STANDBY_MATCH, 1449 DOZABLE_MATCH | STANDBY_MATCH, 1450 DATA_SAVER_DISABLED, 1451 BLOCKED_REASON_BATTERY_SAVER | BLOCKED_REASON_APP_STANDBY 1452 ); 1453 doTestGetUidNetworkingBlockedReasons( 1454 OEM_DENY_1_MATCH | OEM_DENY_2_MATCH | OEM_DENY_3_MATCH, 1455 OEM_DENY_1_MATCH | OEM_DENY_3_MATCH, 1456 DATA_SAVER_DISABLED, 1457 BLOCKED_REASON_OEM_DENY 1458 ); 1459 doTestGetUidNetworkingBlockedReasons( 1460 DOZABLE_MATCH, 1461 DOZABLE_MATCH | BACKGROUND_MATCH | STANDBY_MATCH, 1462 DATA_SAVER_DISABLED, 1463 BLOCKED_REASON_NONE 1464 ); 1465 1466 // Note that HAPPY_BOX and PENALTY_BOX are not disabled by configuration map 1467 doTestGetUidNetworkingBlockedReasons( 1468 NO_MATCH, 1469 PENALTY_BOX_USER_MATCH, 1470 DATA_SAVER_DISABLED, 1471 BLOCKED_METERED_REASON_USER_RESTRICTED 1472 ); 1473 doTestGetUidNetworkingBlockedReasons( 1474 NO_MATCH, 1475 PENALTY_BOX_ADMIN_MATCH, 1476 DATA_SAVER_ENABLED, 1477 BLOCKED_METERED_REASON_ADMIN_DISABLED | BLOCKED_METERED_REASON_DATA_SAVER 1478 ); 1479 doTestGetUidNetworkingBlockedReasons( 1480 NO_MATCH, 1481 PENALTY_BOX_USER_MATCH | PENALTY_BOX_ADMIN_MATCH | HAPPY_BOX_MATCH, 1482 DATA_SAVER_ENABLED, 1483 BLOCKED_METERED_REASON_USER_RESTRICTED | BLOCKED_METERED_REASON_ADMIN_DISABLED 1484 ); 1485 doTestGetUidNetworkingBlockedReasons( 1486 STANDBY_MATCH, 1487 STANDBY_MATCH | PENALTY_BOX_USER_MATCH | HAPPY_BOX_MATCH, 1488 DATA_SAVER_ENABLED, 1489 BLOCKED_REASON_APP_STANDBY | BLOCKED_METERED_REASON_USER_RESTRICTED 1490 ); 1491 } 1492 1493 @Test 1494 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testIsUidNetworkingBlockedForCoreUids()1495 public void testIsUidNetworkingBlockedForCoreUids() throws Exception { 1496 final long allowlistMatch = BACKGROUND_MATCH; // Enable any allowlist match. 1497 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(allowlistMatch)); 1498 1499 // Verify that a normal uid that is not on this chain is indeed blocked. 1500 assertTrue(BpfNetMapsUtils.isUidNetworkingBlocked(TEST_UID, false, mConfigurationMap, 1501 mUidOwnerMap, mDataSaverEnabledMap)); 1502 1503 // Core appIds are not on the chain but should still be allowed on any user. 1504 for (int userId = 0; userId < 20; userId++) { 1505 for (final int aid : CORE_AIDS) { 1506 final int uid = UserHandle.getUid(userId, aid); 1507 assertFalse(BpfNetMapsUtils.isUidNetworkingBlocked(uid, false, mConfigurationMap, 1508 mUidOwnerMap, mDataSaverEnabledMap)); 1509 } 1510 } 1511 } 1512 1513 @Test 1514 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testGetUidNetworkingBlockedReasonsForCoreUids()1515 public void testGetUidNetworkingBlockedReasonsForCoreUids() throws Exception { 1516 // Enable BACKGROUND_MATCH that is an allowlist match. 1517 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(BACKGROUND_MATCH)); 1518 1519 // Non-core uid that is not on this chain is blocked by BLOCKED_REASON_APP_BACKGROUND. 1520 assertEquals(BLOCKED_REASON_APP_BACKGROUND, BpfNetMapsUtils.getUidNetworkingBlockedReasons( 1521 TEST_UID, mConfigurationMap, mUidOwnerMap, mDataSaverEnabledMap)); 1522 1523 // Core appIds are not on the chain but should not be blocked on any users. 1524 for (int userId = 0; userId < 20; userId++) { 1525 for (final int aid : CORE_AIDS) { 1526 final int uid = UserHandle.getUid(userId, aid); 1527 assertEquals(BLOCKED_REASON_NONE, BpfNetMapsUtils.getUidNetworkingBlockedReasons( 1528 uid, mConfigurationMap, mUidOwnerMap, mDataSaverEnabledMap)); 1529 } 1530 } 1531 } 1532 doTestIsUidRestrictedOnMeteredNetworks( final long enabledMatches, final long uidRules, final short dataSaver, final boolean expectedRestricted )1533 private void doTestIsUidRestrictedOnMeteredNetworks( 1534 final long enabledMatches, 1535 final long uidRules, 1536 final short dataSaver, 1537 final boolean expectedRestricted 1538 ) throws Exception { 1539 mConfigurationMap.updateEntry(UID_RULES_CONFIGURATION_KEY, new U32(enabledMatches)); 1540 mUidOwnerMap.updateEntry(new S32(TEST_UID), new UidOwnerValue(NULL_IIF, uidRules)); 1541 mDataSaverEnabledMap.updateEntry(DATA_SAVER_ENABLED_KEY, new U8(dataSaver)); 1542 1543 assertEquals(expectedRestricted, mBpfNetMaps.isUidRestrictedOnMeteredNetworks(TEST_UID)); 1544 } 1545 1546 @Test 1547 @IgnoreUpTo(Build.VERSION_CODES.S_V2) testIsUidRestrictedOnMeteredNetworks()1548 public void testIsUidRestrictedOnMeteredNetworks() throws Exception { 1549 doTestIsUidRestrictedOnMeteredNetworks( 1550 NO_MATCH, 1551 NO_MATCH, 1552 DATA_SAVER_DISABLED, 1553 false /* expectRestricted */ 1554 ); 1555 doTestIsUidRestrictedOnMeteredNetworks( 1556 DOZABLE_MATCH | POWERSAVE_MATCH | STANDBY_MATCH, 1557 DOZABLE_MATCH | STANDBY_MATCH , 1558 DATA_SAVER_DISABLED, 1559 false /* expectRestricted */ 1560 ); 1561 doTestIsUidRestrictedOnMeteredNetworks( 1562 NO_MATCH, 1563 PENALTY_BOX_USER_MATCH, 1564 DATA_SAVER_DISABLED, 1565 true /* expectRestricted */ 1566 ); 1567 doTestIsUidRestrictedOnMeteredNetworks( 1568 NO_MATCH, 1569 PENALTY_BOX_ADMIN_MATCH, 1570 DATA_SAVER_DISABLED, 1571 true /* expectRestricted */ 1572 ); 1573 doTestIsUidRestrictedOnMeteredNetworks( 1574 NO_MATCH, 1575 PENALTY_BOX_USER_MATCH | PENALTY_BOX_ADMIN_MATCH | HAPPY_BOX_MATCH, 1576 DATA_SAVER_DISABLED, 1577 true /* expectRestricted */ 1578 ); 1579 doTestIsUidRestrictedOnMeteredNetworks( 1580 NO_MATCH, 1581 NO_MATCH, 1582 DATA_SAVER_ENABLED, 1583 true /* expectRestricted */ 1584 ); 1585 doTestIsUidRestrictedOnMeteredNetworks( 1586 NO_MATCH, 1587 HAPPY_BOX_MATCH, 1588 DATA_SAVER_ENABLED, 1589 false /* expectRestricted */ 1590 ); 1591 } 1592 } 1593