Merge "NetworkCapabilities: Embed location senstive TransportInfo"

This commit is contained in:
Roshan Pius
2021-01-14 15:38:15 +00:00
committed by Gerrit Code Review
7 changed files with 235 additions and 49 deletions

View File

@@ -408,7 +408,8 @@ public abstract class NetworkAgent {
throw new IllegalArgumentException(); throw new IllegalArgumentException();
} }
mInitialConfiguration = new InitialConfiguration(context, new NetworkCapabilities(nc), mInitialConfiguration = new InitialConfiguration(context,
new NetworkCapabilities(nc, /* parcelLocationSensitiveFields */ true),
new LinkProperties(lp), score, config, ni); new LinkProperties(lp), score, config, ni);
} }
@@ -818,7 +819,9 @@ public abstract class NetworkAgent {
Objects.requireNonNull(networkCapabilities); Objects.requireNonNull(networkCapabilities);
mBandwidthUpdatePending.set(false); mBandwidthUpdatePending.set(false);
mLastBwRefreshTime = System.currentTimeMillis(); mLastBwRefreshTime = System.currentTimeMillis();
final NetworkCapabilities nc = new NetworkCapabilities(networkCapabilities); final NetworkCapabilities nc =
new NetworkCapabilities(networkCapabilities,
/* parcelLocationSensitiveFields */ true);
queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc)); queueOrSendMessage(reg -> reg.sendNetworkCapabilities(nc));
} }

View File

