Android 11 init进程对Selinux的处理一文中,我们知道,在init进程对Selinux的处理过程中,会将precompiled_sepolicy或者动态编译相关目录下的cil文件得到的compiled_sepolicy写入给内核。那么precompiled_sepolicy文件和cil文件是从哪里来的呢?

Selinux的编译逻辑基本都是在system\sepolicy\Android.mk文件中

首先关注Android.mk中的几个宏

PLAT_PUBLIC_POLICY := system/sepolicy/public
PLAT_PRIVATE_POLICY := system/sepolicy/private
PLAT_VENDOR_POLICY := system/sepolicy/vendor
SYSTEM_EXT_PUBLIC_POLICY := $(BOARD_PLAT_PUBLIC_SEPOLICY_DIR)
SYSTEM_EXT_PRIVATE_POLICY := $(BOARD_PLAT_PRIVATE_SEPOLICY_DIR)
PRODUCT_PUBLIC_POLICY := $(PRODUCT_PUBLIC_SEPOLICY_DIRS)
PRODUCT_PRIVATE_POLICY := $(PRODUCT_PRIVATE_SEPOLICY_DIRS)
BOARD_SEPOLICY_DIRS  

其中BOARD_SEPOLICY_DIRS 可以由厂商自定义路径,这样厂商自己的文件也会加到Selinux的编译系统中。比如

BOARD_SEPOLICY_DIRS ?= \
    device/rockchip/common/sepolicy/vendor

precompiled_sepolicy的生成过程

#################################
include $(CLEAR_VARS)

LOCAL_MODULE := precompiled_sepolicy
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_TAGS := optional
LOCAL_PROPRIETARY_MODULE := true

ifeq ($(BOARD_USES_ODMIMAGE),true)
LOCAL_MODULE_PATH := $(TARGET_OUT_ODM)/etc/selinux
else
LOCAL_MODULE_PATH := $(TARGET_OUT_VENDOR)/etc/selinux
endif

如果有odm分区,目标文件precompiled_sepolicy就放在odm/etc/selinux目录下,否则就放在vendor/etc/selinux目录。

$(LOCAL_BUILT_MODULE): PRIVATE_CIL_FILES := $(all_cil_files)
$(LOCAL_BUILT_MODULE): PRIVATE_NEVERALLOW_ARG := $(NEVERALLOW_ARG)
$(LOCAL_BUILT_MODULE): $(HOST_OUT_EXECUTABLES)/secilc $(all_cil_files) $(built_sepolicy_neverallows)
	$(hide) $(HOST_OUT_EXECUTABLES)/secilc -m -M true -G -c $(POLICYVERS) $(PRIVATE_NEVERALLOW_ARG) \
		$(PRIVATE_CIL_FILES) -o $@ -f /dev/null

通过secilc,将cil文件编译成目标文件precompiled_sepolicy,其中cil文件包含

all_cil_files := \
    $(built_plat_cil) \
    $(built_plat_mapping_cil) \
    $(built_pub_vers_cil) \
    $(built_vendor_cil)

ifdef HAS_SYSTEM_EXT_SEPOLICY
all_cil_files += $(built_system_ext_cil)
endif

ifdef HAS_SYSTEM_EXT_PUBLIC_SEPOLICY
all_cil_files += $(built_system_ext_mapping_cil)
endif

ifdef HAS_PRODUCT_SEPOLICY
all_cil_files += $(built_product_cil)
endif

ifdef HAS_PRODUCT_PUBLIC_SEPOLICY
all_cil_files += $(built_product_mapping_cil)
endif

ifdef BOARD_ODM_SEPOLICY_DIRS
all_cil_files += $(built_odm_cil)
endif

再来看一下cil文件的生成过程,以built_plat_cil 为例,其它的都类似

built_plat_cil
built_plat_cil是在生成plat_sepolicy.cil的时候赋值的

include $(CLEAR_VARS)

LOCAL_MODULE := plat_sepolicy.cil

//省略
built_plat_cil := $(LOCAL_BUILT_MODULE)

plat_sepolicy.cil 会放在system/etc/selinux目录下

include $(CLEAR_VARS)

