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