diff options
| author | 2022-12-17 19:24:15 -0800 | |
|---|---|---|
| committer | 2022-12-19 01:15:47 -0800 | |
| commit | 4b8c2445896947b1451a754759efb76bf2e1ed45 (patch) | |
| tree | 4b34837c9e3ef6b37e8201018a0623a0a0c83b75 /services/permission/java | |
| parent | 60d184bdfa8100b6122cb53cfd0b6bdf2dcddb54 (diff) | |
Add config permissions and GIDs handling.
Also set up more actual system states, except for device and profile
owners.
Also add missing runtime-only permission handling, and reorder items
in Permission.kt.
Bug: 252884423
Test: presubmit
Change-Id: I6faf6c192b11ee668cf442dd8b885e761eefea6b
Diffstat (limited to 'services/permission/java')
6 files changed, 286 insertions, 89 deletions
diff --git a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt index 306970a22d62..3b277f8fbb8a 100644 --- a/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt +++ b/services/permission/java/com/android/server/permission/access/AccessCheckingService.kt @@ -17,6 +17,10 @@ package com.android.server.permission.access import android.content.Context +import android.content.pm.PackageManager +import android.content.pm.PackageManagerInternal +import android.os.SystemProperties +import android.os.UserHandle import com.android.internal.annotations.Keep import com.android.server.LocalManagerRegistry import com.android.server.LocalServices @@ -24,12 +28,16 @@ import com.android.server.SystemConfig import com.android.server.SystemService import com.android.server.appop.AppOpsCheckingServiceInterface import com.android.server.permission.access.appop.AppOpService -import com.android.server.permission.access.collection.IntSet +import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports import com.android.server.permission.access.permission.PermissionService +import com.android.server.pm.KnownPackages import com.android.server.pm.PackageManagerLocal import com.android.server.pm.UserManagerService import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.pkg.PackageState +import kotlin.contracts.ExperimentalContracts +import kotlin.contracts.InvocationKind +import kotlin.contracts.contract @Keep class AccessCheckingService(context: Context) : SystemService(context) { @@ -44,6 +52,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { private lateinit var appOpService: AppOpService private lateinit var permissionService: PermissionService + private lateinit var packageManagerInternal: PackageManagerInternal private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var userManagerService: UserManagerService private lateinit var systemConfig: SystemConfig @@ -57,6 +66,7 @@ class AccessCheckingService(context: Context) : SystemService(context) { } fun initialize() { + packageManagerInternal = LocalServices.getService(PackageManagerInternal::class.java) packageManagerLocal = LocalManagerRegistry.getManagerOrThrow(PackageManagerLocal::class.java) userManagerService = UserManagerService.getInstance() @@ -64,19 +74,94 @@ class AccessCheckingService(context: Context) : SystemService(context) { val userIds = IntSet(userManagerService.userIdsIncludingPreCreated) val (packageStates, disabledSystemPackageStates) = packageManagerLocal.allPackageStates + val knownPackages = packageManagerInternal.knownPackages + val isLeanback = systemConfig.isLeanback + val configPermissions = systemConfig.permissions + val privilegedPermissionAllowlistPackages = + systemConfig.privilegedPermissionAllowlistPackages val permissionAllowlist = systemConfig.permissionAllowlist + val implicitToSourcePermissions = systemConfig.implicitToSourcePermissions val state = AccessState() policy.initialize( - state, userIds, packageStates, disabledSystemPackageStates, permissionAllowlist + state, userIds, packageStates, disabledSystemPackageStates, knownPackages, isLeanback, + configPermissions, privilegedPermissionAllowlistPackages, permissionAllowlist, + implicitToSourcePermissions ) persistence.read(state) this.state = state + mutateState { + with(policy) { onInitialized() } + } + appOpService.initialize() permissionService.initialize() } + private val PackageManagerInternal.knownPackages: IntMap<Array<String>> + get() = IntMap<Array<String>>().apply { + this[KnownPackages.PACKAGE_INSTALLER] = getKnownPackageNames( + KnownPackages.PACKAGE_INSTALLER, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_PERMISSION_CONTROLLER] = getKnownPackageNames( + KnownPackages.PACKAGE_PERMISSION_CONTROLLER, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_VERIFIER] = getKnownPackageNames( + KnownPackages.PACKAGE_VERIFIER, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_SETUP_WIZARD] = getKnownPackageNames( + KnownPackages.PACKAGE_SETUP_WIZARD, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER] = getKnownPackageNames( + KnownPackages.PACKAGE_SYSTEM_TEXT_CLASSIFIER, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_CONFIGURATOR] = getKnownPackageNames( + KnownPackages.PACKAGE_CONFIGURATOR, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER] = getKnownPackageNames( + KnownPackages.PACKAGE_INCIDENT_REPORT_APPROVER, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_APP_PREDICTOR] = getKnownPackageNames( + KnownPackages.PACKAGE_APP_PREDICTOR, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_COMPANION] = getKnownPackageNames( + KnownPackages.PACKAGE_COMPANION, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_RETAIL_DEMO] = getKnownPackageNames( + KnownPackages.PACKAGE_RETAIL_DEMO, UserHandle.USER_SYSTEM + ) + this[KnownPackages.PACKAGE_RECENTS] = getKnownPackageNames( + KnownPackages.PACKAGE_RECENTS, UserHandle.USER_SYSTEM + ) + } + + private val SystemConfig.isLeanback: Boolean + get() = PackageManager.FEATURE_LEANBACK in availableFeatures + + private val SystemConfig.privilegedPermissionAllowlistPackages: IndexedListSet<String> + get() = IndexedListSet<String>().apply { + this += "android" + if (PackageManager.FEATURE_AUTOMOTIVE in availableFeatures) { + // Note that SystemProperties.get(String, String) forces returning an empty string + // even if we pass null for the def parameter. + val carServicePackage = SystemProperties.get("ro.android.car.carservice.package") + if (carServicePackage.isNotEmpty()) { + this += carServicePackage + } + } + } + + private val SystemConfig.implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> + get() = IndexedMap<String, IndexedListSet<String>>().apply { + splitPermissions.forEach { splitPermissionInfo -> + val sourcePermissionName = splitPermissionInfo.splitPermission + splitPermissionInfo.newPermissions.forEach { implicitPermissionName -> + getOrPut(implicitPermissionName) { IndexedListSet() } += sourcePermissionName + } + } + } + fun getDecision(subject: AccessUri, `object`: AccessUri): Int = getState { with(policy) { getDecision(subject, `object`) } @@ -151,10 +236,15 @@ class AccessCheckingService(context: Context) : SystemService(context) { 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() + @OptIn(ExperimentalContracts::class) + internal inline fun <T> getState(action: GetStateScope.() -> T): T { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } + return GetStateScope(state).action() + } + @OptIn(ExperimentalContracts::class) internal inline fun mutateState(crossinline action: MutateStateScope.() -> Unit) { + contract { callsInPlace(action, InvocationKind.EXACTLY_ONCE) } synchronized(stateLock) { val oldState = state val newState = oldState.copy() diff --git a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt index 8cf4aeec585c..2d83bfd5a526 100644 --- a/services/permission/java/com/android/server/permission/access/AccessPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/AccessPolicy.kt @@ -19,6 +19,7 @@ package com.android.server.permission.access import android.util.Log import com.android.modules.utils.BinaryXmlPullParser import com.android.modules.utils.BinaryXmlSerializer +import com.android.server.SystemConfig import com.android.server.permission.access.appop.PackageAppOpPolicy import com.android.server.permission.access.appop.UidAppOpPolicy import com.android.server.permission.access.collection.* // ktlint-disable no-wildcard-imports @@ -59,7 +60,12 @@ class AccessPolicy private constructor( userIds: IntSet, packageStates: Map<String, PackageState>, disabledSystemPackageStates: Map<String, PackageState>, - permissionAllowlist: PermissionAllowlist + knownPackages: IntMap<Array<String>>, + isLeanback: Boolean, + configPermissions: Map<String, SystemConfig.PermissionEntry>, + privilegedPermissionAllowlistPackages: IndexedListSet<String>, + permissionAllowlist: PermissionAllowlist, + implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>> ) { state.systemState.apply { this.userIds += userIds @@ -69,7 +75,12 @@ class AccessPolicy private constructor( appIds.getOrPut(packageState.appId) { IndexedListSet() } .add(packageState.packageName) } + this.knownPackages = knownPackages + this.isLeanback = isLeanback + this.configPermissions = configPermissions + this.privilegedPermissionAllowlistPackages = privilegedPermissionAllowlistPackages this.permissionAllowlist = permissionAllowlist + this.implicitToSourcePermissions = implicitToSourcePermissions } } @@ -79,6 +90,12 @@ class AccessPolicy private constructor( } } + fun MutateStateScope.onInitialized() { + forEachSchemePolicy { + with(it) { onInitialized() } + } + } + fun MutateStateScope.onUserAdded(userId: Int) { newState.systemState.userIds += userId newState.userStates[userId] = UserState() @@ -292,6 +309,8 @@ abstract class SchemePolicy { open fun GetStateScope.onStateMutated() {} + open fun MutateStateScope.onInitialized() {} + open fun MutateStateScope.onUserAdded(userId: Int) {} open fun MutateStateScope.onUserRemoved(userId: Int) {} diff --git a/services/permission/java/com/android/server/permission/access/AccessState.kt b/services/permission/java/com/android/server/permission/access/AccessState.kt index 6924d5139737..961619304531 100644 --- a/services/permission/java/com/android/server/permission/access/AccessState.kt +++ b/services/permission/java/com/android/server/permission/access/AccessState.kt @@ -17,6 +17,7 @@ package com.android.server.permission.access import android.content.pm.PermissionGroupInfo +import com.android.server.SystemConfig 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 @@ -42,15 +43,15 @@ class SystemState private constructor( var packageStates: Map<String, PackageState>, var disabledSystemPackageStates: Map<String, PackageState>, val appIds: IntMap<IndexedListSet<String>>, - // A map of KnownPackagesInt to a set of known package names - val knownPackages: IntMap<IndexedListSet<String>>, - // A map of userId to packageName - val deviceAndProfileOwners: IntMap<String>, - // Whether the device supports leanback UI + // Mapping from KnownPackages keys to package names. + var knownPackages: IntMap<Array<String>>, var isLeanback: Boolean, - val privilegedPermissionAllowlistSourcePackageNames: IndexedListSet<String>, + var configPermissions: Map<String, SystemConfig.PermissionEntry>, + var privilegedPermissionAllowlistPackages: IndexedListSet<String>, var permissionAllowlist: PermissionAllowlist, - val implicitToSourcePermissions: Map<String, Set<String>>, + var implicitToSourcePermissions: IndexedMap<String, IndexedListSet<String>>, + // Mapping from user ID to package name. + var deviceAndProfileOwners: IntMap<String>, val permissionGroups: IndexedMap<String, PermissionGroupInfo>, val permissionTrees: IndexedMap<String, Permission>, val permissions: IndexedMap<String, Permission> @@ -61,11 +62,12 @@ class SystemState private constructor( emptyMap(), IntMap(), IntMap(), - IntMap(), false, + emptyMap(), IndexedListSet(), PermissionAllowlist(), IndexedMap(), + IntMap(), IndexedMap(), IndexedMap(), IndexedMap() @@ -77,12 +79,13 @@ class SystemState private constructor( packageStates, disabledSystemPackageStates, appIds.copy { it.copy() }, - knownPackages.copy { it.copy() }, - deviceAndProfileOwners.copy { it }, + knownPackages, isLeanback, - privilegedPermissionAllowlistSourcePackageNames.copy(), + configPermissions, + privilegedPermissionAllowlistPackages, permissionAllowlist, implicitToSourcePermissions, + deviceAndProfileOwners, permissionGroups.copy { it }, permissionTrees.copy { it }, permissions.copy { it } diff --git a/services/permission/java/com/android/server/permission/access/permission/Permission.kt b/services/permission/java/com/android/server/permission/access/permission/Permission.kt index de2df74756b0..88989c4bf201 100644 --- a/services/permission/java/com/android/server/permission/access/permission/Permission.kt +++ b/services/permission/java/com/android/server/permission/access/permission/Permission.kt @@ -17,13 +17,18 @@ package com.android.server.permission.access.permission import android.content.pm.PermissionInfo +import android.os.UserHandle import com.android.server.permission.access.util.hasBits +import libcore.util.EmptyArray data class Permission( val permissionInfo: PermissionInfo, val isReconciled: Boolean, val type: Int, - val appId: Int + val appId: Int, + @Suppress("ArrayInDataClass") + val gids: IntArray = EmptyArray.INT, + val areGidsPerUser: Boolean = false ) { inline val name: String get() = permissionInfo.name @@ -37,36 +42,50 @@ data class Permission( inline val isDynamic: Boolean get() = type == TYPE_DYNAMIC + inline val protectionLevel: Int + @Suppress("DEPRECATION") + get() = permissionInfo.protectionLevel + + inline val isInternal: Boolean + get() = permissionInfo.protection == PermissionInfo.PROTECTION_INTERNAL + inline val isNormal: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_NORMAL inline val isRuntime: Boolean get() = permissionInfo.protection == PermissionInfo.PROTECTION_DANGEROUS - inline val isAppOp: Boolean - get() = permissionInfo.protection == PermissionInfo.PROTECTION_FLAG_APPOP - - inline val isRemoved: Boolean - get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_REMOVED) + inline val isSignature: Boolean + get() = permissionInfo.protection == PermissionInfo.PROTECTION_SIGNATURE - inline val isSoftRestricted: Boolean - get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED) + inline val isAppOp: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APPOP) - inline val isHardRestricted: Boolean - get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_HARD_RESTRICTED) + inline val isAppPredictor: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) - inline val isSignature: Boolean - get() = permissionInfo.protection == PermissionInfo.PROTECTION_SIGNATURE + inline val isCompanion: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_COMPANION) - inline val isInternal: Boolean - get() = permissionInfo.protection == PermissionInfo.PROTECTION_INTERNAL + inline val isConfigurator: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) inline val isDevelopment: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_DEVELOPMENT) + inline val isIncidentReportApprover: Boolean + get() = permissionInfo.protectionFlags + .hasBits(PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) + inline val isInstaller: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_INSTALLER) + inline val isInstant: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_INSTANT) + + inline val isKnownSigner: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER) + inline val isOem: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_OEM) @@ -79,54 +98,53 @@ data class Permission( inline val isPrivileged: Boolean get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_PRIVILEGED) - inline val isSetup: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_SETUP) + inline val isRecents: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RECENTS) - inline val isVerifier: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_VERIFIER) + inline val isRetailDemo: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) - inline val isVendorPrivileged: Boolean - get() = permissionInfo.protectionFlags - .hasBits(PROTECTION_FLAG_VENDOR_PRIVILEGED) + inline val isRole: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_ROLE) + + inline val isRuntimeOnly: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RUNTIME_ONLY) + + inline val isSetup: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_SETUP) inline val isSystemTextClassifier: Boolean get() = permissionInfo.protectionFlags .hasBits(PermissionInfo.PROTECTION_FLAG_SYSTEM_TEXT_CLASSIFIER) - inline val isConfigurator: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_CONFIGURATOR) - - inline val isIncidentReportApprover: Boolean + inline val isVendorPrivileged: Boolean get() = permissionInfo.protectionFlags - .hasBits(PermissionInfo.PROTECTION_FLAG_INCIDENT_REPORT_APPROVER) - - inline val isAppPredictor: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_APP_PREDICTOR) + .hasBits(PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED) - inline val isCompanion: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_COMPANION) + inline val isVerifier: Boolean + get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_VERIFIER) - inline val isRetailDemo: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RETAIL_DEMO) + inline val isHardRestricted: Boolean + get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_HARD_RESTRICTED) - inline val isRecents: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_RECENTS) + inline val isRemoved: Boolean + get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_REMOVED) - inline val isRole: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_ROLE) + inline val isSoftRestricted: Boolean + get() = permissionInfo.flags.hasBits(PermissionInfo.FLAG_SOFT_RESTRICTED) - inline val isKnownSigner: Boolean - get() = permissionInfo.protectionFlags.hasBits(PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER) + inline val knownCerts: Set<String> + get() = permissionInfo.knownCerts inline val hasGids: Boolean - get() = throw NotImplementedError() + get() = gids.isNotEmpty() - inline val protectionLevel: Int - @Suppress("DEPRECATION") - get() = permissionInfo.protectionLevel - - inline val knownCerts: Set<String> - get() = permissionInfo.knownCerts + fun getGidsForUser(userId: Int): IntArray = + if (areGidsPerUser) { + IntArray(gids.size) { i -> UserHandle.getUid(userId, gids[i]) } + } else { + gids.clone() + } companion object { // The permission is defined in an application manifest. @@ -135,8 +153,5 @@ data class Permission( const val TYPE_CONFIG = 1 // The permission is defined dynamically. const val TYPE_DYNAMIC = 2 - - // TODO: PermissionInfo.PROTECTION_FLAG_VENDOR_PRIVILEGED is a testApi - const val PROTECTION_FLAG_VENDOR_PRIVILEGED = 0x8000 } } diff --git a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt index ff7483ffcc60..f8ab6e9f755c 100644 --- a/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt +++ b/services/permission/java/com/android/server/permission/access/permission/PermissionService.kt @@ -40,6 +40,7 @@ import android.os.UserHandle import android.permission.IOnPermissionsChangeListener import android.permission.PermissionManager import android.provider.Settings +import android.util.IntArray as GrowingIntArray import android.util.Log import com.android.internal.compat.IPlatformCompat import com.android.server.FgThread @@ -61,6 +62,7 @@ import com.android.server.pm.permission.LegacyPermissionState import com.android.server.pm.permission.PermissionManagerServiceInterface import com.android.server.pm.permission.PermissionManagerServiceInternal import com.android.server.pm.pkg.AndroidPackage +import libcore.util.EmptyArray import java.io.FileDescriptor import java.io.PrintWriter @@ -77,6 +79,7 @@ class PermissionService( private lateinit var packageManagerInternal: PackageManagerInternal private lateinit var packageManagerLocal: PackageManagerLocal private lateinit var platformCompat: IPlatformCompat + private lateinit var systemConfig: SystemConfig private lateinit var userManagerService: UserManagerService private val mountedStorageVolumes = IndexedSet<String?>() @@ -94,6 +97,7 @@ class PermissionService( platformCompat = IPlatformCompat.Stub.asInterface( ServiceManager.getService(Context.PLATFORM_COMPAT_SERVICE) ) + systemConfig = SystemConfig.getInstance() userManagerService = UserManagerService.getInstance() handlerThread = ServiceThread(LOG_TAG, Process.THREAD_PRIORITY_BACKGROUND, true) @@ -263,7 +267,10 @@ class PermissionService( } override fun getPermissionGids(permissionName: String, userId: Int): IntArray { - TODO("Not yet implemented") + val permission = service.getState { + with(policy) { getPermissions()[permissionName] } + } ?: return EmptyArray.INT + return permission.getGidsForUser(userId) } override fun addPermission(permissionInfo: PermissionInfo, async: Boolean): Boolean { @@ -286,6 +293,29 @@ class PermissionService( TODO("Not yet implemented") } + override fun getGidsForUid(uid: Int): IntArray { + val appId = UserHandle.getAppId(uid) + val userId = UserHandle.getUserId(uid) + val permissionFlags = service.getState { + with(policy) { getUidPermissionFlags(appId, userId) } + } ?: return EmptyArray.INT + val gids = GrowingIntArray.wrap(systemConfig.globalGids) + permissionFlags.forEachIndexed { _, permissionName, flags -> + if (!PermissionFlags.isPermissionGranted(flags)) { + return@forEachIndexed + } + val permission = service.getState { + with(policy) { getPermissions()[permissionName] } + } ?: return@forEachIndexed + val permissionGids = permission.getGidsForUser(userId) + if (permissionGids.isEmpty()) { + return@forEachIndexed + } + gids.addAll(permissionGids) + } + return gids.toArray() + } + override fun grantRuntimePermission(packageName: String, permissionName: String, userId: Int) { TODO("Not yet implemented") } @@ -306,14 +336,6 @@ class PermissionService( TODO("Not yet implemented") } - override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { - onPermissionsChangeListeners.addListener(listener) - } - - override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { - onPermissionsChangeListeners.removeListener(listener) - } - override fun getPermissionFlags(packageName: String, permissionName: String, userId: Int): Int { // TODO: Implement permission checks. val appId = 0 @@ -493,21 +515,29 @@ class PermissionService( TODO("Not yet implemented") } + override fun addOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { + onPermissionsChangeListeners.addListener(listener) + } + + override fun removeOnPermissionsChangeListener(listener: IOnPermissionsChangeListener) { + onPermissionsChangeListeners.removeListener(listener) + } + override fun addOnRuntimePermissionStateChangedListener( listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener ) { - TODO("Not yet implemented") + // TODO: Should be removed once we remove PermissionPolicyService. } override fun removeOnRuntimePermissionStateChangedListener( listener: PermissionManagerServiceInternal.OnRuntimePermissionStateChangedListener ) { - TODO("Not yet implemented") + // TODO: Should be removed once we remove PermissionPolicyService. } override fun getSplitPermissions(): List<SplitPermissionInfoParcelable> { return PermissionManager.splitPermissionInfoListToParcelableList( - SystemConfig.getInstance().splitPermissions + systemConfig.splitPermissions ) } @@ -534,10 +564,6 @@ class PermissionService( return appOpPermissionPackageNames } - override fun getGidsForUid(uid: Int): IntArray { - TODO("Not yet implemented") - } - override fun backupRuntimePermissions(userId: Int): ByteArray? { TODO("Not yet implemented") } diff --git a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt index 1c36bccfa9fd..49759c05489a 100644 --- a/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt +++ b/services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt @@ -78,6 +78,38 @@ class UidPermissionPolicy : SchemePolicy() { onPermissionFlagsChangedListeners.forEachIndexed { _, it -> it.onStateMutated() } } + override fun MutateStateScope.onInitialized() { + newState.systemState.configPermissions.forEach { (permissionName, permissionEntry) -> + val permissions = newState.systemState.permissions + val oldPermission = permissions[permissionName] + val newPermission = if (oldPermission != null) { + if (permissionEntry.gids != null) { + oldPermission.copy( + gids = permissionEntry.gids, areGidsPerUser = permissionEntry.perUser + ) + } else { + return@forEach + } + } else { + @Suppress("DEPRECATION") + val permissionInfo = PermissionInfo().apply { + name = permissionName + packageName = PLATFORM_PACKAGE_NAME + protectionLevel = PermissionInfo.PROTECTION_SIGNATURE + } + if (permissionEntry.gids != null) { + Permission( + permissionInfo, false, Permission.TYPE_CONFIG, 0, permissionEntry.gids, + permissionEntry.perUser + ) + } else { + Permission(permissionInfo, false, Permission.TYPE_CONFIG, 0) + } + } + permissions[permissionName] = newPermission + } + } + override fun MutateStateScope.onUserAdded(userId: Int) { newState.systemState.packageStates.forEach { (_, packageState) -> evaluateAllPermissionStatesForPackageAndUser(packageState, userId, null) @@ -142,6 +174,7 @@ class UidPermissionPolicy : SchemePolicy() { addPermissionGroups(packageState) addPermissions(packageState, changedPermissionNames) // TODO: revokeStoragePermissionsIfScopeExpandedInternal() + // TODO: revokeSystemAlertWindowIfUpgradedPast23() trimPermissions(packageState.packageName, changedPermissionNames) trimPermissionStates(packageState.appId) changedPermissionNames.forEachIndexed { _, permissionName -> @@ -348,6 +381,8 @@ class UidPermissionPolicy : SchemePolicy() { if (packageState != null && androidPackage == null) { return } + // TODO: STOPSHIP: We may need to retain permission definitions by disabled system packages + // to retain their permission state. val isPermissionTreeRemoved = systemState.permissionTrees.removeAllIndexed { _, permissionTreeName, permissionTree -> @@ -417,6 +452,7 @@ class UidPermissionPolicy : SchemePolicy() { val requestedPermissions = IndexedSet<String>() forEachPackageInAppId(appId) { requestedPermissions += it.androidPackage!!.requestedPermissions + // TODO: STOPSHIP: Retain permissions requested by disabled system packages. } newState.userStates.forEachIndexed { _, userId, userState -> userState.uidPermissionFlags[appId].forEachReversedIndexed { _, permissionName, _ -> @@ -556,12 +592,21 @@ class UidPermissionPolicy : SchemePolicy() { } else if (permission.isRuntime) { var newFlags = oldFlags and PermissionFlags.MASK_RUNTIME if (getAppIdTargetSdkVersion(appId, permissionName) < Build.VERSION_CODES.M) { - newFlags = newFlags or PermissionFlags.LEGACY_GRANTED - // Explicitly check against the old state to determine if this permission is new. - val isNewPermission = - getOldStatePermissionFlags(appId, userId, permissionName) == 0 - if (isNewPermission) { - newFlags = newFlags or PermissionFlags.IMPLICIT + if (permission.isRuntimeOnly) { + // Different from the old implementation, which simply skips a runtime-only + // permission, we now only allow holding on to the restriction related flags, + // since such flags may only be set one-time in some cases, and disallow all + // other flags thus keeping it revoked. + newFlags = newFlags and PermissionFlags.MASK_EXEMPT + } else { + newFlags = newFlags or PermissionFlags.LEGACY_GRANTED + // Explicitly check against the old state to determine if this permission is + // new. + val isNewPermission = + getOldStatePermissionFlags(appId, userId, permissionName) == 0 + if (isNewPermission) { + newFlags = newFlags or PermissionFlags.IMPLICIT + } } } else { newFlags = newFlags andInv PermissionFlags.LEGACY_GRANTED @@ -743,8 +788,7 @@ class UidPermissionPolicy : SchemePolicy() { if (!androidPackage.isPrivileged) { return true } - if (permission.packageName !in - newState.systemState.privilegedPermissionAllowlistSourcePackageNames) { + if (permission.packageName !in newState.systemState.privilegedPermissionAllowlistPackages) { return true } val allowlistState = getPrivilegedPermissionAllowlistState(androidPackage, permission.name) |