LOCAL_MODULE := plat_sepolicy.cil
LOCAL_MODULE_CLASS := ETC
LOCAL_MODULE_TAGS := optional
LOCAL_MODULE_PATH := $(TARGET_OUT)/etc/selinux

收集 PLAT_PRIVATE_POLICY和 PLAT_PUBLIC_POLICY 目录下的 文件,通过transform-policy-to-conf 进行宏展开,得到plat_policy.conf文件。其中PLAT_PRIVATE_POLICY和PLAT_PUBLIC_POLICY 对应的目录,参考前面提到的Android.mk中的宏

policy_files := $(call build_policy, $(sepolicy_build_files), \
  $(PLAT_PUBLIC_POLICY) $(PLAT_PRIVATE_POLICY))
plat_policy.conf := $(intermediates)/plat_policy.conf
$(plat_policy.conf): PRIVATE_MLS_SENS := $(MLS_SENS)
$(plat_policy.conf): PRIVATE_MLS_CATS := $(MLS_CATS)
$(plat_policy.conf): PRIVATE_TARGET_BUILD_VARIANT := $(TARGET_BUILD_VARIANT)
$(plat_policy.conf): PRIVATE_TGT_ARCH := $(my_target_arch)
$(plat_policy.conf): PRIVATE_TGT_WITH_ASAN := $(with_asan)
$(plat_policy.conf): PRIVATE_TGT_WITH_NATIVE_COVERAGE := $(with_native_coverage)
$(plat_policy.conf): PRIVATE_ADDITIONAL_M4DEFS := $(LOCAL_ADDITIONAL_M4DEFS)
$(plat_policy.conf): PRIVATE_SEPOLICY_SPLIT := $(PRODUCT_SEPOLICY_SPLIT)
$(plat_policy.conf): PRIVATE_COMPATIBLE_PROPERTY := $(PRODUCT_COMPATIBLE_PROPERTY)
$(plat_policy.conf): PRIVATE_TREBLE_SYSPROP_NEVERALLOW := $(treble_sysprop_neverallow)
$(plat_policy.conf): PRIVATE_POLICY_FILES := $(policy_files)
$(plat_policy.conf): $(policy_files) $(M4)
	$(transform-policy-to-conf)
	$(hide) sed '/^\s*dontaudit.*;/d' $@ | sed '/^\s*dontaudit/,/;/d' > $@.dontaudit

sepolicy_build_files 包含的文件有:

sepolicy_build_files := security_classes \
                        initial_sids \
                        access_vectors \
                        global_macros \
                        neverallow_macros \
                        mls_macros \
                        mls_decl \
                        mls \
                        policy_capabilities \
                        te_macros \
                        attributes \
                        ioctl_defines \
                        ioctl_macros \
                        *.te \
                        roles_decl \
                        roles \
                        users \
                        initial_sid_contexts \
                        fs_use \
                        genfs_contexts \
                        port_contexts

收集到的文件,宏展开得到plat_policy.conf后,通过checkpolicy生成plat_sepolicy.cil目标文件

$(LOCAL_BUILT_MODULE): PRIVATE_ADDITIONAL_CIL_FILES := \
  $(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY))
$(LOCAL_BUILT_MODULE): PRIVATE_NEVERALLOW_ARG := $(NEVERALLOW_ARG)
$(LOCAL_BUILT_MODULE): $(plat_policy.conf) $(HOST_OUT_EXECUTABLES)/checkpolicy \
  $(HOST_OUT_EXECUTABLES)/secilc \
  $(call build_policy, $(sepolicy_build_cil_workaround_files), $(PLAT_PRIVATE_POLICY)) \
  $(built_sepolicy_neverallows)
	@mkdir -p $(dir $@)
	$(hide) $(CHECKPOLICY_ASAN_OPTIONS) $(HOST_OUT_EXECUTABLES)/checkpolicy -M -C -c \
		$(POLICYVERS) -o $@.tmp $<
	$(hide) cat $(PRIVATE_ADDITIONAL_CIL_FILES) >> $@.tmp
	$(hide) $(HOST_OUT_EXECUTABLES)/secilc -m -M true -G -c $(POLICYVERS) $(PRIVATE_NEVERALLOW_ARG) $@.tmp -o /dev/null -f /dev/null
	$(hide) mv $@.tmp $@

