selinux(案例) recovery删除data目录下的文件

本文介绍在Android 6.0系统中如何解决SELinux限制导致的升级包删除问题。通过修改文件上下文和权限策略,实现了recovery模式下对特定路径文件的有效管理。

原文 https://blog.youkuaiyun.com/kc58236582/article/details/51752765

在recover升级的时候,我们有个需要从服务器上下载升级包,然后放在data/download,这部分工作是放在一个systemapp中完成的。

然后重启进入recoveyr模式,在recovery升级完之后,我们需要在recovery中删除这个文件,这部分是在recovery中完成。

功能很简单,但是在android6.0上碰到selinux的问题。

我们先来看recovery.te中是不允许recovery操作data下面的目录,也就是下面这个neverallow原则

[html]  view plain  copy
  1. # Recovery should never touch /data.  
  2. #  
  3. # In particular, if /data is encrypted, it is not accessible  
  4. # to recovery anyway.  
  5. #  
  6. # For now, we only enforce write/execute restrictions, as domain.te  
  7. # contains a number of read-only rules that apply to all  
  8. # domains, including recovery.  
  9. #  
  10. # TODO: tighten this up further.  
  11. neverallow recovery data_file_type:file { no_w_file_perms no_x_file_perms };  
  12. neverallow recovery data_file_type:dir no_w_dir_perms;  
我们再来看下system_data_file在file_contexts.te中的定义

[cpp]  view plain  copy
  1. /data(/.*)?     u:object_r:system_data_file:s0  

而在file.te定义了system_data_file文件属于data_file_type类型,因此recovery也是不能操作data下面的文件
[html]  view plain  copy
  1. ./file.te:56:type system_data_file, file_type, data_file_type;  

在我们可以自己定义自己的file类型,我们可以定义data/download属于download_data_file类型

[html]  view plain  copy
  1. /data/download(/.*)?           u:object_r:download_data_file:s0  

然后在file.te中定义download_data_file类型, 注意是只属于file_type类型的。

[html]  view plain  copy
  1. type download_data_file, file_type;   
然后在recovery.te中增加对download_data_file的权限
[html]  view plain  copy
  1. allow recovery download_data_file:dir { write search remove_name };  
  2. allow recovery download_data_file:file { read getattr unlink };  

另外我们还需在一个systemapp中先下载升级包,所以需要在system_app.te中增加对如下权限:

[html]  view plain  copy
  1. allow system_app download_data_file:dir { search write add_name getattr remove_name };  
  2. allow system_app download_data_file:file { create read write open getattr unlink };  


但是最后还是失败了,为什么呢,因为一开始没有data/download这个目录,而是我们再app中自己下载的时候创建的目录,所以是system_data_file类型的。那么我们就需要在一开始就有data/download目录,所以在init.rc中添加如下代码:

[html]  view plain  copy
  1. mkdir /data/download 0771 system system  

最后我们还需要在uncrypt.te中增加如下,因为data目录有可能需要进行加密处理。

[html]  view plain  copy
  1. allow uncrypt download_data_file:dir { search getattr };  
  2. allow uncrypt download_data_file:file { getattr read open };

