Merge "LocationPermissionChecker: Exempt privileged components from location check" am: 2324ff48be am: 3f78d1ce0a

Original change: https://android-review.googlesource.com/c/platform/frameworks/base/+/1550515

MUST ONLY BE SUBMITTED BY AUTOMERGER

Change-Id: I45afdaba68269d59cfcf670ef7fdef6a19b3a9d2
This commit is contained in:
Roshan Pius
2021-01-18 02:52:29 +00:00
committed by Automerger Merge Worker
3 changed files with 82 additions and 8 deletions

View File

@@ -24,6 +24,7 @@ import android.app.AppOpsManager;
import android.content.Context; import android.content.Context;
import android.content.pm.PackageManager; import android.content.pm.PackageManager;
import android.location.LocationManager; import android.location.LocationManager;
import android.net.NetworkStack;
import android.os.Binder; import android.os.Binder;
import android.os.Build; import android.os.Build;
import android.os.UserHandle; import android.os.UserHandle;
@@ -147,6 +148,13 @@ public class LocationPermissionChecker {
int uid, @Nullable String message) { int uid, @Nullable String message) {
checkPackage(uid, pkgName); checkPackage(uid, pkgName);
// Apps with NETWORK_SETTINGS, NETWORK_SETUP_WIZARD, NETWORK_STACK & MAINLINE_NETWORK_STACK
// are granted a bypass.
if (checkNetworkSettingsPermission(uid) || checkNetworkSetupWizardPermission(uid)
|| checkNetworkStackPermission(uid) || checkMainlineNetworkStackPermission(uid)) {
return SUCCEEDED;
}
// Location mode must be enabled // Location mode must be enabled
if (!isLocationModeEnabled()) { if (!isLocationModeEnabled()) {
return ERROR_LOCATION_MODE_OFF; return ERROR_LOCATION_MODE_OFF;
@@ -259,4 +267,37 @@ public class LocationPermissionChecker {
// We don't care about pid, pass in -1 // We don't care about pid, pass in -1
return mContext.checkPermission(permissionType, -1, uid); return mContext.checkPermission(permissionType, -1, uid);
} }
/**
* Returns true if the |uid| holds NETWORK_SETTINGS permission.
*/
public boolean checkNetworkSettingsPermission(int uid) {
return getUidPermission(android.Manifest.permission.NETWORK_SETTINGS, uid)
== PackageManager.PERMISSION_GRANTED;
}
/**
* Returns true if the |uid| holds NETWORK_SETUP_WIZARD permission.
*/
public boolean checkNetworkSetupWizardPermission(int uid) {
return getUidPermission(android.Manifest.permission.NETWORK_SETUP_WIZARD, uid)
== PackageManager.PERMISSION_GRANTED;
}
/**
* Returns true if the |uid| holds NETWORK_STACK permission.
*/
public boolean checkNetworkStackPermission(int uid) {
return getUidPermission(android.Manifest.permission.NETWORK_STACK, uid)
== PackageManager.PERMISSION_GRANTED;
}
/**
* Returns true if the |uid| holds MAINLINE_NETWORK_STACK permission.
*/
public boolean checkMainlineNetworkStackPermission(int uid) {
return getUidPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK, uid)
== PackageManager.PERMISSION_GRANTED;
}
} }

View File

