PermissionMonitor: Limit preinstalled apps network permissions
Not all preinstalled apps should have access to background networks or restricted networks. But we give them all network access permissions currently, it's not a good design. So we shall limit preinstalled apps permissions, they should just request the appropriate permission for their use case from the network permissions. Bug:19610688 Test: runtest frameworks-net Change-Id: I184ae3197208c979847ca134c8f01b32528badf1
This commit is contained in:
@@ -24,6 +24,7 @@ import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
||||
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
|
||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||
|
||||
import android.annotation.NonNull;
|
||||
import android.content.BroadcastReceiver;
|
||||
import android.content.Context;
|
||||
import android.content.Intent;
|
||||
@@ -34,6 +35,7 @@ import android.content.pm.PackageManager;
|
||||
import android.content.pm.PackageManager.NameNotFoundException;
|
||||
import android.content.pm.UserInfo;
|
||||
import android.net.Uri;
|
||||
import android.os.Build;
|
||||
import android.os.INetworkManagementService;
|
||||
import android.os.RemoteException;
|
||||
import android.os.UserHandle;
|
||||
@@ -155,9 +157,8 @@ public class PermissionMonitor {
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
boolean isPreinstalledSystemApp(PackageInfo app) {
|
||||
int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
|
||||
return (flags & (FLAG_SYSTEM | FLAG_UPDATED_SYSTEM_APP)) != 0;
|
||||
static boolean isVendorApp(@NonNull ApplicationInfo appInfo) {
|
||||
return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct();
|
||||
}
|
||||
|
||||
@VisibleForTesting
|
||||
@@ -177,7 +178,13 @@ public class PermissionMonitor {
|
||||
}
|
||||
|
||||
private boolean hasRestrictedNetworkPermission(PackageInfo app) {
|
||||
if (isPreinstalledSystemApp(app)) return true;
|
||||
// TODO : remove this check in the future(b/31479477). All apps should just
|
||||
// request the appropriate permission for their use case since android Q.
|
||||
if (app.applicationInfo != null
|
||||
&& app.applicationInfo.targetSdkVersion < Build.VERSION_CODES.Q
|
||||
&& isVendorApp(app.applicationInfo)) {
|
||||
return true;
|
||||
}
|
||||
return hasPermission(app, CONNECTIVITY_INTERNAL)
|
||||
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
|
||||
}
|
||||
@@ -186,13 +193,8 @@ public class PermissionMonitor {
|
||||
// This function defines what it means to hold the permission to use
|
||||
// background networks.
|
||||
return hasPermission(app, CHANGE_NETWORK_STATE)
|
||||
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS)
|
||||
|| hasPermission(app, CONNECTIVITY_INTERNAL)
|
||||
|| hasPermission(app, NETWORK_STACK)
|
||||
// TODO : remove this check (b/31479477). Not all preinstalled apps should
|
||||
// have access to background networks, they should just request the appropriate
|
||||
// permission for their use case from the list above.
|
||||
|| isPreinstalledSystemApp(app);
|
||||
|| hasRestrictedNetworkPermission(app);
|
||||
}
|
||||
|
||||
public boolean hasUseBackgroundNetworksPermission(int uid) {
|
||||
|
||||
@@ -21,7 +21,9 @@ import static android.Manifest.permission.CHANGE_WIFI_STATE;
|
||||
import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
|
||||
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
|
||||
import static android.Manifest.permission.NETWORK_STACK;
|
||||
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
|
||||
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_OEM;
|
||||
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_PRODUCT;
|
||||
import static android.content.pm.ApplicationInfo.PRIVATE_FLAG_VENDOR;
|
||||
import static android.content.pm.PackageManager.GET_PERMISSIONS;
|
||||
|
||||
import static org.junit.Assert.assertFalse;
|
||||
@@ -34,6 +36,7 @@ import android.content.Context;
|
||||
import android.content.pm.ApplicationInfo;
|
||||
import android.content.pm.PackageInfo;
|
||||
import android.content.pm.PackageManager;
|
||||
import android.os.Build;
|
||||
import android.support.test.filters.SmallTest;
|
||||
import android.support.test.runner.AndroidJUnit4;
|
||||
|
||||
@@ -48,6 +51,10 @@ import org.mockito.MockitoAnnotations;
|
||||
public class PermissionMonitorTest {
|
||||
private static final int MOCK_UID = 10001;
|
||||
private static final String[] MOCK_PACKAGE_NAMES = new String[] { "com.foo.bar" };
|
||||
private static final String PARTITION_SYSTEM = "system";
|
||||
private static final String PARTITION_OEM = "oem";
|
||||
private static final String PARTITION_PRODUCT = "product";
|
||||
private static final String PARTITION_VENDOR = "vendor";
|
||||
|
||||
@Mock private Context mContext;
|
||||
@Mock private PackageManager mPackageManager;
|
||||
@@ -62,23 +69,37 @@ public class PermissionMonitorTest {
|
||||
mPermissionMonitor = new PermissionMonitor(mContext, null);
|
||||
}
|
||||
|
||||
private void expectPermission(String[] permissions, boolean preinstalled) throws Exception {
|
||||
final PackageInfo packageInfo = packageInfoWithPermissions(permissions, preinstalled);
|
||||
private void expectPermission(String[] permissions, String partition,
|
||||
int targetSdkVersion) throws Exception {
|
||||
final PackageInfo packageInfo = packageInfoWithPermissions(permissions, partition);
|
||||
packageInfo.applicationInfo.targetSdkVersion = targetSdkVersion;
|
||||
when(mPackageManager.getPackageInfoAsUser(
|
||||
eq(MOCK_PACKAGE_NAMES[0]), eq(GET_PERMISSIONS), anyInt())).thenReturn(packageInfo);
|
||||
}
|
||||
|
||||
private PackageInfo packageInfoWithPermissions(String[] permissions, boolean preinstalled) {
|
||||
private PackageInfo packageInfoWithPermissions(String[] permissions, String partition) {
|
||||
final PackageInfo packageInfo = new PackageInfo();
|
||||
packageInfo.requestedPermissions = permissions;
|
||||
packageInfo.applicationInfo = new ApplicationInfo();
|
||||
packageInfo.applicationInfo.flags = preinstalled ? FLAG_SYSTEM : 0;
|
||||
int privateFlags = 0;
|
||||
switch (partition) {
|
||||
case PARTITION_OEM:
|
||||
privateFlags = PRIVATE_FLAG_OEM;
|
||||
break;
|
||||
case PARTITION_PRODUCT:
|
||||
privateFlags = PRIVATE_FLAG_PRODUCT;
|
||||
break;
|
||||
case PARTITION_VENDOR:
|
||||
privateFlags = PRIVATE_FLAG_VENDOR;
|
||||
break;
|
||||
}
|
||||
packageInfo.applicationInfo.privateFlags = privateFlags;
|
||||
return packageInfo;
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasPermission() {
|
||||
PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
|
||||
PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM);
|
||||
assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
||||
assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
||||
assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
||||
@@ -86,7 +107,7 @@ public class PermissionMonitorTest {
|
||||
|
||||
app = packageInfoWithPermissions(new String[] {
|
||||
CHANGE_NETWORK_STATE, NETWORK_STACK
|
||||
}, false);
|
||||
}, PARTITION_SYSTEM);
|
||||
assertTrue(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
||||
assertTrue(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
||||
assertFalse(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
||||
@@ -94,7 +115,7 @@ public class PermissionMonitorTest {
|
||||
|
||||
app = packageInfoWithPermissions(new String[] {
|
||||
CONNECTIVITY_USE_RESTRICTED_NETWORKS, CONNECTIVITY_INTERNAL
|
||||
}, false);
|
||||
}, PARTITION_SYSTEM);
|
||||
assertFalse(mPermissionMonitor.hasPermission(app, CHANGE_NETWORK_STATE));
|
||||
assertFalse(mPermissionMonitor.hasPermission(app, NETWORK_STACK));
|
||||
assertTrue(mPermissionMonitor.hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS));
|
||||
@@ -102,35 +123,64 @@ public class PermissionMonitorTest {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsPreinstalledSystemApp() {
|
||||
PackageInfo app = packageInfoWithPermissions(new String[] {}, false);
|
||||
assertFalse(mPermissionMonitor.isPreinstalledSystemApp(app));
|
||||
|
||||
app = packageInfoWithPermissions(new String[] {}, true);
|
||||
assertTrue(mPermissionMonitor.isPreinstalledSystemApp(app));
|
||||
public void testIsVendorApp() {
|
||||
PackageInfo app = packageInfoWithPermissions(new String[] {}, PARTITION_SYSTEM);
|
||||
assertFalse(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||
app = packageInfoWithPermissions(new String[] {}, PARTITION_OEM);
|
||||
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||
app = packageInfoWithPermissions(new String[] {}, PARTITION_PRODUCT);
|
||||
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||
app = packageInfoWithPermissions(new String[] {}, PARTITION_VENDOR);
|
||||
assertTrue(mPermissionMonitor.isVendorApp(app.applicationInfo));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testHasUseBackgroundNetworksPermission() throws Exception {
|
||||
expectPermission(new String[] { CHANGE_NETWORK_STATE }, false);
|
||||
expectPermission(new String[] { CHANGE_NETWORK_STATE },
|
||||
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { NETWORK_STACK }, PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CONNECTIVITY_INTERNAL },
|
||||
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CONNECTIVITY_USE_RESTRICTED_NETWORKS },
|
||||
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
|
||||
expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, false);
|
||||
expectPermission(new String[] { CHANGE_NETWORK_STATE },
|
||||
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { NETWORK_STACK },
|
||||
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CONNECTIVITY_INTERNAL },
|
||||
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CONNECTIVITY_USE_RESTRICTED_NETWORKS },
|
||||
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
|
||||
// TODO : make this false when b/31479477 is fixed
|
||||
expectPermission(new String[] {}, true);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CHANGE_WIFI_STATE }, true);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
|
||||
expectPermission(new String[] { NETWORK_STACK, CONNECTIVITY_INTERNAL }, true);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
|
||||
expectPermission(new String[] {}, false);
|
||||
expectPermission(new String[] {}, PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||
PARTITION_SYSTEM, Build.VERSION_CODES.P);
|
||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] {}, PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||
PARTITION_VENDOR, Build.VERSION_CODES.P);
|
||||
assertTrue(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
|
||||
expectPermission(new String[] { CHANGE_WIFI_STATE }, false);
|
||||
expectPermission(new String[] {}, PARTITION_SYSTEM, Build.VERSION_CODES.Q);
|
||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||
PARTITION_SYSTEM, Build.VERSION_CODES.Q);
|
||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] {}, PARTITION_VENDOR, Build.VERSION_CODES.Q);
|
||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
expectPermission(new String[] { CHANGE_WIFI_STATE },
|
||||
PARTITION_VENDOR, Build.VERSION_CODES.Q);
|
||||
assertFalse(mPermissionMonitor.hasUseBackgroundNetworksPermission(MOCK_UID));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user