@@ -76,12 +76,33 @@ public final class NetworkCapabilities implements Parcelable {
*/ */
private String mRequestorPackageName; private String mRequestorPackageName;
/**
* Indicates whether parceling should preserve fields that are set based on permissions of
* the process receiving the {@link NetworkCapabilities}.
*/
private final boolean mParcelLocationSensitiveFields;
public NetworkCapabilities() { public NetworkCapabilities() {
mParcelLocationSensitiveFields = false;
clearAll(); clearAll();
mNetworkCapabilities = DEFAULT_CAPABILITIES; mNetworkCapabilities = DEFAULT_CAPABILITIES;
} }
public NetworkCapabilities(NetworkCapabilities nc) { public NetworkCapabilities(NetworkCapabilities nc) {
this(nc, false /* parcelLocationSensitiveFields */);
}
/**
* Make a copy of NetworkCapabilities.
*
* @param nc Original NetworkCapabilities
* @param parcelLocationSensitiveFields Whether to parcel location sensitive data or not.
* @hide
*/
@SystemApi
public NetworkCapabilities(
@Nullable NetworkCapabilities nc, boolean parcelLocationSensitiveFields) {
mParcelLocationSensitiveFields = parcelLocationSensitiveFields;
if (nc != null) { if (nc != null) {
set(nc); set(nc);
} }
@@ -93,6 +114,12 @@ public final class NetworkCapabilities implements Parcelable {
* @hide * @hide
*/ */
public void clearAll() { public void clearAll() {
// Ensures that the internal copies maintained by the connectivity stack does not set
// this bit.
if (mParcelLocationSensitiveFields) {
throw new UnsupportedOperationException(
"Cannot clear NetworkCapabilities when parcelLocationSensitiveFields is set");
}
mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0; mNetworkCapabilities = mTransportTypes = mUnwantedNetworkCapabilities = 0;
mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED; mLinkUpBandwidthKbps = mLinkDownBandwidthKbps = LINK_BANDWIDTH_UNSPECIFIED;
mNetworkSpecifier = null; mNetworkSpecifier = null;
@@ -109,6 +136,8 @@ public final class NetworkCapabilities implements Parcelable {
/** /**
* Set all contents of this object to the contents of a NetworkCapabilities. * Set all contents of this object to the contents of a NetworkCapabilities.
*
* @param nc Original NetworkCapabilities
* @hide * @hide
*/ */
public void set(@NonNull NetworkCapabilities nc) { public void set(@NonNull NetworkCapabilities nc) {
@@ -117,7 +146,11 @@ public final class NetworkCapabilities implements Parcelable {
mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps; mLinkUpBandwidthKbps = nc.mLinkUpBandwidthKbps;
mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps; mLinkDownBandwidthKbps = nc.mLinkDownBandwidthKbps;
mNetworkSpecifier = nc.mNetworkSpecifier; mNetworkSpecifier = nc.mNetworkSpecifier;
mTransportInfo = nc.mTransportInfo; if (nc.getTransportInfo() != null) {
setTransportInfo(nc.getTransportInfo().makeCopy(mParcelLocationSensitiveFields));
} else {
setTransportInfo(null);
}
mSignalStrength = nc.mSignalStrength; mSignalStrength = nc.mSignalStrength;
setUids(nc.mUids); // Will make the defensive copy setUids(nc.mUids); // Will make the defensive copy
setAdministratorUids(nc.getAdministratorUids()); setAdministratorUids(nc.getAdministratorUids());

View File

@@ -16,10 +16,48 @@
package android.net; package android.net;
import android.annotation.NonNull;
import android.annotation.SystemApi;
/** /**
* A container for transport-specific capabilities which is returned by * A container for transport-specific capabilities which is returned by
* {@link NetworkCapabilities#getTransportInfo()}. Specific networks * {@link NetworkCapabilities#getTransportInfo()}. Specific networks
* may provide concrete implementations of this interface. * may provide concrete implementations of this interface.
* @see android.net.wifi.aware.WifiAwareNetworkInfo
* @see android.net.wifi.WifiInfo
*/ */
public interface TransportInfo { public interface TransportInfo {
/**
* Create a copy of a {@link TransportInfo} that will preserve location sensitive fields that
* were set based on the permissions of the process that originally received it.
*
* <p>By default {@link TransportInfo} does not preserve such fields during parceling, as
* they should not be shared outside of the process that receives them without appropriate
* checks.
*
* @param parcelLocationSensitiveFields Whether the location sensitive fields should be kept
* when parceling
* @return Copy of this instance.
* @hide
*/
@SystemApi
@NonNull
default TransportInfo makeCopy(boolean parcelLocationSensitiveFields) {
return this;
}
/**
* Returns whether this TransportInfo type has location sensitive fields or not (helps
* to determine whether to perform a location permission check or not before sending to
* apps).
*
* @return {@code true} if this instance contains location sensitive info, {@code false}
* otherwise.
* @hide
*/
@SystemApi
default boolean hasLocationSensitiveFields() {
return false;
}
} }

View File

@@ -1569,7 +1569,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
if (nc != null) { if (nc != null) {
result.put( result.put(
nai.network, nai.network,
maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled(
nc, mDeps.getCallingUid(), callingPackageName)); nc, mDeps.getCallingUid(), callingPackageName));
} }
@@ -1579,7 +1579,9 @@ public class ConnectivityService extends IConnectivityManager.Stub
for (Network network : networks) { for (Network network : networks) {
nc = getNetworkCapabilitiesInternal(network); nc = getNetworkCapabilitiesInternal(network);
if (nc != null) { if (nc != null) {
result.put(network, maybeSanitizeLocationInfoForCaller( result.put(
network,
createWithLocationInfoSanitizedIfNecessaryWhenParceled(
nc, mDeps.getCallingUid(), callingPackageName)); nc, mDeps.getCallingUid(), callingPackageName));
} }
} }
@@ -1661,7 +1663,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) { public NetworkCapabilities getNetworkCapabilities(Network network, String callingPackageName) {
mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName); mAppOpsManager.checkPackage(mDeps.getCallingUid(), callingPackageName);
enforceAccessPermission(); enforceAccessPermission();
return maybeSanitizeLocationInfoForCaller( return createWithLocationInfoSanitizedIfNecessaryWhenParceled(
getNetworkCapabilitiesInternal(network), getNetworkCapabilitiesInternal(network),
mDeps.getCallingUid(), callingPackageName); mDeps.getCallingUid(), callingPackageName);
} }
@@ -1682,37 +1684,51 @@ public class ConnectivityService extends IConnectivityManager.Stub
return newNc; return newNc;
} }
private boolean hasLocationPermission(int callerUid, @NonNull String callerPkgName) {
final long token = Binder.clearCallingIdentity();
try {
return mLocationPermissionChecker.checkLocationPermission(
callerPkgName, null /* featureId */, callerUid, null /* message */);
} finally {
Binder.restoreCallingIdentity(token);
}
}
@VisibleForTesting @VisibleForTesting
@Nullable @Nullable
NetworkCapabilities maybeSanitizeLocationInfoForCaller( NetworkCapabilities createWithLocationInfoSanitizedIfNecessaryWhenParceled(
@Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) { @Nullable NetworkCapabilities nc, int callerUid, @NonNull String callerPkgName) {
if (nc == null) { if (nc == null) {
return null; return null;
} }
final NetworkCapabilities newNc = new NetworkCapabilities(nc); Boolean hasLocationPermission = null;
if (callerUid != newNc.getOwnerUid()) { final NetworkCapabilities newNc;
// Avoid doing location permission check if the transport info has no location sensitive
// data.
if (nc.getTransportInfo() != null && nc.getTransportInfo().hasLocationSensitiveFields()) {
hasLocationPermission = hasLocationPermission(callerUid, callerPkgName);
newNc = new NetworkCapabilities(nc, hasLocationPermission);
} else {
newNc = new NetworkCapabilities(nc, false /* parcelLocationSensitiveFields */);
}
// Reset owner uid if not destined for the owner app.
if (callerUid != nc.getOwnerUid()) {
newNc.setOwnerUid(INVALID_UID); newNc.setOwnerUid(INVALID_UID);
return newNc; return newNc;
} }
// Allow VPNs to see ownership of their own VPN networks - not location sensitive. // Allow VPNs to see ownership of their own VPN networks - not location sensitive.
if (nc.hasTransport(TRANSPORT_VPN)) { if (nc.hasTransport(TRANSPORT_VPN)) {
// Owner UIDs already checked above. No need to re-check. // Owner UIDs already checked above. No need to re-check.
return newNc; return newNc;
} }
if (hasLocationPermission == null) {
final long token = Binder.clearCallingIdentity(); // Location permission not checked yet, check now for masking owner UID.
try { hasLocationPermission = hasLocationPermission(callerUid, callerPkgName);
if (!mLocationPermissionChecker.checkLocationPermission( }
callerPkgName, null /* featureId */, callerUid, null /* message */)) { // Reset owner uid if the app has no location permission.
// Caller does not have the requisite location permissions. Reset the if (!hasLocationPermission) {
// owner's UID in the NetworkCapabilities. newNc.setOwnerUid(INVALID_UID);
newNc.setOwnerUid(INVALID_UID);
}
} finally {
Binder.restoreCallingIdentity(token);
} }
return newNc; return newNc;
} }
@@ -6976,7 +6992,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
networkAgent.networkCapabilities, nri.mPid, nri.mUid); networkAgent.networkCapabilities, nri.mPid, nri.mUid);
putParcelable( putParcelable(
bundle, bundle,
maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled(
nc, nri.mUid, nri.request.getRequestorPackageName())); nc, nri.mUid, nri.request.getRequestorPackageName()));
putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions( putParcelable(bundle, linkPropertiesRestrictedForCallerPermissions(
networkAgent.linkProperties, nri.mPid, nri.mUid)); networkAgent.linkProperties, nri.mPid, nri.mUid));
@@ -6995,7 +7011,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
networkAgent.networkCapabilities, nri.mPid, nri.mUid); networkAgent.networkCapabilities, nri.mPid, nri.mUid);
putParcelable( putParcelable(
bundle, bundle,
maybeSanitizeLocationInfoForCaller( createWithLocationInfoSanitizedIfNecessaryWhenParceled(
netCap, nri.mUid, nri.request.getRequestorPackageName())); netCap, nri.mUid, nri.request.getRequestorPackageName()));
break; break;
} }

