商务服务
Android - 深入浅出理解SeLinux
2024-11-01 00:22

官方文档

Android - 深入浅出理解SeLinux

https://source.android.com/docs/security/features/selinux

https://source.android.com/docs/security/features/selinux/images/SELinux_Treble.pdf

Your visual how-to guide for SELinux policy enforcement | Opensource.com

SeLinux(Security-Enhanced Linux)是一个标签系统(labeling system)。每个进程都有一个label(称为process label,每个文件系统所涵盖的文件/目录、网络端口、设备等对象也有一个lable(称为Object label)。SeLinux通过编写规则来控制一个process label对一个Object label的访问,这个规则称之为策略(Policy)。SeLinux的这种安全机制称为Mandatory Access Control (MAC),是在内核层实现的。

在标准的Linux上,也就是未实施SeLinux的Linux上,传统的访问控制是通过owner/group + permission flags(比如rwx)实现的,称之为Discretionary Access Control (DAC).

SeLinux和传统的DAC不是替代的关系,而是并行的关系。两者同时在起作用。之所以出现SeLinux,是因为传统DAC的安全机制过于粗粝,而Selinux提供了更为细致和安全的访问控制。简言之,传统DAC机制下,一旦你获得了root权限,将无所不能,但在SeLinux的机制下,即使获得了root权限,也仍然需要遵循已经设置好的访问策略,只有指定的进程才可以访问指定的文件。

SeLinux有两种运行模式

  • Permissive mode:当访问并未授权时,不会阻止访问,但会打印log
  • Enforcing mode:当访问未被授权时,会阻止访问,并且会打印log

log将出现在dmesg和logcat。

除了可以对整体进行模式设置,也可以针对某个进程单独设置某个模式,除此之外的进程使用全局模式。

SeLinux在Android 4~7和Android 8以后采用了不同的设计

Android 4~7上,SeLinux的策略是作为一个整体来编译和更新的

Android 8及以后,SeLinux采用了模块化、动态化设计,Platform(可以理解为AOSP的部分)、Non-Platform(vendor、odm、oem的部分,这里总体称为vendor部分)的SeLinux策略分别独立编译、升级。

附一张Android设备的架构图

编译后会生成对应的img文件

● system.img. Contains mainly Android framework.

● boot.img. (kernel/ramdisk) Contains Linux kernel + Android patches.

● vendor.img. Contains SoC-specific code and configurations.

● odm.img. Contains device-specific code and configurations.

● oem.img. Contains OEM/carrier-related configurations and customizations.

● bootloader. Brings up the kernel (vendor-proprietary).

● radio. Modem (proprietary).

Android 8以后,SeLinux的策略文件可以伴随相应的img独立编译或者OTA。

什么是标签(Label?怎么基于Label对访问进行控制

先抛开Label这个概念不说。所谓SeLinux里的访问控制,就是判定一个Source有没有权限去访问Target。这里的Source一般就是进程,Target最长见的就是文件系统(比如文件、目录、socket、设备等等,当然还有其他类型的Target。换句话说,SeLinux的机制就是通过读取一个“规则”,来控制一个进程有没有权限去访问一个文件(或其他类型)。

上面说的“规则”,在SeLinux里的术语叫做Policy(策略)或叫Access Vector Rule。是可以由AOSP和厂商、供应商来编写的。

上面的Source,还叫做Subject(主体

上面的Target,还叫做Object(对象或客体

Label、Source、Target、Subject、Object,这些都不重要, 在实际语法中并没有相关关键词,只要各种资料里出现这些词的时候知道其所指就可以。

策略规则的语法为

  • Source - The type (or attribute) of the subject of the rule. Who is requesting the access?(是谁在请求访问一个资源
  • Target - The type (or attribute) of the object. To what is the access requested?(被访问的对象
  • Class - The kind of object (e.g. file, socket) being accessed.(被访问者的类型
  • Permissions - The operation (or set of operations) (e.g. read, write) being performed.(对Target具体要做什么操作?比如对被访问者是文件来说,是要读、写它还是其他操作

具体例子如下

这个例子是说,允许sample_app这个进程去访问app_data_file(它是一个file类型,也就是文件,允许的操作是read和write。

而其实这里的sample_app并不是一个真正的具体的进程名,而是在系统编译阶段就定义好的一个标签(Label,一些真正的进程被映射到sample_app这个标签上,那么在执行上面规则的时候,其实生效的、有权限访问app_data_file的是所有映射了sample_app标签的那些进程。同样的,app_data_file也不是一个具体的文件名。它也是一个提前声明了的标签,一些真正的文件被映射到这个标签上,sample_app有权访问的是所映射的这些文件。

从这里看出来,有别于传统DAC的Owner、Group、Permissions 的控制方式,所谓的“基于标签系统”的SeLinux,就是这种通过声明标签的方式来表述访问规则的。

标签只是一种概念性的东西,具体体现在策略文件里,则是抽象成了Type、Attribute、Class、Permissions这些具体关键字。

以下面这个规则举例

Rule Name

上面规则示例中,allow就是Rule Name的一种。SeLinux有多种RuleName

  • allow:表示允许Source对Target执行许可的操作
  • neverallow:表示不允许Source对Target执行制定的操作
  • auditallow:表示允许操作并记录访问决策信息
  • dontaudit:表示不记录违反规则的决策信息,切违反规则不影响运行。

其中allow是用的最多的。

Type

上面的示例中,sample_app、app_data_file都是一个Type。简单理解就是将一个或几个进程声明为Type A, 将一个或多个文件声明为Type B。那么在控制这个进程有没有权限访问这个文件的时候,只用A和B来表示就可以了。

这样做有什么好处?“一类进程”总比具体的“一个进程”要灵活的多。把多个进程声明为同一个Type,那么在写规则的时候只要描述这个Type,那么这个Type对应的所有进程都会生效。文件或其他对象也是同样的。

也就是说,在规则中描述Source能不能访问Target,是通过Type来表述的。

Type是厂商或供应商可以自定义的

将多个Type归为一组,就是一个Attribute。

通俗的说,把一些进程声明为Type,但是多个Type有某种共通的特性,就可以把这些Type声明为同一个Attribute。在描述规则的时候,可以将Source或者Target指定为一个Attribute而不是Type,这样所有属于这个Attribute的Type都生效。

AOSP本身内置了一些Attribute,而这些Attribute很多都是约定俗称的固定含义。比如

domain

所有进程的type必须归属于domain。domain因此成了进程type的常见表述。

file_type

所有文件type都归属于file_type

...

AOSP内置的Attribute见

platform/system/sepolicy/public/attributes

platform/system/sepolicy/private/attributes

platform/system/sepolicy/prebuilts/api/[version]/public/attributes

platform/system/sepolicy/prebuilts/api/[version]/private/attributes

Class

上面示例中,“:file”就是一个Class。简单说就是将某些被访问对象归为一种Class,比如说被访问的是文件,Class一般就是file,如果是目录,Class就是dir,如果是socket,Class就是socket等等。Class是AOSP内定义好的,一般不需要自定义

具体有那些Class,可见源码platform/system/sepolicy/private/security_classes

Class是用来做什么的?其实是与Permissions相关的。

Permissions

即示例中的 { read write }。表示具体可以做什么操作。不同的Class有不同的Permissions集合。罗列一些Class对应Permission(非完整

Class

Permission

file

ioctl read write create getattr setattr lock relabelfrom relabelto append unlink link rename execute swapon quotaon mounton

directory

add_name remove_name reparent search rmdir open audit_access execmod

socket

ioctl read write create getattr setattr lock relabelfrom relabelto append bind connect listen accept getopt setopt shutdown recvfrom sendto recv_msg send_msg name_bind

filesystem

mount remount unmount getattr relabelfrom relabelto transition associate quotamod quotaget

process

fork transition sigchld sigkill sigstop signull signal ptrace getsched setsched getsession getpgid setpgid getcap setcap share getattr setexec setfscreate noatsecure siginh setrlimit rlimitinh dyntransition setcurrent execmem execstack execheap setkeycreate setsockcreate

security

compute_av compute_create compute_member check_context load_policy compute_relabel compute_user setenforce setbool setsecparam setcheckreqprot read_policy

capability

chown dac_override dac_read_search fowner fsetid kill setgid setuid setpcap linux_immutable net_bind_service net_broadcast net_admin net_raw ipc_lock ipc_owner sys_module sys_rawio sys_chroot sys_ptrace sys_pacct sys_admin sys_boot sys_nice sys_resource sys_time sys_tty_config mknod lease audit_write audit_control setfcap

MORE

AND MORE

可以从对应的Class中选取任意个Permission

Class与Perimssion的完整映射具体见源码kernel/arm64/security/selinux/include/classmap.h

示例

以控制狗是否有权吃猫粮狗粮为例。

有一个狗叫小黄, 一种狗粮叫“狗粮A”。

现在声明一个Type叫dog,一个Type叫dog_chow,系统本身内置了Class叫food,food对应的permissions里包含了eat这个权限。

随后将小黄映射到dog这个type,将狗粮A映射到dog_chow这个type

这样,在添加了这样一条规则后,小黄就有权限去吃狗粮A了

此时如果还有一只狗小白,那么可以将小白映射到dog这个type,这样小白也可以有权限吃狗粮A。

上面所说的“映射”,即将一个进程关联到一个Type,或者将一个文件关联到一个Type,是通过context来完成的。

进程Context(seapp_contexts

一个进程的Context条目可能如下

user=_app代表这是一个常规的app

isPrivApp=true代表这是一个预置app

name=com.android.vzwomatrigger 指定了进程名

domain=vzwomatrigger_app 将进程名关联到一个type

type=privapp_data_file 这是一个文件type,指定了app的data directory目录所属的type

levelFrom=all MLS/MCS的level相关

AOSP内置进程Context见platform/system/sepolicy/private/seapp_contexts

供应商或厂商要定义自己的seapp_context,将在/vender下或<root>/device/manufacturer/device-name/sepolicy下相应目录添加

文件Context

一个文件的Context可能这样

/system/bin/bcc 指的是具体文件

u:object_r:rs_exec:s0是一个security context。其中的rs_exec为type。这样文件和type就进行了关联

Security Context

其格式为

在Android中

user是固定的,永远为u

role是固定的,访问者(称subject或source)永远为r;被访问者(称object或target)永远为object_r。一般情况下,进程一方就是subject,文件一方就是object,所以一般进程的role为r,文件的role为object_r。

type为与文件关联的type

sensitivity是固定的,永远为s0

categories是Multi-Level Security (MLS) 协议,用来隔离一个app的data,防止被另一个app访问,或者隔离不同用户间对同一个app data的访问。

AOSP内置的文件Context见platform/system/sepolicy/private/file_contexts

seinfo

seapp_context除了可以一个具体应用映射一个domain也可以seinf映射domainmac_permissions.xml定义seinfo根据app所属signature分配一个seinfo

比如

platform/system/sepolicy/private/mac_permissions.xml

也就是所有拥有PLATFORM signatureapp拥有platform这个seinfoseapp_context可以如下配置

所有拥有platform签名并且配置具体contextapp将遵循其seinfo platform规则

untrusted_app

配置seinfo配置seapp_contextapp默认untrusted_app各级seapp_context也有untrusted_app权限配置

查看当前Context

要看进程的Context,使用ps -Z

查看文件的Context,使用


	

参见https://android.googlesource.com/platform/system/sepolicy/

之前提到Android架构中大致包含AOSP厂商Vendor部分Android 8以上系统AOSP厂商供应商部分是独立配置方便OTA更新

这种架构SeLinux的Policy文件体系包含以下目录

system/sepolicy/public部分AOSP公开vender使用作为基础api比如声明domainattribute就在下面platform/system/sepolicy/public/attributes这部分Policy需要兼容处理因为Vender引用这里policy如果OTA单独升级AOSP需要向后兼容处理。详见https://source.android.com/docs/security/features/selinux/compatibility

system/sepolicy/privateAOSP内部使用system image内部policyvender不应该感知到这部分policy

system/sepolicy/vendorvender部分policy

device/manufacturer/device-name/sepolicy特定设备policy比如三星设备device/samsung/tuna/sepolicy

BoardConfig.mk makefile

AOSPSeLinux Policy文件一般不需要更改少量更改厂商主要修改定制Policy/device/manufacturer/device-name//device/manufacturer/device-name/BoardConfig.mk用于指定Policy文件具体路径通过BOARD_VENDOR_SEPOLICY_DIRS比如

device/samsung/tuna/BoardConfig.mk

system_ext  product分区

Android 11及以上系统system_ext  product分区独立单独policy并且区分publicprivatepublic部分同样vender引用system_extproduct版本兼容处理partner自己负责AOSP不负责

SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS:指定system_ext的public的目录安装system_ext分区

SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS指定system_ext的private目录system_ext内部使用安装system_ext分区

PRODUCT_PUBLIC_SEPOLICY_DIRS指定product分区public目录安装product分区

PRODUCT_PRIVATE_SEPOLICY_DIRS指定product的private目录安装product分区

SeLinux策略配置相关文件统称Policy文件

Policy文件一般包含

TE文件

就是一堆.te文件TE定义Type访问规则进程文件Type定义、访问规则定制就只TE完成一般每个进程一个独立te文件所有文件te统一声明一个file.te文件详见3.3

Context files

file_contexts前面说过file_contexts里面定义文件context用于文件目录文件type关联起来

genfs_contexts用于文件系统(比如/proc和vfattype关联起来

property_contexts用于Android系统propertiestype关联起来

service_contexts用于service进程type关联

seapp_contexts用于apptype关联

mac_permissions.xml根据appsignature包名app分配一个seinfoseinfo用于app没有明确关联一个type归属一个默认type

keystore2_key_contexts Keystore 2.0 namespaces分配一个label

用来声明Attribute

security_classes

用来声明Class

所有的规则配置,或称Policy,都写在.te文件中。编写完TE文件后,将TE文件放在对应目录下,Android系统编译后.te文件将被编译成.cil文件。在init进程启动阶段,会将.cil文件汇总统一编译成一个命名为policy的文件。cil文件是可读的,policy文件是二进制的。在系统运行时最终加载使用的是policy文件。

policy文件一般在/sys/fs/selinux/policy

一般一个进程单独声明一个TE文件。比如一个dhcp进程单独有一个te文件叫dhcp.te。而文件的te统一整合在file.te(比如platform/system/sepolicy/public/file.te)中。

针对Platform(AOSP的部分)、Non-Platform(厂商、供应商的部分,TE会有不同的放置目录。

下面是TE文件的一个例子

platform/system/sepolicy/public/dhcp.te

TE文件语法解析

type dhcp, domain; -- 声明一个type名为dhcp,其继承domain这个Attribute,也就是说在声明时便继承了domain所拥有的权限。domain属性是进程专用的,很显然这是一个进程的te文件。

permissive dhcp; -- 将dhcp标识为permissive模式。之前说到,SeLinux开启模式可以全局设置,也可以针对进程单独设置。这里是单独设置该进程的模式。

type dhcp_exec, exec_type, file_type; -- 声明一个type名为dhcp_exec, 从属于exec_type和file_type两个Attribute。也就是说同时继承两个Attribute所代表的文件。exec_type用于代表可执行文件,也就是进程的可执行文件入口;file_type代表通用文件。从这里我们知道dhcp_exec代表dhcp可执行文件的入口。

init_daemon_domain(dhcp) -- 这是一个宏,代表这是一个从init启动的进程并且可以init通信。宏的源码见platform/system/sepolicy/public/te_macros

net_domain -- 也是一个宏,可以进行通用网络操作比如读写TCP操作socket

allow dhcp self:capability { setgid setuid net_admin net_raw net_bind_service}; -- 这个就是具体规则描述dhcpsource selftargetcapability一个Class可以操作这句允许dhcp这个进程自己setgid操作self关键用来表示source可以自己什么操作

除了上面例子出现关键字有时我们看到typeattribute这个关键字代表之前已经声明Type关联一个之前声明Attribute

更多语法TypeStatements - SELinux Wiki

Android 8以上编译过程/system  /vendorpolicy合并这个逻辑体现/platform/system/sepolicy/Android.mk

具体policy位置

Location

Contains

system/sepolicy/public

The platform's sepolicy API

system/sepolicy/private

Platform implementation details (vendors can ignore)

system/sepolicy/vendor

Policy and context files that vendors can use (vendors can ignore if desired)

BOARD_SEPOLICY_DIRS

Vendor sepolicy

BOARD_ODM_SEPOLICY_DIRS (Android 9 and higher)

Odm sepolicy

SYSTEM_EXT_PUBLIC_SEPOLICY_DIRS (Android 11 and higher)

System_ext's sepolicy API

SYSTEM_EXT_PRIVATE_SEPOLICY_DIRS (Android 11 and higher)

System_ext implementation details (vendors can ignore)

PRODUCT_PUBLIC_SEPOLICY_DIRS (Android 11 and higher)

Product's sepolicy API

PRODUCT_PRIVATE_SEPOLICY_DIRS (Android 11 and higher)

Product implementation details (vendors can ignore)

编译过程

  1. Policy转化成CIL Common Intermediate Language )文件包括
    1. system + system_ext + productpublic部分policy
    2. 合并private + public policy
    3. 合并public + vendor and BOARD_SEPOLICY_DIRS policy
  2. public部分policy进行整理成对应版本policy作为vendor policy一部分然后publicpolicy合并public + vendor and BOARD_SEPOLICY_DIRS policy告知其哪部分可以连接到platformattribute
  3. 创建一个mapping文件连接platformvendor部分
  4. 合并所有policy文件整合mappingplatformvenderpolicy最终输出一个二进制的名为policy文件一般这个文件的位置在/sys/fs/sepolicy/policy。这个policy最终会被kernel加载。这个工作init进程初始化进行也就是运行时进行

SeLinux正式开启之前init进程收集所有cil文件将其编译policy这个过程需要花费1-2时间为了更快完成此过程会将CIL编一阶段预编译放在/vendor/etc/selinux/precompiled_sepolicy/odm/etc/selinux/precompiled_sepolicy并且附有sha256 摘要运行时检查sha256是否变化如果没有变化直接使用预编译文件

编译kernel指定CONFIG_SECURITY_SELINUX=y

比如kernel/arm64/arch/arm64/configs/defconfig添加配置

kernel/arm64/include/linux/selinux.h配置进行判断

厂商目录BoardConfig.mk(比/device/google/trout/trout_arm64/BoardConfig.mk)添加如下配置改变SeLinux模式

上面两个配置只用开发阶段正式版本需要移除否则无法通过CTS正式版本SeLinux强制enforcing模式

非正式的修改方法

ALLOW_PERMISSIVE_SELINUX宏定义了是否启用permissivve模式。

core/init/Android.bp中有对该宏设置

实际的生效位置

厂商供应添加一些进程访问行为策略之后需要确认是否符合SeLinux规则

如果任何访问限制出现打印log

精简下log,只需avc:后面即可

字段含义

{ find }组织行为

scontext(可以理解source context缩写行为执行context

tcontext(可以理解target context的缩写访问context

tclass访问class详见本文之前解释

 使用auditallow生成TE

ubuntu中,通过apt-get audit2allow安装audit2allow。

获取policy文件

/sys/fs/selinux/policy

将上面的avc log保存test.avc文件然后执行

    以上就是本篇文章【Android - 深入浅出理解SeLinux】的全部内容了,欢迎阅览 ! 文章地址:http://dfvalve.xrbh.cn/news/7347.html 
     资讯      企业新闻      行情      企业黄页      同类资讯      首页      网站地图      返回首页 迅博思语资讯移动站 http://keant.xrbh.cn/ , 查看更多   
最新新闻
云南网络营销软件哪个好?权威推荐助您快速选择
在数字化时代,网络营销软件成为了许多企业实现营销目标的重要工具。然而,市面上网络营销软件琳琅满目,选择一个适合自己的并不
宫崎骏的时代结束了
在《你想活出怎样的人生》之前,宫崎骏一直是著名的退休诈骗犯。七次退休又七次复出,年过八旬,创作欲还是旺盛到令人害怕。然而
个人大数据信用查询平台哪个更准确一些?蘑菇画像个人大数据信用报告查询平台更好用
个人大数据信用查询平台哪个更准确一些?蘑菇画像个人大数据信用报告查询平台更好用,个人大数据信用查询平台市面上还是比较多的
小红书关键词热度查询!国风大潮下,品牌怎么玩出花样、玩出水平?
国风,是当下年轻人钟爱的潮流。汉服穿搭、文物手办、国潮仿妆……频频出圈。“民族的就是世界的”,国风的影响力可谓深远,一说
app推广接单发布平台哪个好?怎么领取任务赚钱?
最近几年,随着互联网的快速发展,利用网络兼职的赚钱方式也呈现越来越火,非常受大众欢迎的趋势。而且其种类也非常多:微商、社
【可打印】文学常识常考100题汇总,初中生练一练!(部编版初中语文)
关注本公众号,私信发送数字:2493,领取电子打印版文学常识1、成语“万事俱备,只欠东风”是根据《三国演义》________ (战役)
“迎旅发大会 游美丽望城”望城首届文旅短视频大赛,最高3万奖励等你来拿!
湘江水浩浩奔腾,流淌沧桑巨变。铜官窑静穆肃然,在这里诉说着望城的厚重历史,流传着“君生我未生,我生君已老”凄美爱情故事;落日
mysql导入大txt文件怎么打开_mysql怎么导入txt文件?
有时候我们在使用mysql数据库的时候,想导入txt文本文档,要怎么操作呢?下面本篇文章就来给大家介绍一下方法
寸头抖音短视频教程_人开始衰老的迹象是什么
岁月不饶人,我才50出头,可是许多衰老迹象已经越来越明显,惹得中医闺蜜笑话这样的我。1、觉得右后背和肩膀疼,出现“五十肩”
什么是网站页脚:以及最佳页脚设计示例
主体内容外,网站还包括页眉和页脚,用于帮助访问者的特定目的。由于我们认为网站页脚设计同样重要,我们整理了10个最佳免费网站
本企业新闻

点击拨打: