Android SELinux介绍和配置

本文的文档连接在以下位置,如有需要可以下载:

https://download.csdn.net/download/fanx9339/12542410 

  • SELinux是什么?

    SELinux是一套完整的安全策略,最开始是美国国家安全局和一些公司联合设计为了针对Linux系统的安全隐患而产生的一套系统,它为每一个进程,每一个文件,每一个属性都定义了标签,用来控制进程对文件的操作的权限控制!
在安卓里面,SELinux有三种状态:

enforce模式:强制模式,必须有配置权限才能执行相应的访问/操作
permissive模式:宽容模式,打印记录出现的越权行为,但是不禁止该访问/操作
disable:关闭模式,关闭SELinux,不受SELinux权限控制,此模式会导致不安全风险

SELinux默认是打开的。我们可以在窗口命令行下输入命令getenforce来查看我们的设备的SELinux状态。我们可以在命令行下输入命令:setenforce 0暂时性的将SELinux关闭,如果需要永久关闭,需要我们编译软件之前,在ubootkernel代码中将androidboot.selinux属性设置为disable

  • 安全上下文标签

    上面有提到SELinux系统中,每一个对象(进程和文件或者设备)都有自己的安全标签。在串口下,通过ps -Z命令可以查看进程的安全上下文标签,可以通过ls -Z查看文件的安全上下文标签,例如:

  1. LABEL                          USER     PID   PPID  NAME
  2. u:r:init:s0                    root 1 0 /init
  3. u:r:kernel:s0                  root 2 0 kthreadd
  4. ...
  5. u:r:kernel:s0                  root 258 2 irq/322-HPH_R O
  6. u:r:logd:s0                    logd 259 1 /system/bin/logd
  7. u:r:healthd:s0                 root 260 1 /sbin/healthd
  8. u:r:lmkd:s0                    root 261 1 /system/bin/lmkd
  9. u:r:servicemanager:s0          system 262 1 /system/bin/servicemanager
  10. u:r:vold:s0                    root 263 1 /system/bin/vold
  11. u:r:surfaceflinger:s0          system 264 1 /system/bin/surfaceflinger


看到一个完整的安全上下文它由四部分组成:u,r,init,s0
u表示用户,Android系统的SELinux中只定义了一个用户,所有的进程都属于同一个安全用户,叫做:u
r表示角色,表示这是一个进程的安全上下文,和文件的安全上下文(object_r),属性上下文和其他上下文彼此区分
init这个字段对于进程或者服务来说,是表示进程运行的域,也叫:domain(后面配置规则的时候会遇到),而对于文件或者其他对象来说,可以理解为类型type。根据不同的对象(有的是文件,有的是设备,有的是进程),Android定义了100多个不同的关键字来区别这些进程的域和文件和设备的类型。我们可以根据需求自定义,例如本文中后面定义的preinstallpreinstall_exec
s0安全级别,第四列专为多级安全功能(扩展 MLS)而设计,MLS 是一种访问机制,可增加安全上下文和格式敏感度 [: 类别列表] [-敏感度 [: 类别列表]],例如 s0 - s15: c0 - c1023,而在当前Android 版本中不需要类别。敏感度和类别组合表示当前的安全级别,数字根据最低和最高级别的安全功能进行确定。刺裂参数被用于查看MLS限制,其中“15”和“1023”表示最大敏感度和类别,此参数范围可以在Android.mk中进行确定,Android中默认配置为“1”和“1024”,代表敏感度只定义了s0,类别列表定义了c0-c1023
在安卓系统中,我们只需要重点关注第二和第三个字段,就是角色和域/类型。
 

  • 如何配置SELinux的策略

    SEAndroid 策略源位于 SDK system/sepolicy 目录。该策略包括用于生成 SELinux 核心策略文件的源文件:file_contexts 配置、property_contexts 配置、seapp_contexts 配置和 mac_permissions.xml 配置。
 

* file_contexts 配置用于在构建(例如,系统分区)和运行时(例如,设备节点、服务套接字文件和由 init.rc 创建的/数据目录等)标记文件。
* property_contexts 被用于指定 Android 属性的安全上下文,供查看权限。
* seapp_contexts 配置被用于标记应用进程和应用程序包目录。
* mac_permissions.xml 配置是中间件 MAC 策略

与设备相关的策略文件位于 device/xxxxxxx/common/sepolicy 目录中。

 

在配置规则之前,我们首先要知道什么是规则?

