权限安全模型:保护级别与检查链
2026/8/9大约 3 分钟权限与安全Android 14权限保护级别检查链
权限安全模型:保护级别与检查链
上一章看了沙箱。这一章进入第二层,回答:权限的保护级别怎么定,谁有权定义权限, 一次权限检查到底经过哪些环节?
声明、授予与检查是三个阶段
| 常见误解 | 正确理解 |
|---|---|
| 所有权限都是系统定义的 | 应用可以定义自己的权限,并指定保护级别 |
| 声明了权限就能用 | 声明与授予是两回事,还要过检查链 |
| 权限名一样就等价 | 权限按包名 + 权限名定位,同名不同属主是不同权限 |
核心结论
- 权限定义属于某个包,保护级别决定授予规则。
- normal 安装即授,dangerous 运行时申请,signature/privileged 需身份背书。
- 权限树(permission tree)允许应用声明以自己前缀命名的子权限。
- 检查链:权限定义 → 授予状态 → AppOps → 调用方身份。
- “没授予”与“没定义”是两类问题,日志表现不同。
权限模型主链
逐步解释:
- 定义:包声明权限与保护级别,服务登记。
- 授予:按保护级别在不同时机授予。
- 检查:每次调用都按“定义 → 授予 → 策略”判定。
保护级别速查
| 级别 | 授予时机 | 说明 |
|---|---|---|
| normal | 安装时 | 低风险 |
| dangerous | 运行时 | 弹窗申请 |
| signature | 签名匹配 | 同签名才授 |
| privileged | 系统白名单 | 特权应用可授 |
| development | 开发期 | 调试用 |
权限声明者可以自定义级别;系统对 signature/privileged 还有额外的签名与白名单校验。
源码证据
阅读目标:确认权限登记与检查入口。
正文指针:PermissionManagerService.java 的登记与检查; PermissionInfo.java 的保护级别定义。
// PermissionInfo.java(伪代码,行号以 r75 为准)
public static final int PROTECTION_NORMAL = 0;
public static final int PROTECTION_DANGEROUS = 1;
public static final int PROTECTION_SIGNATURE = 2;这段代码证明: 保护级别是权限定义的核心属性;检查时先找定义,再看授予状态, 最后叠加策略,任何一环不过都拒绝。
验证与排障
环境:开发设备或模拟器;以下命令不需要 root。
adb shell pm list permissions
adb shell dumpsys package <包名> | grep -A30 "requested permissions"
adb shell dumpsys package <包名> | grep -A20 "runtime permissions"先确认权限是否定义(requested),再确认是否授予(runtime permissions),最后看 AppOps 与日志。权限问题先分清“没定义、没授予、被策略拒”三种情况。
常见误区
- “权限都是系统定的”:应用可自定义权限。
- “声明即授予”:声明与授予分离。
- “同名权限等价”:属主不同则不同。
- “权限被拒就是没点允许”:可能是保护级别、白名单或 SELinux。
延伸问题
- permission tree 的命名规则是什么?
- development 权限在什么构建类型下生效?
- 权限升级(appop → runtime)的兼容逻辑是什么?
- 系统服务如何声明并保护自己的权限?
源码入口
| 文件 | 关键位置 | 作用 |
|---|---|---|
PermissionInfo.java | 保护级别 | 级别定义 |
PermissionManagerService.java | 登记/检查 | 权限中枢 |
PackageManagerService.java | 授予流程 | 安装期授予 |
runtime-permissions.xml | 用户目录 | 授予状态 |
公共路径:frameworks/base/core/java/android/content/pm/ 与 frameworks/base/services/core/java/com/android/server/pm/permission/。 行号以 r75 检索为准。
权限通过后仍可能受操作策略限制,见 AppOps。