[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
This commit is contained in:
Wayne Ma
2022-01-17 18:04:05 +08:00
committed by Patrick Rohr
parent dd5bc74532
commit 2fde98c87b
5 changed files with 319 additions and 109 deletions

View File

@@ -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 @@ import android.util.Log;
*/
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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
* 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 class BpfNetMaps {
*/
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 @@ public class BpfNetMaps {
* @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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
* 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 @@ public class BpfNetMaps {
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);
}

View File

@@ -396,6 +396,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 @@ public class ConnectivityService extends IConnectivityManager.Stub
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 class ConnectivityService extends IConnectivityManager.Stub
public void swapActiveStatsMap() {
enforceNetworkStackOrSettingsPermission();
try {
mNetd.trafficSwapActiveStatsMap();
} catch (RemoteException | ServiceSpecificException e) {
mBpfNetMaps.swapActiveStatsMap();
} catch (ServiceSpecificException e) {
throw new IllegalStateException(e);
}
}

View File

@@ -68,6 +68,7 @@ import com.android.internal.annotations.GuardedBy;
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 @@ public class PermissionMonitor {
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 class PermissionMonitor {
}
}
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 @@ public class PermissionMonitor {
mNetd = netd;
mDeps = deps;
mContext = context;
mBpfNetMaps = bpfNetMaps;
}
private int getPackageNetdNetworkPermission(@NonNull final PackageInfo app) {
@@ -803,9 +808,9 @@ public class PermissionMonitor {
}
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 @@ public class PermissionMonitor {
if (e.errorCode != OsConstants.EOPNOTSUPP) {
loge("Exception when updating permissions: ", e);
}
} catch (RemoteException e) {
loge("Exception when updating permissions: ", e);
}
}
@@ -878,26 +881,27 @@ public class PermissionMonitor {
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);
}
}