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