Skip to content

签名权限

分析 signature 权限的 signer、lineage capability、knownSigner 和平台白名单判定。

AndroidPMS签名权限

签名权限 ​

signature 权限的授予条件不是简单比较两个证书字节。Android 17 的 AppIdPermissionPolicy 同时考虑权限定义包的签名、请求包的签名 lineage、PERMISSION capability、平台包 lineage,以及平台签名权限的 allowlist。knownSigner 则走证书摘要集合,和普通 signature capability 是两条不同路径。

1. 授予条件分层 ​

层判断
基础类型permission.isSignature
定义包关系sourceSigningDetails 与请求包 signer
lineage 能力PERMISSION
平台关系platform package signer/capability
额外保护platform signature allowlist、knownSigner

2. 类型与标志 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/Permission.kt

kotlin
inline val isSignature: Boolean
    get() = protection == PermissionInfo.PROTECTION_SIGNATURE

inline val isKnownSigner: Boolean
    get() = protectionFlags.hasBits(
        PermissionInfo.PROTECTION_FLAG_KNOWN_SIGNER)

inline val knownCerts: Set<String>
    get() = permissionInfo.knownCerts

isSignature 只看基础 protection,knownSigner 是附加 flag。一个 permission 可以是 signature 基础级别并附加 privileged、knownSigner 等策略;代码必须分别读取这两个属性。

3. 签名关系主函数 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt

kotlin
private fun MutateStateScope.shouldGrantPermissionBySignature(
    packageState: PackageState,
    permission: Permission,
): Boolean {
    val packageSigningDetails =
        packageState.androidPackage!!.signingDetails
    val sourceSigningDetails =
        newState.externalState.packageStates[permission.packageName]
            ?.androidPackage?.signingDetails
    val platformSigningDetails =
        newState.externalState.packageStates[PLATFORM_PACKAGE_NAME]!!
            .androidPackage!!.signingDetails
    val hasCommonSigner =
        sourceSigningDetails?.hasCommonSignerWithCapability(
            packageSigningDetails,
            SigningDetails.CertCapabilities.PERMISSION,
        ) == true ||
            packageSigningDetails.hasAncestorOrSelf(
                platformSigningDetails) ||
            platformSigningDetails.checkCapability(
                packageSigningDetails,
                SigningDetails.CertCapabilities.PERMISSION,
            )

允许来源有三类:定义包与请求包共享具备 PERMISSION 的 signer;请求包 lineage 包含平台 signer;平台 signer 对请求包授予 PERMISSION capability。未知定义包签名时,第一项为空,后两项仍可能决定结果。

4. 能力与精确匹配 ​

hasCommonSignerWithCapability 允许在 lineage 中寻找共同 signer;checkCapability 则要求目标旧 signer 出现在当前对象的 lineage,并且历史 Signature.flags 包含所需能力。多 signer 包不支持 rotation,最终退化为 exact match。

java
boolean matchFound = hasCertificate(
        oldDetails.mSignatures[0], flags);
if (oldDetails.mSignatures.length > 1) {
    return signaturesMatchExactly(oldDetails);
}

因此签名权限问题不能只看“当前证书不同”。应继续检查旧证书是否位于 lineage,以及新 signer 是否仍授予 PERMISSION。

5. 平台权限白名单 ​

kotlin
if (!Flags.signaturePermissionAllowlistEnabled()) {
    return hasCommonSigner
}
if (!hasCommonSigner) {
    return false
}
if (permission.packageName == PLATFORM_PACKAGE_NAME) {
    val isRequestedByFactoryApp =
        if (packageState.isSystem) {
            if (packageState.isUpdatedSystemApp) {
                val disabledSystemPackage =
                    newState.externalState.disabledSystemPackageStates[
                        packageState.packageName]?.androidPackage
                disabledSystemPackage != null &&
                    permission.name in
                        disabledSystemPackage.requestedPermissions
            } else {
                true
            }
        } else {
            false
        }
    if (!(isRequestedByFactoryApp ||
        getSignaturePermissionAllowlistState(
            packageState, permission.name) == true
    )) {
        if (!Build.isDebuggable()
                || isSignaturePermissionAllowlistForceEnforced) {
            return false
        }
    }
}
return true

allowlist flag 关闭时,签名关系足够;开启后,平台包定义的 signature permission 还要求出厂 system app 请求过,或签名 allowlist 明确为 true。debuggable 构建默认可只告警,user 构建或 force-enforced 则拒绝。

6. knownSigner 路径 ​

源码文件:frameworks/base/services/permission/java/com/android/server/permission/access/permission/AppIdPermissionPolicy.kt

kotlin
if (
    permission.isKnownSigner &&
    androidPackage.signingDetails.hasAncestorOrSelfWithDigest(
        permission.knownCerts)
) {
    return true
}

knownSigner 不要求请求包与定义包拥有同一 signer,而是检查请求包当前/历史证书的 SHA-256 digest 是否落在 permission 的 knownCerts 集合。摘要匹配成功后即可满足该附加策略,但仍处在整体权限授予重算流程中。

7. 其他保护标志 ​

签名关系通过后,policy 还会处理 installer、verifier、preInstalled、setup、module、role 等附加 flag。它们依据 known package、系统分区或角色 holder 判断,不应与 PERMISSION capability 混为一谈。

8. 权限重算时机 ​

kotlin
val shouldGrantBySignature =
    permission.isSignature &&
        requestingPackageStates.anyIndexed { _, packageState ->
            shouldGrantPermissionBySignature(
                packageState, permission)
        }
if (mayGrantByPrivileged &&
    (shouldGrantBySignature || shouldGrantByProtectionFlags)
) {
    PermissionFlags.PROTECTION_GRANTED
}

签名权限不是在每次 checkPermission 时重新比较证书,而是在包扫描、安装更新和权限状态 reconcile 时计算 flags。之后运行时检查读取已计算的 PROTECTION_GRANTED,签名变更会触发下一次重算和必要的状态清理。

9. 排查清单 ​

  1. 确认 permission 基础 protection 是否为 signature,附加 flag 是否包含 knownSigner/privileged。
  2. 对比定义包、请求包和 platform 包的 SigningDetails。
  3. 检查 lineage 中旧 signer 的 PERMISSION flags,而不是只看当前证书。
  4. 多 signer 包按 exact match 排查,不套用 rotation。
  5. 平台 signature permission 检查 factory app 请求和分区 allowlist。
  6. knownSigner 权限检查 knownCerts digest 是否包含当前/历史证书。
  7. 确认权限状态是否经历了包更新后的 reconcile;旧 flags 可能尚未被清理或重算。

10. 源码阅读路线 ​

  1. Permission.isSignature/isKnownSigner/knownCerts:确认类型与附加标志。
  2. AppIdPermissionPolicy.shouldGrantPermissionBySignature:主授予路径。
  3. SigningDetails.hasCommonSignerWithCapability:定义包与请求包的共同 signer。
  4. SigningDetails.checkCapability:lineage capability 判定。
  5. AppIdPermissionPolicy 的 knownSigner 和平台 allowlist 分支。
  6. 权限 reconcile 中 PROTECTION_GRANTED 写入:确认何时把签名关系变成用户状态。

签名权限的核心不是“证书相等”,而是 signer 身份、lineage 方向、PERMISSION capability、平台 allowlist 和 knownCerts 共同决定的策略。把这些条件拆开阅读,才能解释密钥轮换后权限为何继续保留、被撤销或只在特定构建中失败。