[NETD-TC#15] Make ConnectivityService and PermissionMonitor
calls BpfNetMaps on T
Since TrafficController moves to mainline module for T, so some netd binder
interfaces revelant to BPF are going to deprecated. Provide JNI APIs to
call TrafficController inside mainline module for T.
Bug: 209935649
Test: atest CtsHostsideNetworkTests
Change-Id: Ib3b43cf2840e02806395af9f1e019ca6fccd032e
diff --git a/service/src/com/android/server/BpfNetMaps.java b/service/src/com/android/server/BpfNetMaps.java
index 9d89788..e444a12 100644
--- a/service/src/com/android/server/BpfNetMaps.java
+++ b/service/src/com/android/server/BpfNetMaps.java
@@ -16,6 +16,8 @@
package com.android.server;
+import android.net.INetd;
+import android.os.RemoteException;
import android.os.ServiceSpecificException;
import android.system.Os;
import android.util.Log;
@@ -27,10 +29,19 @@
*/
public class BpfNetMaps {
private static final String TAG = "BpfNetMaps";
+ private final INetd mNetd;
+ // TODO: change USE_JNI to SdkLevel.isAtLeastT()
+ private static final boolean USE_JNI = false;
static {
- System.loadLibrary("traffic_controller_jni");
- native_init();
+ if (USE_JNI) {
+ System.loadLibrary("traffic_controller_jni");
+ native_init();
+ }
+ }
+
+ public BpfNetMaps(INetd netd) {
+ mNetd = netd;
}
/**
@@ -41,6 +52,14 @@
* cause of the failure.
*/
public void addNaughtyApp(final int uid) {
+ if (!USE_JNI) {
+ try {
+ mNetd.bandwidthAddNaughtyApp(uid);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return;
+ }
final int err = native_addNaughtyApp(uid);
if (err != 0) {
throw new ServiceSpecificException(err, "Unable to add naughty app: "
@@ -56,6 +75,14 @@
* cause of the failure.
*/
public void removeNaughtyApp(final int uid) {
+ if (!USE_JNI) {
+ try {
+ mNetd.bandwidthRemoveNaughtyApp(uid);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return;
+ }
final int err = native_removeNaughtyApp(uid);
if (err != 0) {
throw new ServiceSpecificException(err, "Unable to remove naughty app: "
@@ -71,6 +98,14 @@
* cause of the failure.
*/
public void addNiceApp(final int uid) {
+ if (!USE_JNI) {
+ try {
+ mNetd.bandwidthAddNiceApp(uid);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return;
+ }
final int err = native_addNiceApp(uid);
if (err != 0) {
throw new ServiceSpecificException(err, "Unable to add nice app: "
@@ -86,6 +121,14 @@
* cause of the failure.
*/
public void removeNiceApp(final int uid) {
+ if (!USE_JNI) {
+ try {
+ mNetd.bandwidthRemoveNiceApp(uid);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return;
+ }
final int err = native_removeNiceApp(uid);
if (err != 0) {
throw new ServiceSpecificException(err, "Unable to remove nice app: "
@@ -102,6 +145,14 @@
* cause of the failure.
*/
public void setChildChain(final int childChain, final boolean enable) {
+ if (!USE_JNI) {
+ try {
+ mNetd.firewallEnableChildChain(childChain, enable);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return;
+ }
final int err = native_setChildChain(childChain, enable);
if (err != 0) {
throw new ServiceSpecificException(-err, "Unable to set child chain: "
@@ -124,6 +175,14 @@
*/
public int replaceUidChain(final String chainName, final boolean isAllowlist,
final int[] uids) {
+ if (!USE_JNI) {
+ try {
+ mNetd.firewallReplaceUidChain(chainName, isAllowlist, uids);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return 0;
+ }
final int err = native_replaceUidChain(chainName, isAllowlist, uids);
if (err != 0) {
Log.e(TAG, "replaceUidChain failed: " + Os.strerror(-err));
@@ -140,8 +199,15 @@
* @throws ServiceSpecificException in case of failure, with an error code indicating the
* cause of the failure.
*/
- public void setUidRule(final int childChain, final int uid,
- final int firewallRule) {
+ public void setUidRule(final int childChain, final int uid, final int firewallRule) {
+ if (!USE_JNI) {
+ try {
+ mNetd.firewallSetUidRule(childChain, uid, firewallRule);
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return;
+ }
final int err = native_setUidRule(childChain, uid, firewallRule);
if (err != 0) {
throw new ServiceSpecificException(-err, "Unable to set uid rule: "
@@ -166,6 +232,14 @@
* cause of the failure.
*/
public void addUidInterfaceRules(final String ifName, final int[] uids) {
+ if (!USE_JNI) {
+ try {
+ mNetd.firewallAddUidInterfaceRules(ifName, uids);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception when updating permissions: " + e);
+ }
+ return;
+ }
final int err = native_addUidInterfaceRules(ifName, uids);
if (err != 0) {
throw new ServiceSpecificException(err, "Unable to add uid interface rules: "
@@ -184,6 +258,14 @@
* cause of the failure.
*/
public void removeUidInterfaceRules(final int[] uids) {
+ if (!USE_JNI) {
+ try {
+ mNetd.firewallRemoveUidInterfaceRules(uids);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Exception when updating permissions: " + e);
+ }
+ return;
+ }
final int err = native_removeUidInterfaceRules(uids);
if (err != 0) {
throw new ServiceSpecificException(err, "Unable to remove uid interface rules: "
@@ -197,6 +279,14 @@
* cause of the failure.
*/
public void swapActiveStatsMap() {
+ if (!USE_JNI) {
+ try {
+ mNetd.trafficSwapActiveStatsMap();
+ } catch (RemoteException e) {
+ throw new IllegalStateException(e);
+ }
+ return;
+ }
final int err = native_swapActiveStatsMap();
if (err != 0) {
throw new ServiceSpecificException(err, "Unable to swap active stats map: "
@@ -213,8 +303,16 @@
* revoke all permissions for the uids.
* @param uids uid of users to grant permission
*/
- public void setNetPermForUids(final int permission, final int[] uids) {
- native_setPermissionForUids(permission, uids);
+ public void setNetPermForUids(final int permissions, final int[] uids) {
+ if (!USE_JNI) {
+ try {
+ mNetd.trafficSetNetPermForUids(permissions, uids);
+ } catch (RemoteException e) {
+ Log.e(TAG, "Pass appId list of special permission failed." + e);
+ }
+ return;
+ }
+ native_setPermissionForUids(permissions, uids);
}
/**
@@ -255,7 +353,7 @@
private native int native_addUidInterfaceRules(String ifName, int[] uids);
private native int native_removeUidInterfaceRules(int[] uids);
private native int native_swapActiveStatsMap();
- private native void native_setPermissionForUids(int permission, int[] uids);
+ private native void native_setPermissionForUids(int permissions, int[] uids);
private native int native_setCounterSet(int counterSet, int uid);
private native int native_deleteTagData(int tag, int uid);
}
diff --git a/service/src/com/android/server/ConnectivityService.java b/service/src/com/android/server/ConnectivityService.java
index fa7dfa9..0259f7d 100644
--- a/service/src/com/android/server/ConnectivityService.java
+++ b/service/src/com/android/server/ConnectivityService.java
@@ -396,6 +396,7 @@
private NetworkStatsManager mStatsManager;
private NetworkPolicyManager mPolicyManager;
private final NetdCallback mNetdCallback;
+ private final BpfNetMaps mBpfNetMaps;
/**
* TestNetworkService (lazily) created upon first usage. Locked to prevent creation of multiple
@@ -1335,6 +1336,15 @@
return DeviceConfigUtils.isFeatureEnabled(context, NAMESPACE_CONNECTIVITY, name,
TETHERING_MODULE_NAME, defaultEnabled);
}
+
+ /**
+ * Get the BpfNetMaps implementation to use in ConnectivityService.
+ * @param netd
+ * @return BpfNetMaps implementation.
+ */
+ public BpfNetMaps getBpfNetMaps(INetd netd) {
+ return new BpfNetMaps(netd);
+ }
}
public ConnectivityService(Context context) {
@@ -1403,6 +1413,7 @@
mProxyTracker = mDeps.makeProxyTracker(mContext, mHandler);
mNetd = netd;
+ mBpfNetMaps = mDeps.getBpfNetMaps(netd);
mTelephonyManager = (TelephonyManager) mContext.getSystemService(Context.TELEPHONY_SERVICE);
mAppOpsManager = (AppOpsManager) mContext.getSystemService(Context.APP_OPS_SERVICE);
mLocationPermissionChecker = mDeps.makeLocationPermissionChecker(mContext);
@@ -1430,7 +1441,7 @@
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
- mPermissionMonitor = new PermissionMonitor(mContext, mNetd);
+ mPermissionMonitor = new PermissionMonitor(mContext, mNetd, mBpfNetMaps);
mUserAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
// Listen for user add/removes to inform PermissionMonitor.
@@ -10709,11 +10720,11 @@
try {
if (add) {
- mNetd.bandwidthAddNiceApp(uid);
+ mBpfNetMaps.addNiceApp(uid);
} else {
- mNetd.bandwidthRemoveNiceApp(uid);
+ mBpfNetMaps.removeNiceApp(uid);
}
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -10724,11 +10735,11 @@
try {
if (add) {
- mNetd.bandwidthAddNaughtyApp(uid);
+ mBpfNetMaps.addNaughtyApp(uid);
} else {
- mNetd.bandwidthRemoveNaughtyApp(uid);
+ mBpfNetMaps.removeNaughtyApp(uid);
}
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -10738,9 +10749,9 @@
enforceNetworkStackOrSettingsPermission();
try {
- mNetd.firewallSetUidRule(chain, uid,
+ mBpfNetMaps.setUidRule(chain, uid,
allow ? INetd.FIREWALL_RULE_ALLOW : INetd.FIREWALL_RULE_DENY);
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -10750,8 +10761,8 @@
enforceNetworkStackOrSettingsPermission();
try {
- mNetd.firewallEnableChildChain(chain, enable);
- } catch (RemoteException | ServiceSpecificException e) {
+ mBpfNetMaps.setChildChain(chain, enable);
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -10763,22 +10774,22 @@
try {
switch (chain) {
case ConnectivityManager.FIREWALL_CHAIN_DOZABLE:
- mNetd.firewallReplaceUidChain("fw_dozable", true /* isAllowList */, uids);
+ mBpfNetMaps.replaceUidChain("fw_dozable", true /* isAllowList */, uids);
break;
case ConnectivityManager.FIREWALL_CHAIN_STANDBY:
- mNetd.firewallReplaceUidChain("fw_standby", false /* isAllowList */, uids);
+ mBpfNetMaps.replaceUidChain("fw_standby", false /* isAllowList */, uids);
break;
case ConnectivityManager.FIREWALL_CHAIN_POWERSAVE:
- mNetd.firewallReplaceUidChain("fw_powersave", true /* isAllowList */, uids);
+ mBpfNetMaps.replaceUidChain("fw_powersave", true /* isAllowList */, uids);
break;
case ConnectivityManager.FIREWALL_CHAIN_RESTRICTED:
- mNetd.firewallReplaceUidChain("fw_restricted", true /* isAllowList */, uids);
+ mBpfNetMaps.replaceUidChain("fw_restricted", true /* isAllowList */, uids);
break;
default:
throw new IllegalArgumentException("replaceFirewallChain with invalid chain: "
+ chain);
}
- } catch (RemoteException | ServiceSpecificException e) {
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
@@ -10787,8 +10798,8 @@
public void swapActiveStatsMap() {
enforceNetworkStackOrSettingsPermission();
try {
- mNetd.trafficSwapActiveStatsMap();
- } catch (RemoteException | ServiceSpecificException e) {
+ mBpfNetMaps.swapActiveStatsMap();
+ } catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}
diff --git a/service/src/com/android/server/connectivity/PermissionMonitor.java b/service/src/com/android/server/connectivity/PermissionMonitor.java
index 439db89..c9c1776 100755
--- a/service/src/com/android/server/connectivity/PermissionMonitor.java
+++ b/service/src/com/android/server/connectivity/PermissionMonitor.java
@@ -68,6 +68,7 @@
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.net.module.util.CollectionUtils;
+import com.android.server.BpfNetMaps;
import java.util.ArrayList;
import java.util.HashMap;
@@ -93,6 +94,7 @@
private final INetd mNetd;
private final Dependencies mDeps;
private final Context mContext;
+ private final BpfNetMaps mBpfNetMaps;
@GuardedBy("this")
private final Set<UserHandle> mUsers = new HashSet<>();
@@ -184,12 +186,14 @@
}
}
- public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) {
- this(context, netd, new Dependencies());
+ public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd,
+ @NonNull final BpfNetMaps bpfNetMaps) {
+ this(context, netd, bpfNetMaps, new Dependencies());
}
@VisibleForTesting
PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd,
+ @NonNull final BpfNetMaps bpfNetMaps,
@NonNull final Dependencies deps) {
mPackageManager = context.getPackageManager();
mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
@@ -197,6 +201,7 @@
mNetd = netd;
mDeps = deps;
mContext = context;
+ mBpfNetMaps = bpfNetMaps;
}
private int getPackageNetdNetworkPermission(@NonNull final PackageInfo app) {
@@ -803,9 +808,9 @@
}
try {
if (add) {
- mNetd.firewallAddUidInterfaceRules(iface, toIntArray(uids));
+ mBpfNetMaps.addUidInterfaceRules(iface, toIntArray(uids));
} else {
- mNetd.firewallRemoveUidInterfaceRules(toIntArray(uids));
+ mBpfNetMaps.removeUidInterfaceRules(toIntArray(uids));
}
} catch (ServiceSpecificException e) {
// Silently ignore exception when device does not support eBPF, otherwise just log
@@ -813,8 +818,6 @@
if (e.errorCode != OsConstants.EOPNOTSUPP) {
loge("Exception when updating permissions: ", e);
}
- } catch (RemoteException e) {
- loge("Exception when updating permissions: ", e);
}
}
@@ -878,26 +881,27 @@
try {
// TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids()
if (allPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(
+ mBpfNetMaps.setNetPermForUids(
PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS,
toIntArray(allPermissionAppIds));
}
if (internetPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(PERMISSION_INTERNET,
+ mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET,
toIntArray(internetPermissionAppIds));
}
if (updateStatsPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS,
+ mBpfNetMaps.setNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS,
toIntArray(updateStatsPermissionAppIds));
}
if (noPermissionAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(PERMISSION_NONE, toIntArray(noPermissionAppIds));
+ mBpfNetMaps.setNetPermForUids(PERMISSION_NONE,
+ toIntArray(noPermissionAppIds));
}
if (uninstalledAppIds.size() != 0) {
- mNetd.trafficSetNetPermForUids(PERMISSION_UNINSTALLED,
+ mBpfNetMaps.setNetPermForUids(PERMISSION_UNINSTALLED,
toIntArray(uninstalledAppIds));
}
- } catch (RemoteException e) {
+ } catch (ServiceSpecificException e) {
Log.e(TAG, "Pass appId list of special permission failed." + e);
}
}
diff --git a/tests/unit/java/com/android/server/BpfNetMapsTest.java b/tests/unit/java/com/android/server/BpfNetMapsTest.java
new file mode 100644
index 0000000..ac21e77
--- /dev/null
+++ b/tests/unit/java/com/android/server/BpfNetMapsTest.java
@@ -0,0 +1,86 @@
+/*
+ * Copyright (C) 2022 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 static android.net.INetd.FIREWALL_CHAIN_DOZABLE;
+import static android.net.INetd.FIREWALL_RULE_ALLOW;
+import static android.net.INetd.PERMISSION_INTERNET;
+
+import static org.junit.Assume.assumeFalse;
+import static org.mockito.Mockito.verify;
+
+import android.net.INetd;
+import android.os.Build;
+
+import androidx.test.filters.SmallTest;
+
+import com.android.modules.utils.build.SdkLevel;
+import com.android.testutils.DevSdkIgnoreRule;
+import com.android.testutils.DevSdkIgnoreRunner;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.mockito.Mock;
+import org.mockito.MockitoAnnotations;
+
+@RunWith(DevSdkIgnoreRunner.class)
+@SmallTest
+@DevSdkIgnoreRule.IgnoreUpTo(Build.VERSION_CODES.R)
+public final class BpfNetMapsTest {
+ private static final String TAG = "BpfNetMapsTest";
+ private static final int TEST_UID = 10086;
+ private static final int[] TEST_UIDS = {10002, 10003};
+ private static final String IFNAME = "wlan0";
+ private static final String CHAINNAME = "fw_dozable";
+ private BpfNetMaps mBpfNetMaps;
+
+ @Mock INetd mNetd;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ mBpfNetMaps = new BpfNetMaps(mNetd);
+ }
+
+ @Test
+ public void testBpfNetMapsBeforeT() throws Exception {
+ assumeFalse(SdkLevel.isAtLeastT());
+ mBpfNetMaps.addNaughtyApp(TEST_UID);
+ verify(mNetd).bandwidthAddNaughtyApp(TEST_UID);
+ mBpfNetMaps.removeNaughtyApp(TEST_UID);
+ verify(mNetd).bandwidthRemoveNaughtyApp(TEST_UID);
+ mBpfNetMaps.addNiceApp(TEST_UID);
+ verify(mNetd).bandwidthAddNiceApp(TEST_UID);
+ mBpfNetMaps.removeNiceApp(TEST_UID);
+ verify(mNetd).bandwidthRemoveNiceApp(TEST_UID);
+ mBpfNetMaps.setChildChain(FIREWALL_CHAIN_DOZABLE, true);
+ verify(mNetd).firewallEnableChildChain(FIREWALL_CHAIN_DOZABLE, true);
+ mBpfNetMaps.replaceUidChain(CHAINNAME, true, TEST_UIDS);
+ verify(mNetd).firewallReplaceUidChain(CHAINNAME, true, TEST_UIDS);
+ mBpfNetMaps.setUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_ALLOW);
+ verify(mNetd).firewallSetUidRule(FIREWALL_CHAIN_DOZABLE, TEST_UID, FIREWALL_RULE_ALLOW);
+ mBpfNetMaps.addUidInterfaceRules(IFNAME, TEST_UIDS);
+ verify(mNetd).firewallAddUidInterfaceRules(IFNAME, TEST_UIDS);
+ mBpfNetMaps.removeUidInterfaceRules(TEST_UIDS);
+ verify(mNetd).firewallRemoveUidInterfaceRules(TEST_UIDS);
+ mBpfNetMaps.swapActiveStatsMap();
+ verify(mNetd).trafficSwapActiveStatsMap();
+ mBpfNetMaps.setNetPermForUids(PERMISSION_INTERNET, TEST_UIDS);
+ verify(mNetd).trafficSetNetPermForUids(PERMISSION_INTERNET, TEST_UIDS);
+ }
+}
diff --git a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
index 99ef80b..6590543 100644
--- a/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
+++ b/tests/unit/java/com/android/server/connectivity/PermissionMonitorTest.java
@@ -89,6 +89,7 @@
import androidx.test.filters.SmallTest;
import com.android.net.module.util.CollectionUtils;
+import com.android.server.BpfNetMaps;
import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRunner;
@@ -146,9 +147,11 @@
@Mock private UserManager mUserManager;
@Mock private PermissionMonitor.Dependencies mDeps;
@Mock private SystemConfigManager mSystemConfigManager;
+ @Mock private BpfNetMaps mBpfNetMaps;
private PermissionMonitor mPermissionMonitor;
private NetdMonitor mNetdMonitor;
+ private BpfMapMonitor mBpfMapMonitor;
@Before
public void setUp() throws Exception {
@@ -177,8 +180,9 @@
// by default.
doReturn(VERSION_Q).when(mDeps).getDeviceFirstSdkInt();
- mPermissionMonitor = new PermissionMonitor(mContext, mNetdService, mDeps);
+ mPermissionMonitor = new PermissionMonitor(mContext, mNetdService, mBpfNetMaps, mDeps);
mNetdMonitor = new NetdMonitor(mNetdService);
+ mBpfMapMonitor = new BpfMapMonitor(mBpfNetMaps);
doReturn(List.of()).when(mPackageManager).getInstalledPackagesAsUser(anyInt(), anyInt());
}
@@ -511,9 +515,37 @@
assertBackgroundPermission(true, MOCK_PACKAGE2, MOCK_UID12, NETWORK_STACK);
}
+ private class BpfMapMonitor {
+ private final SparseIntArray mAppIdsTrafficPermission = new SparseIntArray();
+ private static final int DOES_NOT_EXIST = -2;
+
+ BpfMapMonitor(BpfNetMaps mockBpfmap) throws Exception {
+ // Add hook to verify and track result of trafficSetNetPerm.
+ doAnswer((InvocationOnMock invocation) -> {
+ final Object[] args = invocation.getArguments();
+ final int permission = (int) args[0];
+ for (final int appId : (int[]) args[1]) {
+ mAppIdsTrafficPermission.put(appId, permission);
+ }
+ return null;
+ }).when(mockBpfmap).setNetPermForUids(anyInt(), any(int[].class));
+ }
+
+ public void expectTrafficPerm(int permission, int... appIds) {
+ for (final int appId : appIds) {
+ if (mAppIdsTrafficPermission.get(appId, DOES_NOT_EXIST) == DOES_NOT_EXIST) {
+ fail("appId " + appId + " does not exist.");
+ }
+ if (mAppIdsTrafficPermission.get(appId) != permission) {
+ fail("appId " + appId + " has wrong permission: "
+ + mAppIdsTrafficPermission.get(appId));
+ }
+ }
+ }
+ }
+
private class NetdMonitor {
private final SparseIntArray mUidsNetworkPermission = new SparseIntArray();
- private final SparseIntArray mAppIdsTrafficPermission = new SparseIntArray();
private static final int DOES_NOT_EXIST = -2;
NetdMonitor(INetd mockNetd) throws Exception {
@@ -545,16 +577,6 @@
}
return null;
}).when(mockNetd).networkClearPermissionForUser(any(int[].class));
-
- // Add hook to verify and track result of trafficSetNetPerm.
- doAnswer((InvocationOnMock invocation) -> {
- final Object[] args = invocation.getArguments();
- final int permission = (int) args[0];
- for (final int appId : (int[]) args[1]) {
- mAppIdsTrafficPermission.put(appId, permission);
- }
- return null;
- }).when(mockNetd).trafficSetNetPermForUids(anyInt(), any(int[].class));
}
public void expectNetworkPerm(int permission, UserHandle[] users, int... appIds) {
@@ -581,18 +603,6 @@
}
}
}
-
- public void expectTrafficPerm(int permission, int... appIds) {
- for (final int appId : appIds) {
- if (mAppIdsTrafficPermission.get(appId, DOES_NOT_EXIST) == DOES_NOT_EXIST) {
- fail("appId " + appId + " does not exist.");
- }
- if (mAppIdsTrafficPermission.get(appId) != permission) {
- fail("appId " + appId + " has wrong permission: "
- + mAppIdsTrafficPermission.get(appId));
- }
- }
- }
}
@Test
@@ -702,30 +712,30 @@
// When VPN is connected, expect a rule to be set up for user app MOCK_UID11
mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange1, VPN_UID);
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID11}));
+ verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID11}));
- reset(mNetdService);
+ reset(mBpfNetMaps);
// When MOCK_UID11 package is uninstalled and reinstalled, expect Netd to be updated
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID11);
- verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[]{MOCK_UID11}));
+ verify(mBpfNetMaps).removeUidInterfaceRules(aryEq(new int[]{MOCK_UID11}));
mPermissionMonitor.onPackageAdded(MOCK_PACKAGE1, MOCK_UID11);
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID11}));
+ verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID11}));
- reset(mNetdService);
+ reset(mBpfNetMaps);
// During VPN uid update (vpnRange1 -> vpnRange2), ConnectivityService first deletes the
// old UID rules then adds the new ones. Expect netd to be updated
mPermissionMonitor.onVpnUidRangesRemoved("tun0", vpnRange1, VPN_UID);
- verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID11}));
+ verify(mBpfNetMaps).removeUidInterfaceRules(aryEq(new int[] {MOCK_UID11}));
mPermissionMonitor.onVpnUidRangesAdded("tun0", vpnRange2, VPN_UID);
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID12}));
+ verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID12}));
- reset(mNetdService);
+ reset(mBpfNetMaps);
// When VPN is disconnected, expect rules to be torn down
mPermissionMonitor.onVpnUidRangesRemoved("tun0", vpnRange2, VPN_UID);
- verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[] {MOCK_UID12}));
+ verify(mBpfNetMaps).removeUidInterfaceRules(aryEq(new int[] {MOCK_UID12}));
assertNull(mPermissionMonitor.getVpnUidRanges("tun0"));
}
@@ -744,13 +754,13 @@
// Newly-installed package should have uid rules added
addPackageForUsers(new UserHandle[]{MOCK_USER1, MOCK_USER2}, MOCK_PACKAGE1, MOCK_APPID1);
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID11}));
- verify(mNetdService).firewallAddUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID21}));
+ verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID11}));
+ verify(mBpfNetMaps).addUidInterfaceRules(eq("tun0"), aryEq(new int[]{MOCK_UID21}));
// Removed package should have its uid rules removed
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID11);
- verify(mNetdService).firewallRemoveUidInterfaceRules(aryEq(new int[]{MOCK_UID11}));
- verify(mNetdService, never()).firewallRemoveUidInterfaceRules(aryEq(new int[]{MOCK_UID21}));
+ verify(mBpfNetMaps).removeUidInterfaceRules(aryEq(new int[]{MOCK_UID11}));
+ verify(mBpfNetMaps, never()).removeUidInterfaceRules(aryEq(new int[]{MOCK_UID21}));
}
@@ -784,91 +794,91 @@
// Send the permission information to netd, expect permission updated.
mPermissionMonitor.sendAppIdsTrafficPermission(netdPermissionsAppIds);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, SYSTEM_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, SYSTEM_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, SYSTEM_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, SYSTEM_APPID2);
// Update permission of MOCK_APPID1, expect new permission show up.
mPermissionMonitor.sendPackagePermissionsForAppId(MOCK_APPID1, PERMISSION_TRAFFIC_ALL);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
// Change permissions of SYSTEM_APPID2, expect new permission show up and old permission
// revoked.
mPermissionMonitor.sendPackagePermissionsForAppId(SYSTEM_APPID2, PERMISSION_INTERNET);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, SYSTEM_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, SYSTEM_APPID2);
// Revoke permission from SYSTEM_APPID1, expect no permission stored.
mPermissionMonitor.sendPackagePermissionsForAppId(SYSTEM_APPID1, PERMISSION_NONE);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, SYSTEM_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_NONE, SYSTEM_APPID1);
}
@Test
public void testPackageInstall() throws Exception {
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET, UPDATE_DEVICE_STATS);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
addPackage(MOCK_PACKAGE2, MOCK_UID12, INTERNET);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID2);
}
@Test
public void testPackageInstallSharedUid() throws Exception {
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET, UPDATE_DEVICE_STATS);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
// Install another package with the same uid and no permissions should not cause the app id
// to lose permissions.
addPackage(MOCK_PACKAGE2, MOCK_UID11);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
}
@Test
public void testPackageUninstallBasic() throws Exception {
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET, UPDATE_DEVICE_STATS);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
when(mPackageManager.getPackagesForUid(MOCK_UID11)).thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID11);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
}
@Test
public void testPackageRemoveThenAdd() throws Exception {
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET, UPDATE_DEVICE_STATS);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
when(mPackageManager.getPackagesForUid(MOCK_UID11)).thenReturn(new String[]{});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID11);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
}
@Test
public void testPackageUpdate() throws Exception {
addPackage(MOCK_PACKAGE1, MOCK_UID11);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1);
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
}
@Test
public void testPackageUninstallWithMultiplePackages() throws Exception {
addPackage(MOCK_PACKAGE1, MOCK_UID11, INTERNET, UPDATE_DEVICE_STATS);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
// Install another package with the same uid but different permissions.
addPackage(MOCK_PACKAGE2, MOCK_UID11, INTERNET);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID11);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_UID11);
// Uninstall MOCK_PACKAGE1 and expect only INTERNET permission left.
when(mPackageManager.getPackagesForUid(eq(MOCK_UID11)))
.thenReturn(new String[]{MOCK_PACKAGE2});
mPermissionMonitor.onPackageRemoved(MOCK_PACKAGE1, MOCK_UID11);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
}
@Test
@@ -876,7 +886,8 @@
// Use the real context as this test must ensure the *real* system package holds the
// necessary permission.
final Context realContext = InstrumentationRegistry.getContext();
- final PermissionMonitor monitor = new PermissionMonitor(realContext, mNetdService);
+ final PermissionMonitor monitor = new PermissionMonitor(realContext, mNetdService,
+ mBpfNetMaps);
final PackageManager manager = realContext.getPackageManager();
final PackageInfo systemInfo = manager.getPackageInfo(REAL_SYSTEM_PACKAGE_NAME,
GET_PERMISSIONS | MATCH_ANY_USER);
@@ -891,8 +902,8 @@
.thenReturn(new int[]{ MOCK_UID12 });
mPermissionMonitor.startMonitoring();
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID2);
}
private BroadcastReceiver expectBroadcastReceiver(String... actions) {
@@ -923,7 +934,7 @@
buildAndMockPackageInfoWithPermissions(MOCK_PACKAGE1, MOCK_UID11, INTERNET,
UPDATE_DEVICE_STATS);
receiver.onReceive(mContext, addedIntent);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
// Verify receiving PACKAGE_REMOVED intent.
when(mPackageManager.getPackagesForUid(MOCK_UID11)).thenReturn(new String[]{});
@@ -931,7 +942,7 @@
Uri.fromParts("package", MOCK_PACKAGE1, null /* fragment */));
removedIntent.putExtra(Intent.EXTRA_UID, MOCK_UID11);
receiver.onReceive(mContext, removedIntent);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_UNINSTALLED, MOCK_APPID1);
}
private ContentObserver expectRegisterContentObserver(Uri expectedUri) {
@@ -1070,7 +1081,7 @@
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
mPermissionMonitor.startMonitoring();
mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1, MOCK_APPID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1, MOCK_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1, MOCK_APPID2);
final BroadcastReceiver receiver = expectBroadcastReceiver(
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
@@ -1087,8 +1098,8 @@
MOCK_APPID1);
mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
MOCK_APPID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID2);
}
@Test
@@ -1114,8 +1125,8 @@
MOCK_APPID1);
mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
MOCK_APPID2);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID2);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID2);
}
@Test
@@ -1128,7 +1139,7 @@
.when(mPackageManager).getInstalledPackagesAsUser(eq(GET_PERMISSIONS), anyInt());
mPermissionMonitor.startMonitoring();
mNetdMonitor.expectNoNetworkPerm(new UserHandle[]{MOCK_USER1}, MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_NONE, MOCK_APPID1);
final BroadcastReceiver receiver = expectBroadcastReceiver(
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
@@ -1140,7 +1151,7 @@
receiver.onReceive(mContext, externalIntent);
mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_UPDATE_DEVICE_STATS, MOCK_APPID1);
}
@Test
@@ -1155,7 +1166,7 @@
mPermissionMonitor.startMonitoring();
mNetdMonitor.expectNetworkPerm(PERMISSION_NETWORK, new UserHandle[]{MOCK_USER1},
MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_INTERNET, MOCK_APPID1);
final BroadcastReceiver receiver = expectBroadcastReceiver(
Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
@@ -1169,7 +1180,7 @@
receiver.onReceive(mContext, externalIntent);
mNetdMonitor.expectNetworkPerm(PERMISSION_SYSTEM, new UserHandle[]{MOCK_USER1},
MOCK_APPID1);
- mNetdMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
+ mBpfMapMonitor.expectTrafficPerm(PERMISSION_TRAFFIC_ALL, MOCK_APPID1);
}
@Test