Loading services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +34 −20 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context import com.android.internal.annotations.Keep import com.android.server.LocalManagerRegistry import com.android.server.LocalServices import com.android.server.SystemConfig import com.android.server.SystemService import com.android.server.appop.AppOpsCheckingServiceInterface import com.android.server.permission.access.appop.AppOpService Loading @@ -28,7 +29,6 @@ import com.android.server.permission.access.permission.PermissionService import com.android.server.pm.PackageManagerLocal import com.android.server.pm.UserManagerService import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.permission.PermissionManagerServiceInternal import com.android.server.pm.pkg.PackageState @Keep Loading @@ -46,6 +46,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var userManagerService: UserManagerService private lateinit var systemConfig: SystemConfig override fun onStart() { appOpService = AppOpService(this) Loading @@ -59,12 +60,16 @@ class AccessCheckingService(context: Context) : SystemService(context) { packageManagerLocal = LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java) userManagerService = UserManagerService.getInstance() systemConfig = SystemConfig.getInstance() val userIds = IntSet(userManagerService.userIdsIncludingPreCreated) val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates val permissionAllowlist = systemConfig.permissionAllowlist val state = AccessState() policy.initialize(state, userIds, packageStates) policy.initialize( state, userIds, packageStates, disabledSystemPackageStates, permissionAllowlist ) persistence.read(state) this.state = state Loading Loading @@ -96,46 +101,55 @@ class AccessCheckingService(context: Context) : SystemService(context) { } internal fun onStorageVolumeMounted(volumeUuid: String?, isSystemUpdated: Boolean) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onStorageVolumeMounted(packageStates, volumeUuid, isSystemUpdated) } with(policy) { onStorageVolumeMounted( packageStates, disabledSystemPackageStates, volumeUuid, isSystemUpdated ) } } } internal fun onPackageAdded(packageName: String) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageAdded(packageStates, packageName) } with(policy) { onPackageAdded(packageStates, disabledSystemPackageStates, packageName) } } } internal fun onPackageRemoved(packageName: String, appId: Int) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageRemoved(packageStates, packageName, appId) } with(policy) { onPackageRemoved(packageStates, disabledSystemPackageStates, packageName, appId) } } } internal fun onPackageInstalled( packageName: String, params: PermissionManagerServiceInternal.PackageInstalledParams, userId: Int ) { val packageStates = packageManagerLocal.packageStates internal fun onPackageInstalled(packageName: String, userId: Int) { val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageInstalled(packageStates, packageName, params, userId) } with(policy) { onPackageInstalled(packageStates, disabledSystemPackageStates, packageName, userId) } } } internal fun onPackageUninstalled(packageName: String, appId: Int, userId: Int) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageUninstalled(packageStates, packageName, appId, userId) } with(policy) { onPackageUninstalled( packageStates, disabledSystemPackageStates, packageName, appId, userId ) } } } private val PackageManagerLocal.packageStates: Map<String, PackageState> get() = withUnfilteredSnapshot().use { it.packageStates } private val PackageManagerLocal.allPackageStates: Pair<Map<String, PackageState>, Map<String, PackageState>> get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates } internal inline fun <T> getState(action: GetStateScope.() -> T): T = GetStateScope(state).action() Loading services/permission/java/com/android/server/permission/access/AccessPolicy.kt +55 −28 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import com.android.server.permission.access.permission.UidPermissionPolicy import com.android.server.permission.access.util.forEachTag import com.android.server.permission.access.util.tag import com.android.server.permission.access.util.tagName import com.android.server.pm.permission.PermissionManagerServiceInternal import com.android.server.pm.permission.PermissionAllowlist import com.android.server.pm.pkg.PackageState class AccessPolicy private constructor( Loading Loading @@ -54,14 +54,22 @@ class AccessPolicy private constructor( with(getSchemePolicy(subject, `object`)) { setDecision(subject, `object`, decision) } } fun initialize(state: AccessState, userIds: IntSet, packageStates: Map<String, PackageState>) { fun initialize( state: AccessState, userIds: IntSet, packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, permissionAllowlist: PermissionAllowlist ) { state.systemState.apply { this.userIds += userIds this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates packageStates.forEach { (_, packageState) -> appIds.getOrPut(packageState.appId) { IndexedListSet() } .add(packageState.packageName) } this.permissionAllowlist = permissionAllowlist } } Loading @@ -83,10 +91,14 @@ class AccessPolicy private constructor( fun MutateStateScope.onStorageVolumeMounted( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, volumeUuid: String?, isSystemUpdated: Boolean ) { newState.systemState.packageStates = packageStates newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates } forEachSchemePolicy { with(it) { onStorageVolumeMounted(volumeUuid, isSystemUpdated) } } Loading @@ -94,18 +106,24 @@ class AccessPolicy private constructor( fun MutateStateScope.onPackageAdded( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String ) { newState.systemState.packageStates = packageStates var isAppIdAdded = false val packageState = packageStates[packageName] // TODO(zhanghai): Remove check before submission. checkNotNull(packageState) // TODO(zhanghai): STOPSHIP: Remove check before feature enable. checkNotNull(packageState) { "Added package $packageName isn't found in packageStates in onPackageAdded()" } val appId = packageState.appId newState.systemState.appIds.getOrPut(appId) { var isAppIdAdded = false newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates appIds.getOrPut(appId) { isAppIdAdded = true IndexedListSet() }.add(packageName) } if (isAppIdAdded) { forEachSchemePolicy { with(it) { onAppIdAdded(appId) } Loading @@ -118,18 +136,22 @@ class AccessPolicy private constructor( fun MutateStateScope.onPackageRemoved( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String, appId: Int ) { newState.systemState.packageStates = packageStates // TODO(zhanghai): STOPSHIP: Remove check before feature enable. check(packageName !in packageStates) { "Removed package $packageName is still in packageStates in onPackageRemoved()" } var isAppIdRemoved = false // TODO(zhanghai): Remove check before submission. check(packageName !in packageStates) newState.systemState.appIds.apply appIds@{ this[appId]?.apply { newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates appIds[appId]?.apply { this -= packageName if (isEmpty()) { this@appIds -= appId appIds -= appId isAppIdRemoved = true } } Loading @@ -146,26 +168,35 @@ class AccessPolicy private constructor( fun MutateStateScope.onPackageInstalled( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String, params: PermissionManagerServiceInternal.PackageInstalledParams, userId: Int ) { newState.systemState.packageStates = packageStates newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates } val packageState = packageStates[packageName] // TODO(zhanghai): Remove check before submission. checkNotNull(packageState) // TODO(zhanghai): STOPSHIP: Remove check before feature enable. checkNotNull(packageState) { "Installed package $packageName isn't found in packageStates in onPackageInstalled()" } forEachSchemePolicy { with(it) { onPackageInstalled(packageState, params, userId) } with(it) { onPackageInstalled(packageState, userId) } } } fun MutateStateScope.onPackageUninstalled( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String, appId: Int, userId: Int ) { newState.systemState.packageStates = packageStates newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates } forEachSchemePolicy { with(it) { onPackageUninstalled(packageName, appId, userId) } } Loading Loading @@ -298,11 +329,7 @@ abstract class SchemePolicy { open fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {} open fun MutateStateScope.onPackageInstalled( packageState: PackageState, params: PermissionManagerServiceInternal.PackageInstalledParams, userId: Int ) {} open fun MutateStateScope.onPackageInstalled(packageState: PackageState, userId: Int) {} open fun MutateStateScope.onPackageUninstalled(packageName: String, appId: Int, userId: Int) {} Loading services/permission/java/com/android/server/permission/access/AccessState.kt +28 −31 Original line number Diff line number Diff line Loading @@ -19,15 +19,22 @@ package com.android.server.permission.access import android.content.pm.PermissionGroupInfo import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.permission.Permission import com.android.server.pm.permission.PermissionAllowlist import com.android.server.pm.pkg.PackageState class AccessState private constructor( val systemState: SystemState, val userStates: IntMap<UserState> ) { constructor() : this(SystemState(), IntMap()) constructor() : this( SystemState(), IntMap() ) fun copy(): AccessState = AccessState(systemState.copy(), userStates.copy { it.copy() }) fun copy(): AccessState = AccessState( systemState.copy(), userStates.copy { it.copy() } ) } class SystemState private constructor( Loading @@ -39,30 +46,26 @@ class SystemState private constructor( val knownPackages: IntMap<IndexedListSet<String>>, // A map of userId to packageName val deviceAndProfileOwners: IntMap<String>, // A map of packageName to (A map of oem permission name to whether it's granted) val oemPermissions: IndexedMap<String, IndexedMap<String, Boolean>>, val privilegedPermissionAllowlistSourcePackageNames: IndexedListSet<String>, // A map of packageName to a set of vendor priv app permission names val vendorPrivAppPermissions: Map<String, Set<String>>, val productPrivAppPermissions: Map<String, Set<String>>, val systemExtPrivAppPermissions: Map<String, Set<String>>, val privAppPermissions: Map<String, Set<String>>, val apexPrivAppPermissions: Map<String, Map<String, Set<String>>>, val vendorPrivAppDenyPermissions: Map<String, Set<String>>, val productPrivAppDenyPermissions: Map<String, Set<String>>, val systemExtPrivAppDenyPermissions: Map<String, Set<String>>, val apexPrivAppDenyPermissions: Map<String, Map<String, Set<String>>>, val privAppDenyPermissions: Map<String, Set<String>>, var permissionAllowlist: PermissionAllowlist, val implicitToSourcePermissions: Map<String, Set<String>>, val permissionGroups: IndexedMap<String, PermissionGroupInfo>, val permissionTrees: IndexedMap<String, Permission>, val permissions: IndexedMap<String, Permission> ) : WritableState() { constructor() : this( IntSet(), emptyMap(), emptyMap(), IntMap(), IntMap(), IntMap(), IndexedMap(), IndexedListSet(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap() IntSet(), emptyMap(), emptyMap(), IntMap(), IntMap(), IntMap(), IndexedListSet(), PermissionAllowlist(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap() ) fun copy(): SystemState = Loading @@ -73,18 +76,8 @@ class SystemState private constructor( appIds.copy { it.copy() }, knownPackages.copy { it.copy() }, deviceAndProfileOwners.copy { it }, oemPermissions.copy { it.copy { it } }, privilegedPermissionAllowlistSourcePackageNames.copy(), vendorPrivAppPermissions, productPrivAppPermissions, systemExtPrivAppPermissions, privAppPermissions, apexPrivAppPermissions, vendorPrivAppDenyPermissions, productPrivAppDenyPermissions, systemExtPrivAppDenyPermissions, apexPrivAppDenyPermissions, privAppDenyPermissions, permissionAllowlist, implicitToSourcePermissions, permissionGroups.copy { it }, permissionTrees.copy { it }, Loading @@ -98,7 +91,11 @@ class UserState private constructor( val uidAppOpModes: IntMap<IndexedMap<String, Int>>, val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>> ) : WritableState() { constructor() : this(IntMap(), IntMap(), IndexedMap()) constructor() : this( IntMap(), IntMap(), IndexedMap() ) fun copy(): UserState = UserState( uidPermissionFlags.copy { it.copy { it } }, Loading services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +2 −1 Original line number Diff line number Diff line Loading @@ -435,7 +435,8 @@ class PermissionService( } else { intArrayOf(userId) } userIds.forEach { service.onPackageInstalled(androidPackage.packageName, params, it) } userIds.forEach { service.onPackageInstalled(androidPackage.packageName, it) } // TODO: Handle params. } override fun onPackageUninstalled( Loading services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt +41 −58 Original line number Diff line number Diff line Loading @@ -597,11 +597,9 @@ class UidPermissionPolicy : SchemePolicy() { newState.systemState.privilegedPermissionAllowlistSourcePackageNames) { return true } if (isInSystemConfigPrivAppPermissions(androidPackage, permission.name)) { return true } if (isInSystemConfigPrivAppDenyPermissions(androidPackage, permission.name)) { return false val allowlistState = getPrivilegedPermissionAllowlistState(androidPackage, permission.name) if (allowlistState != null) { return allowlistState } // Updated system apps do not need to be allowlisted if (packageState.isUpdatedSystemApp) { Loading @@ -611,66 +609,51 @@ class UidPermissionPolicy : SchemePolicy() { return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE } private fun MutateStateScope.isInSystemConfigPrivAppPermissions( androidPackage: AndroidPackage, permissionName: String ): Boolean { // TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName. The below is only for // passing compilation but won't actually work. //val apexModuleName = androidPackage.apexModuleName val apexModuleName = androidPackage.packageName val systemState = newState.systemState val packageName = androidPackage.packageName val permissionNames = when { androidPackage.isVendor -> systemState.vendorPrivAppPermissions[packageName] androidPackage.isProduct -> systemState.productPrivAppPermissions[packageName] androidPackage.isSystemExt -> systemState.systemExtPrivAppPermissions[packageName] apexModuleName != null -> { val apexPrivAppPermissions = systemState.apexPrivAppPermissions[apexModuleName] ?.get(packageName) val privAppPermissions = systemState.privAppPermissions[packageName] when { apexPrivAppPermissions == null -> privAppPermissions privAppPermissions == null -> apexPrivAppPermissions else -> apexPrivAppPermissions + privAppPermissions } } else -> systemState.privAppPermissions[packageName] } return permissionNames?.contains(permissionName) == true } private fun MutateStateScope.isInSystemConfigPrivAppDenyPermissions( /** * Get the whether a privileged permission is explicitly allowed or denied for a package in the * allowlist, or `null` if it's not in the allowlist. */ private fun MutateStateScope.getPrivilegedPermissionAllowlistState( androidPackage: AndroidPackage, permissionName: String ): Boolean { // Different from the previous implementation, which may incorrectly use the APEX package // name, we now use the APEX module name to be consistent with the allowlist. ): Boolean? { val permissionAllowlist = newState.systemState.permissionAllowlist // TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName. The below is only for // passing compilation but won't actually work. //val apexModuleName = androidPackage.apexModuleName val apexModuleName = androidPackage.packageName val systemState = newState.systemState val packageName = androidPackage.packageName val permissionNames = when { androidPackage.isVendor -> systemState.vendorPrivAppDenyPermissions[packageName] androidPackage.isProduct -> systemState.productPrivAppDenyPermissions[packageName] androidPackage.isSystemExt -> systemState.systemExtPrivAppDenyPermissions[packageName] // Different from the previous implementation, which ignores the regular priv app // denylist in this case, we now respect it as well to be consistent with the allowlist. return when { androidPackage.isVendor -> permissionAllowlist.getVendorPrivilegedAppAllowlistState( packageName, permissionName ) androidPackage.isProduct -> permissionAllowlist.getProductPrivilegedAppAllowlistState( packageName, permissionName ) androidPackage.isSystemExt -> permissionAllowlist.getSystemExtPrivilegedAppAllowlistState( packageName, permissionName ) apexModuleName != null -> { val apexPrivAppDenyPermissions = systemState .apexPrivAppDenyPermissions[apexModuleName]?.get(packageName) val privAppDenyPermissions = systemState.privAppDenyPermissions[packageName] when { apexPrivAppDenyPermissions == null -> privAppDenyPermissions privAppDenyPermissions == null -> apexPrivAppDenyPermissions else -> apexPrivAppDenyPermissions + privAppDenyPermissions val nonApexAllowlistState = permissionAllowlist.getPrivilegedAppAllowlistState( packageName, permissionName ) if (nonApexAllowlistState != null) { // TODO(andreionea): Remove check as soon as all apk-in-apex // permission allowlists are migrated. Log.w( LOG_TAG, "Package $packageName is an APK in APEX but has permission" + " allowlist on the system image, please bundle the allowlist in the" + " $apexModuleName APEX instead" ) } val apexAllowlistState = permissionAllowlist.getApexPrivilegedAppAllowlistState( apexModuleName, packageName, permissionName ) apexAllowlistState ?: nonApexAllowlistState } else -> systemState.privAppDenyPermissions[packageName] else -> permissionAllowlist.getPrivilegedAppAllowlistState(packageName, permissionName) } return permissionNames?.contains(permissionName) == true } private fun MutateStateScope.anyPackageInAppId( Loading Loading @@ -811,13 +794,13 @@ class UidPermissionPolicy : SchemePolicy() { } permission.isOem -> { if (androidPackage.isOem) { val isOemAllowlisted = newState.systemState .oemPermissions[packageName]?.get(permissionName) checkNotNull(isOemAllowlisted) { val allowlistState = newState.systemState.permissionAllowlist .getOemAppAllowlistState(packageName, permissionName) checkNotNull(allowlistState) { "OEM permission $permissionName requested by package" + " $packageName must be explicitly declared granted or not" } return isOemAllowlisted return allowlistState } } } Loading Loading
services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +34 −20 Original line number Diff line number Diff line Loading @@ -20,6 +20,7 @@ import android.content.Context import com.android.internal.annotations.Keep import com.android.server.LocalManagerRegistry import com.android.server.LocalServices import com.android.server.SystemConfig import com.android.server.SystemService import com.android.server.appop.AppOpsCheckingServiceInterface import com.android.server.permission.access.appop.AppOpService Loading @@ -28,7 +29,6 @@ import com.android.server.permission.access.permission.PermissionService import com.android.server.pm.PackageManagerLocal import com.android.server.pm.UserManagerService import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.permission.PermissionManagerServiceInternal import com.android.server.pm.pkg.PackageState @Keep Loading @@ -46,6 +46,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var userManagerService: UserManagerService private lateinit var systemConfig: SystemConfig override fun onStart() { appOpService = AppOpService(this) Loading @@ -59,12 +60,16 @@ class AccessCheckingService(context: Context) : SystemService(context) { packageManagerLocal = LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java) userManagerService = UserManagerService.getInstance() systemConfig = SystemConfig.getInstance() val userIds = IntSet(userManagerService.userIdsIncludingPreCreated) val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates val permissionAllowlist = systemConfig.permissionAllowlist val state = AccessState() policy.initialize(state, userIds, packageStates) policy.initialize( state, userIds, packageStates, disabledSystemPackageStates, permissionAllowlist ) persistence.read(state) this.state = state Loading Loading @@ -96,46 +101,55 @@ class AccessCheckingService(context: Context) : SystemService(context) { } internal fun onStorageVolumeMounted(volumeUuid: String?, isSystemUpdated: Boolean) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onStorageVolumeMounted(packageStates, volumeUuid, isSystemUpdated) } with(policy) { onStorageVolumeMounted( packageStates, disabledSystemPackageStates, volumeUuid, isSystemUpdated ) } } } internal fun onPackageAdded(packageName: String) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageAdded(packageStates, packageName) } with(policy) { onPackageAdded(packageStates, disabledSystemPackageStates, packageName) } } } internal fun onPackageRemoved(packageName: String, appId: Int) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageRemoved(packageStates, packageName, appId) } with(policy) { onPackageRemoved(packageStates, disabledSystemPackageStates, packageName, appId) } } } internal fun onPackageInstalled( packageName: String, params: PermissionManagerServiceInternal.PackageInstalledParams, userId: Int ) { val packageStates = packageManagerLocal.packageStates internal fun onPackageInstalled(packageName: String, userId: Int) { val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageInstalled(packageStates, packageName, params, userId) } with(policy) { onPackageInstalled(packageStates, disabledSystemPackageStates, packageName, userId) } } } internal fun onPackageUninstalled(packageName: String, appId: Int, userId: Int) { val packageStates = packageManagerLocal.packageStates val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates mutateState { with(policy) { onPackageUninstalled(packageStates, packageName, appId, userId) } with(policy) { onPackageUninstalled( packageStates, disabledSystemPackageStates, packageName, appId, userId ) } } } private val PackageManagerLocal.packageStates: Map<String, PackageState> get() = withUnfilteredSnapshot().use { it.packageStates } private val PackageManagerLocal.allPackageStates: Pair<Map<String, PackageState>, Map<String, PackageState>> get() = withUnfilteredSnapshot().use { it.packageStates to it.disabledSystemPackageStates } internal inline fun <T> getState(action: GetStateScope.() -> T): T = GetStateScope(state).action() Loading
services/permission/java/com/android/server/permission/access/AccessPolicy.kt +55 −28 Original line number Diff line number Diff line Loading @@ -26,7 +26,7 @@ import com.android.server.permission.access.permission.UidPermissionPolicy import com.android.server.permission.access.util.forEachTag import com.android.server.permission.access.util.tag import com.android.server.permission.access.util.tagName import com.android.server.pm.permission.PermissionManagerServiceInternal import com.android.server.pm.permission.PermissionAllowlist import com.android.server.pm.pkg.PackageState class AccessPolicy private constructor( Loading Loading @@ -54,14 +54,22 @@ class AccessPolicy private constructor( with(getSchemePolicy(subject, `object`)) { setDecision(subject, `object`, decision) } } fun initialize(state: AccessState, userIds: IntSet, packageStates: Map<String, PackageState>) { fun initialize( state: AccessState, userIds: IntSet, packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, permissionAllowlist: PermissionAllowlist ) { state.systemState.apply { this.userIds += userIds this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates packageStates.forEach { (_, packageState) -> appIds.getOrPut(packageState.appId) { IndexedListSet() } .add(packageState.packageName) } this.permissionAllowlist = permissionAllowlist } } Loading @@ -83,10 +91,14 @@ class AccessPolicy private constructor( fun MutateStateScope.onStorageVolumeMounted( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, volumeUuid: String?, isSystemUpdated: Boolean ) { newState.systemState.packageStates = packageStates newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates } forEachSchemePolicy { with(it) { onStorageVolumeMounted(volumeUuid, isSystemUpdated) } } Loading @@ -94,18 +106,24 @@ class AccessPolicy private constructor( fun MutateStateScope.onPackageAdded( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String ) { newState.systemState.packageStates = packageStates var isAppIdAdded = false val packageState = packageStates[packageName] // TODO(zhanghai): Remove check before submission. checkNotNull(packageState) // TODO(zhanghai): STOPSHIP: Remove check before feature enable. checkNotNull(packageState) { "Added package $packageName isn't found in packageStates in onPackageAdded()" } val appId = packageState.appId newState.systemState.appIds.getOrPut(appId) { var isAppIdAdded = false newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates appIds.getOrPut(appId) { isAppIdAdded = true IndexedListSet() }.add(packageName) } if (isAppIdAdded) { forEachSchemePolicy { with(it) { onAppIdAdded(appId) } Loading @@ -118,18 +136,22 @@ class AccessPolicy private constructor( fun MutateStateScope.onPackageRemoved( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String, appId: Int ) { newState.systemState.packageStates = packageStates // TODO(zhanghai): STOPSHIP: Remove check before feature enable. check(packageName !in packageStates) { "Removed package $packageName is still in packageStates in onPackageRemoved()" } var isAppIdRemoved = false // TODO(zhanghai): Remove check before submission. check(packageName !in packageStates) newState.systemState.appIds.apply appIds@{ this[appId]?.apply { newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates appIds[appId]?.apply { this -= packageName if (isEmpty()) { this@appIds -= appId appIds -= appId isAppIdRemoved = true } } Loading @@ -146,26 +168,35 @@ class AccessPolicy private constructor( fun MutateStateScope.onPackageInstalled( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String, params: PermissionManagerServiceInternal.PackageInstalledParams, userId: Int ) { newState.systemState.packageStates = packageStates newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates } val packageState = packageStates[packageName] // TODO(zhanghai): Remove check before submission. checkNotNull(packageState) // TODO(zhanghai): STOPSHIP: Remove check before feature enable. checkNotNull(packageState) { "Installed package $packageName isn't found in packageStates in onPackageInstalled()" } forEachSchemePolicy { with(it) { onPackageInstalled(packageState, params, userId) } with(it) { onPackageInstalled(packageState, userId) } } } fun MutateStateScope.onPackageUninstalled( packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, packageName: String, appId: Int, userId: Int ) { newState.systemState.packageStates = packageStates newState.systemState.apply { this.packageStates = packageStates this.disabledSystemPackageStates = disabledSystemPackageStates } forEachSchemePolicy { with(it) { onPackageUninstalled(packageName, appId, userId) } } Loading Loading @@ -298,11 +329,7 @@ abstract class SchemePolicy { open fun MutateStateScope.onPackageRemoved(packageName: String, appId: Int) {} open fun MutateStateScope.onPackageInstalled( packageState: PackageState, params: PermissionManagerServiceInternal.PackageInstalledParams, userId: Int ) {} open fun MutateStateScope.onPackageInstalled(packageState: PackageState, userId: Int) {} open fun MutateStateScope.onPackageUninstalled(packageName: String, appId: Int, userId: Int) {} Loading
services/permission/java/com/android/server/permission/access/AccessState.kt +28 −31 Original line number Diff line number Diff line Loading @@ -19,15 +19,22 @@ package com.android.server.permission.access import android.content.pm.PermissionGroupInfo import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.permission.Permission import com.android.server.pm.permission.PermissionAllowlist import com.android.server.pm.pkg.PackageState class AccessState private constructor( val systemState: SystemState, val userStates: IntMap<UserState> ) { constructor() : this(SystemState(), IntMap()) constructor() : this( SystemState(), IntMap() ) fun copy(): AccessState = AccessState(systemState.copy(), userStates.copy { it.copy() }) fun copy(): AccessState = AccessState( systemState.copy(), userStates.copy { it.copy() } ) } class SystemState private constructor( Loading @@ -39,30 +46,26 @@ class SystemState private constructor( val knownPackages: IntMap<IndexedListSet<String>>, // A map of userId to packageName val deviceAndProfileOwners: IntMap<String>, // A map of packageName to (A map of oem permission name to whether it's granted) val oemPermissions: IndexedMap<String, IndexedMap<String, Boolean>>, val privilegedPermissionAllowlistSourcePackageNames: IndexedListSet<String>, // A map of packageName to a set of vendor priv app permission names val vendorPrivAppPermissions: Map<String, Set<String>>, val productPrivAppPermissions: Map<String, Set<String>>, val systemExtPrivAppPermissions: Map<String, Set<String>>, val privAppPermissions: Map<String, Set<String>>, val apexPrivAppPermissions: Map<String, Map<String, Set<String>>>, val vendorPrivAppDenyPermissions: Map<String, Set<String>>, val productPrivAppDenyPermissions: Map<String, Set<String>>, val systemExtPrivAppDenyPermissions: Map<String, Set<String>>, val apexPrivAppDenyPermissions: Map<String, Map<String, Set<String>>>, val privAppDenyPermissions: Map<String, Set<String>>, var permissionAllowlist: PermissionAllowlist, val implicitToSourcePermissions: Map<String, Set<String>>, val permissionGroups: IndexedMap<String, PermissionGroupInfo>, val permissionTrees: IndexedMap<String, Permission>, val permissions: IndexedMap<String, Permission> ) : WritableState() { constructor() : this( IntSet(), emptyMap(), emptyMap(), IntMap(), IntMap(), IntMap(), IndexedMap(), IndexedListSet(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap() IntSet(), emptyMap(), emptyMap(), IntMap(), IntMap(), IntMap(), IndexedListSet(), PermissionAllowlist(), IndexedMap(), IndexedMap(), IndexedMap(), IndexedMap() ) fun copy(): SystemState = Loading @@ -73,18 +76,8 @@ class SystemState private constructor( appIds.copy { it.copy() }, knownPackages.copy { it.copy() }, deviceAndProfileOwners.copy { it }, oemPermissions.copy { it.copy { it } }, privilegedPermissionAllowlistSourcePackageNames.copy(), vendorPrivAppPermissions, productPrivAppPermissions, systemExtPrivAppPermissions, privAppPermissions, apexPrivAppPermissions, vendorPrivAppDenyPermissions, productPrivAppDenyPermissions, systemExtPrivAppDenyPermissions, apexPrivAppDenyPermissions, privAppDenyPermissions, permissionAllowlist, implicitToSourcePermissions, permissionGroups.copy { it }, permissionTrees.copy { it }, Loading @@ -98,7 +91,11 @@ class UserState private constructor( val uidAppOpModes: IntMap<IndexedMap<String, Int>>, val packageAppOpModes: IndexedMap<String, IndexedMap<String, Int>> ) : WritableState() { constructor() : this(IntMap(), IntMap(), IndexedMap()) constructor() : this( IntMap(), IntMap(), IndexedMap() ) fun copy(): UserState = UserState( uidPermissionFlags.copy { it.copy { it } }, Loading
services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +2 −1 Original line number Diff line number Diff line Loading @@ -435,7 +435,8 @@ class PermissionService( } else { intArrayOf(userId) } userIds.forEach { service.onPackageInstalled(androidPackage.packageName, params, it) } userIds.forEach { service.onPackageInstalled(androidPackage.packageName, it) } // TODO: Handle params. } override fun onPackageUninstalled( Loading
services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt +41 −58 Original line number Diff line number Diff line Loading @@ -597,11 +597,9 @@ class UidPermissionPolicy : SchemePolicy() { newState.systemState.privilegedPermissionAllowlistSourcePackageNames) { return true } if (isInSystemConfigPrivAppPermissions(androidPackage, permission.name)) { return true } if (isInSystemConfigPrivAppDenyPermissions(androidPackage, permission.name)) { return false val allowlistState = getPrivilegedPermissionAllowlistState(androidPackage, permission.name) if (allowlistState != null) { return allowlistState } // Updated system apps do not need to be allowlisted if (packageState.isUpdatedSystemApp) { Loading @@ -611,66 +609,51 @@ class UidPermissionPolicy : SchemePolicy() { return !RoSystemProperties.CONTROL_PRIVAPP_PERMISSIONS_ENFORCE } private fun MutateStateScope.isInSystemConfigPrivAppPermissions( androidPackage: AndroidPackage, permissionName: String ): Boolean { // TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName. The below is only for // passing compilation but won't actually work. //val apexModuleName = androidPackage.apexModuleName val apexModuleName = androidPackage.packageName val systemState = newState.systemState val packageName = androidPackage.packageName val permissionNames = when { androidPackage.isVendor -> systemState.vendorPrivAppPermissions[packageName] androidPackage.isProduct -> systemState.productPrivAppPermissions[packageName] androidPackage.isSystemExt -> systemState.systemExtPrivAppPermissions[packageName] apexModuleName != null -> { val apexPrivAppPermissions = systemState.apexPrivAppPermissions[apexModuleName] ?.get(packageName) val privAppPermissions = systemState.privAppPermissions[packageName] when { apexPrivAppPermissions == null -> privAppPermissions privAppPermissions == null -> apexPrivAppPermissions else -> apexPrivAppPermissions + privAppPermissions } } else -> systemState.privAppPermissions[packageName] } return permissionNames?.contains(permissionName) == true } private fun MutateStateScope.isInSystemConfigPrivAppDenyPermissions( /** * Get the whether a privileged permission is explicitly allowed or denied for a package in the * allowlist, or `null` if it's not in the allowlist. */ private fun MutateStateScope.getPrivilegedPermissionAllowlistState( androidPackage: AndroidPackage, permissionName: String ): Boolean { // Different from the previous implementation, which may incorrectly use the APEX package // name, we now use the APEX module name to be consistent with the allowlist. ): Boolean? { val permissionAllowlist = newState.systemState.permissionAllowlist // TODO(b/261913353): STOPSHIP: Add AndroidPackage.apexModuleName. The below is only for // passing compilation but won't actually work. //val apexModuleName = androidPackage.apexModuleName val apexModuleName = androidPackage.packageName val systemState = newState.systemState val packageName = androidPackage.packageName val permissionNames = when { androidPackage.isVendor -> systemState.vendorPrivAppDenyPermissions[packageName] androidPackage.isProduct -> systemState.productPrivAppDenyPermissions[packageName] androidPackage.isSystemExt -> systemState.systemExtPrivAppDenyPermissions[packageName] // Different from the previous implementation, which ignores the regular priv app // denylist in this case, we now respect it as well to be consistent with the allowlist. return when { androidPackage.isVendor -> permissionAllowlist.getVendorPrivilegedAppAllowlistState( packageName, permissionName ) androidPackage.isProduct -> permissionAllowlist.getProductPrivilegedAppAllowlistState( packageName, permissionName ) androidPackage.isSystemExt -> permissionAllowlist.getSystemExtPrivilegedAppAllowlistState( packageName, permissionName ) apexModuleName != null -> { val apexPrivAppDenyPermissions = systemState .apexPrivAppDenyPermissions[apexModuleName]?.get(packageName) val privAppDenyPermissions = systemState.privAppDenyPermissions[packageName] when { apexPrivAppDenyPermissions == null -> privAppDenyPermissions privAppDenyPermissions == null -> apexPrivAppDenyPermissions else -> apexPrivAppDenyPermissions + privAppDenyPermissions val nonApexAllowlistState = permissionAllowlist.getPrivilegedAppAllowlistState( packageName, permissionName ) if (nonApexAllowlistState != null) { // TODO(andreionea): Remove check as soon as all apk-in-apex // permission allowlists are migrated. Log.w( LOG_TAG, "Package $packageName is an APK in APEX but has permission" + " allowlist on the system image, please bundle the allowlist in the" + " $apexModuleName APEX instead" ) } val apexAllowlistState = permissionAllowlist.getApexPrivilegedAppAllowlistState( apexModuleName, packageName, permissionName ) apexAllowlistState ?: nonApexAllowlistState } else -> systemState.privAppDenyPermissions[packageName] else -> permissionAllowlist.getPrivilegedAppAllowlistState(packageName, permissionName) } return permissionNames?.contains(permissionName) == true } private fun MutateStateScope.anyPackageInAppId( Loading Loading @@ -811,13 +794,13 @@ class UidPermissionPolicy : SchemePolicy() { } permission.isOem -> { if (androidPackage.isOem) { val isOemAllowlisted = newState.systemState .oemPermissions[packageName]?.get(permissionName) checkNotNull(isOemAllowlisted) { val allowlistState = newState.systemState.permissionAllowlist .getOemAppAllowlistState(packageName, permissionName) checkNotNull(allowlistState) { "OEM permission $permissionName requested by package" + " $packageName must be explicitly declared granted or not" } return isOemAllowlisted return allowlistState } } } Loading