Tell netd about local networks

This patch does the following :
• When a network is local but the system doesn't support it,
  throw in registerNetworkAgent.
• When a network is local, tell netd about it.
• Add tests for the above, as well as a test for callbacks
  being sent correctly when the caps are set and not when
  they aren't and that the new keep connected flag is
  respected.

Telling netd about the network being local has it add two
routes that do not exist if the network is not local :
• One at PRIORITY_LOCAL_NETWORK matching unmarked sockets
  and looking up the table for the interface.
20000: from all fwmark 0x0/0x10000 lookup xxxx
• One at PRIORITY_EXPLICIT_NETWORK matching explicitly on
  network 99, so that dnsmasq traffic and any OEM traffic
  marked for network 99 flowing there.
16000: from all fwmark 0x10063/0x1ffff iif lo lookup xxxx
IMPLICIT_NETWORK and EXPLICIT_NETWORK rules are installed
by connectivity service as a matter of course whether the
network is local or not.

See commit If8729fc6f3716a580c936584b851bc38000b5de5 for
implementation details of this mechanic.

There is no need to implement anything in particular for the
new connected reason, as the current implementation will
already keep it connected. A new test makes sure of that.

Test: FrameworksNetTests
      CtsNetTestCases
      FrameworksNetIntegrationTests
      NetworkStackTests
      NetworkStaticLibTests
      TetheringTests
      MtsTetheringTestLatestSdk
      TetheringIntegrationTests
Change-Id: I6fb7dfe4c232eea8cac9ac268897ddb36bb794d1
This commit is contained in:
Chalard Jean
2023-08-10 17:01:11 +09:00
parent 10353d5351
commit 774dc3cd51
3 changed files with 148 additions and 7 deletions

View File

