通俗易懂地总结 Android 系统启动中 Init 进程的第二阶段初始化过程,重点解析 SELinux 初始化及阶段切换的核心逻辑:
一、从第一阶段到第二阶段:SELinux 初始化的桥梁
在 Init 第一阶段(FirstStageMain)的最后,通过 execv 带参数 selinux_setup 重新执行 init 程序,进入 SELinux 初始化阶段。这一阶段的核心目标是:
- 加载 Android 系统的安全策略(SELinux 策略)。
- 确保后续进程在安全的上下文环境中运行。
- 完成从「裸机环境」到「安全受控环境」的过渡,为第二阶段启动系统服务做准备。
二、SELinux 初始化:Android 安全的基石
1. 日志重定向:让 SELinux 日志可追溯
-
问题:SELinux 初始化时,系统日志服务尚未启动,如何记录安全相关日志?
-
解决方案:
-
通过
SelinuxSetupKernelLogging函数将 SELinux 日志重定向到内核缓冲区(/dev/kmsg)。 -
具体实现:
c
void SelinuxSetupKernelLogging() { selinux_callback cb; cb.func_log = SelinuxKlogCallback; // 定义回调函数 selinux_set_callback(SELINUX_CB_LOG, cb); // 注册日志回调 } -
回调函数
SelinuxKlogCallback会将日志格式化为<级别>selinux: 消息,并通过KernelLogger写入内核,后续可通过logcat -b kernel查看。
-
2. 加载 SELinux 策略:定义系统安全规则
-
核心函数:
SelinuxInitialize -
关键步骤:
-
加载策略文件(LoadPolicy) :
- 从
/sys/fs/selinux/policy或其他指定路径读取selinux_policy文件,该文件定义了进程、文件、设备之间的访问权限(例如:限制应用访问系统敏感目录)。 - 类比:相当于给系统安装了一套「安全规则手册」,所有操作必须按手册执行。
- 从
-
设置 SELinux 模式:
-
通过
security_setenforce函数设置运行模式:- 强制模式(Enforcing) :违反策略的操作会被禁止并记录日志(默认模式)。
- 宽容模式(Permissive) :仅记录违规行为,但允许操作(用于调试)。
-
确保内核模式与用户空间设置一致(
kernel_enforcing == is_enforcing)。
-
-
3. 安全上下文设置:为 init 进程「戴安全帽」
-
操作:调用
selinux_android_restorecon("/system/bin/init", 0)为 init 可执行文件设置安全上下文。 -
作用:
- 确保 init 进程在正确的 SELinux 域(domain)中运行,例如
init域,限制其访问权限,防止越权操作。 - 类比:给进程分配一个「身份标签」,规定其能访问的「资源区域」。
- 确保 init 进程在正确的 SELinux 域(domain)中运行,例如
三、进入 Init 第二阶段:参数切换与流程跳转
1. 再次执行 init 程序:带参数 second_stage
c
const char* args[] = {"/system/bin/init", "second_stage", nullptr};
execv(path, args); // 重新执行 init,触发第二阶段逻辑
- 参数意义:
second_stage是 Init 进程的「阶段切换开关」,用于标识从 SELinux 初始化阶段进入真正的用户空间服务启动阶段。 - 代码逻辑:init 的
main函数检测到参数为second_stage时,会执行SecondStageMain函数(第二阶段主逻辑)。
2. 第二阶段的核心任务(文档未详述,但可推测) :
- 解析
init.rc脚本,启动系统服务(如 Zygote、SystemServer)。 - 初始化属性服务(Property Service),管理系统全局属性(如
ro.product.model)。 - 启动守护进程(如
ueventd管理硬件事件)。 - 对比第一阶段:第一阶段是「基建施工」,第二阶段是「设备安装与功能调试」。
四、关键知识点总结
-
SELinux 的作用:
- 全称 Security-Enhanced Linux,通过强制访问控制(MAC)机制,细粒度控制进程对资源的访问,防止恶意软件获取系统权限。
- 在 Android 中,SELinux 是系统安全的核心,例如:限制应用读取其他应用数据、禁止非特权进程修改系统文件。
-
Init 进程的阶段设计哲学:
- 分阶段解耦:第一阶段专注底层环境搭建(挂载文件系统、初始化硬件);第二阶段专注安全策略和服务启动,逻辑清晰,便于维护。
- 逐步加锁:第一阶段在「宽松环境」中快速搭建基础,第二阶段通过 SELinux 「收紧安全策略」,确保后续服务在受控环境中运行。
-
日志与调试:
- 早期日志(包括 SELinux 日志)通过内核缓冲区记录,确保系统启动问题可追溯。
- 开发模式下,Init 崩溃会重启到 Bootloader,便于定位问题(
REBOOT_BOOTLOADER_ON_PANIC标志)。
五、类比说明
Init 进程的第二阶段初始化类似「机场安检流程」:
-
第一阶段:乘客进入机场大厅(搭建基础环境),完成值机(挂载文件系统)、行李托运(初始化设备)。
-
SELinux 初始化:乘客接受安检(加载安全策略),行李过机检查(校验文件完整性),工作人员确认身份(设置安全上下文)。
-
第二阶段:通过安检后,乘客进入候机区(安全上下文环境),等待登机(启动系统服务),最终飞往目的地(系统启动完成)。
通过这一过程,Android 系统确保从用户空间第一个进程开始,所有操作都在严格的安全策略控制下执行,为后续应用运行提供可靠的安全基础。