1 /* 2 * Copyright (C) 2022 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.permission.access.permission 18 19 import android.Manifest 20 import android.app.ActivityManager 21 import android.app.AppOpsManager 22 import android.compat.annotation.ChangeId 23 import android.compat.annotation.EnabledAfter 24 import android.content.Context 25 import android.content.pm.PackageInstaller 26 import android.content.pm.PackageManager 27 import android.content.pm.PackageManagerInternal 28 import android.content.pm.PermissionGroupInfo 29 import android.content.pm.PermissionInfo 30 import android.content.pm.permission.SplitPermissionInfoParcelable 31 import android.metrics.LogMaker 32 import android.os.Binder 33 import android.os.Build 34 import android.os.Handler 35 import android.os.HandlerThread 36 import android.os.Looper 37 import android.os.Message 38 import android.os.Process 39 import android.os.RemoteCallbackList 40 import android.os.RemoteException 41 import android.os.ServiceManager 42 import android.os.UserHandle 43 import android.os.UserManager 44 import android.permission.IOnPermissionsChangeListener 45 import android.permission.PermissionControllerManager 46 import android.permission.PermissionManager 47 import android.provider.Settings 48 import android.util.DebugUtils 49 import android.util.IntArray as GrowingIntArray 50 import android.util.Log 51 import com.android.internal.compat.IPlatformCompat 52 import com.android.internal.logging.MetricsLogger 53 import com.android.internal.logging.nano.MetricsProto 54 import com.android.internal.util.DumpUtils 55 import com.android.internal.util.Preconditions 56 import com.android.server.FgThread 57 import com.android.server.LocalManagerRegistry 58 import com.android.server.LocalServices 59 import com.android.server.PermissionThread 60 import com.android.server.ServiceThread 61 import com.android.server.SystemConfig 62 import com.android.server.permission.access.AccessCheckingService 63 import com.android.server.permission.access.AppOpUri 64 import com.android.server.permission.access.GetStateScope 65 import com.android.server.permission.access.MutateStateScope 66 import com.android.server.permission.access.PermissionUri 67 import com.android.server.permission.access.UidUri 68 import com.android.server.permission.access.appop.UidAppOpPolicy 69 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports 70 import com.android.server.permission.access.util.andInv 71 import com.android.server.permission.access.util.hasAnyBit 72 import com.android.server.permission.access.util.hasBits 73 import com.android.server.permission.access.util.withClearedCallingIdentity 74 import com.android.server.pm.KnownPackages 75 import com.android.server.pm.PackageInstallerService 76 import com.android.server.pm.PackageManagerLocal 77 import com.android.server.pm.UserManagerInternal 78 import com.android.server.pm.UserManagerService 79 import com.android.server.pm.parsing.pkg.AndroidPackageUtils 80 import com.android.server.pm.permission.LegacyPermission 81 import com.android.server.pm.permission.Permission as LegacyPermission2 82 import com.android.server.pm.permission.LegacyPermissionSettings 83 import com.android.server.pm.permission.LegacyPermissionState 84 import com.android.server.pm.permission.PermissionManagerServiceInterface 85 import com.android.server.pm.permission.PermissionManagerServiceInternal 86 import com.android.server.pm.pkg.AndroidPackage 87 import com.android.server.pm.pkg.PackageState 88 import com.android.server.policy.SoftRestrictedPermissionPolicy 89 import libcore.util.EmptyArray 90 import java.io.FileDescriptor 91 import java.io.PrintWriter 92 import java.util.concurrent.CompletableFuture 93 import java.util.concurrent.ExecutionException 94 import java.util.concurrent.TimeUnit 95 import java.util.concurrent.TimeoutException 96 97 /** 98 * Modern implementation of [PermissionManagerServiceInterface]. 99 */ 100 class PermissionService( 101 private val service: AccessCheckingService 102 ) : PermissionManagerServiceInterface { 103 private val policy = 104 service.getSchemePolicy(UidUri.SCHEME, PermissionUri.SCHEME) as UidPermissionPolicy 105 106 private val context = service.context 107 private lateinit var metricsLogger: MetricsLogger 108 private lateinit var packageManagerInternal: PackageManagerInternal 109 private lateinit var packageManagerLocal: PackageManagerLocal 110 private lateinit var platformCompat: IPlatformCompat 111 private lateinit var systemConfig: SystemConfig 112 private lateinit var userManagerInternal: UserManagerInternal 113 private lateinit var userManagerService: UserManagerService 114 115 private lateinit var handlerThread: HandlerThread 116 private lateinit var handler: Handler 117 private lateinit var onPermissionsChangeListeners: OnPermissionsChangeListeners 118 private lateinit var onPermissionFlagsChangedListener: OnPermissionFlagsChangedListener 119 120 private val mountedStorageVolumes = IndexedSet<String?>() 121 122 private lateinit var permissionControllerManager: PermissionControllerManager 123 124 /** 125 * A permission backup might contain apps that are not installed. In this case we delay the 126 * restoration until the app is installed. 127 * 128 * This array (`userId -> noDelayedBackupLeft`) is `true` for all the users where 129 * there is **no more** delayed backup left. 130 */ 131 private val isDelayedPermissionBackupFinished = IntBooleanMap() 132 133 fun initialize() { 134 metricsLogger = MetricsLogger() 135 packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java) 136 packageManagerLocal = 137 LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java) 138 platformCompat = IPlatformCompat.Stub.asInterface( 139 ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE) 140 ) 141 systemConfig = SystemConfig.getInstance() 142 userManagerInternal = LocalServices.getService(UserManagerInternal::class.java) 143 userManagerService = UserManagerService.getInstance() 144 145 handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true) 146 .apply { start() } 147 handler = Handler(handlerThread.looper) 148 onPermissionsChangeListeners = OnPermissionsChangeListeners(FgThread.get().looper) 149 onPermissionFlagsChangedListener = OnPermissionFlagsChangedListener() 150 policy.addOnPermissionFlagsChangedListener(onPermissionFlagsChangedListener) 151 } 152 153 override fun getAllPermissionGroups(flags: Int): List<PermissionGroupInfo> { 154 packageManagerLocal.withUnfilteredSnapshot().use { snapshot -> 155 val callingUid = Binder.getCallingUid() 156 if (snapshot.isUidInstantApp(callingUid)) { 157 return emptyList() 158 } 159 160 val permissionGroups = service.getState { 161 with(policy) { getPermissionGroups() } 162 } 163 164 return permissionGroups.mapNotNullIndexed { _, _, permissionGroup -> 165 if (snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)) { 166 permissionGroup.generatePermissionGroupInfo(flags) 167 } else { 168 null 169 } 170 } 171 } 172 } 173 174 override fun getPermissionGroupInfo( 175 permissionGroupName: String, 176 flags: Int 177 ): PermissionGroupInfo? { 178 val permissionGroup: PermissionGroupInfo 179 packageManagerLocal.withUnfilteredSnapshot().use { snapshot -> 180 val callingUid = Binder.getCallingUid() 181 if (snapshot.isUidInstantApp(callingUid)) { 182 return null 183 } 184 185 permissionGroup = service.getState { 186 with(policy) { getPermissionGroups()[permissionGroupName] } 187 } ?: return null 188 189 if (!snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)) { 190 return null 191 } 192 } 193 194 return permissionGroup.generatePermissionGroupInfo(flags) 195 } 196 197 /** 198 * Generate a new [PermissionGroupInfo] from [PermissionGroupInfo] and adjust it accordingly. 199 */ 200 private fun PermissionGroupInfo.generatePermissionGroupInfo(flags: Int): PermissionGroupInfo = 201 @Suppress("DEPRECATION") 202 PermissionGroupInfo(this).apply { 203 if (!flags.hasBits(PackageManager.GET_META_DATA)) { 204 metaData = null 205 } 206 } 207 208 override fun getPermissionInfo( 209 permissionName: String, 210 flags: Int, 211 opPackageName: String 212 ): PermissionInfo? { 213 val permission: Permission 214 val targetSdkVersion: Int 215 packageManagerLocal.withUnfilteredSnapshot().use { snapshot -> 216 val callingUid = Binder.getCallingUid() 217 if (snapshot.isUidInstantApp(callingUid)) { 218 return null 219 } 220 221 permission = service.getState { 222 with(policy) { getPermissions()[permissionName] } 223 } ?: return null 224 225 if (!snapshot.isPackageVisibleToUid(permission.packageName, callingUid)) { 226 return null 227 } 228 229 val opPackage = snapshot.getPackageState(opPackageName)?.androidPackage 230 targetSdkVersion = when { 231 // System sees all flags. 232 isRootOrSystemOrShell(callingUid) -> Build.VERSION_CODES.CUR_DEVELOPMENT 233 opPackage != null -> opPackage.targetSdkVersion 234 else -> Build.VERSION_CODES.CUR_DEVELOPMENT 235 } 236 } 237 238 return permission.generatePermissionInfo(flags, targetSdkVersion) 239 } 240 241 /** 242 * Generate a new [PermissionInfo] from [Permission] and adjust it accordingly. 243 */ 244 private fun Permission.generatePermissionInfo( 245 flags: Int, 246 targetSdkVersion: Int = Build.VERSION_CODES.CUR_DEVELOPMENT 247 ): PermissionInfo = 248 @Suppress("DEPRECATION") 249 PermissionInfo(permissionInfo).apply { 250 // All Permission objects are registered so the PermissionInfo generated for it should 251 // also have FLAG_INSTALLED. 252 this.flags = this.flags or PermissionInfo.FLAG_INSTALLED 253 if (!flags.hasBits(PackageManager.GET_META_DATA)) { 254 metaData = null 255 } 256 if (targetSdkVersion < Build.VERSION_CODES.O) { 257 val protection = protection 258 // Signature permission's protection flags are always reported. 259 if (protection != PermissionInfo.PROTECTION_SIGNATURE) { 260 protectionLevel = protection 261 } 262 } 263 } 264 265 override fun queryPermissionsByGroup( 266 permissionGroupName: String?, 267 flags: Int 268 ): List<PermissionInfo>? { 269 packageManagerLocal.withUnfilteredSnapshot().use { snapshot -> 270 val callingUid = Binder.getCallingUid() 271 if (snapshot.isUidInstantApp(callingUid)) { 272 return null 273 } 274 275 val permissions: IndexedMap<String, Permission> 276 service.getState { 277 if (permissionGroupName != null) { 278 val permissionGroup = 279 with(policy) { getPermissionGroups()[permissionGroupName] } ?: return null 280 281 if (!snapshot.isPackageVisibleToUid(permissionGroup.packageName, callingUid)) { 282 return null 283 } 284 } 285 286 permissions = with(policy) { getPermissions() } 287 } 288 289 return permissions.mapNotNullIndexed { _, _, permission -> 290 if (permission.groupName == permissionGroupName && 291 snapshot.isPackageVisibleToUid(permission.packageName, callingUid) 292 ) { 293 permission.generatePermissionInfo(flags) 294 } else { 295 null 296 } 297 } 298 } 299 } 300 301 override fun getAllPermissionsWithProtection(protection: Int): List<PermissionInfo> = 302 getPermissionsWithProtectionOrProtectionFlags { permission -> 303 permission.protection == protection 304 } 305 306 override fun getAllPermissionsWithProtectionFlags(protectionFlags: Int): List<PermissionInfo> = 307 getPermissionsWithProtectionOrProtectionFlags { permission -> 308 permission.protectionFlags.hasBits(protectionFlags) 309 } 310 311 private inline fun getPermissionsWithProtectionOrProtectionFlags( 312 predicate: (Permission) -> Boolean 313 ): List<PermissionInfo> { 314 service.getState { 315 with(policy) { 316 return getPermissions().mapNotNullIndexed { _, _, permission -> 317 if (predicate(permission)) { 318 permission.generatePermissionInfo(0) 319 } else { 320 null 321 } 322 } 323 } 324 } 325 } 326 327 override fun getPermissionGids(permissionName: String, userId: Int): IntArray { 328 val permission = service.getState { 329 with(policy) { getPermissions()[permissionName] } 330 } ?: return EmptyArray.INT 331 return permission.getGidsForUser(userId) 332 } 333 334 override fun getInstalledPermissions(packageName: String): Set<String> { 335 requireNotNull(packageName) { "packageName cannot be null" } 336 337 val permissions = service.getState { 338 with(policy) { getPermissions() } 339 } 340 return permissions.mapNotNullIndexedToSet { _, _, permission -> 341 if (permission.packageName == packageName) { 342 permission.name 343 } else { 344 null 345 } 346 } 347 } 348 349 override fun addPermission(permissionInfo: PermissionInfo, async: Boolean): Boolean { 350 val permissionName = permissionInfo.name 351 requireNotNull(permissionName) { "permissionName cannot be null" } 352 val callingUid = Binder.getCallingUid() 353 if (packageManagerLocal.withUnfilteredSnapshot().use { it.isUidInstantApp(callingUid) }) { 354 throw SecurityException("Instant apps cannot add permissions") 355 } 356 if (permissionInfo.labelRes == 0 && permissionInfo.nonLocalizedLabel == null) { 357 throw SecurityException("Label must be specified in permission") 358 } 359 val oldPermission: Permission? 360 361 service.mutateState { 362 val permissionTree = getAndEnforcePermissionTree(permissionName) 363 enforcePermissionTreeSize(permissionInfo, permissionTree) 364 365 oldPermission = with(policy) { getPermissions()[permissionName] } 366 if (oldPermission != null && !oldPermission.isDynamic) { 367 throw SecurityException( 368 "Not allowed to modify non-dynamic permission $permissionName" 369 ) 370 } 371 372 permissionInfo.packageName = permissionTree.permissionInfo.packageName 373 @Suppress("DEPRECATION") 374 permissionInfo.protectionLevel = 375 PermissionInfo.fixProtectionLevel(permissionInfo.protectionLevel) 376 377 val newPermission = Permission( 378 permissionInfo, true, Permission.TYPE_DYNAMIC, permissionTree.appId 379 ) 380 381 with(policy) { addPermission(newPermission, !async) } 382 } 383 384 return oldPermission == null 385 } 386 387 override fun removePermission(permissionName: String) { 388 val callingUid = Binder.getCallingUid() 389 if (packageManagerLocal.withUnfilteredSnapshot().use { it.isUidInstantApp(callingUid) }) { 390 throw SecurityException("Instant applications don't have access to this method") 391 } 392 service.mutateState { 393 getAndEnforcePermissionTree(permissionName) 394 val permission = with(policy) { getPermissions()[permissionName] } ?: return@mutateState 395 396 if (!permission.isDynamic) { 397 // TODO(b/67371907): switch to logging if it fails 398 throw SecurityException( 399 "Not allowed to modify non-dynamic permission $permissionName" 400 ) 401 } 402 403 with(policy) { removePermission(permission) } 404 } 405 } 406 private fun GetStateScope.getAndEnforcePermissionTree(permissionName: String): Permission { 407 val callingUid = Binder.getCallingUid() 408 val permissionTree = with(policy) { findPermissionTree(permissionName) } 409 if (permissionTree != null && permissionTree.appId == UserHandle.getAppId(callingUid)) { 410 return permissionTree 411 } 412 413 throw SecurityException( 414 "Calling UID $callingUid is not allowed to add to or remove from the permission tree" 415 ) 416 } 417 418 private fun GetStateScope.enforcePermissionTreeSize( 419 permissionInfo: PermissionInfo, 420 permissionTree: Permission 421 ) { 422 // We calculate the max size of permissions defined by this uid and throw 423 // if that plus the size of 'info' would exceed our stated maximum. 424 if (permissionTree.appId != Process.SYSTEM_UID) { 425 val permissionTreeFootprint = calculatePermissionTreeFootprint(permissionTree) 426 if (permissionTreeFootprint + permissionInfo.calculateFootprint() > 427 MAX_PERMISSION_TREE_FOOTPRINT 428 ) { 429 throw SecurityException("Permission tree size cap exceeded") 430 } 431 } 432 } 433 434 private fun GetStateScope.calculatePermissionTreeFootprint(permissionTree: Permission): Int { 435 var size = 0 436 with(policy) { 437 getPermissions().forEachValueIndexed { _, permission -> 438 if (permissionTree.appId == permission.appId) { 439 size += permission.footprint 440 } 441 } 442 } 443 return size 444 } 445 446 override fun checkUidPermission(uid: Int, permissionName: String): Int { 447 val userId = UserHandle.getUserId(uid) 448 if (!userManagerInternal.exists(userId)) { 449 return PackageManager.PERMISSION_DENIED 450 } 451 452 // PackageManagerInternal.getPackage(int) already checks package visibility and enforces 453 // that instant apps can't see shared UIDs. Note that on the contrary, 454 // Note that PackageManagerInternal.getPackage(String) doesn't perform any checks. 455 val androidPackage = packageManagerInternal.getPackage(uid) 456 if (androidPackage != null) { 457 // Note that PackageManagerInternal.getPackageStateInternal() is not filtered. 458 val packageState = 459 packageManagerInternal.getPackageStateInternal(androidPackage.packageName) 460 if (packageState == null) { 461 Log.e( 462 LOG_TAG, "checkUidPermission: PackageState not found for AndroidPackage" + 463 " $androidPackage" 464 ) 465 return PackageManager.PERMISSION_DENIED 466 } 467 val isPermissionGranted = service.getState { 468 isPermissionGranted(packageState, userId, permissionName) 469 } 470 return if (isPermissionGranted) { 471 PackageManager.PERMISSION_GRANTED 472 } else { 473 PackageManager.PERMISSION_DENIED 474 } 475 } 476 477 return if (isSystemUidPermissionGranted(uid, permissionName)) { 478 PackageManager.PERMISSION_GRANTED 479 } else { 480 PackageManager.PERMISSION_DENIED 481 } 482 } 483 484 /** 485 * Internal implementation that should only be called by [checkUidPermission]. 486 */ 487 private fun isSystemUidPermissionGranted(uid: Int, permissionName: String): Boolean { 488 val uidPermissions = systemConfig.systemPermissions[uid] ?: return false 489 if (permissionName in uidPermissions) { 490 return true 491 } 492 493 val fullerPermissionName = FULLER_PERMISSIONS[permissionName] 494 if (fullerPermissionName != null && fullerPermissionName in uidPermissions) { 495 return true 496 } 497 498 return false 499 } 500 501 override fun checkPermission(packageName: String, permissionName: String, userId: Int): Int { 502 if (!userManagerInternal.exists(userId)) { 503 return PackageManager.PERMISSION_DENIED 504 } 505 506 val packageState = packageManagerLocal.withFilteredSnapshot(Binder.getCallingUid(), userId) 507 .use { it.getPackageState(packageName) } ?: return PackageManager.PERMISSION_DENIED 508 509 val isPermissionGranted = service.getState { 510 isPermissionGranted(packageState, userId, permissionName) 511 } 512 return if (isPermissionGranted) { 513 PackageManager.PERMISSION_GRANTED 514 } else { 515 PackageManager.PERMISSION_DENIED 516 } 517 } 518 519 /** 520 * Check whether a permission is granted, without any validation on caller. 521 * 522 * This method should always be called for checking whether a permission is granted, instead of 523 * reading permission flags directly from the policy. 524 */ 525 private fun GetStateScope.isPermissionGranted( 526 packageState: PackageState, 527 userId: Int, 528 permissionName: String 529 ): Boolean { 530 val appId = packageState.appId 531 // Note that instant apps can't have shared UIDs, so we only need to check the current 532 // package state. 533 val isInstantApp = packageState.getUserStateOrDefault(userId).isInstantApp 534 if (isSinglePermissionGranted(appId, userId, isInstantApp, permissionName)) { 535 return true 536 } 537 538 val fullerPermissionName = FULLER_PERMISSIONS[permissionName] 539 if (fullerPermissionName != null && 540 isSinglePermissionGranted(appId, userId, isInstantApp, fullerPermissionName)) { 541 return true 542 } 543 544 return false 545 } 546 547 /** 548 * Internal implementation that should only be called by [isPermissionGranted]. 549 */ 550 private fun GetStateScope.isSinglePermissionGranted( 551 appId: Int, 552 userId: Int, 553 isInstantApp: Boolean, 554 permissionName: String 555 ): Boolean { 556 val flags = with(policy) { getPermissionFlags(appId, userId, permissionName) } 557 if (!PermissionFlags.isPermissionGranted(flags)) { 558 return false 559 } 560 561 if (isInstantApp) { 562 val permission = with(policy) { getPermissions()[permissionName] } ?: return false 563 if (!permission.isInstant) { 564 return false 565 } 566 } 567 568 return true 569 } 570 571 override fun getGrantedPermissions(packageName: String, userId: Int): Set<String> { 572 requireNotNull(packageName) { "packageName cannot be null" } 573 Preconditions.checkArgumentNonnegative(userId, "userId") 574 575 val packageState = packageManagerLocal.withUnfilteredSnapshot() 576 .use { it.getPackageState(packageName) } 577 if (packageState == null) { 578 Log.w(LOG_TAG, "getGrantedPermissions: Unknown package $packageName") 579 return emptySet() 580 } 581 582 service.getState { 583 val permissionFlags = with(policy) { getUidPermissionFlags(packageState.appId, userId) } 584 ?: return emptySet() 585 586 return permissionFlags.mapNotNullIndexedToSet { _, permissionName, _ -> 587 if (isPermissionGranted(packageState, userId, permissionName)) { 588 permissionName 589 } else { 590 null 591 } 592 } 593 } 594 } 595 596 override fun getGidsForUid(uid: Int): IntArray { 597 val appId = UserHandle.getAppId(uid) 598 val userId = UserHandle.getUserId(uid) 599 val globalGids = systemConfig.globalGids 600 service.getState { 601 // Different from the old implementation, which returns an empty array when the 602 // permission state is not found, now we always return at least global GIDs. This is 603 // more consistent with the pre-S-refactor behavior. This is also because we are now 604 // actively trimming the per-UID objects when empty. 605 val permissionFlags = with(policy) { getUidPermissionFlags(appId, userId) } 606 ?: return globalGids.copyOf() 607 608 val gids = GrowingIntArray.wrap(globalGids) 609 permissionFlags.forEachIndexed { _, permissionName, flags -> 610 if (!PermissionFlags.isPermissionGranted(flags)) { 611 return@forEachIndexed 612 } 613 614 val permission = with(policy) { getPermissions()[permissionName] } 615 ?: return@forEachIndexed 616 val permissionGids = permission.getGidsForUser(userId) 617 if (permissionGids.isEmpty()) { 618 return@forEachIndexed 619 } 620 gids.addAll(permissionGids) 621 } 622 return gids.toArray() 623 } 624 } 625 626 override fun grantRuntimePermission(packageName: String, permissionName: String, userId: Int) { 627 setRuntimePermissionGranted(packageName, userId, permissionName, isGranted = true) 628 } 629 630 override fun revokeRuntimePermission( 631 packageName: String, 632 permissionName: String, 633 userId: Int, 634 reason: String? 635 ) { 636 setRuntimePermissionGranted( 637 packageName, userId, permissionName, isGranted = false, revokeReason = reason 638 ) 639 } 640 641 override fun revokePostNotificationPermissionWithoutKillForTest( 642 packageName: String, 643 userId: Int 644 ) { 645 setRuntimePermissionGranted( 646 packageName, userId, Manifest.permission.POST_NOTIFICATIONS, isGranted = false, 647 skipKillUid = true 648 ) 649 } 650 651 /** 652 * Shared internal implementation that should only be called by [grantRuntimePermission], 653 * [revokeRuntimePermission] and [revokePostNotificationPermissionWithoutKillForTest]. 654 */ 655 private fun setRuntimePermissionGranted( 656 packageName: String, 657 userId: Int, 658 permissionName: String, 659 isGranted: Boolean, 660 skipKillUid: Boolean = false, 661 revokeReason: String? = null 662 ) { 663 val methodName = if (isGranted) "grantRuntimePermission" else "revokeRuntimePermission" 664 val callingUid = Binder.getCallingUid() 665 val isDebugEnabled = if (isGranted) { 666 PermissionManager.DEBUG_TRACE_GRANTS 667 } else { 668 PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES 669 } 670 if (isDebugEnabled && 671 PermissionManager.shouldTraceGrant(packageName, permissionName, userId)) { 672 val callingUidName = packageManagerInternal.getNameForUid(callingUid) 673 Log.i( 674 LOG_TAG, "$methodName(packageName = $packageName," + 675 " permissionName = $permissionName" + 676 (if (isGranted) "" else "skipKillUid = $skipKillUid, reason = $revokeReason") + 677 ", userId = $userId," + " callingUid = $callingUidName ($callingUid))", 678 RuntimeException() 679 ) 680 } 681 682 if (!userManagerInternal.exists(userId)) { 683 Log.w(LOG_TAG, "$methodName: Unknown user $userId") 684 return 685 } 686 687 enforceCallingOrSelfCrossUserPermission( 688 userId, enforceFullPermission = true, enforceShellRestriction = true, methodName 689 ) 690 val enforcedPermissionName = if (isGranted) { 691 Manifest.permission.GRANT_RUNTIME_PERMISSIONS 692 } else { 693 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS 694 } 695 context.enforceCallingOrSelfPermission(enforcedPermissionName, methodName) 696 697 val packageState: PackageState? 698 val permissionControllerPackageName = packageManagerInternal.getKnownPackageNames( 699 KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM 700 ).first() 701 val permissionControllerPackageState: PackageState? 702 packageManagerLocal.withUnfilteredSnapshot().use { snapshot -> 703 packageState = snapshot.filtered(callingUid, userId) 704 .use { it.getPackageState(packageName) } 705 permissionControllerPackageState = 706 snapshot.getPackageState(permissionControllerPackageName) 707 } 708 val androidPackage = packageState?.androidPackage 709 // Different from the old implementation, which returns when package doesn't exist but 710 // throws when package exists but isn't visible, we now return in both cases to avoid 711 // leaking the package existence. 712 if (androidPackage == null) { 713 Log.w(LOG_TAG, "$methodName: Unknown package $packageName") 714 return 715 } 716 717 val canManageRolePermission = isRootOrSystem(callingUid) || 718 UserHandle.getAppId(callingUid) == permissionControllerPackageState!!.appId 719 val overridePolicyFixed = context.checkCallingOrSelfPermission( 720 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY 721 ) == PackageManager.PERMISSION_GRANTED 722 723 service.mutateState { 724 with(onPermissionFlagsChangedListener) { 725 if (skipKillUid) { 726 skipKillRuntimePermissionRevokedUids() 727 } 728 if (revokeReason != null) { 729 addKillRuntimePermissionRevokedUidsReason(revokeReason) 730 } 731 } 732 733 setRuntimePermissionGranted( 734 packageState, userId, permissionName, isGranted, canManageRolePermission, 735 overridePolicyFixed, reportError = true, methodName 736 ) 737 } 738 } 739 740 private fun setRequestedPermissionStates( 741 packageState: PackageState, 742 userId: Int, 743 permissionStates: IndexedMap<String, Int> 744 ) { 745 service.mutateState { 746 permissionStates.forEachIndexed { _, permissionName, permissionState -> 747 when (permissionState) { 748 PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED, 749 PackageInstaller.SessionParams.PERMISSION_STATE_DENIED -> {} 750 else -> { 751 Log.w( 752 LOG_TAG, "setRequestedPermissionStates: Unknown permission state" + 753 " $permissionState for permission $permissionName" 754 ) 755 return@forEachIndexed 756 } 757 } 758 if (permissionName !in packageState.androidPackage!!.requestedPermissions) { 759 return@forEachIndexed 760 } 761 val permission = with(policy) { getPermissions()[permissionName] } 762 ?: return@forEachIndexed 763 when { 764 permission.isDevelopment || permission.isRuntime -> { 765 if (permissionState == 766 PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED) { 767 setRuntimePermissionGranted( 768 packageState, userId, permissionName, isGranted = true, 769 canManageRolePermission = false, overridePolicyFixed = false, 770 reportError = false, "setRequestedPermissionStates" 771 ) 772 } 773 } 774 permission.isAppOp && permissionName in 775 PackageInstallerService.INSTALLER_CHANGEABLE_APP_OP_PERMISSIONS -> 776 setAppOpPermissionGranted( 777 packageState, userId, permissionName, permissionState == 778 PackageInstaller.SessionParams.PERMISSION_STATE_GRANTED 779 ) 780 else -> {} 781 } 782 } 783 } 784 } 785 786 /** 787 * Set whether a runtime permission is granted, without any validation on caller. 788 */ 789 private fun MutateStateScope.setRuntimePermissionGranted( 790 packageState: PackageState, 791 userId: Int, 792 permissionName: String, 793 isGranted: Boolean, 794 canManageRolePermission: Boolean, 795 overridePolicyFixed: Boolean, 796 reportError: Boolean, 797 methodName: String 798 ) { 799 val permission = with(policy) { getPermissions()[permissionName] } 800 if (permission == null) { 801 if (reportError) { 802 throw IllegalArgumentException("Unknown permission $permissionName") 803 } 804 return 805 } 806 807 val androidPackage = packageState.androidPackage!! 808 val packageName = packageState.packageName 809 when { 810 permission.isDevelopment -> {} 811 permission.isRole -> { 812 if (!canManageRolePermission) { 813 if (reportError) { 814 throw SecurityException("Permission $permissionName is managed by role") 815 } 816 return 817 } 818 } 819 permission.isRuntime -> { 820 if (androidPackage.targetSdkVersion < Build.VERSION_CODES.M) { 821 // If a permission review is required for legacy apps we represent 822 // their permissions as always granted 823 return 824 } 825 if (isGranted && packageState.getUserStateOrDefault(userId).isInstantApp && 826 !permission.isInstant) { 827 if (reportError) { 828 throw SecurityException( 829 "Cannot grant non-instant permission $permissionName to package" + 830 " $packageName" 831 ) 832 } 833 return 834 } 835 } 836 else -> { 837 if (reportError) { 838 throw SecurityException( 839 "Permission $permissionName requested by package $packageName is not a" + 840 " changeable permission type" 841 ) 842 } 843 return 844 } 845 } 846 847 val appId = packageState.appId 848 val oldFlags = with(policy) { getPermissionFlags(appId, userId, permissionName) } 849 850 if (permissionName !in androidPackage.requestedPermissions && oldFlags == 0) { 851 if (reportError) { 852 throw SecurityException( 853 "Permission $permissionName isn't requested by package $packageName" 854 ) 855 } 856 return 857 } 858 859 if (oldFlags.hasBits(PermissionFlags.SYSTEM_FIXED)) { 860 if (reportError) { 861 Log.e( 862 LOG_TAG, "$methodName: Cannot change system fixed permission $permissionName" + 863 " for package $packageName" 864 ) 865 } 866 return 867 } 868 869 if (oldFlags.hasBits(PermissionFlags.POLICY_FIXED) && !overridePolicyFixed) { 870 if (reportError) { 871 Log.e( 872 LOG_TAG, "$methodName: Cannot change policy fixed permission $permissionName" + 873 " for package $packageName" 874 ) 875 } 876 return 877 } 878 879 if (isGranted && oldFlags.hasBits(PermissionFlags.RESTRICTION_REVOKED)) { 880 if (reportError) { 881 Log.e( 882 LOG_TAG, "$methodName: Cannot grant hard-restricted non-exempt permission" + 883 " $permissionName to package $packageName" 884 ) 885 } 886 return 887 } 888 889 if (isGranted && oldFlags.hasBits(PermissionFlags.SOFT_RESTRICTED)) { 890 // TODO: Refactor SoftRestrictedPermissionPolicy. 891 val softRestrictedPermissionPolicy = SoftRestrictedPermissionPolicy.forPermission( 892 context, AndroidPackageUtils.generateAppInfoWithoutState(androidPackage), 893 androidPackage, UserHandle.of(userId), permissionName 894 ) 895 if (!softRestrictedPermissionPolicy.mayGrantPermission()) { 896 if (reportError) { 897 Log.e( 898 LOG_TAG, "$methodName: Cannot grant soft-restricted non-exempt permission" + 899 " $permissionName to package $packageName" 900 ) 901 } 902 return 903 } 904 } 905 906 val newFlags = PermissionFlags.updateRuntimePermissionGranted(oldFlags, isGranted) 907 if (oldFlags == newFlags) { 908 return 909 } 910 911 with(policy) { setPermissionFlags(appId, userId, permissionName, newFlags) } 912 913 if (permission.isRuntime) { 914 val action = if (isGranted) { 915 MetricsProto.MetricsEvent.ACTION_PERMISSION_GRANTED 916 } else { 917 MetricsProto.MetricsEvent.ACTION_PERMISSION_REVOKED 918 } 919 val log = LogMaker(action).apply { 920 setPackageName(packageName) 921 addTaggedData(MetricsProto.MetricsEvent.FIELD_PERMISSION, permissionName) 922 } 923 metricsLogger.write(log) 924 } 925 } 926 927 private fun MutateStateScope.setAppOpPermissionGranted( 928 packageState: PackageState, 929 userId: Int, 930 permissionName: String, 931 isGranted: Boolean 932 ) { 933 val appOpPolicy = service.getSchemePolicy(UidUri.SCHEME, AppOpUri.SCHEME) as UidAppOpPolicy 934 val appOpName = AppOpsManager.permissionToOp(permissionName) 935 val mode = if (isGranted) AppOpsManager.MODE_ALLOWED else AppOpsManager.MODE_ERRORED 936 with(appOpPolicy) { setAppOpMode(packageState.appId, userId, appOpName, mode) } 937 } 938 939 override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int { 940 if (!userManagerInternal.exists(userId)) { 941 Log.w(LOG_TAG, "getPermissionFlags: Unknown user $userId") 942 return 0 943 } 944 945 enforceCallingOrSelfCrossUserPermission( 946 userId, enforceFullPermission = true, enforceShellRestriction = false, 947 "getPermissionFlags" 948 ) 949 enforceCallingOrSelfAnyPermission( 950 "getPermissionFlags", Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 951 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS, 952 Manifest.permission.GET_RUNTIME_PERMISSIONS 953 ) 954 955 val packageState = packageManagerLocal.withFilteredSnapshot() 956 .use { it.getPackageState(packageName) } 957 if (packageState == null) { 958 Log.w(LOG_TAG, "getPermissionFlags: Unknown package $packageName") 959 return 0 960 } 961 962 service.getState { 963 val permission = with(policy) { getPermissions()[permissionName] } 964 if (permission == null) { 965 Log.w(LOG_TAG, "getPermissionFlags: Unknown permission $permissionName") 966 return 0 967 } 968 969 val flags = 970 with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } 971 return PermissionFlags.toApiFlags(flags) 972 } 973 } 974 975 override fun isPermissionRevokedByPolicy( 976 packageName: String, 977 permissionName: String, 978 userId: Int 979 ): Boolean { 980 if (!userManagerInternal.exists(userId)) { 981 Log.w(LOG_TAG, "isPermissionRevokedByPolicy: Unknown user $userId") 982 return false 983 } 984 985 enforceCallingOrSelfCrossUserPermission( 986 userId, enforceFullPermission = true, enforceShellRestriction = false, 987 "isPermissionRevokedByPolicy" 988 ) 989 990 val packageState = packageManagerLocal.withFilteredSnapshot(Binder.getCallingUid(), userId) 991 .use { it.getPackageState(packageName) } ?: return false 992 993 service.getState { 994 if (isPermissionGranted(packageState, userId, permissionName)) { 995 return false 996 } 997 998 val flags = with(policy) { 999 getPermissionFlags(packageState.appId, userId, permissionName) 1000 } 1001 return flags.hasBits(PermissionFlags.POLICY_FIXED) 1002 } 1003 } 1004 1005 override fun isPermissionsReviewRequired(packageName: String, userId: Int): Boolean { 1006 requireNotNull(packageName) { "packageName cannot be null" } 1007 // TODO(b/173235285): Some caller may pass USER_ALL as userId. 1008 // Preconditions.checkArgumentNonnegative(userId, "userId") 1009 1010 val packageState = packageManagerLocal.withUnfilteredSnapshot() 1011 .use { it.getPackageState(packageName) } ?: return false 1012 1013 val permissionFlags = service.getState { 1014 with(policy) { getUidPermissionFlags(packageState.appId, userId) } 1015 } ?: return false 1016 return permissionFlags.anyIndexed { _, _, it -> it.hasBits(REVIEW_REQUIRED_FLAGS) } 1017 } 1018 1019 override fun shouldShowRequestPermissionRationale( 1020 packageName: String, 1021 permissionName: String, 1022 userId: Int 1023 ): Boolean { 1024 if (!userManagerInternal.exists(userId)) { 1025 Log.w(LOG_TAG, "shouldShowRequestPermissionRationale: Unknown user $userId") 1026 return false 1027 } 1028 1029 enforceCallingOrSelfCrossUserPermission( 1030 userId, enforceFullPermission = true, enforceShellRestriction = false, 1031 "shouldShowRequestPermissionRationale" 1032 ) 1033 1034 val callingUid = Binder.getCallingUid() 1035 val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId) 1036 .use { it.getPackageState(packageName) } ?: return false 1037 val appId = packageState.appId 1038 if (UserHandle.getAppId(callingUid) != appId) { 1039 return false 1040 } 1041 1042 val flags: Int 1043 service.getState { 1044 if (isPermissionGranted(packageState, userId, permissionName)) { 1045 return false 1046 } 1047 1048 flags = with(policy) { getPermissionFlags(appId, userId, permissionName) } 1049 } 1050 if (flags.hasAnyBit(UNREQUESTABLE_MASK)) { 1051 return false 1052 } 1053 1054 if (permissionName == Manifest.permission.ACCESS_BACKGROUND_LOCATION) { 1055 val isBackgroundRationaleChangeEnabled = Binder::class.withClearedCallingIdentity { 1056 try { 1057 platformCompat.isChangeEnabledByPackageName( 1058 BACKGROUND_RATIONALE_CHANGE_ID, packageName, userId 1059 ) 1060 } catch (e: RemoteException) { 1061 Log.e(LOG_TAG, "shouldShowRequestPermissionRationale: Unable to check if" + 1062 " compatibility change is enabled", e) 1063 false 1064 } 1065 } 1066 if (isBackgroundRationaleChangeEnabled) { 1067 return true 1068 } 1069 } 1070 1071 return flags.hasBits(PermissionFlags.USER_SET) 1072 } 1073 1074 override fun updatePermissionFlags( 1075 packageName: String, 1076 permissionName: String, 1077 flagMask: Int, 1078 flagValues: Int, 1079 enforceAdjustPolicyPermission: Boolean, 1080 userId: Int 1081 ) { 1082 val callingUid = Binder.getCallingUid() 1083 if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES && 1084 PermissionManager.shouldTraceGrant(packageName, permissionName, userId)) { 1085 val flagMaskString = DebugUtils.flagsToString( 1086 PackageManager::class.java, "FLAG_PERMISSION_", flagMask.toLong() 1087 ) 1088 val flagValuesString = DebugUtils.flagsToString( 1089 PackageManager::class.java, "FLAG_PERMISSION_", flagValues.toLong() 1090 ) 1091 val callingUidName = packageManagerInternal.getNameForUid(callingUid) 1092 Log.i( 1093 LOG_TAG, "updatePermissionFlags(packageName = $packageName," + 1094 " permissionName = $permissionName, flagMask = $flagMaskString," + 1095 " flagValues = $flagValuesString, userId = $userId," + 1096 " callingUid = $callingUidName ($callingUid))", RuntimeException() 1097 ) 1098 } 1099 1100 if (!userManagerInternal.exists(userId)) { 1101 Log.w(LOG_TAG, "updatePermissionFlags: Unknown user $userId") 1102 return 1103 } 1104 1105 enforceCallingOrSelfCrossUserPermission( 1106 userId, enforceFullPermission = true, enforceShellRestriction = true, 1107 "updatePermissionFlags" 1108 ) 1109 enforceCallingOrSelfAnyPermission( 1110 "updatePermissionFlags", Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 1111 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS 1112 ) 1113 1114 // Different from the old implementation, which implicitly didn't allow modifying the 1115 // POLICY_FIXED flag if the caller is system or root UID, now we do allow that since system 1116 // and root UIDs are supposed to have all permissions including 1117 // ADJUST_RUNTIME_PERMISSIONS_POLICY. 1118 if (!isRootOrSystem(callingUid)) { 1119 if (flagMask.hasBits(PackageManager.FLAG_PERMISSION_POLICY_FIXED)) { 1120 if (enforceAdjustPolicyPermission) { 1121 context.enforceCallingOrSelfPermission( 1122 Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY, 1123 "Need ${Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY} to change" + 1124 " policy flags" 1125 ) 1126 } else { 1127 val targetSdkVersion = packageManagerInternal.getUidTargetSdkVersion(callingUid) 1128 require(targetSdkVersion < Build.VERSION_CODES.Q) { 1129 "${Manifest.permission.ADJUST_RUNTIME_PERMISSIONS_POLICY} needs to be" + 1130 " checked for packages targeting ${Build.VERSION_CODES.Q} or later" + 1131 " when changing policy flags" 1132 } 1133 } 1134 } 1135 } 1136 1137 // Using PackageManagerInternal instead of PackageManagerLocal for now due to need to access 1138 // shared user packages. 1139 // TODO: We probably shouldn't check the share user packages, since the package name is 1140 // explicitly provided and grantRuntimePermission() isn't checking shared user packages 1141 // anyway. 1142 val packageState = packageManagerInternal.getPackageStateInternal(packageName) 1143 val androidPackage = packageState?.androidPackage 1144 // Different from the old implementation, which returns when package doesn't exist but 1145 // throws when package exists but isn't visible, we now return in both cases to avoid 1146 // leaking the package existence. 1147 if (androidPackage == null || 1148 packageManagerInternal.filterAppAccess(packageName, callingUid, userId, false)) { 1149 Log.w(LOG_TAG, "updatePermissionFlags: Unknown package $packageName") 1150 return 1151 } 1152 1153 val isPermissionRequested = if (permissionName in androidPackage.requestedPermissions) { 1154 // Fast path, the current package has requested the permission. 1155 true 1156 } else { 1157 // Slow path, go through all shared user packages. 1158 val sharedUserPackageNames = 1159 packageManagerInternal.getSharedUserPackagesForPackage(packageName, userId) 1160 sharedUserPackageNames.any { sharedUserPackageName -> 1161 val sharedUserPackage = packageManagerInternal.getPackage(sharedUserPackageName) 1162 sharedUserPackage != null && 1163 permissionName in sharedUserPackage.requestedPermissions 1164 } 1165 } 1166 1167 val appId = packageState.appId 1168 service.mutateState { 1169 updatePermissionFlags( 1170 appId, userId, permissionName, flagMask, flagValues, 1171 reportErrorForUnknownPermission = true, isPermissionRequested, 1172 "updatePermissionFlags", packageName 1173 ) 1174 } 1175 } 1176 1177 override fun updatePermissionFlagsForAllApps(flagMask: Int, flagValues: Int, userId: Int) { 1178 val callingUid = Binder.getCallingUid() 1179 if (PermissionManager.DEBUG_TRACE_PERMISSION_UPDATES) { 1180 val flagMaskString = DebugUtils.flagsToString( 1181 PackageManager::class.java, "FLAG_PERMISSION_", flagMask.toLong() 1182 ) 1183 val flagValuesString = DebugUtils.flagsToString( 1184 PackageManager::class.java, "FLAG_PERMISSION_", flagValues.toLong() 1185 ) 1186 val callingUidName = packageManagerInternal.getNameForUid(callingUid) 1187 Log.i( 1188 LOG_TAG, "updatePermissionFlagsForAllApps(flagMask = $flagMaskString," + 1189 " flagValues = $flagValuesString, userId = $userId," + 1190 " callingUid = $callingUidName ($callingUid))", RuntimeException() 1191 ) 1192 } 1193 1194 if (!userManagerInternal.exists(userId)) { 1195 Log.w(LOG_TAG, "updatePermissionFlagsForAllApps: Unknown user $userId") 1196 return 1197 } 1198 1199 enforceCallingOrSelfCrossUserPermission( 1200 userId, enforceFullPermission = true, enforceShellRestriction = true, 1201 "updatePermissionFlagsForAllApps" 1202 ) 1203 enforceCallingOrSelfAnyPermission( 1204 "updatePermissionFlagsForAllApps", Manifest.permission.GRANT_RUNTIME_PERMISSIONS, 1205 Manifest.permission.REVOKE_RUNTIME_PERMISSIONS 1206 ) 1207 1208 val packageStates = packageManagerLocal.withUnfilteredSnapshot() 1209 .use { it.packageStates } 1210 service.mutateState { 1211 packageStates.forEach { (packageName, packageState) -> 1212 val androidPackage = packageState.androidPackage ?: return@forEach 1213 androidPackage.requestedPermissions.forEach { permissionName -> 1214 // Different from the old implementation, which only sanitized the SYSTEM_FIXED 1215 // flag, we now properly sanitize all flags as in updatePermissionFlags(). 1216 updatePermissionFlags( 1217 packageState.appId, userId, permissionName, flagMask, flagValues, 1218 reportErrorForUnknownPermission = false, isPermissionRequested = true, 1219 "updatePermissionFlagsForAllApps", packageName 1220 ) 1221 } 1222 } 1223 } 1224 } 1225 1226 /** 1227 * Shared internal implementation that should only be called by [updatePermissionFlags] and 1228 * [updatePermissionFlagsForAllApps]. 1229 */ 1230 private fun MutateStateScope.updatePermissionFlags( 1231 appId: Int, 1232 userId: Int, 1233 permissionName: String, 1234 flagMask: Int, 1235 flagValues: Int, 1236 reportErrorForUnknownPermission: Boolean, 1237 isPermissionRequested: Boolean, 1238 methodName: String, 1239 packageName: String 1240 ) { 1241 // Different from the old implementation, which only allowed the system UID to modify the 1242 // following flags, we now allow the root UID as well since both should have all 1243 // permissions. 1244 // Only the system can change these flags and nothing else. 1245 val callingUid = Binder.getCallingUid() 1246 @Suppress("NAME_SHADOWING") 1247 var flagMask = flagMask 1248 @Suppress("NAME_SHADOWING") 1249 var flagValues = flagValues 1250 if (!isRootOrSystem(callingUid)) { 1251 // Different from the old implementation, which allowed non-system UIDs to remove (but 1252 // not add) permission restriction flags, we now consistently ignore them altogether. 1253 val ignoredMask = PackageManager.FLAG_PERMISSION_SYSTEM_FIXED or 1254 PackageManager.FLAG_PERMISSION_GRANTED_BY_DEFAULT or 1255 // REVIEW_REQUIRED can be set on any permission by the shell, or by any app for the 1256 // NOTIFICATIONS permissions specifically. 1257 if (isShell(callingUid) || permissionName in NOTIFICATIONS_PERMISSIONS) { 1258 0 1259 } else { 1260 PackageManager.FLAG_PERMISSION_REVIEW_REQUIRED 1261 } or PackageManager.FLAG_PERMISSION_RESTRICTION_SYSTEM_EXEMPT or 1262 PackageManager.FLAG_PERMISSION_RESTRICTION_INSTALLER_EXEMPT or 1263 PackageManager.FLAG_PERMISSION_RESTRICTION_UPGRADE_EXEMPT or 1264 PackageManager.FLAG_PERMISSION_APPLY_RESTRICTION 1265 flagMask = flagMask andInv ignoredMask 1266 flagValues = flagValues andInv ignoredMask 1267 } 1268 1269 val permission = with(policy) { getPermissions()[permissionName] } 1270 if (permission == null) { 1271 if (reportErrorForUnknownPermission) { 1272 throw IllegalArgumentException("Unknown permission $permissionName") 1273 } 1274 return 1275 } 1276 1277 val oldFlags = with(policy) { getPermissionFlags(appId, userId, permissionName) } 1278 if (!isPermissionRequested && oldFlags == 0) { 1279 Log.w( 1280 LOG_TAG, "$methodName: Permission $permissionName isn't requested by package" + 1281 " $packageName" 1282 ) 1283 return 1284 } 1285 1286 val newFlags = PermissionFlags.updateFlags(permission, oldFlags, flagMask, flagValues) 1287 with(policy) { setPermissionFlags(appId, userId, permissionName, newFlags) } 1288 } 1289 1290 override fun getAllowlistedRestrictedPermissions( 1291 packageName: String, 1292 allowlistedFlags: Int, 1293 userId: Int 1294 ): IndexedList<String>? { 1295 requireNotNull(packageName) { "packageName cannot be null" } 1296 Preconditions.checkFlagsArgument(allowlistedFlags, PERMISSION_ALLOWLIST_MASK) 1297 Preconditions.checkArgumentNonnegative(userId, "userId cannot be null") 1298 1299 if (!userManagerInternal.exists(userId)) { 1300 Log.w(LOG_TAG, "AllowlistedRestrictedPermission api: Unknown user $userId") 1301 return null 1302 } 1303 1304 enforceCallingOrSelfCrossUserPermission( 1305 userId, enforceFullPermission = false, enforceShellRestriction = false, 1306 "getAllowlistedRestrictedPermissions" 1307 ) 1308 1309 val callingUid = Binder.getCallingUid() 1310 val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId) 1311 .use { it.getPackageState(packageName) } ?: return null 1312 val androidPackage = packageState.androidPackage ?: return null 1313 1314 val isCallerPrivileged = context.checkCallingOrSelfPermission( 1315 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS 1316 ) == PackageManager.PERMISSION_GRANTED 1317 1318 if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM) && 1319 !isCallerPrivileged) { 1320 throw SecurityException( 1321 "Querying system allowlist requires " + 1322 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS 1323 ) 1324 } 1325 1326 val isCallerInstallerOnRecord = 1327 packageManagerInternal.isCallerInstallerOfRecord(androidPackage, callingUid) 1328 1329 if (allowlistedFlags.hasAnyBit(PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE or 1330 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) { 1331 if (!isCallerPrivileged && !isCallerInstallerOnRecord) { 1332 throw SecurityException( 1333 "Querying upgrade or installer allowlist requires being installer on record" + 1334 " or ${Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS}" 1335 ) 1336 } 1337 } 1338 1339 return getAllowlistedRestrictedPermissionsUnchecked( 1340 packageState.appId, allowlistedFlags, userId 1341 ) 1342 } 1343 1344 /** 1345 * This method does not enforce checks on the caller, should only be called after 1346 * required checks. 1347 */ 1348 private fun getAllowlistedRestrictedPermissionsUnchecked( 1349 appId: Int, 1350 allowlistedFlags: Int, 1351 userId: Int 1352 ): IndexedList<String>? { 1353 val permissionFlags = service.getState { 1354 with(policy) { getUidPermissionFlags(appId, userId) } 1355 } ?: return null 1356 1357 var queryFlags = 0 1358 if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM)) { 1359 queryFlags = queryFlags or PermissionFlags.SYSTEM_EXEMPT 1360 } 1361 if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE)) { 1362 queryFlags = queryFlags or PermissionFlags.UPGRADE_EXEMPT 1363 } 1364 if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER)) { 1365 queryFlags = queryFlags or PermissionFlags.INSTALLER_EXEMPT 1366 } 1367 1368 return permissionFlags.mapNotNullIndexed { _, permissionName, flags -> 1369 if (flags.hasAnyBit(queryFlags)) permissionName else null 1370 } 1371 } 1372 1373 override fun addAllowlistedRestrictedPermission( 1374 packageName: String, 1375 permissionName: String, 1376 allowlistedFlags: Int, 1377 userId: Int 1378 ): Boolean { 1379 requireNotNull(permissionName) { "permissionName cannot be null" } 1380 if (!enforceRestrictedPermission(permissionName)) { 1381 return false 1382 } 1383 1384 val permissionNames = getAllowlistedRestrictedPermissions( 1385 packageName, allowlistedFlags, userId 1386 ) ?: IndexedList(1) 1387 1388 if (permissionName !in permissionNames) { 1389 permissionNames += permissionName 1390 return setAllowlistedRestrictedPermissions( 1391 packageName, permissionNames, allowlistedFlags, userId, isAddingPermission = true 1392 ) 1393 } 1394 return false 1395 } 1396 1397 private fun addAllowlistedRestrictedPermissionsUnchecked( 1398 androidPackage: AndroidPackage, 1399 appId: Int, 1400 permissionNames: List<String>, 1401 userId: Int 1402 ) { 1403 val newPermissionNames = getAllowlistedRestrictedPermissionsUnchecked(appId, 1404 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId 1405 )?.let { 1406 IndexedSet(permissionNames).apply { this += it }.toList() 1407 } ?: permissionNames 1408 1409 setAllowlistedRestrictedPermissionsUnchecked(androidPackage, appId, newPermissionNames, 1410 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER, userId) 1411 } 1412 1413 override fun removeAllowlistedRestrictedPermission( 1414 packageName: String, 1415 permissionName: String, 1416 allowlistedFlags: Int, 1417 userId: Int 1418 ): Boolean { 1419 requireNotNull(permissionName) { "permissionName cannot be null" } 1420 if (!enforceRestrictedPermission(permissionName)) { 1421 return false 1422 } 1423 1424 val permissions = getAllowlistedRestrictedPermissions( 1425 packageName, allowlistedFlags, userId 1426 ) ?: return false 1427 1428 if (permissions.remove(permissionName)) { 1429 return setAllowlistedRestrictedPermissions( 1430 packageName, permissions, allowlistedFlags, userId, isAddingPermission = false 1431 ) 1432 } 1433 1434 return false 1435 } 1436 1437 private fun enforceRestrictedPermission(permissionName: String): Boolean { 1438 val permission = service.getState { with(policy) { getPermissions()[permissionName] } } 1439 if (permission == null) { 1440 Log.w(LOG_TAG, "permission definition for $permissionName does not exist") 1441 return false 1442 } 1443 1444 if (packageManagerLocal.withFilteredSnapshot() 1445 .use { it.getPackageState(permission.packageName) } == null) { 1446 return false 1447 } 1448 1449 val isImmutablyRestrictedPermission = 1450 permission.isHardOrSoftRestricted && permission.isImmutablyRestricted 1451 if (isImmutablyRestrictedPermission && context.checkCallingOrSelfPermission( 1452 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS 1453 ) != PackageManager.PERMISSION_GRANTED) { 1454 throw SecurityException( 1455 "Cannot modify allowlist of an immutably restricted permission: ${permission.name}" 1456 ) 1457 } 1458 1459 return true 1460 } 1461 1462 private fun setAllowlistedRestrictedPermissions( 1463 packageName: String, 1464 permissionNames: List<String>, 1465 allowlistedFlags: Int, 1466 userId: Int, 1467 isAddingPermission: Boolean 1468 ): Boolean { 1469 Preconditions.checkArgument(allowlistedFlags.countOneBits() == 1) 1470 1471 val isCallerPrivileged = context.checkCallingOrSelfPermission( 1472 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS 1473 ) == PackageManager.PERMISSION_GRANTED 1474 1475 val callingUid = Binder.getCallingUid() 1476 val packageState = packageManagerLocal.withFilteredSnapshot(callingUid, userId) 1477 .use { snapshot -> snapshot.packageStates[packageName] ?: return false } 1478 val androidPackage = packageState.androidPackage ?: return false 1479 1480 val isCallerInstallerOnRecord = 1481 packageManagerInternal.isCallerInstallerOfRecord(androidPackage, callingUid) 1482 1483 if (allowlistedFlags.hasBits(PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE)) { 1484 if (!isCallerPrivileged && !isCallerInstallerOnRecord) { 1485 throw SecurityException( 1486 "Modifying upgrade allowlist requires being installer on record or " + 1487 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS 1488 ) 1489 } 1490 if (isAddingPermission && !isCallerPrivileged) { 1491 throw SecurityException( 1492 "Adding to upgrade allowlist requires" + 1493 Manifest.permission.WHITELIST_RESTRICTED_PERMISSIONS 1494 ) 1495 } 1496 } 1497 1498 setAllowlistedRestrictedPermissionsUnchecked( 1499 androidPackage, packageState.appId, permissionNames, allowlistedFlags, userId 1500 ) 1501 1502 return true 1503 } 1504 1505 /** 1506 * This method does not enforce checks on the caller, should only be called after 1507 * required checks. 1508 */ 1509 private fun setAllowlistedRestrictedPermissionsUnchecked( 1510 androidPackage: AndroidPackage, 1511 appId: Int, 1512 permissionNames: List<String>, 1513 allowlistedFlags: Int, 1514 userId: Int 1515 ) { 1516 service.mutateState { 1517 with(policy) { 1518 val permissionsFlags = 1519 getUidPermissionFlags(appId, userId) ?: return@mutateState 1520 1521 val permissions = getPermissions() 1522 androidPackage.requestedPermissions.forEachIndexed { _, requestedPermission -> 1523 val permission = permissions[requestedPermission] 1524 if (permission == null || !permission.isHardOrSoftRestricted) { 1525 return@forEachIndexed 1526 } 1527 1528 val oldFlags = permissionsFlags[requestedPermission] ?: 0 1529 val wasGranted = PermissionFlags.isPermissionGranted(oldFlags) 1530 1531 var newFlags = oldFlags 1532 var mask = 0 1533 var allowlistFlagsCopy = allowlistedFlags 1534 while (allowlistFlagsCopy != 0) { 1535 val flag = 1 shl allowlistFlagsCopy.countTrailingZeroBits() 1536 allowlistFlagsCopy = allowlistFlagsCopy and flag.inv() 1537 when (flag) { 1538 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM -> { 1539 mask = mask or PermissionFlags.SYSTEM_EXEMPT 1540 newFlags = 1541 if (permissionNames.contains(requestedPermission)) { 1542 newFlags or PermissionFlags.SYSTEM_EXEMPT 1543 } else { 1544 newFlags andInv PermissionFlags.SYSTEM_EXEMPT 1545 } 1546 } 1547 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE -> { 1548 mask = mask or PermissionFlags.UPGRADE_EXEMPT 1549 newFlags = 1550 if (permissionNames.contains(requestedPermission)) { 1551 newFlags or PermissionFlags.UPGRADE_EXEMPT 1552 } else { 1553 newFlags andInv PermissionFlags.UPGRADE_EXEMPT 1554 } 1555 } 1556 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER -> { 1557 mask = mask or PermissionFlags.INSTALLER_EXEMPT 1558 newFlags = 1559 if (permissionNames.contains(requestedPermission)) { 1560 newFlags or PermissionFlags.INSTALLER_EXEMPT 1561 } else { 1562 newFlags andInv PermissionFlags.INSTALLER_EXEMPT 1563 } 1564 } 1565 } 1566 } 1567 1568 if (oldFlags == newFlags) { 1569 return@forEachIndexed 1570 } 1571 1572 val wasAllowlisted = oldFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT) 1573 val isAllowlisted = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT) 1574 1575 // If the permission is policy fixed as granted but it is no longer 1576 // on any of the allowlists we need to clear the policy fixed flag 1577 // as allowlisting trumps policy i.e. policy cannot grant a non 1578 // grantable permission. 1579 if (oldFlags.hasBits(PermissionFlags.POLICY_FIXED)) { 1580 if (!isAllowlisted && wasGranted) { 1581 mask = mask or PermissionFlags.POLICY_FIXED 1582 newFlags = newFlags andInv PermissionFlags.POLICY_FIXED 1583 } 1584 } 1585 1586 // If we are allowlisting an app that does not support runtime permissions 1587 // we need to make sure it goes through the permission review UI at launch. 1588 if (androidPackage.targetSdkVersion < Build.VERSION_CODES.M && 1589 !wasAllowlisted && isAllowlisted) { 1590 mask = mask or PermissionFlags.IMPLICIT 1591 newFlags = newFlags or PermissionFlags.IMPLICIT 1592 } 1593 1594 updatePermissionFlags( 1595 appId, userId, requestedPermission, mask, newFlags 1596 ) 1597 } 1598 } 1599 } 1600 } 1601 1602 override fun resetRuntimePermissions(androidPackage: AndroidPackage, userId: Int) { 1603 // TODO("Not yet implemented") 1604 } 1605 1606 override fun resetRuntimePermissionsForUser(userId: Int) { 1607 // TODO("Not yet implemented") 1608 } 1609 1610 override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { 1611 onPermissionsChangeListeners.addListener(listener) 1612 } 1613 1614 override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { 1615 onPermissionsChangeListeners.removeListener(listener) 1616 } 1617 1618 override fun addOnRuntimePermissionStateChangedListener( 1619 listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener 1620 ) { 1621 // TODO: Should be removed once we remove PermissionPolicyService. 1622 } 1623 1624 override fun removeOnRuntimePermissionStateChangedListener( 1625 listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener 1626 ) { 1627 // TODO: Should be removed once we remove PermissionPolicyService. 1628 } 1629 1630 override fun getSplitPermissions(): List<SplitPermissionInfoParcelable> { 1631 return PermissionManager.splitPermissionInfoListToParcelableList( 1632 systemConfig.splitPermissions 1633 ) 1634 } 1635 1636 1637 1638 override fun getAppOpPermissionPackages(permissionName: String): Array<String> { 1639 requireNotNull(permissionName) { "permissionName cannot be null" } 1640 val packageNames = IndexedSet<String>() 1641 1642 val permission = service.getState { 1643 with(policy) { getPermissions()[permissionName] } 1644 } 1645 if (permission == null || !permission.isAppOp) { 1646 packageNames.toTypedArray() 1647 } 1648 1649 packageManagerLocal.withUnfilteredSnapshot().use { snapshot -> 1650 snapshot.packageStates.forEach packageStates@{ (_, packageState) -> 1651 val androidPackage = packageState.androidPackage ?: return@packageStates 1652 if (permissionName in androidPackage.requestedPermissions) { 1653 packageNames += androidPackage.packageName 1654 } 1655 } 1656 } 1657 1658 return packageNames.toTypedArray() 1659 } 1660 1661 override fun getAllAppOpPermissionPackages(): Map<String, Set<String>> { 1662 val appOpPermissionPackageNames = IndexedMap<String, IndexedSet<String>>() 1663 val permissions = service.getState { with(policy) { getPermissions() } } 1664 packageManagerLocal.withUnfilteredSnapshot().use { snapshot -> 1665 snapshot.packageStates.forEach packageStates@{ (_, packageState) -> 1666 val androidPackage = packageState.androidPackage ?: return@packageStates 1667 androidPackage.requestedPermissions.forEach requestedPermissions@{ permissionName -> 1668 val permission = permissions[permissionName] ?: return@requestedPermissions 1669 if (permission.isAppOp) { 1670 val packageNames = appOpPermissionPackageNames 1671 .getOrPut(permissionName) { IndexedSet() } 1672 packageNames += androidPackage.packageName 1673 } 1674 } 1675 } 1676 } 1677 return appOpPermissionPackageNames 1678 } 1679 1680 override fun backupRuntimePermissions(userId: Int): ByteArray? { 1681 Preconditions.checkArgumentNonnegative(userId, "userId cannot be null") 1682 val backup = CompletableFuture<ByteArray>() 1683 permissionControllerManager.getRuntimePermissionBackup( 1684 UserHandle.of(userId), PermissionThread.getExecutor(), backup::complete 1685 ) 1686 1687 return try { 1688 backup.get(BACKUP_TIMEOUT_MILLIS, TimeUnit.MILLISECONDS) 1689 } catch (e: Exception) { 1690 when (e) { 1691 is TimeoutException, is InterruptedException, is ExecutionException -> { 1692 Log.e(LOG_TAG, "Cannot create permission backup for user $userId", e) 1693 null 1694 } 1695 else -> throw e 1696 } 1697 } 1698 } 1699 1700 override fun restoreRuntimePermissions(backup: ByteArray, userId: Int) { 1701 requireNotNull(backup) { "backup" } 1702 Preconditions.checkArgumentNonnegative(userId, "userId") 1703 1704 synchronized(isDelayedPermissionBackupFinished) { 1705 isDelayedPermissionBackupFinished -= userId 1706 } 1707 permissionControllerManager.stageAndApplyRuntimePermissionsBackup( 1708 backup, UserHandle.of(userId) 1709 ) 1710 } 1711 1712 override fun restoreDelayedRuntimePermissions(packageName: String, userId: Int) { 1713 requireNotNull(packageName) { "packageName" } 1714 Preconditions.checkArgumentNonnegative(userId, "userId") 1715 1716 synchronized(isDelayedPermissionBackupFinished) { 1717 if (isDelayedPermissionBackupFinished.get(userId, false)) { 1718 return 1719 } 1720 } 1721 permissionControllerManager.applyStagedRuntimePermissionBackup( 1722 packageName, UserHandle.of(userId), PermissionThread.getExecutor() 1723 ) { hasMoreBackup -> 1724 if (hasMoreBackup) { 1725 return@applyStagedRuntimePermissionBackup 1726 } 1727 synchronized(isDelayedPermissionBackupFinished) { 1728 isDelayedPermissionBackupFinished.put(userId, true) 1729 } 1730 } 1731 } 1732 1733 override fun dump(fd: FileDescriptor, pw: PrintWriter, args: Array<out String>?) { 1734 if (!DumpUtils.checkDumpPermission(context, LOG_TAG, pw)) { 1735 return 1736 } 1737 context.getSystemService(PermissionControllerManager::class.java)!!.dump(fd, args) 1738 } 1739 1740 override fun getPermissionTEMP(permissionName: String): LegacyPermission2? { 1741 val permission = service.getState { 1742 with(policy) { getPermissions()[permissionName] } 1743 } ?: return null 1744 1745 return LegacyPermission2( 1746 permission.permissionInfo, permission.type, permission.isReconciled, permission.appId, 1747 permission.gids, permission.areGidsPerUser 1748 ) 1749 } 1750 1751 override fun getLegacyPermissions(): List<LegacyPermission> = 1752 service.getState { 1753 with(policy) { getPermissions() } 1754 }.mapIndexed { _, _, permission -> 1755 LegacyPermission( 1756 permission.permissionInfo, permission.type, permission.appId, permission.gids 1757 ) 1758 } 1759 1760 override fun readLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) { 1761 // Package settings has been read when this method is called. 1762 service.initialize() 1763 } 1764 1765 override fun writeLegacyPermissionsTEMP(legacyPermissionSettings: LegacyPermissionSettings) { 1766 service.getState { 1767 val permissions = with(policy) { getPermissions() } 1768 legacyPermissionSettings.replacePermissions(toLegacyPermissions(permissions)) 1769 val permissionTrees = with(policy) { getPermissionTrees() } 1770 legacyPermissionSettings.replacePermissionTrees(toLegacyPermissions(permissionTrees)) 1771 } 1772 } 1773 1774 private fun toLegacyPermissions( 1775 permissions: IndexedMap<String, Permission> 1776 ): List<LegacyPermission> = 1777 permissions.mapIndexed { _, _, permission -> 1778 // We don't need to provide UID and GIDs, which are only retrieved when dumping. 1779 LegacyPermission( 1780 permission.permissionInfo, permission.type, 0, EmptyArray.INT 1781 ) 1782 } 1783 1784 override fun getLegacyPermissionState(appId: Int): LegacyPermissionState { 1785 val legacyState = LegacyPermissionState() 1786 val userIds = userManagerService.userIdsIncludingPreCreated 1787 service.getState { 1788 val permissions = with(policy) { getPermissions() } 1789 userIds.forEachIndexed { _, userId -> 1790 val permissionFlags = with(policy) { getUidPermissionFlags(appId, userId) } 1791 ?: return@forEachIndexed 1792 1793 permissionFlags.forEachIndexed permissionFlags@{ _, permissionName, flags -> 1794 val permission = permissions[permissionName] ?: return@permissionFlags 1795 val legacyPermissionState = LegacyPermissionState.PermissionState( 1796 permissionName, 1797 permission.isRuntime, 1798 PermissionFlags.isPermissionGranted(flags), 1799 PermissionFlags.toApiFlags(flags) 1800 ) 1801 legacyState.putPermissionState(legacyPermissionState, userId) 1802 } 1803 } 1804 } 1805 return legacyState 1806 } 1807 1808 override fun readLegacyPermissionStateTEMP() {} 1809 1810 override fun writeLegacyPermissionStateTEMP() {} 1811 1812 override fun onSystemReady() { 1813 service.onSystemReady() 1814 permissionControllerManager = PermissionControllerManager( 1815 context, PermissionThread.getHandler() 1816 ) 1817 } 1818 1819 override fun onUserCreated(userId: Int) { 1820 service.onUserAdded(userId) 1821 } 1822 1823 override fun onUserRemoved(userId: Int) { 1824 service.onUserRemoved(userId) 1825 } 1826 1827 override fun onStorageVolumeMounted(volumeUuid: String, fingerprintChanged: Boolean) { 1828 service.onStorageVolumeMounted(volumeUuid, fingerprintChanged) 1829 synchronized(mountedStorageVolumes) { 1830 mountedStorageVolumes += volumeUuid 1831 } 1832 } 1833 1834 override fun onPackageAdded( 1835 packageState: PackageState, 1836 isInstantApp: Boolean, 1837 oldPackage: AndroidPackage? 1838 ) { 1839 synchronized(mountedStorageVolumes) { 1840 if (packageState.volumeUuid !in mountedStorageVolumes) { 1841 // Wait for the storage volume to be mounted and batch the state mutation there. 1842 return 1843 } 1844 } 1845 service.onPackageAdded(packageState.packageName) 1846 } 1847 1848 override fun onPackageRemoved(androidPackage: AndroidPackage) { 1849 // This may not be a full removal so ignored - we'll figure out full removal in 1850 // onPackageUninstalled(). 1851 } 1852 1853 override fun onPackageInstalled( 1854 androidPackage: AndroidPackage, 1855 previousAppId: Int, 1856 params: PermissionManagerServiceInternal.PackageInstalledParams, 1857 userId: Int 1858 ) { 1859 synchronized(mountedStorageVolumes) { 1860 if (androidPackage.volumeUuid !in mountedStorageVolumes) { 1861 // Wait for the storage volume to be mounted and batch the state mutation there. 1862 // PackageInstalledParams won't exist when packages are being scanned instead of 1863 // being installed by an installer. 1864 return 1865 } 1866 } 1867 val userIds = if (userId == UserHandle.USER_ALL) { 1868 userManagerService.userIdsIncludingPreCreated 1869 } else { 1870 intArrayOf(userId) 1871 } 1872 @Suppress("NAME_SHADOWING") 1873 userIds.forEach { userId -> 1874 service.onPackageInstalled(androidPackage.packageName, userId) 1875 } 1876 1877 @Suppress("NAME_SHADOWING") 1878 userIds.forEach { userId -> 1879 // TODO: Remove when this callback receives packageState directly. 1880 val packageState = 1881 packageManagerInternal.getPackageStateInternal(androidPackage.packageName)!! 1882 addAllowlistedRestrictedPermissionsUnchecked(androidPackage, packageState.appId, 1883 params.allowlistedRestrictedPermissions, userId) 1884 setRequestedPermissionStates(packageState, userId, params.permissionStates) 1885 } 1886 } 1887 1888 override fun onPackageUninstalled( 1889 packageName: String, 1890 appId: Int, 1891 packageState: PackageState, 1892 androidPackage: AndroidPackage?, 1893 sharedUserPkgs: List<AndroidPackage>, 1894 userId: Int 1895 ) { 1896 val userIds = if (userId == UserHandle.USER_ALL) { 1897 userManagerService.userIdsIncludingPreCreated 1898 } else { 1899 intArrayOf(userId) 1900 } 1901 userIds.forEach { service.onPackageUninstalled(packageName, appId, it) } 1902 val packageState = packageManagerInternal.packageStates[packageName] 1903 if (packageState == null) { 1904 service.onPackageRemoved(packageName, appId) 1905 } 1906 } 1907 1908 /** 1909 * Check whether a UID is root or system. 1910 */ 1911 private fun isRootOrSystem(uid: Int) = 1912 when (UserHandle.getAppId(uid)) { 1913 Process.ROOT_UID, Process.SYSTEM_UID -> true 1914 else -> false 1915 } 1916 1917 /** 1918 * Check whether a UID is shell. 1919 */ 1920 private fun isShell(uid: Int) = UserHandle.getAppId(uid) == Process.SHELL_UID 1921 1922 /** 1923 * Check whether a UID is root, system or shell. 1924 */ 1925 private fun isRootOrSystemOrShell(uid: Int) = isRootOrSystem(uid) || isShell(uid) 1926 1927 /** 1928 * This method should typically only be used when granting or revoking permissions, since the 1929 * app may immediately restart after this call. 1930 * 1931 * If you're doing surgery on app code/data, use [PackageFreezer] to guard your work against 1932 * the app being relaunched. 1933 */ 1934 private fun killUid(uid: Int, reason: String) { 1935 val activityManager = ActivityManager.getService() 1936 if (activityManager != null) { 1937 val appId = UserHandle.getAppId(uid) 1938 val userId = UserHandle.getUserId(uid) 1939 Binder::class.withClearedCallingIdentity { 1940 try { 1941 activityManager.killUidForPermissionChange(appId, userId, reason) 1942 } catch (e: RemoteException) { 1943 /* ignore - same process */ 1944 } 1945 } 1946 } 1947 } 1948 1949 /** 1950 * @see PackageManagerLocal.withFilteredSnapshot 1951 */ 1952 private fun PackageManagerLocal.withFilteredSnapshot( 1953 callingUid: Int, 1954 userId: Int 1955 ): PackageManagerLocal.FilteredSnapshot = 1956 withFilteredSnapshot(callingUid, UserHandle.of(userId)) 1957 1958 /** 1959 * Get the [PackageState] for a package name. 1960 * 1961 * This is for parity with [PackageManagerLocal.FilteredSnapshot.getPackageState] which is more 1962 * efficient than [PackageManagerLocal.FilteredSnapshot.getPackageStates], so that we can always 1963 * prefer using `getPackageState()` without worrying about whether the snapshot is filtered. 1964 */ 1965 private fun PackageManagerLocal.UnfilteredSnapshot.getPackageState( 1966 packageName: String 1967 ): PackageState? = packageStates[packageName] 1968 1969 /** 1970 * Check whether a UID belongs to an instant app. 1971 */ 1972 private fun PackageManagerLocal.UnfilteredSnapshot.isUidInstantApp(uid: Int): Boolean = 1973 // Unfortunately we don't have the API for getting the owner UID of an isolated UID or the 1974 // API for getting the SharedUserApi object for an app ID yet, so for now we just keep 1975 // calling the old API. 1976 packageManagerInternal.getInstantAppPackageName(uid) != null 1977 1978 /** 1979 * Check whether a package is visible to a UID within the same user as the UID. 1980 */ 1981 private fun PackageManagerLocal.UnfilteredSnapshot.isPackageVisibleToUid( 1982 packageName: String, 1983 uid: Int 1984 ): Boolean = isPackageVisibleToUid(packageName, UserHandle.getUserId(uid), uid) 1985 1986 /** 1987 * Check whether a package in a particular user is visible to a UID. 1988 */ 1989 private fun PackageManagerLocal.UnfilteredSnapshot.isPackageVisibleToUid( 1990 packageName: String, 1991 userId: Int, 1992 uid: Int 1993 ): Boolean = filtered(uid, userId).use { it.getPackageState(packageName) != null } 1994 1995 /** 1996 * @see PackageManagerLocal.UnfilteredSnapshot.filtered 1997 */ 1998 private fun PackageManagerLocal.UnfilteredSnapshot.filtered( 1999 callingUid: Int, 2000 userId: Int 2001 ): PackageManagerLocal.FilteredSnapshot = filtered(callingUid, UserHandle.of(userId)) 2002 2003 /** 2004 * If neither you nor the calling process of an IPC you are handling has been granted the 2005 * permission for accessing a particular [userId], throw a [SecurityException]. 2006 * 2007 * @see Context.enforceCallingOrSelfPermission 2008 * @see UserManager.DISALLOW_DEBUGGING_FEATURES 2009 */ 2010 private fun enforceCallingOrSelfCrossUserPermission( 2011 userId: Int, 2012 enforceFullPermission: Boolean, 2013 enforceShellRestriction: Boolean, 2014 message: String? 2015 ) { 2016 require(userId >= 0) { "userId $userId is invalid" } 2017 val callingUid = Binder.getCallingUid() 2018 val callingUserId = UserHandle.getUserId(callingUid) 2019 if (userId != callingUserId) { 2020 val permissionName = if (enforceFullPermission) { 2021 Manifest.permission.INTERACT_ACROSS_USERS_FULL 2022 } else { 2023 Manifest.permission.INTERACT_ACROSS_USERS 2024 } 2025 if (context.checkCallingOrSelfPermission(permissionName) != 2026 PackageManager.PERMISSION_GRANTED) { 2027 val exceptionMessage = buildString { 2028 if (message != null) { 2029 append(message) 2030 append(": ") 2031 } 2032 append("Neither user ") 2033 append(Binder.getCallingUid()) 2034 append(" nor current process has ") 2035 append(permissionName) 2036 append(" to access user ") 2037 append(userId) 2038 } 2039 throw SecurityException(exceptionMessage) 2040 } 2041 } 2042 if (enforceShellRestriction && isShell(callingUid)) { 2043 val isShellRestricted = userManagerInternal.hasUserRestriction( 2044 UserManager.DISALLOW_DEBUGGING_FEATURES, userId 2045 ) 2046 if (isShellRestricted) { 2047 val exceptionMessage = buildString { 2048 if (message != null) { 2049 append(message) 2050 append(": ") 2051 } 2052 append("Shell is disallowed to access user ") 2053 append(userId) 2054 } 2055 throw SecurityException(exceptionMessage) 2056 } 2057 } 2058 } 2059 2060 /** 2061 * If neither you nor the calling process of an IPC you are handling has been granted any of the 2062 * permissions, throw a [SecurityException]. 2063 * 2064 * @see Context.enforceCallingOrSelfPermission 2065 */ 2066 private fun enforceCallingOrSelfAnyPermission( 2067 message: String?, 2068 vararg permissionNames: String 2069 ) { 2070 val hasAnyPermission = permissionNames.any { permissionName -> 2071 context.checkCallingOrSelfPermission(permissionName) == 2072 PackageManager.PERMISSION_GRANTED 2073 } 2074 if (!hasAnyPermission) { 2075 val exceptionMessage = buildString { 2076 if (message != null) { 2077 append(message) 2078 append(": ") 2079 } 2080 append("Neither user ") 2081 append(Binder.getCallingUid()) 2082 append(" nor current process has any of ") 2083 permissionNames.joinTo(this, ", ") 2084 } 2085 throw SecurityException(exceptionMessage) 2086 } 2087 } 2088 2089 /** 2090 * Callback invoked when interesting actions have been taken on a permission. 2091 */ 2092 private inner class OnPermissionFlagsChangedListener : 2093 UidPermissionPolicy.OnPermissionFlagsChangedListener() { 2094 private var isPermissionFlagsChanged = false 2095 2096 private val runtimePermissionChangedUids = IntSet() 2097 // Mapping from UID to whether only notifications permissions are revoked. 2098 private val runtimePermissionRevokedUids = IntBooleanMap() 2099 private val gidsChangedUids = IntSet() 2100 2101 private var isKillRuntimePermissionRevokedUidsSkipped = false 2102 private val killRuntimePermissionRevokedUidsReasons = IndexedSet<String>() 2103 2104 fun MutateStateScope.skipKillRuntimePermissionRevokedUids() { 2105 isKillRuntimePermissionRevokedUidsSkipped = true 2106 } 2107 2108 fun MutateStateScope.addKillRuntimePermissionRevokedUidsReason(reason: String) { 2109 killRuntimePermissionRevokedUidsReasons += reason 2110 } 2111 2112 override fun onPermissionFlagsChanged( 2113 appId: Int, 2114 userId: Int, 2115 permissionName: String, 2116 oldFlags: Int, 2117 newFlags: Int 2118 ) { 2119 isPermissionFlagsChanged = true 2120 2121 val uid = UserHandle.getUid(userId, appId) 2122 val permission = service.getState { 2123 with(policy) { getPermissions()[permissionName] } 2124 } ?: return 2125 val wasPermissionGranted = PermissionFlags.isPermissionGranted(oldFlags) 2126 val isPermissionGranted = PermissionFlags.isPermissionGranted(newFlags) 2127 2128 if (permission.isRuntime) { 2129 // Different from the old implementation, which notifies the listeners when the 2130 // permission flags have changed for a non-runtime permission, now we no longer do 2131 // that because permission flags are only for runtime permissions and the listeners 2132 // aren't being notified of non-runtime permission grant state changes anyway. 2133 runtimePermissionChangedUids += uid 2134 if (wasPermissionGranted && !isPermissionGranted) { 2135 runtimePermissionRevokedUids[uid] = 2136 permissionName in NOTIFICATIONS_PERMISSIONS && 2137 runtimePermissionRevokedUids.getWithDefault(uid, true) 2138 } 2139 } 2140 2141 if (permission.hasGids && !wasPermissionGranted && isPermissionGranted) { 2142 gidsChangedUids += uid 2143 } 2144 } 2145 2146 override fun onStateMutated() { 2147 if (isPermissionFlagsChanged) { 2148 PackageManager.invalidatePackageInfoCache() 2149 isPermissionFlagsChanged = false 2150 } 2151 2152 runtimePermissionChangedUids.forEachIndexed { _, uid -> 2153 onPermissionsChangeListeners.onPermissionsChanged(uid) 2154 } 2155 runtimePermissionChangedUids.clear() 2156 2157 if (!isKillRuntimePermissionRevokedUidsSkipped) { 2158 val reason = if (killRuntimePermissionRevokedUidsReasons.isNotEmpty()) { 2159 killRuntimePermissionRevokedUidsReasons.joinToString(", ") 2160 } else { 2161 PermissionManager.KILL_APP_REASON_PERMISSIONS_REVOKED 2162 } 2163 runtimePermissionRevokedUids.forEachIndexed { 2164 _, uid, areOnlyNotificationsPermissionsRevoked -> 2165 handler.post { 2166 if (areOnlyNotificationsPermissionsRevoked && 2167 isAppBackupAndRestoreRunning(uid) 2168 ) { 2169 return@post 2170 } 2171 killUid(uid, reason) 2172 } 2173 } 2174 } 2175 runtimePermissionRevokedUids.clear() 2176 2177 gidsChangedUids.forEachIndexed { _, uid -> 2178 handler.post { killUid(uid, PermissionManager.KILL_APP_REASON_GIDS_CHANGED) } 2179 } 2180 gidsChangedUids.clear() 2181 2182 isKillRuntimePermissionRevokedUidsSkipped = false 2183 killRuntimePermissionRevokedUidsReasons.clear() 2184 } 2185 2186 private fun isAppBackupAndRestoreRunning(uid: Int): Boolean { 2187 if (checkUidPermission(uid, Manifest.permission.BACKUP) != 2188 PackageManager.PERMISSION_GRANTED) { 2189 return false 2190 } 2191 return try { 2192 val contentResolver = context.contentResolver 2193 val userId = UserHandle.getUserId(uid) 2194 val isInSetup = Settings.Secure.getIntForUser( 2195 contentResolver, Settings.Secure.USER_SETUP_COMPLETE, userId 2196 ) == 0 2197 val isInDeferredSetup = Settings.Secure.getIntForUser( 2198 contentResolver, Settings.Secure.USER_SETUP_PERSONALIZATION_STATE, userId 2199 ) == Settings.Secure.USER_SETUP_PERSONALIZATION_STARTED 2200 isInSetup || isInDeferredSetup 2201 } catch (e: Settings.SettingNotFoundException) { 2202 Log.w(LOG_TAG, "Failed to check if the user is in restore: $e") 2203 false 2204 } 2205 } 2206 } 2207 2208 private class OnPermissionsChangeListeners(looper: Looper) : Handler(looper) { 2209 private val listeners = RemoteCallbackList<IOnPermissionsChangeListener>() 2210 2211 override fun handleMessage(msg: Message) { 2212 when (msg.what) { 2213 MSG_ON_PERMISSIONS_CHANGED -> { 2214 val uid = msg.arg1 2215 handleOnPermissionsChanged(uid) 2216 } 2217 } 2218 } 2219 2220 private fun handleOnPermissionsChanged(uid: Int) { 2221 listeners.broadcast { listener -> 2222 try { 2223 listener.onPermissionsChanged(uid) 2224 } catch (e: RemoteException) { 2225 Log.e(LOG_TAG, "Error when calling OnPermissionsChangeListener", e) 2226 } 2227 } 2228 } 2229 2230 fun addListener(listener: IOnPermissionsChangeListener) { 2231 listeners.register(listener) 2232 } 2233 2234 fun removeListener(listener: IOnPermissionsChangeListener) { 2235 listeners.unregister(listener) 2236 } 2237 2238 fun onPermissionsChanged(uid: Int) { 2239 if (listeners.registeredCallbackCount > 0) { 2240 obtainMessage(MSG_ON_PERMISSIONS_CHANGED, uid, 0).sendToTarget() 2241 } 2242 } 2243 2244 companion object { 2245 private const val MSG_ON_PERMISSIONS_CHANGED = 1 2246 } 2247 } 2248 2249 companion object { 2250 private val LOG_TAG = PermissionService::class.java.simpleName 2251 2252 /** 2253 * This change makes it so that apps are told to show rationale for asking for background 2254 * location access every time they request. 2255 */ 2256 @ChangeId 2257 @EnabledAfter(targetSdkVersion = Build.VERSION_CODES.Q) 2258 private val BACKGROUND_RATIONALE_CHANGE_ID = 147316723L 2259 2260 private val FULLER_PERMISSIONS = IndexedMap<String, String>().apply { 2261 this[Manifest.permission.ACCESS_COARSE_LOCATION] = 2262 Manifest.permission.ACCESS_FINE_LOCATION 2263 this[Manifest.permission.INTERACT_ACROSS_USERS] = 2264 Manifest.permission.INTERACT_ACROSS_USERS_FULL 2265 } 2266 2267 private val NOTIFICATIONS_PERMISSIONS = indexedSetOf( 2268 Manifest.permission.POST_NOTIFICATIONS 2269 ) 2270 2271 private const val REVIEW_REQUIRED_FLAGS = PermissionFlags.LEGACY_GRANTED or 2272 PermissionFlags.IMPLICIT 2273 private const val UNREQUESTABLE_MASK = PermissionFlags.RESTRICTION_REVOKED or 2274 PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED or 2275 PermissionFlags.USER_FIXED 2276 2277 private val BACKUP_TIMEOUT_MILLIS = TimeUnit.SECONDS.toMillis(60) 2278 2279 /** Cap the size of permission trees that 3rd party apps can define; in characters of text */ 2280 private const val MAX_PERMISSION_TREE_FOOTPRINT = 32768 2281 2282 private const val PERMISSION_ALLOWLIST_MASK = 2283 PackageManager.FLAG_PERMISSION_WHITELIST_UPGRADE or 2284 PackageManager.FLAG_PERMISSION_WHITELIST_SYSTEM or 2285 PackageManager.FLAG_PERMISSION_WHITELIST_INSTALLER 2286 } 2287 } 2288