selinux label的初始化过程

selinux的架构中主要分为:subject和object。subject可以认为是进程,object可以认为是文件(linux中一切皆文件)。在系统代码中,通过撰写sepolicy规则文件(.te),在编译阶段预先为每个关键(subject)进程设置了security context,也为object(文件)设置了security context。那么这些文件是如何生效的呢?
第一步:静态sepolicy文件之间不存在冲突,能正常编译通过;
第二步:编译阶段把sepolicy文件编译成binary文件,并传入到内核;
第三步:内核在启动后以传入的sepolicy文件为原材料,构建起selinux在kernel层的工作框架。

默认第一步已经完成的情况下,重点讨论第二步和第三步的工作流程。
sepolicy文件编译到rom里面后,会保存在rom的某个位置,然后在启动阶段把这个文件传入到kernel中。为了完成这一步需要做以下几个步骤:
1)找到selinuxfs挂载点,一般在/sys/fs/selinux,然后把这个文件写入到该目录下的load文件中;
2)然后导入selinux context文件,加载其中定义的object(文件)的security context;

system/core/init/init.cpp

545int main(int argc, char** argv) {
546    ...
564    bool is_first_stage = (getenv("INIT_SECOND_STAGE") == nullptr);
565
566    if (is_first_stage) {
567    ...
586        mount("sysfs", "/sys", "sysfs", 0, NULL);
587        mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL);
588        ...
618        // Enable seccomp if global boot option was passed (otherwise it is enabled in zygote).
619        global_seccomp();
620
621        // Set up SELinux, loading the SELinux policy.
622        SelinuxSetupKernelLogging();
623        SelinuxInitialize();
624
625        // We're in the kernel domain, so re-exec init to transition to the init domain now
626        // that the SELinux policy has been loaded.
627        if (selinux_android_restorecon("/init", 0) == -1) {
628            PLOG(FATAL) << "restorecon failed of /init failed";
629        }
630
631        setenv("INIT_SECOND_STAGE", "true", 1);
632        ...
644    }
645
646    ...
683    // Now set up SELinux for second stage.
684    SelinuxSetupKernelLogging();
685    SelabelInitialize();
686    SelinuxRestoreContext();
687    ...

其中上述代码中SelinuxInitialize函数完成把规则文件导入到/sys/fs/selinux/dload中,流程如下:
SelinuxInitialize=>LoadPolicy=>LoadSplitPolicy=>FindPrecompiledSplitPolicy=>selinux_android_load_policy_from_fd。代码实现如下:
system/core/init/selinux.cpp

