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.PackageManager.GET_PERMISSIONS; 25 import static android.content.pm.PackageManager.MATCH_ANY_USER; 26 import static android.net.INetd.PERMISSION_INTERNET; 27 import static android.net.INetd.PERMISSION_NETWORK; 28 import static android.net.INetd.PERMISSION_NONE; 29 import static android.net.INetd.PERMISSION_SYSTEM; 30 import static android.net.INetd.PERMISSION_UNINSTALLED; 31 import static android.net.INetd.PERMISSION_UPDATE_DEVICE_STATS; 32 import static android.net.NetworkStack.PERMISSION_MAINLINE_NETWORK_STACK; 33 import static android.os.Process.INVALID_UID; 34 import static android.os.Process.SYSTEM_UID; 35 36 import static com.android.internal.util.ArrayUtils.convertToIntArray; 37 38 import android.annotation.NonNull; 39 import android.annotation.Nullable; 40 import android.app.ActivityManager; 41 import android.content.Context; 42 import android.content.pm.ApplicationInfo; 43 import android.content.pm.PackageInfo; 44 import android.content.pm.PackageManager; 45 import android.content.pm.PackageManager.NameNotFoundException; 46 import android.content.pm.PackageManagerInternal; 47 import android.content.pm.UserInfo; 48 import android.net.INetd; 49 import android.net.UidRange; 50 import android.os.Build; 51 import android.os.RemoteException; 52 import android.os.ServiceSpecificException; 53 import android.os.UserHandle; 54 import android.os.UserManager; 55 import android.system.OsConstants; 56 import android.util.ArraySet; 57 import android.util.Log; 58 import android.util.SparseArray; 59 import android.util.SparseIntArray; 60 61 import com.android.internal.annotations.GuardedBy; 62 import com.android.internal.annotations.VisibleForTesting; 63 import com.android.internal.util.IndentingPrintWriter; 64 import com.android.server.LocalServices; 65 import com.android.server.SystemConfig; 66 67 import java.util.ArrayList; 68 import java.util.Collection; 69 import java.util.HashMap; 70 import java.util.HashSet; 71 import java.util.List; 72 import java.util.Map; 73 import java.util.Map.Entry; 74 import java.util.Set; 75 76 /** 77 * A utility class to inform Netd of UID permisisons. 78 * Does a mass update at boot and then monitors for app install/remove. 79 * 80 * @hide 81 */ 82 public class PermissionMonitor implements PackageManagerInternal.PackageListObserver { 83 private static final String TAG = "PermissionMonitor"; 84 private static final boolean DBG = true; 85 protected static final Boolean SYSTEM = Boolean.TRUE; 86 protected static final Boolean NETWORK = Boolean.FALSE; 87 private static final int VERSION_Q = Build.VERSION_CODES.Q; 88 89 private final PackageManager mPackageManager; 90 private final UserManager mUserManager; 91 private final INetd mNetd; 92 private final Dependencies mDeps; 93 94 // Values are User IDs. 95 @GuardedBy("this") 96 private final Set<Integer> mUsers = new HashSet<>(); 97 98 // Keys are app uids. Values are true for SYSTEM permission and false for NETWORK permission. 99 @GuardedBy("this") 100 private final Map<Integer, Boolean> mApps = new HashMap<>(); 101 102 // Keys are active non-bypassable and fully-routed VPN's interface name, Values are uid ranges 103 // for apps under the VPN 104 @GuardedBy("this") 105 private final Map<String, Set<UidRange>> mVpnUidRanges = new HashMap<>(); 106 107 // A set of appIds for apps across all users on the device. We track appIds instead of uids 108 // directly to reduce its size and also eliminate the need to update this set when user is 109 // added/removed. 110 @GuardedBy("this") 111 private final Set<Integer> mAllApps = new HashSet<>(); 112 113 /** 114 * Dependencies of PermissionMonitor, for injection in tests. 115 */ 116 @VisibleForTesting 117 public static class Dependencies { 118 /** 119 * Get device first sdk version. 120 */ getDeviceFirstSdkInt()121 public int getDeviceFirstSdkInt() { 122 return Build.VERSION.FIRST_SDK_INT; 123 } 124 125 /** 126 * Check whether given uid has specific permission. 127 */ uidPermission(@onNull final String permission, final int uid)128 public int uidPermission(@NonNull final String permission, final int uid) { 129 return ActivityManager.checkUidPermission(permission, uid); 130 } 131 } 132 PermissionMonitor(@onNull final Context context, @NonNull final INetd netd)133 public PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd) { 134 this(context, netd, new Dependencies()); 135 } 136 137 @VisibleForTesting PermissionMonitor(@onNull final Context context, @NonNull final INetd netd, @NonNull final Dependencies deps)138 PermissionMonitor(@NonNull final Context context, @NonNull final INetd netd, 139 @NonNull final Dependencies deps) { 140 mPackageManager = context.getPackageManager(); 141 mUserManager = (UserManager) context.getSystemService(Context.USER_SERVICE); 142 mNetd = netd; 143 mDeps = deps; 144 } 145 146 // Intended to be called only once at startup, after the system is ready. Installs a broadcast 147 // receiver to monitor ongoing UID changes, so this shouldn't/needn't be called again. startMonitoring()148 public synchronized void startMonitoring() { 149 log("Monitoring"); 150 151 PackageManagerInternal pmi = LocalServices.getService(PackageManagerInternal.class); 152 if (pmi != null) { 153 pmi.getPackageList(this); 154 } else { 155 loge("failed to get the PackageManagerInternal service"); 156 } 157 List<PackageInfo> apps = mPackageManager.getInstalledPackages(GET_PERMISSIONS 158 | MATCH_ANY_USER); 159 if (apps == null) { 160 loge("No apps"); 161 return; 162 } 163 164 SparseIntArray netdPermsUids = new SparseIntArray(); 165 166 for (PackageInfo app : apps) { 167 int uid = app.applicationInfo != null ? app.applicationInfo.uid : INVALID_UID; 168 if (uid < 0) { 169 continue; 170 } 171 mAllApps.add(UserHandle.getAppId(uid)); 172 173 final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); 174 final boolean hasRestrictedPermission = 175 hasRestrictedNetworkPermission(app.applicationInfo); 176 177 if (isNetwork || hasRestrictedPermission) { 178 Boolean permission = mApps.get(uid); 179 // If multiple packages share a UID (cf: android:sharedUserId) and ask for different 180 // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). 181 if (permission == null || permission == NETWORK) { 182 mApps.put(uid, hasRestrictedPermission); 183 } 184 } 185 186 //TODO: unify the management of the permissions into one codepath. 187 final int otherNetdPerms = getNetdPermissionMask(uid); 188 netdPermsUids.put(uid, netdPermsUids.get(uid) | otherNetdPerms); 189 } 190 191 List<UserInfo> users = mUserManager.getUsers(true); // exclude dying users 192 if (users != null) { 193 for (UserInfo user : users) { 194 mUsers.add(user.id); 195 } 196 } 197 198 final SparseArray<ArraySet<String>> systemPermission = 199 SystemConfig.getInstance().getSystemPermissions(); 200 for (int i = 0; i < systemPermission.size(); i++) { 201 ArraySet<String> perms = systemPermission.valueAt(i); 202 int uid = systemPermission.keyAt(i); 203 int netdPermission = 0; 204 // Get the uids of native services that have UPDATE_DEVICE_STATS or INTERNET permission. 205 if (perms != null) { 206 netdPermission |= perms.contains(UPDATE_DEVICE_STATS) 207 ? PERMISSION_UPDATE_DEVICE_STATS : 0; 208 netdPermission |= perms.contains(INTERNET) ? PERMISSION_INTERNET : 0; 209 } 210 netdPermsUids.put(uid, netdPermsUids.get(uid) | netdPermission); 211 } 212 log("Users: " + mUsers.size() + ", Apps: " + mApps.size()); 213 update(mUsers, mApps, true); 214 sendPackagePermissionsToNetd(netdPermsUids); 215 } 216 217 @VisibleForTesting isVendorApp(@onNull ApplicationInfo appInfo)218 static boolean isVendorApp(@NonNull ApplicationInfo appInfo) { 219 return appInfo.isVendor() || appInfo.isOem() || appInfo.isProduct(); 220 } 221 222 @VisibleForTesting hasPermission(@onNull final String permission, final int uid)223 boolean hasPermission(@NonNull final String permission, final int uid) { 224 return mDeps.uidPermission(permission, uid) == PackageManager.PERMISSION_GRANTED; 225 } 226 227 @VisibleForTesting hasRestrictedNetworkPermission(@ullable final ApplicationInfo appInfo)228 boolean hasRestrictedNetworkPermission(@Nullable final ApplicationInfo appInfo) { 229 if (appInfo == null) return false; 230 // TODO : remove this check in the future(b/162295056). All apps should just 231 // request the appropriate permission for their use case since android Q. 232 if ((appInfo.targetSdkVersion < VERSION_Q && isVendorApp(appInfo)) 233 // Backward compatibility for b/114245686, on devices that launched before Q daemons 234 // and apps running as the system UID are exempted from this check. 235 || (appInfo.uid == SYSTEM_UID && mDeps.getDeviceFirstSdkInt() < VERSION_Q)) { 236 return true; 237 } 238 239 return hasPermission(PERMISSION_MAINLINE_NETWORK_STACK, appInfo.uid) 240 || hasPermission(NETWORK_STACK, appInfo.uid) 241 || hasPermission(CONNECTIVITY_USE_RESTRICTED_NETWORKS, appInfo.uid); 242 } 243 244 /** Returns whether the given uid has using background network permission. */ hasUseBackgroundNetworksPermission(final int uid)245 public synchronized boolean hasUseBackgroundNetworksPermission(final int uid) { 246 // Apps with any of the CHANGE_NETWORK_STATE, NETWORK_STACK, CONNECTIVITY_INTERNAL or 247 // CONNECTIVITY_USE_RESTRICTED_NETWORKS permission has the permission to use background 248 // networks. mApps contains the result of checks for both CHANGE_NETWORK_STATE permission 249 // and hasRestrictedNetworkPermission. If uid is in the mApps list that means uid has one of 250 // permissions at least. 251 return mApps.containsKey(uid); 252 } 253 toIntArray(Collection<Integer> list)254 private int[] toIntArray(Collection<Integer> list) { 255 int[] array = new int[list.size()]; 256 int i = 0; 257 for (Integer item : list) { 258 array[i++] = item; 259 } 260 return array; 261 } 262 update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add)263 private void update(Set<Integer> users, Map<Integer, Boolean> apps, boolean add) { 264 List<Integer> network = new ArrayList<>(); 265 List<Integer> system = new ArrayList<>(); 266 for (Entry<Integer, Boolean> app : apps.entrySet()) { 267 List<Integer> list = app.getValue() ? system : network; 268 for (int user : users) { 269 list.add(UserHandle.getUid(user, app.getKey())); 270 } 271 } 272 try { 273 if (add) { 274 mNetd.networkSetPermissionForUser(PERMISSION_NETWORK, convertToIntArray(network)); 275 mNetd.networkSetPermissionForUser(PERMISSION_SYSTEM, convertToIntArray(system)); 276 } else { 277 mNetd.networkClearPermissionForUser(convertToIntArray(network)); 278 mNetd.networkClearPermissionForUser(convertToIntArray(system)); 279 } 280 } catch (RemoteException e) { 281 loge("Exception when updating permissions: " + e); 282 } 283 } 284 285 /** 286 * Called when a user is added. See {link #ACTION_USER_ADDED}. 287 * 288 * @param user The integer userHandle of the added user. See {@link #EXTRA_USER_HANDLE}. 289 * 290 * @hide 291 */ onUserAdded(int user)292 public synchronized void onUserAdded(int user) { 293 if (user < 0) { 294 loge("Invalid user in onUserAdded: " + user); 295 return; 296 } 297 mUsers.add(user); 298 299 Set<Integer> users = new HashSet<>(); 300 users.add(user); 301 update(users, mApps, true); 302 } 303 304 /** 305 * Called when an user is removed. See {link #ACTION_USER_REMOVED}. 306 * 307 * @param user The integer userHandle of the removed user. See {@link #EXTRA_USER_HANDLE}. 308 * 309 * @hide 310 */ onUserRemoved(int user)311 public synchronized void onUserRemoved(int user) { 312 if (user < 0) { 313 loge("Invalid user in onUserRemoved: " + user); 314 return; 315 } 316 mUsers.remove(user); 317 318 Set<Integer> users = new HashSet<>(); 319 users.add(user); 320 update(users, mApps, false); 321 } 322 323 @VisibleForTesting highestPermissionForUid(Boolean currentPermission, String name, int uid)324 protected Boolean highestPermissionForUid(Boolean currentPermission, String name, int uid) { 325 if (currentPermission == SYSTEM) { 326 return currentPermission; 327 } 328 try { 329 final PackageInfo app = mPackageManager.getPackageInfo(name, GET_PERMISSIONS); 330 final boolean isNetwork = hasPermission(CHANGE_NETWORK_STATE, uid); 331 final boolean hasRestrictedPermission = 332 hasRestrictedNetworkPermission(app.applicationInfo); 333 if (isNetwork || hasRestrictedPermission) { 334 currentPermission = hasRestrictedPermission; 335 } 336 } catch (NameNotFoundException e) { 337 // App not found. 338 loge("NameNotFoundException " + name); 339 } 340 return currentPermission; 341 } 342 getPermissionForUid(final int uid)343 private int getPermissionForUid(final int uid) { 344 // Check all the packages for this UID. The UID has the permission if any of the 345 // packages in it has the permission. 346 final String[] packages = mPackageManager.getPackagesForUid(uid); 347 if (packages == null || packages.length <= 0) { 348 // The last package of this uid is removed from device. Clean the package up. 349 return PERMISSION_UNINSTALLED; 350 } 351 return getNetdPermissionMask(uid); 352 } 353 354 /** 355 * Called when a package is added. 356 * 357 * @param packageName The name of the new package. 358 * @param uid The uid of the new package. 359 * 360 * @hide 361 */ 362 @Override onPackageAdded(@onNull final String packageName, final int uid)363 public synchronized void onPackageAdded(@NonNull final String packageName, final int uid) { 364 sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); 365 366 // If multiple packages share a UID (cf: android:sharedUserId) and ask for different 367 // permissions, don't downgrade (i.e., if it's already SYSTEM, leave it as is). 368 final Boolean permission = highestPermissionForUid(mApps.get(uid), packageName, uid); 369 if (permission != mApps.get(uid)) { 370 mApps.put(uid, permission); 371 372 Map<Integer, Boolean> apps = new HashMap<>(); 373 apps.put(uid, permission); 374 update(mUsers, apps, true); 375 } 376 377 // If the newly-installed package falls within some VPN's uid range, update Netd with it. 378 // This needs to happen after the mApps update above, since removeBypassingUids() depends 379 // on mApps to check if the package can bypass VPN. 380 for (Map.Entry<String, Set<UidRange>> vpn : mVpnUidRanges.entrySet()) { 381 if (UidRange.containsUid(vpn.getValue(), uid)) { 382 final Set<Integer> changedUids = new HashSet<>(); 383 changedUids.add(uid); 384 removeBypassingUids(changedUids, /* vpnAppUid */ -1); 385 updateVpnUids(vpn.getKey(), changedUids, true); 386 } 387 } 388 mAllApps.add(UserHandle.getAppId(uid)); 389 } 390 391 /** 392 * Called when a package is removed. 393 * 394 * @param packageName The name of the removed package or null. 395 * @param uid containing the integer uid previously assigned to the package. 396 * 397 * @hide 398 */ 399 @Override onPackageRemoved(@onNull final String packageName, final int uid)400 public synchronized void onPackageRemoved(@NonNull final String packageName, final int uid) { 401 sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); 402 403 // If the newly-removed package falls within some VPN's uid range, update Netd with it. 404 // This needs to happen before the mApps update below, since removeBypassingUids() depends 405 // on mApps to check if the package can bypass VPN. 406 for (Map.Entry<String, Set<UidRange>> vpn : mVpnUidRanges.entrySet()) { 407 if (UidRange.containsUid(vpn.getValue(), uid)) { 408 final Set<Integer> changedUids = new HashSet<>(); 409 changedUids.add(uid); 410 removeBypassingUids(changedUids, /* vpnAppUid */ -1); 411 updateVpnUids(vpn.getKey(), changedUids, false); 412 } 413 } 414 // If the package has been removed from all users on the device, clear it form mAllApps. 415 if (mPackageManager.getNameForUid(uid) == null) { 416 mAllApps.remove(UserHandle.getAppId(uid)); 417 } 418 419 Map<Integer, Boolean> apps = new HashMap<>(); 420 Boolean permission = null; 421 String[] packages = mPackageManager.getPackagesForUid(uid); 422 if (packages != null && packages.length > 0) { 423 for (String name : packages) { 424 permission = highestPermissionForUid(permission, name, uid); 425 if (permission == SYSTEM) { 426 // An app with this UID still has the SYSTEM permission. 427 // Therefore, this UID must already have the SYSTEM permission. 428 // Nothing to do. 429 return; 430 } 431 } 432 } 433 if (permission == mApps.get(uid)) { 434 // The permissions of this UID have not changed. Nothing to do. 435 return; 436 } else if (permission != null) { 437 mApps.put(uid, permission); 438 apps.put(uid, permission); 439 update(mUsers, apps, true); 440 } else { 441 mApps.remove(uid); 442 apps.put(uid, NETWORK); // doesn't matter which permission we pick here 443 update(mUsers, apps, false); 444 } 445 } 446 447 /** 448 * Called when a package is changed. 449 * 450 * @param packageName The name of the changed package. 451 * @param uid The uid of the changed package. 452 * 453 * @hide 454 */ 455 @Override onPackageChanged(@onNull final String packageName, final int uid)456 public synchronized void onPackageChanged(@NonNull final String packageName, final int uid) { 457 sendPackagePermissionsForUid(uid, getPermissionForUid(uid)); 458 } 459 getNetdPermissionMask(final int uid)460 private int getNetdPermissionMask(final int uid) { 461 int permissions = PERMISSION_NONE; 462 if (hasPermission(INTERNET, uid)) { 463 permissions |= PERMISSION_INTERNET; 464 } 465 if (hasPermission(UPDATE_DEVICE_STATS, uid)) { 466 permissions |= PERMISSION_UPDATE_DEVICE_STATS; 467 } 468 return permissions; 469 } 470 getPackageInfo(String packageName)471 private PackageInfo getPackageInfo(String packageName) { 472 try { 473 PackageInfo app = mPackageManager.getPackageInfo(packageName, GET_PERMISSIONS 474 | MATCH_ANY_USER); 475 return app; 476 } catch (NameNotFoundException e) { 477 return null; 478 } 479 } 480 481 /** 482 * Called when a new set of UID ranges are added to an active VPN network 483 * 484 * @param iface The active VPN network's interface name 485 * @param rangesToAdd The new UID ranges to be added to the network 486 * @param vpnAppUid The uid of the VPN app 487 */ onVpnUidRangesAdded(@onNull String iface, Set<UidRange> rangesToAdd, int vpnAppUid)488 public synchronized void onVpnUidRangesAdded(@NonNull String iface, Set<UidRange> rangesToAdd, 489 int vpnAppUid) { 490 // Calculate the list of new app uids under the VPN due to the new UID ranges and update 491 // Netd about them. Because mAllApps only contains appIds instead of uids, the result might 492 // be an overestimation if an app is not installed on the user on which the VPN is running, 493 // but that's safe. 494 final Set<Integer> changedUids = intersectUids(rangesToAdd, mAllApps); 495 removeBypassingUids(changedUids, vpnAppUid); 496 updateVpnUids(iface, changedUids, true); 497 if (mVpnUidRanges.containsKey(iface)) { 498 mVpnUidRanges.get(iface).addAll(rangesToAdd); 499 } else { 500 mVpnUidRanges.put(iface, new HashSet<UidRange>(rangesToAdd)); 501 } 502 } 503 504 /** 505 * Called when a set of UID ranges are removed from an active VPN network 506 * 507 * @param iface The VPN network's interface name 508 * @param rangesToRemove Existing UID ranges to be removed from the VPN network 509 * @param vpnAppUid The uid of the VPN app 510 */ onVpnUidRangesRemoved(@onNull String iface, Set<UidRange> rangesToRemove, int vpnAppUid)511 public synchronized void onVpnUidRangesRemoved(@NonNull String iface, 512 Set<UidRange> rangesToRemove, int vpnAppUid) { 513 // Calculate the list of app uids that are no longer under the VPN due to the removed UID 514 // ranges and update Netd about them. 515 final Set<Integer> changedUids = intersectUids(rangesToRemove, mAllApps); 516 removeBypassingUids(changedUids, vpnAppUid); 517 updateVpnUids(iface, changedUids, false); 518 Set<UidRange> existingRanges = mVpnUidRanges.getOrDefault(iface, null); 519 if (existingRanges == null) { 520 loge("Attempt to remove unknown vpn uid Range iface = " + iface); 521 return; 522 } 523 existingRanges.removeAll(rangesToRemove); 524 if (existingRanges.size() == 0) { 525 mVpnUidRanges.remove(iface); 526 } 527 } 528 529 /** 530 * Compute the intersection of a set of UidRanges and appIds. Returns a set of uids 531 * that satisfies: 532 * 1. falls into one of the UidRange 533 * 2. matches one of the appIds 534 */ intersectUids(Set<UidRange> ranges, Set<Integer> appIds)535 private Set<Integer> intersectUids(Set<UidRange> ranges, Set<Integer> appIds) { 536 Set<Integer> result = new HashSet<>(); 537 for (UidRange range : ranges) { 538 for (int userId = range.getStartUser(); userId <= range.getEndUser(); userId++) { 539 for (int appId : appIds) { 540 final int uid = UserHandle.getUid(userId, appId); 541 if (range.contains(uid)) { 542 result.add(uid); 543 } 544 } 545 } 546 } 547 return result; 548 } 549 550 /** 551 * Remove all apps which can elect to bypass the VPN from the list of uids 552 * 553 * An app can elect to bypass the VPN if it hold SYSTEM permission, or if its the active VPN 554 * app itself. 555 * 556 * @param uids The list of uids to operate on 557 * @param vpnAppUid The uid of the VPN app 558 */ removeBypassingUids(Set<Integer> uids, int vpnAppUid)559 private void removeBypassingUids(Set<Integer> uids, int vpnAppUid) { 560 uids.remove(vpnAppUid); 561 uids.removeIf(uid -> mApps.getOrDefault(uid, NETWORK) == SYSTEM); 562 } 563 564 /** 565 * Update netd about the list of uids that are under an active VPN connection which they cannot 566 * bypass. 567 * 568 * This is to instruct netd to set up appropriate filtering rules for these uids, such that they 569 * can only receive ingress packets from the VPN's tunnel interface (and loopback). 570 * 571 * @param iface the interface name of the active VPN connection 572 * @param add {@code true} if the uids are to be added to the interface, {@code false} if they 573 * are to be removed from the interface. 574 */ updateVpnUids(String iface, Set<Integer> uids, boolean add)575 private void updateVpnUids(String iface, Set<Integer> uids, boolean add) { 576 if (uids.size() == 0) { 577 return; 578 } 579 try { 580 if (add) { 581 mNetd.firewallAddUidInterfaceRules(iface, toIntArray(uids)); 582 } else { 583 mNetd.firewallRemoveUidInterfaceRules(toIntArray(uids)); 584 } 585 } catch (ServiceSpecificException e) { 586 // Silently ignore exception when device does not support eBPF, otherwise just log 587 // the exception and do not crash 588 if (e.errorCode != OsConstants.EOPNOTSUPP) { 589 loge("Exception when updating permissions: ", e); 590 } 591 } catch (RemoteException e) { 592 loge("Exception when updating permissions: ", e); 593 } 594 } 595 596 /** 597 * Called by PackageListObserver when a package is installed/uninstalled. Send the updated 598 * permission information to netd. 599 * 600 * @param uid the app uid of the package installed 601 * @param permissions the permissions the app requested and netd cares about. 602 * 603 * @hide 604 */ 605 @VisibleForTesting sendPackagePermissionsForUid(int uid, int permissions)606 void sendPackagePermissionsForUid(int uid, int permissions) { 607 SparseIntArray netdPermissionsAppIds = new SparseIntArray(); 608 netdPermissionsAppIds.put(uid, permissions); 609 sendPackagePermissionsToNetd(netdPermissionsAppIds); 610 } 611 612 /** 613 * Called by packageManagerService to send IPC to netd. Grant or revoke the INTERNET 614 * and/or UPDATE_DEVICE_STATS permission of the uids in array. 615 * 616 * @param netdPermissionsAppIds integer pairs of uids and the permission granted to it. If the 617 * permission is 0, revoke all permissions of that uid. 618 * 619 * @hide 620 */ 621 @VisibleForTesting sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds)622 void sendPackagePermissionsToNetd(SparseIntArray netdPermissionsAppIds) { 623 if (mNetd == null) { 624 Log.e(TAG, "Failed to get the netd service"); 625 return; 626 } 627 ArrayList<Integer> allPermissionAppIds = new ArrayList<>(); 628 ArrayList<Integer> internetPermissionAppIds = new ArrayList<>(); 629 ArrayList<Integer> updateStatsPermissionAppIds = new ArrayList<>(); 630 ArrayList<Integer> noPermissionAppIds = new ArrayList<>(); 631 ArrayList<Integer> uninstalledAppIds = new ArrayList<>(); 632 for (int i = 0; i < netdPermissionsAppIds.size(); i++) { 633 int permissions = netdPermissionsAppIds.valueAt(i); 634 switch(permissions) { 635 case (PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS): 636 allPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); 637 break; 638 case PERMISSION_INTERNET: 639 internetPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); 640 break; 641 case PERMISSION_UPDATE_DEVICE_STATS: 642 updateStatsPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); 643 break; 644 case PERMISSION_NONE: 645 noPermissionAppIds.add(netdPermissionsAppIds.keyAt(i)); 646 break; 647 case PERMISSION_UNINSTALLED: 648 uninstalledAppIds.add(netdPermissionsAppIds.keyAt(i)); 649 default: 650 Log.e(TAG, "unknown permission type: " + permissions + "for uid: " 651 + netdPermissionsAppIds.keyAt(i)); 652 } 653 } 654 try { 655 // TODO: add a lock inside netd to protect IPC trafficSetNetPermForUids() 656 if (allPermissionAppIds.size() != 0) { 657 mNetd.trafficSetNetPermForUids( 658 PERMISSION_INTERNET | PERMISSION_UPDATE_DEVICE_STATS, 659 convertToIntArray(allPermissionAppIds)); 660 } 661 if (internetPermissionAppIds.size() != 0) { 662 mNetd.trafficSetNetPermForUids(PERMISSION_INTERNET, 663 convertToIntArray(internetPermissionAppIds)); 664 } 665 if (updateStatsPermissionAppIds.size() != 0) { 666 mNetd.trafficSetNetPermForUids(PERMISSION_UPDATE_DEVICE_STATS, 667 convertToIntArray(updateStatsPermissionAppIds)); 668 } 669 if (noPermissionAppIds.size() != 0) { 670 mNetd.trafficSetNetPermForUids(PERMISSION_NONE, 671 convertToIntArray(noPermissionAppIds)); 672 } 673 if (uninstalledAppIds.size() != 0) { 674 mNetd.trafficSetNetPermForUids(PERMISSION_UNINSTALLED, 675 convertToIntArray(uninstalledAppIds)); 676 } 677 } catch (RemoteException e) { 678 Log.e(TAG, "Pass appId list of special permission failed." + e); 679 } 680 } 681 682 /** Should only be used by unit tests */ 683 @VisibleForTesting getVpnUidRanges(String iface)684 public Set<UidRange> getVpnUidRanges(String iface) { 685 return mVpnUidRanges.get(iface); 686 } 687 688 /** Dump info to dumpsys */ dump(IndentingPrintWriter pw)689 public void dump(IndentingPrintWriter pw) { 690 pw.println("Interface filtering rules:"); 691 pw.increaseIndent(); 692 for (Map.Entry<String, Set<UidRange>> vpn : mVpnUidRanges.entrySet()) { 693 pw.println("Interface: " + vpn.getKey()); 694 pw.println("UIDs: " + vpn.getValue().toString()); 695 pw.println(); 696 } 697 pw.decreaseIndent(); 698 } 699 log(String s)700 private static void log(String s) { 701 if (DBG) { 702 Log.d(TAG, s); 703 } 704 } 705 loge(String s)706 private static void loge(String s) { 707 Log.e(TAG, s); 708 } 709 loge(String s, Throwable e)710 private static void loge(String s, Throwable e) { 711 Log.e(TAG, s, e); 712 } 713 } 714