@@ -19,6 +19,7 @@ package com.android.server;
import static android.Manifest.permission.RECEIVE_DATA_ACTIVITY_CHANGE;
import static android.app.ActivityManager.UidFrozenStateChangedCallback.UID_FROZEN_STATE_FROZEN;
import static android.content.pm.PackageManager.FEATURE_BLUETOOTH;
import static android.content.pm.PackageManager.FEATURE_LEANBACK;
import static android.content.pm.PackageManager.FEATURE_WATCH;
import static android.content.pm.PackageManager.FEATURE_WIFI;
import static android.content.pm.PackageManager.FEATURE_WIFI_DIRECT;
@@ -67,6 +68,7 @@ import static android.net.NetworkCapabilities.NET_CAPABILITY_CAPTIVE_PORTAL;
import static android.net.NetworkCapabilities.NET_CAPABILITY_ENTERPRISE;
import static android.net.NetworkCapabilities.NET_CAPABILITY_FOREGROUND;
import static android.net.NetworkCapabilities.NET_CAPABILITY_INTERNET;
import static android.net.NetworkCapabilities.NET_CAPABILITY_LOCAL_NETWORK;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_CONGESTED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_METERED;
import static android.net.NetworkCapabilities.NET_CAPABILITY_NOT_RESTRICTED;
@@ -5006,7 +5008,10 @@ public class ConnectivityService extends IConnectivityManager.Stub
!nai.networkAgentConfig.allowBypass /* secure */,
getVpnType(nai), nai.networkAgentConfig.excludeLocalRouteVpn);
} else {
config = new NativeNetworkConfig(nai.network.getNetId(), NativeNetworkType.PHYSICAL,
final boolean hasLocalCap =
nai.networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK);
config = new NativeNetworkConfig(nai.network.getNetId(),
hasLocalCap ? NativeNetworkType.PHYSICAL_LOCAL : NativeNetworkType.PHYSICAL,
getNetworkPermission(nai.networkCapabilities),
false /* secure */,
VpnManager.TYPE_VPN_NONE,
@@ -8055,6 +8060,18 @@ public class ConnectivityService extends IConnectivityManager.Stub
return nai == getDefaultNetwork();
}
/**
* Returns whether local agents are supported on this device.
*
* Local agents are supported from U on TVs, and from V on all devices.
*/
@VisibleForTesting
public boolean areLocalAgentsSupported() {
final PackageManager pm = mContext.getPackageManager();
// Local agents are supported starting on U on TVs and on V on everything else.
return mDeps.isAtLeastV() || (mDeps.isAtLeastU() && pm.hasSystemFeature(FEATURE_LEANBACK));
}
/**
* Register a new agent with ConnectivityService to handle a network.
*
@@ -8084,6 +8101,12 @@ public class ConnectivityService extends IConnectivityManager.Stub
} else {
enforceNetworkFactoryPermission();
}
final boolean hasLocalCap =
networkCapabilities.hasCapability(NET_CAPABILITY_LOCAL_NETWORK);
if (hasLocalCap && !areLocalAgentsSupported()) {
// Before U, netd doesn't support PHYSICAL_LOCAL networks so this can't work.
throw new IllegalArgumentException("Local agents are not supported in this version");
}
final int uid = mDeps.getCallingUid();
final long token = Binder.clearCallingIdentity();
@@ -9189,7 +9212,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
// are Type.LISTEN, but should not have NetworkCallbacks invoked.
return;
}
Bundle bundle = new Bundle();
final Bundle bundle = new Bundle();
// TODO b/177608132: make sure callbacks are indexed by NRIs and not NetworkRequest objects.
// TODO: check if defensive copies of data is needed.
final NetworkRequest nrForCallback = nri.getNetworkRequestForCallback();

View File

@@ -64,7 +64,6 @@ import android.util.SparseArray;
import com.android.internal.annotations.VisibleForTesting;
import com.android.internal.util.IndentingPrintWriter;
import com.android.internal.util.WakeupMessage;
import com.android.modules.utils.build.SdkLevel;
import com.android.server.ConnectivityService;
import java.io.PrintWriter;
@@ -470,8 +469,8 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
+ networkCapabilities.getOwnerUid() + " to " + nc.getOwnerUid());
nc.setOwnerUid(networkCapabilities.getOwnerUid());
}
restrictCapabilitiesFromNetworkAgent(
nc, creatorUid, mHasAutomotiveFeature, carrierPrivilegeAuthenticator);
restrictCapabilitiesFromNetworkAgent(nc, creatorUid, mHasAutomotiveFeature,
mConnServiceDeps, carrierPrivilegeAuthenticator);
return nc;
}
@@ -601,6 +600,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
private static final String TAG = ConnectivityService.class.getSimpleName();
private static final boolean VDBG = false;
private final ConnectivityService mConnService;
private final ConnectivityService.Dependencies mConnServiceDeps;
private final Context mContext;
private final Handler mHandler;
private final QosCallbackTracker mQosCallbackTracker;
@@ -628,6 +628,7 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
networkCapabilities = nc;
networkAgentConfig = config;
mConnService = connService;
mConnServiceDeps = deps;
setScore(score); // uses members connService, networkCapabilities and networkAgentConfig
clatd = new Nat464Xlat(this, netd, dnsResolver, deps);
mContext = context;
@@ -1518,23 +1519,26 @@ public class NetworkAgentInfo implements NetworkRanker.Scoreable {
*/
public static void restrictCapabilitiesFromNetworkAgent(@NonNull final NetworkCapabilities nc,
final int creatorUid, final boolean hasAutomotiveFeature,
@NonNull final ConnectivityService.Dependencies deps,
@Nullable final CarrierPrivilegeAuthenticator authenticator) {
if (nc.hasTransport(TRANSPORT_TEST)) {
nc.restrictCapabilitiesForTestNetwork(creatorUid);
}
if (!areAllowedUidsAcceptableFromNetworkAgent(nc, hasAutomotiveFeature, authenticator)) {
if (!areAllowedUidsAcceptableFromNetworkAgent(
nc, hasAutomotiveFeature, deps, authenticator)) {
nc.setAllowedUids(new ArraySet<>());
}
}
private static boolean areAllowedUidsAcceptableFromNetworkAgent(
@NonNull final NetworkCapabilities nc, final boolean hasAutomotiveFeature,
@NonNull final ConnectivityService.Dependencies deps,
@Nullable final CarrierPrivilegeAuthenticator carrierPrivilegeAuthenticator) {
// NCs without access UIDs are fine.
if (!nc.hasAllowedUids()) return true;
// S and below must never accept access UIDs, even if an agent sends them, because netd
// didn't support the required feature in S.
if (!SdkLevel.isAtLeastT()) return false;
if (!deps.isAtLeastT()) return false;
// On a non-restricted network, access UIDs make no sense
if (nc.hasCapability(NET_CAPABILITY_NOT_RESTRICTED)) return false;