阅读:9336回复:3
Android SELinux详解
一、SELinux是什么?
SELinux是一套完整的安全策略,最开始是美国国家安全局和一些公司联合设计为了针对Linux系统的安全隐患而产生的一套系统,它为每一个进程,每一个文件,每一个属性都定义了标签,用来控制进程对文件的操作的权限控制! 在安卓里面,SELinux有三种状态: enforce模式:强制模式,必须有配置权限才能访问/操作 SELinux默认是打开的。我们可以在窗口命令行下输入命令getenforce来查看我们的设备的SELinux状态。我们可以在命令行下输入命令:setenforce 0暂时性的将SELinux关闭,如果需要永久关闭,需要我们编译软件之前,在uboot和kernel代码中将androidboot.selinux属性设置为disable。 二、安全上下文标签 上面有提到SELinux系统中,每一个对象(进程和文件或者设备)都有自己的安全标签。在串口下,通过ps -Z命令可以查看进程的安全上下文标签,可以通过ls -Z查看文件的安全上下文标签,例如:
看到一个完整的安全上下文它由四部分组成:u,r,init,s0 u:表示用户,Android系统的SELinux中之定义了一个用户,所有的进程都属于同一个安全用户,叫做:u r:表示角色,表示这是一个进程的安全上下文,和文件的安全上下文(object_r),属性上下文和其他上下文彼此区分 init:这个字段对于进程或者服务来说,是表示进程运行的域,也叫:domain(后面配置规则的时候会遇到),而对于文件或者其他对象来说,可以理解为类型type。根据不同的对象(有的是文件,有的是设备,有的是进程),Android定义了100多个不同的关键字来区别这些进程的域和文件和设备的类型。 s0:安全级别,第四列专为多级安全功能(扩展 MLS)而设计,MLS 是一种访问机制,可增加安全上下文和格式敏感度 [: 类别列表] [-敏感度 [: 类别列表]],例如 s0 - s15: c0 - c1023,而在当前Android 版本中不需要类别。 在安卓系统中,我们只需要重点关注第二和第三个字段,就是角色和域/类型。 三、如何配置SELinux的策略 SEAndroid 策略源位于 SDK system/sepolicy 目录。该策略包括用于生成 SELinux 核心策略文件的源文件:file_contexts 配置、property_contexts 配置、seapp_contexts 配置和 mac_permissions.xml 配置。 * file_contexts 配置用于在构建(例如,系统分区)和运行时(例如,设备节点、服务套接字文件与设备相关的策略文件位于 device/xxxxxxx/common/sepolicy 目录中。 在配置规则之前,我们首先要知道什么是规则? 配置规则我们一般写在device/xxxxxxx/common/sepolicy目录下的te文件中。可以看到这个目录下有很多的te文件。 那么具体应该如何来编写呢?这里我们举一个例子来说明:假如我们要在init.rc文件中启动一个service,他的功能是在开机的时候安装一些APP,我们已经编译好了这个service的可执行文件:preinstall。 1.首先刚刚上面讲了,每一个对象不管是文件还是属性还是设备,在SELinux下都有一个安全上下文,我们首先要定义我们的可执行文件preinstall的安全上下文,这个上面有介绍是在device/xxxxxxx/common/sepolicy/file_contexts文件中设置的:按照上面介绍的安全上下文格式,4个部分,我们定义为: /system/bin/preinstall u:object_r:preinstall_exec:s0 可以看到,我们给preinstall的类型取名叫:preinstall_exec。为啥叫这个名字?我们稍后介绍! 上面说了规则的主体是domain,那么这里,我们的domain是什么呢?我们的preinstall是写在init.rc中,是fork自init进程的,init进程的domain系统已经配置了,它的domain就叫做“init”。在SELinux的系统中,子进程fork父进程,他们的domain也是默认继承自父进程,所以我们的preinstall所在的子进程的域默认也是“init”。那我们是不是可以开始针对“init”这个domain开始编写规则了呢?答案是不能!因为init进程域是系统的,负责很多基础的工作,而我们的preinstall进程和init进程没有什么关系和联系,是彼此独立的两个功能,在SELinux的原则上,应该将preinstall进程域从init进程域中单独出来,仅针对preinstall子进程域配置该有的权限,而不是直接在init进程域的基础上新增缺少的权限,这样也是为了符合SELinux的规范!那么问题来了,怎么创建preinstall自己的的domain呢? 我们在device/xxxxxxx/common/sepolicy/目录下新建一个文件,取名就叫preinstall.te: //这句话是声明一个新的domain,名字叫:preinstall 这样写完了之后,我们就了自己的domain,可以开始给自己的domain主体设置权限了,安装APP,我们需要从/data目录下读取文件,那么这个data目录的访问权限如何写呢? 首先我们可以在命令行下通过ls -Z查看一下data目录的安全上下文: ls -Z 其中的vendor_file就是我们的type了。写权限命令之前,我们把标准公式拿出来: [section_rule] [section_domain] [section_target] [section_action] section_rule:规则名称,常用的有:allow允许,dontaudit不记录,neverallow不允许。 section_domain:domain域,对哪一个domain进行操作,就写哪个名字。 section_target:操作的对象type信息,有安全上下文的中type,后面加冒号,加一个class组成。class有file,dir,fd等等,具体可以在security_classes文件中可以查看。 section_action:具体的动作,读read,写write,创建create等,具体可以在access_vectors文件中查看! 那么很简单了,我们就能写出我们的完整的te文件了: type preinstall domain 还有一些我们没想到的权限,就需要抓取打印dmesg | grep avc查看违反了那些规则:可以使用 linux 工具 allow2audit 可以将违反规则的 avc 记录生成放行规则 (适合于dmesg 所有输出,初期的开发阶段)。也可以手动来写规则,例如打印如下: type=1400audit(1386760471.880:7):avc: denied {entrypoint}for pid=1227comm=``init''path=``/我们从scontext中获取到domain:healthd,从tcontext中获取到type:rootfs,tclass:file 所以我们可以写出rule如下: allow healthd rootfs:file entrypoint;将以上rule语句写进名字为“healthd.te”的文件中,重新编译即可!然后重新测试,在抓取打印看看是否还有缺失的打印,反复几次就OK了! 四、App应用的安全上下文标签 上面介绍了我们的二进制可执行文件一般都是通过domain迁移来确定自己的domain,而APP应用的安全上斜纹标签却不一样,这里我们单独介绍。 seinfo 我们都知道APP都会被签名,一般有这四种签名:platform,media,test,shared。而SELinux系统就是根据APP被签名的不同,定义了不同的seinfo(安全信息)概念。在system/sepolicy/private/mac_permissions.xml文件中定义了根据不同的签名来确定不同的seinfo: <!-- Platform dev key in AOSP -->可以看到默认这里之定义了三个seinfo,如果我们APP的签名不在这几个里面,那么seinfo会取值为“default”。确定了seinfo后,再根据system/sepolicy/private/seapp_contexts文件确认doamain和type: neverallow isEphemeralApp=true domain=((?!ephemeral_app).)*以上文中红色字这行为例:当user是system时,seinfo是platform,那么它的domain就是system_app,它的文件type就是system_app_data_file。 这里的user是指的APP的uid,系统会为每一个应用分配一个uid,定义在system/core/include/private/android_filesystem_config.h文件中,android系统默认保留了1000-9999之内的uid,例如1000就是表示system: #define AID_ROOT 0 /* traditional unix root user */ 那如果我们的APP是第三方APP,安装后他的user一般是这种形式的:u0_xxx,那么这些APP在seapp_contexts文件中怎么表示呢?Android系统对于所有的不是系统预定义的user的其他,全部表示为:"_app",通过上文中的蓝色字体可以看到,这些APP基本上被认定为domain:untrusted_app, untrusted_app_27, untrusted_app_25 。 再从上述绿色的行可以看到,还可以用APP的进程name来匹配。 如果我们需要针对我们的某一个预装在system目录下使用platform签名的APP单独一个安全上下文,我们只需要在我们自己的SELinux目录device/xxxxxxx/common/sepolicy/private目录新增seapp_contexts文件,新增一条: user=system seinfo=platform domain=mytest_app name=com.mytest.app type=mytest_app_data_file 前提是mytest_app这个domain和mytest_app_data_file这个type也要手动的定义。 有了单独的domain,我们可以针对这个APP单独配置权限了。 |
|
|
沙发#
发布于:2020-05-01 07:18
先赞一个
|
|
|