Android SELinux avc dennied权限问题

本文介绍了解决Android系统中因SELinux导致的权限问题的方法。通过分析日志中的avc:denied提示,逐步定位并修复缺失权限,提供了一套实用的解决方案。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Android SELinux avc dennied权限问题解决方法


1. 概述


SELinux是Google从android 5.0开始,强制引入的一套非常严格的权限管理机制,主要用于增强系统的安全性。
然而,在开发中,我们经常会遇到由于SELinux造成的各种权限不足,即使拥有“万能的root权限”,也不能获取全部的权限。本文旨在结合具体案例,讲解如何根据log来快速解决90%的SELinux权限问题。
2. 调试确认SELinux问题


为了澄清是否因为SELinux导致的问题,可先执行:
setenforce 0 (临时禁用掉SELinux)
getenforce  (得到结果为Permissive)
如果问题消失了,基本可以确认是SELinux造成的权限问题,需要通过正规的方式来解决权限问题。
遇到权限问题,在logcat或者kernel的log中一定会打印avc denied提示缺少什么权限,可以通过命令过滤出所有的avc denied,再根据这些log各个击破:
cat /proc/kmsg | grep avc 

dmesg | grep avc
例如:
audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0
可以看到有avc denied,且最后有permissive=0,表示不允许。
3. 具体案例分析


