Skip to content

平台签名

分析 platform package 签名基准、android.uid.system 和平台签名能力判断。

AndroidPMS签名SharedUserId

平台签名 ​

平台签名不是一个“系统应用标志”。Android 17 把 platform package 的 SigningDetails 作为签名基准,把 android.uid.system 作为预注册 shared UID,再由 lineage/capability 判断包是否可以被视为平台签名。system、privileged、platform-signed 是三个不同概念。

1. 三个概念 ​

概念由谁决定含义
system app包路径/flags包来自系统分区
privileged app包路径/flags包位于 priv-app
platform signedSigningDetailssigner 与 platform package 相同或被授权

privileged app 仍受 allowlist;platform signed 也不自动获得所有 internal/OEM 权限。最终权限由 protection policy 和白名单共同决定。

2. 平台包基准 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

java
public static final String PLATFORM_PACKAGE_NAME = "android";

@GuardedBy("mLock")
private AndroidPackage mPlatformPackage;

platform package 的包名是 android。扫描到该包时 PMS 保存其 AndroidPackage,后续 isPlatformSigned 直接使用它的 SigningDetails,而不是读取某个固定证书文件路径。

java
if (PLATFORM_PACKAGE_NAME.equals(pkg.getPackageName())) {
    mPlatformPackage = pkg;
    synchronized (mLock) {
        mSettings.setRuntimePermissionsFingerPrint(
                getRuntimePermissionsFingerPrint());
    }
}

平台包状态和 runtime permission fingerprint 在扫描阶段建立;平台 key 变更会影响权限迁移和所有基于 platform signer 的判断。

3. system UID 注册 ​

java
mSettings.addSharedUserLPw(
        "android.uid.system", Process.SYSTEM_UID,
        ApplicationInfo.FLAG_SYSTEM,
        ApplicationInfo.PRIVATE_FLAG_PRIVILEGED);

android.uid.system 在 Settings 初始化时预注册到 UID 1000,并带有 system/privileged flags。声明该 sharedUserId 的 APK 只能在扫描时通过 shared UID signer 检查后加入;UID 映射本身不替代签名验证。

java
if (s.mAppId == uid) {
    return s;
}
PackageManagerService.reportSettingsProblem(
        Log.ERROR,
        "Adding duplicate shared user, keeping first: " + name);
return null;

同名 shared user 的 UID 不一致会被视为设置错误,保留第一次注册的映射。

4. isPlatformSigned ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java

java
public boolean isPlatformSigned(String packageName) {
    PackageStateInternal packageState =
            snapshot().getPackageStateInternal(packageName);
    if (packageState == null) return false;
    SigningDetails signingDetails =
            packageState.getSigningDetails();
    return signingDetails.hasAncestorOrSelf(
            mPlatformPackage.getSigningDetails())
            || mPlatformPackage.getSigningDetails().checkCapability(
                    signingDetails,
                    SigningDetails.CertCapabilities.PERMISSION);
}

判断有两个方向:

  • 请求包 lineage 包含 platform signer,说明它从平台 key 轮换而来。
  • platform signer 对请求包 signer 授予 PERMISSION capability,允许平台签名权限关系在特定 lineage 中延续。

这不是简单的 Signature.equals,也不是只看 ApplicationInfo.FLAG_SYSTEM。

5. shared UID 校验 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java

java
if (sharedUserSetting != null) {
    final SigningDetails sharedUserSignatures =
            sharedUserSetting.getSigningDetails();
    if (sharedUserSignatures != SigningDetails.UNKNOWN) {
        final boolean sigMatch =
                PackageManagerServiceUtils.canJoinSharedUserId(
                        pkg.getPackageName(),
                        pkg.getSigningDetails(),
                        sharedUserSetting,
                        PackageManagerServiceUtils
                                .SHARED_USER_ID_JOIN_TYPE_SYSTEM);
        if (!sigMatch) {
            throw new PackageManagerException(
                    INSTALL_FAILED_SHARED_USER_INCOMPATIBLE,
                    "Package has no signatures that match shared user");
        }
    }
    pkgSetting.setAppId(sharedUserSetting.mAppId);
}

加入 shared UID 先做 signer/capability 检查,成功后才把 package setting 的 appId 改为 shared user appId。顺序保证包不能先获得 UID 1000,再用该身份绕过签名校验。

6. 平台权限限制 ​

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

kotlin
val hasCommonSigner =
    sourceSigningDetails?.hasCommonSignerWithCapability(
        packageSigningDetails,
        SigningDetails.CertCapabilities.PERMISSION,
    ) == true ||
        packageSigningDetails.hasAncestorOrSelf(platformSigningDetails) ||
        platformSigningDetails.checkCapability(
            packageSigningDetails,
            SigningDetails.CertCapabilities.PERMISSION,
        )
if (!hasCommonSigner) return false

平台定义的 signature permission 先要求 signer 关系成立;之后 Android 17 在启用 signature permission allowlist 时还会检查 system app 的 factory request 或分区 signature allowlist。platform signed 并不意味着普通 APK 可以随意请求平台权限。

7. 平台包更新保护 ​

源码文件:frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.java

java
if (!comparePackageSignatures(
        platformPkgSetting, pkg.getSigningDetails())) {
    throw new PackageManagerException(
            INSTALL_FAILED_UPDATE_INCOMPATIBLE,
            "Platform package signature mismatch");
}

系统扫描和平台包更新路径会把新 platform package 与已持久化 platform setting 比较。即使其他包通过了 lineage capability,platform package 自身的签名变化仍是系统级风险,需要单独拒绝或满足受控 rotation 条件。

8. 服务间能力 ​

java
public boolean hasSignatureCapability(
        int serverUid, int clientUid,
        @SigningDetails.CertCapabilities int capability) {
    SigningDetails server = snapshot().getSigningDetails(serverUid);
    SigningDetails client = snapshot().getSigningDetails(clientUid);
    return server.checkCapability(client, capability)
            || client.hasAncestorOrSelf(server);
}

系统服务之间还可以按指定 capability 检查 server/client UID 的 signer 关系。传入 PERMISSION、INSTALLED_DATA 或其他 capability 会得到不同语义;不能把“平台签名”当成一个无参数的万能授权。

9. 排查顺序 ​

  1. 确认 platform package android 的 SigningDetails 是否成功建立。
  2. shared UID 问题检查 android.uid.system 是否预注册,以及 SHARED_USER_ID capability。
  3. isPlatformSigned 返回 false 时分别检查 ancestor 和 platform→package 的 PERMISSION capability。
  4. signature permission 仍失败时检查平台权限 allowlist、factory manifest request 和构建类型。
  5. system package 更新失败时同时比较 data 版本和 disabled system package。
  6. 不要把 system/privileged flags 当成 platform signer 证明。

10. 源码阅读路线 ​

  1. PackageManagerService 的 platform package 保存和 isPlatformSigned。
  2. Settings 初始化的 android.uid.system 注册。
  3. InstallPackageHelper/PackageManagerServiceUtils 的 shared UID signer 检查。
  4. AppIdPermissionPolicy 的 platform signature permission 判定。
  5. SigningDetails ancestor/capability 方法。
  6. 系统包更新路径的 platform signature 比较。

平台签名是一个基准关系,不是单一 flag:platform package 提供锚点,shared UID 决定进程身份,SigningDetails capability 决定信任范围,权限 allowlist 决定平台 signature permission 的最终授予。只有这些条件共同成立,系统应用才获得预期能力。