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