Sanitize owner UID iff owning app does not have location permissions.

This change adds permission checking to ensure that the following
conditions are enforced in order for apps to receive the owner UID:
1. The app must be the owner of the network
2. The app must hold the FINE_LOCATION permission/appop
3. The user must have their location toggle enabled.

Bug: 142072839
Test: atest FrameworksNetTests
Change-Id: I7a981a82f1219828ee89c8c96eb9d2efd153377f
This commit is contained in:
Qingxi Li
2020-01-08 12:51:49 -08:00
parent 02d8578fc3
commit b274810c34
5 changed files with 185 additions and 62 deletions

View File

@@ -1150,6 +1150,10 @@ public class ConnectivityServiceTest {
Arrays.asList(new UserInfo[] {
new UserInfo(VPN_USER, "", 0),
}));
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = Build.VERSION_CODES.Q;
when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
.thenReturn(applicationInfo);
// InstrumentationTestRunner prepares a looper, but AndroidJUnitRunner does not.
// http://b/25897652 .
@@ -2974,7 +2978,7 @@ public class ConnectivityServiceTest {
networkCapabilities.addTransportType(TRANSPORT_WIFI)
.setNetworkSpecifier(new MatchAllNetworkSpecifier());
mService.requestNetwork(networkCapabilities, null, 0, null,
ConnectivityManager.TYPE_WIFI, TEST_PACKAGE_NAME);
ConnectivityManager.TYPE_WIFI, mContext.getPackageName());
});
class NonParcelableSpecifier extends NetworkSpecifier {
@@ -6369,17 +6373,89 @@ public class ConnectivityServiceTest {
assertEquals(wifiLp, mService.getActiveLinkProperties());
}
private void setupLocationPermissions(
int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = targetSdk;
when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
.thenReturn(applicationInfo);
when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
if (op != null) {
when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
.thenReturn(AppOpsManager.MODE_ALLOWED);
}
if (perm != null) {
mServiceContext.setPermission(perm, PERMISSION_GRANTED);
}
}
private int getOwnerUidNetCapsForCallerPermission(int ownerUid, int callerUid) {
final NetworkCapabilities netCap = new NetworkCapabilities().setOwnerUid(ownerUid);
return mService
.maybeSanitizeLocationInfoForCaller(netCap, callerUid, mContext.getPackageName())
.getOwnerUid();
}
@Test
public void testNetworkCapabilitiesRestrictedForCallerPermissions() {
int callerUid = Process.myUid();
final NetworkCapabilities originalNc = new NetworkCapabilities();
originalNc.setOwnerUid(callerUid);
public void testMaybeSanitizeLocationInfoForCallerWithFineLocationAfterQ() throws Exception {
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
final NetworkCapabilities newNc =
mService.networkCapabilitiesRestrictedForCallerPermissions(
originalNc, Process.myPid(), callerUid);
final int myUid = Process.myUid();
assertEquals(myUid, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
}
assertEquals(Process.INVALID_UID, newNc.getOwnerUid());
@Test
public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationPreQ() 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));
}
@Test
public void testMaybeSanitizeLocationInfoForCallerLocationOff() 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));
}
@Test
public void testMaybeSanitizeLocationInfoForCallerWrongUid() 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));
}
@Test
public void testMaybeSanitizeLocationInfoForCallerWithCoarseLocationAfterQ() 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);
// Test that without the location permission, the owner field is sanitized.
final int myUid = Process.myUid();
assertEquals(Process.INVALID_UID, getOwnerUidNetCapsForCallerPermission(myUid, myUid));
}
@Test
public void testMaybeSanitizeLocationInfoForCallerWithoutLocationPermission() 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));
}
private TestNetworkAgentWrapper establishVpn(
@@ -6581,21 +6657,6 @@ public class ConnectivityServiceTest {
mContext.getOpPackageName()));
}
private void setupLocationPermissions(
int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = targetSdk;
when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
.thenReturn(applicationInfo);
when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(locationToggle);
when(mAppOpsManager.noteOp(eq(op), eq(Process.myUid()), eq(mContext.getPackageName())))
.thenReturn(AppOpsManager.MODE_ALLOWED);
mServiceContext.setPermission(perm, PERMISSION_GRANTED);
}
private void setUpConnectivityDiagnosticsCallback() throws Exception {
final NetworkRequest request = new NetworkRequest.Builder().build();
when(mConnectivityDiagnosticsCallback.asBinder()).thenReturn(mIBinder);