@@ -15,6 +15,8 @@
*/ */
package com.android.internal.util; package com.android.internal.util;
import static android.Manifest.permission.NETWORK_SETTINGS;
import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue; import static org.junit.Assert.assertTrue;
import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.any;
@@ -82,6 +84,7 @@ public class LocationPermissionCheckerTest {
private int mAllowCoarseLocationApps; private int mAllowCoarseLocationApps;
private int mFineLocationPermission; private int mFineLocationPermission;
private int mAllowFineLocationApps; private int mAllowFineLocationApps;
private int mNetworkSettingsPermission;
private int mCurrentUser; private int mCurrentUser;
private boolean mIsLocationEnabled; private boolean mIsLocationEnabled;
private boolean mThrowSecurityException; private boolean mThrowSecurityException;
@@ -138,6 +141,7 @@ public class LocationPermissionCheckerTest {
mFineLocationPermission = PackageManager.PERMISSION_DENIED; mFineLocationPermission = PackageManager.PERMISSION_DENIED;
mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED; mAllowCoarseLocationApps = AppOpsManager.MODE_ERRORED;
mAllowFineLocationApps = AppOpsManager.MODE_ERRORED; mAllowFineLocationApps = AppOpsManager.MODE_ERRORED;
mNetworkSettingsPermission = PackageManager.PERMISSION_DENIED;
} }
private void setupMockInterface() { private void setupMockInterface() {
@@ -151,6 +155,8 @@ public class LocationPermissionCheckerTest {
.thenReturn(mCoarseLocationPermission); .thenReturn(mCoarseLocationPermission);
when(mMockContext.checkPermission(mManifestStringFine, -1, mUid)) when(mMockContext.checkPermission(mManifestStringFine, -1, mUid))
.thenReturn(mFineLocationPermission); .thenReturn(mFineLocationPermission);
when(mMockContext.checkPermission(NETWORK_SETTINGS, -1, mUid))
.thenReturn(mNetworkSettingsPermission);
when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled); when(mLocationManager.isLocationEnabledForUser(any())).thenReturn(mIsLocationEnabled);
} }
@@ -264,6 +270,21 @@ public class LocationPermissionCheckerTest {
assertEquals(LocationPermissionChecker.ERROR_LOCATION_MODE_OFF, result); assertEquals(LocationPermissionChecker.ERROR_LOCATION_MODE_OFF, result);
} }
@Test
public void testenforceCanAccessScanResults_LocationModeDisabledHasNetworkSettings()
throws Exception {
mThrowSecurityException = false;
mIsLocationEnabled = false;
mNetworkSettingsPermission = PackageManager.PERMISSION_GRANTED;
setupTestCase();
final int result =
mChecker.checkLocationPermissionWithDetailInfo(
TEST_PKG_NAME, TEST_FEATURE_ID, mUid, null);
assertEquals(LocationPermissionChecker.SUCCEEDED, result);
}
private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) { private static void assertThrows(Class<? extends Exception> exceptionClass, Runnable r) {
try { try {
r.run(); r.run();

View File

@@ -2074,10 +2074,6 @@ public class ConnectivityServiceTest {
@Test @Test
public void testOwnerUidCannotChange() throws Exception { public void testOwnerUidCannotChange() throws Exception {
// Owner UIDs are not visible without location permission.
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
final NetworkCapabilities ncTemplate = new NetworkCapabilities(); final NetworkCapabilities ncTemplate = new NetworkCapabilities();
final int originalOwnerUid = Process.myUid(); final int originalOwnerUid = Process.myUid();
ncTemplate.setOwnerUid(originalOwnerUid); ncTemplate.setOwnerUid(originalOwnerUid);
@@ -2097,6 +2093,10 @@ public class ConnectivityServiceTest {
mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true); mWiFiNetworkAgent.setNetworkCapabilities(agentCapabilities, true);
waitForIdle(); waitForIdle();
// Owner UIDs are not visible without location permission.
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
// Check that the capability change has been applied but the owner UID is not modified. // Check that the capability change has been applied but the owner UID is not modified.
NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork()); NetworkCapabilities nc = mCm.getNetworkCapabilities(mWiFiNetworkAgent.getNetwork());
assertEquals(originalOwnerUid, nc.getOwnerUid()); assertEquals(originalOwnerUid, nc.getOwnerUid());
@@ -7781,8 +7781,22 @@ public class ConnectivityServiceTest {
naExtraInfo.unregister(); naExtraInfo.unregister();
} }
// To avoid granting location permission bypass.
private void denyAllLocationPrivilegedPermissions() {
mServiceContext.setPermission(NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK,
PERMISSION_DENIED);
mServiceContext.setPermission(Manifest.permission.NETWORK_SETTINGS,
PERMISSION_DENIED);
mServiceContext.setPermission(Manifest.permission.NETWORK_STACK,
PERMISSION_DENIED);
mServiceContext.setPermission(Manifest.permission.NETWORK_SETUP_WIZARD,
PERMISSION_DENIED);
}
private void setupLocationPermissions( private void setupLocationPermissions(
int targetSdk, boolean locationToggle, String op, String perm) throws Exception { int targetSdk, boolean locationToggle, String op, String perm) throws Exception {
denyAllLocationPrivilegedPermissions();
final ApplicationInfo applicationInfo = new ApplicationInfo(); final ApplicationInfo applicationInfo = new ApplicationInfo();
applicationInfo.targetSdkVersion = targetSdk; applicationInfo.targetSdkVersion = targetSdk;
when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any())) when(mPackageManager.getApplicationInfoAsUser(anyString(), anyInt(), any()))
@@ -8156,15 +8170,13 @@ public class ConnectivityServiceTest {
new NetworkAgentInfo(null, network, null, null, new NetworkCapabilities(), 0, new NetworkAgentInfo(null, network, null, null, new NetworkCapabilities(), 0,
mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID); mServiceContext, null, null, mService, null, null, null, 0, INVALID_UID);
setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
mMockVpn.establishForMyUid(); mMockVpn.establishForMyUid();
assertUidRangesUpdatedForMyUid(true); assertUidRangesUpdatedForMyUid(true);
// Wait for networks to connect and broadcasts to be sent before removing permissions. // Wait for networks to connect and broadcasts to be sent before removing permissions.
waitForIdle(); waitForIdle();
mServiceContext.setPermission(android.Manifest.permission.NETWORK_STACK, PERMISSION_DENIED); setupLocationPermissions(Build.VERSION_CODES.Q, true, AppOpsManager.OPSTR_FINE_LOCATION,
Manifest.permission.ACCESS_FINE_LOCATION);
assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network})); assertTrue(mService.setUnderlyingNetworksForVpn(new Network[] {network}));
waitForIdle(); waitForIdle();