201bool FindPrecompiledSplitPolicy(std::string* file) {
202    file->clear();
203    // If there is an odm partition, precompiled_sepolicy will be in
204    // odm/etc/selinux. Otherwise it will be in vendor/etc/selinux.
205    static constexpr const char vendor_precompiled_sepolicy[] =
206        "/vendor/etc/selinux/precompiled_sepolicy";
207    static constexpr const char odm_precompiled_sepolicy[] =
208        "/odm/etc/selinux/precompiled_sepolicy";
209    if (access(odm_precompiled_sepolicy, R_OK) == 0) {
210        *file = odm_precompiled_sepolicy;
211    } else if (access(vendor_precompiled_sepolicy, R_OK) == 0) {
212        *file = vendor_precompiled_sepolicy;
213    } else {
214        PLOG(INFO) << "No precompiled sepolicy";
215        return false;
216    }
217    std::string actual_plat_id;
218    if (!ReadFirstLine("/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256", &actual_plat_id)) {
219        PLOG(INFO) << "Failed to read "
220                      "/system/etc/selinux/plat_and_mapping_sepolicy.cil.sha256";
221        return false;
222    }
223
224    std::string precompiled_plat_id;
225    std::string precompiled_sha256 = *file + ".plat_and_mapping.sha256";
226    if (!ReadFirstLine(precompiled_sha256.c_str(), &precompiled_plat_id)) {
227        PLOG(INFO) << "Failed to read " << precompiled_sha256;
228        file->clear();
229        return false;
230    }
231    if ((actual_plat_id.empty()) || (actual_plat_id != precompiled_plat_id)) {
232        file->clear();
233        return false;
234    }
235    return true;
236}
...
252bool IsSplitPolicyDevice() {
253    return access(plat_policy_cil_file, R_OK) != -1;
254}
255
256bool LoadSplitPolicy() {
257    // IMPLEMENTATION NOTE: Split policy consists of three CIL files:
258    // * platform -- policy needed due to logic contained in the system image,
259    // * non-platform -- policy needed due to logic contained in the vendor image,
260    // * mapping -- mapping policy which helps preserve forward-compatibility of non-platform policy
261    //   with newer versions of platform policy.
262    //
263    // secilc is invoked to compile the above three policy files into a single monolithic policy
264    // file. This file is then loaded into the kernel.
265
266    // Load precompiled policy from vendor image, if a matching policy is found there. The policy
267    // must match the platform policy on the system image.
268    std::string precompiled_sepolicy_file;
269    if (FindPrecompiledSplitPolicy(&precompiled_sepolicy_file)) {
270        unique_fd fd(open(precompiled_sepolicy_file.c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
271        if (fd != -1) {
272            if (selinux_android_load_policy_from_fd(fd, precompiled_sepolicy_file.c_str()) < 0) {
273                LOG(ERROR) << "Failed to load SELinux policy from " << precompiled_sepolicy_file;
274                return false;
275            }
276            return true;
277        }
278    }
367}
...
378bool LoadPolicy() {
379    return IsSplitPolicyDevice() ? LoadSplitPolicy() : LoadMonolithicPolicy();
380}
...
384void SelinuxInitialize() {
385    Timer t;
386
387    LOG(INFO) << "Loading SELinux policy";
388    if (!LoadPolicy()) {
389        LOG(FATAL) << "Unable to load SELinux policy";
390    }
391    ...
400    if (auto result = WriteFile("/sys/fs/selinux/checkreqprot", "0"); !result) {
401        LOG(FATAL) << "Unable to write to /sys/fs/selinux/checkreqprot: " << result.error();
402    }
403}

然后通过SelabelInitialize()和SelinuxRestoreContext()把系统中的selinux context文件,加载其中定义的object(文件)的security context。
其中SelabelInitialize的函数中完成了两个步骤:
1)首

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
Linux服务器的初始化过程可以分为几个主要步骤。首先,当计算机打开电源后,BIOS会进行开机自检,并按照BIOS中设置的启动设备(通常是硬盘)来启动。接下来,由启动设备上的grub程序开始引导Linux。引导程序成功完成引导任务后,Linux接管了CPU的控制权,开始执行Linux的核心映像代码,即内核引导过程。在内核引导过程中,内核会进行一系列复杂的工作,最后加载init程序,完成内核引导的工作。init进程是系统所有进程的起点,它读取配置文件/etc/inittab,该文件包含了一系列指令,指导系统启动时要执行的操作。\[1\]\[2\] 在初始化过程中,还可以进行一些其他的配置。例如,可以对SELinux进行配置,SELinux是一个提供强大安全防护功能的系统。然而,有时候SELinux可能会与其他软件发生冲突,导致问题排查困难。在这种情况下,可以选择关闭SELinux以解决问题。\[3\] 总结来说,Linux服务器的初始化过程包括BIOS开机自检、引导程序引导Linux内核、内核引导过程、加载init进程和执行配置文件中的指令。在初始化过程中,还可以进行其他配置,如SELinux的配置。 #### 引用[.reference_title] - *1* *2* [Linux简单入门(四)初步进入](https://blog.csdn.net/yy068/article/details/86553327)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] - *3* [Linux服务器初始化工作](https://blog.csdn.net/weixin_43045613/article/details/127040945)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v91^control_2,239^v3^insert_chatgpt"}} ] [.reference_item] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值