总结编译的整体逻辑

在这里插入图片描述

1,查找相关目录下的te文件,进行宏展开,转化成policy.conf文件。
2,将 policy.conf 文件,通过checkpolicy,编译成中间文件*.cil
3,通过secilc工具,编译成二进制文件precompiled_sepolicy

最终根目录系统结构为

console:/ # ls -al system/etc/selinux/
total 1764
drwxr-xr-x  3 root root    4096 2024-01-17 18:00 .
drwxr-xr-x 14 root root    4096 2024-01-24 16:47 ..
drwxr-xr-x  2 root root    4096 2024-01-17 17:59 mapping
-rw-r--r--  1 root root   41949 2024-01-17 17:59 plat_file_contexts
-rw-r--r--  1 root root    8752 2024-01-17 17:59 plat_hwservice_contexts
-rw-r--r--  1 root root    7371 2024-01-17 17:59 plat_mac_permissions.xml
-rw-r--r--  1 root root   47325 2024-01-17 17:59 plat_property_contexts
-rw-r--r--  1 root root    2898 2024-01-17 18:00 plat_seapp_contexts
-rw-r--r--  1 root root 1646622 2024-01-17 17:59 plat_sepolicy.cil
-rw-r--r--  1 root root      65 2024-01-17 17:59 plat_sepolicy_and_mapping.sha256
-rw-r--r--  1 root root   18876 2024-01-17 17:59 plat_service_contexts
console:/ # ls -al vendor/etc/selinux/
total 1184
drwxr-xr-x  2 root shell   4096 2024-01-17 18:00 .
drwxr-xr-x 13 root shell   4096 2024-01-24 16:46 ..
-rw-r--r--  1 root root  926046 2024-01-17 18:00 plat_pub_versioned.cil
-rw-r--r--  1 root root       5 2024-01-17 17:59 plat_sepolicy_vers.txt
-rw-r--r--  1 root root    1511 2024-01-17 17:59 selinux_denial_metadata
-rw-r--r--  1 root root   21807 2024-01-17 17:59 vendor_file_contexts
-rw-r--r--  1 root root     280 2024-01-17 17:59 vendor_hwservice_contexts
-rw-r--r--  1 root root    6751 2024-01-17 17:59 vendor_mac_permissions.xml
-rw-r--r--  1 root root    3900 2024-01-17 17:59 vendor_property_contexts
-rw-r--r--  1 root root       0 2024-01-17 18:00 vendor_seapp_contexts
-rw-r--r--  1 root root  216664 2024-01-17 18:00 vendor_sepolicy.cil
-rw-r--r--  1 root root     214 2024-01-17 17:59 vendor_service_contexts
-rw-r--r--  1 root root     130 2024-01-17 18:00 vndservice_contexts
console:/ # ls -al odm/etc/selinux/
total 556
drwxr-xr-x 2 root root   4096 2024-01-17 18:00 .
drwxr-xr-x 3 root root   4096 2024-01-17 18:00 ..
-rw-r--r-- 1 root root 545403 2024-01-17 18:00 precompiled_sepolicy
-rw-r--r-- 1 root root     65 2024-01-17 18:00 precompiled_sepolicy.plat_sepolicy_and_mapping.sha256
-rw-r--r-- 1 root root     65 2024-01-17 18:00 precompiled_sepolicy.product_sepolicy_and_mapping.sha256
-rw-r--r-- 1 root root     65 2024-01-17 18:00 precompiled_sepolicy.system_ext_sepolicy_and_mapping.sha256

上面只是简要的分析了一下编译过程,具体的还需要分析Android.mk文件。

参考Android.mk文件,我们如果更改了Selinux某些内容,可以执行make selinux_policy或者mmma system/sepolicy 进行模块编译就行了,不用整编系统,然后替换system/vendor 下相关的文件即可。

Logo

开放原子开发者工作坊旨在鼓励更多人参与开源活动,与志同道合的开发者们相互交流开发经验、分享开发心得、获取前沿技术趋势。工作坊有多种形式的开发者活动,如meetup、训练营等,主打技术交流,干货满满,真诚地邀请各位开发者共同参与!

更多推荐