1 /* 2 * Copyright (C) 2015 The Android Open Source Project 3 * 4 * Licensed under the Apache License, Version 2.0 (the "License"); 5 * you may not use this file except in compliance with the License. 6 * You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License 15 */ 16 17 package com.android.server.net; 18 19 import static android.Manifest.permission.READ_NETWORK_USAGE_HISTORY; 20 import static android.net.NetworkStats.UID_ALL; 21 import static android.net.TrafficStats.UID_REMOVED; 22 import static android.net.TrafficStats.UID_TETHERING; 23 24 import android.Manifest; 25 import android.annotation.IntDef; 26 import android.app.AppOpsManager; 27 import android.app.admin.DevicePolicyManagerInternal; 28 import android.content.Context; 29 import android.content.pm.PackageManager; 30 import android.os.Binder; 31 import android.os.Process; 32 import android.os.UserHandle; 33 import android.telephony.TelephonyManager; 34 35 import com.android.server.LocalServices; 36 37 import java.lang.annotation.Retention; 38 import java.lang.annotation.RetentionPolicy; 39 40 /** Utility methods for controlling access to network stats APIs. */ 41 public final class NetworkStatsAccess { NetworkStatsAccess()42 private NetworkStatsAccess() {} 43 44 /** 45 * Represents an access level for the network usage history and statistics APIs. 46 * 47 * <p>Access levels are in increasing order; that is, it is reasonable to check access by 48 * verifying that the caller's access level is at least the minimum required level. 49 */ 50 @IntDef({ 51 Level.DEFAULT, 52 Level.USER, 53 Level.DEVICESUMMARY, 54 Level.DEVICE, 55 }) 56 @Retention(RetentionPolicy.SOURCE) 57 public @interface Level { 58 /** 59 * Default, unprivileged access level. 60 * 61 * <p>Can only access usage for one's own UID. 62 * 63 * <p>Every app will have at least this access level. 64 */ 65 int DEFAULT = 0; 66 67 /** 68 * Access level for apps which can access usage for any app running in the same user. 69 * 70 * <p>Granted to: 71 * <ul> 72 * <li>Profile owners. 73 * </ul> 74 */ 75 int USER = 1; 76 77 /** 78 * Access level for apps which can access usage summary of device. Device summary includes 79 * usage by apps running in any profiles/users, however this access level does not 80 * allow querying usage of individual apps running in other profiles/users. 81 * 82 * <p>Granted to: 83 * <ul> 84 * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit 85 * so it is not necessarily sufficient to declare this in the manifest. 86 * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission. 87 * </ul> 88 */ 89 int DEVICESUMMARY = 2; 90 91 /** 92 * Access level for apps which can access usage for any app on the device, including apps 93 * running on other users/profiles. 94 * 95 * <p>Granted to: 96 * <ul> 97 * <li>Device owners. 98 * <li>Carrier-privileged applications. 99 * <li>The system UID. 100 * </ul> 101 */ 102 int DEVICE = 3; 103 } 104 105 /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */ checkAccessLevel( Context context, int callingUid, String callingPackage)106 public static @NetworkStatsAccess.Level int checkAccessLevel( 107 Context context, int callingUid, String callingPackage) { 108 final DevicePolicyManagerInternal dpmi = LocalServices.getService( 109 DevicePolicyManagerInternal.class); 110 final TelephonyManager tm = (TelephonyManager) 111 context.getSystemService(Context.TELEPHONY_SERVICE); 112 boolean hasCarrierPrivileges; 113 final long token = Binder.clearCallingIdentity(); 114 try { 115 hasCarrierPrivileges = tm != null 116 && tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) 117 == TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS; 118 } finally { 119 Binder.restoreCallingIdentity(token); 120 } 121 122 final boolean isDeviceOwner = dpmi != null && dpmi.isActiveDeviceOwner(callingUid); 123 final int appId = UserHandle.getAppId(callingUid); 124 if (hasCarrierPrivileges || isDeviceOwner 125 || appId == Process.SYSTEM_UID || appId == Process.NETWORK_STACK_UID) { 126 // Carrier-privileged apps and device owners, and the system (including the 127 // network stack) can access data usage for all apps on the device. 128 return NetworkStatsAccess.Level.DEVICE; 129 } 130 131 boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage); 132 if (hasAppOpsPermission || context.checkCallingOrSelfPermission( 133 READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) { 134 return NetworkStatsAccess.Level.DEVICESUMMARY; 135 } 136 137 //TODO(b/169395065) Figure out if this flow makes sense in Device Owner mode. 138 boolean isProfileOwner = dpmi != null && (dpmi.isActiveProfileOwner(callingUid) 139 || dpmi.isActiveDeviceOwner(callingUid)); 140 if (isProfileOwner) { 141 // Apps with the AppOps permission, profile owners, and apps with the privileged 142 // permission can access data usage for all apps in this user/profile. 143 return NetworkStatsAccess.Level.USER; 144 } 145 146 // Everyone else gets default access (only to their own UID). 147 return NetworkStatsAccess.Level.DEFAULT; 148 } 149 150 /** 151 * Returns whether the given caller should be able to access the given UID when the caller has 152 * the given {@link NetworkStatsAccess.Level}. 153 */ isAccessibleToUser(int uid, int callerUid, @NetworkStatsAccess.Level int accessLevel)154 public static boolean isAccessibleToUser(int uid, int callerUid, 155 @NetworkStatsAccess.Level int accessLevel) { 156 switch (accessLevel) { 157 case NetworkStatsAccess.Level.DEVICE: 158 // Device-level access - can access usage for any uid. 159 return true; 160 case NetworkStatsAccess.Level.DEVICESUMMARY: 161 // Can access usage for any app running in the same user, along 162 // with some special uids (system, removed, or tethering) and 163 // anonymized uids 164 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED 165 || uid == UID_TETHERING || uid == UID_ALL 166 || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid); 167 case NetworkStatsAccess.Level.USER: 168 // User-level access - can access usage for any app running in the same user, along 169 // with some special uids (system, removed, or tethering). 170 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED 171 || uid == UID_TETHERING 172 || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid); 173 case NetworkStatsAccess.Level.DEFAULT: 174 default: 175 // Default access level - can only access one's own usage. 176 return uid == callerUid; 177 } 178 } 179 hasAppOpsPermission( Context context, int callingUid, String callingPackage)180 private static boolean hasAppOpsPermission( 181 Context context, int callingUid, String callingPackage) { 182 if (callingPackage != null) { 183 AppOpsManager appOps = (AppOpsManager) context.getSystemService( 184 Context.APP_OPS_SERVICE); 185 186 final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS, 187 callingUid, callingPackage); 188 if (mode == AppOpsManager.MODE_DEFAULT) { 189 // The default behavior here is to check if PackageManager has given the app 190 // permission. 191 final int permissionCheck = context.checkCallingPermission( 192 Manifest.permission.PACKAGE_USAGE_STATS); 193 return permissionCheck == PackageManager.PERMISSION_GRANTED; 194 } 195 return (mode == AppOpsManager.MODE_ALLOWED); 196 } 197 return false; 198 } 199 } 200