15、安全与权限管理:Android Automotive 安全模型、系统签名、SEAndroid 策略

各位同学,今天我们来聊聊车载系统里最“硬核”的部分——安全。说实话,做车机安全跟做手机安全完全是两码事。手机死机了重启就行,车机要是被攻破了,那可是人命关天。我在做某个量产项目时,就亲眼见过因为签名证书泄露,导致测试车被刷入恶意固件的惨案……嗯,从那以后我对安全这块就再也不敢马虎了。

15.1 Android Automotive 安全模型概览

Android Automotive 的安全模型,说白了就是“层层设防”。它继承了 Android 原生的沙箱机制,但针对车载场景做了大量增强。你想想看,车上有多个用户(驾驶员、乘客),还有各种 ECU 通信,权限模型必须更精细。

核心安全原则只有三条:

  • 默认拒绝:没有明确授予的权限,一律视为禁止。
  • 最小权限:每个进程只给够用的权限,多一点都不行。
  • 职责分离:系统服务、应用、硬件驱动各司其职,互不信任。

我个人习惯把 Automotive 的安全架构画成下面这张图,方便理解:

Android Automotive 安全模型分层 应用层(App Sandbox) 每个应用独立 UID,默认无权限 框架层(System Services) 权限检查、SEAndroid 强制访问控制 HAL 层(Hardware Abstraction) 系统签名验证,硬件访问控制 内核层(Linux Kernel + SEAndroid) 强制访问控制(MAC),系统调用过滤

每一层都依赖下一层提供的安全保证。应用层出了问题,框架层还能兜底;框架层被绕过,还有内核层的 SEAndroid 做最后一道防线。这就是所谓的“纵深防御”。

15.2 系统签名:车机的“身份证”

系统签名在 Automotive 里比手机重要得多。为什么?因为车机上很多系统级 API 只对签名应用开放。比如控制空调、读取车速、调用摄像头——这些接口如果被第三方应用拿到,后果不堪设想。

Android Automotive 使用四类签名:

签名类型 用途 保护级别
平台签名(platform) 系统应用、核心服务 最高,可访问 system 权限
媒体签名(media) 音视频相关应用 高,可访问媒体权限
共享签名(shared) 同一开发者的多个应用 中,可共享 UID
测试签名(testkey) 开发调试阶段 低,仅用于 eng 版本
⚠️ 重要提醒: 千万不要把测试签名用到量产车上!我曾经见过一个团队,为了赶进度直接用 testkey 签了系统镜像,结果车辆上市后,任何拿到 root 权限的人都能用同样的 testkey 签名恶意应用,直接调用系统 API。后来不得不紧急召回 OTA 更新签名。

签名验证流程其实不复杂:

// 系统签名验证核心逻辑(简化)
public boolean verifySignature(ApplicationInfo appInfo) {
    // 1. 读取应用签名证书
    Signature[] signatures = appInfo.getSignatures();
    // 2. 与系统预置的 platform 证书对比
    if (Arrays.equals(signatures, PLATFORM_CERT)) {
        return true; // 授予 platform 级别权限
    }
    // 3. 与 media 证书对比
    if (Arrays.equals(signatures, MEDIA_CERT)) {
        return true; // 授予 media 级别权限
    }
    // 4. 默认拒绝
    return false;
}

你可能会问:“那我把 platform 证书偷出来不就行了?”嗯,理论上可以,但实际操作中,OEM 厂商会把私钥存储在硬件安全模块(HSM)里,物理上就无法导出。我建议你在项目初期就建立好密钥管理流程,别等到量产前才手忙脚乱。

15.3 SEAndroid 策略:强制访问控制

SEAndroid 是 Android 安全体系里我最欣赏的部分。它基于 Linux 的 SELinux,实现了强制访问控制(MAC)。什么意思呢?就是即使你拿到了 root 权限,也不能为所欲为。

举个例子:

# 一个典型的 SEAndroid 策略规则
allow system_app vehicle_service:service { start stop };
# 解释:允许 system_app 域的应用,对 vehicle_service 服务执行 start 和 stop 操作

这条规则意味着,只有被标记为 system_app 的进程才能控制车辆服务。其他进程,哪怕是 root 用户,也无法执行这个操作。

在 Automotive 中,SEAndroid 策略主要关注三个领域:

  • 车辆服务访问:控制哪些应用可以读写车辆属性(车速、转向、空调等)
  • 系统服务保护:防止未授权进程访问 ActivityManager、PackageManager 等核心服务
  • 设备节点控制:限制对 /dev/vehicle、/dev/can 等硬件节点的访问

💡 个人经验: 我在调试一个车载信息娱乐系统时,发现第三方地图应用总是无法获取 GPS 数据。查了两天,最后发现是 SEAndroid 策略里忘了给该应用的 domain 添加 gps_device 的访问权限。加上一行 allow map_app gps_device:chr_file read; 就解决了。所以,遇到权限问题,先查 SEAndroid 的 avc 日志!

查看 avc 拒绝日志的命令:

adb logcat -b events | grep "avc: denied"

这条命令能帮你快速定位哪些操作被 SEAndroid 拦截了。我个人习惯在开发阶段把策略设为 permissive 模式(只记录不拦截),等调试完再切回 enforcing 模式。但注意,量产车必须 enforcing!

15.4 权限管理实战:车载特有的权限

Android Automotive 新增了一批车载专属权限,这些在手机上是没有的。我列几个常用的:

权限名称 保护级别 用途
android.car.permission.CAR_SPEED signature|privileged 读取车辆速度
android.car.permission.CAR_ENERGY signature|privileged 读取续航里程、油耗
android.car.permission.CAR_INFO signature 读取 VIN 码、车辆配置
android.car.permission.CAR_CONTROL_AUDIO_VOLUME signature 控制音量(包括导航混音)

🔧 调试技巧: 如果你在开发车载应用时遇到权限拒绝,可以用 pm check-permission 命令检查应用是否拥有某个权限:

adb shell pm check-permission android.car.permission.CAR_SPEED com.example.myapp

返回 true 表示有权限,false 表示没有。

最后说一句,安全不是一次性工作。随着系统版本升级、新功能加入,SEAndroid 策略和权限定义都需要持续维护。我建议你在每个 sprint 结束时都跑一遍安全审计脚本,确保没有遗漏的开放端口或过度授权的应用。

好了,这一章的内容就到这里。安全是车机的生命线,希望各位同学在实际项目中能把这些原则落到实处。


公众号:蓝海资料掘金营,微信deep3321