解决原则是:缺什么权限补什么,一步一步补到没有avc denied为止。
解决权限问题需要修改的权限文件如下位置,以.te结尾
A:Android/devicesoftwinner/astar-common/sepolicy/*.te
B:Android/external/sepolicy/*.te
其中,A是对B的overlay(覆盖),能在A修改的尽量在A修改,尽量避免修改B,修改B可能会导致CTS fail问题,修改A不会影响CTS测试。
(如果不需要深入了解,请直接跳到万能公式这一章阅读更简洁)
下面给出四个案例:
案例1
audit(0.0:67): avc: denied { write } for path="/dev/block/vold/93:96" dev="tmpfs" ino=/1263 scontext=u:r:kernel:s0 tcontext=u:object_r:block_device:s0 tclass=blk_file permissive=0
 
分析过程:
缺少什么权限:      { write }权限,
谁缺少权限:        scontext=u:r:kernel:s0
对哪个文件缺少权限:tcontext=u:object_r:block_device
什么类型的文件:    tclass=blk_file
完整的意思: kernel进程对block_device类型的blk_file缺少write权限。
 
解决方法:在上文A位置,找到kernel.te这个文件,加入以下内容:
allow  kernel  block_device:blk_file  write;
make installclean后重新编译,刷boot.img才会生效。
 
案例2
audit(0.0:53): avc: denied { execute } for  path="/data/data/com.mofing/qt-reserved-files/plugins/platforms/libgnustl_shared.so" dev="nandl" ino=115502 scontext=u:r:platform_app:s0 tcontext=u:object_r:app_data_file:s0 tclass=file permissive=0
 
分析过程:
缺少什么权限:      { execute}权限,
谁缺少权限:        scontext = u:r:platform_app:s0
对哪个文件缺少权限:tcontext = u:object_r:app_data_file
什么类型的文件:    tclass= file
完整的意思: platform_app进程对app_data_file类型的file缺少execute权限。
 
解决方法:在上文A位置,找到platform_app.te这个文件,加入以下内容:
allow  platform_app  app_data_file:file  execute;
make installclean后重新编译,刷boot.img才会生效。
 
案例3
audit(1444651438.800:8): avc: denied { search } for pid=158 comm="setmacaddr" name="/" dev="nandi" ino=1 scontext=u:r:engsetmacaddr:s0 tcontext=u:object_r:vfat:s0 tclass=dir permissive=0
解决方法 :engsetmacaddr.te
allow  engsetmacaddr  vfat:dir  { search write add_name create }; 或者
allow  engsetmacaddr   vfat:dir  create_dir_perms;
(create_dir_perms包含search write add_name create可参考external/sepolicy/global_macros的定义声明)
 
案例4
audit(1441759284.810:5): avc: denied { read } for pid=1494 comm="sdcard" name="0" dev="nandk" ino=245281 scontext=u:r:sdcardd:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0
解决方法 :sdcardd.te 
allow  sdcardd  system_data_file:dir  read;  或者
allow  sdcardd  system_data_file:dir  rw_dir_perms;
 (rw_dir_perms包含read write,可参考external/sepolicy/global_macros的定义声明)
 
 
4. 万能公式


通过这四个案例,我们可以总结出一般规律,
以第案例4为例:
audit(1441759284.810:5): avc: denied { read } for pid=1494 comm="sdcard" name="0" dev="nandk" ino=245281 scontext=u:r:sdcardd:s0 tcontext=u:object_r:system_data_file:s0 tclass=dir permissive=0
 
某个scontext对某个tclass类型的tcontext缺乏某个权限,我们需要允许这个权限:
我们的log重新排列一下,
scontext = u:r:sdcardd
tcontex t= u:object_r:system_data_file:s0
tclass = dir
avc: denied { read }
 
得到万能套用公式如下:
在scontext所指的.te文件(例如sdcardd.te)中加入类似如下allowe内容:
 
5. TIPS


1. 以上以.te为后缀的文件都在以下位置:
A:Android/devicesoftwinner/astar-common/sepolicy/*.te
B:Android/external/sepolicy/*.te
其中,A是对B的overlay(覆盖),能在A修改的尽量在A修改,修改B可能会导致CTS fail问题,修改A不会影响CTS测试。修改之后,为了节约验证时间,只重刷boot.img即可看效果;
 
2. 有时候avc denied的log不是一次性暴露所有权限问题,要等解决一个权限问题之后,才会暴露另外一个权限问题。比如提示缺少某个目录的read权限,加入read之后,才显示缺少write权限,要一次次一次试,一次一次加,时间成本极大。
针对dir缺少的任何权限,建议赋予create_dir_perms,基本涵盖对dir的所有权限,比如:
{ open search write read rename create rmdir getattr }等等。
针对file缺少的任何权限,建议赋予rwx_file_perms,基本涵盖对file的所有权限,比如:
包含{ open read write open execute getattr create ioctl }等等。
更多内容请参考external/sepolicy/global_macros来了解更多权限声明。
3. 要加入的权限很多时,可以用中括号,比如:
allow engsetmacaddr  vfat:dir { search write add_name create};
4. 修改A位置的.te文件遇到编译错误怎么办?
(首先请排除拼写错误)说明此项权限是SELinux明确禁止的,也是Google CTS禁止的,如果产品不需要过CTS,可以修改。一般来说,编译出错的log会提示相关哪个文件哪一行出错,文件位置一定会在B里的.te文件。比如B规定了以下neverallow,
neverallow system_server sdcard_type:dir { open read write };
那么system_server是不能拥有这些权限的,如果赋予这些权限就编译报错,解决方法是根据编译错误提示的行号,把这一句注释掉即可。
 
 
6. 高级进阶


6.1. 新建.te安全策略文件方法


以上基本是对已经存在的进程增加权限,但对第三方进程改如何新增一个全新的te文件并赋予权限呢?
以写mac地址的setmacaddr执行文件为例(这个执行档android原生不存在,自行添加的):
在init.xxx.rc中如下服务:
service engsetmacaddr  /system/bin/setmacaddr  /data/misc/wifi/wifimac.txt
    class main
    disabled
oneshot
 
 
1. 在device/softwinner/astar-common/sepolicy/file_contexts中,参考其他进程声明一个scontext:
……
/system/bin/install-recovery.sh u:object_r:install_recovery_exec:s0
/system/bin/dex2oat     u:object_r:dex2oat_exec:s0
/system/bin/patchoat    u:object_r:dex2oat_exec:s0
/system/bin/setmacaddr u:object_r:engsetmacaddr_exec:s0
指定setmacaddr的路径,并指定一个名字,一定要以service名+_exec结尾
 
2.参考其.te文件在device/softwinner/astar-common/sepolicy/file_contexts 创建engsetmacaddr.te文件,内容如下:
type engsetmacaddr, domain;
type engsetmacaddr_exec, exec_type, file_type;


init_daemon_domain(engsetmacaddr)


allow engsetmacaddr  vfat:dir { search write add_name create};
allow engsetmacaddr  vfat:file { create read write open };
allow engsetmacaddr  engsetmacaddr:capability dac_override;
allow engsetmacaddr  shell_exec:file { execute read open execute_no_trans};
allow engsetmacaddr  system_data_file:dir { write add_name remove_name };
allow engsetmacaddr  system_data_file:file { create execute_no_trans write open setattr};
allow engsetmacaddr  system_file:file { execute_no_trans};
以上赋予的权限全部是根据avc denied的log缺什么一步一步补什么来的。
 
6.2. 新设备节点增加访问权限


驱动创建了一个新的设备节点,即使权限是777,android层也是没有访问权限的。
下面以一个/dev/wifi_bt节点为示范,让此节点被用户空间的system_server进程访问。
1. 编辑devicesoftwinner/astar-common/sepolicy/device.te,仿照这个文件里的写法,定义一个dev_type类型的wifi_bt_device设备:
type misc_block_device, dev_type;
type private_block_device, dev_type;
……
type wf_bt_device, dev_type;  
 
2. 编辑file_contexts.te,将/dev/wf_bt节点声明为第1步定义的wf_bt_device:
/dev/block/by-name/misc         u:object_r:misc_block_device:s0
/dev/block/by-name/alog         u:object_r:log_block_device:s0
/dev/block/by-name/private      u:object_r:private_block_device:s0
# We add here  
/dev/wf_bt              u:object_r:wf_bt_device:s0  
 
3. 在system_server.te,根据dmesg | grep avc允许system_server对wf_bt_device这个节点可读可写:
# Read/Write to /proc/net/xt_qtaguid/ctrl and and /dev/xt_qtaguid.  
allow system_server qtaguid_proc:file rw_file_perms;  
allow system_server qtaguid_device:chr_file rw_file_perms;  
 ……
allow system_server wf_bt_device:chr_file rw_file_perms;  
其他进程如需访问/dev/wf_bt节点,依样画葫芦,增加对wf_bt_device的权限即可。
<think>我们正在处理一个SELinux权限问题,具体是stressapptest应用在执行时遇到了`avc: denied { getattr }`错误,可能还涉及`execute`和`search`权限。根据引用[3]的通用解决思路,我们可以按以下步骤操作: ### 1. **确认问题是否由SELinux引起** - 临时禁用SELinux(仅用于测试): ```bash adb shell setenforce 0 ``` - 重新运行`stressapptest`,如果问题消失,则确认为SELinux权限问题。 ### 2. **收集完整的AVC拒绝日志** - 重新启用SELinux: ```bash adb shell setenforce 1 ``` - 触发`stressapptest`错误,然后从日志中提取完整的AVC拒绝信息,例如: ```bash adb shell su -c 'cat /proc/kmsg | grep "avc: .*stressapptest"' > avc_log.txt ``` - 关键字段:`scontext`(进程上下文)、`tcontext`(目标文件/目录上下文)、`tclass`(目标类别)和操作(如`getattr`, `execute`, `search`)。 ### 3. **分析日志并生成规则** - 示例日志格式(参考引用[1][2][3][4]): ``` avc: denied { getattr execute search } for pid=1234 comm="stressapptest" path="/path/to/file" dev="..." ino=... scontext=u:r:stressapptest:s0 tcontext=u:object_r:target_type:s0 tclass=dir ``` - 使用`audit2allow`工具(需在Linux环境中安装`policycoreutils`)生成规则: ```bash audit2allow -i avc_log.txt ``` - 输出示例: ``` #============= stressapptest ============== allow stressapptest target_type:dir { getattr search execute }; ``` ### 4. **修改SELinux策略** - 根据`audit2allow`的输出,在`stressapptest`的SELinux策略文件(如`stressapptest.te`)中添加规则: ```te # 允许stressapptest对目标类型(target_type)的目录(tclass=dir)执行getattr、search和execute操作 allow stressapptest target_type:dir { getattr search execute }; ``` - **扩展建议**(引用[3]): - 若目标类别为`dir`且需要多个权限,可直接使用预定义的权限集`create_dir_perms`: ```te allow stressapptest target_type:dir create_dir_perms; ``` - 若目标类别为`file`,则使用`rwx_file_perms`: ```te allow stressapptest target_type:file rwx_file_perms; ``` ### 5. **重新编译并加载策略** - **Android源码环境**: - 将修改后的`.te`文件放入策略目录(如`device/<vendor>/<device>/sepolicy`)。 - 重新编译系统镜像并刷机。 - **已Root设备(临时方案)**: - 将`.te`文件编译为`.pp`模块并加载: ```bash # 1. 将.te文件编译为.mod checkmodule -M -m -o stressapptest.mod stressapptest.te # 2. 将.mod打包为.pp semodule_package -o stressapptest.pp -m stressapptest.mod # 3. 加载模块 adb push stressapptest.pp /data/local/tmp/ adb shell su -c "semodule -i /data/local/tmp/stressapptest.pp" ``` ### 6. **验证修复** - 重启设备或重新加载策略后,运行`stressapptest`测试是否仍有权限错误。 ### 注意事项 - **最小权限原则**:仅授予必要的权限(如仅`{ getattr search execute }`而非全集)。 - **多次迭代**:根据引用[3],SELinux错误可能分批暴露,需反复测试并添加规则。 - **上下文类型确认**:确保`target_type`(如`system_data_file`、`mnt_media_rw_file`等)正确,避免过度授权。 --- ### 相关问题 1. 如何为Android自定义SELinux策略模块(`.te`文件)并集成到系统镜像中? 2. `audit2allow`工具在Android开发环境中的具体安装和使用步骤是什么? 3. 除了`getattr`、`execute`和`search`,`stressapptest`还可能因哪些SELinux权限操作被拒绝? 4. 如何查看Android系统中文件或进程的SELinux标签(`ls -Z`、`ps -Z`的等效命令)? 5. SELinux策略中的`create_dir_perms`和`rwx_file_perms`分别包含哪些具体权限? [^1]: [SELinux关于avc:denied错误](引用1) [^3]: [Android SELinux avc dennied权限问题解决方法](引用3)</think>### 解决 Android stressapptest 的 SELinux 权限问题avc: denied { getattr }) 根据引用[3]的通用解决框架和引用[1][2][4]的案例,解决步骤分为以下阶段: --- #### 1. **确认 SELinux 问题根源** ```bash # 临时禁用 SELinux 验证 adb shell setenforce 0 # 运行 stressapptest 测试 adb shell stressapptest # 检查问题是否消失 ``` - 若问题消失,确认是 SELinux 权限问题 [^3] - 完成后恢复安全模式:`adb shell setenforce 1` --- #### 2. **获取完整 AVC 拒绝日志** ```bash adb shell su -c 'cat /proc/kmsg | grep "avc: .*stressapptest"' > avc_log.txt ``` 关键字段解析(以引用[3][4]为例): - `scontext=u:r:stressapptest:s0` → 进程安全上下文 - `tcontext=u:object_r:target_type:s0` → 目标资源类型 - `tclass=dir/file` → 资源类别 - `{ getattr execute search }` → 被拒绝的操作 --- #### 3. **生成 SELinux 策略规则** 根据引用[3]的通用公式: ```te # 在 stressapptest.te 文件中添加 allow stressapptest target_type:tclass { denied_operations }; ``` 实际案例对应: ```te # 示例1:目录权限(引用[3]方案) allow stressapptest mnt_media_rw_file:dir create_dir_perms; # 示例2:文件权限(引用[4]场景) allow stressapptest system_data_file:file rwx_file_perms; ``` #### 预定义权限集说明(引用[3]): | 权限集 | 包含操作 | 适用场景 | |------------------|--------------------------------------|---------------| | `create_dir_perms` | { open search write read rename create rmdir getattr } | 目录操作 | | `rwx_file_perms` | { open read write execute getattr create ioctl } | 文件操作 | --- #### 4. **策略文件修改与编译** 1. 定位策略文件: - AOSP 路径:`/device/[厂商]/[设备]/sepolicy/stressapptest.te` - 无专用文件时创建新文件 2. 添加规则: ```te # 允许 stressapptest 访问 sysfs(常见硬件接口) allow stressapptest sysfs:file rwx_file_perms; # 允许访问数据目录(引用[4]场景) allow stressapptest system_data_file:dir create_dir_perms; ``` 3. 编译并刷写策略: ```bash # 在 AOSP 环境编译 make sepolicy # 推送新策略文件 adb push sepolicy /sepolicy ``` --- #### 5. **迭代测试与权限补充** - SELinux 错误通常分批暴露(引用[3]) - 测试流程: ```mermaid graph LR A[添加基础权限] --> B[运行测试] B --> C{新AVC日志?} C -->|是| D[追加新权限] C -->|否| E[完成] D --> B ``` --- #### 典型场景解决方案 1. **访问 /sys 文件**(硬件信息): ```te allow stressapptest sysfs:file { getattr open read }; ``` 2. **访问 /data 目录**(引用[4]): ```te allow stressapptest system_data_file:dir search; allow stressapptest system_data_file:file getattr; ``` 3. **执行二进制文件**: ```te allow stressapptest exec_type:file execute; ``` --- ### 相关问题 1. 如何确定 `stressapptest` 需要访问的具体文件路径? 2. 在非 AOSP 环境中如何修改 SELinux 策略? 3. `create_dir_perms` 和 `rwx_file_perms` 的具体权限定义在哪里查看? 4. 如何为 Android 系统添加新的 SELinux 类型标签? 5. 多次添加权限后仍存在拒绝,如何深度调试? [^1]: [SELinux关于avc:denied错误](引用1) [^3]: [Android SELinux avc dennied权限问题解决方法](引用3) [^4]: [Android Selinux Error avc: denied { getattr }](引用4)
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值