规则就是针对domain对象的,上面我们说过,每一个进程都属于一个domain(域),规则就是设置哪个domain(域)的对象(就是进程)能够对哪些type(类型)的目标对象(文件或者属性或者设备)具有哪有操作(删除啊,访问啊等等),这就是规则!


配置规则我们一般写在device/xxxxxxx/common/sepolicy目录下的te文件中。可以看到这个目录下有很多的te文件。
那么具体应该如何来编写呢?这里我们举一个例子来说明:假如我们要在init.rc文件中启动一个service,他的功能是在开机的时候安装一些APP,我们已经编译好了这个service的可执行文件:preinstall
刚刚上面讲了,每一个对象不管是文件还是属性还是设备,在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中,是forkinit进程的,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
type preinstall  domain
//这句话是声明一个新的type,名字叫:preinstall_exec,我们之前在file_contexts中引用了这个type的。
//后面的exec_type就是说把我们新的preinstall_exec和系统定义好的exec_type关联起来,可以类比于java的继承,子类继承父类的属性的概念。因为我们的preinstall是个可执行文件,所以我们继承了系统的exec_type,而不是device_type很好理解吧,也可以同时关联多个type,例如:type preinstall_exec exec_type vendor_type,就是说我的preinstall_type同时和exec_typevendor_type具有相同的类型。
type preinstall_exec exec_type
//这下面这句话的方法实现在源码中的te_macros文件中,意思我大概翻译一下就是:
init进程中执行了“preinstall_exec” type的文件时,将新的子进程的domain从默认的init转换到preinstall这个domain
init_daemon_trans(preinstall)


这样写完了之后,我们就了自己的domain,可以开始给自己的domain主体设置权限了,安装APP,我们需要从/data目录下读取文件,那么这个data目录的访问权限如何写呢?
首先我们可以在命令行下通过ls -Z查看一下data目录的安全上下文:

ls -Z
data         u:object_r:vendor_file:s0

其中的vendor_file就是我们的type了。写权限命令之前,我们把标准公式拿出来:

[section_rule] [section_domain] [section_target] [section_action]

section_rule:规则名称,常用的有:allow允许,dontaudit不记录,neverallow不允许。
section_domaindomain域,对哪一个domain进行授权,就写哪个名字。
section_target:操作的对象type信息,由安全上下文的中type,后面加冒号,加一个class组成。classfiledirfd等等,具体可以在security_classes文件中可以查看。
section_action:具体的动作,读read,写write,创建create等,具体可以在access_vectors文件中查看!

那么很简单了,我们就能写出我们的完整的te文件了:

type preinstall  domain
type preinstall_exec exec_type
init_daemon_trans(preinstall)
allow preinstall vendor_file:file read

还有一些我们没想到的权限,就需要抓取打印dmesg | grep avc查看违反了那些规则:可以使用 linux 工具 allow2audit 可以将违反规则的 avc 记录生成放行规则 (适合于dmesg 所有输出,初期的开发阶段)。也可以手动来写规则,例如打印如下:
 

type=1400audit(1386760471.880:7):avc: denied {entrypoint}for pid=1227comm=``init''path=``/
sbin/healthd''dev=``rootfs''ino=4396scontext=u:r:healthd:s0tcontext=u:object_r:rootfs:s0tclass=file

我们从scontext中获取到domain=healthd,tcontext中获取到type=rootfstclass=file
所以我们可以写出rule如下:

allow healthd rootfs:file entrypoint;

将以上rule语句写进名字为“healthd.te”的文件中,重新编译即可!然后重新测试,在抓取打印看看是否还有缺失的打印,反复几次就OK了!

 

四、App应用的安全上下文标签

    上面介绍了我们的二进制可执行文件一般都是通过domain迁移来确定自己的domain,而APP应用的安全上下文却不一样,这里我们单独介绍。

seinfo

我们都知道APP都会被签名,一般有这四种签名:platformmediatestshared。而SELinux系统就是根据APP被签名的不同,定义了不同的seinfo(安全信息)概念。在system/sepolicy/private/mac_permissions.xml文件中定义了根据不同的签名来确定不同的seinfo:

<!-- Platform dev key in AOSP -->

    <signer signature="@PLATFORM" >

      <seinfo value="platform" />

    </signer>



    <!-- Media key in AOSP -->

    <signer signature="@MEDIA" >

      <seinfo value="media" />

    </signer>



    <signer signature="@NETWORK_STACK" >

      <seinfo value="network_stack" />

    </signer>

    可以看到默认这里只定义了三个seinfo,如果我们APP的签名不在这几个里面,那么seinfo会取值为“default”

