【转载 http://blog.csdn.net/mockingbirds/article/details/53026770】
有时候会遇到selinux相关的问题,今天来做一下总结:
打开和关闭selinux功能
如果出现了selinux相关的权限拒绝,则在kernel log 或者android log中都有对应的”avc: denied”,当然也可能和selinux的模式有关系,我们需要首先要确认当时SELinux 的模式, 是enforcing mode 还是 permissve mode.
如果问题容易复现,我们可以先将SELinux 模式调整到Permissive mode,然后再测试确认是否与SELinux 约束相关.
在ENG 版本中:
adb shell setenforce 0
setenforce 0 设置SELinux 成为permissive模式 临时关闭selinux
setenforce 1 临时打开selinux
- 1
- 2
- 3
- 4
另外当出现selinux相关问题,我们可以通过下面的命令来抓取对应的log
adb shell dmesg | grep avc
adb shell "cat /proc/kmsg | grep avc" > avc_log.txt
- 1
- 2
根据log来写出需要缺少的权限
07-06 05:09:22.397 I/auditd ( 627): avc: denied { find } for service=ext_telephony_service_impl pid=11765 uid=10024 scontext=u:r:priv_app:s0:c512,c768 tcontext=u:object_r:ext_telephony_service_server:s0 tclass=service_manager permissive=1
缺少什么权限: 缺少 find 权限
谁缺少权限: scontext=u:r:priv_app:s0
对哪个文件缺少权限: tcontext=u:object_r:ext_telephony_service_server
什么类型的文件: tclass=service_manager
allow priv_app ext_telephony_service_server:service_manager {find}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
可以看到上面我们根据log,以及scontext,tcontext,tclass的值反推出当前缺少的权限以及那个类型的文件缺少什么权限,进而可以写出当前的配置。
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
allow platform_app app_data_file:file execute
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
如果是多个权限的添加可以使用下面方式:
allow mediaserver acdb_delta_file:file { create open read append getattr };
需要注意的是:
1. 有时候avc denied的log不是一次性显示所有问题,要等解决一个权限问题之后,才会提示另外一个权限问题, 比如提示确实某个目录的read权限,你加入read之后,再显示缺少write权限,要你一次次一次试,一次一次加。
这时你可以简单粗暴写个rw_dir_perms,这个权限包含了{open search write …}等等很多权限,我们可以查看external/sepolicy/global_macros来了解更多权限声明;
2. 要加入的权限很多时,可以用中括号,比如
allow engsetmacaddr vfat:dir { search write add_name create};
使修改生效
在sourcecode/external/sepolicy 目录下的对应模块的policy.mk做更改,添加或者移除我们修改的.te文件
BOARD_SEPOLICY_UNION += \
audioserver.te \
chargemon.te \
config_linker.te \
display_cc.te \
priv_app.te \
qns.te \
rild.te \
secd.te \
system_app.te \
system_server.te \
thermal-engine.te \
wvkbd.te
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
查看文件和进程的权限配置
查看进程的权限
ps -Z
- 1
查看文件的权限
ls -Z
u:object_r:app_data_file:s0:c512,c768 appmetadata
u:object_r:app_data_file:s0:c512,c768 fileinternal
u:object_r:app_data_file:s0:c512,c768 gaClientId
- 1
- 2
- 3
- 4
- 5
SEAndroid框架
在SEAndroid中,每一个进程和文件都会关联有一个安全上下文。这个安全上下文由用户、角色、类型、安全级别四个部分组成,每一部分通过一个冒号来分隔,
分别是SELinux用户、SELinux角色、类型、安全级别,格式为“user:role:type:sensitivity”。
users定义在这里:
source/system/sepolicy/users
- 1
roles定义在这里:
source/system/sepolicy/roles
- 1
在SEAndroid中:
file_type 用来标注文件的安全上下文中的类型
domain 用来标注进程的安全上下文的类型
并且每一个用来描述文件安全上下文的类型都将file_type设置为其属性,每一个用来进程安全上下文的类型都将domain设置为其属性。
sepolicy结构
a. App进程 -> mac_permissions.xml
b. App数据文件 -> seapp_contexts
c. 系统文件 -> file_contexts
d. 系统属性 -> property_contexts
以上文件均位于external/sepolicy目录中。
- 1
- 2
- 3
- 4
- 5
te文件常见的四种命名规则
- allow:赋予某项权限。
- allowaudit:audit含义就是记录某项操作。默认情况下是SELinux只记录那些权限检查失败的操作。allowaudit则使得权限检查成功的操作也被记录。注意,allowaudit只是允许记录,它和赋予权限没关系。赋予权限必须且只能使
用allow语句。 - dontaudit:对那些权限检查失败的操作不做记录。
- neverallow:前面讲过,用来检查安全策略文件中是否有违反该项规则的allow语句
在te文件中,我们一般遇到的语法是这样的:
rule_name source_type target_type:class perm_set
解读为: 为source_type设置一个rule_name的规则,规则是对target_type的class 进行 perm_set的操作。
- 1
- 2
下面拿些栗子给大家尝尝:
neverallow { appdomain -unconfineddomain } kmem_device:chr_file { read write };
绝对不允许app(除了有unconfineddomain属性的app)对kmem_device类型的字符设备进行读写的操作
neverallow { appdomain -unconfineddomain } self:capability2 *;
绝对不允许除了unconfineddomain以外的app对self类型的capability2进行任何的操作
type httpd_user_content_t, file_type, httpdcontent;
声明一个httpd_user_content_t的类型,具有file_type和httpdcontent的属性
type httpd_user_content_t;
声明一个httpd_user_content_t的类型
typeattribute httpd_user_content_t file_type, httpdcontent;
定义httpd_user_content_t具有file_type, httpdcontent的属性
allow user_t bin_t:file ~{ write setattr ioctl };
允许user_t对bin_t类型的file进行除了write setattr ioctl相关的操作
type_transition system wifi_data_file:sock_file system_wpa_socket;
当一个类型为system的类别去进行wifi_data_file类型的sock_file访问时,类型默认切换到system_wpa_socket
allow {user_t domain} {bin_t file_type sbin_t}:file execute ;
允许user_t和domain属性的类对bin_t, file_type, sbin_t类型的file进行可执行的操作
allow init unlabeled:filesystem mount;
允许init类型对unlabeled类型的filesystem进行mount的操作
allow init fotad:unix_stream_socket { bind create };
允许init类型对fotad类型的unix_stream_socket 进行bind和create的操作
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
type和class命令
一个Type所具有的权限是通过allow语句来描述的,
allow unconfineddomain domain:binder { call transfer set_context_mgr };
表明domain为unconfineddomain的进程可以与其它进程进行binder ipc通信(call),并且能够向这些进程传递Binder对象(transfer),以及将自己设置为Binder上下文管理器(set_context_mgr)
- 1
- 2
- 3
type命令格式
type的命令如下:
type type_id [alias alias_id,] [attribute_id]
将type_id(别名为alias)关联到attribute. 这样的话,方便用attribute来管理不同的type中包含相同的属性的部分。
type init, domain;
将init关联到domain,即将domain设置为init类型的属性
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
class命令的格式
class class_name [ inherits common_name ] { permission_name ... }
inherits表示继承了common定义的权限,然后自己额外实现了permission_name的权限
- 1
- 2
- 3
以上就是最近关于SEAndroid的记录,以后会不断更新该篇,或者等到自己相对理清了SEAndroid,会分开来记录学习。