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.DeviceAdminInfo;
28 import android.app.admin.DevicePolicyManagerInternal;
29 import android.content.Context;
30 import android.content.pm.PackageManager;
31 import android.os.UserHandle;
32 import android.telephony.TelephonyManager;
33 
34 import com.android.server.LocalServices;
35 
36 import java.lang.annotation.Retention;
37 import java.lang.annotation.RetentionPolicy;
38 
39 /** Utility methods for controlling access to network stats APIs. */
40 public final class NetworkStatsAccess {
NetworkStatsAccess()41     private NetworkStatsAccess() {}
42 
43     /**
44      * Represents an access level for the network usage history and statistics APIs.
45      *
46      * <p>Access levels are in increasing order; that is, it is reasonable to check access by
47      * verifying that the caller's access level is at least the minimum required level.
48      */
49     @IntDef({
50             Level.DEFAULT,
51             Level.USER,
52             Level.DEVICESUMMARY,
53             Level.DEVICE,
54     })
55     @Retention(RetentionPolicy.SOURCE)
56     public @interface Level {
57         /**
58          * Default, unprivileged access level.
59          *
60          * <p>Can only access usage for one's own UID.
61          *
62          * <p>Every app will have at least this access level.
63          */
64         int DEFAULT = 0;
65 
66         /**
67          * Access level for apps which can access usage for any app running in the same user.
68          *
69          * <p>Granted to:
70          * <ul>
71          * <li>Profile owners.
72          * </ul>
73          */
74         int USER = 1;
75 
76         /**
77          * Access level for apps which can access usage summary of device. Device summary includes
78          * usage by apps running in any profiles/users, however this access level does not
79          * allow querying usage of individual apps running in other profiles/users.
80          *
81          * <p>Granted to:
82          * <ul>
83          * <li>Apps with the PACKAGE_USAGE_STATS permission granted. Note that this is an AppOps bit
84          * so it is not necessarily sufficient to declare this in the manifest.
85          * <li>Apps with the (signature/privileged) READ_NETWORK_USAGE_HISTORY permission.
86          * </ul>
87          */
88         int DEVICESUMMARY = 2;
89 
90         /**
91          * Access level for apps which can access usage for any app on the device, including apps
92          * running on other users/profiles.
93          *
94          * <p>Granted to:
95          * <ul>
96          * <li>Device owners.
97          * <li>Carrier-privileged applications.
98          * <li>The system UID.
99          * </ul>
100          */
101         int DEVICE = 3;
102     }
103 
104     /** Returns the {@link NetworkStatsAccess.Level} for the given caller. */
checkAccessLevel( Context context, int callingUid, String callingPackage)105     public static @NetworkStatsAccess.Level int checkAccessLevel(
106             Context context, int callingUid, String callingPackage) {
107         final DevicePolicyManagerInternal dpmi = LocalServices.getService(
108                 DevicePolicyManagerInternal.class);
109         final TelephonyManager tm = (TelephonyManager)
110                 context.getSystemService(Context.TELEPHONY_SERVICE);
111         boolean hasCarrierPrivileges = tm != null &&
112                 tm.checkCarrierPrivilegesForPackageAnyPhone(callingPackage) ==
113                         TelephonyManager.CARRIER_PRIVILEGE_STATUS_HAS_ACCESS;
114         boolean isDeviceOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
115                 DeviceAdminInfo.USES_POLICY_DEVICE_OWNER);
116         if (hasCarrierPrivileges || isDeviceOwner
117                 || UserHandle.getAppId(callingUid) == android.os.Process.SYSTEM_UID) {
118             // Carrier-privileged apps and device owners, and the system can access data usage for
119             // all apps on the device.
120             return NetworkStatsAccess.Level.DEVICE;
121         }
122 
123         boolean hasAppOpsPermission = hasAppOpsPermission(context, callingUid, callingPackage);
124         if (hasAppOpsPermission || context.checkCallingOrSelfPermission(
125                 READ_NETWORK_USAGE_HISTORY) == PackageManager.PERMISSION_GRANTED) {
126             return NetworkStatsAccess.Level.DEVICESUMMARY;
127         }
128 
129         boolean isProfileOwner = dpmi != null && dpmi.isActiveAdminWithPolicy(callingUid,
130                 DeviceAdminInfo.USES_POLICY_PROFILE_OWNER);
131         if (isProfileOwner) {
132             // Apps with the AppOps permission, profile owners, and apps with the privileged
133             // permission can access data usage for all apps in this user/profile.
134             return NetworkStatsAccess.Level.USER;
135         }
136 
137         // Everyone else gets default access (only to their own UID).
138         return NetworkStatsAccess.Level.DEFAULT;
139     }
140 
141     /**
142      * Returns whether the given caller should be able to access the given UID when the caller has
143      * the given {@link NetworkStatsAccess.Level}.
144      */
isAccessibleToUser(int uid, int callerUid, @NetworkStatsAccess.Level int accessLevel)145     public static boolean isAccessibleToUser(int uid, int callerUid,
146             @NetworkStatsAccess.Level int accessLevel) {
147         switch (accessLevel) {
148             case NetworkStatsAccess.Level.DEVICE:
149                 // Device-level access - can access usage for any uid.
150                 return true;
151             case NetworkStatsAccess.Level.DEVICESUMMARY:
152                 // Can access usage for any app running in the same user, along
153                 // with some special uids (system, removed, or tethering) and
154                 // anonymized uids
155                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
156                         || uid == UID_TETHERING || uid == UID_ALL
157                         || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
158             case NetworkStatsAccess.Level.USER:
159                 // User-level access - can access usage for any app running in the same user, along
160                 // with some special uids (system, removed, or tethering).
161                 return uid == android.os.Process.SYSTEM_UID || uid == UID_REMOVED
162                         || uid == UID_TETHERING
163                         || UserHandle.getUserId(uid) == UserHandle.getUserId(callerUid);
164             case NetworkStatsAccess.Level.DEFAULT:
165             default:
166                 // Default access level - can only access one's own usage.
167                 return uid == callerUid;
168         }
169     }
170 
hasAppOpsPermission( Context context, int callingUid, String callingPackage)171     private static boolean hasAppOpsPermission(
172             Context context, int callingUid, String callingPackage) {
173         if (callingPackage != null) {
174             AppOpsManager appOps = (AppOpsManager) context.getSystemService(
175                     Context.APP_OPS_SERVICE);
176 
177             final int mode = appOps.noteOp(AppOpsManager.OP_GET_USAGE_STATS,
178                     callingUid, callingPackage);
179             if (mode == AppOpsManager.MODE_DEFAULT) {
180                 // The default behavior here is to check if PackageManager has given the app
181                 // permission.
182                 final int permissionCheck = context.checkCallingPermission(
183                         Manifest.permission.PACKAGE_USAGE_STATS);
184                 return permissionCheck == PackageManager.PERMISSION_GRANTED;
185             }
186             return (mode == AppOpsManager.MODE_ALLOWED);
187         }
188         return false;
189     }
190 }
191