确定了seinfo后,再根据system/sepolicy/private/seapp_contexts文件确认doamaintype

neverallow isEphemeralApp=true domain=((?!ephemeral_app).)*

 

isSystemServer=true domain=system_server_startup

 

user=_app seinfo=platform name=com.android.traceur domain=traceur_app type=app_data_file levelFrom=all

user=system seinfo=platform domain=system_app type=system_app_data_file

user=bluetooth seinfo=platform domain=bluetooth type=bluetooth_data_file

user=network_stack seinfo=network_stack domain=network_stack levelFrom=all type=radio_data_file

user=nfc seinfo=platform domain=nfc type=nfc_data_file

user=secure_element seinfo=platform domain=secure_element levelFrom=all

user=radio seinfo=platform domain=radio type=radio_data_file

user=shared_relro domain=shared_relro

user=shell seinfo=platform domain=shell name=com.android.shell type=shell_data_file

user=webview_zygote seinfo=webview_zygote domain=webview_zygote

user=_isolated domain=isolated_app levelFrom=all

user=_app seinfo=app_zygote domain=app_zygote levelFrom=all

user=_app seinfo=media domain=mediaprovider name=android.process.media type=app_data_file levelFrom=user

user=_app seinfo=platform domain=platform_app type=app_data_file levelFrom=user

user=_app isEphemeralApp=true domain=ephemeral_app type=app_data_file levelFrom=all

user=_app isPrivApp=true domain=priv_app type=privapp_data_file levelFrom=user

user=_app minTargetSdkVersion=29 domain=untrusted_app type=app_data_file levelFrom=all

user=_app minTargetSdkVersion=28 domain=untrusted_app_27 type=app_data_file levelFrom=all

user=_app minTargetSdkVersion=26 domain=untrusted_app_27 type=app_data_file levelFrom=user

user=_app domain=untrusted_app_25 type=app_data_file levelFrom=user

user=_app minTargetSdkVersion=28 fromRunAs=true domain=runas_app levelFrom=all

user=_app fromRunAs=true domain=runas_app levelFrom=user

以上文中红色字这行为例:当usersystem时,seinfoplatform,那么它的domain就是system_app,它的文件type就是system_app_data_file

这里的user是指的APPuid,系统会为每一个应用分配一个uid,定义在system/core/include/private/android_filesystem_config.h文件中,android系统默认保留了1000-9999之内的uid,例如1000就是表示system

那如果我们的APP是第三方APP,安装后他的user一般是这种形式的:u0_xxx,那么这些APPseapp_contexts文件中怎么表示呢?Android系统对于所有的不是系统预定义的userAPP,全部表示为:"_app",通过上文中的蓝色字体可以看到,这些APP基本上被认定为domainuntrusted_app, untrusted_app_27, untrusted_app_25 

#define AID_ROOT 0 /* traditional unix root user */

/* The following are for LTP and should only be used for testing */

#define AID_DAEMON 1 /* traditional unix daemon owner */

#define AID_BIN 2    /* traditional unix binaries owner */



#define AID_SYSTEM 1000 /* system server */



#define AID_RADIO 1001           /* telephony subsystem, RIL */

#define AID_BLUETOOTH 1002       /* bluetooth subsystem */

#define AID_GRAPHICS 1003        /* graphics devices */

#define AID_INPUT 1004           /* input devices */

#define AID_AUDIO 1005           /* audio devices */

#define AID_CAMERA 1006          /* camera devices */

再从上述绿色的行可以看到,还可以用APP的进程name来匹配。

如果我们需要针对我们的某一个预装在system目录下使用platform签名的APP单独一个安全上下文,我们只需要在我们自己的SELinux目录device/xxxxxxx/common/sepolicy/private目录新增seapp_contexts文件(直接修改system/sepolicy目录下会导致无法过CTS认证),新增一条:

user=system seinfo=platform domain=mytest_app name=com.mytest.app type=mytest_app_data_file

前提是mytest_app这个domainmytest_app_data_file这个type也要手动的定义。

有了单独的domain,我们可以针对这个APP单独配置权限了。

 

在自己的自定义的目录下新增te文件,要带上:

BOARD_SEPOLICY_DIRS += paxdroid/device/a100/sepolicy

把目录编译进去!

