OSDN Git Service

Add CONNECTIVITY_USE_RESTRICTED_NETWORKS permission
authorHugo Benichi <hugobenichi@google.com>
Tue, 19 Jul 2016 06:59:27 +0000 (15:59 +0900)
committerHugo Benichi <hugobenichi@google.com>
Mon, 25 Jul 2016 01:24:42 +0000 (10:24 +0900)
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

core/res/AndroidManifest.xml
services/core/java/com/android/server/ConnectivityService.java
services/core/java/com/android/server/connectivity/PermissionMonitor.java

index 48dfdff..ed71fc2 100644 (file)
     <permission android:name="android.permission.CONNECTIVITY_INTERNAL"
         android:protectionLevel="signature|privileged" />
 
+    <!-- Allows an internal user to use restricted Networks.
+         @hide -->
+    <permission android:name="android.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS"
+        android:protectionLevel="signature|privileged" />
+
     <!-- Allows a system application to access hardware packet offload capabilities.
          @hide -->
     <permission android:name="android.permission.PACKET_KEEPALIVE_OFFLOAD"
index 051cb2d..1106262 100644 (file)
@@ -1577,6 +1577,16 @@ public class ConnectivityService extends IConnectivityManager.Stub
                 "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() {
         mContext.enforceCallingOrSelfPermission(KeepaliveTracker.PERMISSION, "ConnectivityService");
     }
@@ -4109,7 +4119,7 @@ public class ConnectivityService extends IConnectivityManager.Stub
 
     private void enforceNetworkRequestPermissions(NetworkCapabilities networkCapabilities) {
         if (networkCapabilities.hasCapability(NET_CAPABILITY_NOT_RESTRICTED) == false) {
-            enforceConnectivityInternalPermission();
+            enforceConnectivityRestrictedNetworksPermission();
         } else {
             enforceChangePermission();
         }
index 22cefd1..7cd1b7b 100644 (file)
@@ -18,6 +18,7 @@ package com.android.server.connectivity;
 
 import static android.Manifest.permission.CHANGE_NETWORK_STATE;
 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_UPDATED_SYSTEM_APP;
 import static android.content.pm.PackageManager.GET_PERMISSIONS;
@@ -65,10 +66,10 @@ public class PermissionMonitor {
     private final BroadcastReceiver mIntentReceiver;
 
     // 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.
-    private final Map<Integer, Boolean> mApps = new HashMap<Integer, Boolean>();
+    private final Map<Integer, Boolean> mApps = new HashMap<>();
 
     public PermissionMonitor(Context context, INetworkManagementService netd) {
         mContext = context;
@@ -126,14 +127,14 @@ public class PermissionMonitor {
             }
 
             boolean isNetwork = hasNetworkPermission(app);
-            boolean isSystem = hasSystemPermission(app);
+            boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
 
-            if (isNetwork || isSystem) {
+            if (isNetwork || hasRestrictedPermission) {
                 Boolean permission = mApps.get(uid);
                 // 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).
                 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);
     }
 
-    private boolean hasSystemPermission(PackageInfo app) {
+    private boolean hasRestrictedNetworkPermission(PackageInfo app) {
         int flags = app.applicationInfo != null ? app.applicationInfo.flags : 0;
         if ((flags & FLAG_SYSTEM) != 0 || (flags & FLAG_UPDATED_SYSTEM_APP) != 0) {
             return true;
         }
-        return hasPermission(app, CONNECTIVITY_INTERNAL);
+        return hasPermission(app, CONNECTIVITY_INTERNAL)
+                || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
     }
 
     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) {
-        List<Integer> network = new ArrayList<Integer>();
-        List<Integer> system = new ArrayList<Integer>();
+        List<Integer> network = new ArrayList<>();
+        List<Integer> system = new ArrayList<>();
         for (Entry<Integer, Boolean> app : apps.entrySet()) {
             List<Integer> list = app.getValue() ? system : network;
             for (int user : users) {
@@ -209,7 +211,7 @@ public class PermissionMonitor {
         }
         mUsers.add(user);
 
-        Set<Integer> users = new HashSet<Integer>();
+        Set<Integer> users = new HashSet<>();
         users.add(user);
         update(users, mApps, true);
     }
@@ -221,7 +223,7 @@ public class PermissionMonitor {
         }
         mUsers.remove(user);
 
-        Set<Integer> users = new HashSet<Integer>();
+        Set<Integer> users = new HashSet<>();
         users.add(user);
         update(users, mApps, false);
     }
@@ -235,16 +237,16 @@ public class PermissionMonitor {
         try {
             PackageInfo app = mPackageManager.getPackageInfo(appName, GET_PERMISSIONS);
             boolean isNetwork = hasNetworkPermission(app);
-            boolean isSystem = hasSystemPermission(app);
-            if (isNetwork || isSystem) {
+            boolean hasRestrictedPermission = hasRestrictedNetworkPermission(app);
+            if (isNetwork || hasRestrictedPermission) {
                 Boolean permission = mApps.get(appUid);
                 // 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).
                 if (permission == null || permission == NETWORK) {
-                    mApps.put(appUid, isSystem);
+                    mApps.put(appUid, hasRestrictedPermission);
 
-                    Map<Integer, Boolean> apps = new HashMap<Integer, Boolean>();
-                    apps.put(appUid, isSystem);
+                    Map<Integer, Boolean> apps = new HashMap<>();
+                    apps.put(appUid, hasRestrictedPermission);
                     update(mUsers, apps, true);
                 }
             }
@@ -260,7 +262,7 @@ public class PermissionMonitor {
         }
         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
         update(mUsers, apps, false);
     }