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