View File

@@ -24,6 +24,7 @@ java_library {
"androidx.test.rules", "androidx.test.rules",
"junit", "junit",
"mockito-target-minus-junit4", "mockito-target-minus-junit4",
"modules-utils-build",
"net-tests-utils", "net-tests-utils",
"net-utils-framework-common", "net-utils-framework-common",
"platform-test-annotations", "platform-test-annotations",

View File

@@ -42,9 +42,11 @@ import static android.net.NetworkCapabilities.TRANSPORT_VPN;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI; import static android.net.NetworkCapabilities.TRANSPORT_WIFI;
import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE; import static android.net.NetworkCapabilities.TRANSPORT_WIFI_AWARE;
import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES; import static android.net.NetworkCapabilities.UNRESTRICTED_CAPABILITIES;
import static android.os.Process.INVALID_UID;
import static com.android.testutils.ParcelUtils.assertParcelSane; import static com.android.testutils.ParcelUtils.assertParcelSane;
import static com.android.testutils.ParcelUtils.assertParcelingIsLossless; import static com.android.testutils.ParcelUtils.assertParcelingIsLossless;
import static com.android.testutils.ParcelUtils.parcelingRoundTrip;
import static org.junit.Assert.assertArrayEquals; import static org.junit.Assert.assertArrayEquals;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
@@ -53,18 +55,19 @@ import static org.junit.Assert.assertNotEquals;
import static org.junit.Assert.assertNull; import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail; import static org.junit.Assert.fail;
import static org.junit.Assume.assumeTrue;
import android.net.wifi.WifiInfo;
import android.net.wifi.aware.DiscoverySession; import android.net.wifi.aware.DiscoverySession;
import android.net.wifi.aware.PeerHandle; import android.net.wifi.aware.PeerHandle;
import android.net.wifi.aware.WifiAwareNetworkSpecifier; import android.net.wifi.aware.WifiAwareNetworkSpecifier;
import android.os.Build; import android.os.Build;
import android.os.Process;
import android.test.suitebuilder.annotation.SmallTest; import android.test.suitebuilder.annotation.SmallTest;
import android.util.ArraySet; import android.util.ArraySet;
import androidx.core.os.BuildCompat;
import androidx.test.runner.AndroidJUnit4; import androidx.test.runner.AndroidJUnit4;
import com.android.modules.utils.build.SdkLevel;
import com.android.testutils.DevSdkIgnoreRule; import com.android.testutils.DevSdkIgnoreRule;
import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo; import com.android.testutils.DevSdkIgnoreRule.IgnoreUpTo;
@@ -89,10 +92,11 @@ public class NetworkCapabilitiesTest {
private PeerHandle mPeerHandle = Mockito.mock(PeerHandle.class); private PeerHandle mPeerHandle = Mockito.mock(PeerHandle.class);
private boolean isAtLeastR() { private boolean isAtLeastR() {
// BuildCompat.isAtLeastR() is used to check the Android version before releasing Android R. return SdkLevel.isAtLeastR();
// Build.VERSION.SDK_INT > Build.VERSION_CODES.Q is used to check the Android version after }
// releasing Android R.
return BuildCompat.isAtLeastR() || Build.VERSION.SDK_INT > Build.VERSION_CODES.Q; private boolean isAtLeastS() {
return SdkLevel.isAtLeastS();
} }
@Test @Test
@@ -324,8 +328,59 @@ public class NetworkCapabilitiesTest {
testParcelSane(netCap); testParcelSane(netCap);
} }
private NetworkCapabilities createNetworkCapabilitiesWithWifiInfo() {
// uses a real WifiInfo to test parceling of sensitive data.
final WifiInfo wifiInfo = new WifiInfo.Builder()
.setSsid("sssid1234".getBytes())
.setBssid("00:11:22:33:44:55")
.build();
return new NetworkCapabilities()
.addCapability(NET_CAPABILITY_INTERNET)
.addCapability(NET_CAPABILITY_EIMS)
.addCapability(NET_CAPABILITY_NOT_METERED)
.setSSID(TEST_SSID)
.setTransportInfo(wifiInfo)
.setRequestorPackageName("com.android.test")
.setRequestorUid(9304);
}
@Test
public void testParcelNetworkCapabilitiesWithLocationSensitiveFields() {
assumeTrue(isAtLeastS());
final NetworkCapabilities netCap = createNetworkCapabilitiesWithWifiInfo();
final NetworkCapabilities netCapWithLocationSensitiveFields =
new NetworkCapabilities(netCap, true);
assertParcelingIsLossless(netCapWithLocationSensitiveFields);
testParcelSane(netCapWithLocationSensitiveFields);
assertEquals(netCapWithLocationSensitiveFields,
parcelingRoundTrip(netCapWithLocationSensitiveFields));
}
@Test
public void testParcelNetworkCapabilitiesWithoutLocationSensitiveFields() {
assumeTrue(isAtLeastS());
final NetworkCapabilities netCap = createNetworkCapabilitiesWithWifiInfo();
final NetworkCapabilities netCapWithoutLocationSensitiveFields =
new NetworkCapabilities(netCap, false);
final NetworkCapabilities sanitizedNetCap =
new NetworkCapabilities(netCapWithoutLocationSensitiveFields);
final WifiInfo sanitizedWifiInfo = new WifiInfo.Builder()
.setSsid(new byte[0])
.setBssid(WifiInfo.DEFAULT_MAC_ADDRESS)
.build();
sanitizedNetCap.setTransportInfo(sanitizedWifiInfo);
assertEquals(sanitizedNetCap, parcelingRoundTrip(netCapWithoutLocationSensitiveFields));
}
private void testParcelSane(NetworkCapabilities cap) { private void testParcelSane(NetworkCapabilities cap) {
if (isAtLeastR()) { if (isAtLeastS()) {
assertParcelSane(cap, 16);
} else if (isAtLeastR()) {
assertParcelSane(cap, 15); assertParcelSane(cap, 15);
} else { } else {
assertParcelSane(cap, 11); assertParcelSane(cap, 11);
@@ -639,26 +694,23 @@ public class NetworkCapabilitiesTest {
// Sequence 1: Transport + Transport + TransportInfo // Sequence 1: Transport + Transport + TransportInfo
NetworkCapabilities nc1 = new NetworkCapabilities(); NetworkCapabilities nc1 = new NetworkCapabilities();
nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI) nc1.addTransportType(TRANSPORT_CELLULAR).addTransportType(TRANSPORT_WIFI)
.setTransportInfo(new TransportInfo() {}); .setTransportInfo(new TestTransportInfo());
// Sequence 2: Transport + NetworkSpecifier + Transport // Sequence 2: Transport + NetworkSpecifier + Transport
NetworkCapabilities nc2 = new NetworkCapabilities(); NetworkCapabilities nc2 = new NetworkCapabilities();
nc2.addTransportType(TRANSPORT_CELLULAR).setTransportInfo(new TransportInfo() {}) nc2.addTransportType(TRANSPORT_CELLULAR).setTransportInfo(new TestTransportInfo())
.addTransportType(TRANSPORT_WIFI); .addTransportType(TRANSPORT_WIFI);
} }
@Test @Test
public void testCombineTransportInfo() { public void testCombineTransportInfo() {
NetworkCapabilities nc1 = new NetworkCapabilities(); NetworkCapabilities nc1 = new NetworkCapabilities();
nc1.setTransportInfo(new TransportInfo() { nc1.setTransportInfo(new TestTransportInfo());
// empty
});
NetworkCapabilities nc2 = new NetworkCapabilities(); NetworkCapabilities nc2 = new NetworkCapabilities();
// new TransportInfo so that object is not #equals to nc1's TransportInfo (that's where // new TransportInfo so that object is not #equals to nc1's TransportInfo (that's where
// combine fails) // combine fails)
nc2.setTransportInfo(new TransportInfo() { nc2.setTransportInfo(new TestTransportInfo());
// empty
});
try { try {
nc1.combineCapabilities(nc2); nc1.combineCapabilities(nc2);
@@ -761,7 +813,7 @@ public class NetworkCapabilitiesTest {
// Test default owner uid. // Test default owner uid.
// If the owner uid is not set, the default value should be Process.INVALID_UID. // If the owner uid is not set, the default value should be Process.INVALID_UID.
final NetworkCapabilities nc1 = new NetworkCapabilities.Builder().build(); final NetworkCapabilities nc1 = new NetworkCapabilities.Builder().build();
assertEquals(Process.INVALID_UID, nc1.getOwnerUid()); assertEquals(INVALID_UID, nc1.getOwnerUid());
// Test setAdministratorUids and getAdministratorUids. // Test setAdministratorUids and getAdministratorUids.
final int[] administratorUids = {1001, 10001}; final int[] administratorUids = {1001, 10001};
final NetworkCapabilities nc2 = new NetworkCapabilities.Builder() final NetworkCapabilities nc2 = new NetworkCapabilities.Builder()
@@ -906,6 +958,16 @@ public class NetworkCapabilitiesTest {
private class TestTransportInfo implements TransportInfo { private class TestTransportInfo implements TransportInfo {
TestTransportInfo() { TestTransportInfo() {
} }
@Override
public TransportInfo makeCopy(boolean parcelLocationSensitiveFields) {
return this;
}
@Override
public boolean hasLocationSensitiveFields() {
return false;
}
} }
@Test @IgnoreUpTo(Build.VERSION_CODES.Q) @Test @IgnoreUpTo(Build.VERSION_CODES.Q)

View File

@@ -201,6 +201,7 @@ import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils; import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig; import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker; import android.net.util.MultinetworkPolicyTracker;
import android.net.wifi.WifiInfo;
import android.os.BadParcelableException; import android.os.BadParcelableException;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
@@ -7802,51 +7803,76 @@ public class ConnectivityServiceTest {
private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) { private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid); final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
return mService return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
.maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName()) netCap, callerUid, mContext.getPackageName()).getOwnerUid();
.getOwnerUid(); }
private void verifyWifiInfoCopyNetCapsForCallerPermission(
int callerUid, boolean shouldMakeCopyWithLocationSensitiveFieldsParcelable) {
final WifiInfo wifiInfo = mock(WifiInfo.class);
when(wifiInfo.hasLocationSensitiveFields()).thenReturn(true);
final NetworkCapabilities netCap = new NetworkCapabilities().setTransportInfo(wifiInfo);
mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
netCap, callerUid, mContext.getPackageName());
verify(wifiInfo).makeCopy(eq(shouldMakeCopyWithLocationSensitiveFieldsParcelable));
} }
@Test @Test
public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception { public void testCreateForCallerWithLocationInfoSanitizedWithFineLocationAfterQ()
throws Exception {
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION); Manifest.permission.ACCESS_FINE_LOCATION);
final int myUid = Process.myUid(); final int myUid = Process.myUid();
assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
} }
@Test @Test
public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception { public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationPreQ()
throws Exception {
setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION, setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION); Manifest.permission.ACCESS_COARSE_LOCATION);
final int myUid = Process.myUid(); final int myUid = Process.myUid();
assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
} }
@Test @Test
public void testMaybeSanitizeLocationInfoForCallerLocationOff() throws Exception { public void testCreateForCallerWithLocationInfoSanitizedLocationOff() throws Exception {
// Test that even with fine location permission, and UIDs matching, the UID is sanitized. // Test that even with fine location permission, and UIDs matching, the UID is sanitized.
setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION, setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION); Manifest.permission.ACCESS_FINE_LOCATION);
final int myUid = Process.myUid(); final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
} }
@Test @Test
public void testMaybeSanitizeLocationInfoForCallerWrongUid() throws Exception { public void testCreateForCallerWithLocationInfoSanitizedWrongUid() throws Exception {
// Test that even with fine location permission, not being the owner leads to sanitization. // Test that even with fine location permission, not being the owner leads to sanitization.
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION, setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION); Manifest.permission.ACCESS_FINE_LOCATION);
final int myUid = Process.myUid(); final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid)); assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
} }
@Test @Test
public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception { public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationAfterQ()
throws Exception {
// Test that not having fine location permission leads to sanitization. // Test that not having fine location permission leads to sanitization.
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION, setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION); Manifest.permission.ACCESS_COARSE_LOCATION);
@@ -7854,15 +7880,22 @@ public class ConnectivityServiceTest {
// Test that without the location permission, the owner field is sanitized. // Test that without the location permission, the owner field is sanitized.
final int myUid = Process.myUid(); final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
} }
@Test @Test
public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception { public void testCreateForCallerWithLocationInfoSanitizedWithoutLocationPermission()
throws Exception {
setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */); setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
// Test that without the location permission, the owner field is sanitized. // Test that without the location permission, the owner field is sanitized.
final int myUid = Process.myUid(); final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid)); assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
} }
private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType) private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)