summaryrefslogtreecommitdiff
path: root/services/permission/java
diff options
context:
space:
mode:
author Hai Zhang <zhanghai@google.com> 2022-12-17 19:24:15 -0800
committer Hai Zhang <zhanghai@google.com> 2022-12-19 01:15:47 -0800
commit4b8c2445896947b1451a754759efb76bf2e1ed45 (patch)
tree4b34837c9e3ef6b37e8201018a0623a0a0c83b75 /services/permission/java
parent60d184bdfa8100b6122cb53cfd0b6bdf2dcddb54 (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')
-rw-r--r--services/permission/java/com/android/server/permission/access/AccessCheckingService.kt98
-rw-r--r--services/permission/java/com/android/server/permission/access/AccessPolicy.kt21
-rw-r--r--services/permission/java/com/android/server/permission/access/AccessState.kt25
-rw-r--r--services/permission/java/com/android/server/permission/access/permission/Permission.kt113
-rw-r--r--services/permission/java/com/android/server/permission/access/permission/PermissionService.kt58
-rw-r--r--services/permission/java/com/android/server/permission/access/permission/UidPermissionPolicy.kt60
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)