1 /* <lambda>null2 * Copyright (C) 2023 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.health.connect.HealthPermissions 21 import android.os.Build 22 import android.util.Slog 23 import com.android.server.permission.access.GetStateScope 24 import com.android.server.permission.access.MutateStateScope 25 import com.android.server.permission.access.immutable.* // ktlint-disable no-wildcard-imports 26 import com.android.server.permission.access.util.andInv 27 import com.android.server.permission.access.util.hasAnyBit 28 import com.android.server.permission.access.util.hasBits 29 import com.android.server.pm.pkg.PackageState 30 31 class AppIdPermissionUpgrade(private val policy: AppIdPermissionPolicy) { 32 /** 33 * Upgrade the package permissions, if needed. 34 * 35 * @param version package version 36 * @see [com.android.server.permission.access.util.PackageVersionMigration.getVersion] 37 */ 38 fun MutateStateScope.upgradePackageState( 39 packageState: PackageState, 40 userId: Int, 41 version: Int, 42 ) { 43 val packageName = packageState.packageName 44 if (version <= 3) { 45 Slog.v( 46 LOG_TAG, 47 "Allowlisting and upgrading background location permission for " + 48 "package: $packageName, version: $version, user:$userId", 49 ) 50 allowlistRestrictedPermissions(packageState, userId) 51 upgradeBackgroundLocationPermission(packageState, userId) 52 } 53 if (version <= 10) { 54 Slog.v( 55 LOG_TAG, 56 "Upgrading access media location permission for package: $packageName" + 57 ", version: $version, user: $userId", 58 ) 59 upgradeAccessMediaLocationPermission(packageState, userId) 60 } 61 // TODO Enable isAtLeastT check, when moving subsystem to mainline. 62 if (version <= 12 /*&& SdkLevel.isAtLeastT()*/) { 63 Slog.v( 64 LOG_TAG, 65 "Upgrading scoped media and body sensor permissions for package: $packageName" + 66 ", version: $version, user: $userId", 67 ) 68 upgradeAuralVisualMediaPermissions(packageState, userId) 69 upgradeBodySensorBackgroundPermissions(packageState, userId) 70 } 71 // TODO Enable isAtLeastU check, when moving subsystem to mainline. 72 if (version <= 14 /*&& SdkLevel.isAtLeastU()*/) { 73 Slog.v( 74 LOG_TAG, 75 "Upgrading visual media permission for package: $packageName" + 76 ", version: $version, user: $userId", 77 ) 78 upgradeUserSelectedVisualMediaPermission(packageState, userId) 79 } 80 // TODO Enable isAtLeastB check, when moving subsystem to mainline. 81 if (version <= 16 /*&& SdkLevel.isAtLeastB()*/) { 82 Slog.v( 83 LOG_TAG, 84 "Upgrading body sensor / read heart rate permissions for package: $packageName" + 85 ", version: $version, user: $userId", 86 ) 87 upgradeBodySensorReadHeartRatePermissions(packageState, userId) 88 } 89 90 // Add a new upgrade step: if (packageVersion <= LATEST_VERSION) { .... } 91 // Also increase LATEST_VERSION 92 } 93 94 private fun MutateStateScope.allowlistRestrictedPermissions( 95 packageState: PackageState, 96 userId: Int, 97 ) { 98 packageState.androidPackage!!.requestedPermissions.forEach { permissionName -> 99 if (permissionName in LEGACY_RESTRICTED_PERMISSIONS) { 100 with(policy) { 101 updatePermissionFlags( 102 packageState.appId, 103 userId, 104 permissionName, 105 PermissionFlags.UPGRADE_EXEMPT, 106 PermissionFlags.UPGRADE_EXEMPT, 107 ) 108 } 109 } 110 } 111 } 112 113 private fun MutateStateScope.upgradeBackgroundLocationPermission( 114 packageState: PackageState, 115 userId: Int, 116 ) { 117 if ( 118 Manifest.permission.ACCESS_BACKGROUND_LOCATION in 119 packageState.androidPackage!!.requestedPermissions 120 ) { 121 val appId = packageState.appId 122 val accessFineLocationFlags = 123 with(policy) { 124 getPermissionFlags(appId, userId, Manifest.permission.ACCESS_FINE_LOCATION) 125 } 126 val accessCoarseLocationFlags = 127 with(policy) { 128 getPermissionFlags(appId, userId, Manifest.permission.ACCESS_COARSE_LOCATION) 129 } 130 val isForegroundLocationGranted = 131 PermissionFlags.isAppOpGranted(accessFineLocationFlags) || 132 PermissionFlags.isAppOpGranted(accessCoarseLocationFlags) 133 if (isForegroundLocationGranted) { 134 grantRuntimePermission( 135 packageState, 136 userId, 137 Manifest.permission.ACCESS_BACKGROUND_LOCATION, 138 ) 139 } 140 } 141 } 142 143 private fun MutateStateScope.upgradeAccessMediaLocationPermission( 144 packageState: PackageState, 145 userId: Int, 146 ) { 147 if ( 148 Manifest.permission.ACCESS_MEDIA_LOCATION in 149 packageState.androidPackage!!.requestedPermissions 150 ) { 151 val flags = 152 with(policy) { 153 getPermissionFlags( 154 packageState.appId, 155 userId, 156 Manifest.permission.READ_EXTERNAL_STORAGE, 157 ) 158 } 159 if (PermissionFlags.isAppOpGranted(flags)) { 160 grantRuntimePermission( 161 packageState, 162 userId, 163 Manifest.permission.ACCESS_MEDIA_LOCATION, 164 ) 165 } 166 } 167 } 168 169 /** Upgrade permissions based on storage permissions grant */ 170 private fun MutateStateScope.upgradeAuralVisualMediaPermissions( 171 packageState: PackageState, 172 userId: Int, 173 ) { 174 val androidPackage = packageState.androidPackage!! 175 if (androidPackage.targetSdkVersion < Build.VERSION_CODES.TIRAMISU) { 176 return 177 } 178 val requestedPermissionNames = androidPackage.requestedPermissions 179 val isStorageUserGranted = 180 STORAGE_PERMISSIONS.anyIndexed { _, permissionName -> 181 if (permissionName !in requestedPermissionNames) { 182 return@anyIndexed false 183 } 184 val flags = 185 with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } 186 PermissionFlags.isAppOpGranted(flags) && flags.hasBits(PermissionFlags.USER_SET) 187 } 188 if (isStorageUserGranted) { 189 AURAL_VISUAL_MEDIA_PERMISSIONS.forEachIndexed { _, permissionName -> 190 if (permissionName in requestedPermissionNames) { 191 grantRuntimePermission(packageState, userId, permissionName) 192 } 193 } 194 } 195 } 196 197 private fun MutateStateScope.upgradeBodySensorBackgroundPermissions( 198 packageState: PackageState, 199 userId: Int, 200 ) { 201 if ( 202 Manifest.permission.BODY_SENSORS_BACKGROUND !in 203 packageState.androidPackage!!.requestedPermissions 204 ) { 205 return 206 } 207 208 // Should have been granted when first getting exempt as if the perm was just split 209 val appId = packageState.appId 210 val backgroundBodySensorsFlags = 211 with(policy) { 212 getPermissionFlags(appId, userId, Manifest.permission.BODY_SENSORS_BACKGROUND) 213 } 214 if (backgroundBodySensorsFlags.hasAnyBit(PermissionFlags.MASK_EXEMPT)) { 215 return 216 } 217 218 // Add Upgrade Exemption - BODY_SENSORS_BACKGROUND is a restricted permission 219 with(policy) { 220 updatePermissionFlags( 221 appId, 222 userId, 223 Manifest.permission.BODY_SENSORS_BACKGROUND, 224 PermissionFlags.UPGRADE_EXEMPT, 225 PermissionFlags.UPGRADE_EXEMPT, 226 ) 227 } 228 229 val bodySensorsFlags = 230 with(policy) { getPermissionFlags(appId, userId, Manifest.permission.BODY_SENSORS) } 231 val isForegroundBodySensorsGranted = PermissionFlags.isAppOpGranted(bodySensorsFlags) 232 if (isForegroundBodySensorsGranted) { 233 grantRuntimePermission( 234 packageState, 235 userId, 236 Manifest.permission.BODY_SENSORS_BACKGROUND, 237 ) 238 } 239 } 240 241 /** Upgrade permission based on the grant in [Manifest.permission_group.READ_MEDIA_VISUAL] */ 242 private fun MutateStateScope.upgradeUserSelectedVisualMediaPermission( 243 packageState: PackageState, 244 userId: Int, 245 ) { 246 val androidPackage = packageState.androidPackage!! 247 if (androidPackage.targetSdkVersion < Build.VERSION_CODES.TIRAMISU) { 248 return 249 } 250 val requestedPermissionNames = androidPackage.requestedPermissions 251 val isVisualMediaUserGranted = 252 VISUAL_MEDIA_PERMISSIONS.anyIndexed { _, permissionName -> 253 if (permissionName !in requestedPermissionNames) { 254 return@anyIndexed false 255 } 256 val flags = 257 with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } 258 PermissionFlags.isAppOpGranted(flags) && flags.hasBits(PermissionFlags.USER_SET) 259 } 260 if (isVisualMediaUserGranted) { 261 if (Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED in requestedPermissionNames) { 262 grantRuntimePermission( 263 packageState, 264 userId, 265 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED, 266 ) 267 } 268 } 269 } 270 271 /** 272 * Upgrade permissions based on the body sensors and health permissions status. 273 * 274 * Starting in BAKLAVA, the BODY_SENSORS and BODY_SENSORS_BACKGROUND permissions are being 275 * replaced by the READ_HEART_RATE and READ_HEALTH_DATA_IN_BACKGROUND permissions respectively. 276 * To ensure that older apps can continue using BODY_SENSORS without breaking we need to keep 277 * their permission state in sync with the new health permissions. 278 * 279 * The approach we take is to be as conservative as possible. This means if either permission is 280 * not granted, then we want to ensure that both end up not granted to force the user to 281 * re-grant with the expanded scope. 282 */ 283 private fun MutateStateScope.upgradeBodySensorReadHeartRatePermissions( 284 packageState: PackageState, 285 userId: Int, 286 ) { 287 val androidPackage = packageState.androidPackage!! 288 if (androidPackage.targetSdkVersion >= Build.VERSION_CODES.BAKLAVA) { 289 return 290 } 291 292 // First sync BODY_SENSORS and READ_HEART_RATE, if required. 293 val isBodySensorsRequested = 294 Manifest.permission.BODY_SENSORS in androidPackage.requestedPermissions 295 val isReadHeartRateRequested = 296 HealthPermissions.READ_HEART_RATE in androidPackage.requestedPermissions 297 var isBodySensorsGranted = 298 isRuntimePermissionGranted(packageState, userId, Manifest.permission.BODY_SENSORS) 299 if (isBodySensorsRequested && isReadHeartRateRequested) { 300 val isReadHeartRateGranted = 301 isRuntimePermissionGranted(packageState, userId, HealthPermissions.READ_HEART_RATE) 302 if (isBodySensorsGranted != isReadHeartRateGranted) { 303 if (isBodySensorsGranted) { 304 if ( 305 revokeRuntimePermission( 306 packageState, 307 userId, 308 Manifest.permission.BODY_SENSORS, 309 ) 310 ) { 311 isBodySensorsGranted = false 312 } 313 } 314 if (isReadHeartRateGranted) { 315 revokeRuntimePermission(packageState, userId, HealthPermissions.READ_HEART_RATE) 316 } 317 } 318 } 319 320 // Then check to ensure we haven't put the background/foreground permissions out of sync. 321 var isBodySensorsBackgroundGranted = 322 isRuntimePermissionGranted( 323 packageState, 324 userId, 325 Manifest.permission.BODY_SENSORS_BACKGROUND, 326 ) 327 // Background permission should not be granted without the foreground permission. 328 if (!isBodySensorsGranted && isBodySensorsBackgroundGranted) { 329 if ( 330 revokeRuntimePermission( 331 packageState, 332 userId, 333 Manifest.permission.BODY_SENSORS_BACKGROUND, 334 ) 335 ) { 336 isBodySensorsBackgroundGranted = false 337 } 338 } 339 340 // Finally sync BODY_SENSORS_BACKGROUND and READ_HEALTH_DATA_IN_BACKGROUND, if required. 341 val isBodySensorsBackgroundRequested = 342 Manifest.permission.BODY_SENSORS_BACKGROUND in androidPackage.requestedPermissions 343 val isReadHealthDataInBackgroundRequested = 344 HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND in androidPackage.requestedPermissions 345 if (isBodySensorsBackgroundRequested && isReadHealthDataInBackgroundRequested) { 346 val isReadHealthDataInBackgroundGranted = 347 isRuntimePermissionGranted( 348 packageState, 349 userId, 350 HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, 351 ) 352 if (isBodySensorsBackgroundGranted != isReadHealthDataInBackgroundGranted) { 353 if (isBodySensorsBackgroundGranted) { 354 revokeRuntimePermission( 355 packageState, 356 userId, 357 Manifest.permission.BODY_SENSORS_BACKGROUND, 358 ) 359 } 360 if (isReadHealthDataInBackgroundGranted) { 361 revokeRuntimePermission( 362 packageState, 363 userId, 364 HealthPermissions.READ_HEALTH_DATA_IN_BACKGROUND, 365 ) 366 } 367 } 368 } 369 } 370 371 private fun GetStateScope.isRuntimePermissionGranted( 372 packageState: PackageState, 373 userId: Int, 374 permissionName: String, 375 ): Boolean { 376 val permissionFlags = 377 with(policy) { getPermissionFlags(packageState.appId, userId, permissionName) } 378 return PermissionFlags.isAppOpGranted(permissionFlags) 379 } 380 381 private fun MutateStateScope.grantRuntimePermission( 382 packageState: PackageState, 383 userId: Int, 384 permissionName: String, 385 ) { 386 Slog.v( 387 LOG_TAG, 388 "Granting runtime permission for package: ${packageState.packageName}, " + 389 "permission: $permissionName, userId: $userId", 390 ) 391 val permission = newState.systemState.permissions[permissionName]!! 392 if (packageState.getUserStateOrDefault(userId).isInstantApp && !permission.isInstant) { 393 return 394 } 395 396 val appId = packageState.appId 397 var flags = with(policy) { getPermissionFlags(appId, userId, permissionName) } 398 if (flags.hasAnyBit(MASK_ANY_FIXED)) { 399 Slog.v( 400 LOG_TAG, 401 "Not allowed to grant $permissionName to package ${packageState.packageName}", 402 ) 403 return 404 } 405 406 flags = flags or PermissionFlags.RUNTIME_GRANTED 407 flags = 408 flags andInv 409 (PermissionFlags.APP_OP_REVOKED or 410 PermissionFlags.IMPLICIT or 411 PermissionFlags.LEGACY_GRANTED or 412 PermissionFlags.HIBERNATION or 413 PermissionFlags.ONE_TIME) 414 with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } 415 } 416 417 /** 418 * Revoke a runtime permission for a given user from a given package. 419 * 420 * @return true if the permission was revoked, false otherwise. 421 */ 422 private fun MutateStateScope.revokeRuntimePermission( 423 packageState: PackageState, 424 userId: Int, 425 permissionName: String, 426 ): Boolean { 427 Slog.v( 428 LOG_TAG, 429 "Revoking runtime permission for package: ${packageState.packageName}, " + 430 "permission: $permissionName, userId: $userId", 431 ) 432 433 val appId = packageState.appId 434 var flags = with(policy) { getPermissionFlags(appId, userId, permissionName) } 435 if (flags.hasAnyBit(MASK_SYSTEM_OR_POLICY_FIXED)) { 436 Slog.v( 437 LOG_TAG, 438 "Cannot revoke fixed runtime permission from package: " + 439 "${packageState.packageName}, permission: $permissionName, userId: $userId", 440 ) 441 return false 442 } 443 444 flags = 445 flags andInv 446 (PermissionFlags.RUNTIME_GRANTED or 447 MASK_USER_SETTABLE or 448 PermissionFlags.PREGRANT or 449 PermissionFlags.ROLE) 450 with(policy) { setPermissionFlags(appId, userId, permissionName, flags) } 451 return true 452 } 453 454 companion object { 455 private val LOG_TAG = AppIdPermissionUpgrade::class.java.simpleName 456 457 private const val MASK_ANY_FIXED = 458 PermissionFlags.USER_SET or 459 PermissionFlags.ONE_TIME or 460 PermissionFlags.USER_FIXED or 461 PermissionFlags.POLICY_FIXED or 462 PermissionFlags.SYSTEM_FIXED 463 464 private const val MASK_SYSTEM_OR_POLICY_FIXED = 465 PermissionFlags.SYSTEM_FIXED or PermissionFlags.POLICY_FIXED 466 467 private const val MASK_USER_SETTABLE = 468 PermissionFlags.USER_SET or 469 PermissionFlags.USER_FIXED or 470 PermissionFlags.APP_OP_REVOKED or 471 PermissionFlags.ONE_TIME or 472 PermissionFlags.HIBERNATION or 473 PermissionFlags.USER_SELECTED 474 475 private val LEGACY_RESTRICTED_PERMISSIONS = 476 indexedSetOf( 477 Manifest.permission.ACCESS_BACKGROUND_LOCATION, 478 Manifest.permission.READ_EXTERNAL_STORAGE, 479 Manifest.permission.WRITE_EXTERNAL_STORAGE, 480 Manifest.permission.SEND_SMS, 481 Manifest.permission.RECEIVE_SMS, 482 Manifest.permission.RECEIVE_WAP_PUSH, 483 Manifest.permission.RECEIVE_MMS, 484 Manifest.permission.READ_CELL_BROADCASTS, 485 Manifest.permission.READ_CALL_LOG, 486 Manifest.permission.WRITE_CALL_LOG, 487 Manifest.permission.PROCESS_OUTGOING_CALLS, 488 ) 489 490 private val STORAGE_PERMISSIONS = 491 indexedSetOf( 492 Manifest.permission.READ_EXTERNAL_STORAGE, 493 Manifest.permission.WRITE_EXTERNAL_STORAGE, 494 ) 495 private val AURAL_VISUAL_MEDIA_PERMISSIONS = 496 indexedSetOf( 497 Manifest.permission.READ_MEDIA_AUDIO, 498 Manifest.permission.READ_MEDIA_IMAGES, 499 Manifest.permission.READ_MEDIA_VIDEO, 500 Manifest.permission.ACCESS_MEDIA_LOCATION, 501 Manifest.permission.READ_MEDIA_VISUAL_USER_SELECTED, 502 ) 503 // Visual media permissions in T 504 private val VISUAL_MEDIA_PERMISSIONS = 505 indexedSetOf( 506 Manifest.permission.READ_MEDIA_IMAGES, 507 Manifest.permission.READ_MEDIA_VIDEO, 508 Manifest.permission.ACCESS_MEDIA_LOCATION, 509 ) 510 } 511 } 512