NetworkCapabilities: Embed location senstive TransportInfo

Changes:
i) Add a new constructor for NetworkCapabilities which accepts whether
location sensitive fields need to be parceled or not. Defalts to false
on the other constructor. This boolean should only be set on the copy of
NetworkCapabilities when sent to apps that hold location permission.
(Similar to how sensitive fields are handled in LinkProperties)
ii) Add a new makeCopy() method in the TransportInfo interface which
accepts whether location sensitive fields need to be parceled or not.
iii) Migrate the existing NetworkCapabilities owner UID masking to use
this new mechanism (instead of existing masking in ConnectivityService).
iv) Always set parcelLocationSensitiveFields to true in the NetworkAgent
surface (since that is a privileged surface from the transports to the
connectivity service)
v) Add a hasSensitiveFields() in TransportInfo interface to avoid
perfoming location permission checks for location insensitive
TrasnsportInfo.

Also, migrate to the new SdkLevel util for isAtLeastR() & isAtLeastS()
checks.

Bug: 162602799
Test: atest android.net
Test: atest com.android.server
Change-Id: Ie522d8c75a82ae521ccfd5165823d0c72642e651
Merged-In: Ie522d8c75a82ae521ccfd5165823d0c72642e651
This commit is contained in:
Roshan Pius
2020-12-28 09:01:49 -08:00
parent d895e5a193
commit 9ed1462e82
7 changed files with 235 additions and 49 deletions

View File

@@ -202,6 +202,7 @@ import android.net.metrics.IpConnectivityLog;
import android.net.shared.NetworkMonitorUtils;
import android.net.shared.PrivateDnsConfig;
import android.net.util.MultinetworkPolicyTracker;
import android.net.wifi.WifiInfo;
import android.os.BadParcelableException;
import android.os.Binder;
import android.os.Build;
@@ -7568,51 +7569,76 @@ public class ConnectivityServiceTest {
private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
return mService
.maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
.getOwnerUid();
return mService.createWithLocationInfoSanitizedIfNecessaryWhenParceled(
netCap, callerUid, mContext.getPackageName()).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
public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
public void testCreateForCallerWithLocationInfoSanitizedWithFineLocationAfterQ()
throws Exception {
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
final int myUid = Process.myUid();
assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
}
@Test
public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() throws Exception {
public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationPreQ()
throws Exception {
setupLocationPermissions(Build.VERSION_CODES.P, true, AppOpsManager.OPSTR_COARSE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION);
final int myUid = Process.myUid();
assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
}
@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.
setupLocationPermissions(Build.VERSION_CODES.Q, false, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
}
@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.
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid + 1, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
true /* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
}
@Test
public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() throws Exception {
public void testCreateForCallerWithLocationInfoSanitizedWithCoarseLocationAfterQ()
throws Exception {
// Test that not having fine location permission leads to sanitization.
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_COARSE_LOCATION,
Manifest.permission.ACCESS_COARSE_LOCATION);
@@ -7620,15 +7646,22 @@ public class ConnectivityServiceTest {
// Test that without the location permission, the owner field is sanitized.
final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
}
@Test
public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() throws Exception {
public void testCreateForCallerWithLocationInfoSanitizedWithoutLocationPermission()
throws Exception {
setupLocationPermissions(Build.VERSION_CODES.Q, true, null /* op */, null /* perm */);
// Test that without the location permission, the owner field is sanitized.
final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
verifyWifiInfoCopyNetCapsForCallerPermission(myUid,
false/* shouldMakeCopyWithLocationSensitiveFieldsParcelable */);
}
private void setupConnectionOwnerUid(int vpnOwnerUid, @VpnManager.VpnType int vpnType)