Add Restricted Mode Firewall Chain

Adding new allowlist firewall chain to support restricted networking
mode. See go/restricted-networking-mode.

Bug: b/157505406
Bug: b/170323408
Test: atest NetworkManagementServiceTest
Change-Id: I8e39b3d7b129ad74224d0c1311135b7b48f6514f
This commit is contained in:
Patrick Rohr
2020-11-19 11:28:13 +01:00
parent 73a74fa6dd
commit 9aabc50ec9
4 changed files with 54 additions and 9 deletions

View File

@ -144,6 +144,8 @@ public class NetworkPolicyManager {
public static final String FIREWALL_CHAIN_NAME_STANDBY = "standby";
/** @hide */
public static final String FIREWALL_CHAIN_NAME_POWERSAVE = "powersave";
/** @hide */
public static final String FIREWALL_CHAIN_NAME_RESTRICTED = "restricted";
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;

View File

@ -24,12 +24,14 @@ import static android.net.INetd.FIREWALL_ALLOWLIST;
import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
import static android.net.INetd.FIREWALL_CHAIN_NONE;
import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_DENYLIST;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkStats.SET_DEFAULT;
@ -218,6 +220,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
*/
@GuardedBy("mRulesLock")
private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
/**
* Contains the per-UID firewall rules that are used when Restricted Networking Mode is enabled.
*/
@GuardedBy("mRulesLock")
private SparseIntArray mUidFirewallRestrictedRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mRulesLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@ -604,9 +611,15 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
syncFirewallChainLocked(FIREWALL_CHAIN_RESTRICTED, "restricted ");
final int[] chains = {
FIREWALL_CHAIN_STANDBY,
FIREWALL_CHAIN_DOZABLE,
FIREWALL_CHAIN_POWERSAVE,
FIREWALL_CHAIN_RESTRICTED
};
final int[] chains =
{FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
for (int chain : chains) {
if (getFirewallChainState(chain)) {
setFirewallChainEnabled(chain, true);
@ -1708,6 +1721,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
return FIREWALL_CHAIN_NAME_DOZABLE;
case FIREWALL_CHAIN_POWERSAVE:
return FIREWALL_CHAIN_NAME_POWERSAVE;
case FIREWALL_CHAIN_RESTRICTED:
return FIREWALL_CHAIN_NAME_RESTRICTED;
default:
throw new IllegalArgumentException("Bad child chain: " + chain);
}
@ -1721,6 +1736,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
return FIREWALL_ALLOWLIST;
case FIREWALL_CHAIN_POWERSAVE:
return FIREWALL_ALLOWLIST;
case FIREWALL_CHAIN_RESTRICTED:
return FIREWALL_ALLOWLIST;
default:
return isFirewallEnabled() ? FIREWALL_ALLOWLIST : FIREWALL_DENYLIST;
}
@ -1765,6 +1782,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
case FIREWALL_CHAIN_POWERSAVE:
mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
break;
case FIREWALL_CHAIN_RESTRICTED:
mNetdService.firewallReplaceUidChain("fw_restricted", true, uids);
break;
case FIREWALL_CHAIN_NONE:
default:
Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
@ -1849,6 +1869,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
return mUidFirewallDozableRules;
case FIREWALL_CHAIN_POWERSAVE:
return mUidFirewallPowerSaveRules;
case FIREWALL_CHAIN_RESTRICTED:
return mUidFirewallRestrictedRules;
case FIREWALL_CHAIN_NONE:
return mUidFirewallRules;
default:
@ -1923,17 +1945,22 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
synchronized (mRulesLock) {
dumpUidFirewallRule(pw, "", mUidFirewallRules);
pw.print("UID firewall standby chain enabled: "); pw.println(
getFirewallChainState(FIREWALL_CHAIN_STANDBY));
pw.print("UID firewall standby chain enabled: ");
pw.println(getFirewallChainState(FIREWALL_CHAIN_STANDBY));
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_STANDBY, mUidFirewallStandbyRules);
pw.print("UID firewall dozable chain enabled: "); pw.println(
getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
pw.print("UID firewall dozable chain enabled: ");
pw.println(getFirewallChainState(FIREWALL_CHAIN_DOZABLE));
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_DOZABLE, mUidFirewallDozableRules);
pw.println("UID firewall powersave chain enabled: " +
getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
pw.print("UID firewall powersave chain enabled: ");
pw.println(getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
pw.print("UID firewall restricted mode chain enabled: ");
pw.println(getFirewallChainState(FIREWALL_CHAIN_RESTRICTED));
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_RESTRICTED,
mUidFirewallRestrictedRules);
}
synchronized (mIdleTimerLock) {
@ -2127,6 +2154,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of power saver mode");
return true;
}
if (getFirewallChainState(FIREWALL_CHAIN_RESTRICTED)
&& mUidFirewallRestrictedRules.get(uid) != FIREWALL_RULE_ALLOW) {
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of restricted mode");
return true;
}
if (mUidRejectOnMetered.get(uid)) {
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of no metered data"
+ " in the background");

View File

@ -17,11 +17,13 @@ package com.android.server.net;
import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
import static android.net.INetd.FIREWALL_CHAIN_RESTRICTED;
import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_RESTRICTED;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.os.Process.INVALID_UID;
@ -339,6 +341,8 @@ public class NetworkPolicyLogger {
return FIREWALL_CHAIN_NAME_STANDBY;
case FIREWALL_CHAIN_POWERSAVE:
return FIREWALL_CHAIN_NAME_POWERSAVE;
case FIREWALL_CHAIN_RESTRICTED:
return FIREWALL_CHAIN_NAME_RESTRICTED;
default:
return String.valueOf(chain);
}

View File

@ -279,11 +279,18 @@ public class NetworkManagementServiceTest {
isRestrictedForStandby.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForStandby.put(INetd.FIREWALL_RULE_DENY, true);
expected.put(INetd.FIREWALL_CHAIN_STANDBY, isRestrictedForStandby);
// Restricted mode chain
final ArrayMap<Integer, Boolean> isRestrictedForRestrictedMode = new ArrayMap<>();
isRestrictedForRestrictedMode.put(NetworkPolicyManager.FIREWALL_RULE_DEFAULT, true);
isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_ALLOW, false);
isRestrictedForRestrictedMode.put(INetd.FIREWALL_RULE_DENY, true);
expected.put(INetd.FIREWALL_CHAIN_RESTRICTED, isRestrictedForRestrictedMode);
final int[] chains = {
INetd.FIREWALL_CHAIN_STANDBY,
INetd.FIREWALL_CHAIN_POWERSAVE,
INetd.FIREWALL_CHAIN_DOZABLE
INetd.FIREWALL_CHAIN_DOZABLE,
INetd.FIREWALL_CHAIN_RESTRICTED
};
final int[] states = {
INetd.FIREWALL_RULE_ALLOW,