本次分析代码都是基于 android-13.0.0_r3 版本进行分析
主要是分析内核的启动过程,大概将各个板块在启动过程中什么时候启动,对应的函数调用链条,方便后续进行详细分析的时候有个大概的框架概念。详细的各个板块的拆解分析,留给后面的专门的解析文章。
DAC 基于 UID/GID 的传统 Linux 权限控制,通过文件所有者和权限位控制访问。
比如我们最重要的进程的权限设置
Init进程中的DAC权限设置 - system/core/init/service_utils.cpp:235
Zygote中的DAC权限设置 - frameworks/base/core/jni/com_android_internal_os_Zygote.cpp:1891
Zygote中的MAC权限设置 - frameworks/base/core/jni/com_android_internal_os_Zygote.cpp:2133
Init 中MAC权限设置
zygote 进程是 Android 系统中的一个关键组件,主要负责应用程序的启动和管理。
在启动时,zygote 会预加载一些常用的类和资源,以提高后续应用程序的启动速度。这种预加载机制可以减少内存使用和启动时间。
zygote 使用 fork 机制来创建新的应用程序进程。当应用程序需要启动时,zygote 会复制自身的内存空间,从而快速生成新的进程。这种方式比传统的进程创建方式更高效。
预加载过程
运行在 Zygote 进程中监听 socket,fork 应用进程,管理 USAP 池等
zygote 进程在启动时会创建 SystemServer 进程,SystemServer 进程则依赖于 zygote 提供的功能来管理和启动其他服务。
SystemServer 进程负责启动和管理各种系统服务,如 ActivityManager、WindowManager、PackageManager、PowerManager 等。这些服务是 Android 系统正常运行所必需的。
┌─────────────────────────────────────────────────────────────┐
│ Kernel 启动 │
│ (PID 1: /init) │
└────────────────────┬──────────────────────────────────────────┘
│
▼
┌────────────────────────────┐
│ main() [main.cpp:53] │
│ - 设置优先级 -20 │
│ - 路由到不同阶段 │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ FirstStageMain() │
│ [first_stage_init.cpp:333] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│挂载文件│ │创建设备│ │加载内核│
│系统 │ │节点 │ │模块 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ execv("selinux_setup") │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ SetupSelinux() │
│ [selinux.cpp:701] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│挂载缺失│ │读取策略│ │加载策略│
│分区 │ │文件 │ │到内核 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ execv("second_stage") │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ SecondStageMain() │
│ [init.cpp:922] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│初始化属│ │加载init│ │创建epoll│
│性服务 │ │.rc脚本 │ │事件循环 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ 触发启动事件 │
│ - early-init │
│ - init │
│ - late-init │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ 启动Zygote服务 │
│ (通过init.rc) │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ ZygoteInit.main() │
│ [ZygoteInit.java:796] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│预加载类│ │预加载资│ │预加载共│
│和资源 │ │源 │ │享库 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ forkSystemServer() │
└────────────┬────────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│父进程 │ │子进程 │
│(Zygote) │ │(System │
│ │ │ Server) │
└──────────┘ └────┬─────┘
│
▼
┌────────────────────────────┐
│ SystemServer.main() │
│ [SystemServer.java:682] │
└────────────┬───────────────┘
│
▼
┌────────────────────────────┐
│ SystemServer.run() │
│ [SystemServer.java:790] │
└────────────┬───────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│启动引导│ │启动核心│ │启动其他│
│服务 │ │服务 │ │服务 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ Looper.loop() │
│ 进入主循环 │
└────────────────────────────┘
┌─────────────────────────────────────────────────────────────┐
│ Kernel 启动 │
│ (PID 1: /init) │
└────────────────────┬──────────────────────────────────────────┘
│
▼
┌────────────────────────────┐
│ main() [main.cpp:53] │
│ - 设置优先级 -20 │
│ - 路由到不同阶段 │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ FirstStageMain() │
│ [first_stage_init.cpp:333] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│挂载文件│ │创建设备│ │加载内核│
│系统 │ │节点 │ │模块 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ execv("selinux_setup") │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ SetupSelinux() │
│ [selinux.cpp:701] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│挂载缺失│ │读取策略│ │加载策略│
│分区 │ │文件 │ │到内核 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ execv("second_stage") │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ SecondStageMain() │
│ [init.cpp:922] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│初始化属│ │加载init│ │创建epoll│
│性服务 │ │.rc脚本 │ │事件循环 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ 触发启动事件 │
│ - early-init │
│ - init │
│ - late-init │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ 启动Zygote服务 │
│ (通过init.rc) │
└────────────┬────────────────┘
│
▼
┌────────────────────────────┐
│ ZygoteInit.main() │
│ [ZygoteInit.java:796] │
└────────────┬────────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│预加载类│ │预加载资│ │预加载共│
│和资源 │ │源 │ │享库 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ forkSystemServer() │
└────────────┬────────────────┘
│
┌───────────┴───────────┐
│ │
▼ ▼
┌──────────┐ ┌──────────┐
│父进程 │ │子进程 │
│(Zygote) │ │(System │
│ │ │ Server) │
└──────────┘ └────┬─────┘
│
▼
┌────────────────────────────┐
│ SystemServer.main() │
│ [SystemServer.java:682] │
└────────────┬───────────────┘
│
▼
┌────────────────────────────┐
│ SystemServer.run() │
│ [SystemServer.java:790] │
└────────────┬───────────────┘
│
┌───────────┼───────────┐
│ │ │
▼ ▼ ▼
┌────────┐ ┌────────┐ ┌────────┐
│启动引导│ │启动核心│ │启动其他│
│服务 │ │服务 │ │服务 │
└────────┘ └────────┘ └────────┘
│ │ │
└───────────┼───────────┘
│
▼
┌────────────────────────────┐
│ Looper.loop() │
│ 进入主循环 │
└────────────────────────────┘
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#elif __has_feature(hwaddress_sanitizer)
__hwasan_set_error_report_callback(AsanReportCallback);
#endif
setpriority(PRIO_PROCESS, 0, -20);
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
return FirstStageMain(argc, argv);
}
int main(int argc, char** argv) {
#if __has_feature(address_sanitizer)
__asan_set_error_report_callback(AsanReportCallback);
#elif __has_feature(hwaddress_sanitizer)
__hwasan_set_error_report_callback(AsanReportCallback);
#endif
setpriority(PRIO_PROCESS, 0, -20);
if (!strcmp(basename(argv[0]), "ueventd")) {
return ueventd_main(argc, argv);
}
if (argc > 1) {
if (!strcmp(argv[1], "subcontext")) {
android::base::InitLogging(argv, &android::base::KernelLogger);
const BuiltinFunctionMap& function_map = GetBuiltinFunctionMap();
return SubcontextMain(argc, argv, &function_map);
}
if (!strcmp(argv[1], "selinux_setup")) {
return SetupSelinux(argv);
}
if (!strcmp(argv[1], "second_stage")) {
return SecondStageMain(argc, argv);
}
}
return FirstStageMain(argc, argv);
}
int FirstStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
boot_clock::time_point start_time = boot_clock::now();
std::vector<std::pair<std::string, int>> errors;
#define CHECKCALL(x) \
if ((x) != 0) errors.emplace_back(#x " failed", errno);
umask(0);
CHECKCALL(clearenv());
CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
CHECKCALL(mkdir("/dev/pts", 0755));
CHECKCALL(mkdir("/dev/socket", 0755));
CHECKCALL(mkdir("/dev/dm-user", 0755));
CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
#define MAKE_STR(x) __STRING(x)
CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
#undef MAKE_STR
CHECKCALL(chmod("/proc/cmdline", 0440));
std::string cmdline;
android::base::ReadFileToString("/proc/cmdline", &cmdline);
chmod("/proc/bootconfig", 0440);
std::string bootconfig;
android::base::ReadFileToString("/proc/bootconfig", &bootconfig);
gid_t groups[] = {AID_READPROC};
CHECKCALL(setgroups(arraysize(groups), groups));
CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));
if constexpr (WORLD_WRITABLE_KMSG) {
CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)));
}
CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));
CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=1000"));
CHECKCALL(mkdir("/mnt/vendor", 0755));
CHECKCALL(mkdir("/mnt/product", 0755));
CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
CHECKCALL(mount("tmpfs", "/microdroid_resources", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0750,uid=0,gid=0"));
}
#undef CHECKCALL
SetStdioToDevNull(argv);
InitKernelLogging(argv);
if (!errors.empty()) {
for (const auto& [error_string, error_errno] : errors) {
LOG(ERROR) << error_string << " " << strerror(error_errno);
}
LOG(FATAL) << "Init encountered errors starting first stage, aborting";
}
LOG(INFO) << "init first stage started!";
auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
if (!old_root_dir) {
PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
}
struct stat old_root_info {};
if (stat("/", &old_root_info) != 0) {
PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
old_root_dir.reset();
}
auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline, bootconfig) : 0;
auto want_parallel =
bootconfig.find("androidboot.load_modules_parallel = \"true\"") != std::string::npos;
boot_clock::time_point module_start_time = boot_clock::now();
int module_count = 0;
BootMode boot_mode = GetBootMode(cmdline, bootconfig);
if (!LoadKernelModules(boot_mode, want_console,
want_parallel, module_count)) {
if (want_console != FirstStageConsoleParam::DISABLED) {
LOG(ERROR) << "Failed to load kernel modules, starting console";
} else {
LOG(FATAL) << "Failed to load kernel modules";
}
}
if (module_count > 0) {
auto module_elapse_time = std::chrono::duration_cast<std::chrono::milliseconds>(
boot_clock::now() - module_start_time);
setenv(kEnvInitModuleDurationMs, std::to_string(module_elapse_time.count()).c_str(), 1);
LOG(INFO) << "Loaded " << module_count << " kernel modules took "
<< module_elapse_time.count() << " ms";
}
MaybeResumeFromHibernation(bootconfig);
std::unique_ptr<FirstStageMount> fsm;
bool created_devices = false;
if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) {
if (!IsRecoveryMode()) {
fsm = CreateFirstStageMount(cmdline);
if (fsm) {
created_devices = fsm->DoCreateDevices();
if (!created_devices) {
LOG(ERROR) << "Failed to create device nodes early";
}
}
}
StartConsole(cmdline);
}
if (access(kBootImageRamdiskProp, F_OK) == 0) {
std::string dest = GetRamdiskPropForSecondStage();
std::string dir = android::base::Dirname(dest);
std::error_code ec;
if (!fs::create_directories(dir, ec) && !!ec) {
LOG(FATAL) << "Can't mkdir " << dir << ": " << ec.message();
}
if (!fs::copy_file(kBootImageRamdiskProp, dest, ec)) {
LOG(FATAL) << "Can't copy " << kBootImageRamdiskProp << " to " << dest << ": "
<< ec.message();
}
LOG(INFO) << "Copied ramdisk prop to " << dest;
}
if (access("/force_debuggable", F_OK) == 0) {
constexpr const char adb_debug_prop_src[] = "/adb_debug.prop";
constexpr const char userdebug_plat_sepolicy_cil_src[] = "/userdebug_plat_sepolicy.cil";
std::error_code ec;
if (access(adb_debug_prop_src, F_OK) == 0 &&
!fs::copy_file(adb_debug_prop_src, kDebugRamdiskProp, ec)) {
LOG(WARNING) << "Can't copy " << adb_debug_prop_src << " to " << kDebugRamdiskProp
<< ": " << ec.message();
}
if (access(userdebug_plat_sepolicy_cil_src, F_OK) == 0 &&
!fs::copy_file(userdebug_plat_sepolicy_cil_src, kDebugRamdiskSEPolicy, ec)) {
LOG(WARNING) << "Can't copy " << userdebug_plat_sepolicy_cil_src << " to "
<< kDebugRamdiskSEPolicy << ": " << ec.message();
}
setenv("INIT_FORCE_DEBUGGABLE", "true", 1);
}
if (ForceNormalBoot(cmdline, bootconfig)) {
mkdir("/first_stage_ramdisk", 0755);
PrepareSwitchRoot();
if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {
PLOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself";
}
SwitchRoot("/first_stage_ramdisk");
}
if (IsRecoveryMode()) {
LOG(INFO) << "First stage mount skipped (recovery mode)";
} else {
if (!fsm) {
fsm = CreateFirstStageMount(cmdline);
}
if (!fsm) {
LOG(FATAL) << "FirstStageMount not available";
}
if (!created_devices && !fsm->DoCreateDevices()) {
LOG(FATAL) << "Failed to create devices required for first stage mount";
}
if (!fsm->DoFirstStageMount()) {
LOG(FATAL) << "Failed to mount required partitions early ...";
}
}
struct stat new_root_info {};
if (stat("/", &new_root_info) != 0) {
PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
old_root_dir.reset();
}
if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) {
FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
}
SetInitAvbVersionInRecovery();
setenv(kEnvFirstStageStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(),
1);
const char* path = "/system/bin/init";
const char* args[] = {path, "selinux_setup", nullptr};
auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
close(fd);
execv(path, const_cast<char**>(args));
PLOG(FATAL) << "execv(\"" << path << "\") failed";
return 1;
}
int FirstStageMain(int argc, char** argv) {
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
boot_clock::time_point start_time = boot_clock::now();
std::vector<std::pair<std::string, int>> errors;
#define CHECKCALL(x) \
if ((x) != 0) errors.emplace_back(#x " failed", errno);
umask(0);
CHECKCALL(clearenv());
CHECKCALL(setenv("PATH", _PATH_DEFPATH, 1));
CHECKCALL(mount("tmpfs", "/dev", "tmpfs", MS_NOSUID, "mode=0755"));
CHECKCALL(mkdir("/dev/pts", 0755));
CHECKCALL(mkdir("/dev/socket", 0755));
CHECKCALL(mkdir("/dev/dm-user", 0755));
CHECKCALL(mount("devpts", "/dev/pts", "devpts", 0, NULL));
#define MAKE_STR(x) __STRING(x)
CHECKCALL(mount("proc", "/proc", "proc", 0, "hidepid=2,gid=" MAKE_STR(AID_READPROC)));
#undef MAKE_STR
CHECKCALL(chmod("/proc/cmdline", 0440));
std::string cmdline;
android::base::ReadFileToString("/proc/cmdline", &cmdline);
chmod("/proc/bootconfig", 0440);
std::string bootconfig;
android::base::ReadFileToString("/proc/bootconfig", &bootconfig);
gid_t groups[] = {AID_READPROC};
CHECKCALL(setgroups(arraysize(groups), groups));
CHECKCALL(mount("sysfs", "/sys", "sysfs", 0, NULL));
CHECKCALL(mount("selinuxfs", "/sys/fs/selinux", "selinuxfs", 0, NULL));
CHECKCALL(mknod("/dev/kmsg", S_IFCHR | 0600, makedev(1, 11)));
if constexpr (WORLD_WRITABLE_KMSG) {
CHECKCALL(mknod("/dev/kmsg_debug", S_IFCHR | 0622, makedev(1, 11)));
}
CHECKCALL(mknod("/dev/random", S_IFCHR | 0666, makedev(1, 8)));
CHECKCALL(mknod("/dev/urandom", S_IFCHR | 0666, makedev(1, 9)));
CHECKCALL(mknod("/dev/ptmx", S_IFCHR | 0666, makedev(5, 2)));
CHECKCALL(mknod("/dev/null", S_IFCHR | 0666, makedev(1, 3)));
CHECKCALL(mount("tmpfs", "/mnt", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=1000"));
CHECKCALL(mkdir("/mnt/vendor", 0755));
CHECKCALL(mkdir("/mnt/product", 0755));
CHECKCALL(mount("tmpfs", "/debug_ramdisk", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
CHECKCALL(mount("tmpfs", kSecondStageRes, "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0755,uid=0,gid=0"));
if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
CHECKCALL(mount("tmpfs", "/microdroid_resources", "tmpfs", MS_NOEXEC | MS_NOSUID | MS_NODEV,
"mode=0750,uid=0,gid=0"));
}
#undef CHECKCALL
SetStdioToDevNull(argv);
InitKernelLogging(argv);
if (!errors.empty()) {
for (const auto& [error_string, error_errno] : errors) {
LOG(ERROR) << error_string << " " << strerror(error_errno);
}
LOG(FATAL) << "Init encountered errors starting first stage, aborting";
}
LOG(INFO) << "init first stage started!";
auto old_root_dir = std::unique_ptr<DIR, decltype(&closedir)>{opendir("/"), closedir};
if (!old_root_dir) {
PLOG(ERROR) << "Could not opendir(\"/\"), not freeing ramdisk";
}
struct stat old_root_info {};
if (stat("/", &old_root_info) != 0) {
PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
old_root_dir.reset();
}
auto want_console = ALLOW_FIRST_STAGE_CONSOLE ? FirstStageConsole(cmdline, bootconfig) : 0;
auto want_parallel =
bootconfig.find("androidboot.load_modules_parallel = \"true\"") != std::string::npos;
boot_clock::time_point module_start_time = boot_clock::now();
int module_count = 0;
BootMode boot_mode = GetBootMode(cmdline, bootconfig);
if (!LoadKernelModules(boot_mode, want_console,
want_parallel, module_count)) {
if (want_console != FirstStageConsoleParam::DISABLED) {
LOG(ERROR) << "Failed to load kernel modules, starting console";
} else {
LOG(FATAL) << "Failed to load kernel modules";
}
}
if (module_count > 0) {
auto module_elapse_time = std::chrono::duration_cast<std::chrono::milliseconds>(
boot_clock::now() - module_start_time);
setenv(kEnvInitModuleDurationMs, std::to_string(module_elapse_time.count()).c_str(), 1);
LOG(INFO) << "Loaded " << module_count << " kernel modules took "
<< module_elapse_time.count() << " ms";
}
MaybeResumeFromHibernation(bootconfig);
std::unique_ptr<FirstStageMount> fsm;
bool created_devices = false;
if (want_console == FirstStageConsoleParam::CONSOLE_ON_FAILURE) {
if (!IsRecoveryMode()) {
fsm = CreateFirstStageMount(cmdline);
if (fsm) {
created_devices = fsm->DoCreateDevices();
if (!created_devices) {
LOG(ERROR) << "Failed to create device nodes early";
}
}
}
StartConsole(cmdline);
}
if (access(kBootImageRamdiskProp, F_OK) == 0) {
std::string dest = GetRamdiskPropForSecondStage();
std::string dir = android::base::Dirname(dest);
std::error_code ec;
if (!fs::create_directories(dir, ec) && !!ec) {
LOG(FATAL) << "Can't mkdir " << dir << ": " << ec.message();
}
if (!fs::copy_file(kBootImageRamdiskProp, dest, ec)) {
LOG(FATAL) << "Can't copy " << kBootImageRamdiskProp << " to " << dest << ": "
<< ec.message();
}
LOG(INFO) << "Copied ramdisk prop to " << dest;
}
if (access("/force_debuggable", F_OK) == 0) {
constexpr const char adb_debug_prop_src[] = "/adb_debug.prop";
constexpr const char userdebug_plat_sepolicy_cil_src[] = "/userdebug_plat_sepolicy.cil";
std::error_code ec;
if (access(adb_debug_prop_src, F_OK) == 0 &&
!fs::copy_file(adb_debug_prop_src, kDebugRamdiskProp, ec)) {
LOG(WARNING) << "Can't copy " << adb_debug_prop_src << " to " << kDebugRamdiskProp
<< ": " << ec.message();
}
if (access(userdebug_plat_sepolicy_cil_src, F_OK) == 0 &&
!fs::copy_file(userdebug_plat_sepolicy_cil_src, kDebugRamdiskSEPolicy, ec)) {
LOG(WARNING) << "Can't copy " << userdebug_plat_sepolicy_cil_src << " to "
<< kDebugRamdiskSEPolicy << ": " << ec.message();
}
setenv("INIT_FORCE_DEBUGGABLE", "true", 1);
}
if (ForceNormalBoot(cmdline, bootconfig)) {
mkdir("/first_stage_ramdisk", 0755);
PrepareSwitchRoot();
if (mount("/first_stage_ramdisk", "/first_stage_ramdisk", nullptr, MS_BIND, nullptr) != 0) {
PLOG(FATAL) << "Could not bind mount /first_stage_ramdisk to itself";
}
SwitchRoot("/first_stage_ramdisk");
}
if (IsRecoveryMode()) {
LOG(INFO) << "First stage mount skipped (recovery mode)";
} else {
if (!fsm) {
fsm = CreateFirstStageMount(cmdline);
}
if (!fsm) {
LOG(FATAL) << "FirstStageMount not available";
}
if (!created_devices && !fsm->DoCreateDevices()) {
LOG(FATAL) << "Failed to create devices required for first stage mount";
}
if (!fsm->DoFirstStageMount()) {
LOG(FATAL) << "Failed to mount required partitions early ...";
}
}
struct stat new_root_info {};
if (stat("/", &new_root_info) != 0) {
PLOG(ERROR) << "Could not stat(\"/\"), not freeing ramdisk";
old_root_dir.reset();
}
if (old_root_dir && old_root_info.st_dev != new_root_info.st_dev) {
FreeRamdisk(old_root_dir.get(), old_root_info.st_dev);
}
SetInitAvbVersionInRecovery();
setenv(kEnvFirstStageStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(),
1);
const char* path = "/system/bin/init";
const char* args[] = {path, "selinux_setup", nullptr};
auto fd = open("/dev/kmsg", O_WRONLY | O_CLOEXEC);
dup2(fd, STDOUT_FILENO);
dup2(fd, STDERR_FILENO);
close(fd);
execv(path, const_cast<char**>(args));
PLOG(FATAL) << "execv(\"" << path << "\") failed";
return 1;
}
┌─────────────────────────────────────────────────────────┐
│ SetupSelinux() 入口 │
│ [system/core/init/selinux.cpp:701] │
└────────────────┬──────────────────────────────────────┘
│
▼
┌────────────────┐
│ 初始化日志系统 │
│ SelinuxSetupKernelLogging()
└────────┬───────┘
│
▼
┌─────────────────────────────┐
│ 判断设备类型 │
│ IsMicrodroid()? │
└──────┬──────────────┬───────┘
│ │
┌──────▼──────┐ ┌───▼──────────────────┐
│ Microdroid │ │ Android设备 │
│ 加载策略 │ │ LoadSelinuxPolicyAndroid()
└─────────────┘ └──────┬───────────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ 挂载缺失分区 │ │ 读取策略文件 │
│ MountMissingSystem │ │ ReadPolicy() │
│ Partitions() │ └──────┬───────────────┘
└──────────────────────┘ │
│
┌─────────────────────┴─────────────────────┐
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Split Policy设备? │ │ Monolithic Policy │
│ IsSplitPolicyDevice()│ │ OpenMonolithicPolicy()│
└──────┬───────────────┘ │ 打开 /sepolicy │
│ └──────────────────────┘
▼
┌──────────────────────┐
│ OpenSplitPolicy() │
└──────┬───────────────┘
│
├──────────────────────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ 查找预编译策略 │ │ 编译策略 │
│ FindPrecompiled │ │ 调用secic编译CIL文件 │
│ SplitPolicy() │ │ ForkExecveAndWaitFor │
│ │ │ Completion(secilc) │
│ 验证SHA256哈希 │ └──────────────────────┘
└──────────────────┘
│
▼
┌──────────────────────┐
│ Snapuserd过渡处理 │
│ StartTransition() │
│ (停止snapuserd) │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 加载策略到内核 │
│ LoadSelinuxPolicy() │
│ security_load_policy()│
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 完成Snapuserd过渡 │
│ FinishTransition() │
│ (重启snapuserd) │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 设置Enforcing模式 │
│ SelinuxSetEnforcement()│
│ security_setenforce() │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 恢复init文件上下文 │
│ restorecon("/system/ │
│ bin/init") │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ execv到second_stage │
│ execv("/system/bin/ │
│ init", "second_stage")│
└──────────────────────┘
┌─────────────────────────────────────────────────────────┐
│ SetupSelinux() 入口 │
│ [system/core/init/selinux.cpp:701] │
└────────────────┬──────────────────────────────────────┘
│
▼
┌────────────────┐
│ 初始化日志系统 │
│ SelinuxSetupKernelLogging()
└────────┬───────┘
│
▼
┌─────────────────────────────┐
│ 判断设备类型 │
│ IsMicrodroid()? │
└──────┬──────────────┬───────┘
│ │
┌──────▼──────┐ ┌───▼──────────────────┐
│ Microdroid │ │ Android设备 │
│ 加载策略 │ │ LoadSelinuxPolicyAndroid()
└─────────────┘ └──────┬───────────────┘
│
┌────────────┴────────────┐
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ 挂载缺失分区 │ │ 读取策略文件 │
│ MountMissingSystem │ │ ReadPolicy() │
│ Partitions() │ └──────┬───────────────┘
└──────────────────────┘ │
│
┌─────────────────────┴─────────────────────┐
│ │
▼ ▼
┌──────────────────────┐ ┌──────────────────────┐
│ Split Policy设备? │ │ Monolithic Policy │
│ IsSplitPolicyDevice()│ │ OpenMonolithicPolicy()│
└──────┬───────────────┘ │ 打开 /sepolicy │
│ └──────────────────────┘
▼
┌──────────────────────┐
│ OpenSplitPolicy() │
└──────┬───────────────┘
│
├──────────────────────────────┐
│ │
▼ ▼
┌──────────────────┐ ┌──────────────────────┐
│ 查找预编译策略 │ │ 编译策略 │
│ FindPrecompiled │ │ 调用secic编译CIL文件 │
│ SplitPolicy() │ │ ForkExecveAndWaitFor │
│ │ │ Completion(secilc) │
│ 验证SHA256哈希 │ └──────────────────────┘
└──────────────────┘
│
▼
┌──────────────────────┐
│ Snapuserd过渡处理 │
│ StartTransition() │
│ (停止snapuserd) │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 加载策略到内核 │
│ LoadSelinuxPolicy() │
│ security_load_policy()│
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 完成Snapuserd过渡 │
│ FinishTransition() │
│ (重启snapuserd) │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 设置Enforcing模式 │
│ SelinuxSetEnforcement()│
│ security_setenforce() │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ 恢复init文件上下文 │
│ restorecon("/system/ │
│ bin/init") │
└──────┬───────────────┘
│
▼
┌──────────────────────┐
│ execv到second_stage │
│ execv("/system/bin/ │
│ init", "second_stage")│
└──────────────────────┘
int SetupSelinux(char** argv) {
SetStdioToDevNull(argv);
InitKernelLogging(argv);
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
boot_clock::time_point start_time = boot_clock::now();
SelinuxSetupKernelLogging();
if (IsMicrodroid()) {
LoadSelinuxPolicyMicrodroid();
} else {
LoadSelinuxPolicyAndroid();
}
SelinuxSetEnforcement();
if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
const int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
if (selinux_android_restorecon("/microdroid_resources", flags) == -1) {
PLOG(FATAL) << "restorecon of /microdroid_resources failed";
}
}
if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
}
setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
execv(path, const_cast<char**>(args));
PLOG(FATAL) << "execv(\"" << path << "\") failed";
return 1;
}
int SetupSelinux(char** argv) {
SetStdioToDevNull(argv);
InitKernelLogging(argv);
if (REBOOT_BOOTLOADER_ON_PANIC) {
InstallRebootSignalHandlers();
}
boot_clock::time_point start_time = boot_clock::now();
SelinuxSetupKernelLogging();
if (IsMicrodroid()) {
LoadSelinuxPolicyMicrodroid();
} else {
LoadSelinuxPolicyAndroid();
}
SelinuxSetEnforcement();
if (IsMicrodroid() && android::virtualization::IsOpenDiceChangesFlagEnabled()) {
const int flags = SELINUX_ANDROID_RESTORECON_RECURSE;
if (selinux_android_restorecon("/microdroid_resources", flags) == -1) {
PLOG(FATAL) << "restorecon of /microdroid_resources failed";
}
}
if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
}
setenv(kEnvSelinuxStartedAt, std::to_string(start_time.time_since_epoch().count()).c_str(), 1);
const char* path = "/system/bin/init";
const char* args[] = {path, "second_stage", nullptr};
execv(path, const_cast<char**>(args));
PLOG(FATAL) << "execv(\"" << path << "\") failed";
return 1;
}
void LoadSelinuxPolicyMicrodroid() {
constexpr const char kMicrodroidPrecompiledSepolicy[] =
"/system/etc/selinux/microdroid_precompiled_sepolicy";
LOG(INFO) << "Opening SELinux policy from " << kMicrodroidPrecompiledSepolicy;
unique_fd policy_fd(open(kMicrodroidPrecompiledSepolicy, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (policy_fd < 0) {
PLOG(FATAL) << "Failed to open " << kMicrodroidPrecompiledSepolicy;
}
std::string policy;
if (!android::base::ReadFdToString(policy_fd, &policy)) {
PLOG(FATAL) << "Failed to read policy file: " << kMicrodroidPrecompiledSepolicy;
}
LoadSelinuxPolicy(policy);
}
void LoadSelinuxPolicyMicrodroid() {
constexpr const char kMicrodroidPrecompiledSepolicy[] =
"/system/etc/selinux/microdroid_precompiled_sepolicy";
LOG(INFO) << "Opening SELinux policy from " << kMicrodroidPrecompiledSepolicy;
unique_fd policy_fd(open(kMicrodroidPrecompiledSepolicy, O_RDONLY | O_CLOEXEC | O_NOFOLLOW));
if (policy_fd < 0) {
PLOG(FATAL) << "Failed to open " << kMicrodroidPrecompiledSepolicy;
}
std::string policy;
if (!android::base::ReadFdToString(policy_fd, &policy)) {
PLOG(FATAL) << "Failed to read policy file: " << kMicrodroidPrecompiledSepolicy;
}
LoadSelinuxPolicy(policy);
}
void LoadSelinuxPolicyAndroid() {
MountMissingSystemPartitions();
LOG(INFO) << "Opening SELinux policy";
std::string policy;
ReadPolicy(&policy);
auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
if (snapuserd_helper) {
snapuserd_helper->StartTransition();
}
LoadSelinuxPolicy(policy);
if (snapuserd_helper) {
snapuserd_helper->FinishTransition();
snapuserd_helper = nullptr;
}
}
void LoadSelinuxPolicyAndroid() {
MountMissingSystemPartitions();
LOG(INFO) << "Opening SELinux policy";
std::string policy;
ReadPolicy(&policy);
auto snapuserd_helper = SnapuserdSelinuxHelper::CreateIfNeeded();
if (snapuserd_helper) {
snapuserd_helper->StartTransition();
}
LoadSelinuxPolicy(policy);
if (snapuserd_helper) {
snapuserd_helper->FinishTransition();
snapuserd_helper = nullptr;
}
}
bool OpenSplitPolicy(PolicyFile* policy_file) {
const auto userdebug_plat_sepolicy = GetUserdebugPlatformPolicyFile();
const bool use_userdebug_policy = userdebug_plat_sepolicy.has_value();
if (use_userdebug_policy) {
LOG(INFO) << "Using userdebug system sepolicy " << *userdebug_plat_sepolicy;
}
if (!use_userdebug_policy) {
if (auto res = FindPrecompiledSplitPolicy(); res.ok()) {
unique_fd fd(open(res->c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
if (fd != -1) {
policy_file->fd = std::move(fd);
policy_file->path = std::move(*res);
return true;
}
} else {
LOG(INFO) << res.error();
}
}
LOG(INFO) << "Compiling SELinux policy";
char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
unique_fd compiled_sepolicy_fd(mkostemp(compiled_sepolicy, O_CLOEXEC));
if (compiled_sepolicy_fd < 0) {
PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy;
return false;
}
std::string vend_plat_vers;
if (!GetVendorMappingVersion(&vend_plat_vers)) {
return false;
}
std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
std::string plat_compat_cil_file("/system/etc/selinux/mapping/" + vend_plat_vers +
".compat.cil");
if (access(plat_compat_cil_file.c_str(), F_OK) == -1) {
plat_compat_cil_file.clear();
}
std::string system_ext_policy_cil_file("/system_ext/etc/selinux/system_ext_sepolicy.cil");
if (access(system_ext_policy_cil_file.c_str(), F_OK) == -1) {
system_ext_policy_cil_file.clear();
}
std::string system_ext_mapping_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +
".cil");
if (access(system_ext_mapping_file.c_str(), F_OK) == -1) {
system_ext_mapping_file.clear();
}
std::string system_ext_compat_cil_file("/system_ext/etc/selinux/mapping/" + vend_plat_vers +
".compat.cil");
if (access(system_ext_compat_cil_file.c_str(), F_OK) == -1) {
system_ext_compat_cil_file.clear();
}
std::string product_policy_cil_file("/product/etc/selinux/product_sepolicy.cil");
if (access(product_policy_cil_file.c_str(), F_OK) == -1) {
product_policy_cil_file.clear();
}
std::string product_mapping_file("/product/etc/selinux/mapping/" + vend_plat_vers + ".cil");
if (access(product_mapping_file.c_str(), F_OK) == -1) {
product_mapping_file.clear();
}
std::string vendor_policy_cil_file("/vendor/etc/selinux/vendor_sepolicy.cil");
if (access(vendor_policy_cil_file.c_str(), F_OK) == -1) {
LOG(ERROR) << "Missing " << vendor_policy_cil_file;
return false;
}
std::string plat_pub_versioned_cil_file("/vendor/etc/selinux/plat_pub_versioned.cil");
if (access(plat_pub_versioned_cil_file.c_str(), F_OK) == -1) {
LOG(ERROR) << "Missing " << plat_pub_versioned_cil_file;
return false;
}
std::string odm_policy_cil_file("/odm/etc/selinux/odm_sepolicy.cil");
if (access(odm_policy_cil_file.c_str(), F_OK) == -1) {
odm_policy_cil_file.clear();
}
const std::string version_as_string = std::to_string(SEPOLICY_VERSION);
std::vector<std::string> genfs_cil_files;
int vendor_genfs_version = get_genfs_labels_version();
std::string genfs_cil_file =
std::format("/system/etc/selinux/plat_sepolicy_genfs_{}.cil", vendor_genfs_version);
if (access(genfs_cil_file.c_str(), F_OK) != 0) {
LOG(INFO) << "Missing " << genfs_cil_file << "; skipping";
genfs_cil_file.clear();
} else {
LOG(INFO) << "Using " << genfs_cil_file << " for genfs labels";
}
std::vector<const char*> compile_args {
"/system/bin/secilc",
use_userdebug_policy ? *userdebug_plat_sepolicy : plat_policy_cil_file,
"-m", "-M", "true", "-G", "-N",
"-c", version_as_string.c_str(),
plat_mapping_file.c_str(),
"-o", compiled_sepolicy,
"-f", "/sys/fs/selinux/null",
};
if (!plat_compat_cil_file.empty()) {
compile_args.push_back(plat_compat_cil_file.c_str());
}
if (!system_ext_policy_cil_file.empty()) {
compile_args.push_back(system_ext_policy_cil_file.c_str());
}
if (!system_ext_mapping_file.empty()) {
compile_args.push_back(system_ext_mapping_file.c_str());
}
if (!system_ext_compat_cil_file.empty()) {
compile_args.push_back(system_ext_compat_cil_file.c_str());
}
if (!product_policy_cil_file.empty()) {
compile_args.push_back(product_policy_cil_file.c_str());
}
if (!product_mapping_file.empty()) {
compile_args.push_back(product_mapping_file.c_str());
}
if (!plat_pub_versioned_cil_file.empty()) {
compile_args.push_back(plat_pub_versioned_cil_file.c_str());
}
if (!vendor_policy_cil_file.empty()) {
compile_args.push_back(vendor_policy_cil_file.c_str());
}
if (!odm_policy_cil_file.empty()) {
compile_args.push_back(odm_policy_cil_file.c_str());
}
if (!genfs_cil_file.empty()) {
compile_args.push_back(genfs_cil_file.c_str());
}
compile_args.push_back(nullptr);
if (!ForkExecveAndWaitForCompletion(compile_args[0], (char**)compile_args.data())) {
unlink(compiled_sepolicy);
return false;
}
unlink(compiled_sepolicy);
policy_file->fd = std::move(compiled_sepolicy_fd);
policy_file->path = compiled_sepolicy;
return true;
}
bool OpenSplitPolicy(PolicyFile* policy_file) {
const auto userdebug_plat_sepolicy = GetUserdebugPlatformPolicyFile();
const bool use_userdebug_policy = userdebug_plat_sepolicy.has_value();
if (use_userdebug_policy) {
LOG(INFO) << "Using userdebug system sepolicy " << *userdebug_plat_sepolicy;
}
if (!use_userdebug_policy) {
if (auto res = FindPrecompiledSplitPolicy(); res.ok()) {
unique_fd fd(open(res->c_str(), O_RDONLY | O_CLOEXEC | O_BINARY));
if (fd != -1) {
policy_file->fd = std::move(fd);
policy_file->path = std::move(*res);
return true;
}
} else {
LOG(INFO) << res.error();
}
}
LOG(INFO) << "Compiling SELinux policy";
char compiled_sepolicy[] = "/dev/sepolicy.XXXXXX";
unique_fd compiled_sepolicy_fd(mkostemp(compiled_sepolicy, O_CLOEXEC));
if (compiled_sepolicy_fd < 0) {
PLOG(ERROR) << "Failed to create temporary file " << compiled_sepolicy;
return false;
}
std::string vend_plat_vers;
if (!GetVendorMappingVersion(&vend_plat_vers)) {
return false;
}
std::string plat_mapping_file("/system/etc/selinux/mapping/" + vend_plat_vers + ".cil");
std::string plat_compat_cil_file("/system/etc/selinux/mapping/" + vend_plat_vers +
".compat.cil");
if (access(plat_compat_cil_file.c_str(), F_OK) == -1) {
plat_compat_cil_file.clear();
}
std::string system_ext_policy_cil_file("/system_ext/etc/selinux/system_ext_sepolicy.cil");
if (access(system_ext_policy_cil_file.c_str(), F_OK) == -1) {
system_ext_policy_cil_file.clear();
[培训]Windows内核深度攻防:从Hook技术到Rootkit实战!