<think>嗯,用户想了解设备因崩溃次数过多而进入恢复模式的原因。这个问题其实挺专业的,涉及到系统底层的保护机制。从对话历史看,用户之前问过进入recoverymode的多种原因,现在特别关注crash次数过多的情况。用户引用了四段资料,其中第二段提到Android8.0核心app或service崩溃多次会进入Recovery,这正好是问题的关键切入点。用户可能是Android开发者或系统维护人员,因为ta在引用中提到了具体调试经历(注释shutdownthread代码)。ta现在遇到设备频繁重置的问题,显得比较着急,需要给出准确的技术解释。需要重点解释三个层面:首先是Android系统的崩溃计数机制,特别是healthd服务如何监控崩溃次数;其次是系统设计的保护逻辑,为什么选择进入recovery而不是简单重启;最后是不同Android版本的实现差异,比如Oreo之后的改进。用户引用的资料里提到内存转储(Kdump)和分区表信息,虽然不完全相关,但说明ta对底层机制有兴趣。可以在回答中适当关联,比如解释系统崩溃时如何生成last_kmsg日志。要特别注意术语的准确性,比如"coreservice"在Android上下文中的具体定义。同时给出实用建议,比如查看/cache/recovery/last_log的方法,这样用户能立即用于问题排查。最后生成的相关问题要延续这个技术深度,比如询问AB分区设备的特殊处理机制,或者如何区分软件崩溃和硬件故障导致的恢复模式触发。</think>设备因崩溃次数过多进入恢复模式(Recovery Mode)是系统级的自我保护机制,主要涉及以下核心原因和运作逻辑: --- ### 一、核心机制:系统健康监控(Healthd 服务) Android 系统通过 **`healthd` 服务**持续监控关键进程(如系统服务、核心应用)的崩溃行为。当崩溃次数超过阈值时,会触发恢复模式: ```mermaid graph TD A[关键进程崩溃] --> B{healthd 计数} B -->|达到阈值| C[写入 /cache/recovery/command] C --> D[写入 bootloader_message] D --> E[重启进入 Recovery] ``` - **阈值规则**: - 系统服务(如 `system_server`)连续崩溃 **≥ 3次** - 核心应用(如启动器、电话服务)**5分钟内崩溃 ≥ 5次** - **触发动作**: 在 `/cache/recovery/command` 写入指令: `--reason=rescueparty_factoryreset` `--factory_reset` [^2] --- ### 二、根本原因分析 | 崩溃类型 | 典型场景 | 进入 Recovery 的原因 | |----------------|-----------------------------------|-----------------------------------| | **系统服务崩溃** | `system_server` 守护进程异常终止 | 框架层功能瘫痪(如窗口管理失效) | | **硬件驱动故障** | GPU/传感器驱动导致内核 panic | 触发 Kdump 机制保存崩溃日志[^1] | | **存储损坏** | /data 分区文件系统错误 | 无法完成正常启动流程 | | **OTA 更新失败** | 新系统版本存在兼容性缺陷 | A/B 分区回滚机制激活[^2] | > ⚠️ **关键证据链**: > 崩溃日志存储在 `/data/system/dropbox/` 和 `/proc/vmcore`(内核崩溃)[^1][^4],当系统无法正常访问这些日志时,强制进入 Recovery 进行深度修复。 --- ### 三、恢复模式的处理流程 1. **日志分析阶段** Recovery 优先读取 `/cache/recovery/last_kmsg` 获取崩溃快照: ```bash crash -i last_kmsg # 使用 crash 工具解析内核日志 ``` 2. **分级修复策略** ```mermaid graph LR S[启动失败] --> T1{崩溃类型} T1 -->|文件系统错误| U1[运行 e2fsck 修复 /data] T1 -->|服务崩溃| U2[清除 /data 分区缓存] T1 -->|系统更新失败| U3[回退到上一个 A/B 槽位] ``` 3. **终极方案:恢复出厂设置** 当上述修复无效时,执行 `--wipe_data` 指令清除用户数据[^3]。 --- ### 四、开发者调试建议 若需阻止频繁进入 Recovery: 1. **获取崩溃日志** ```bash adb pull /data/tombstones # 提取 native 崩溃日志 adb logcat -b crash # 查看 Java 层崩溃堆栈 ``` 2. **临时禁用保护机制** ```bash adb shell settings put global rescue_party_level 0 # 关闭 RescueParty ``` > **风险**:可能导致设备无法启动,仅限调试使用[^2]。 --- ### 典型错误案例解析 > **现象**:Android 8.0 设备开机后 30 秒自动进入 Recovery 恢复出厂设置[^2] > **根因分析**: > - `system_server` 因 SELinux 策略冲突崩溃 > - 连续崩溃触发 RescueParty 的 `FACTORY_RESET` 级别 > **解决方案**: > 检查 `/data/anr/traces.txt` 中系统服务堆栈,修复策略冲突。
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值