签名系统级应用在Android文件系统移动文件的权限问题咨询
问题根因及解决方案
根因说明
/system分区默认以只读模式挂载,哪怕是运行在system uid下的特权应用,也默认没有/system分区的写入权限:
- 移动(mv)操作本质需要删除/system下的源文件,会触发/system分区写入请求,直接被拦截
- 复制操作报错通常是源文件的权限、SELinux上下文不允许system uid读取,或是目标目录权限不匹配导致
可行解决方案
1. 优先调整操作逻辑规避/system写入
如果只是需要把预置文件同步到应用数据目录,不要使用移动操作,改用只读读源+写入目标路径的纯复制逻辑:
- 提前确保
/system下待读取的源文件权限至少为0644,owner为root:root即可,system uid默认拥有这类文件的全局读权限 - 写入目标路径优先用应用Context获取的私有目录:
context.getFilesDir().getAbsolutePath(),自动匹配权限不需要额外配置
2. 必须修改/system分区的处理方案
如果业务场景确实需要移动/删除/system下的文件,需要先重新挂载/system为可写模式:
- 首先在应用
AndroidManifest.xml中声明特权权限:<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>,系统签名+priv-app路径即可正常获取该权限 - 操作前执行挂载命令:
mount -o remount,rw /system,所有操作完成后切回只读模式避免系统分区被误改:mount -o remount,ro /system
3. SELinux权限适配
如果上述操作完成后仍报权限错误,属于SELinux规则拦截:
- 临时执行
setenforce 0关闭SELinux验证测试,如果操作正常即可确认是SELinux问题 - 在你的自定义AOSP源码SEPolicy目录中新增对应规则,示例参考:
allow system_app system_file:file { read open getattr };
若需要写入/system分区额外加这行allow system_app system_file:file { write unlink };
4. Java File IO备选方案
如果Java层IO一直调用失败,可以直接调用底层shell命令完成操作:
// 复制文件示例 Process process = Runtime.getRuntime().exec("cp /system/源文件路径 " + context.getFilesDir().getAbsolutePath() + "/目标文件名"); int exitCode = process.waitFor(); // exitCode为0代表执行成功
内容的提问来源于stack exchange,提问作者Garry McKee
相关产品推荐
相关产品推荐

