• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * Copyright (C) 2014 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.connectivity;
18 
19 import static android.Manifest.permission.CHANGE_NETWORK_STATE;
20 import static android.Manifest.permission.CONNECTIVITY_USE_RESTRICTED_NETWORKS;
21 import static android.Manifest.permission.INTERNET;
22 import static android.Manifest.permission.NEARBY_WIFI_DEVICES;
23 import static android.Manifest.permission.NETWORK_STACK;
24 import static android.Manifest.permission.UPDATE_DEVICE_STATS;
25 import static android.content.pm.PackageInfo.REQUESTED_PERMISSION_GRANTED;
26 import static android.content.pm.PackageManager.GET_PERMISSIONS;
27 import static android.net.ConnectivitySettingsManager.UIDS_ALLOWED_ON_RESTRICTED_NETWORKS;
28 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK;
29 import static android.net.connectivity.ConnectivityCompatChanges.RESTRICT_LOCAL_NETWORK;
30 import static android.os.Process.INVALID_UID;
31 import static android.os.Process.SYSTEM_UID;
32 
33 import static com.android.server.connectivity.NetworkPermissions.PERMISSION_NETWORK;
34 import static com.android.server.connectivity.NetworkPermissions.PERMISSION_NONE;
35 import static com.android.server.connectivity.NetworkPermissions.PERMISSION_SYSTEM;
36 import static com.android.server.connectivity.NetworkPermissions.TRAFFIC_PERMISSION_INTERNET;
37 import static com.android.server.connectivity.NetworkPermissions.TRAFFIC_PERMISSION_UNINSTALLED;
38 import static com.android.server.connectivity.NetworkPermissions.TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS;
39 import static com.android.net.module.util.CollectionUtils.toIntArray;
40 
41 import android.annotation.NonNull;
42 import android.annotation.Nullable;
43 import android.app.compat.CompatChanges;
44 import android.content.AttributionSource;
45 import android.content.BroadcastReceiver;
46 import android.content.Context;
47 import android.content.Intent;
48 import android.content.IntentFilter;
49 import android.content.pm.ApplicationInfo;
50 import android.content.pm.PackageInfo;
51 import android.content.pm.PackageManager;
52 import android.content.pm.PackageManager.NameNotFoundException;
53 import android.database.ContentObserver;
54 import android.net.ConnectivitySettingsManager;
55 import android.net.INetd;
56 import android.net.UidRange;
57 import android.net.Uri;
58 import android.os.Build;
59 import android.os.Handler;
60 import android.os.HandlerThread;
61 import android.os.Process;
62 import android.os.RemoteException;
63 import android.os.ServiceSpecificException;
64 import android.os.SystemConfigManager;
65 import android.os.UserHandle;
66 import android.os.UserManager;
67 import android.permission.PermissionManager;
68 import android.provider.Settings;
69 import android.util.ArrayMap;
70 import android.util.ArraySet;
71 import android.util.Log;
72 import android.util.SparseIntArray;
73 
74 import com.android.internal.annotations.GuardedBy;
75 import com.android.internal.annotations.VisibleForTesting;
76 import com.android.internal.util.IndentingPrintWriter;
77 import com.android.modules.utils.build.SdkLevel;
78 import com.android.net.module.util.CollectionUtils;
79 import com.android.net.module.util.SharedLog;
80 import com.android.networkstack.apishim.ProcessShimImpl;
81 import com.android.networkstack.apishim.common.ProcessShim;
82 import com.android.server.BpfNetMaps;
83 
84 import java.util.ArrayList;
85 import java.util.HashSet;
86 import java.util.List;
87 import java.util.Map;
88 import java.util.Set;
89 
90 /**
91  * A utility class to inform Netd of UID permissions.
92  * Does a mass update at boot and then monitors for app install/remove.
93  *
94  * @hide
95  */
96 public class PermissionMonitor {
97     private static final String TAG = "PermissionMonitor";
98     private static final boolean DBG = true;
99     private static final int VERSION_Q = Build.VERSION_CODES.Q;
100 
101     private final PackageManager mPackageManager;
102     private final UserManager mUserManager;
103     private final SystemConfigManager mSystemConfigManager;
104     private final PermissionManager mPermissionManager;
105     private final PermissionChangeListener mPermissionChangeListener;
106     private final INetd mNetd;
107     private final Dependencies mDeps;
108     private final Context mContext;
109     private final BpfNetMaps mBpfNetMaps;
110     private final HandlerThread mThread;
111 
112     private static final ProcessShim sProcessShim = ProcessShimImpl.newInstance();
113 
114     @GuardedBy("this")
115     private final Set<UserHandle> mUsers = new HashSet<>();
116 
117     // Keys are uids. Values are netd network permissions.
118     @GuardedBy("this")
119     private final SparseIntArray mUidToNetworkPerm = new SparseIntArray();
120 
121     // NonNull keys are active non-bypassable and fully-routed VPN's interface name, Values are uid
122     // ranges for apps under the VPNs which enable interface filtering.
123     // If key is null, Values are uid ranges for apps under the VPNs which are connected but do not
124     // enable interface filtering.
125     @GuardedBy("this")
126     private final Map<String, Set<UidRange>> mVpnInterfaceUidRanges = new ArrayMap<>();
127 
128     // Items are uid ranges for apps under the VPN Lockdown
129     // Ranges were given through ConnectivityManager#setRequireVpnForUids, and ranges are allowed to
130     // have duplicates. Also, it is allowed to give ranges that are already subject to lockdown.
131     // So we need to maintain uid range with multiset.
132     @GuardedBy("this")
133     private final MultiSet<UidRange> mVpnLockdownUidRanges = new MultiSet<>();
134 
135     // A set of appIds for apps across all users on the device. We track appIds instead of uids
136     // directly to reduce its size and also eliminate the need to update this set when user is
137     // added/removed.
138     @GuardedBy("this")
139     private final Set<Integer> mAllApps = new HashSet<>();
140 
141     // A set of uids which are allowed to use restricted networks. The packages of these uids can't
142     // hold the CONNECTIVITY_USE_RESTRICTED_NETWORKS permission because they can't be
143     // signature|privileged apps. However, these apps should still be able to use restricted
144     // networks under certain conditions (e.g. government app using emergency services). So grant
145     // netd system permission to these uids which is listed in UIDS_ALLOWED_ON_RESTRICTED_NETWORKS.
146     @GuardedBy("this")
147     private final Set<Integer> mUidsAllowedOnRestrictedNetworks = new ArraySet<>();
148 
149     // Store PackageManager for each user.
150     // Keys are users, Values are PackageManagers which get from each user.
151     @GuardedBy("this")
152     private final Map<UserHandle, PackageManager> mUsersPackageManager = new ArrayMap<>();
153 
154     // Store appIds traffic permissions for each user.
155     // Keys are users, Values are SparseArrays where each entry maps an appId to the permissions
156     // that appId has within that user. The permissions are a bitmask of PERMISSION_INTERNET and
157     // PERMISSION_UPDATE_DEVICE_STATS, or 0 (PERMISSION_NONE) if the app has neither of those
158     // permissions. They can never be PERMISSION_UNINSTALLED.
159     @GuardedBy("this")
160     private final Map<UserHandle, SparseIntArray> mUsersTrafficPermissions = new ArrayMap<>();
161 
162     private static final int SYSTEM_APPID = SYSTEM_UID;
163 
164     private static final int MAX_PERMISSION_UPDATE_LOGS = 40;
165     private final SharedLog mPermissionUpdateLogs = new SharedLog(MAX_PERMISSION_UPDATE_LOGS, TAG);
166 
167     private BroadcastReceiver mIntentReceiver = new BroadcastReceiver() {
168         @Override
169         public void onReceive(Context context, Intent intent) {
170             final String action = intent.getAction();
171 
172             if (Intent.ACTION_PACKAGE_ADDED.equals(action)) {
173                 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
174                 final Uri packageData = intent.getData();
175                 final String packageName =
176                         packageData != null ? packageData.getSchemeSpecificPart() : null;
177                 onPackageAdded(packageName, uid);
178             } else if (Intent.ACTION_PACKAGE_REMOVED.equals(action)) {
179                 final int uid = intent.getIntExtra(Intent.EXTRA_UID, -1);
180                 final Uri packageData = intent.getData();
181                 final String packageName =
182                         packageData != null ? packageData.getSchemeSpecificPart() : null;
183                 onPackageRemoved(packageName, uid);
184             } else if (Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE.equals(action)) {
185                 final String[] pkgList =
186                         intent.getStringArrayExtra(Intent.EXTRA_CHANGED_PACKAGE_LIST);
187                 onExternalApplicationsAvailable(pkgList);
188             } else if (Intent.ACTION_USER_ADDED.equals(action)) {
189                 final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
190                 // User should be filled for below intents, check the existence.
191                 if (user == null) {
192                     Log.wtf(TAG, action + " broadcast without EXTRA_USER");
193                     return;
194                 }
195                 onUserAdded(user);
196             } else if (Intent.ACTION_USER_REMOVED.equals(action)) {
197                 final UserHandle user = intent.getParcelableExtra(Intent.EXTRA_USER);
198                 // User should be filled for below intents, check the existence.
199                 if (user == null) {
200                     Log.wtf(TAG, action + " broadcast without EXTRA_USER");
201                     return;
202                 }
203                 onUserRemoved(user);
204             } else {
205                 Log.wtf(TAG, "received unexpected intent: " + action);
206             }
207         }
208     };
209 
210     /**
211      * Dependencies of PermissionMonitor, for injection in tests.
212      */
213     @VisibleForTesting
214     public static class Dependencies {
215         /**
216          * Get device first sdk version.
217          */
getDeviceFirstSdkInt()218         public int getDeviceFirstSdkInt() {
219             return Build.VERSION.DEVICE_INITIAL_SDK_INT;
220         }
221 
222         /**
223          * Get uids allowed to use restricted networks via ConnectivitySettingsManager.
224          */
getUidsAllowedOnRestrictedNetworks(@onNull Context context)225         public Set<Integer> getUidsAllowedOnRestrictedNetworks(@NonNull Context context) {
226             return ConnectivitySettingsManager.getUidsAllowedOnRestrictedNetworks(context);
227         }
228 
229         /**
230          * Register ContentObserver for given Uri.
231          */
registerContentObserver(@onNull Context context, @NonNull Uri uri, boolean notifyForDescendants, @NonNull ContentObserver observer)232         public void registerContentObserver(@NonNull Context context, @NonNull Uri uri,
233                 boolean notifyForDescendants, @NonNull ContentObserver observer) {
234             context.getContentResolver().registerContentObserver(
235                     uri, notifyForDescendants, observer);
236         }
237 
shouldEnforceLocalNetRestrictions(int uid)238         public boolean shouldEnforceLocalNetRestrictions(int uid) {
239             // TODO(b/394567896): Update compat change checks for enforcement
240             return BpfNetMaps.isAtLeast25Q2() &&
241                     CompatChanges.isChangeEnabled(RESTRICT_LOCAL_NETWORK, uid);
242         }
243     }
244 
245     private static class MultiSet<T> {
246         private final Map<T, Integer> mMap = new ArrayMap<>();
247 
248         /**
249          * Returns the number of key in the set before this addition.
250          */
add(T key)251         public int add(T key) {
252             final int oldCount = mMap.getOrDefault(key, 0);
253             mMap.put(key, oldCount + 1);
254             return oldCount;
255         }
256 
257         /**
258          * Return the number of key in the set before this removal.
259          */
remove(T key)260         public int remove(T key) {
261             final int oldCount = mMap.getOrDefault(key, 0);
262             if (oldCount == 0) {
263                 Log.wtf(TAG, "Attempt to remove non existing key = " + key.toString());
264             } else if (oldCount == 1) {
265                 mMap.remove(key);
266             } else {
267                 mMap.put(key, oldCount - 1);
268             }
269             return oldCount;
270         }
271 
getSet()272         public Set<T> getSet() {
273             return mMap.keySet();
274         }
275     }
276 
PermissionMonitor(@onNull final Context context, @NonNull final INetd netd, @NonNull final BpfNetMaps bpfNetMaps, @NonNull final HandlerThread thread)277     public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd,
278             @NonNull final BpfNetMaps bpfNetMaps, @NonNull final HandlerThread thread) {
279         this(context, netd, bpfNetMaps, new Dependencies(), thread);
280     }
281 
282     @VisibleForTesting
PermissionMonitor(@onNull final Context context, @NonNull final INetd netd, @NonNull final BpfNetMaps bpfNetMaps, @NonNull final Dependencies deps, @NonNull final HandlerThread thread)283     public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd,
284             @NonNull final BpfNetMaps bpfNetMaps,
285             @NonNull final Dependencies deps,
286             @NonNull final HandlerThread thread) {
287         mPackageManager = context.getPackageManager();
288         mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE);
289         mSystemConfigManager = context.getSystemService(SystemConfigManager.class);
290         mPermissionManager = context.getSystemService(PermissionManager.class);
291         mPermissionChangeListener = new PermissionChangeListener();
292         mNetd = netd;
293         mDeps = deps;
294         mContext = context;
295         mBpfNetMaps = bpfNetMaps;
296         mThread = thread;
297         if (BpfNetMaps.isAtLeast25Q2()) {
298             // Local net restrictions is supported as a developer opt-in starting in Android B.
299             // This listener should finish registration by the time the system has completed
300             // boot setup such that any changes to runtime permissions for local network
301             // restrictions can only occur after this registration has completed.
302             mPackageManager.addOnPermissionsChangeListener(mPermissionChangeListener);
303         }
304     }
305 
306     @VisibleForTesting
setLocalNetworkPermissions(final int uid, @Nullable final String packageName)307     void setLocalNetworkPermissions(final int uid, @Nullable final String packageName) {
308         if (!mDeps.shouldEnforceLocalNetRestrictions(uid)) return;
309 
310         final AttributionSource attributionSource =
311                 new AttributionSource.Builder(uid).setPackageName(packageName).build();
312         final int permissionState = mPermissionManager.checkPermissionForPreflight(
313                 NEARBY_WIFI_DEVICES, attributionSource);
314         if (permissionState == PermissionManager.PERMISSION_GRANTED) {
315             mBpfNetMaps.removeUidFromLocalNetBlockMap(attributionSource.getUid());
316         } else {
317             mBpfNetMaps.addUidToLocalNetBlockMap(attributionSource.getUid());
318         }
319         if (hasSdkSandbox(uid)){
320             // SDKs in the SDK RT cannot hold runtime permissions
321             final int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
322             if (!mBpfNetMaps.isUidBlockedFromUsingLocalNetwork(sdkSandboxUid)) {
323                 mBpfNetMaps.addUidToLocalNetBlockMap(sdkSandboxUid);
324             }
325         }
326     }
327 
ensureRunningOnHandlerThread()328     private void ensureRunningOnHandlerThread() {
329         if (mThread.getLooper().getThread() != Thread.currentThread()) {
330             throw new IllegalStateException(
331                     "Not running on Handler thread: " + Thread.currentThread().getName());
332         }
333     }
334 
getPackageNetdNetworkPermission(@onNull final PackageInfo app)335     private int getPackageNetdNetworkPermission(@NonNull final PackageInfo app) {
336         if (hasRestrictedNetworkPermission(app)) {
337             return PERMISSION_SYSTEM;
338         }
339         if (hasNetworkPermission(app)) {
340             return PERMISSION_NETWORK;
341         }
342         return PERMISSION_NONE;
343     }
344 
isHigherNetworkPermission(final int targetPermission, final int currentPermission)345     static boolean isHigherNetworkPermission(final int targetPermission,
346             final int currentPermission) {
347         // This is relied on strict order of network permissions (SYSTEM > NETWORK > NONE), and it
348         // is enforced in tests.
349         return targetPermission > currentPermission;
350     }
351 
getInstalledPackagesAsUser(final UserHandle user)352     private List<PackageInfo> getInstalledPackagesAsUser(final UserHandle user) {
353         return mPackageManager.getInstalledPackagesAsUser(GET_PERMISSIONS, user.getIdentifier());
354     }
355 
updateAllApps(final List<PackageInfo> apps)356     private synchronized void updateAllApps(final List<PackageInfo> apps) {
357         for (PackageInfo app : apps) {
358             final int appId = app.applicationInfo != null
359                     ? UserHandle.getAppId(app.applicationInfo.uid) : INVALID_UID;
360             if (appId < 0) {
361                 continue;
362             }
363             mAllApps.add(appId);
364         }
365     }
366 
hasSdkSandbox(final int uid)367     private static boolean hasSdkSandbox(final int uid) {
368         return SdkLevel.isAtLeastT() && Process.isApplicationUid(uid);
369     }
370 
371     // Return the network permission for the passed list of apps. Note that this depends on the
372     // current settings of the device (See isUidAllowedOnRestrictedNetworks).
makeUidsNetworkPerm(final List<PackageInfo> apps)373     private SparseIntArray makeUidsNetworkPerm(final List<PackageInfo> apps) {
374         final SparseIntArray uidsPerm = new SparseIntArray();
375         for (PackageInfo app : apps) {
376             final int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID;
377             if (uid < 0) {
378                 continue;
379             }
380             final int permission = getPackageNetdNetworkPermission(app);
381             if (isHigherNetworkPermission(permission, uidsPerm.get(uid, PERMISSION_NONE))) {
382                 uidsPerm.put(uid, permission);
383                 if (hasSdkSandbox(uid)) {
384                     int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
385                     uidsPerm.put(sdkSandboxUid, permission);
386                 }
387             }
388             setLocalNetworkPermissions(uid, app.packageName);
389         }
390         return uidsPerm;
391     }
392 
makeAppIdsTrafficPerm(final List<PackageInfo> apps)393     private static SparseIntArray makeAppIdsTrafficPerm(final List<PackageInfo> apps) {
394         final SparseIntArray appIdsPerm = new SparseIntArray();
395         for (PackageInfo app : apps) {
396             final int appId = app.applicationInfo != null
397                     ? UserHandle.getAppId(app.applicationInfo.uid) : INVALID_UID;
398             if (appId < 0) {
399                 continue;
400             }
401             final int otherNetdPerms = getNetdPermissionMask(app.requestedPermissions,
402                     app.requestedPermissionsFlags);
403             final int permission = appIdsPerm.get(appId) | otherNetdPerms;
404             appIdsPerm.put(appId, permission);
405             if (hasSdkSandbox(appId)) {
406                 appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
407             }
408         }
409         return appIdsPerm;
410     }
411 
updateUidsNetworkPermission(final SparseIntArray uids)412     private synchronized void updateUidsNetworkPermission(final SparseIntArray uids) {
413         for (int i = 0; i < uids.size(); i++) {
414             mUidToNetworkPerm.put(uids.keyAt(i), uids.valueAt(i));
415         }
416         sendUidsNetworkPermission(uids, true /* add */);
417     }
418 
419     /**
420      * Calculates permissions for appIds.
421      * Maps each appId to the union of all traffic permissions that the appId has in all users.
422      *
423      * @return The appIds traffic permissions.
424      */
makeAppIdsTrafficPermForAllUsers()425     private synchronized SparseIntArray makeAppIdsTrafficPermForAllUsers() {
426         final SparseIntArray appIds = new SparseIntArray();
427         // Check appIds permissions from each user.
428         for (UserHandle user : mUsersTrafficPermissions.keySet()) {
429             final SparseIntArray userAppIds = mUsersTrafficPermissions.get(user);
430             for (int i = 0; i < userAppIds.size(); i++) {
431                 final int appId = userAppIds.keyAt(i);
432                 final int permission = userAppIds.valueAt(i);
433                 appIds.put(appId, appIds.get(appId) | permission);
434             }
435         }
436         return appIds;
437     }
438 
getSystemTrafficPerm()439     private SparseIntArray getSystemTrafficPerm() {
440         final SparseIntArray appIdsPerm = new SparseIntArray();
441         for (final int uid : mSystemConfigManager.getSystemPermissionUids(INTERNET)) {
442             final int appId = UserHandle.getAppId(uid);
443             final int permission = appIdsPerm.get(appId) | TRAFFIC_PERMISSION_INTERNET;
444             appIdsPerm.put(appId, permission);
445             if (hasSdkSandbox(appId)) {
446                 appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
447             }
448         }
449         for (final int uid : mSystemConfigManager.getSystemPermissionUids(UPDATE_DEVICE_STATS)) {
450             final int appId = UserHandle.getAppId(uid);
451             final int permission = appIdsPerm.get(appId) | TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS;
452             appIdsPerm.put(appId, permission);
453             if (hasSdkSandbox(appId)) {
454                 appIdsPerm.put(sProcessShim.toSdkSandboxUid(appId), permission);
455             }
456         }
457         return appIdsPerm;
458     }
459 
460     // Intended to be called only once at startup, after the system is ready. Installs a broadcast
461     // receiver to monitor ongoing UID changes, so this shouldn't/needn't be called again.
startMonitoring()462     public synchronized void startMonitoring() {
463         log("Monitoring");
464 
465         final Handler handler = new Handler(mThread.getLooper());
466         final Context userAllContext = mContext.createContextAsUser(UserHandle.ALL, 0 /* flags */);
467         final IntentFilter intentFilter = new IntentFilter();
468         intentFilter.addAction(Intent.ACTION_PACKAGE_ADDED);
469         intentFilter.addAction(Intent.ACTION_PACKAGE_REMOVED);
470         intentFilter.addDataScheme("package");
471         userAllContext.registerReceiver(
472                 mIntentReceiver, intentFilter, null /* broadcastPermission */, handler);
473 
474         // Listen to EXTERNAL_APPLICATIONS_AVAILABLE is that an app becoming available means it may
475         // need to gain a permission. But an app that becomes unavailable can neither gain nor lose
476         // permissions on that account, it just can no longer run. Thus, doesn't need to listen to
477         // EXTERNAL_APPLICATIONS_UNAVAILABLE.
478         final IntentFilter externalIntentFilter =
479                 new IntentFilter(Intent.ACTION_EXTERNAL_APPLICATIONS_AVAILABLE);
480         userAllContext.registerReceiver(
481                 mIntentReceiver, externalIntentFilter, null /* broadcastPermission */, handler);
482 
483         // Listen for user add/remove.
484         final IntentFilter userIntentFilter = new IntentFilter();
485         userIntentFilter.addAction(Intent.ACTION_USER_ADDED);
486         userIntentFilter.addAction(Intent.ACTION_USER_REMOVED);
487         userAllContext.registerReceiver(
488                 mIntentReceiver, userIntentFilter, null /* broadcastPermission */, handler);
489 
490         // Register UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting observer
491         mDeps.registerContentObserver(
492                 userAllContext,
493                 Settings.Global.getUriFor(UIDS_ALLOWED_ON_RESTRICTED_NETWORKS),
494                 false /* notifyForDescendants */,
495                 new ContentObserver(handler) {
496                     @Override
497                     public void onChange(boolean selfChange) {
498                         onSettingChanged();
499                     }
500                 });
501 
502         // Read UIDS_ALLOWED_ON_RESTRICTED_NETWORKS setting and update
503         // mUidsAllowedOnRestrictedNetworks.
504         updateUidsAllowedOnRestrictedNetworks(mDeps.getUidsAllowedOnRestrictedNetworks(mContext));
505 
506         // Read system traffic permissions when a user removed and put them to USER_ALL because they
507         // are not specific to any particular user.
508         mUsersTrafficPermissions.put(UserHandle.ALL, getSystemTrafficPerm());
509 
510         final List<UserHandle> usrs = mUserManager.getUserHandles(true /* excludeDying */);
511         // Update netd permissions for all users.
512         for (UserHandle user : usrs) {
513             onUserAdded(user);
514         }
515         log("Users: " + mUsers.size() + ", UidToNetworkPerm: " + mUidToNetworkPerm.size());
516     }
517 
518     @VisibleForTesting
updateUidsAllowedOnRestrictedNetworks(final Set<Integer> uids)519     synchronized void updateUidsAllowedOnRestrictedNetworks(final Set<Integer> uids) {
520         mUidsAllowedOnRestrictedNetworks.clear();
521         mUidsAllowedOnRestrictedNetworks.addAll(uids);
522     }
523 
524     @VisibleForTesting
isVendorApp(@onNull ApplicationInfo appInfo)525     static boolean isVendorApp(@NonNull ApplicationInfo appInfo) {
526         return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct();
527     }
528 
529     @VisibleForTesting
isCarryoverPackage(final ApplicationInfo appInfo)530     boolean isCarryoverPackage(final ApplicationInfo appInfo) {
531         if (appInfo == null) return false;
532         return (appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo))
533                 // Backward compatibility for b/114245686, on devices that launched before Q daemons
534                 // and apps running as the system UID are exempted from this check.
535                 || (UserHandle.getAppId(appInfo.uid) == SYSTEM_APPID
536                         && mDeps.getDeviceFirstSdkInt() < VERSION_Q);
537     }
538 
539     @VisibleForTesting
isUidAllowedOnRestrictedNetworks(final ApplicationInfo appInfo)540     synchronized boolean isUidAllowedOnRestrictedNetworks(final ApplicationInfo appInfo) {
541         if (appInfo == null) return false;
542         // Check whether package's uid is in allowed on restricted networks uid list. If so, this
543         // uid can have netd system permission.
544         return isUidAllowedOnRestrictedNetworks(appInfo.uid);
545     }
546 
547     /**
548      * Returns whether the given uid is in allowed on restricted networks list.
549      */
isUidAllowedOnRestrictedNetworks(final int uid)550     public synchronized boolean isUidAllowedOnRestrictedNetworks(final int uid) {
551         return mUidsAllowedOnRestrictedNetworks.contains(uid);
552     }
553 
554     @VisibleForTesting
hasPermission(@onNull final PackageInfo app, @NonNull final String permission)555     boolean hasPermission(@NonNull final PackageInfo app, @NonNull final String permission) {
556         if (app.requestedPermissions == null || app.requestedPermissionsFlags == null) {
557             return false;
558         }
559         final int index = CollectionUtils.indexOf(app.requestedPermissions, permission);
560         if (index < 0 || index >= app.requestedPermissionsFlags.length) return false;
561         return (app.requestedPermissionsFlags[index] & REQUESTED_PERMISSION_GRANTED) != 0;
562     }
563 
564     @VisibleForTesting
hasNetworkPermission(@onNull final PackageInfo app)565     boolean hasNetworkPermission(@NonNull final PackageInfo app) {
566         return hasPermission(app, CHANGE_NETWORK_STATE);
567     }
568 
569     @VisibleForTesting
hasRestrictedNetworkPermission(@onNull final PackageInfo app)570     boolean hasRestrictedNetworkPermission(@NonNull final PackageInfo app) {
571         // TODO : remove carryover package check in the future(b/31479477). All apps should just
572         //  request the appropriate permission for their use case since android Q.
573         return isCarryoverPackage(app.applicationInfo)
574                 || isUidAllowedOnRestrictedNetworks(app.applicationInfo)
575                 || hasPermission(app, PERMISSION_MAINLINE_NETWORK_STACK)
576                 || hasPermission(app, NETWORK_STACK)
577                 || hasPermission(app, CONNECTIVITY_USE_RESTRICTED_NETWORKS);
578     }
579 
580     /** Returns whether the given uid has using background network permission. */
hasUseBackgroundNetworksPermission(final int uid)581     public synchronized boolean hasUseBackgroundNetworksPermission(final int uid) {
582         // Apps with any of the CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_INTERNAL or
583         // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission has the permission to use background
584         // networks. mUidToNetworkPerm contains the result of checks for hasNetworkPermission and
585         // hasRestrictedNetworkPermission, as well as the list of UIDs allowed on restricted
586         // networks. If uid is in the mUidToNetworkPerm list that means uid has one of permissions
587         // at least.
588         return mUidToNetworkPerm.get(uid, PERMISSION_NONE) != PERMISSION_NONE;
589     }
590 
591     /**
592      * Returns whether the given uid has permission to use restricted networks.
593      */
hasRestrictedNetworksPermission(int uid)594     public synchronized boolean hasRestrictedNetworksPermission(int uid) {
595         return PERMISSION_SYSTEM == mUidToNetworkPerm.get(uid, PERMISSION_NONE);
596     }
597 
sendUidsNetworkPermission(SparseIntArray uids, boolean add)598     private void sendUidsNetworkPermission(SparseIntArray uids, boolean add) {
599         ensureRunningOnHandlerThread();
600         List<Integer> network = new ArrayList<>();
601         List<Integer> system = new ArrayList<>();
602         for (int i = 0; i < uids.size(); i++) {
603             final int permission = uids.valueAt(i);
604             if (PERMISSION_NONE == permission) {
605                 continue; // Normally NONE is not stored in this map, but just in case
606             }
607             List<Integer> list = (PERMISSION_SYSTEM == permission) ? system : network;
608             list.add(uids.keyAt(i));
609         }
610         try {
611             if (add) {
612                 mNetd.networkSetPermissionForUser(PERMISSION_NETWORK, toIntArray(network));
613                 mNetd.networkSetPermissionForUser(PERMISSION_SYSTEM, toIntArray(system));
614             } else {
615                 mNetd.networkClearPermissionForUser(toIntArray(network));
616                 mNetd.networkClearPermissionForUser(toIntArray(system));
617             }
618         } catch (RemoteException e) {
619             loge("Exception when updating permissions: " + e);
620         }
621     }
622 
623     /**
624      * Called when a user is added. See {link #ACTION_USER_ADDED}.
625      *
626      * @param user The integer userHandle of the added user. See {@link #EXTRA_USER_HANDLE}.
627      *
628      * @hide
629      */
630     @VisibleForTesting
onUserAdded(@onNull UserHandle user)631     synchronized void onUserAdded(@NonNull UserHandle user) {
632         mUsers.add(user);
633 
634         final List<PackageInfo> apps = getInstalledPackagesAsUser(user);
635 
636         // Save all apps in mAllApps
637         updateAllApps(apps);
638 
639         // Uids network permissions
640         final SparseIntArray uids = makeUidsNetworkPerm(apps);
641         updateUidsNetworkPermission(uids);
642 
643         // Add new user appIds permissions.
644         final SparseIntArray addedUserAppIds = makeAppIdsTrafficPerm(apps);
645         mUsersTrafficPermissions.put(user, addedUserAppIds);
646         // Generate appIds from all users and send result to netd.
647         final SparseIntArray appIds = makeAppIdsTrafficPermForAllUsers();
648         sendAppIdsTrafficPermission(appIds);
649 
650         // Log user added
651         mPermissionUpdateLogs.log("New user(" + user.getIdentifier() + ") added: nPerm uids="
652                 + uids + ", tPerm appIds=" + addedUserAppIds);
653     }
654 
655     /**
656      * Called when an user is removed. See {link #ACTION_USER_REMOVED}.
657      *
658      * @param user The integer userHandle of the removed user. See {@link #EXTRA_USER_HANDLE}.
659      *
660      * @hide
661      */
662     @VisibleForTesting
onUserRemoved(@onNull UserHandle user)663     synchronized void onUserRemoved(@NonNull UserHandle user) {
664         mUsers.remove(user);
665 
666         // Remove uids network permissions that belongs to the user.
667         final SparseIntArray removedUids = new SparseIntArray();
668         final SparseIntArray allUids = mUidToNetworkPerm.clone();
669         for (int i = 0; i < allUids.size(); i++) {
670             final int uid = allUids.keyAt(i);
671             if (user.equals(UserHandle.getUserHandleForUid(uid))) {
672                 mUidToNetworkPerm.delete(uid);
673                 if (mDeps.shouldEnforceLocalNetRestrictions(uid)) {
674                     mBpfNetMaps.removeUidFromLocalNetBlockMap(uid);
675                     if (hasSdkSandbox(uid)) mBpfNetMaps.removeUidFromLocalNetBlockMap(
676                             sProcessShim.toSdkSandboxUid(uid));
677                 }
678                 removedUids.put(uid, allUids.valueAt(i));
679             }
680         }
681         sendUidsNetworkPermission(removedUids, false /* add */);
682 
683         // Remove appIds traffic permission that belongs to the user
684         final SparseIntArray removedUserAppIds = mUsersTrafficPermissions.remove(user);
685         // Generate appIds from the remaining users.
686         final SparseIntArray appIds = makeAppIdsTrafficPermForAllUsers();
687 
688         if (removedUserAppIds == null) {
689             Log.wtf(TAG, "onUserRemoved: Receive unknown user=" + user);
690             return;
691         }
692 
693         // Clear permission on those appIds belong to this user only, set the permission to
694         // PERMISSION_UNINSTALLED.
695         for (int i = 0; i < removedUserAppIds.size(); i++) {
696             final int appId = removedUserAppIds.keyAt(i);
697             // Need to clear permission if the removed appId is not found in the array.
698             if (appIds.indexOfKey(appId) < 0) {
699                 appIds.put(appId, TRAFFIC_PERMISSION_UNINSTALLED);
700             }
701         }
702         sendAppIdsTrafficPermission(appIds);
703 
704         // Log user removed
705         mPermissionUpdateLogs.log("User(" + user.getIdentifier() + ") removed: nPerm uids="
706                 + removedUids + ", tPerm appIds=" + removedUserAppIds);
707     }
708 
709     /**
710      * Compare the current network permission and the given package's permission to find out highest
711      * permission for the uid.
712      *
713      * @param uid The target uid
714      * @param currentPermission Current uid network permission
715      * @param name The package has same uid that need compare its permission to update uid network
716      *             permission.
717      */
718     @VisibleForTesting
highestPermissionForUid(int uid, int currentPermission, String name)719     protected int highestPermissionForUid(int uid, int currentPermission, String name) {
720         // If multiple packages share a UID (cf: android:sharedUserId) and ask for different
721         // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is).
722         if (currentPermission == PERMISSION_SYSTEM) {
723             return currentPermission;
724         }
725         final PackageInfo app = getPackageInfoAsUser(name, UserHandle.getUserHandleForUid(uid));
726         if (app == null) return currentPermission;
727 
728         final int permission = getPackageNetdNetworkPermission(app);
729         if (isHigherNetworkPermission(permission, currentPermission)) {
730             return permission;
731         }
732         return currentPermission;
733     }
734 
getTrafficPermissionForUid(final int uid)735     private int getTrafficPermissionForUid(final int uid) {
736         int permission = PERMISSION_NONE;
737         // Check all the packages for this UID. The UID has the permission if any of the
738         // packages in it has the permission.
739         final String[] packages = mPackageManager.getPackagesForUid(uid);
740         if (packages != null && packages.length > 0) {
741             for (String name : packages) {
742                 final PackageInfo app = getPackageInfoAsUser(name,
743                         UserHandle.getUserHandleForUid(uid));
744                 if (app != null && app.requestedPermissions != null) {
745                     permission |= getNetdPermissionMask(app.requestedPermissions,
746                             app.requestedPermissionsFlags);
747                 }
748             }
749         } else {
750             // The last package of this uid is removed from device. Clean the package up.
751             permission = TRAFFIC_PERMISSION_UNINSTALLED;
752         }
753         return permission;
754     }
755 
updateVpnUid(int uid, boolean add)756     private synchronized void updateVpnUid(int uid, boolean add) {
757         // Apps that can use restricted networks can always bypass VPNs.
758         if (hasRestrictedNetworksPermission(uid)) {
759             return;
760         }
761         for (Map.Entry<String, Set<UidRange>> vpn : mVpnInterfaceUidRanges.entrySet()) {
762             if (UidRange.containsUid(vpn.getValue(), uid)) {
763                 final Set<Integer> changedUids = new HashSet<>();
764                 changedUids.add(uid);
765                 updateVpnUidsInterfaceRules(vpn.getKey(), changedUids, add);
766             }
767         }
768     }
769 
updateLockdownUid(int uid, boolean add)770     private synchronized void updateLockdownUid(int uid, boolean add) {
771         // Apps that can use restricted networks can always bypass VPNs.
772         if (hasRestrictedNetworksPermission(uid)) {
773             return;
774         }
775 
776         if (UidRange.containsUid(mVpnLockdownUidRanges.getSet(), uid)) {
777             updateLockdownUidRule(uid, add);
778         }
779     }
780 
781     /**
782      * This handles both network and traffic permission, because there is no overlap in actual
783      * values, where network permission is NETWORK or SYSTEM, and traffic permission is INTERNET
784      * or UPDATE_DEVICE_STATS
785      */
permissionToString(int permission)786     private String permissionToString(int permission) {
787         switch (permission) {
788             case PERMISSION_NONE:
789                 return "NONE";
790             case PERMISSION_NETWORK:
791                 return "NETWORK";
792             case PERMISSION_SYSTEM:
793                 return "SYSTEM";
794             case TRAFFIC_PERMISSION_INTERNET:
795                 return "INTERNET";
796             case TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS:
797                 return "UPDATE_DEVICE_STATS";
798             case (TRAFFIC_PERMISSION_INTERNET | TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS):
799                 return "ALL";
800             case TRAFFIC_PERMISSION_UNINSTALLED:
801                 return "UNINSTALLED";
802             default:
803                 return "UNKNOWN";
804         }
805     }
806 
updateAppIdTrafficPermission(int uid)807     private synchronized void updateAppIdTrafficPermission(int uid) {
808         final int uidTrafficPerm = getTrafficPermissionForUid(uid);
809         final SparseIntArray userTrafficPerms =
810                 mUsersTrafficPermissions.get(UserHandle.getUserHandleForUid(uid));
811         if (userTrafficPerms == null) {
812             Log.wtf(TAG, "Can't get user traffic permission from uid=" + uid);
813             return;
814         }
815         // Do not put PERMISSION_UNINSTALLED into the array. If no package left on the uid
816         // (PERMISSION_UNINSTALLED), remove the appId from the array. Otherwise, update the latest
817         // permission to the appId.
818         final int appId = UserHandle.getAppId(uid);
819         if (uidTrafficPerm == TRAFFIC_PERMISSION_UNINSTALLED) {
820             userTrafficPerms.delete(appId);
821         } else {
822             userTrafficPerms.put(appId, uidTrafficPerm);
823         }
824     }
825 
getAppIdTrafficPermission(int appId)826     private synchronized int getAppIdTrafficPermission(int appId) {
827         int permission = PERMISSION_NONE;
828         boolean installed = false;
829         for (UserHandle user : mUsersTrafficPermissions.keySet()) {
830             final SparseIntArray userApps = mUsersTrafficPermissions.get(user);
831             final int appIdx = userApps.indexOfKey(appId);
832             if (appIdx >= 0) {
833                 permission |= userApps.valueAt(appIdx);
834                 installed = true;
835             }
836         }
837         return installed ? permission : TRAFFIC_PERMISSION_UNINSTALLED;
838     }
839 
840     /**
841      * Called when a package is added.
842      *
843      * @param packageName The name of the new package.
844      * @param uid The uid of the new package.
845      *
846      * @hide
847      */
848     @VisibleForTesting
onPackageAdded(@onNull final String packageName, final int uid)849     synchronized void onPackageAdded(@NonNull final String packageName, final int uid) {
850         // Update uid permission.
851         updateAppIdTrafficPermission(uid);
852         // Get the appId permission from all users then send the latest permission to netd.
853         final int appId = UserHandle.getAppId(uid);
854         final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
855         sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
856 
857         final int currentPermission = mUidToNetworkPerm.get(uid, PERMISSION_NONE);
858         final int permission = highestPermissionForUid(uid, currentPermission, packageName);
859         if (permission != currentPermission) {
860             mUidToNetworkPerm.put(uid, permission);
861 
862             SparseIntArray apps = new SparseIntArray();
863             apps.put(uid, permission);
864 
865             if (hasSdkSandbox(uid)) {
866                 int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
867                 mUidToNetworkPerm.put(sdkSandboxUid, permission);
868                 apps.put(sdkSandboxUid, permission);
869             }
870             sendUidsNetworkPermission(apps, true /* add */);
871         }
872         setLocalNetworkPermissions(uid, packageName);
873 
874         // If the newly-installed package falls within some VPN's uid range, update Netd with it.
875         // This needs to happen after the mUidToNetworkPerm update above, since
876         // hasRestrictedNetworksPermission() in updateVpnUid() and updateLockdownUid() depends on
877         // mUidToNetworkPerm to check if the package can bypass VPN.
878         updateVpnUid(uid, true /* add */);
879         updateLockdownUid(uid, true /* add */);
880         mAllApps.add(appId);
881 
882         // Log package added.
883         mPermissionUpdateLogs.log("Package add: uid=" + uid
884                 + ", nPerm=(" + permissionToString(permission) + "/"
885                 + permissionToString(currentPermission) + ")"
886                 + ", tPerm=" + permissionToString(appIdTrafficPerm));
887     }
888 
highestUidNetworkPermission(int uid)889     private int highestUidNetworkPermission(int uid) {
890         int permission = PERMISSION_NONE;
891         final String[] packages = mPackageManager.getPackagesForUid(uid);
892         if (!CollectionUtils.isEmpty(packages)) {
893             for (String name : packages) {
894                 // If multiple packages have the same UID, give the UID all permissions that
895                 // any package in that UID has.
896                 permission = highestPermissionForUid(uid, permission, name);
897                 if (permission == PERMISSION_SYSTEM) {
898                     break;
899                 }
900             }
901         }
902         return permission;
903     }
904 
905     /**
906      * Called when a package is removed.
907      *
908      * @param packageName The name of the removed package or null.
909      * @param uid containing the integer uid previously assigned to the package.
910      *
911      * @hide
912      */
913     @VisibleForTesting
onPackageRemoved(@onNull final String packageName, final int uid)914     synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) {
915         // Update uid permission.
916         updateAppIdTrafficPermission(uid);
917         if (BpfNetMaps.isAtLeast25Q2()) {
918             mBpfNetMaps.removeUidFromLocalNetBlockMap(uid);
919             if (hasSdkSandbox(uid)) mBpfNetMaps.removeUidFromLocalNetBlockMap(
920                     sProcessShim.toSdkSandboxUid(uid));
921         }
922         // Get the appId permission from all users then send the latest permission to netd.
923         final int appId = UserHandle.getAppId(uid);
924         final int appIdTrafficPerm = getAppIdTrafficPermission(appId);
925         sendPackagePermissionsForAppId(appId, appIdTrafficPerm);
926 
927         // If the newly-removed package falls within some VPN's uid range, update Netd with it.
928         // This needs to happen before the mUidToNetworkPerm update below, since
929         // hasRestrictedNetworksPermission() in updateVpnUid() and updateLockdownUid() depends on
930         // mUidToNetworkPerm to check if the package can bypass VPN.
931         updateVpnUid(uid, false /* add */);
932         updateLockdownUid(uid, false /* add */);
933         // If the package has been removed from all users on the device, clear it form mAllApps.
934         if (mPackageManager.getNameForUid(uid) == null) {
935             mAllApps.remove(appId);
936         }
937 
938         final int currentPermission = mUidToNetworkPerm.get(uid, PERMISSION_NONE);
939         final int permission = highestUidNetworkPermission(uid);
940 
941         // Log package removed.
942         mPermissionUpdateLogs.log("Package remove: uid=" + uid
943                 + ", nPerm=(" + permissionToString(permission) + "/"
944                 + permissionToString(currentPermission) + ")"
945                 + ", tPerm=" + permissionToString(appIdTrafficPerm));
946 
947         if (permission != currentPermission) {
948             final SparseIntArray apps = new SparseIntArray();
949             int sdkSandboxUid = -1;
950             if (hasSdkSandbox(uid)) {
951                 sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
952             }
953             if (permission == PERMISSION_NONE) {
954                 mUidToNetworkPerm.delete(uid);
955                 apps.put(uid, PERMISSION_NETWORK);  // doesn't matter which permission we pick here
956                 if (sdkSandboxUid != -1) {
957                     mUidToNetworkPerm.delete(sdkSandboxUid);
958                     apps.put(sdkSandboxUid, PERMISSION_NETWORK);
959                 }
960                 sendUidsNetworkPermission(apps, false);
961             } else {
962                 mUidToNetworkPerm.put(uid, permission);
963                 apps.put(uid, permission);
964                 if (sdkSandboxUid != -1) {
965                     mUidToNetworkPerm.put(sdkSandboxUid, permission);
966                     apps.put(sdkSandboxUid, permission);
967                 }
968                 sendUidsNetworkPermission(apps, true);
969             }
970         }
971     }
972 
getNetdPermissionMask(String[] requestedPermissions, int[] requestedPermissionsFlags)973     private static int getNetdPermissionMask(String[] requestedPermissions,
974                                              int[] requestedPermissionsFlags) {
975         int permissions = PERMISSION_NONE;
976         if (requestedPermissions == null || requestedPermissionsFlags == null) return permissions;
977         for (int i = 0; i < requestedPermissions.length; i++) {
978             if (requestedPermissions[i].equals(INTERNET)
979                     && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
980                 permissions |= TRAFFIC_PERMISSION_INTERNET;
981             }
982             if (requestedPermissions[i].equals(UPDATE_DEVICE_STATS)
983                     && ((requestedPermissionsFlags[i] & REQUESTED_PERMISSION_GRANTED) != 0)) {
984                 permissions |= TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS;
985             }
986         }
987         return permissions;
988     }
989 
getPackageManagerAsUser(UserHandle user)990     private synchronized PackageManager getPackageManagerAsUser(UserHandle user) {
991         PackageManager pm = mUsersPackageManager.get(user);
992         if (pm == null) {
993             pm = mContext.createContextAsUser(user, 0 /* flag */).getPackageManager();
994             mUsersPackageManager.put(user, pm);
995         }
996         return pm;
997     }
998 
getPackageInfoAsUser(String packageName, UserHandle user)999     private PackageInfo getPackageInfoAsUser(String packageName, UserHandle user) {
1000         try {
1001             final PackageInfo info = getPackageManagerAsUser(user)
1002                     .getPackageInfo(packageName, GET_PERMISSIONS);
1003             return info;
1004         } catch (NameNotFoundException e) {
1005             // App not found.
1006             loge("NameNotFoundException " + packageName);
1007             return null;
1008         }
1009     }
1010 
1011     /**
1012      * Called when a new set of UID ranges are added to an active VPN network
1013      *
1014      * @param iface The active VPN network's interface name. Null iface indicates that the app is
1015      *              allowed to receive packets on all interfaces.
1016      * @param rangesToAdd The new UID ranges to be added to the network
1017      * @param vpnAppUid The uid of the VPN app
1018      */
onVpnUidRangesAdded(@ullable String iface, Set<UidRange> rangesToAdd, int vpnAppUid)1019     public synchronized void onVpnUidRangesAdded(@Nullable String iface, Set<UidRange> rangesToAdd,
1020             int vpnAppUid) {
1021         // Calculate the list of new app uids under the VPN due to the new UID ranges and update
1022         // Netd about them. Because mAllApps only contains appIds instead of uids, the result might
1023         // be an overestimation if an app is not installed on the user on which the VPN is running,
1024         // but that's safe: if an app is not installed, it cannot receive any packets, so dropping
1025         // packets to that UID is fine.
1026         final Set<Integer> changedUids = intersectUids(rangesToAdd, mAllApps);
1027         removeBypassingUids(changedUids, vpnAppUid);
1028         updateVpnUidsInterfaceRules(iface, changedUids, true /* add */);
1029         if (mVpnInterfaceUidRanges.containsKey(iface)) {
1030             mVpnInterfaceUidRanges.get(iface).addAll(rangesToAdd);
1031         } else {
1032             mVpnInterfaceUidRanges.put(iface, new HashSet<UidRange>(rangesToAdd));
1033         }
1034     }
1035 
1036     /**
1037      * Called when a set of UID ranges are removed from an active VPN network
1038      *
1039      * @param iface The VPN network's interface name. Null iface indicates that the app is allowed
1040      *              to receive packets on all interfaces.
1041      * @param rangesToRemove Existing UID ranges to be removed from the VPN network
1042      * @param vpnAppUid The uid of the VPN app
1043      */
onVpnUidRangesRemoved(@ullable String iface, Set<UidRange> rangesToRemove, int vpnAppUid)1044     public synchronized void onVpnUidRangesRemoved(@Nullable String iface,
1045             Set<UidRange> rangesToRemove, int vpnAppUid) {
1046         // Calculate the list of app uids that are no longer under the VPN due to the removed UID
1047         // ranges and update Netd about them.
1048         final Set<Integer> changedUids = intersectUids(rangesToRemove, mAllApps);
1049         removeBypassingUids(changedUids, vpnAppUid);
1050         updateVpnUidsInterfaceRules(iface, changedUids, false /* add */);
1051         Set<UidRange> existingRanges = mVpnInterfaceUidRanges.getOrDefault(iface, null);
1052         if (existingRanges == null) {
1053             loge("Attempt to remove unknown vpn uid Range iface = " + iface);
1054             return;
1055         }
1056         existingRanges.removeAll(rangesToRemove);
1057         if (existingRanges.size() == 0) {
1058             mVpnInterfaceUidRanges.remove(iface);
1059         }
1060     }
1061 
1062     /**
1063      * Called when UID ranges under VPN Lockdown are updated
1064      *
1065      * @param add {@code true} if the uids are to be added to the Lockdown, {@code false} if they
1066      *        are to be removed from the Lockdown.
1067      * @param ranges The updated UID ranges under VPN Lockdown. This function does not treat the VPN
1068      *               app's UID in any special way. The caller is responsible for excluding the VPN
1069      *               app UID from the passed-in ranges.
1070      *               Ranges can have duplications, overlaps, and/or contain the range that is
1071      *               already subject to lockdown.
1072      */
updateVpnLockdownUidRanges(boolean add, UidRange[] ranges)1073     public synchronized void updateVpnLockdownUidRanges(boolean add, UidRange[] ranges) {
1074         final Set<UidRange> affectedUidRanges = new HashSet<>();
1075 
1076         for (final UidRange range : ranges) {
1077             if (add) {
1078                 // Rule will be added if mVpnLockdownUidRanges does not have this uid range entry
1079                 // currently.
1080                 if (mVpnLockdownUidRanges.add(range) == 0) {
1081                     affectedUidRanges.add(range);
1082                 }
1083             } else {
1084                 // Rule will be removed if the number of the range in the set is 1 before the
1085                 // removal.
1086                 if (mVpnLockdownUidRanges.remove(range) == 1) {
1087                     affectedUidRanges.add(range);
1088                 }
1089             }
1090         }
1091 
1092         // mAllApps only contains appIds instead of uids. So the generated uid list might contain
1093         // apps that are installed only on some users but not others. But that's safe: if an app is
1094         // not installed, it cannot receive any packets, so dropping packets to that UID is fine.
1095         final Set<Integer> affectedUids = intersectUids(affectedUidRanges, mAllApps);
1096 
1097         // We skip adding rule to privileged apps and allow them to bypass incoming packet
1098         // filtering. The behaviour is consistent with how lockdown works for outgoing packets, but
1099         // the implementation is different: while ConnectivityService#setRequireVpnForUids does not
1100         // exclude privileged apps from the prohibit routing rules used to implement outgoing packet
1101         // filtering, privileged apps can still bypass outgoing packet filtering because the
1102         // prohibit rules observe the protected from VPN bit.
1103         // If removing a UID, we ensure it is not present anywhere in the set first.
1104         for (final int uid: affectedUids) {
1105             if (!hasRestrictedNetworksPermission(uid)
1106                     && (add || !UidRange.containsUid(mVpnLockdownUidRanges.getSet(), uid))) {
1107                 updateLockdownUidRule(uid, add);
1108             }
1109         }
1110     }
1111 
1112     /**
1113      * Compute the intersection of a set of UidRanges and appIds. Returns a set of uids
1114      * that satisfies:
1115      *   1. falls into one of the UidRange
1116      *   2. matches one of the appIds
1117      */
intersectUids(Set<UidRange> ranges, Set<Integer> appIds)1118     private Set<Integer> intersectUids(Set<UidRange> ranges, Set<Integer> appIds) {
1119         Set<Integer> result = new HashSet<>();
1120         for (UidRange range : ranges) {
1121             for (int userId = range.getStartUser(); userId <= range.getEndUser(); userId++) {
1122                 for (int appId : appIds) {
1123                     final UserHandle handle = UserHandle.of(userId);
1124                     if (handle == null) continue;
1125 
1126                     final int uid = handle.getUid(appId);
1127                     if (range.contains(uid)) {
1128                         result.add(uid);
1129                     }
1130                 }
1131             }
1132         }
1133         return result;
1134     }
1135 
1136     /**
1137      * Remove all apps which can elect to bypass the VPN from the list of uids
1138      *
1139      * An app can elect to bypass the VPN if it holds SYSTEM permission, or if it's the active VPN
1140      * app itself.
1141      *
1142      * @param uids The list of uids to operate on
1143      * @param vpnAppUid The uid of the VPN app
1144      */
removeBypassingUids(Set<Integer> uids, int vpnAppUid)1145     private void removeBypassingUids(Set<Integer> uids, int vpnAppUid) {
1146         uids.remove(vpnAppUid);
1147         uids.removeIf(this::hasRestrictedNetworksPermission);
1148     }
1149 
1150     /**
1151      * Update netd about the list of uids that are under an active VPN connection which they cannot
1152      * bypass.
1153      *
1154      * This is to instruct netd to set up appropriate filtering rules for these uids, such that they
1155      * can only receive ingress packets from the VPN's tunnel interface (and loopback).
1156      * Null iface set up a wildcard rule that allow app to receive packets on all interfaces.
1157      *
1158      * @param iface the interface name of the active VPN connection
1159      * @param add {@code true} if the uids are to be added to the interface, {@code false} if they
1160      *        are to be removed from the interface.
1161      */
updateVpnUidsInterfaceRules(String iface, Set<Integer> uids, boolean add)1162     private void updateVpnUidsInterfaceRules(String iface, Set<Integer> uids, boolean add) {
1163         if (uids.size() == 0) {
1164             return;
1165         }
1166         try {
1167             if (add) {
1168                 mBpfNetMaps.addUidInterfaceRules(iface, toIntArray(uids));
1169             } else {
1170                 mBpfNetMaps.removeUidInterfaceRules(toIntArray(uids));
1171             }
1172         } catch (RemoteException | ServiceSpecificException e) {
1173             loge("Exception when updating permissions: ", e);
1174         }
1175     }
1176 
updateLockdownUidRule(int uid, boolean add)1177     private void updateLockdownUidRule(int uid, boolean add) {
1178         try {
1179             mBpfNetMaps.updateUidLockdownRule(uid, add);
1180         } catch (ServiceSpecificException e) {
1181             loge("Failed to " + (add ? "add" : "remove") + " Lockdown rule: " + e);
1182         }
1183     }
1184 
1185     /**
1186      * Send the updated permission information to netd. Called upon package install/uninstall.
1187      *
1188      * @param appId the appId of the package installed
1189      * @param permissions the permissions the app requested and netd cares about.
1190      *
1191      * @hide
1192      */
1193     @VisibleForTesting
sendPackagePermissionsForAppId(int appId, int permissions)1194     void sendPackagePermissionsForAppId(int appId, int permissions) {
1195         SparseIntArray netdPermissionsAppIds = new SparseIntArray();
1196         netdPermissionsAppIds.put(appId, permissions);
1197         if (hasSdkSandbox(appId)) {
1198             int sdkSandboxAppId = sProcessShim.toSdkSandboxUid(appId);
1199             netdPermissionsAppIds.put(sdkSandboxAppId, permissions);
1200         }
1201         sendAppIdsTrafficPermission(netdPermissionsAppIds);
1202     }
1203 
1204     /**
1205      * Grant or revoke the INTERNET and/or UPDATE_DEVICE_STATS permission of the appIds in array.
1206      *
1207      * @param netdPermissionsAppIds integer pairs of appIds and the permission granted to it. If the
1208      * permission is 0, revoke all permissions of that appId.
1209      *
1210      * @hide
1211      */
1212     @VisibleForTesting
sendAppIdsTrafficPermission(SparseIntArray netdPermissionsAppIds)1213     void sendAppIdsTrafficPermission(SparseIntArray netdPermissionsAppIds) {
1214         ensureRunningOnHandlerThread();
1215         final ArrayList<Integer> allPermissionAppIds = new ArrayList<>();
1216         final ArrayList<Integer> internetPermissionAppIds = new ArrayList<>();
1217         final ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>();
1218         final ArrayList<Integer> noPermissionAppIds = new ArrayList<>();
1219         final ArrayList<Integer> uninstalledAppIds = new ArrayList<>();
1220         for (int i = 0; i < netdPermissionsAppIds.size(); i++) {
1221             int permissions = netdPermissionsAppIds.valueAt(i);
1222             switch(permissions) {
1223                 case (TRAFFIC_PERMISSION_INTERNET | TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS):
1224                     allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
1225                     break;
1226                 case TRAFFIC_PERMISSION_INTERNET:
1227                     internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
1228                     break;
1229                 case TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS:
1230                     updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
1231                     break;
1232                 case PERMISSION_NONE:
1233                     noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i));
1234                     break;
1235                 case TRAFFIC_PERMISSION_UNINSTALLED:
1236                     uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i));
1237                     break;
1238                 default:
1239                     Log.e(TAG, "unknown permission type: " + permissions + "for uid: "
1240                             + netdPermissionsAppIds.keyAt(i));
1241             }
1242         }
1243         try {
1244             // TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids()
1245             if (allPermissionAppIds.size() != 0) {
1246                 mBpfNetMaps.setNetPermForUids(
1247                         TRAFFIC_PERMISSION_INTERNET | TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS,
1248                         toIntArray(allPermissionAppIds));
1249             }
1250             if (internetPermissionAppIds.size() != 0) {
1251                 mBpfNetMaps.setNetPermForUids(TRAFFIC_PERMISSION_INTERNET,
1252                         toIntArray(internetPermissionAppIds));
1253             }
1254             if (updateStatsPermissionAppIds.size() != 0) {
1255                 mBpfNetMaps.setNetPermForUids(TRAFFIC_PERMISSION_UPDATE_DEVICE_STATS,
1256                         toIntArray(updateStatsPermissionAppIds));
1257             }
1258             if (noPermissionAppIds.size() != 0) {
1259                 mBpfNetMaps.setNetPermForUids(PERMISSION_NONE,
1260                         toIntArray(noPermissionAppIds));
1261             }
1262             if (uninstalledAppIds.size() != 0) {
1263                 mBpfNetMaps.setNetPermForUids(TRAFFIC_PERMISSION_UNINSTALLED,
1264                         toIntArray(uninstalledAppIds));
1265             }
1266         } catch (RemoteException | ServiceSpecificException e) {
1267             Log.e(TAG, "Pass appId list of special permission failed." + e);
1268         }
1269     }
1270 
onSettingChanged()1271     private synchronized void onSettingChanged() {
1272         // Step1. Update uids allowed to use restricted networks and compute the set of uids to
1273         // update.
1274         final Set<Integer> uidsToUpdate = new ArraySet<>(mUidsAllowedOnRestrictedNetworks);
1275         updateUidsAllowedOnRestrictedNetworks(mDeps.getUidsAllowedOnRestrictedNetworks(mContext));
1276         uidsToUpdate.addAll(mUidsAllowedOnRestrictedNetworks);
1277 
1278         final SparseIntArray updatedUids = new SparseIntArray();
1279         final SparseIntArray removedUids = new SparseIntArray();
1280 
1281         // Step2. For each uid to update, find out its new permission.
1282         for (Integer uid : uidsToUpdate) {
1283             final int permission = highestUidNetworkPermission(uid);
1284 
1285             if (PERMISSION_NONE == permission) {
1286                 // Doesn't matter which permission is set here.
1287                 removedUids.put(uid, PERMISSION_NETWORK);
1288                 mUidToNetworkPerm.delete(uid);
1289                 if (hasSdkSandbox(uid)) {
1290                     int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
1291                     removedUids.put(sdkSandboxUid, PERMISSION_NETWORK);
1292                     mUidToNetworkPerm.delete(sdkSandboxUid);
1293                 }
1294             } else {
1295                 updatedUids.put(uid, permission);
1296                 mUidToNetworkPerm.put(uid, permission);
1297                 if (hasSdkSandbox(uid)) {
1298                     int sdkSandboxUid = sProcessShim.toSdkSandboxUid(uid);
1299                     updatedUids.put(sdkSandboxUid, permission);
1300                     mUidToNetworkPerm.put(sdkSandboxUid, permission);
1301                 }
1302             }
1303         }
1304 
1305         // Step3. Update or revoke permission for uids with netd.
1306         sendUidsNetworkPermission(updatedUids, true /* add */);
1307         sendUidsNetworkPermission(removedUids, false /* add */);
1308         mPermissionUpdateLogs.log("Setting change: update=" + updatedUids
1309                 + ", remove=" + removedUids);
1310     }
1311 
onExternalApplicationsAvailable(String[] pkgList)1312     private synchronized void onExternalApplicationsAvailable(String[] pkgList) {
1313         if (CollectionUtils.isEmpty(pkgList)) {
1314             Log.e(TAG, "No available external application.");
1315             return;
1316         }
1317 
1318         for (String app : pkgList) {
1319             for (UserHandle user : mUsers) {
1320                 final PackageInfo info = getPackageInfoAsUser(app, user);
1321                 if (info == null || info.applicationInfo == null) continue;
1322 
1323                 final int uid = info.applicationInfo.uid;
1324                 onPackageAdded(app, uid); // Use onPackageAdded to add package one by one.
1325             }
1326         }
1327     }
1328 
1329     /** Dump info to dumpsys */
dump(IndentingPrintWriter pw)1330     public void dump(IndentingPrintWriter pw) {
1331         pw.println("Interface filtering rules:");
1332         pw.increaseIndent();
1333         for (Map.Entry<String, Set<UidRange>> vpn : mVpnInterfaceUidRanges.entrySet()) {
1334             pw.println("Interface: " + vpn.getKey());
1335             pw.println("UIDs: " + vpn.getValue().toString());
1336             pw.println();
1337         }
1338         pw.decreaseIndent();
1339 
1340         pw.println();
1341         pw.println("Lockdown filtering rules:");
1342         pw.increaseIndent();
1343         synchronized (this) {
1344             for (final UidRange range : mVpnLockdownUidRanges.getSet()) {
1345                 pw.println("UIDs: " + range);
1346             }
1347         }
1348         pw.decreaseIndent();
1349 
1350         pw.println();
1351         pw.println("Update logs:");
1352         pw.increaseIndent();
1353         mPermissionUpdateLogs.reverseDump(pw);
1354         pw.decreaseIndent();
1355     }
1356 
log(String s)1357     private static void log(String s) {
1358         if (DBG) {
1359             Log.d(TAG, s);
1360         }
1361     }
1362 
loge(String s)1363     private static void loge(String s) {
1364         Log.e(TAG, s);
1365     }
1366 
loge(String s, Throwable e)1367     private static void loge(String s, Throwable e) {
1368         Log.e(TAG, s, e);
1369     }
1370 
1371     private class PermissionChangeListener implements PackageManager.OnPermissionsChangedListener {
1372         @Override
onPermissionsChanged(int uid)1373         public void onPermissionsChanged(int uid) {
1374             setLocalNetworkPermissions(uid, null);
1375         }
1376     }
1377 }
1378