Merge "Add a flag to disable the background firewall chain" into main

This commit is contained in:
Suprabh Shukla 2024-04-02 05:47:56 +00:00 • committed by Gerrit Code Review
commit aeacff5033
5 changed files with 206 additions and 6 deletions

View file

@ -478,6 +478,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private volatile boolean mLockdownEnabled;
private final boolean mRequestRestrictedWifiEnabled;
private final boolean mBackgroundFirewallChainEnabled;
/**
* Stale copy of uid blocked reasons provided by NPMS. As long as they are accessed only in
@ -1798,6 +1799,8 @@ public class ConnectivityService extends IConnectivityManager.Stub
mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
mRequestRestrictedWifiEnabled = mDeps.isAtLeastU()
&& mDeps.isFeatureEnabled(context, REQUEST_RESTRICTED_WIFI);
mBackgroundFirewallChainEnabled = mDeps.isAtLeastV() && mDeps.isFeatureNotChickenedOut(
context, ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN);
mCarrierPrivilegeAuthenticator = mDeps.makeCarrierPrivilegeAuthenticator(
mContext, mTelephonyManager, mRequestRestrictedWifiEnabled,
this::handleUidCarrierPrivilegesLost, mHandler);
@ -4152,6 +4155,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
pw.println();
pw.println("Multicast routing supported: " +
(mMulticastRoutingCoordinatorService != null));
pw.println();
pw.println("Background firewall chain enabled: " + mBackgroundFirewallChainEnabled);
}
private void dumpNetworks(IndentingPrintWriter pw) {
@ -13521,6 +13527,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
public void setUidFirewallRule(final int chain, final int uid, final int rule) {
enforceNetworkStackOrSettingsPermission();
if (chain == FIREWALL_CHAIN_BACKGROUND && !mBackgroundFirewallChainEnabled) {
Log.i(TAG, "Ignoring operation setUidFirewallRule on the background chain because the"
+ " feature is disabled.");
return;
}
// There are only two type of firewall rule: FIREWALL_RULE_ALLOW or FIREWALL_RULE_DENY
int firewallRule = getFirewallRuleType(chain, rule);
@ -13593,6 +13605,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
public void setFirewallChainEnabled(final int chain, final boolean enable) {
enforceNetworkStackOrSettingsPermission();
if (chain == FIREWALL_CHAIN_BACKGROUND && !mBackgroundFirewallChainEnabled) {
Log.i(TAG, "Ignoring operation setFirewallChainEnabled on the background chain because"
+ " the feature is disabled.");
return;
}
try {
mBpfNetMaps.setChildChain(chain, enable);
} catch (ServiceSpecificException e) {
@ -13619,6 +13637,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
public void replaceFirewallChain(final int chain, final int[] uids) {
enforceNetworkStackOrSettingsPermission();
if (chain == FIREWALL_CHAIN_BACKGROUND && !mBackgroundFirewallChainEnabled) {
Log.i(TAG, "Ignoring operation replaceFirewallChain on the background chain because"
+ " the feature is disabled.");
return;
}
mBpfNetMaps.replaceUidChain(chain, uids);
}

View file

@ -42,6 +42,8 @@ public final class ConnectivityFlags {
public static final String INGRESS_TO_VPN_ADDRESS_FILTERING =
"ingress_to_vpn_address_filtering";
public static final String BACKGROUND_FIREWALL_CHAIN = "background_firewall_chain";
private boolean mNoRematchAllRequestsOnRegister;
/**

View file

@ -172,6 +172,7 @@ import static com.android.server.ConnectivityService.makeNflogPrefix;
import static com.android.server.ConnectivityServiceTestUtils.transportToLegacyType;
import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackRegister;
import static com.android.server.NetworkAgentWrapper.CallbackType.OnQosCallbackUnregister;
import static com.android.server.connectivity.ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN;
import static com.android.server.connectivity.ConnectivityFlags.INGRESS_TO_VPN_ADDRESS_FILTERING;
import static com.android.testutils.Cleanup.testAndCleanup;
import static com.android.testutils.ConcurrentUtils.await;
@ -391,6 +392,7 @@ import com.android.internal.net.VpnConfig;
import com.android.internal.util.WakeupMessage;
import com.android.internal.util.test.BroadcastInterceptingContext;
import com.android.internal.util.test.FakeSettingsProvider;
import com.android.modules.utils.build.SdkLevel;
import com.android.net.module.util.ArrayTrackRecord;
import com.android.net.module.util.BaseNetdUnsolicitedEventListener;
import com.android.net.module.util.CollectionUtils;
@ -2171,6 +2173,8 @@ public class ConnectivityServiceTest {
return true;
case INGRESS_TO_VPN_ADDRESS_FILTERING:
return true;
case BACKGROUND_FIREWALL_CHAIN:
return true;
default:
return super.isFeatureNotChickenedOut(context, name);
}
@ -10488,7 +10492,10 @@ public class ConnectivityServiceTest {
doTestSetUidFirewallRule(FIREWALL_CHAIN_POWERSAVE, FIREWALL_RULE_DENY);
doTestSetUidFirewallRule(FIREWALL_CHAIN_RESTRICTED, FIREWALL_RULE_DENY);
doTestSetUidFirewallRule(FIREWALL_CHAIN_LOW_POWER_STANDBY, FIREWALL_RULE_DENY);
doTestSetUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, FIREWALL_RULE_DENY);
if (SdkLevel.isAtLeastV()) {
// FIREWALL_CHAIN_BACKGROUND is only available on V+.
doTestSetUidFirewallRule(FIREWALL_CHAIN_BACKGROUND, FIREWALL_RULE_DENY);
}
doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_1, FIREWALL_RULE_ALLOW);
doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_2, FIREWALL_RULE_ALLOW);
doTestSetUidFirewallRule(FIREWALL_CHAIN_OEM_DENY_3, FIREWALL_RULE_ALLOW);
@ -10496,16 +10503,19 @@ public class ConnectivityServiceTest {
@Test @IgnoreUpTo(SC_V2)
public void testSetFirewallChainEnabled() throws Exception {
final List<Integer> firewallChains = Arrays.asList(
final List<Integer> firewallChains = new ArrayList<>(Arrays.asList(
FIREWALL_CHAIN_DOZABLE,
FIREWALL_CHAIN_STANDBY,
FIREWALL_CHAIN_POWERSAVE,
FIREWALL_CHAIN_RESTRICTED,
FIREWALL_CHAIN_LOW_POWER_STANDBY,
FIREWALL_CHAIN_BACKGROUND,
FIREWALL_CHAIN_OEM_DENY_1,
FIREWALL_CHAIN_OEM_DENY_2,
FIREWALL_CHAIN_OEM_DENY_3);
FIREWALL_CHAIN_OEM_DENY_3));
if (SdkLevel.isAtLeastV()) {
// FIREWALL_CHAIN_BACKGROUND is only available on V+.
firewallChains.add(FIREWALL_CHAIN_BACKGROUND);
}
for (final int chain: firewallChains) {
mCm.setFirewallChainEnabled(chain, true /* enabled */);
verify(mBpfNetMaps).setChildChain(chain, true /* enable */);
@ -10552,7 +10562,10 @@ public class ConnectivityServiceTest {
doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_POWERSAVE, allowlist);
doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_RESTRICTED, allowlist);
doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_LOW_POWER_STANDBY, allowlist);
doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_BACKGROUND, allowlist);
if (SdkLevel.isAtLeastV()) {
// FIREWALL_CHAIN_BACKGROUND is only available on V+.
doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_BACKGROUND, allowlist);
}
doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_STANDBY, denylist);
doTestSetFirewallChainEnabledCloseSocket(FIREWALL_CHAIN_OEM_DENY_1, denylist);
@ -10574,7 +10587,10 @@ public class ConnectivityServiceTest {
doTestReplaceFirewallChain(FIREWALL_CHAIN_POWERSAVE);
doTestReplaceFirewallChain(FIREWALL_CHAIN_RESTRICTED);
doTestReplaceFirewallChain(FIREWALL_CHAIN_LOW_POWER_STANDBY);
doTestReplaceFirewallChain(FIREWALL_CHAIN_BACKGROUND);
if (SdkLevel.isAtLeastV()) {
// FIREWALL_CHAIN_BACKGROUND is only available on V+.
doTestReplaceFirewallChain(FIREWALL_CHAIN_BACKGROUND);
}
doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_1);
doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_2);
doTestReplaceFirewallChain(FIREWALL_CHAIN_OEM_DENY_3);

