Merge changes Ic6ff7a3d,Iff9b9792
* changes: Refactor code and improve tests for VPN filtering Remove LOCKDOWN from FirewallChain IntDef
This commit is contained in:
@@ -52,7 +52,6 @@ import static android.net.ConnectivityManager.CONNECTIVITY_ACTION;
|
||||
import static android.net.ConnectivityManager.EXTRA_NETWORK_INFO;
|
||||
import static android.net.ConnectivityManager.EXTRA_NETWORK_TYPE;
|
||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_DOZABLE;
|
||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOCKDOWN_VPN;
|
||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOW_POWER_STANDBY;
|
||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_1;
|
||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_OEM_DENY_2;
|
||||
@@ -9516,38 +9515,28 @@ public class ConnectivityServiceTest {
|
||||
|
||||
@Test @IgnoreUpTo(Build.VERSION_CODES.S_V2)
|
||||
public void testLockdownSetFirewallUidRule() throws Exception {
|
||||
// For ConnectivityService#setAlwaysOnVpnPackage.
|
||||
mServiceContext.setPermission(
|
||||
Manifest.permission.CONTROL_ALWAYS_ON_VPN, PERMISSION_GRANTED);
|
||||
// Needed to call Vpn#setAlwaysOnPackage.
|
||||
mServiceContext.setPermission(Manifest.permission.CONTROL_VPN, PERMISSION_GRANTED);
|
||||
// Needed to call Vpn#isAlwaysOnPackageSupported.
|
||||
mServiceContext.setPermission(NETWORK_SETTINGS, PERMISSION_GRANTED);
|
||||
|
||||
final Set<Range<Integer>> lockdownRange = UidRange.toIntRanges(Set.of(PRIMARY_UIDRANGE));
|
||||
// Enable Lockdown
|
||||
final ArrayList<String> allowList = new ArrayList<>();
|
||||
mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, ALWAYS_ON_PACKAGE,
|
||||
true /* lockdown */, allowList);
|
||||
mCm.setRequireVpnForUids(true /* requireVpn */, lockdownRange);
|
||||
waitForIdle();
|
||||
|
||||
// Lockdown rule is set to apps uids
|
||||
verify(mBpfNetMaps).setUidRule(
|
||||
eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP1_UID), eq(FIREWALL_RULE_DENY));
|
||||
verify(mBpfNetMaps).setUidRule(
|
||||
eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP2_UID), eq(FIREWALL_RULE_DENY));
|
||||
verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, true /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, true /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, true /* add */);
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Disable lockdown
|
||||
mVpnManagerService.setAlwaysOnVpnPackage(PRIMARY_USER, null, false /* lockdown */,
|
||||
allowList);
|
||||
mCm.setRequireVpnForUids(false /* requireVPN */, lockdownRange);
|
||||
waitForIdle();
|
||||
|
||||
// Lockdown rule is removed from apps uids
|
||||
verify(mBpfNetMaps).setUidRule(
|
||||
eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP1_UID), eq(FIREWALL_RULE_ALLOW));
|
||||
verify(mBpfNetMaps).setUidRule(
|
||||
eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(APP2_UID), eq(FIREWALL_RULE_ALLOW));
|
||||
verify(mBpfNetMaps, times(3)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(APP1_UID, false /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(APP2_UID, false /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, false /* add */);
|
||||
|
||||
// Interface rules are not changed by Lockdown mode enable/disable
|
||||
verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
|
||||
@@ -10528,27 +10517,28 @@ public class ConnectivityServiceTest {
|
||||
assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges("tun0"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLegacyVpnInterfaceFilteringRule() throws Exception {
|
||||
LinkProperties lp = new LinkProperties();
|
||||
lp.setInterfaceName("tun0");
|
||||
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
|
||||
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
|
||||
private void checkInterfaceFilteringRuleWithNullInterface(final LinkProperties lp,
|
||||
final int uid) throws Exception {
|
||||
// The uid range needs to cover the test app so the network is visible to it.
|
||||
final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
|
||||
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
|
||||
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
|
||||
mMockVpn.establish(lp, uid, vpnRange);
|
||||
assertVpnUidRangesUpdated(true, vpnRange, uid);
|
||||
|
||||
if (SdkLevel.isAtLeastT()) {
|
||||
// On T and above, A connected Legacy VPN should have interface rules with null
|
||||
// interface. Null Interface is a wildcard and this accepts traffic from all the
|
||||
// interfaces. There are two expected invocations, one during the VPN initial
|
||||
// On T and above, VPN should have rules for null interface. Null Interface is a
|
||||
// wildcard and this accepts traffic from all the interfaces.
|
||||
// There are two expected invocations, one during the VPN initial
|
||||
// connection, one during the VPN LinkProperties update.
|
||||
ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
|
||||
verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
|
||||
eq(null) /* iface */, uidCaptor.capture());
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
|
||||
if (uid == VPN_UID) {
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID);
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID);
|
||||
} else {
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
|
||||
}
|
||||
assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
|
||||
vpnRange);
|
||||
|
||||
@@ -10557,50 +10547,37 @@ public class ConnectivityServiceTest {
|
||||
|
||||
// Disconnected VPN should have interface rules removed
|
||||
verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
|
||||
assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
|
||||
if (uid == VPN_UID) {
|
||||
assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID);
|
||||
} else {
|
||||
assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
|
||||
}
|
||||
assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
|
||||
} else {
|
||||
// Before T, Legacy VPN should not have interface rules.
|
||||
// Before T, rules are not configured for null interface.
|
||||
verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLegacyVpnInterfaceFilteringRule() throws Exception {
|
||||
LinkProperties lp = new LinkProperties();
|
||||
lp.setInterfaceName("tun0");
|
||||
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), null));
|
||||
lp.addRoute(new RouteInfo(new IpPrefix(Inet4Address.ANY, 0), null));
|
||||
// Legacy VPN should have interface filtering with null interface.
|
||||
checkInterfaceFilteringRuleWithNullInterface(lp, Process.SYSTEM_UID);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLocalIpv4OnlyVpnInterfaceFilteringRule() throws Exception {
|
||||
LinkProperties lp = new LinkProperties();
|
||||
lp.setInterfaceName("tun0");
|
||||
lp.addRoute(new RouteInfo(new IpPrefix("192.0.2.0/24"), null, "tun0"));
|
||||
lp.addRoute(new RouteInfo(new IpPrefix(Inet6Address.ANY, 0), RTN_UNREACHABLE));
|
||||
// The uid range needs to cover the test app so the network is visible to it.
|
||||
final Set<UidRange> vpnRange = Collections.singleton(PRIMARY_UIDRANGE);
|
||||
mMockVpn.establish(lp, Process.SYSTEM_UID, vpnRange);
|
||||
assertVpnUidRangesUpdated(true, vpnRange, Process.SYSTEM_UID);
|
||||
|
||||
if (SdkLevel.isAtLeastT()) {
|
||||
// IPv6 unreachable route should not be misinterpreted as a default route
|
||||
// On T and above, A connected VPN that does not provide a default route should have
|
||||
// interface rules with null interface. Null Interface is a wildcard and this accepts
|
||||
// traffic from all the interfaces. There are two expected invocations, one during the
|
||||
// VPN initial connection, one during the VPN LinkProperties update.
|
||||
ArgumentCaptor<int[]> uidCaptor = ArgumentCaptor.forClass(int[].class);
|
||||
verify(mBpfNetMaps, times(2)).addUidInterfaceRules(
|
||||
eq(null) /* iface */, uidCaptor.capture());
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(0), APP1_UID, APP2_UID, VPN_UID);
|
||||
assertContainsExactly(uidCaptor.getAllValues().get(1), APP1_UID, APP2_UID, VPN_UID);
|
||||
assertEquals(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */),
|
||||
vpnRange);
|
||||
|
||||
mMockVpn.disconnect();
|
||||
waitForIdle();
|
||||
|
||||
// Disconnected VPN should have interface rules removed
|
||||
verify(mBpfNetMaps).removeUidInterfaceRules(uidCaptor.capture());
|
||||
assertContainsExactly(uidCaptor.getValue(), APP1_UID, APP2_UID, VPN_UID);
|
||||
assertNull(mService.mPermissionMonitor.getVpnInterfaceUidRanges(null /* iface */));
|
||||
} else {
|
||||
// Before T, VPN with IPv6 unreachable route should not have interface rules.
|
||||
verify(mBpfNetMaps, never()).addUidInterfaceRules(any(), any());
|
||||
}
|
||||
// VPN that does not provide a default route should have interface filtering with null
|
||||
// interface.
|
||||
checkInterfaceFilteringRuleWithNullInterface(lp, VPN_UID);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
@@ -30,9 +30,6 @@ import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
|
||||
import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_REQUIRED;
|
||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||
import static android.content.pm.PackageManager.MATCH_ANY_USER;
|
||||
import static android.net.ConnectivityManager.FIREWALL_CHAIN_LOCKDOWN_VPN;
|
||||
import static android.net.ConnectivityManager.FIREWALL_RULE_ALLOW;
|
||||
import static android.net.ConnectivityManager.FIREWALL_RULE_DENY;
|
||||
import static android.net.ConnectivitySettingsManager.UIDS_ALLOWED_ON_RESTRICTED_NETWORKS;
|
||||
import static android.net.INetd.PERMISSION_INTERNET;
|
||||
import static android.net.INetd.PERMISSION_NETWORK;
|
||||
@@ -698,7 +695,8 @@ public class PermissionMonitorTest {
|
||||
mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
|
||||
SYSTEM_APPID1);
|
||||
|
||||
final List<PackageInfo> pkgs = List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID21,
|
||||
final List<PackageInfo> pkgs = List.of(
|
||||
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID21,
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS),
|
||||
buildPackageInfo(SYSTEM_PACKAGE2, SYSTEM_APP_UID21, CHANGE_NETWORK_STATE));
|
||||
doReturn(pkgs).when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS),
|
||||
@@ -764,9 +762,10 @@ public class PermissionMonitorTest {
|
||||
MOCK_APPID1);
|
||||
}
|
||||
|
||||
private void doTestuidFilteringDuringVpnConnectDisconnectAndUidUpdates(@Nullable String ifName)
|
||||
private void doTestUidFilteringDuringVpnConnectDisconnectAndUidUpdates(@Nullable String ifName)
|
||||
throws Exception {
|
||||
doReturn(List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS),
|
||||
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID12),
|
||||
@@ -774,7 +773,7 @@ public class PermissionMonitorTest {
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID11);
|
||||
mPermissionMonitor.startMonitoring();
|
||||
// Every app on user 0 except MOCK_UID12 are under VPN.
|
||||
// Every app on user 0 except MOCK_UID12 is subject to the VPN.
|
||||
final Set<UidRange> vpnRange1 = Set.of(
|
||||
new UidRange(0, MOCK_UID12 - 1),
|
||||
new UidRange(MOCK_UID12 + 1, UserHandle.PER_USER_RANGE - 1));
|
||||
@@ -811,18 +810,19 @@ public class PermissionMonitorTest {
|
||||
|
||||
@Test
|
||||
public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdates() throws Exception {
|
||||
doTestuidFilteringDuringVpnConnectDisconnectAndUidUpdates("tun0");
|
||||
doTestUidFilteringDuringVpnConnectDisconnectAndUidUpdates("tun0");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testUidFilteringDuringVpnConnectDisconnectAndUidUpdatesWithWildcard()
|
||||
throws Exception {
|
||||
doTestuidFilteringDuringVpnConnectDisconnectAndUidUpdates(null /* ifName */);
|
||||
doTestUidFilteringDuringVpnConnectDisconnectAndUidUpdates(null /* ifName */);
|
||||
}
|
||||
|
||||
private void doTestUidFilteringDuringPackageInstallAndUninstall(@Nullable String ifName) throws
|
||||
Exception {
|
||||
doReturn(List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS),
|
||||
buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
@@ -857,155 +857,149 @@ public class PermissionMonitorTest {
|
||||
|
||||
@Test
|
||||
public void testLockdownUidFilteringWithLockdownEnableDisable() {
|
||||
doReturn(List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS),
|
||||
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID12),
|
||||
buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
mPermissionMonitor.startMonitoring();
|
||||
// Every app on user 0 except MOCK_UID12 are under VPN.
|
||||
final UidRange[] vpnRange1 = {
|
||||
// Every app on user 0 except MOCK_UID12 is subject to the VPN.
|
||||
final UidRange[] lockdownRange = {
|
||||
new UidRange(0, MOCK_UID12 - 1),
|
||||
new UidRange(MOCK_UID12 + 1, UserHandle.PER_USER_RANGE - 1)
|
||||
};
|
||||
|
||||
// Add Lockdown uid range, expect a rule to be set up for user app MOCK_UID11
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, vpnRange1);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(
|
||||
eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_DENY));
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(vpnRange1));
|
||||
// Add Lockdown uid range, expect a rule to be set up for MOCK_UID11 and VPN_UID
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps, times(2)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, true /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, true /* add */);
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Remove Lockdown uid range, expect rules to be torn down
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, vpnRange1);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_ALLOW));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps, times(2)).updateUidLockdownRule(anyInt(), eq(false) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, false /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(VPN_UID, false /* add */);
|
||||
assertTrue(mPermissionMonitor.getVpnLockdownUidRanges().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockdownUidFilteringWithLockdownEnableDisableWithMultiAdd() {
|
||||
doReturn(List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS),
|
||||
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
mPermissionMonitor.startMonitoring();
|
||||
// MOCK_UID11 is under VPN.
|
||||
// MOCK_UID11 is subject to the VPN.
|
||||
final UidRange range = new UidRange(MOCK_UID11, MOCK_UID11);
|
||||
final UidRange[] vpnRange = {range};
|
||||
final UidRange[] lockdownRange = {range};
|
||||
|
||||
// Add Lockdown uid range at 1st time, expect a rule to be set up
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, vpnRange);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_DENY));
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(vpnRange));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(true) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, true /* add */);
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Add Lockdown uid range at 2nd time, expect a rule not to be set up because the uid
|
||||
// already has the rule
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, vpnRange);
|
||||
verify(mBpfNetMaps, never()).setUidRule(anyInt(), anyInt(), anyInt());
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(vpnRange));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps, never()).updateUidLockdownRule(anyInt(), anyBoolean());
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Remove Lockdown uid range at 1st time, expect a rule not to be torn down because we added
|
||||
// the range 2 times.
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, vpnRange);
|
||||
verify(mBpfNetMaps, never()).setUidRule(anyInt(), anyInt(), anyInt());
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(vpnRange));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps, never()).updateUidLockdownRule(anyInt(), anyBoolean());
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Remove Lockdown uid range at 2nd time, expect a rule to be torn down because we added
|
||||
// twice and we removed twice.
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, vpnRange);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_ALLOW));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(false) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, false /* add */);
|
||||
assertTrue(mPermissionMonitor.getVpnLockdownUidRanges().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockdownUidFilteringWithLockdownEnableDisableWithDuplicates() {
|
||||
doReturn(List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS),
|
||||
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
mPermissionMonitor.startMonitoring();
|
||||
// MOCK_UID11 is under VPN.
|
||||
// MOCK_UID11 is subject to the VPN.
|
||||
final UidRange range = new UidRange(MOCK_UID11, MOCK_UID11);
|
||||
final UidRange[] vpnRangeDuplicates = {range, range};
|
||||
final UidRange[] vpnRange = {range};
|
||||
final UidRange[] lockdownRangeDuplicates = {range, range};
|
||||
final UidRange[] lockdownRange = {range};
|
||||
|
||||
// Add Lockdown uid ranges which contains duplicated uid ranges
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, vpnRangeDuplicates);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_DENY));
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(vpnRange));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRangeDuplicates);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(true) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, true /* add */);
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Remove Lockdown uid range at 1st time, expect a rule not to be torn down because uid
|
||||
// ranges we added contains duplicated uid ranges.
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, vpnRange);
|
||||
verify(mBpfNetMaps, never()).setUidRule(anyInt(), anyInt(), anyInt());
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(vpnRange));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps, never()).updateUidLockdownRule(anyInt(), anyBoolean());
|
||||
assertEquals(mPermissionMonitor.getVpnLockdownUidRanges(), Set.of(lockdownRange));
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Remove Lockdown uid range at 2nd time, expect a rule to be torn down.
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* false */, vpnRange);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_ALLOW));
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(false /* add */, lockdownRange);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(false) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, false /* add */);
|
||||
assertTrue(mPermissionMonitor.getVpnLockdownUidRanges().isEmpty());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLockdownUidFilteringWithInstallAndUnInstall() {
|
||||
doReturn(List.of(buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(SYSTEM_PACKAGE1, SYSTEM_APP_UID11, CHANGE_NETWORK_STATE,
|
||||
NETWORK_STACK, CONNECTIVITY_USE_RESTRICTED_NETWORKS),
|
||||
buildPackageInfo(SYSTEM_PACKAGE2, VPN_UID)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
doReturn(List.of(MOCK_USER1, MOCK_USER2)).when(mUserManager).getUserHandles(eq(true));
|
||||
|
||||
mPermissionMonitor.startMonitoring();
|
||||
final UidRange[] vpnRange = {
|
||||
final UidRange[] lockdownRange = {
|
||||
UidRange.createForUser(MOCK_USER1),
|
||||
UidRange.createForUser(MOCK_USER2)
|
||||
};
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, vpnRange);
|
||||
mPermissionMonitor.updateVpnLockdownUidRanges(true /* add */, lockdownRange);
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Installing package should add Lockdown rules
|
||||
addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_APPID1);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_DENY));
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID21),
|
||||
eq(FIREWALL_RULE_DENY));
|
||||
verify(mBpfNetMaps, times(2)).updateUidLockdownRule(anyInt(), eq(true) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, true /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID21, true /* add */);
|
||||
|
||||
reset(mBpfNetMaps);
|
||||
|
||||
// Uninstalling package should remove Lockdown rules
|
||||
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID11);
|
||||
verify(mBpfNetMaps)
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID11),
|
||||
eq(FIREWALL_RULE_ALLOW));
|
||||
verify(mBpfNetMaps, never())
|
||||
.setUidRule(eq(FIREWALL_CHAIN_LOCKDOWN_VPN), eq(MOCK_UID21),
|
||||
eq(FIREWALL_RULE_ALLOW));
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(anyInt(), eq(false) /* add */);
|
||||
verify(mBpfNetMaps).updateUidLockdownRule(MOCK_UID11, false /* add */);
|
||||
}
|
||||
|
||||
// Normal package add/remove operations will trigger multiple intent for uids corresponding to
|
||||
@@ -1329,7 +1323,8 @@ public class PermissionMonitorTest {
|
||||
public void testOnExternalApplicationsAvailable() throws Exception {
|
||||
// Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
|
||||
// and have different uids. There has no permission for both uids.
|
||||
doReturn(List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID12)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
mPermissionMonitor.startMonitoring();
|
||||
@@ -1387,7 +1382,8 @@ public class PermissionMonitorTest {
|
||||
throws Exception {
|
||||
// Initial the permission state. MOCK_PACKAGE1 and MOCK_PACKAGE2 are installed on external
|
||||
// storage and shared on MOCK_UID11. There has no permission for MOCK_UID11.
|
||||
doReturn(List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID11)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
mPermissionMonitor.startMonitoring();
|
||||
@@ -1413,7 +1409,8 @@ public class PermissionMonitorTest {
|
||||
// Initial the permission state. MOCK_PACKAGE1 is installed on external storage and
|
||||
// MOCK_PACKAGE2 is installed on device. These two packages are shared on MOCK_UID11.
|
||||
// MOCK_UID11 has NETWORK and INTERNET permissions.
|
||||
doReturn(List.of(buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
doReturn(List.of(
|
||||
buildPackageInfo(MOCK_PACKAGE1, MOCK_UID11),
|
||||
buildPackageInfo(MOCK_PACKAGE2, MOCK_UID11, CHANGE_NETWORK_STATE, INTERNET)))
|
||||
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
|
||||
mPermissionMonitor.startMonitoring();
|
||||
|
||||
Reference in New Issue
Block a user