summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--core/java/android/net/NetworkPolicyManager.java10
-rw-r--r--services/core/java/com/android/server/ConnectivityService.java177
-rw-r--r--services/core/java/com/android/server/NetworkManagementService.java33
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyLogger.java7
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java8
-rw-r--r--services/core/java/com/android/server/net/NetworkPolicyManagerService.java76
6 files changed, 307 insertions, 4 deletions
diff --git a/core/java/android/net/NetworkPolicyManager.java b/core/java/android/net/NetworkPolicyManager.java
index a3ba180ce46e..661469b03cff 100644
--- a/core/java/android/net/NetworkPolicyManager.java
+++ b/core/java/android/net/NetworkPolicyManager.java
@@ -79,6 +79,8 @@ public class NetworkPolicyManager {
public static final int POLICY_REJECT_VPN = 0x20000;
/** Reject network usage on wifi network */
public static final int POLICY_REJECT_WIFI = 0x8000;
+ /** Reject network usage on all networks */
+ public static final int POLICY_REJECT_ALL = 0x40000;
/*
* Rules defining whether an uid has access to a network given its type (metered / non-metered).
@@ -128,7 +130,11 @@ public class NetworkPolicyManager {
* @hide
*/
public static final int RULE_REJECT_ALL = 1 << 6;
-
+ /**
+ * Reject traffic on all networks at all times
+ * @hide
+ */
+ public static final int RULE_REJECT_ISOLATED = 1 << 7;
/**
* Mask used to get the {@code RULE_xxx_METERED} rules
* @hide
@@ -150,6 +156,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_ISOLATED = "isolated";
private static final boolean ALLOW_PLATFORM_APP_POLICY = true;
diff --git a/services/core/java/com/android/server/ConnectivityService.java b/services/core/java/com/android/server/ConnectivityService.java
index 1227121f2024..7ac20de9e840 100644
--- a/services/core/java/com/android/server/ConnectivityService.java
+++ b/services/core/java/com/android/server/ConnectivityService.java
@@ -175,6 +175,7 @@ import android.util.Log;
import android.util.Pair;
import android.util.Slog;
import android.util.SparseArray;
+import android.util.SparseBooleanArray;
import android.util.SparseIntArray;
import android.util.Xml;
@@ -667,6 +668,15 @@ public class ConnectivityService extends IConnectivityManager.Stub
final Map<IBinder, ConnectivityDiagnosticsCallbackInfo> mConnectivityDiagnosticsCallbacks =
new HashMap<>();
+ // Tracking for network isolated uids
+ //
+ @GuardedBy("mIsolatedUids")
+ private final SparseBooleanArray mIsolatedUids = new SparseBooleanArray();
+ // Network requests that are still active but will not receive any callbacks
+ // owing to the calling uid beging network isolated. Only accessed on
+ // event handler thread so no locking necessary.
+ private final HashMap<NetworkRequest, NetworkRequestInfo> mDetachedRequests = new HashMap<>();
+
/**
* Implements support for the legacy "one network per network type" model.
*
@@ -1341,6 +1351,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
*/
private boolean isNetworkWithLinkPropertiesBlocked(LinkProperties lp, int uid,
boolean ignoreBlocked) {
+ // Network isolation should be checked first since it overrides ignore blocked status.
+ if (isUidIsolated(uid)) {
+ return true;
+ }
// Networks aren't blocked when ignoring blocked status
if (ignoreBlocked) {
return false;
@@ -1509,6 +1523,11 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public NetworkInfo[] getAllNetworkInfo() {
enforceAccessPermission();
+ if (isUidIsolated(Binder.getCallingUid())) {
+ // If a uid is network isolated, do not provide any visibility.
+ return new NetworkInfo[0];
+ }
+
final ArrayList<NetworkInfo> result = Lists.newArrayList();
for (int networkType = 0; networkType <= ConnectivityManager.MAX_NETWORK_TYPE;
networkType++) {
@@ -1534,6 +1553,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
@Override
public Network[] getAllNetworks() {
enforceAccessPermission();
+ if (isUidIsolated(Binder.getCallingUid())) {
+ // If a uid is network isolated, do not provide any visibility.
+ return new Network[0];
+ }
synchronized (mNetworkForNetId) {
final Network[] result = new Network[mNetworkForNetId.size()];
for (int i = 0; i < mNetworkForNetId.size(); i++) {
@@ -2005,6 +2028,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
final int oldRules = mUidRules.get(uid, RULE_NONE);
if (oldRules == newRules) return;
+ final boolean wasIsolated =
+ mPolicyManagerInternal.isNetworkingIsolatedByUidRules(oldRules);
+ final boolean isIsolated =
+ mPolicyManagerInternal.isNetworkingIsolatedByUidRules(newRules);
+ if (isIsolated != wasIsolated) {
+ if (isIsolated) {
+ setUidIsolated(uid);
+ } else {
+ clearUidIsolated(uid);
+ }
+ }
+
maybeNotifyNetworkBlockedForNewUidRules(uid, newRules);
if (newRules == RULE_NONE) {
@@ -2014,6 +2049,110 @@ public class ConnectivityService extends IConnectivityManager.Stub
}
}
+ private void setUidIsolated(int uid) {
+ synchronized (mIsolatedUids) {
+ mIsolatedUids.put(uid, true);
+ }
+ detachNetworkRequestsForUid(uid);
+ }
+
+ private void clearUidIsolated(int uid) {
+ synchronized (mIsolatedUids) {
+ mIsolatedUids.delete(uid);
+ }
+ reattachNetworkRequestsForUid(uid);
+ }
+
+ private boolean isUidIsolated(int uid) {
+ synchronized (mIsolatedUids) {
+ return mIsolatedUids.get(uid);
+ }
+ }
+
+ private void addDetachedRequest(NetworkRequestInfo nri) {
+ mDetachedRequests.put(nri.request, nri);
+ }
+
+ // App has died or callback is being unregistered, clean up.
+ // Match callback by PendingIntent.
+ private boolean removeDetachedNetworkRequests(PendingIntent pendingIntent, int uid) {
+ // Use same logic as findExistingNetworkRequestInfo()
+ Intent intent = pendingIntent.getIntent();
+ for (NetworkRequestInfo nri : mDetachedRequests.values()) {
+ PendingIntent existingPendingIntent = nri.mPendingIntent;
+ if (existingPendingIntent != null &&
+ existingPendingIntent.getIntent().filterEquals(intent)) {
+ return removeDetachedNetworkRequests(nri, uid);
+ }
+ }
+ return false;
+ }
+
+ // App has died or callback is being unregistered, clean up.
+ // Match callback by NetworkRequest.
+ private boolean removeDetachedNetworkRequests(NetworkRequest request, int uid) {
+ return removeDetachedNetworkRequests(mDetachedRequests.get(request), uid);
+ }
+
+ private boolean removeDetachedNetworkRequests(NetworkRequestInfo nri, int uid) {
+ // binderDied() runs as system uid so allow clean up
+ if (nri != null && (nri.mUid == uid || uid == Process.SYSTEM_UID)) {
+ nri.unlinkDeathRecipient();
+ mDetachedRequests.remove(nri.request);
+ return true;
+ }
+ return false;
+ }
+
+ private void detachNetworkRequestsForUid(int uid) {
+ // Collect network requests for this uid
+ final List<NetworkRequestInfo> nriList = new ArrayList<>();
+ for (NetworkRequestInfo nri : mNetworkRequests.values()) {
+ if (nri != null && nri.mUid == uid) {
+ nriList.add(nri);
+ }
+ }
+ for (NetworkRequestInfo nri : nriList) {
+ if (VDBG || DDBG) {
+ Log.d(TAG, "detaching request " + nri);
+ }
+
+ // Trigger onLost callbacks for matching networks
+ for (NetworkAgentInfo nai : mNetworkAgentInfos.values()) {
+ if (nai.isSatisfyingRequest(nri.request.requestId)) {
+ if (VDBG || DDBG) {
+ Log.d(TAG, "sending onLost to " + nri + " for " + nai);
+ }
+ callCallbackForRequest(nri, nai, ConnectivityManager.CALLBACK_LOST, 0);
+ }
+ }
+ // Remove the request from normal ConnectivityService machinery.
+ // This prevents receiving any further callbacks.
+ handleRemoveNetworkRequest(nri);
+ // Go through nri constructor to reinitialize things cleaned up
+ // by handleRemoveNetworkRequest(). eg updating per uid
+ // reference counts and setting binder linkToDeath.
+ mDetachedRequests.put(nri.request, new NetworkRequestInfo(nri));
+ }
+ }
+
+ private void reattachNetworkRequestsForUid(int uid) {
+ // Collect network requests for this uid
+ final List<NetworkRequestInfo> nriList = new ArrayList<>();
+ for (NetworkRequestInfo nri : mDetachedRequests.values()) {
+ if (nri != null && nri.mUid == uid) {
+ nriList.add(nri);
+ }
+ }
+ for (NetworkRequestInfo nri : nriList) {
+ if (VDBG || DDBG) {
+ Log.d(TAG, "reattaching request " + nri);
+ }
+ mDetachedRequests.remove(nri.request);
+ handleRegisterNetworkRequest(nri);
+ }
+ }
+
void handleRestrictBackgroundChanged(boolean restrictBackground) {
if (mRestrictBackground == restrictBackground) return;
@@ -3451,12 +3590,19 @@ public class ConnectivityService extends IConnectivityManager.Stub
+ nri.request + " because their intents matched.");
handleReleaseNetworkRequest(existingRequest.request, getCallingUid(),
/* callOnUnavailable */ false);
+ } else {
+ // Remove anything on the detached list
+ removeDetachedNetworkRequests(nri.mPendingIntent, Binder.getCallingUid());
}
handleRegisterNetworkRequest(nri);
}
private void handleRegisterNetworkRequest(NetworkRequestInfo nri) {
ensureRunningOnConnectivityServiceThread();
+ if (isUidIsolated(nri.mUid)) {
+ addDetachedRequest(nri);
+ return;
+ }
mNetworkRequests.put(nri.request, nri);
mNetworkRequestInfoLogs.log("REGISTER " + nri);
if (nri.request.isListen()) {
@@ -3475,6 +3621,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void handleReleaseNetworkRequestWithIntent(PendingIntent pendingIntent,
int callingUid) {
+ if (removeDetachedNetworkRequests(pendingIntent, callingUid)) {
+ // Was already released during detach so nothing further to do.
+ return;
+ }
NetworkRequestInfo nri = findExistingNetworkRequestInfo(pendingIntent);
if (nri != null) {
handleReleaseNetworkRequest(nri.request, callingUid, /* callOnUnavailable */ false);
@@ -3565,6 +3715,14 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void handleReleaseNetworkRequest(NetworkRequest request, int callingUid,
boolean callOnUnavailable) {
+ if (removeDetachedNetworkRequests(request, callingUid)) {
+ // Was already released during detach so nothing further to do.
+ if (VDBG || DDBG) {
+ Log.d(TAG, "removed detached request = " + request + " uid = " + callingUid);
+ }
+ return;
+ }
+
final NetworkRequestInfo nri =
getNriForAppRequest(request, callingUid, "release NetworkRequest");
if (nri == null) {
@@ -5394,6 +5552,25 @@ public class ConnectivityService extends IConnectivityManager.Stub
this(r, null);
}
+ // Recreate new from a previously detached request.
+ NetworkRequestInfo(NetworkRequestInfo nri) {
+ request = nri.request;
+ messenger = nri.messenger;
+ mBinder = nri.mBinder;
+ mPendingIntent = nri.mPendingIntent;
+ mPid = nri.mPid;
+ mUid = nri.mUid;
+ enforceRequestCountLimit();
+
+ if (mBinder != null) {
+ try {
+ mBinder.linkToDeath(this, 0);
+ } catch (RemoteException e) {
+ binderDied();
+ }
+ }
+ }
+
private void enforceRequestCountLimit() {
synchronized (mUidToNetworkRequestCount) {
int networkRequests = mUidToNetworkRequestCount.get(mUid, 0) + 1;
diff --git a/services/core/java/com/android/server/NetworkManagementService.java b/services/core/java/com/android/server/NetworkManagementService.java
index f40f64d06b15..5362e7a65129 100644
--- a/services/core/java/com/android/server/NetworkManagementService.java
+++ b/services/core/java/com/android/server/NetworkManagementService.java
@@ -22,6 +22,7 @@ import static android.Manifest.permission.OBSERVE_NETWORK_POLICY;
import static android.Manifest.permission.SHUTDOWN;
import static android.net.INetd.FIREWALL_BLACKLIST;
import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_ISOLATED;
import static android.net.INetd.FIREWALL_CHAIN_NONE;
import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
@@ -29,6 +30,7 @@ import static android.net.INetd.FIREWALL_RULE_ALLOW;
import static android.net.INetd.FIREWALL_RULE_DENY;
import static android.net.INetd.FIREWALL_WHITELIST;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_DOZABLE;
+import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_ISOLATED;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
@@ -219,6 +221,12 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
*/
@GuardedBy("mRulesLock")
private SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
+ /**
+ * Set of UIDs that are to be blocked/allowed by firewall controller. This set of Ids matches
+ * unconditionally at all times.
+ */
+ @GuardedBy("mRulesLock")
+ private SparseIntArray mUidFirewallIsolatedRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mRulesLock")
final SparseBooleanArray mFirewallChainStates = new SparseBooleanArray();
@@ -714,9 +722,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
syncFirewallChainLocked(FIREWALL_CHAIN_STANDBY, "standby ");
syncFirewallChainLocked(FIREWALL_CHAIN_DOZABLE, "dozable ");
syncFirewallChainLocked(FIREWALL_CHAIN_POWERSAVE, "powersave ");
+ syncFirewallChainLocked(FIREWALL_CHAIN_ISOLATED, "isolated ");
final int[] chains =
- {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE};
+ {FIREWALL_CHAIN_STANDBY, FIREWALL_CHAIN_DOZABLE, FIREWALL_CHAIN_POWERSAVE,
+ FIREWALL_CHAIN_ISOLATED};
for (int chain : chains) {
if (getFirewallChainState(chain)) {
setFirewallChainEnabled(chain, true);
@@ -1908,6 +1918,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
return FIREWALL_CHAIN_NAME_DOZABLE;
case FIREWALL_CHAIN_POWERSAVE:
return FIREWALL_CHAIN_NAME_POWERSAVE;
+ case FIREWALL_CHAIN_ISOLATED:
+ return FIREWALL_CHAIN_NAME_ISOLATED;
default:
throw new IllegalArgumentException("Bad child chain: " + chain);
}
@@ -1921,6 +1933,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
return FIREWALL_WHITELIST;
case FIREWALL_CHAIN_POWERSAVE:
return FIREWALL_WHITELIST;
+ case FIREWALL_CHAIN_ISOLATED:
+ return FIREWALL_BLACKLIST;
default:
return isFirewallEnabled() ? FIREWALL_WHITELIST : FIREWALL_BLACKLIST;
}
@@ -1965,6 +1979,9 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
case FIREWALL_CHAIN_POWERSAVE:
mNetdService.firewallReplaceUidChain("fw_powersave", true, uids);
break;
+ case FIREWALL_CHAIN_ISOLATED:
+ mNetdService.firewallReplaceUidChain("fw_isolated", false, uids);
+ break;
case FIREWALL_CHAIN_NONE:
default:
Slog.d(TAG, "setFirewallUidRules() called on invalid chain: " + chain);
@@ -2049,6 +2066,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
return mUidFirewallDozableRules;
case FIREWALL_CHAIN_POWERSAVE:
return mUidFirewallPowerSaveRules;
+ case FIREWALL_CHAIN_ISOLATED:
+ return mUidFirewallIsolatedRules;
case FIREWALL_CHAIN_NONE:
return mUidFirewallRules;
default:
@@ -2134,6 +2153,10 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
pw.println("UID firewall powersave chain enabled: " +
getFirewallChainState(FIREWALL_CHAIN_POWERSAVE));
dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_POWERSAVE, mUidFirewallPowerSaveRules);
+
+ pw.println("UID firewall isolated chain enabled: " +
+ getFirewallChainState(FIREWALL_CHAIN_ISOLATED));
+ dumpUidFirewallRule(pw, FIREWALL_CHAIN_NAME_ISOLATED, mUidFirewallIsolatedRules);
}
synchronized (mIdleTimerLock) {
@@ -2312,6 +2335,11 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
private boolean isNetworkRestrictedInternal(int uid) {
synchronized (mRulesLock) {
+ if (getFirewallChainState(FIREWALL_CHAIN_ISOLATED)
+ && mUidFirewallIsolatedRules.get(uid) == FIREWALL_RULE_DENY) {
+ if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of isolated mode");
+ return true;
+ }
if (getFirewallChainState(FIREWALL_CHAIN_STANDBY)
&& mUidFirewallStandbyRules.get(uid) == FIREWALL_RULE_DENY) {
if (DBG) Slog.d(TAG, "Uid " + uid + " restricted because of app standby mode");
@@ -2397,7 +2425,8 @@ public class NetworkManagementService extends INetworkManagementService.Stub {
final int[] chains = {
FIREWALL_CHAIN_DOZABLE,
FIREWALL_CHAIN_STANDBY,
- FIREWALL_CHAIN_POWERSAVE
+ FIREWALL_CHAIN_POWERSAVE,
+ FIREWALL_CHAIN_ISOLATED
};
for (int chain : chains) {
setFirewallChainState(chain, false);
diff --git a/services/core/java/com/android/server/net/NetworkPolicyLogger.java b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
index 3bd18f9a360f..94e62d91495c 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyLogger.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyLogger.java
@@ -16,11 +16,13 @@
package com.android.server.net;
import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_ISOLATED;
import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
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_ISOLATED;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_POWERSAVE;
import static android.net.NetworkPolicyManager.FIREWALL_CHAIN_NAME_STANDBY;
import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
@@ -76,6 +78,7 @@ public class NetworkPolicyLogger {
static final int NTWK_BLOCKED_BG_RESTRICT = 5;
static final int NTWK_ALLOWED_DEFAULT = 6;
static final int NTWK_ALLOWED_SYSTEM = 7;
+ static final int NTWK_BLOCKED_ISOLATED = 8;
private final LogBuffer mNetworkBlockedBuffer = new LogBuffer(MAX_NETWORK_BLOCKED_LOG_SIZE);
private final LogBuffer mUidStateChangeBuffer = new LogBuffer(MAX_LOG_SIZE);
@@ -279,6 +282,8 @@ public class NetworkPolicyLogger {
return "blocked when background is restricted";
case NTWK_ALLOWED_DEFAULT:
return "allowed by default";
+ case NTWK_BLOCKED_ISOLATED:
+ return "blocked by isolation";
default:
return String.valueOf(reason);
}
@@ -339,6 +344,8 @@ public class NetworkPolicyLogger {
return FIREWALL_CHAIN_NAME_STANDBY;
case FIREWALL_CHAIN_POWERSAVE:
return FIREWALL_CHAIN_NAME_POWERSAVE;
+ case FIREWALL_CHAIN_ISOLATED:
+ return FIREWALL_CHAIN_NAME_ISOLATED;
default:
return String.valueOf(chain);
}
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
index 48f1ddb023fd..7c05c50a7bcd 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerInternal.java
@@ -16,6 +16,7 @@
package com.android.server.net;
+import static com.android.server.net.NetworkPolicyManagerService.isNetworkingIsolatedByUidRulesInternal;
import static com.android.server.net.NetworkPolicyManagerService.isUidNetworkingBlockedInternal;
import android.annotation.NonNull;
@@ -44,6 +45,13 @@ public abstract class NetworkPolicyManagerInternal {
public abstract boolean isUidRestrictedOnMeteredNetworks(int uid);
/**
+ * @return true if the uid rules provided mean that network access should be blocked.
+ */
+ public static boolean isNetworkingIsolatedByUidRules(int uidRules) {
+ return isNetworkingIsolatedByUidRulesInternal(uidRules);
+ };
+
+ /**
* @return true if networking is blocked on the given interface for the given uid according
* to current networking policies.
*/
diff --git a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
index db7643384075..975325b65010 100644
--- a/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
+++ b/services/core/java/com/android/server/net/NetworkPolicyManagerService.java
@@ -43,6 +43,7 @@ import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_ENABLED
import static android.net.ConnectivityManager.RESTRICT_BACKGROUND_STATUS_WHITELISTED;
import static android.net.ConnectivityManager.TYPE_MOBILE;
import static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_CHAIN_ISOLATED;
import static android.net.INetd.FIREWALL_CHAIN_POWERSAVE;
import static android.net.INetd.FIREWALL_CHAIN_STANDBY;
import static android.net.INetd.FIREWALL_RULE_ALLOW;
@@ -58,6 +59,7 @@ import static android.net.NetworkPolicyManager.FIREWALL_RULE_DEFAULT;
import static android.net.NetworkPolicyManager.MASK_ALL_NETWORKS;
import static android.net.NetworkPolicyManager.MASK_METERED_NETWORKS;
import static android.net.NetworkPolicyManager.POLICY_ALLOW_METERED_BACKGROUND;
+import static android.net.NetworkPolicyManager.POLICY_REJECT_ALL;
import static android.net.NetworkPolicyManager.POLICY_NONE;
import static android.net.NetworkPolicyManager.POLICY_REJECT_METERED_BACKGROUND;
import static android.net.NetworkPolicyManager.POLICY_REJECT_CELLULAR;
@@ -65,6 +67,7 @@ import static android.net.NetworkPolicyManager.POLICY_REJECT_VPN;
import static android.net.NetworkPolicyManager.POLICY_REJECT_WIFI;
import static android.net.NetworkPolicyManager.RULE_ALLOW_ALL;
import static android.net.NetworkPolicyManager.RULE_ALLOW_METERED;
+import static android.net.NetworkPolicyManager.RULE_REJECT_ISOLATED;
import static android.net.NetworkPolicyManager.RULE_NONE;
import static android.net.NetworkPolicyManager.RULE_REJECT_ALL;
import static android.net.NetworkPolicyManager.RULE_REJECT_METERED;
@@ -111,6 +114,7 @@ import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_TMP_WHITEL
import static com.android.server.net.NetworkPolicyLogger.NTWK_ALLOWED_WHITELIST;
import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_BG_RESTRICT;
import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_BLACKLIST;
+import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_ISOLATED;
import static com.android.server.net.NetworkPolicyLogger.NTWK_BLOCKED_POWER;
import static com.android.server.net.NetworkStatsService.ACTION_NETWORK_STATS_UPDATED;
@@ -471,6 +475,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
final SparseIntArray mUidFirewallDozableRules = new SparseIntArray();
@GuardedBy("mUidRulesFirstLock")
final SparseIntArray mUidFirewallPowerSaveRules = new SparseIntArray();
+ @GuardedBy("mUidRulesFirstLock")
+ final SparseIntArray mUidFirewallIsolatedRules = new SparseIntArray();
/** Set of states for the child firewall chains. True if the chain is active. */
@GuardedBy("mUidRulesFirstLock")
@@ -813,6 +819,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
setRestrictBackgroundUL(mLoadedRestrictBackground, "init_service");
updateRulesForGlobalChangeAL(false);
updateNotificationsNL();
+ // Enable the network isolated blacklist chain
+ enableFirewallChainUL(FIREWALL_CHAIN_ISOLATED, true);
}
}
@@ -2587,6 +2595,11 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (!UserHandle.isApp(uid)) {
throw new IllegalArgumentException("cannot apply policy to UID " + uid);
}
+
+ if (LOGD) {
+ Log.d(TAG, "setUidPolicy: uid = " + uid + " policy = " + policy);
+ }
+
synchronized (mUidRulesFirstLock) {
final long token = Binder.clearCallingIdentity();
try {
@@ -2609,6 +2622,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
throw new IllegalArgumentException("cannot apply policy to UID " + uid);
}
+ if (LOGD) {
+ Log.d(TAG, "addUidPolicy: uid = " + uid + " policy = " + policy);
+ }
+
synchronized (mUidRulesFirstLock) {
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
policy |= oldPolicy;
@@ -2627,6 +2644,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
throw new IllegalArgumentException("cannot apply policy to UID " + uid);
}
+ if (LOGD) {
+ Log.d(TAG, "removeUidPolicy: uid = " + uid + " policy = " + policy);
+ }
+
synchronized (mUidRulesFirstLock) {
final int oldPolicy = mUidPolicy.get(uid, POLICY_NONE);
policy = oldPolicy & ~policy;
@@ -2679,6 +2700,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// uid policy changed, recompute rules and persist policy.
updateRulesForDataUsageRestrictionsUL(uid);
+ updateRulesForIsolatedUL(uid);
if (persist) {
synchronized (mNetworkPoliciesSecondLock) {
writePolicyAL();
@@ -4220,6 +4242,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mUidFirewallStandbyRules.delete(uid);
mUidFirewallDozableRules.delete(uid);
mUidFirewallPowerSaveRules.delete(uid);
+ mUidFirewallIsolatedRules.delete(uid);
mPowerSaveWhitelistExceptIdleAppIds.delete(uid);
mPowerSaveWhitelistAppIds.delete(uid);
mPowerSaveTempWhitelistAppIds.delete(uid);
@@ -4254,6 +4277,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
// Update firewall and internal rules for Data Saver Mode.
updateRulesForDataUsageRestrictionsUL(uid);
+ updateRulesForIsolatedUL(uid);
}
/**
@@ -4426,6 +4450,42 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
}
}
+ private void updateRulesForIsolatedUL(int uid) {
+ final int uidPolicy = mUidPolicy.get(uid, POLICY_NONE);
+ final int oldUidRules = mUidRules.get(uid, RULE_NONE);
+ final boolean wasIsolated = (oldUidRules & RULE_REJECT_ISOLATED) != 0;
+ final boolean isIsolated = (uidPolicy & POLICY_REJECT_ALL) != 0;
+
+ if (isIsolated == wasIsolated) {
+ // No change
+ return;
+ }
+
+ final long token = Binder.clearCallingIdentity();
+ try {
+ setUidFirewallRule(FIREWALL_CHAIN_ISOLATED, uid,
+ isIsolated ? FIREWALL_RULE_DENY : FIREWALL_RULE_DEFAULT);
+ } finally {
+ Binder.restoreCallingIdentity(token);
+ }
+
+ int uidRules = oldUidRules;
+ if (isIsolated) {
+ uidRules |= RULE_REJECT_ISOLATED;
+ } else {
+ uidRules &= ~RULE_REJECT_ISOLATED;
+ }
+
+ if (uidRules == RULE_NONE) {
+ mUidRules.delete(uid);
+ } else {
+ mUidRules.put(uid, uidRules);
+ }
+
+ // Dispatch changed rule to existing listeners.
+ mHandler.obtainMessage(MSG_RULES_CHANGED, uid, uidRules).sendToTarget();
+ }
+
/**
* Updates the power-related part of the {@link #mUidRules} for a given map, and notify external
* listeners in case of change.
@@ -4508,7 +4568,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
newRule = isWhitelisted ? RULE_ALLOW_ALL : RULE_REJECT_ALL;
}
- final int newUidRules = (oldUidRules & MASK_METERED_NETWORKS) | newRule;
+ // Generate new uid rules, ensuring we persist any existing
+ // metered networks and network isolated rules.
+ final int newUidRules = (oldUidRules
+ & (MASK_METERED_NETWORKS | RULE_REJECT_ISOLATED)) | newRule;
if (LOGV) {
Log.v(TAG, "updateRulesForPowerRestrictionsUL(" + uid + ")"
@@ -4984,6 +5047,8 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mUidFirewallStandbyRules.put(uid, rule);
} else if (chain == FIREWALL_CHAIN_POWERSAVE) {
mUidFirewallPowerSaveRules.put(uid, rule);
+ } else if (chain == FIREWALL_CHAIN_ISOLATED) {
+ mUidFirewallIsolatedRules.put(uid, rule);
}
try {
@@ -5029,6 +5094,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_STANDBY, uid, FIREWALL_RULE_DEFAULT);
mNetworkManager
.setFirewallUidRule(FIREWALL_CHAIN_POWERSAVE, uid, FIREWALL_RULE_DEFAULT);
+ mNetworkManager.setFirewallUidRule(FIREWALL_CHAIN_ISOLATED, uid, FIREWALL_RULE_DEFAULT);
mNetworkManager.setUidMeteredNetworkWhitelist(uid, false);
mNetworkManager.setUidMeteredNetworkBlacklist(uid, false);
} catch (IllegalStateException e) {
@@ -5209,6 +5275,10 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
return uid < Process.FIRST_APPLICATION_UID;
}
+ static boolean isNetworkingIsolatedByUidRulesInternal(int uidRules) {
+ return hasRule(uidRules, RULE_REJECT_ISOLATED);
+ }
+
static boolean isUidNetworkingBlockedInternal(int uid, int uidRules, boolean isNetworkMetered,
boolean isBackgroundRestricted, @Nullable NetworkPolicyLogger logger) {
final int reason;
@@ -5216,6 +5286,9 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
if (isSystem(uid)) {
reason = NTWK_ALLOWED_SYSTEM;
}
+ else if (hasRule(uidRules, RULE_REJECT_ISOLATED)) {
+ reason = NTWK_BLOCKED_ISOLATED;
+ }
else if (hasRule(uidRules, RULE_REJECT_ALL)) {
reason = NTWK_BLOCKED_POWER;
}
@@ -5250,6 +5323,7 @@ public class NetworkPolicyManagerService extends INetworkPolicyManager.Stub {
case NTWK_BLOCKED_POWER:
case NTWK_BLOCKED_BLACKLIST:
case NTWK_BLOCKED_BG_RESTRICT:
+ case NTWK_BLOCKED_ISOLATED:
blocked = true;
break;
default: