SeLinux详解

概览

当我们在编写一些系统功能,往往会涉及到selinux。它是什么呢?本文将通过以下6个方面去进行介绍:

  • SeLinux概述
  • SEAndroid中的标签文件,策略文件及策略规则
  • SEAndroid中定义的宏
  • SEAndroid中的约束
  • SEAndroid的编译规则
  • SELinux修改实例

SeLinux概述

什么是SeLinux?

  SELinux的全称是安全加强的Linux (Security-EnhancedLinux)。Android通过SELinux对所有的进程,甚至是拥有root/superuser特权的进程加强访问约束。通过SELinux,Android可以更好地保护和限制系统服务对应用数据和系统日志的访问,从而减少恶意软件的影响。
  SELinux遵循默认拒绝的原则,任何没有被策略文件允许的操作都是被拒绝的。如果某个进程想访问指定的文件需要在策略文件中明确地指出。

SeLinux的两种运行模式

Permissive mode (宽容模式):
  不被许可的操作会记录下来,但是不会停止该操作
Enforcing mode (强制模式):
  不被许可的操作会记录下来,同时该操作会被阻止

背景

Android 版本 SeLinux功能
Android 5.0 Android全面实行强制模式
Android 6.0 通过减少许可策略的操作来加强系统安全,这些操作包括:用户隔离,IOCTL过滤,减少暴露的服务,进一步收紧selinux域和限制/proc访问
Android 7.0 更新SELinux的配置,进一步锁定应用程序沙盒,减少攻击面。将整体的mediaserver堆栈分解成更小的进程,以减少其权限范围
Android 8.0 这个版本上采用Treble框架,将底层的供应商代码从Android系统framework中分离,同时更新SELinux允许设备制造商和SOC供应商去更新它们各自的策略部分

MAC&DAC

  MAC的全称是:Mandatory access control,强制访问控制。
  DAC的全称是:Discretionary access control,自主访问控制。
  在DAC系统中,指定资源的所有者控制着它的访问权限。这通常是粗粒度的,并且会受到权限意外提升的影响。相较而言,SELinux可以识别各类内核对象和在它们身上执行的敏感换作。当这些敏感操作执行时,一个基于安全对象存储信息来判断该操作是否被允许的函数会运行。SELinux正是这些函数的实现者以及这些安全对象的管理者。SELinux为传统的DAC环境提供了一个MAC的保护伞。比如,只有root用户才能向原始的块设备写东西。对于传统的基于DAC的Linux环境来说,一旦root用户受到威胁,它可以给每个原始块设备写入数据。但是,SELinux可以通过策略文件让获得root权限的进程只对指定标签的设备写入数据。这样该进程就无法对其他的设备进行修改了。

SeLinux中的标签文件,策略文件及策略规则

标签文件

  我们想一想,如果需要对系统中的所有对象都进行区分并划分其权限,那么我们第一步要怎么做?首先我们需要给所有的对象加上一个标签,这个标签对比来说就是人的身份证,通过身份证我们知道你是哪里人。同理,通过标签我们也能知道这些对象是属于哪个部分的,也就是在Android中每个对象都有对应的se标签。谈到se标签,首先我们需要了解其对应的格式,其格式是user:role:type:mls_level。它由4个部分组成,user代表用户,role代表角色,type代表这个对象所属的类型,mls level代表se权限的敏感级别。在SeLinux中mls通常有s0、s1、s2和s3四个级别,而我们在Android系统中只用到了s0。除此以外,Android系统中的角色也只有object_r这一个。
  在Android系统中根据对象的类型定义了几种重要的标签文件,分别是:file_contexts、genfs_contexts、property_contexts、 service_contexts、 seapp_contexts以 及mac_permissions.xml。

  • file_contexts
      介绍file contexts文件和其内容之前,有些知识我们要先了解。Android系统中存在大量的文件,同时也存在很多种文件系统。比如本机文件系统,其作用是将数据保存到硬盘或可移动多媒体设备,其代表有ext3和XFS;兼容其他系统的非本地文件系统,代表有vfat;还有在内存中用于内核和用户空间交互的伪文件系统,代表有proc和sysfs。不同的文件系统,作用不同,从而导致对应的se标签也不一样,当然se标签的格式也是不一样。file_contexts这个文件中对应的就是支持扩展属性的文件系统对象的se标签,即前面所说的本机文件系统。对应的文件系统有ext2,ext3,xfs,jfs,reiserfs等。file_contexts中对应的标签内容书写格式是这样的:
    在这里插入图片描述其中文件类别是一个可选的参数,它对应的是文件类型,主要有以下几种文件类型:

    • b:块文件
    • c:字符文件
    • d:目录文件
    • p:命名管道文件
    • f:常规文件
    • l:链接文件
    • s:套接字文件

    具体使用效果如下:
    在这里插入图片描述Google在Android系统中定义了对应的file_contexts文件,路径 是/system/sepolicy/private/file_contexts。其中部分内容如下:
    在这里插入图片描述

  • genfs_contexts
      genfs_contexts文件中包含的也是文件对象对应的标签。和file_contexts文件不同的是文件对象所属的文件系统是不同的。file_contexts中的标签是给支持可扩展属性的文件系统的,也就是Linux硬盘上常用的文件系统;而genfs_contexts文件中对应的标签是在内存中用于内核和用户空间交互的伪文件系统。两个文件性质上来说是一样的,但是因为所对应的文件系统不同,所以书写的格式也不同。genfs_contexts中标签的格式如下:
    在这里插入图片描述
    Google在Android系统中也定义了相关的genfs_contexts文件,其部分内容如下:
    在这里插入图片描述

  • property_contexts
      这个文件包含的是Android系统中属性所对应的标签。系统通过这些标签来控制哪些应用(即进程)可以设置系统的属性,它们会在启动时加载到init进程中。标签格式如下:
    在这里插入图片描述

  • service_contexts
      该文件中的内容是Angroid binder服务所对应的标签。系统通过这些标签来控制哪些应用(即进程)可以注册和查询一个服务的binder引用。这些配置会在启动时加载到servicemanager进程中。

  • seapp_contexts
      这个文件中的内容是Android 应用和/data/data目录所对应的标签。这些配置会在每个应用启动时被加载到zygote进程或在启动时被加载到installd。

  • mac_permissions.xml
      这不是一个标签文件,在这个文件中,Google会根据应用的签名或者应用的包名去分配一个seinfo标签。在seapp_contexts文件中,seinfo标签的值可以当作key找到应用所对应的标签。这些配置会在启动时添加到system_server中。

策略文件及规则

  策略文件是以.te为后缀的,组成策略语句的内容有:策略规则语句、类型、权限及相关的宏。通常我们在撰写策略语句的时候会先声明类型,类型是标识系统中每个要进行访问或者其他操作的进程的,就像标识所要控制资源对象的标签一样。声明进程类型的语法是:
   type type_name [ alias alias_set] [, attribute_set];
声明时要使用type关键字;type_name指的是要声明的类型名称;alias是给类型指定别名的关键字;alias_set是别名集合,每个类型可以有一个或多个别名,当有多个别名时需要用{}将它们包裹起来,同时别名之间要以间隔隔开;attribute_settype关联的属性集合,属性和别名之间要通过逗号隔开,属性与属性之间也要通过逗号隔开。
  属性的作用是为了简化策略规则的编写而诞生的。对于一个复杂的策略来说,一个type要同时具有多个权限才能使功能得到正常执行,而属性则可以给type带来这个效果。举个例子来说:
    #Allow read/write access to /dev/null
   allow domain null_device chr_file {getattr open read ioctl lock append write};
  这条策略语句允许domain属性的应用去访问并读写null_device这个标签所表示的对象的字符文件。如果我们定义了一个type,并且这个type关联了domain属性,那么代表type对应的进程也可以访问并读写null_device这个标签代表的对象的字符文件。属性声明语法如下:
   attribute attribute_name;
attribute是关键字,attribute_name是对应的属性名称。
  除了在声明类型时可以关联属性之外,我们还可以通过typeattribute去关联之前定义的类型和属性。语法如下:
   typeattribute type_name attrib_names;
type_name是类型名称,attrib_names是属性名称。

SeLinux中定义的4种访问向量规则

allow:用于描述允许类型之间进行访问。
dontaudit:指定的访问权限被拒绝后的信息不会被记录下来。
auditallow:指定的访问事件信息会被记录下来。
neverallow:指定哪些访问权限不能在任何allow规则中被允许,也就是策略中指定neverallow的规则,在别的地方也不能被允许,否则编译会报错。

常规的策略语法

Rule name:allow, dontaudit, auditallow 或者 neverallow。
Source type(s):被允许访问的类型,一般是指进程的域类型。
Target type(s):需要被访问的资源对象类型。
Object class(es):指定权限被允许访问的对象类型。
Permission(s):source访问指定对象类别的目标类型所需要的权限。

策略语句编写案例

前面是对策略语法的一个整体描述,下面看一个具体的例子:
   allow user_t bin_t:file execute;
这个语句是允许user_t进程类型执行bin_t类型的文件对象。

在策略语句中,我们还可以使用属性来简化策略:
   allow domain exec_type:file execute;
domain是一个属性,在给进程定义type的时候,一般都会关联这个属性。关联domain的type都有执行exec_type类型文件的se权限。

在策略语句中使用”-“符号去否定某个类型或者权限,如下:
   allow domain {exec_type -sbin_t}:file execute;
上面语句是允许domain去执行所有除了sbin_t之外的exec_type类型的文件。

在策略语句中使用”*“符号代表对象类别拥有的所有权限,如下:
   allow user_t bin_t:{file dir} *;
上面语句是允许user_t所代表的进程拥有bin_t类型的文件或目录的所有权限。

在策略语句中使用”~“符号代表除指定的权限之外的所有权限,如下:
   allow user_t bin_t:file ~{write setattr ioctl};
上面语句是user_t所标识的进程对bin_t类型的文件对象拥有除write、setattr和ioctl之外的所有权限,当然这些权限是指文件所包含的权限组。

在策略语句中还有一个保留的关键字”self“,它一般是指代和源类型一样的目标类型,如下:
   allow user_t user_t:process signal;
   allow user_t self:process signal;
上面两条语句是等效的。

目标对象所对应的类别及权限

Class Permission
file ioctl read write create getattr setattr lock relabelfrom relabelto appendunlink link rename
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值