配套系列教学视频链接:
说明
系统:Android10.0
设备: FireFly RK3399 (ROC-RK3399-PC-PLUS)
前言
本章节重点介绍在Android源码中, 涉及selinux策略文件所在目录和文件,以及编译规则
一, selinux策略所在目录
system/sepolicy/ | Android核心公共的策略文件,上下文文件 |
external/selinux | 外部 SELinux 项目,用于构建主机环境中编译 SELinux 政策和标签所需的各种工具,如提供libselinux库函数,checkpolicy编译器(policy.conf编译成cil文件),secilc编译器(cil文件编译成二进制) |
BOARD_SEPOLICY_DIRS | 板级/供应商定制或扩展的策略文件 |
system/sepolicy/:Android核心公共的策略文件,上下文文件
tree -L 1 system/sepolicy/
system/sepolicy/
├── Android.bp
├── Android.mk:大部分的编译目标的规则文件,会include当前目录各个mk文件,如file_contexts.mk等
├── apex
├── build : 提供编译脚本, 脚本包含了各种编译命令,如build_cil用于编译cil文件
├── CleanSpec.mk
├── definitions.mk :只定义了transform-policy-to-conf一个函数,将策略文件转成conf文件,生成xx_policy.conf,
本质上是调用m4命令对文件中的宏进行处理。
├── file_contexts.mk:编译目标文件plat_property_context
├── hwservice_contexts.mk
├── mac_permissions.mk
├── policy_version.mk : 指定当前系统API, 如30
├── prebuilts: 提供旧版本的私有和共有策略, 保证系统向下兼容,
diff -Nur system/sepolicy/prebuilts/api/29.0/private/ system/sepolicy/private/ 是一样的。
├── private : 平台私有策略,非平台策略是不能引用和扩展(也可以理解为供应商忽略/不要动)。
├── property_contexts.mk : 编译目标文件plat_property_context以及vendor_property_contexts的规则
在out/target/product/rk3399_roc_pc_plus/obj/ETC/plat_property_contexts_intermediates/plat_property_contexts里面会清楚的标明是由那些文件编译出来的。
├── public: 平台公开策略,非平台策略是可以引用和扩展的。
├── README
├── reqd_mask: 包含了上下文中role,user的定义,里面大部分文件都是一些模板,内容是空的。
├── mls
├── property_contexts
├── reqd_mask.te
├── roles
├── roles_decl
├── ......
└── users
├── seapp_contexts.mk
├── service_contexts.mk
├── tests: 测试脚本
├── tools:提供脚本和命令如checkfc检查上下文文件语法,sepolicy-check命令用于合并主 seapp_contexts 配置和特定设备配置的工具,同时检查配置的有效性
└── vendor: 非平台策略文件,供应商可以使用的政策和上下文文件
external/selinux:外部 SELinux 项目,用于构建主机环境中编译 SELinux 政策和标签所需的各种工具,如提供libselinux库函数,checkpolicy编译器(policy.conf编译成cil文件),secilc编译器(cil文件编译成二进制),getenfore/setenfore命令
tree -L 1 external/selinux/
external/selinux/
├── Android.bp
├── checkpolicy : policy.conf编译成cil文件
├── CleanSpec.mk
├── dbus
├── gui
├── libselinux : 提供libselinux库函数, getenfore/setenfore命令
├── libsemanage
├── libsepol: 提供检查上下文语法的工具和库函数。
├── Makefile
├── mcstrans
├── MODULE_LICENSE_GPL
├── NOTICE
├── OWNERS
├── policycoreutils: 提供load_policy,chcon等命令
├── prebuilts : 提供audit2allow,sediff等命令
├── python
├── README
├── README.android
├── restorecond
├── sandbox
├── scripts
├── secilc : cil文件编译成二进制
└── semodule-utils
BOARD_SEPOLICY_DIRS : 板级/供应商定制或扩展的策略文件,
一般在device/manufacturer/device-name/BoardConfig.mk中指定, 格式为:
BOARD_SEPOLICY_DIRS += device/$SoC/common/sepolicy
BOARD_SEPOLICY_DIRS += device/$SoC/$DEVICE/sepolicy
当然也有BOARD_ODM_SEPOLICY_DIRS和BOARD_ODM_SEPOLICY_DIRS分别指定odm和product分区的策略文件。
rk3399对应的vendor seplicy文件目录为device/rockchip/common/sepolicy,各个产品引用如下
device/rockchip/rk3399/rk3399_roc_pc_plus/rk3399_roc_pc_plus.mk +22
include device/rockchip/common/BoardConfig.mk
# Sepolicy
PRODUCT_SEPOLICY_SPLIT := false
BOARD_SEPOLICY_DIRS ?= \
device/rockchip/common/sepolicy/vendor
BOARD_PLAT_PUBLIC_SEPOLICY_DIR ?= device/rockchip/common/sepolicy/public
BOARD_PLAT_PRIVATE_SEPOLICY_DIR ?= \
device/rockchip/common/sepolicy/private \
device/rockchip/$(TARGET_BOARD_PLATFORM)/sepolicy (实际不存在)
二, Android Selinux总体编译逻辑
Android编译的核心规则都是在system/sepolicy/Android.mk定义,可参考官网:
构建 SELinux 政策 | Android 开源项目 | Android Open Source Project
总体编译步骤如下所说:
# build process for device:
# 1) convert policies to CIL: 将政策转换为 SELinux 通用中间语言 (CIL) 格式
# - private + public platform policy to CIL
# - mapping file to CIL (should already be in CIL form)
# - non-platform public policy to CIL
# - non-platform public + private policy to CIL
# 2) attributize policy:公共政策属性化,并将公共政策作为供应商政策的一部分进行版本控制。
# - run script which takes non-platform public and non-platform combined
# private + public policy and produces attributized and versioned
# non-platform policy
# 3) combine policy files : 合并政策文件
# - combine mapping, platform and non-platform policy.
# - compile output binary policy file
最核心的过程就是:
te策略文件
----transform-policy-to-conf(m4宏处理)---> 宏展开并合并文件,得到policy.conf,
----checkpolicy编译conf文件---------------->得到cil通用中间语言文件
----secilc工具编译cil文件---------------------> 得到目标文件precompiled_sepolicy二进制
谷歌官网构建sepolicy政策文件的图示:
Android.mk中指定的编译源文件:
详细过程请参考大神: Android P SELinux (二) 开机初始化与策略文件编译过程_headwind_的博客-CSDN博客
Android.mk中比较常见的一个规则:
define build_policy
$(foreach type, $(1), $(foreach file, $(addsuffix /$(type), $(2)), $(sort $(wildcard $(file)))))
endef
参数2,表示一个目标目录
参数1, 表示在目标目录下查找的文件名
调用:
$(call build_policy, file_contexts, $(PLAT_PRIVATE_POLICY))
表示从PLAT_PRIVATE_POLICY目录中找出所有的file_contexts文件