DO NOT MERGE ANYWHERE Add CONNECTIVITY_USE_RESTRICTED_NETWORKS permission

This patch creates a new permission used by ConnectivityService to give
access to restricted networks without the NET_CAPABILITY_NOT_RESTRICTED
capability bit on.

Bug: 24497316
Change-Id: I5b6c8a9ef14395b2f1ab26cb17b24d7876ec79f1
This commit is contained in:
Hugo Benichi
2016-07-19 15:59:27 +09:00
committed by Chris Elliott
parent 26b435dfe1
commit 849682f5a0
2 changed files with 30 additions and 18 deletions

View File

@@ -1462,6 +1462,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
"ConnectivityService"); "ConnectivityService");
} }
private void enforceConnectivityRestrictedNetworksPermission() {
try {
mContext.enforceCallingOrSelfPermission(
android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS,
"ConnectivityService");
return;
} catch (SecurityException e) { /* fallback to ConnectivityInternalPermission */ }
enforceConnectivityInternalPermission();
}
private void enforceKeepalivePermission() { private void enforceKeepalivePermission() {
mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService"); mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService");
} }
@@ -3694,7 +3704,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) { private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) { if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
enforceConnectivityInternalPermission(); enforceConnectivityRestrictedNetworksPermission();
} else { } else {
enforceChangePermission(); enforceChangePermission();
} }

View File

@@ -18,6 +18,7 @@ package com.android.server.connectivity;
import static android.Manifest.permission.CHANGE_NETWORK_STATE; import static android.Manifest.permission.CHANGE_NETWORK_STATE;
import static android.Manifest.permission.CONNECTIVITY_INTERNAL; import static android.Manifest.permission.CONNECTIVITY_INTERNAL;
import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
import static android.content.pm.ApplicationInfo.FLAG_SYSTEM; import static android.content.pm.ApplicationInfo.FLAG_SYSTEM;
import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP; import static android.content.pm.ApplicationInfo.FLAG_UPDATED_SYSTEM_APP;
import static android.content.pm.PackageManager.GET_PERMISSIONS; import static android.content.pm.PackageManager.GET_PERMISSIONS;
@@ -65,10 +66,10 @@ public class PermissionMonitor {
private final BroadcastReceiver mIntentReceiver; private final BroadcastReceiver mIntentReceiver;
// Values are User IDs. // Values are User IDs.
private final Set<Integer> mUsers = new HashSet<Integer>(); private final Set<Integer> mUsers = new HashSet<>();
// Keys are App IDs. Values are true for SYSTEM permission and false for NETWORK permission. // Keys are App IDs. Values are true for SYSTEM permission and false for NETWORK permission.
private final Map<Integer, Boolean> mApps = new HashMap<Integer, Boolean>(); private final Map<Integer, Boolean> mApps = new HashMap<>();
public PermissionMonitor(Context context, INetworkManagementService netd) { public PermissionMonitor(Context context, INetworkManagementService netd) {
mContext = context; mContext = context;
@@ -126,14 +127,14 @@ public class PermissionMonitor {
} }
boolean isNetwork = hasNetworkPermission(app); boolean isNetwork = hasNetworkPermission(app);
boolean isSystem = hasSystemPermission(app); boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
if (isNetwork || isSystem) { if (isNetwork || hasRestrictedPermission) {
Boolean permission = mApps.get(uid); Boolean permission = mApps.get(uid);
// If multiple packages share a UID (cf: android:sharedUserId) and ask for different // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
// permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
if (permission == null || permission == NETWORK) { if (permission == null || permission == NETWORK) {
mApps.put(uid, isSystem); mApps.put(uid, hasRestrictedPermission);
} }
} }
} }
@@ -164,12 +165,13 @@ public class PermissionMonitor {
return hasPermission(app, CHANGE_NETWORK_STATE); return hasPermission(app, CHANGE_NETWORK_STATE);
} }
private boolean hasSystemPermission(PackageInfo app) { private boolean hasRestrictedNetworkPermission(PackageInfo app) {
int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0; int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
if ((flags & FLAG_SYSTEM) != 0 || (flags & FLAG_UPDATED_SYSTEM_APP) != 0) { if ((flags & FLAG_SYSTEM) != 0 || (flags & FLAG_UPDATED_SYSTEM_APP) != 0) {
return true; return true;
} }
return hasPermission(app, CONNECTIVITY_INTERNAL); return hasPermission(app, CONNECTIVITY_INTERNAL)
|| hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
} }
private int[] toIntArray(List<Integer> list) { private int[] toIntArray(List<Integer> list) {
@@ -181,8 +183,8 @@ public class PermissionMonitor {
} }
private void update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add) { private void update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add) {
List<Integer> network = new ArrayList<Integer>(); List<Integer> network = new ArrayList<>();
List<Integer> system = new ArrayList<Integer>(); List<Integer> system = new ArrayList<>();
for (Entry<Integer, Boolean> app : apps.entrySet()) { for (Entry<Integer, Boolean> app : apps.entrySet()) {
List<Integer> list = app.getValue() ? system : network; List<Integer> list = app.getValue() ? system : network;
for (int user : users) { for (int user : users) {
@@ -209,7 +211,7 @@ public class PermissionMonitor {
} }
mUsers.add(user); mUsers.add(user);
Set<Integer> users = new HashSet<Integer>(); Set<Integer> users = new HashSet<>();
users.add(user); users.add(user);
update(users, mApps, true); update(users, mApps, true);
} }
@@ -221,7 +223,7 @@ public class PermissionMonitor {
} }
mUsers.remove(user); mUsers.remove(user);
Set<Integer> users = new HashSet<Integer>(); Set<Integer> users = new HashSet<>();
users.add(user); users.add(user);
update(users, mApps, false); update(users, mApps, false);
} }
@@ -235,16 +237,16 @@ public class PermissionMonitor {
try { try {
PackageInfo app = mPackageManager.getPackageInfo(appName, GET_PERMISSIONS); PackageInfo app = mPackageManager.getPackageInfo(appName, GET_PERMISSIONS);
boolean isNetwork = hasNetworkPermission(app); boolean isNetwork = hasNetworkPermission(app);
boolean isSystem = hasSystemPermission(app); boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
if (isNetwork || isSystem) { if (isNetwork || hasRestrictedPermission) {
Boolean permission = mApps.get(appUid); Boolean permission = mApps.get(appUid);
// If multiple packages share a UID (cf: android:sharedUserId) and ask for different // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
// permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
if (permission == null || permission == NETWORK) { if (permission == null || permission == NETWORK) {
mApps.put(appUid, isSystem); mApps.put(appUid, hasRestrictedPermission);
Map<Integer, Boolean> apps = new HashMap<Integer, Boolean>(); Map<Integer, Boolean> apps = new HashMap<>();
apps.put(appUid, isSystem); apps.put(appUid, hasRestrictedPermission);
update(mUsers, apps, true); update(mUsers, apps, true);
} }
} }
@@ -260,7 +262,7 @@ public class PermissionMonitor {
} }
mApps.remove(appUid); mApps.remove(appUid);
Map<Integer, Boolean> apps = new HashMap<Integer, Boolean>(); Map<Integer, Boolean> apps = new HashMap<>();
apps.put(appUid, NETWORK); // doesn't matter which permission we pick here apps.put(appUid, NETWORK); // doesn't matter which permission we pick here
update(mUsers, apps, false); update(mUsers, apps, false);
} }