Merge "Add a flag to disable the background firewall chain" into main
This commit is contained in:
commit
aeacff5033
5 changed files with 206 additions and 6 deletions
|
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
/**
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
|
|
@ -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())
|
||||
}
|
||||
}
|
||||
}
|
||||
|
|
@ -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)
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue