吐槽:准备学习一下SELinux/SEAndroid手里有一本书《深入理解Android内核设计思想》,看完章节“我是谁?我在哪?”能理解四层的意思,我发现另外的六层都是给会的人写的,头大难搞。趁着假期查资料看博客,一点一点修补本文章,有理解偏差或理解不到位的地方望大佬们纠正。
内容提纲:
➢SEAndroid/SELinux简介
➢SEAndroid/SELinux框架
➢SELinux Policy介绍
➢安全策略文件(TE文件)
➢SELinux安全问题分析
----➢SELinux设备文件权限解决办法
----➢SELinux服务权限解决办法
----➢SELinux可执行权限解决办法
➢补充
----➢客体类型添加
SELinux呢这里就不展开讲述了,直接进行SEAndroid机制。前段时间u盘插上板子,作者利用串口交互,以root用户想要删除U盘里的内容,就会报错误权限不足,这就得益于SEAndroid对设备的全面保护。
SEAndroid是Google在nlet 4.4 上正式推出的一套以SELinux为基础于核的系统安全机制。而SELinux则是由美国NSA (国安局)和一些公司( RedHat、Tresys )设计的一 个针对 的安全加强系统。NSA最初设计的安全模型叫FLASK ,全称为Flux Advanced Security Kernel (由Uta大学和美国国防部开发,后来由NSA将其开源) , 当时这套模型针对DTOS系统。后来, NSA觉得Linux更具发展和普及前景,所以就在Linux系统上重新实现了FLASK,称之为SELinux。
两种安全机制DAC(Discretionary Access Control)和MAC(Mandatory Access Control)。通俗地讲,这两个机制的区别是。在DAC里,如果个应用获取了一个用户权限,如Root,那他的所有操作操作都是基于这个用户权限。而MAC就简单霸道好多,无论你是谁,甚至是有Root用户权限,文件权限为777,但每个动作都是需要被允许之后可以被执行。这里可以是在安全策略文件中被允许也可以是用户手动允许 。
用户看到的:服务权限、文件权限、属性权限、APP权限。
SELinux最终编译成libselinux.so文件,为上层提供服务。
SELinux两个最基本的对象是主体( Subject )和客体(Object )。主体和客体分别对应的是"进程”和“文件”。这里的文件并不单指的是实际存在的文件,而是指Linux里"一 切皆文件”里指的文件。如Socket ,系统属性等。
在SEAndroid中对主体和客体进行了进一步形式上的封装和扩展,其实差不多。SEAndroid里细分为 :系统文件,服务,系统属性,Binder和Socket.这里的系统属性指的是build.prop里的属性,也是getprop命令查询出来的属性。
1.ps - Z可以查看当前进程(主体)安全上下文。
root@rk3288:/ # ps -Z
LABEL USER PID PPID NAME
u:r:init:s0 root 1 0 /init
u:r:kernel:s0 root 2 0 kthreadd
u:r:kernel:s0 root 3 2 ksoftirqd/0
u:r:kernel:s0 root 5 2 kworker/0:0H
u:r:kernel:s0 root 7 2 migration/0
u:r:kernel:s0 root 8 2 rcu_preempt
u:r:kernel:s0 root 9 2 rcu_bh
u:r:kernel:s0 root 10 2 rcu_sched
u:r:kernel:s0 root 11 2 watchdog/0
u:r:kernel:s0 root 12 2 watchdog/1
u:r:kernel:s0 root 13 2 migration/1
u:r:kernel:s0 root 14 2 ksoftirqd/1
u:r:kernel:s0 root 16 2 kworker/1:0H
u:r:kernel:s0 root 17 2 watchdog/2
u:r:kernel:s0 root 18 2 migration/2
u:r:kernel:s0 root 19 2 ksoftirqd/2
u:r:kernel:s0 root 21 2 kworker/2:0H
u:r:kernel:s0 root 22 2 watchdog/3
u:r:kernel:s0 root 23 2 migration/3
u:r:kernel:s0 root 24 2 ksoftirqd/3
u:r:kernel:s0 root 26 2 kworker/3:0H
u:r:kernel:s0 root 27 2 khelper
u:r:kernel:s0 root 28 2 kdevtmpfs
左边的一列是Security Context。u:r:init:s0的意思是:
u,是指user,它代表SELinux的一个用户。
r,为role(角色)即Role Based Access(基于角色的访问控制,简称为RBAC),它是SELinux中比较高层次。简单点说,一个u可以属于多个role,不同的role具有不同的权限。
init/kernel,代表该进程所属的Domain(域)。
s0,SELinux为了满足军用和教育行业而设计的MultiLevel Security(MLS)机制。简单点说,MLS将系统的进程和文件进行了分级,不同级别的资源需要对应的级别的进程才能进行访问。
2.ls - Z可以查看当前文件(客体)安全上下文。
root@rk3288:/ # ls -Z
drwxr-xr-x root root u:object_r:cgroup:s0 acct
drwxrwxrwx root root u:object_r:rootfs:s0 bin
drwxrwx--- system cache u:object_r:cache_file:s0 cache
lrwxrwxrwx root root u:object_r:rootfs:s0 charger -> /sbin/healthd
dr-x------ root root u:object_r:rootfs:s0 config
lrwxrwxrwx root root u:object_r:rootfs:s0 d -> /sys/kernel/debug
drwxrwx--x system system u:object_r:system_data_file:s0 data
-rw-r--r-- root root u:object_r:rootfs:s0 default.prop
drwxr-xr-x root root u:object_r:device:s0 dev
drwx------ root root u:object_r:rootfs:s0 dmb
-rw-r--r-- root root u:object_r:rootfs:s0 drmboot.ko
drwxrwxrwx root root u:object_r:rootfs:s0 env_flag
lrwxrwxrwx root root u:object_r:rootfs:s0 etc -> /system/etc
-rw-r--r-- root root u:object_r:rootfs:s0 file_contexts
lrwxrwxrwx root root u:object_r:rootfs:s0 fstab.rk30board -> /fstab.rk30board.bootmode.emmc
-rw-r----- root root u:object_r:rootfs:s0 fstab.rk30board.bootmode.emmc
-rw-r----- root root u:object_r:rootfs:s0 fstab.rk30board.bootmode.unknown
drwxrwxrwx root root u:object_r:rootfs:s0 home
-rwxr-x--- root root u:object_r:init_exec:s0 init
-rwxr-x--- root root u:object_r:rootfs:s0 init.connectivity.rc
-rwxr-x--- root root u:object_r:rootfs:s0 init.environ.rc
-rwxr-x--- root root u:object_r:rootfs:s0 init.rc
-rw-r--r-- root root u:object_r:rootfs:s0 张志路-root.txt
在这里细心的朋友就会注意到:“之前我们Linux的label不是UID/GID吗?怎么变成了user:role:type:security了呢?”没错这都是SEAndroid替换的,注意我说的是‘替换’。SEAndroid呢,主要通过label中的Type来定义安全策略的(这就是Type Enforment)这就是我们.te文件的由来。
读到这里你可能就要问了,上面分析的这些信息在哪里被设置定义的呢?这些信息都在xxx_contexts文件中被登记在案的,前提是要先type定义客体,这个下面还会讨论。
MAC的安全策略文件学名是TEAC(Type Enforcement Access Control)。简称TE。里面的语言被称为强制类型语言。
在Android源码中对应的TE文件所在的路径为Android源码/external/sepolicy/
在SELinux当中,所有访问都必须明确授权,SEL inx默认不允许任何访问,完全不考虑当前UG0结构,即不考虑用户/组ID是什么。这也就意味着,在这里没有超级用户了。那么如果主体需要对客体进行访问该如何进行呢?
在SELinux当中,通常是使用allow规则来指定主体类型(即域)对客体类型授子访问权限,也就是allow规则规定了哪些类型的进程可以访问哪些客体。allow规则由四部分组成:
/* 主体 客体 */
allow domains types:classes permissons
SELinux Mode,SELinux Mode 有两种模式Permissve Mode(宽容模式)和Enforcing Mode(强制模式)。区别在于宽容模式只会打印SELinux Log。而强制模式会进行真正拦截。如果被拦截,kernel log中的关键字“avc:denied“。可以通过cat /sys/fs/selinux/enforc命令进行查看权限。
setenforce命令:
1.用type关键字定义客体。(这里就发挥一下我的联想类比能力。就好比出生去type一张身份证)
2.将定义的客体放到【file_contexts】或者【service_contexts】文件中,告诉系统你的客体。(就好像结婚登记)
3.用allow关键字添加说明主体访问客体的权限。(就好像修订自己家规家法)
avc:denied{
connectto} for pid=2671 comm="ping"
path="/dev/socket/dnsproxyd"
scontext=u:r:shell:s0 tcontext=u:r:netd:s0 tclass=unix_stream_socket
[53692.570392] type=1400 audit(12565266.940:42): avc: denied
{
read write } for pid=10794 comm="m.example.hello" name="led1"
dev="tmpfs" ino=39430 scontext=u:r:untrusted_app:s0
tcontext=u:object_r:device:s0 tclass=chr_file permissive=0
分析:
解决办法:在untrusted_app.te文件中添加
Allow untrusted_app device:chr_file {
read write }
把缺少的权限添加上去,添加的过程如下:
先进去Android源码下的/external/sepolicy/下
①修改file_contexts
/dev/led1 u:object_r:led1_device:s0
②修改device.te
type led1_device, dev_type(, mlstrustedobject); (括号内为6.0权限)
③修改untrusted_app.te
allow untrusted_app led1_device:chr_file rw_file_perms;
添加好了之后重新编译Android的源码,烧写system.img和boot.img
131 E SELinux : avc: denied {
add } for service=Hello
scontext=u:r:system_server:s0 tcontext=u:object_r:default_android_service:s0
tclass=service_manager
分析:
解决方法:在system_server.te中添加
allow system_server default_android_service:service_manager add;
先进去Android源码下的/external/sepolicy/下
①在service.te文件中添加
type Hello_service, (app_api_service,)service_manager_type; (括号内为6.0权限)
②在service_contexts文件中添加
Hello u:object_r:Hello_service:s0
③在system_server.te文件中添加
allow system_server Hello_service: service_manager add;
12-25 11:51:27.260 147 147 W init : type=1400
audit(0.0:4): avc: denied {
execute_no_trans } for
path="/system/bin/test" dev="nandd" ino=476
scontext=u:r:init:s0 tcontext=u:object_r:system_file:s0
tclass=file permissive=0
分析:
解决方法:在init.te中添加
allow init system_file:file execute_no_trans;
先进去Android源码下的/external/sepolicy/下
①新建test.te文件中添加
type test,domain;
type test_exec,exec_type,file_type;
init_daemon_domain(test)
②在file_contexts文件中添加
/system/bin/test u:object_r:test_exec:s0
③在init.te文件中添加
allow test system_file:file execute_no_trans;
添加好了之后重新编译Android的源码,烧写system.img和boot.img
根据我们上面讲的TE文件语法那一小节,了解到allow语句。注意allow语句是主体访问客体缺少权限,allow语句添加权限信息。
但是系统并不认识我们写的客体,这时,我们就需要用type 语句定义一下我们的客体(客体类型添加),让系统认识一下。
这里我们先看一小段init.te的内容:
类型声明语法:
Android系统是允许设备厂商定制自己的安全策略的。先留个尾巴,后续再写。