### 回答1: Android SELinuxAndroid操作系统中的一种安全机制,它可以限制应用程序的访问权限,保护用户数据的安全性。SELinux是一种强制访问控制(MAC)机制,它通过强制规则来限制应用程序的访问权限,即使应用程序本身存在漏洞,也可以保护系统的安全性。Android SELinux的实现基于Linux内核的SELinux模块,它通过定义安全策略来控制应用程序的访问权限,包括文件系统、网络、进程等方面。Android SELinux的实现需要在系统级别进行配置,因此需要一定的技术知识和经验。 ### 回答2: 安卓的SELinux是一项安全功能,做到了不同级别权限间的隔离。它与Linux的SELinux相似,都是基于Mandatary Access Control(MAC)的实现。MAC使用了定义好的安全策略来决定进程访问对象的许可。每个对象有一个或多个安全标签,决定了可访问这些对象的访问者。SELinux实现了一个高度定制化的MAC实现,以达到保护系统免受攻击的效果。 SELinux可以将任何应用程序、库或系统进程在安全上互相隔离。每个进程可以分配一个不同的安全上下文,用于决定该进程可以执行的操作。SELinux允许管理员定义一个策略集,以确保只有那些拥有特定权限的应用程序可以执行特定的操作。SELinux包括以下4个组件。 * Security-enhanced kernel:该内核支持SELinux,并且为应用程序和系统提供安全保护。通常,操作系统上的SELinux是直接编译到内核配置中的。 * SELinux policy:这是一组规则,它定义了哪些进程可以访问哪些资源,以及何时可以访问它们。这是SELinux的“脑”。SELinux策略通过使用安全标签来标识资源和进程,并使用规则来决定它们之间的安全关系。 * SELinux utilities:这些社区提供的工具用于安装、更新和管理SELinux策略。通常情况下,管理员会安装每个Linux发行版自带的安全工具。 * SELinux-aware applications:这是应用程序和守护进程,它们能够在SELinux的约束下运行。这些应用程序还懂得如何处理SELinux策略,以确保它们对系统的安全有积极贡献。 总的来说,SELinux是一项强大而高度定制化的MAC实现,能够确保安卓系统和应用程序免受攻击。它通过一组规则定义了可用资源和进程之间的安全关系,从而在操作系统和应用层上实现了分离和隔离。作为一项优秀的安全保护功能,它能够在各种安卓设备上为用户提供强大的保护措施,从而发挥关键的作用。 ### 回答3: Android操作系统是目前全球手机、平板等终端设备最常用的操作系统之一。Android系统架构中有一个非常重要的安全机制,即SE_LINUX(Security-Enhanced Linux)。SE_LINUX是由美国国家安全局(NSA)和Redhat合作研发的一种新型操作系统,它基于强制性访问控制(Mandatory Access Control)机制,是一种可扩展的安全模型,功能十分强大。 Android系统使用SE_LINUX来保障应用程序的安全。在Android的SE_LINUX中,安全策略旨在为每个进程提供最佳的资源保护。当应用程序尝试访问受限制的资源时,安全策略会检查该应用程序的标记是否具有访问受限制资源的许可权,以确保安全性。如果没有访问权限,访问请求就会被拒绝,在应用程序层面上保证了Android系统的安全。 其中,SE_LINUX的工作原理是在内核上增加了一个“SELinux子系统”,具体实现过程如下:(1)在内核源代码中添加SELinux子系统;(2)在Linux 内核上开发安全模块;(3)编写用户空间程序和共享代码,实现SELinux规则和策略以及管理SELinux权限的机制。Android系统的SE_LINUX是基于SMLS架构,即安全、多层、标签、安全。 同时,SE_LINUX还为Android系统中的进程、文件系统、系统服务进行了标记化管理。每个进程都有一个唯一的SELinux安全上下文标签进行标识,涉及到的对象都会增加一个SELinux标签,当某个进程尝试访问某个对象时,它的SELinux上下文标签需要满足该对象的SELinux上下文标签的安全策略,否则该进程就会被降级或者拒绝访问该对象。 总之,Android SE_LINUX是Android操作系统架构中的重要安全机制,它通过强制性访问控制(Mandatory Access Control)机制来保护应用程序的安全,在访问受限制的资源时会进行检查、获取许可证以保证安全。SE_LINUX的工作原理是标记化管理,确保每个进程、文件系统、系统服务都对应一个唯一的安全标签,实现了权限的有效、高效管理。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

静默安装9339

希望本文章对你有一点点帮助

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值