1 /* 2 * Copyright (C) 2021 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.content.pm.PackageManager 21 import android.content.pm.PermissionGroupInfo 22 import android.content.pm.PermissionInfo 23 import android.content.pm.SigningDetails 24 import android.os.Build 25 import android.os.UserHandle 26 import android.util.Log 27 import com.android.internal.os.RoSystemProperties 28 import com.android.modules.utils.BinaryXmlPullParser 29 import com.android.modules.utils.BinaryXmlSerializer 30 import com.android.server.permission.access.AccessState 31 import com.android.server.permission.access.AccessUri 32 import com.android.server.permission.access.GetStateScope 33 import com.android.server.permission.access.MutateStateScope 34 import com.android.server.permission.access.PermissionUri 35 import com.android.server.permission.access.SchemePolicy 36 import com.android.server.permission.access.UidUri 37 import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports 38 import com.android.server.permission.access.util.andInv 39 import com.android.server.permission.access.util.hasAnyBit 40 import com.android.server.permission.access.util.hasBits 41 import com.android.server.permission.access.util.isInternal 42 import com.android.server.pm.KnownPackages 43 import com.android.server.pm.parsing.PackageInfoUtils 44 import com.android.server.pm.permission.CompatibilityPermissionInfo 45 import com.android.server.pm.pkg.AndroidPackage 46 import com.android.server.pm.pkg.PackageState 47 48 class UidPermissionPolicy : SchemePolicy() { 49 private val persistence = UidPermissionPersistence() 50 51 @Volatile 52 private var onPermissionFlagsChangedListeners = 53 IndexedListSet<OnPermissionFlagsChangedListener>() 54 private val onPermissionFlagsChangedListenersLock = Any() 55 56 private val privilegedPermissionAllowlistViolations = IndexedSet<String>() 57 58 override val subjectScheme: String 59 get() = UidUri.SCHEME 60 61 override val objectScheme: String 62 get() = PermissionUri.SCHEME 63 64 override fun GetStateScope.getDecision(subject: AccessUri, `object`: AccessUri): Int { 65 subject as UidUri 66 `object` as PermissionUri 67 return getPermissionFlags(subject.appId, subject.userId, `object`.permissionName) 68 } 69 70 override fun MutateStateScope.setDecision( 71 subject: AccessUri, 72 `object`: AccessUri, 73 decision: Int 74 ) { 75 subject as UidUri 76 `object` as PermissionUri 77 setPermissionFlags(subject.appId, subject.userId, `object`.permissionName, decision) 78 } 79 80 override fun GetStateScope.onStateMutated() { 81 onPermissionFlagsChangedListeners.forEachIndexed { _, it -> it.onStateMutated() } 82 } 83 84 override fun MutateStateScope.onInitialized() { 85 newState.systemState.configPermissions.forEach { (permissionName, permissionEntry) -> 86 val permissions = newState.systemState.permissions 87 val oldPermission = permissions[permissionName] 88 val newPermission = if (oldPermission != null) { 89 if (permissionEntry.gids != null) { 90 oldPermission.copy( 91 gids = permissionEntry.gids, areGidsPerUser = permissionEntry.perUser 92 ) 93 } else { 94 return@forEach 95 } 96 } else { 97 @Suppress("DEPRECATION") 98 val permissionInfo = PermissionInfo().apply { 99 name = permissionName 100 packageName = PLATFORM_PACKAGE_NAME 101 protectionLevel = PermissionInfo.PROTECTION_SIGNATURE 102 } 103 if (permissionEntry.gids != null) { 104 Permission( 105 permissionInfo, false, Permission.TYPE_CONFIG, 0, permissionEntry.gids, 106 permissionEntry.perUser 107 ) 108 } else { 109 Permission(permissionInfo, false, Permission.TYPE_CONFIG, 0) 110 } 111 } 112 permissions[permissionName] = newPermission 113 } 114 } 115 116 override fun MutateStateScope.onUserAdded(userId: Int) { 117 newState.systemState.packageStates.forEach { (_, packageState) -> 118 evaluateAllPermissionStatesForPackageAndUser(packageState, userId, null) 119 } 120 newState.systemState.appIds.forEachKeyIndexed { _, appId -> 121 inheritImplicitPermissionStates(appId, userId) 122 } 123 } 124 125 override fun MutateStateScope.onAppIdRemoved(appId: Int) { 126 newState.userStates.forEachValueIndexed { _, userState -> 127 userState.uidPermissionFlags -= appId 128 userState.requestWrite() 129 // Skip notifying the change listeners since the app ID no longer exists. 130 } 131 } 132 133 override fun MutateStateScope.onStorageVolumeMounted( 134 volumeUuid: String?, 135 isSystemUpdated: Boolean 136 ) { 137 val changedPermissionNames = IndexedSet<String>() 138 newState.systemState.packageStates.forEach { (_, packageState) -> 139 val androidPackage = packageState.androidPackage 140 if (androidPackage == null || androidPackage.volumeUuid != volumeUuid) { 141 return@forEach 142 } 143 adoptPermissions(packageState, changedPermissionNames) 144 addPermissionGroups(packageState) 145 addPermissions(packageState, changedPermissionNames) 146 trimPermissions(packageState.packageName, changedPermissionNames) 147 trimPermissionStates(packageState.appId) 148 revokePermissionsOnPackageUpdate(packageState.appId) 149 } 150 changedPermissionNames.forEachIndexed { _, permissionName -> 151 evaluatePermissionStateForAllPackages(permissionName, null) 152 } 153 154 newState.systemState.packageStates.forEach { (_, packageState) -> 155 val androidPackage = packageState.androidPackage 156 if (androidPackage == null || androidPackage.volumeUuid != volumeUuid) { 157 return@forEach 158 } 159 val installedPackageState = if (isSystemUpdated) packageState else null 160 evaluateAllPermissionStatesForPackage(packageState, installedPackageState) 161 } 162 newState.systemState.packageStates.forEach { (_, packageState) -> 163 val androidPackage = packageState.androidPackage 164 if (androidPackage == null || androidPackage.volumeUuid != volumeUuid) { 165 return@forEach 166 } 167 newState.systemState.userIds.forEachIndexed { _, userId -> 168 inheritImplicitPermissionStates(packageState.appId, userId) 169 } 170 } 171 } 172 173 override fun MutateStateScope.onPackageAdded(packageState: PackageState) { 174 val changedPermissionNames = IndexedSet<String>() 175 adoptPermissions(packageState, changedPermissionNames) 176 addPermissionGroups(packageState) 177 addPermissions(packageState, changedPermissionNames) 178 // TODO: revokeSystemAlertWindowIfUpgradedPast23() 179 trimPermissions(packageState.packageName, changedPermissionNames) 180 trimPermissionStates(packageState.appId) 181 revokePermissionsOnPackageUpdate(packageState.appId) 182 changedPermissionNames.forEachIndexed { _, permissionName -> 183 evaluatePermissionStateForAllPackages(permissionName, null) 184 } 185 evaluateAllPermissionStatesForPackage(packageState, packageState) 186 newState.systemState.userIds.forEachIndexed { _, userId -> 187 inheritImplicitPermissionStates(packageState.appId, userId) 188 } 189 } 190 191 override fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) { 192 // TODO: STOPSHIP: Remove this check or at least turn into logging. 193 check(packageName !in newState.systemState.disabledSystemPackageStates) { 194 "Package $packageName reported as removed before disabled system package is enabled" 195 } 196 197 val changedPermissionNames = IndexedSet<String>() 198 trimPermissions(packageName, changedPermissionNames) 199 if (appId in newState.systemState.appIds) { 200 trimPermissionStates(appId) 201 } 202 changedPermissionNames.forEachIndexed { _, permissionName -> 203 evaluatePermissionStateForAllPackages(permissionName, null) 204 } 205 } 206 207 override fun MutateStateScope.onPackageUninstalled( 208 packageName: String, 209 appId: Int, 210 userId: Int 211 ) { 212 resetRuntimePermissions(packageName, appId, userId) 213 } 214 215 fun MutateStateScope.resetRuntimePermissions( 216 packageName: String, 217 appId: Int, 218 userId: Int 219 ) { 220 val androidPackage = newState.systemState.packageStates[packageName]?.androidPackage 221 ?: return 222 androidPackage.requestedPermissions.forEachIndexed { _, permissionName -> 223 val permission = newState.systemState.permissions[permissionName] 224 ?: return@forEachIndexed 225 if (permission.isRemoved) { 226 return@forEachIndexed 227 } 228 val isRequestedByOtherPackages = anyRequestingPackageInAppId(appId, permissionName) { 229 it.packageName != packageName 230 } 231 if (isRequestedByOtherPackages) { 232 return@forEachIndexed 233 } 234 val oldFlags = getPermissionFlags(appId, userId, permissionName) 235 if (oldFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK)) { 236 return@forEachIndexed 237 } 238 var newFlags = oldFlags 239 newFlags = if ( 240 newFlags.hasBits(PermissionFlags.ROLE) || newFlags.hasBits(PermissionFlags.PREGRANT) 241 ) { 242 newFlags or PermissionFlags.RUNTIME_GRANTED 243 } else { 244 newFlags andInv PermissionFlags.RUNTIME_GRANTED 245 } 246 newFlags = newFlags andInv USER_SETTABLE_MASK 247 if (newFlags.hasBits(PermissionFlags.LEGACY_GRANTED)) { 248 newFlags = newFlags or PermissionFlags.IMPLICIT 249 } 250 setPermissionFlags(appId, userId, permissionName, newFlags) 251 } 252 } 253 254 private fun MutateStateScope.adoptPermissions( 255 packageState: PackageState, 256 changedPermissionNames: IndexedSet<String> 257 ) { 258 val `package` = packageState.androidPackage!! 259 `package`.adoptPermissions.forEachIndexed { _, originalPackageName -> 260 val packageName = `package`.packageName 261 if (!canAdoptPermissions(packageName, originalPackageName)) { 262 return@forEachIndexed 263 } 264 val systemState = newState.systemState 265 val permissions = systemState.permissions 266 permissions.forEachIndexed permissions@ { 267 permissionIndex, permissionName, oldPermission -> 268 if (oldPermission.packageName != originalPackageName) { 269 return@permissions 270 } 271 @Suppress("DEPRECATION") 272 val newPermissionInfo = PermissionInfo().apply { 273 name = oldPermission.permissionInfo.name 274 this.packageName = packageName 275 protectionLevel = oldPermission.permissionInfo.protectionLevel 276 } 277 // Different from the old implementation, which removes the GIDs upon permission 278 // adoption, but adds them back on the next boot, we now just consistently keep the 279 // GIDs. 280 val newPermission = oldPermission.copy( 281 permissionInfo = newPermissionInfo, isReconciled = false, appId = 0 282 ) 283 permissions.setValueAt(permissionIndex, newPermission) 284 systemState.requestWrite() 285 changedPermissionNames += permissionName 286 } 287 } 288 } 289 290 private fun MutateStateScope.canAdoptPermissions( 291 packageName: String, 292 originalPackageName: String 293 ): Boolean { 294 val originalPackageState = newState.systemState.packageStates[originalPackageName] 295 ?: return false 296 if (!originalPackageState.isSystem) { 297 Log.w( 298 LOG_TAG, "Unable to adopt permissions from $originalPackageName to $packageName:" + 299 " original package not in system partition" 300 ) 301 return false 302 } 303 if (originalPackageState.androidPackage != null) { 304 Log.w( 305 LOG_TAG, "Unable to adopt permissions from $originalPackageName to $packageName:" + 306 " original package still exists" 307 ) 308 return false 309 } 310 return true 311 } 312 313 private fun MutateStateScope.addPermissionGroups(packageState: PackageState) { 314 // Different from the old implementation, which decides whether the app is an instant app by 315 // the install flags, now for consistent behavior we allow adding permission groups if the 316 // app is non-instant in at least one user. 317 val isInstantApp = packageState.userStates.allIndexed { _, _, it -> it.isInstantApp } 318 if (isInstantApp) { 319 Log.w( 320 LOG_TAG, "Ignoring permission groups declared in package" + 321 " ${packageState.packageName}: instant apps cannot declare permission groups" 322 ) 323 return 324 } 325 packageState.androidPackage!!.permissionGroups.forEachIndexed { _, parsedPermissionGroup -> 326 val newPermissionGroup = PackageInfoUtils.generatePermissionGroupInfo( 327 parsedPermissionGroup, PackageManager.GET_META_DATA.toLong() 328 )!! 329 // TODO: Clear permission state on group take-over? 330 val permissionGroupName = newPermissionGroup.name 331 val oldPermissionGroup = newState.systemState.permissionGroups[permissionGroupName] 332 if (oldPermissionGroup != null && 333 newPermissionGroup.packageName != oldPermissionGroup.packageName) { 334 val newPackageName = newPermissionGroup.packageName 335 val oldPackageName = oldPermissionGroup.packageName 336 // Different from the old implementation, which defines permission group on 337 // a first-come-first-serve basis, and relies on system apps being scanned before 338 // non-system apps, we now allow system apps to override permission groups similar 339 // to permissions so that we no longer need to rely on the scan order. 340 if (!packageState.isSystem) { 341 Log.w( 342 LOG_TAG, "Ignoring permission group $permissionGroupName declared in" + 343 " package $newPackageName: already declared in another" + 344 " package $oldPackageName" 345 ) 346 return@forEachIndexed 347 } 348 if (newState.systemState.packageStates[oldPackageName]?.isSystem == true) { 349 Log.w( 350 LOG_TAG, "Ignoring permission group $permissionGroupName declared in" + 351 " system package $newPackageName: already declared in another" + 352 " system package $oldPackageName" 353 ) 354 return@forEachIndexed 355 } 356 Log.w( 357 LOG_TAG, "Overriding permission group $permissionGroupName with" + 358 " new declaration in system package $newPackageName: originally" + 359 " declared in another package $oldPackageName" 360 ) 361 } 362 newState.systemState.permissionGroups[permissionGroupName] = newPermissionGroup 363 } 364 } 365 366 private fun MutateStateScope.addPermissions( 367 packageState: PackageState, 368 changedPermissionNames: IndexedSet<String> 369 ) { 370 packageState.androidPackage!!.permissions.forEachIndexed { _, parsedPermission -> 371 // TODO: 372 // parsedPermission.flags = parsedPermission.flags andInv PermissionInfo.FLAG_INSTALLED 373 // TODO: This seems actually unused. 374 // if (packageState.androidPackage.targetSdkVersion > Build.VERSION_CODES.LOLLIPOP_MR1) { 375 // parsedPermission.setParsedPermissionGroup( 376 // newState.systemState.permissionGroup[parsedPermission.group] 377 // ) 378 // } 379 val newPermissionInfo = PackageInfoUtils.generatePermissionInfo( 380 parsedPermission, PackageManager.GET_META_DATA.toLong() 381 )!! 382 // TODO: newPermissionInfo.flags |= PermissionInfo.FLAG_INSTALLED 383 val systemState = newState.systemState 384 val permissionName = newPermissionInfo.name 385 val oldPermission = if (parsedPermission.isTree) { 386 systemState.permissionTrees[permissionName] 387 } else { 388 systemState.permissions[permissionName] 389 } 390 // Different from the old implementation, which may add an (incomplete) signature 391 // permission inside another package's permission tree, we now consistently ignore such 392 // permissions. 393 val permissionTree = findPermissionTree(permissionName) 394 val newPackageName = newPermissionInfo.packageName 395 if (permissionTree != null && newPackageName != permissionTree.packageName) { 396 Log.w( 397 LOG_TAG, "Ignoring permission $permissionName declared in package" + 398 " $newPackageName: base permission tree ${permissionTree.name} is" + 399 " declared in another package ${permissionTree.packageName}" 400 ) 401 return@forEachIndexed 402 } 403 val newPermission = if (oldPermission != null && 404 newPackageName != oldPermission.packageName) { 405 val oldPackageName = oldPermission.packageName 406 // Only allow system apps to redefine non-system permissions. 407 if (!packageState.isSystem) { 408 Log.w( 409 LOG_TAG, "Ignoring permission $permissionName declared in package" + 410 " $newPackageName: already declared in another package" + 411 " $oldPackageName" 412 ) 413 return@forEachIndexed 414 } 415 if (oldPermission.type == Permission.TYPE_CONFIG && !oldPermission.isReconciled) { 416 // It's a config permission and has no owner, take ownership now. 417 oldPermission.copy( 418 permissionInfo = newPermissionInfo, isReconciled = true, 419 appId = packageState.appId 420 ) 421 } else if (systemState.packageStates[oldPackageName]?.isSystem != true) { 422 Log.w( 423 LOG_TAG, "Overriding permission $permissionName with new declaration in" + 424 " system package $newPackageName: originally declared in another" + 425 " package $oldPackageName" 426 ) 427 // Remove permission state on owner change. 428 systemState.userIds.forEachIndexed { _, userId -> 429 systemState.appIds.forEachKeyIndexed { _, appId -> 430 setPermissionFlags(appId, userId, permissionName, 0) 431 } 432 } 433 // Different from the old implementation, which removes the GIDs upon permission 434 // override, but adds them back on the next boot, we now just consistently keep 435 // the GIDs. 436 Permission( 437 newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId, 438 oldPermission.gids, oldPermission.areGidsPerUser 439 ) 440 } else { 441 Log.w( 442 LOG_TAG, "Ignoring permission $permissionName declared in system package" + 443 " $newPackageName: already declared in another system package" + 444 " $oldPackageName" 445 ) 446 return@forEachIndexed 447 } 448 } else { 449 if (oldPermission != null) { 450 val isPermissionGroupChanged = newPermissionInfo.isRuntime && 451 newPermissionInfo.group != null && 452 newPermissionInfo.group != oldPermission.groupName 453 val isPermissionTypeChanged = oldPermission.type != Permission.TYPE_CONFIG && ( 454 (newPermissionInfo.isRuntime && !oldPermission.isRuntime) || 455 (newPermissionInfo.isInternal && !oldPermission.isInternal) 456 ) 457 if (isPermissionGroupChanged || isPermissionTypeChanged) { 458 systemState.userIds.forEachIndexed { _, userId -> 459 systemState.appIds.forEachKeyIndexed { _, appId -> 460 if (isPermissionGroupChanged) { 461 // We might auto-grant permissions if any permission of 462 // the group is already granted. Hence if the group of 463 // a granted permission changes we need to revoke it to 464 // avoid having permissions of the new group auto-granted. 465 Log.w( 466 LOG_TAG, "Revoking runtime permission $permissionName for" + 467 " appId $appId and userId $userId as the permission" + 468 " group changed from ${oldPermission.groupName}" + 469 " to ${newPermissionInfo.group}" 470 ) 471 } 472 if (isPermissionTypeChanged) { 473 Log.w( 474 LOG_TAG, "Revoking permission $permissionName for" + 475 " appId $appId and userId $userId as the permission" + 476 " type changed." 477 ) 478 } 479 setPermissionFlags(appId, userId, permissionName, 0) 480 } 481 } 482 } 483 } 484 485 // Different from the old implementation, which doesn't update the permission 486 // definition upon app update, but does update it on the next boot, we now 487 // consistently update the permission definition upon app update. 488 @Suppress("IfThenToElvis") 489 if (oldPermission != null) { 490 oldPermission.copy( 491 permissionInfo = newPermissionInfo, isReconciled = true, 492 appId = packageState.appId 493 ) 494 } else { 495 Permission( 496 newPermissionInfo, true, Permission.TYPE_MANIFEST, packageState.appId 497 ) 498 } 499 } 500 501 if (parsedPermission.isTree) { 502 systemState.permissionTrees[permissionName] = newPermission 503 } else { 504 systemState.permissions[permissionName] = newPermission 505 } 506 systemState.requestWrite() 507 changedPermissionNames += permissionName 508 } 509 } 510 511 private fun MutateStateScope.trimPermissions( 512 packageName: String, 513 changedPermissionNames: IndexedSet<String> 514 ) { 515 val systemState = newState.systemState 516 val packageState = systemState.packageStates[packageName] 517 val androidPackage = packageState?.androidPackage 518 if (packageState != null && androidPackage == null) { 519 return 520 } 521 val disabledSystemPackage = systemState.disabledSystemPackageStates[packageName] 522 ?.androidPackage 523 // Unlike in the previous implementation, we now also retain permission trees defined by 524 // disabled system packages for consistency with permissions. 525 val isPermissionTreeRemoved = systemState.permissionTrees.removeAllIndexed { 526 _, permissionTreeName, permissionTree -> 527 permissionTree.packageName == packageName && ( 528 packageState == null || androidPackage!!.permissions.noneIndexed { _, it -> 529 it.isTree && it.name == permissionTreeName 530 } 531 ) && ( 532 disabledSystemPackage?.permissions?.anyIndexed { _, it -> 533 it.isTree && it.name == permissionTreeName 534 } != true 535 ) 536 } 537 if (isPermissionTreeRemoved) { 538 systemState.requestWrite() 539 } 540 541 systemState.permissions.removeAllIndexed { permissionIndex, permissionName, permission -> 542 val updatedPermission = updatePermissionIfDynamic(permission) 543 newState.systemState.permissions.setValueAt(permissionIndex, updatedPermission) 544 if (updatedPermission.packageName == packageName && ( 545 packageState == null || androidPackage!!.permissions.noneIndexed { _, it -> 546 !it.isTree && it.name == permissionName 547 } 548 ) && ( 549 disabledSystemPackage?.permissions?.anyIndexed { _, it -> 550 !it.isTree && it.name == permissionName 551 } != true 552 )) { 553 // Different from the old implementation where we keep the permission state if the 554 // permission is declared by a disabled system package (ag/15189282), we now 555 // shouldn't be notified when the updated system package is removed but the disabled 556 // system package isn't re-enabled yet, so we don't need to maintain that brittle 557 // special case either. 558 systemState.userIds.forEachIndexed { _, userId -> 559 systemState.appIds.forEachKeyIndexed { _, appId -> 560 setPermissionFlags(appId, userId, permissionName, 0) 561 } 562 } 563 changedPermissionNames += permissionName 564 systemState.requestWrite() 565 true 566 } else { 567 false 568 } 569 } 570 } 571 572 private fun MutateStateScope.updatePermissionIfDynamic(permission: Permission): Permission { 573 if (!permission.isDynamic) { 574 return permission 575 } 576 val permissionTree = findPermissionTree(permission.name) ?: return permission 577 @Suppress("DEPRECATION") 578 return permission.copy( 579 permissionInfo = PermissionInfo(permission.permissionInfo).apply { 580 packageName = permissionTree.packageName 581 }, appId = permissionTree.appId, isReconciled = true 582 ) 583 } 584 585 private fun MutateStateScope.trimPermissionStates(appId: Int) { 586 val requestedPermissions = IndexedSet<String>() 587 forEachPackageInAppId(appId) { 588 // Note that we still trim the permission states requested by disabled system packages. 589 // Because in the previous implementation: 590 // despite revokeSharedUserPermissionsForLeavingPackageInternal() retains permissions 591 // requested by disabled system packages, revokeUnusedSharedUserPermissionsLocked(), 592 // which is call upon app update installation, didn't do such preservation. 593 // Hence, permissions only requested by disabled system packages were still trimmed in 594 // the previous implementation. 595 requestedPermissions += it.androidPackage!!.requestedPermissions 596 } 597 newState.userStates.forEachIndexed { _, userId, userState -> 598 userState.uidPermissionFlags[appId]?.forEachReversedIndexed { _, permissionName, _ -> 599 if (permissionName !in requestedPermissions) { 600 setPermissionFlags(appId, userId, permissionName, 0) 601 } 602 } 603 } 604 } 605 606 private fun MutateStateScope.revokePermissionsOnPackageUpdate(appId: Int) { 607 // If the app is updated, and has scoped storage permissions, then it is possible that the 608 // app updated in an attempt to get unscoped storage. If so, revoke all storage permissions. 609 newState.userStates.forEachIndexed { _, userId, userState -> 610 userState.uidPermissionFlags[appId]?.forEachReversedIndexed { 611 _, permissionName, oldFlags -> 612 if (permissionName !in STORAGE_AND_MEDIA_PERMISSIONS || oldFlags == 0) { 613 return@forEachReversedIndexed 614 } 615 val oldTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, oldState) 616 val newTargetSdkVersion = getAppIdTargetSdkVersion(appId, permissionName, newState) 617 val isTargetSdkVersionDowngraded = oldTargetSdkVersion >= Build.VERSION_CODES.Q && 618 newTargetSdkVersion < Build.VERSION_CODES.Q 619 val isTargetSdkVersionUpgraded = oldTargetSdkVersion < Build.VERSION_CODES.Q && 620 newTargetSdkVersion >= Build.VERSION_CODES.Q 621 val oldIsRequestLegacyExternalStorage = anyRequestingPackageInAppId( 622 appId, permissionName, oldState 623 ) { it.androidPackage!!.isRequestLegacyExternalStorage } 624 val newIsRequestLegacyExternalStorage = anyRequestingPackageInAppId( 625 appId, permissionName, newState 626 ) { it.androidPackage!!.isRequestLegacyExternalStorage } 627 val isNewlyRequestingLegacyExternalStorage = !isTargetSdkVersionUpgraded && 628 !oldIsRequestLegacyExternalStorage && newIsRequestLegacyExternalStorage 629 if ((isNewlyRequestingLegacyExternalStorage || isTargetSdkVersionDowngraded) && 630 oldFlags.hasBits(PermissionFlags.RUNTIME_GRANTED)) { 631 val newFlags = oldFlags andInv ( 632 PermissionFlags.RUNTIME_GRANTED or USER_SETTABLE_MASK 633 ) 634 setPermissionFlags(appId, userId, permissionName, newFlags) 635 } 636 } 637 } 638 } 639 640 private fun MutateStateScope.evaluatePermissionStateForAllPackages( 641 permissionName: String, 642 installedPackageState: PackageState? 643 ) { 644 val systemState = newState.systemState 645 systemState.userIds.forEachIndexed { _, userId -> 646 systemState.appIds.forEachKeyIndexed { _, appId -> 647 val isPermissionRequested = 648 anyRequestingPackageInAppId(appId, permissionName) { true } 649 if (isPermissionRequested) { 650 evaluatePermissionState(appId, userId, permissionName, installedPackageState) 651 } 652 } 653 } 654 } 655 656 private fun MutateStateScope.evaluateAllPermissionStatesForPackage( 657 packageState: PackageState, 658 installedPackageState: PackageState? 659 ) { 660 newState.systemState.userIds.forEachIndexed { _, userId -> 661 evaluateAllPermissionStatesForPackageAndUser( 662 packageState, userId, installedPackageState 663 ) 664 } 665 } 666 667 private fun MutateStateScope.evaluateAllPermissionStatesForPackageAndUser( 668 packageState: PackageState, 669 userId: Int, 670 installedPackageState: PackageState? 671 ) { 672 packageState.androidPackage?.requestedPermissions?.forEachIndexed { _, permissionName -> 673 evaluatePermissionState( 674 packageState.appId, userId, permissionName, installedPackageState 675 ) 676 } 677 } 678 679 private fun MutateStateScope.evaluatePermissionState( 680 appId: Int, 681 userId: Int, 682 permissionName: String, 683 installedPackageState: PackageState? 684 ) { 685 val packageNames = newState.systemState.appIds[appId] 686 val hasMissingPackage = packageNames.anyIndexed { _, packageName -> 687 newState.systemState.packageStates[packageName]!!.androidPackage == null 688 } 689 if (packageNames.size == 1 && hasMissingPackage) { 690 // For non-shared-user packages with missing androidPackage, skip evaluation. 691 return 692 } 693 val permission = newState.systemState.permissions[permissionName] 694 val oldFlags = getPermissionFlags(appId, userId, permissionName) 695 if (permission == null) { 696 if (oldFlags == 0) { 697 // If the permission definition is missing and we don't have any permission states 698 // for this permission, add the INSTALL_REVOKED flag to ensure that we don't 699 // automatically grant the permission when it's defined 700 setPermissionFlags(appId, userId, permissionName, PermissionFlags.INSTALL_REVOKED) 701 } 702 return 703 } 704 if (permission.isNormal) { 705 val wasGranted = oldFlags.hasBits(PermissionFlags.INSTALL_GRANTED) 706 if (!wasGranted) { 707 val wasRevoked = oldFlags.hasBits(PermissionFlags.INSTALL_REVOKED) 708 val isRequestedByInstalledPackage = installedPackageState != null && 709 permissionName in installedPackageState.androidPackage!!.requestedPermissions 710 val isRequestedBySystemPackage = 711 anyRequestingPackageInAppId(appId, permissionName) { it.isSystem } 712 val isCompatibilityPermission = anyRequestingPackageInAppId(appId, permissionName) { 713 isCompatibilityPermissionForPackage(it.androidPackage!!, permissionName) 714 } 715 // If this is an existing, non-system package, 716 // then we can't add any new permissions to it. 717 // Except if this is a permission that was added to the platform 718 val newFlags = if (!wasRevoked || isRequestedByInstalledPackage || 719 isRequestedBySystemPackage || isCompatibilityPermission) { 720 PermissionFlags.INSTALL_GRANTED 721 } else { 722 PermissionFlags.INSTALL_REVOKED 723 } 724 setPermissionFlags(appId, userId, permissionName, newFlags) 725 } 726 } else if (permission.isSignature || permission.isInternal) { 727 val wasProtectionGranted = oldFlags.hasBits(PermissionFlags.PROTECTION_GRANTED) 728 var newFlags = if (hasMissingPackage && wasProtectionGranted) { 729 // Keep the non-runtime permission grants for shared UID with missing androidPackage 730 PermissionFlags.PROTECTION_GRANTED 731 } else { 732 val mayGrantByPrivileged = !permission.isPrivileged || ( 733 anyRequestingPackageInAppId(appId, permissionName) { 734 checkPrivilegedPermissionAllowlist(it, permission) 735 } 736 ) 737 val shouldGrantBySignature = permission.isSignature && ( 738 anyRequestingPackageInAppId(appId, permissionName) { 739 shouldGrantPermissionBySignature(it, permission) 740 } 741 ) 742 val shouldGrantByProtectionFlags = 743 anyRequestingPackageInAppId(appId, permissionName) { 744 shouldGrantPermissionByProtectionFlags(it, permission) 745 } 746 if (mayGrantByPrivileged && 747 (shouldGrantBySignature || shouldGrantByProtectionFlags)) { 748 PermissionFlags.PROTECTION_GRANTED 749 } else { 750 0 751 } 752 } 753 // Different from the old implementation, which seemingly allows granting an 754 // unallowlisted privileged permission via development or role but revokes it upon next 755 // reconciliation, we now properly allows that because the privileged protection flag 756 // should only affect the other static flags, but not dynamic flags like development or 757 // role. This may be useful in the case of an updated system app. 758 if (permission.isDevelopment) { 759 newFlags = newFlags or (oldFlags and PermissionFlags.RUNTIME_GRANTED) 760 } 761 if (permission.isRole) { 762 newFlags = newFlags or ( 763 oldFlags and (PermissionFlags.ROLE or PermissionFlags.RUNTIME_GRANTED) 764 ) 765 } 766 setPermissionFlags(appId, userId, permissionName, newFlags) 767 } else if (permission.isRuntime) { 768 var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME 769 if (getAppIdTargetSdkVersion(appId, permissionName) < Build.VERSION_CODES.M) { 770 if (permission.isRuntimeOnly) { 771 // Different from the old implementation, which simply skips a runtime-only 772 // permission, we now only allow holding on to the restriction related flags, 773 // since such flags may only be set one-time in some cases, and disallow all 774 // other flags thus keeping it revoked. 775 newFlags = newFlags and PermissionFlags.MASK_EXEMPT 776 } else { 777 newFlags = newFlags or PermissionFlags.LEGACY_GRANTED 778 // Explicitly check against the old state to determine if this permission is 779 // new. 780 val isNewPermission = 781 getOldStatePermissionFlags(appId, userId, permissionName) == 0 782 if (isNewPermission) { 783 newFlags = newFlags or PermissionFlags.IMPLICIT 784 } 785 } 786 } else { 787 val wasGrantedByLegacy = newFlags.hasBits(PermissionFlags.LEGACY_GRANTED) 788 newFlags = newFlags andInv PermissionFlags.LEGACY_GRANTED 789 val wasGrantedByImplicit = newFlags.hasBits(PermissionFlags.IMPLICIT_GRANTED) 790 val isLeanbackNotificationsPermission = newState.systemState.isLeanback && 791 permissionName in NOTIFICATIONS_PERMISSIONS 792 val isImplicitPermission = anyRequestingPackageInAppId(appId, permissionName) { 793 permissionName in it.androidPackage!!.implicitPermissions 794 } 795 val sourcePermissions = newState.systemState 796 .implicitToSourcePermissions[permissionName] 797 val isAnySourcePermissionNonRuntime = sourcePermissions?.any { 798 val sourcePermission = newState.systemState.permissions[it] 799 checkNotNull(sourcePermission) { 800 "Unknown source permission $it in split permissions" 801 } 802 !sourcePermission.isRuntime 803 } ?: false 804 val shouldGrantByImplicit = isLeanbackNotificationsPermission || 805 (isImplicitPermission && isAnySourcePermissionNonRuntime) 806 if (shouldGrantByImplicit) { 807 newFlags = newFlags or PermissionFlags.IMPLICIT_GRANTED 808 } else { 809 newFlags = newFlags andInv PermissionFlags.IMPLICIT_GRANTED 810 } 811 if ((wasGrantedByLegacy || wasGrantedByImplicit) && !shouldGrantByImplicit) { 812 // The permission was granted from a compatibility grant or an implicit grant, 813 // however this flag might still be set if the user denied this permission in 814 // the settings. Hence upon app upgrade and when this permission is no longer 815 // LEGACY_GRANTED or IMPLICIT_GRANTED and we revoke the permission, we want to 816 // remove this flag so that the app can request the permission again. 817 newFlags = newFlags andInv PermissionFlags.APP_OP_REVOKED 818 } 819 val hasImplicitFlag = newFlags.hasBits(PermissionFlags.IMPLICIT) 820 if (!isImplicitPermission && hasImplicitFlag) { 821 newFlags = newFlags andInv PermissionFlags.IMPLICIT 822 var shouldRetainAsNearbyDevices = false 823 if (permissionName in NEARBY_DEVICES_PERMISSIONS) { 824 val accessBackgroundLocationFlags = getPermissionFlags( 825 appId, userId, Manifest.permission.ACCESS_BACKGROUND_LOCATION 826 ) 827 shouldRetainAsNearbyDevices = 828 PermissionFlags.isAppOpGranted(accessBackgroundLocationFlags) && 829 !accessBackgroundLocationFlags.hasBits(PermissionFlags.IMPLICIT) 830 } 831 val shouldRetainByMask = newFlags.hasAnyBit(SYSTEM_OR_POLICY_FIXED_MASK) 832 if (shouldRetainAsNearbyDevices || shouldRetainByMask) { 833 if (wasGrantedByImplicit) { 834 newFlags = newFlags or PermissionFlags.RUNTIME_GRANTED 835 } 836 } else { 837 newFlags = newFlags andInv ( 838 PermissionFlags.RUNTIME_GRANTED or PermissionFlags.USER_SET or 839 PermissionFlags.USER_FIXED 840 ) 841 } 842 } 843 } 844 845 val isExempt = newFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT) 846 val isHardRestricted = permission.isHardRestricted && !isExempt 847 newFlags = if (isHardRestricted) { 848 newFlags or PermissionFlags.RESTRICTION_REVOKED 849 } else { 850 newFlags andInv PermissionFlags.RESTRICTION_REVOKED 851 } 852 val isSoftRestricted = permission.isSoftRestricted && !isExempt 853 newFlags = if (isSoftRestricted) { 854 newFlags or PermissionFlags.SOFT_RESTRICTED 855 } else { 856 newFlags andInv PermissionFlags.SOFT_RESTRICTED 857 } 858 setPermissionFlags(appId, userId, permissionName, newFlags) 859 } else { 860 Log.e(LOG_TAG, "Unknown protection level ${permission.protectionLevel}" + 861 "for permission ${permission.name} while evaluating permission state" + 862 "for appId $appId and userId $userId") 863 } 864 } 865 866 private fun MutateStateScope.inheritImplicitPermissionStates(appId: Int, userId: Int) { 867 val implicitPermissions = IndexedSet<String>() 868 forEachPackageInAppId(appId) { 869 implicitPermissions += it.androidPackage!!.implicitPermissions 870 } 871 implicitPermissions.forEachIndexed implicitPermissions@ { _, implicitPermissionName -> 872 val implicitPermission = newState.systemState.permissions[implicitPermissionName] 873 checkNotNull(implicitPermission) { 874 "Unknown implicit permission $implicitPermissionName in split permissions" 875 } 876 if (!implicitPermission.isRuntime) { 877 return@implicitPermissions 878 } 879 // Explicitly check against the old state to determine if this permission is new. 880 val isNewPermission = 881 getOldStatePermissionFlags(appId, userId, implicitPermissionName) == 0 882 if (!isNewPermission) { 883 return@implicitPermissions 884 } 885 val sourcePermissions = newState.systemState 886 .implicitToSourcePermissions[implicitPermissionName] ?: return@implicitPermissions 887 var newFlags = getPermissionFlags(appId, userId, implicitPermissionName) 888 sourcePermissions.forEachIndexed sourcePermissions@ { _, sourcePermissionName -> 889 val sourcePermission = newState.systemState.permissions[sourcePermissionName] 890 checkNotNull(sourcePermission) { 891 "Unknown source permission $sourcePermissionName in split permissions" 892 } 893 val sourceFlags = getPermissionFlags(appId, userId, sourcePermissionName) 894 val isSourceGranted = PermissionFlags.isPermissionGranted(sourceFlags) 895 val isNewGranted = PermissionFlags.isPermissionGranted(newFlags) 896 val isGrantingNewFromRevoke = isSourceGranted && !isNewGranted 897 if (isSourceGranted == isNewGranted || isGrantingNewFromRevoke) { 898 if (isGrantingNewFromRevoke) { 899 newFlags = 0 900 } 901 newFlags = newFlags or (sourceFlags and PermissionFlags.MASK_RUNTIME) 902 } 903 } 904 if (implicitPermissionName in RETAIN_IMPLICIT_FLAGS_PERMISSIONS) { 905 newFlags = newFlags andInv PermissionFlags.IMPLICIT 906 } else { 907 newFlags = newFlags or PermissionFlags.IMPLICIT 908 } 909 setPermissionFlags(appId, userId, implicitPermissionName, newFlags) 910 } 911 } 912 913 private fun isCompatibilityPermissionForPackage( 914 androidPackage: AndroidPackage, 915 permissionName: String 916 ): Boolean { 917 for (compatibilityPermission in CompatibilityPermissionInfo.COMPAT_PERMS) { 918 if (compatibilityPermission.name == permissionName && 919 androidPackage.targetSdkVersion < compatibilityPermission.sdkVersion) { 920 Log.i( 921 LOG_TAG, "Auto-granting $permissionName to old package" + 922 " ${androidPackage.packageName}" 923 ) 924 return true 925 } 926 } 927 return false 928 } 929 930 private fun MutateStateScope.shouldGrantPermissionBySignature( 931 packageState: PackageState, 932 permission: Permission 933 ): Boolean { 934 // Check if the package is allowed to use this signature permission. A package is allowed 935 // to use a signature permission if: 936 // - it has the same set of signing certificates as the source package 937 // - or its signing certificate was rotated from the source package's certificate 938 // - or its signing certificate is a previous signing certificate of the defining 939 // package, and the defining package still trusts the old certificate for permissions 940 // - or it shares a common signing certificate in its lineage with the defining package, 941 // and the defining package still trusts the old certificate for permissions 942 // - or it shares the above relationships with the system package 943 val packageSigningDetails = packageState.androidPackage!!.signingDetails 944 val sourceSigningDetails = newState.systemState 945 .packageStates[permission.packageName]?.androidPackage?.signingDetails 946 val platformSigningDetails = newState.systemState 947 .packageStates[PLATFORM_PACKAGE_NAME]!!.androidPackage!!.signingDetails 948 return sourceSigningDetails?.hasCommonSignerWithCapability(packageSigningDetails, 949 SigningDetails.CertCapabilities.PERMISSION) == true || 950 packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) || 951 platformSigningDetails.checkCapability(packageSigningDetails, 952 SigningDetails.CertCapabilities.PERMISSION) 953 } 954 955 private fun MutateStateScope.checkPrivilegedPermissionAllowlist( 956 packageState: PackageState, 957 permission: Permission 958 ): Boolean { 959 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_DISABLE) { 960 return true 961 } 962 if (packageState.packageName == PLATFORM_PACKAGE_NAME) { 963 return true 964 } 965 if (!(packageState.isSystem && packageState.isPrivileged)) { 966 return true 967 } 968 if (permission.packageName !in newState.systemState.privilegedPermissionAllowlistPackages) { 969 return true 970 } 971 val allowlistState = getPrivilegedPermissionAllowlistState(packageState, permission.name) 972 if (allowlistState != null) { 973 return allowlistState 974 } 975 // Updated system apps do not need to be allowlisted 976 if (packageState.isUpdatedSystemApp) { 977 return true 978 } 979 // Only enforce the privileged permission allowlist on boot 980 if (!newState.systemState.isSystemReady) { 981 // Apps that are in updated apex's do not need to be allowlisted 982 if (!packageState.isApkInUpdatedApex) { 983 Log.w( 984 LOG_TAG, "Privileged permission ${permission.name} for package" + 985 " ${packageState.packageName} (${packageState.path}) not in" + 986 " privileged permission allowlist" 987 ) 988 if (RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE) { 989 privilegedPermissionAllowlistViolations += "${packageState.packageName}" + 990 " (${packageState.path}): ${permission.name}" 991 } 992 } 993 } 994 return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE 995 } 996 997 /** 998 * Get the whether a privileged permission is explicitly allowed or denied for a package in the 999 * allowlist, or `null` if it's not in the allowlist. 1000 */ 1001 private fun MutateStateScope.getPrivilegedPermissionAllowlistState( 1002 packageState: PackageState, 1003 permissionName: String 1004 ): Boolean? { 1005 val permissionAllowlist = newState.systemState.permissionAllowlist 1006 val apexModuleName = packageState.apexModuleName 1007 val packageName = packageState.packageName 1008 return when { 1009 packageState.isVendor -> permissionAllowlist.getVendorPrivilegedAppAllowlistState( 1010 packageName, permissionName 1011 ) 1012 packageState.isProduct -> permissionAllowlist.getProductPrivilegedAppAllowlistState( 1013 packageName, permissionName 1014 ) 1015 packageState.isSystemExt -> 1016 permissionAllowlist.getSystemExtPrivilegedAppAllowlistState( 1017 packageName, permissionName 1018 ) 1019 apexModuleName != null -> { 1020 val nonApexAllowlistState = permissionAllowlist.getPrivilegedAppAllowlistState( 1021 packageName, permissionName 1022 ) 1023 if (nonApexAllowlistState != null) { 1024 // TODO(andreionea): Remove check as soon as all apk-in-apex 1025 // permission allowlists are migrated. 1026 Log.w( 1027 LOG_TAG, "Package $packageName is an APK in APEX but has permission" + 1028 " allowlist on the system image, please bundle the allowlist in the" + 1029 " $apexModuleName APEX instead" 1030 ) 1031 } 1032 val apexAllowlistState = permissionAllowlist.getApexPrivilegedAppAllowlistState( 1033 apexModuleName, packageName, permissionName 1034 ) 1035 apexAllowlistState ?: nonApexAllowlistState 1036 } 1037 else -> permissionAllowlist.getPrivilegedAppAllowlistState(packageName, permissionName) 1038 } 1039 } 1040 1041 private fun MutateStateScope.getAppIdTargetSdkVersion( 1042 appId: Int, 1043 permissionName: String, 1044 state: AccessState = newState 1045 ): Int { 1046 var targetSdkVersion = Build.VERSION_CODES.CUR_DEVELOPMENT 1047 forEachRequestingPackageInAppId(appId, permissionName, state) { 1048 targetSdkVersion = targetSdkVersion.coerceAtMost(it.androidPackage!!.targetSdkVersion) 1049 } 1050 return targetSdkVersion 1051 } 1052 1053 private inline fun MutateStateScope.anyRequestingPackageInAppId( 1054 appId: Int, 1055 permissionName: String, 1056 state: AccessState = newState, 1057 predicate: (PackageState) -> Boolean 1058 ): Boolean { 1059 val packageNames = state.systemState.appIds[appId] 1060 return packageNames.anyIndexed { _, packageName -> 1061 val packageState = state.systemState.packageStates[packageName]!! 1062 val androidPackage = packageState.androidPackage 1063 androidPackage != null && permissionName in androidPackage.requestedPermissions && 1064 predicate(packageState) 1065 } 1066 } 1067 1068 private inline fun MutateStateScope.forEachPackageInAppId( 1069 appId: Int, 1070 state: AccessState = newState, 1071 action: (PackageState) -> Unit 1072 ) { 1073 val packageNames = state.systemState.appIds[appId]!! 1074 packageNames.forEachIndexed { _, packageName -> 1075 val packageState = state.systemState.packageStates[packageName]!! 1076 if (packageState.androidPackage != null) { 1077 action(packageState) 1078 } 1079 } 1080 } 1081 1082 private inline fun MutateStateScope.forEachRequestingPackageInAppId( 1083 appId: Int, 1084 permissionName: String, 1085 state: AccessState = newState, 1086 action: (PackageState) -> Unit 1087 ) { 1088 val packageNames = state.systemState.appIds[appId] 1089 packageNames.forEachIndexed { _, packageName -> 1090 val packageState = state.systemState.packageStates[packageName]!! 1091 val androidPackage = packageState.androidPackage 1092 if (androidPackage != null && permissionName in androidPackage.requestedPermissions) { 1093 action(packageState) 1094 } 1095 } 1096 } 1097 1098 private fun MutateStateScope.shouldGrantPermissionByProtectionFlags( 1099 packageState: PackageState, 1100 permission: Permission 1101 ): Boolean { 1102 val androidPackage = packageState.androidPackage!! 1103 val knownPackages = newState.systemState.knownPackages 1104 val packageName = packageState.packageName 1105 if ((permission.isPrivileged || permission.isOem) && packageState.isSystem) { 1106 val shouldGrant = if (packageState.isUpdatedSystemApp) { 1107 // For updated system applications, a privileged/oem permission 1108 // is granted only if it had been defined by the original application. 1109 val disabledSystemPackageState = newState.systemState 1110 .disabledSystemPackageStates[packageState.packageName] 1111 val disabledSystemPackage = disabledSystemPackageState?.androidPackage 1112 disabledSystemPackage != null && 1113 permission.name in disabledSystemPackage.requestedPermissions && 1114 shouldGrantPrivilegedOrOemPermission(disabledSystemPackageState, permission) 1115 } else { 1116 shouldGrantPrivilegedOrOemPermission(packageState, permission) 1117 } 1118 if (shouldGrant) { 1119 return true 1120 } 1121 } 1122 if (permission.isPre23 && androidPackage.targetSdkVersion < Build.VERSION_CODES.M) { 1123 // If this was a previously normal/dangerous permission that got moved 1124 // to a system permission as part of the runtime permission redesign, then 1125 // we still want to blindly grant it to old apps. 1126 return true 1127 } 1128 if (permission.isInstaller && ( 1129 packageName in knownPackages[KnownPackages.PACKAGE_INSTALLER] || 1130 packageName in knownPackages[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] 1131 )) { 1132 // If this permission is to be granted to the system installer and 1133 // this app is an installer or permission controller, then it gets the permission. 1134 return true 1135 } 1136 if (permission.isVerifier && 1137 packageName in knownPackages[KnownPackages.PACKAGE_VERIFIER]) { 1138 // If this permission is to be granted to the system verifier and 1139 // this app is a verifier, then it gets the permission. 1140 return true 1141 } 1142 if (permission.isPreInstalled && packageState.isSystem) { 1143 // Any pre-installed system app is allowed to get this permission. 1144 return true 1145 } 1146 if (permission.isKnownSigner && 1147 androidPackage.signingDetails.hasAncestorOrSelfWithDigest(permission.knownCerts)) { 1148 // If the permission is to be granted to a known signer then check if any of this 1149 // app's signing certificates are in the trusted certificate digest Set. 1150 return true 1151 } 1152 if (permission.isSetup && 1153 packageName in knownPackages[KnownPackages.PACKAGE_SETUP_WIZARD]) { 1154 // If this permission is to be granted to the system setup wizard and 1155 // this app is a setup wizard, then it gets the permission. 1156 return true 1157 } 1158 if (permission.isSystemTextClassifier && 1159 packageName in knownPackages[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER]) { 1160 // Special permissions for the system default text classifier. 1161 return true 1162 } 1163 if (permission.isConfigurator && 1164 packageName in knownPackages[KnownPackages.PACKAGE_CONFIGURATOR]) { 1165 // Special permissions for the device configurator. 1166 return true 1167 } 1168 if (permission.isIncidentReportApprover && 1169 packageName in knownPackages[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER]) { 1170 // If this permission is to be granted to the incident report approver and 1171 // this app is the incident report approver, then it gets the permission. 1172 return true 1173 } 1174 if (permission.isAppPredictor && 1175 packageName in knownPackages[KnownPackages.PACKAGE_APP_PREDICTOR]) { 1176 // Special permissions for the system app predictor. 1177 return true 1178 } 1179 if (permission.isCompanion && 1180 packageName in knownPackages[KnownPackages.PACKAGE_COMPANION]) { 1181 // Special permissions for the system companion device manager. 1182 return true 1183 } 1184 if (permission.isRetailDemo && 1185 packageName in knownPackages[KnownPackages.PACKAGE_RETAIL_DEMO] && 1186 isDeviceOrProfileOwnerUid(packageState.appId)) { 1187 // Special permission granted only to the OEM specified retail demo app. 1188 // Note that the original code was passing app ID as UID, so this behavior is kept 1189 // unchanged. 1190 return true 1191 } 1192 if (permission.isRecents && 1193 packageName in knownPackages[KnownPackages.PACKAGE_RECENTS]) { 1194 // Special permission for the recents app. 1195 return true 1196 } 1197 if (permission.isModule && packageState.apexModuleName != null) { 1198 // Special permission granted for APKs inside APEX modules. 1199 return true 1200 } 1201 return false 1202 } 1203 1204 private fun MutateStateScope.shouldGrantPrivilegedOrOemPermission( 1205 packageState: PackageState, 1206 permission: Permission 1207 ): Boolean { 1208 val permissionName = permission.name 1209 val packageName = packageState.packageName 1210 when { 1211 permission.isPrivileged -> { 1212 if (packageState.isPrivileged) { 1213 // In any case, don't grant a privileged permission to privileged vendor apps, 1214 // if the permission's protectionLevel does not have the extra vendorPrivileged 1215 // flag. 1216 if (packageState.isVendor && !permission.isVendorPrivileged) { 1217 Log.w( 1218 LOG_TAG, "Permission $permissionName cannot be granted to privileged" + 1219 " vendor app $packageName because it isn't a vendorPrivileged" + 1220 " permission" 1221 ) 1222 return false 1223 } 1224 return true 1225 } 1226 } 1227 permission.isOem -> { 1228 if (packageState.isOem) { 1229 val allowlistState = newState.systemState.permissionAllowlist 1230 .getOemAppAllowlistState(packageName, permissionName) 1231 checkNotNull(allowlistState) { 1232 "OEM permission $permissionName requested by package" + 1233 " $packageName must be explicitly declared granted or not" 1234 } 1235 return allowlistState 1236 } 1237 } 1238 } 1239 return false 1240 } 1241 1242 private fun MutateStateScope.isDeviceOrProfileOwnerUid(uid: Int): Boolean { 1243 val userId = UserHandle.getUserId(uid) 1244 val ownerPackageName = newState.systemState.deviceAndProfileOwners[userId] ?: return false 1245 val ownerPackageState = newState.systemState.packageStates[ownerPackageName] ?: return false 1246 val ownerUid = UserHandle.getUid(userId, ownerPackageState.appId) 1247 return uid == ownerUid 1248 } 1249 1250 override fun MutateStateScope.onSystemReady() { 1251 if (!privilegedPermissionAllowlistViolations.isEmpty()) { 1252 throw IllegalStateException("Signature|privileged permissions not in privileged" + 1253 " permission allowlist: $privilegedPermissionAllowlistViolations") 1254 } 1255 } 1256 1257 override fun BinaryXmlPullParser.parseSystemState(state: AccessState) { 1258 with(persistence) { this@parseSystemState.parseSystemState(state) } 1259 } 1260 1261 override fun BinaryXmlSerializer.serializeSystemState(state: AccessState) { 1262 with(persistence) { this@serializeSystemState.serializeSystemState(state) } 1263 } 1264 1265 override fun BinaryXmlPullParser.parseUserState(state: AccessState, userId: Int) { 1266 with(persistence) { this@parseUserState.parseUserState(state, userId) } 1267 } 1268 1269 override fun BinaryXmlSerializer.serializeUserState(state: AccessState, userId: Int) { 1270 with(persistence) { this@serializeUserState.serializeUserState(state, userId) } 1271 } 1272 1273 fun GetStateScope.getPermissionTrees(): IndexedMap<String, Permission> = 1274 state.systemState.permissionTrees 1275 1276 fun GetStateScope.findPermissionTree(permissionName: String): Permission? = 1277 state.systemState.permissionTrees.firstNotNullOfOrNullIndexed { 1278 _, permissionTreeName, permissionTree -> 1279 if (permissionName.startsWith(permissionTreeName) && 1280 permissionName.length > permissionTreeName.length && 1281 permissionName[permissionTreeName.length] == '.') { 1282 permissionTree 1283 } else { 1284 null 1285 } 1286 } 1287 1288 fun MutateStateScope.addPermissionTree(permission: Permission) { 1289 newState.systemState.permissionTrees[permission.name] = permission 1290 newState.systemState.requestWrite() 1291 } 1292 1293 /** 1294 * returns all permission group definitions available in the system 1295 */ 1296 fun GetStateScope.getPermissionGroups(): IndexedMap<String, PermissionGroupInfo> = 1297 state.systemState.permissionGroups 1298 1299 /** 1300 * returns all permission definitions available in the system 1301 */ 1302 fun GetStateScope.getPermissions(): IndexedMap<String, Permission> = 1303 state.systemState.permissions 1304 1305 fun MutateStateScope.addPermission(permission: Permission, sync: Boolean = false) { 1306 newState.systemState.permissions[permission.name] = permission 1307 newState.systemState.requestWrite(sync) 1308 } 1309 1310 fun MutateStateScope.removePermission(permission: Permission) { 1311 newState.systemState.permissions -= permission.name 1312 newState.systemState.requestWrite() 1313 } 1314 1315 fun GetStateScope.getUidPermissionFlags(appId: Int, userId: Int): IndexedMap<String, Int>? = 1316 state.userStates[userId]?.uidPermissionFlags?.get(appId) 1317 1318 fun GetStateScope.getPermissionFlags( 1319 appId: Int, 1320 userId: Int, 1321 permissionName: String 1322 ): Int = getPermissionFlags(state, appId, userId, permissionName) 1323 1324 private fun MutateStateScope.getOldStatePermissionFlags( 1325 appId: Int, 1326 userId: Int, 1327 permissionName: String 1328 ): Int = getPermissionFlags(oldState, appId, userId, permissionName) 1329 1330 private fun getPermissionFlags( 1331 state: AccessState, 1332 appId: Int, 1333 userId: Int, 1334 permissionName: String 1335 ): Int = 1336 state.userStates[userId]?.uidPermissionFlags?.get(appId).getWithDefault(permissionName, 0) 1337 1338 fun MutateStateScope.setPermissionFlags( 1339 appId: Int, 1340 userId: Int, 1341 permissionName: String, 1342 flags: Int 1343 ): Boolean = 1344 updatePermissionFlags(appId, userId, permissionName, PermissionFlags.MASK_ALL, flags) 1345 1346 fun MutateStateScope.updatePermissionFlags( 1347 appId: Int, 1348 userId: Int, 1349 permissionName: String, 1350 flagMask: Int, 1351 flagValues: Int 1352 ): Boolean { 1353 val userState = newState.userStates[userId] 1354 val uidPermissionFlags = userState.uidPermissionFlags 1355 var permissionFlags = uidPermissionFlags[appId] 1356 val oldFlags = permissionFlags.getWithDefault(permissionName, 0) 1357 val newFlags = (oldFlags andInv flagMask) or (flagValues and flagMask) 1358 if (oldFlags == newFlags) { 1359 return false 1360 } 1361 if (permissionFlags == null) { 1362 permissionFlags = IndexedMap() 1363 uidPermissionFlags[appId] = permissionFlags 1364 } 1365 permissionFlags.putWithDefault(permissionName, newFlags, 0) 1366 if (permissionFlags.isEmpty()) { 1367 uidPermissionFlags -= appId 1368 } 1369 userState.requestWrite() 1370 onPermissionFlagsChangedListeners.forEachIndexed { _, it -> 1371 it.onPermissionFlagsChanged(appId, userId, permissionName, oldFlags, newFlags) 1372 } 1373 return true 1374 } 1375 1376 fun addOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) { 1377 synchronized(onPermissionFlagsChangedListenersLock) { 1378 onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners + listener 1379 } 1380 } 1381 1382 fun removeOnPermissionFlagsChangedListener(listener: OnPermissionFlagsChangedListener) { 1383 synchronized(onPermissionFlagsChangedListenersLock) { 1384 onPermissionFlagsChangedListeners = onPermissionFlagsChangedListeners - listener 1385 } 1386 } 1387 1388 companion object { 1389 private val LOG_TAG = UidPermissionPolicy::class.java.simpleName 1390 1391 private const val PLATFORM_PACKAGE_NAME = "android" 1392 1393 // A set of permissions that we don't want to revoke when they are no longer implicit. 1394 private val RETAIN_IMPLICIT_FLAGS_PERMISSIONS = indexedSetOf( 1395 Manifest.permission.ACCESS_MEDIA_LOCATION, 1396 Manifest.permission.ACTIVITY_RECOGNITION, 1397 Manifest.permission.READ_MEDIA_AUDIO, 1398 Manifest.permission.READ_MEDIA_IMAGES, 1399 Manifest.permission.READ_MEDIA_VIDEO, 1400 ) 1401 1402 private val NEARBY_DEVICES_PERMISSIONS = indexedSetOf( 1403 Manifest.permission.BLUETOOTH_ADVERTISE, 1404 Manifest.permission.BLUETOOTH_CONNECT, 1405 Manifest.permission.BLUETOOTH_SCAN, 1406 Manifest.permission.NEARBY_WIFI_DEVICES 1407 ) 1408 1409 private val NOTIFICATIONS_PERMISSIONS = indexedSetOf( 1410 Manifest.permission.POST_NOTIFICATIONS 1411 ) 1412 1413 private val STORAGE_AND_MEDIA_PERMISSIONS = indexedSetOf( 1414 Manifest.permission.READ_EXTERNAL_STORAGE, 1415 Manifest.permission.WRITE_EXTERNAL_STORAGE, 1416 Manifest.permission.READ_MEDIA_AUDIO, 1417 Manifest.permission.READ_MEDIA_VIDEO, 1418 Manifest.permission.READ_MEDIA_IMAGES, 1419 Manifest.permission.ACCESS_MEDIA_LOCATION, 1420 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED 1421 ) 1422 1423 /** 1424 * Mask for all permission flags that can be set by the user 1425 */ 1426 private const val USER_SETTABLE_MASK = 1427 PermissionFlags.USER_SET or 1428 PermissionFlags.USER_FIXED or 1429 PermissionFlags.APP_OP_REVOKED or 1430 PermissionFlags.ONE_TIME or 1431 PermissionFlags.HIBERNATION or 1432 PermissionFlags.USER_SELECTED 1433 1434 /** 1435 * Mask for all permission flags that imply we shouldn't automatically modify the 1436 * permission grant state. 1437 */ 1438 private const val SYSTEM_OR_POLICY_FIXED_MASK = 1439 PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED 1440 } 1441 1442 /** 1443 * Listener for permission flags changes. 1444 */ 1445 abstract class OnPermissionFlagsChangedListener { 1446 /** 1447 * Called when a permission flags change has been made to the upcoming new state. 1448 * 1449 * Implementations should keep this method fast to avoid stalling the locked state mutation, 1450 * and only call external code after [onStateMutated] when the new state has actually become 1451 * the current state visible to external code. 1452 */ 1453 abstract fun onPermissionFlagsChanged( 1454 appId: Int, 1455 userId: Int, 1456 permissionName: String, 1457 oldFlags: Int, 1458 newFlags: Int 1459 ) 1460 1461 /** 1462 * Called when the upcoming new state has become the current state. 1463 * 1464 * Implementations should keep this method fast to avoid stalling the locked state mutation. 1465 */ 1466 abstract fun onStateMutated() 1467 } 1468 } 1469