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