View file

@ -0,0 +1,157 @@
/*
* Copyright (C) 2024 The Android Open Source Project
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package com.android.server
import android.net.ConnectivityManager
import android.os.Build
import androidx.test.filters.SmallTest
import com.android.server.connectivity.ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN
import com.android.testutils.DevSdkIgnoreRule
import com.android.testutils.DevSdkIgnoreRule.IgnoreAfter
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo
import com.android.testutils.DevSdkIgnoreRunner
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.mockito.ArgumentMatchers.anyBoolean
import org.mockito.ArgumentMatchers.anyInt
import org.mockito.Mockito.any
import org.mockito.Mockito.clearInvocations
import org.mockito.Mockito.never
import org.mockito.Mockito.verify
@RunWith(DevSdkIgnoreRunner::class)
@SmallTest
@IgnoreUpTo(Build.VERSION_CODES.S_V2)
class CSFirewallChainTest : CSTest() {
@get:Rule
val ignoreRule = DevSdkIgnoreRule()
// Tests for setFirewallChainEnabled on FIREWALL_CHAIN_BACKGROUND
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, false)])
fun setFirewallChainEnabled_backgroundChainDisabled() {
verifySetFirewallChainEnabledOnBackgroundDoesNothing()
}
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, true)])
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun setFirewallChainEnabled_backgroundChainEnabled_afterU() {
cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, true)
verify(bpfNetMaps).setChildChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, true)
clearInvocations(bpfNetMaps)
cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, false)
verify(bpfNetMaps).setChildChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, false)
}
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, true)])
@IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun setFirewallChainEnabled_backgroundChainEnabled_uptoU() {
verifySetFirewallChainEnabledOnBackgroundDoesNothing()
}
private fun verifySetFirewallChainEnabledOnBackgroundDoesNothing() {
cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, true)
verify(bpfNetMaps, never()).setChildChain(anyInt(), anyBoolean())
cm.setFirewallChainEnabled(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, false)
verify(bpfNetMaps, never()).setChildChain(anyInt(), anyBoolean())
}
// Tests for replaceFirewallChain on FIREWALL_CHAIN_BACKGROUND
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, false)])
fun replaceFirewallChain_backgroundChainDisabled() {
verifyReplaceFirewallChainOnBackgroundDoesNothing()
}
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, true)])
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun replaceFirewallChain_backgroundChainEnabled_afterU() {
val uids = intArrayOf(53, 42, 79)
cm.replaceFirewallChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uids)
verify(bpfNetMaps).replaceUidChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uids)
}
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, true)])
@IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun replaceFirewallChain_backgroundChainEnabled_uptoU() {
verifyReplaceFirewallChainOnBackgroundDoesNothing()
}
private fun verifyReplaceFirewallChainOnBackgroundDoesNothing() {
val uids = intArrayOf(53, 42, 79)
cm.replaceFirewallChain(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uids)
verify(bpfNetMaps, never()).replaceUidChain(anyInt(), any(IntArray::class.java))
}
// Tests for setUidFirewallRule on FIREWALL_CHAIN_BACKGROUND
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, false)])
fun setUidFirewallRule_backgroundChainDisabled() {
verifySetUidFirewallRuleOnBackgroundDoesNothing()
}
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, true)])
@IgnoreUpTo(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun setUidFirewallRule_backgroundChainEnabled_afterU() {
val uid = 2345
cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
ConnectivityManager.FIREWALL_RULE_DEFAULT)
verify(bpfNetMaps).setUidRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
ConnectivityManager.FIREWALL_RULE_DENY)
clearInvocations(bpfNetMaps)
cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
ConnectivityManager.FIREWALL_RULE_DENY)
verify(bpfNetMaps).setUidRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
ConnectivityManager.FIREWALL_RULE_DENY)
clearInvocations(bpfNetMaps)
cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
ConnectivityManager.FIREWALL_RULE_ALLOW)
verify(bpfNetMaps).setUidRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid,
ConnectivityManager.FIREWALL_RULE_ALLOW)
}
@Test
@FeatureFlags(flags = [Flag(BACKGROUND_FIREWALL_CHAIN, true)])
@IgnoreAfter(Build.VERSION_CODES.UPSIDE_DOWN_CAKE)
fun setUidFirewallRule_backgroundChainEnabled_uptoU() {
verifySetUidFirewallRuleOnBackgroundDoesNothing()
}
private fun verifySetUidFirewallRuleOnBackgroundDoesNothing() {
val uid = 2345
listOf(ConnectivityManager.FIREWALL_RULE_DEFAULT, ConnectivityManager.FIREWALL_RULE_ALLOW,
ConnectivityManager.FIREWALL_RULE_DENY).forEach { rule ->
cm.setUidFirewallRule(ConnectivityManager.FIREWALL_CHAIN_BACKGROUND, uid, rule)
verify(bpfNetMaps, never()).setUidRule(anyInt(), anyInt(), anyInt())
}
}
}

View file

@ -161,6 +161,7 @@ open class CSTest {
it[ConnectivityService.ALLOW_SYSUI_CONNECTIVITY_REPORTS] = true
it[ConnectivityService.ALLOW_SATALLITE_NETWORK_FALLBACK] = true
it[ConnectivityFlags.INGRESS_TO_VPN_ADDRESS_FILTERING] = true
it[ConnectivityFlags.BACKGROUND_FIREWALL_CHAIN] = true
}
fun setFeatureEnabled(flag: String, enabled: Boolean) = enabledFeatures.set(flag, enabled)