平台签名
平台签名不是一个“系统应用标志”。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 signed | SigningDetails | signer 与 platform package 相同或被授权 |
privileged app 仍受 allowlist;platform signed 也不自动获得所有 internal/OEM 权限。最终权限由 protection policy 和白名单共同决定。
2. 平台包基准
源码文件:frameworks/base/services/core/java/com/android/server/pm/PackageManagerService.java
public static final String PLATFORM_PACKAGE_NAME = "android";
@GuardedBy("mLock")
private AndroidPackage mPlatformPackage;platform package 的包名是 android。扫描到该包时 PMS 保存其 AndroidPackage,后续 isPlatformSigned 直接使用它的 SigningDetails,而不是读取某个固定证书文件路径。
if (PLATFORM_PACKAGE_NAME.equals(pkg.getPackageName())) {
mPlatformPackage = pkg;
synchronized (mLock) {
mSettings.setRuntimePermissionsFingerPrint(
getRuntimePermissionsFingerPrint());
}
}平台包状态和 runtime permission fingerprint 在扫描阶段建立;平台 key 变更会影响权限迁移和所有基于 platform signer 的判断。
3. system UID 注册
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 映射本身不替代签名验证。
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
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 授予
PERMISSIONcapability,允许平台签名权限关系在特定 lineage 中延续。
这不是简单的 Signature.equals,也不是只看 ApplicationInfo.FLAG_SYSTEM。
5. shared UID 校验
源码文件:frameworks/base/services/core/java/com/android/server/pm/InstallPackageHelper.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
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
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. 服务间能力
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. 排查顺序
- 确认 platform package
android的 SigningDetails 是否成功建立。 - shared UID 问题检查
android.uid.system是否预注册,以及SHARED_USER_IDcapability。 isPlatformSigned返回 false 时分别检查 ancestor 和 platform→package 的PERMISSIONcapability。- signature permission 仍失败时检查平台权限 allowlist、factory manifest request 和构建类型。
- system package 更新失败时同时比较 data 版本和 disabled system package。
- 不要把 system/privileged flags 当成 platform signer 证明。
10. 源码阅读路线
PackageManagerService的 platform package 保存和isPlatformSigned。- Settings 初始化的
android.uid.system注册。 - InstallPackageHelper/PackageManagerServiceUtils 的 shared UID signer 检查。
- AppIdPermissionPolicy 的 platform signature permission 判定。
SigningDetailsancestor/capability 方法。- 系统包更新路径的 platform signature 比较。
平台签名是一个基准关系,不是单一 flag:platform package 提供锚点,shared UID 决定进程身份,SigningDetails capability 决定信任范围,权限 allowlist 决定平台 signature permission 的最终授予。只有这些条件共同成立,系统应用才获得预期能力。
