Skip to content

Commit 7bfea3d

Browse files
author
Tom Cherry
committed
init: clean up the 1st/2nd stage init split
The first split of 1st/2nd stage init went a bit overboard, since it split these even in the case of the recovery image and system-as-root, which don't actually need the split. This change simplifies this a bit: system-as-root and recovery have a single combined /system/bin/init and a symlink from /init to it. non-system-as-root has a separate first stage init at /init on the first stage ramdisk and a combined /system/bin/init on system.img. Two particular benefits from this: 1) Removal of the rsync of TARGET_RAMDISK_OUT to the recovery image 2) Decrease of overall space on the recovery image since it won't have a statically linked first stage init This also unified the various entry points of init to depend entirely on the arguments passed to it, instead of the hybrid of arguments and environment variable used previously. Bug: 80395578 Test: boot both system-as-root and non-system-as-root Change-Id: Ic2f29b6f56b7defc80eaa0e7cd0c9107e978816f
1 parent 13856a0 commit 7bfea3d

10 files changed

+165
-94
lines changed

init/Android.bp

+3
Original file line numberDiff line numberDiff line change
@@ -79,6 +79,7 @@ cc_defaults {
7979
"libkeyutils",
8080
"liblog",
8181
"liblogwrap",
82+
"liblp",
8283
"libselinux",
8384
"libutils",
8485
],
@@ -99,6 +100,7 @@ cc_library_static {
99100
"devices.cpp",
100101
"epoll.cpp",
101102
"firmware_handler.cpp",
103+
"first_stage_init.cpp",
102104
"first_stage_mount.cpp",
103105
"import_parser.cpp",
104106
"init.cpp",
@@ -117,6 +119,7 @@ cc_library_static {
117119
"sigchld_handler.cpp",
118120
"subcontext.cpp",
119121
"subcontext.proto",
122+
"switch_root.cpp",
120123
"rlimit_parser.cpp",
121124
"tokenizer.cpp",
122125
"uevent_listener.cpp",

init/Android.mk

+7-9
Original file line numberDiff line numberDiff line change
@@ -39,12 +39,15 @@ init_cflags += \
3939

4040
# --
4141

42+
# Do not build this even with mmma if we're system-as-root, otherwise it will overwrite the symlink.
43+
ifneq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
4244
include $(CLEAR_VARS)
4345
LOCAL_CPPFLAGS := $(init_cflags)
4446
LOCAL_SRC_FILES := \
4547
devices.cpp \
48+
first_stage_init.cpp \
49+
first_stage_main.cpp \
4650
first_stage_mount.cpp \
47-
init_first_stage.cpp \
4851
reboot_utils.cpp \
4952
selinux.cpp \
5053
switch_root.cpp \
@@ -93,19 +96,16 @@ LOCAL_SANITIZE := signed-integer-overflow
9396
# First stage init is weird: it may start without stdout/stderr, and no /proc.
9497
LOCAL_NOSANITIZE := hwaddress
9598
include $(BUILD_EXECUTABLE)
99+
endif
96100

97101
include $(CLEAR_VARS)
98102

99103
LOCAL_MODULE := init_system
100-
ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
101-
LOCAL_REQUIRED_MODULES := \
102-
init_first_stage \
103-
init_second_stage \
104-
105-
else
106104
LOCAL_REQUIRED_MODULES := \
107105
init_second_stage \
108106

107+
ifeq ($(BOARD_BUILD_SYSTEM_ROOT_IMAGE),true)
108+
LOCAL_POST_INSTALL_CMD := ln -sf /system/bin/init $(TARGET_ROOT_OUT)/init
109109
endif
110110
include $(BUILD_PHONY_PACKAGE)
111111

@@ -118,5 +118,3 @@ LOCAL_REQUIRED_MODULES := \
118118

119119
endif
120120
include $(BUILD_PHONY_PACKAGE)
121-
122-

init/init_first_stage.cpp renamed to init/first_stage_init.cpp

+4-6
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,8 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "first_stage_init.h"
18+
1719
#include <dirent.h>
1820
#include <fcntl.h>
1921
#include <paths.h>
@@ -94,7 +96,7 @@ bool ForceNormalBoot() {
9496

9597
} // namespace
9698

97-
int main(int argc, char** argv) {
99+
int FirstStageMain(int argc, char** argv) {
98100
if (REBOOT_BOOTLOADER_ON_PANIC) {
99101
InstallRebootSignalHandlers();
100102
}
@@ -214,7 +216,7 @@ int main(int argc, char** argv) {
214216
setenv("INIT_STARTED_AT", std::to_string(start_ms).c_str(), 1);
215217

216218
const char* path = "/system/bin/init";
217-
const char* args[] = {path, nullptr};
219+
const char* args[] = {path, "selinux_setup", nullptr};
218220
execv(path, const_cast<char**>(args));
219221

220222
// execv() only returns if an error happened, in which case we
@@ -226,7 +228,3 @@ int main(int argc, char** argv) {
226228

227229
} // namespace init
228230
} // namespace android
229-
230-
int main(int argc, char** argv) {
231-
return android::init::main(argc, argv);
232-
}

init/first_stage_init.h

+25
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
/*
2+
* Copyright (C) 2018 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#pragma once
18+
19+
namespace android {
20+
namespace init {
21+
22+
int FirstStageMain(int argc, char** argv);
23+
24+
} // namespace init
25+
} // namespace android

init/first_stage_main.cpp

+21
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,21 @@
1+
/*
2+
* Copyright (C) 2018 The Android Open Source Project
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* http://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
#include "first_stage_init.h"
18+
19+
int main(int argc, char** argv) {
20+
return android::init::FirstStageMain(argc, argv);
21+
}

init/init.cpp

+1-72
Original file line numberDiff line numberDiff line change
@@ -59,13 +59,8 @@
5959
#include "security.h"
6060
#include "selinux.h"
6161
#include "sigchld_handler.h"
62-
#include "ueventd.h"
6362
#include "util.h"
6463

65-
#if __has_feature(address_sanitizer)
66-
#include <sanitizer/asan_interface.h>
67-
#endif
68-
6964
using namespace std::chrono_literals;
7065
using namespace std::string_literals;
7166

@@ -79,25 +74,6 @@ using android::base::Trim;
7974
namespace android {
8075
namespace init {
8176

82-
#if __has_feature(address_sanitizer)
83-
// Load asan.options if it exists since these are not yet in the environment.
84-
// Always ensure detect_container_overflow=0 as there are false positives with this check.
85-
// Always ensure abort_on_error=1 to ensure we reboot to bootloader for development builds.
86-
extern "C" const char* __asan_default_options() {
87-
return "include_if_exists=/system/asan.options:detect_container_overflow=0:abort_on_error=1";
88-
}
89-
90-
__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) extern "C" void
91-
__sanitizer_report_error_summary(const char* summary) {
92-
LOG(ERROR) << "Main stage (error summary): " << summary;
93-
}
94-
95-
__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) static void
96-
AsanReportCallback(const char* str) {
97-
LOG(ERROR) << "Main stage: " << str;
98-
}
99-
#endif
100-
10177
static int property_triggers_enabled = 0;
10278

10379
static char qemu[32];
@@ -622,57 +598,11 @@ static void GlobalSeccomp() {
622598
});
623599
}
624600

625-
static void SetupSelinux(char** argv) {
626-
android::base::InitLogging(argv, &android::base::KernelLogger, [](const char*) {
627-
RebootSystem(ANDROID_RB_RESTART2, "bootloader");
628-
});
629-
630-
// Set up SELinux, loading the SELinux policy.
631-
SelinuxSetupKernelLogging();
632-
SelinuxInitialize();
633-
634-
// We're in the kernel domain and want to transition to the init domain. File systems that
635-
// store SELabels in their xattrs, such as ext4 do not need an explicit restorecon here,
636-
// but other file systems do. In particular, this is needed for ramdisks such as the
637-
// recovery image for A/B devices.
638-
if (selinux_android_restorecon("/system/bin/init", 0) == -1) {
639-
PLOG(FATAL) << "restorecon failed of /system/bin/init failed";
640-
}
641-
642-
setenv("SELINUX_INITIALIZED", "true", 1);
643-
644-
const char* path = "/system/bin/init";
645-
const char* args[] = {path, nullptr};
646-
execv(path, const_cast<char**>(args));
647-
648-
// execv() only returns if an error happened, in which case we
649-
// panic and never return from this function.
650-
PLOG(FATAL) << "execv(\"" << path << "\") failed";
651-
}
652-
653-
int main(int argc, char** argv) {
654-
#if __has_feature(address_sanitizer)
655-
__asan_set_error_report_callback(AsanReportCallback);
656-
#endif
657-
658-
if (!strcmp(basename(argv[0]), "ueventd")) {
659-
return ueventd_main(argc, argv);
660-
}
661-
662-
if (argc > 1 && !strcmp(argv[1], "subcontext")) {
663-
android::base::InitLogging(argv, &android::base::KernelLogger);
664-
const BuiltinFunctionMap function_map;
665-
return SubcontextMain(argc, argv, &function_map);
666-
}
667-
601+
int SecondStageMain(int argc, char** argv) {
668602
if (REBOOT_BOOTLOADER_ON_PANIC) {
669603
InstallRebootSignalHandlers();
670604
}
671605

672-
if (getenv("SELINUX_INITIALIZED") == nullptr) {
673-
SetupSelinux(argv);
674-
}
675-
676606
// We need to set up stdin/stdout/stderr again now that we're running in init's context.
677607
InitKernelLogging(argv, InitAborter);
678608
LOG(INFO) << "init second stage started!";
@@ -708,7 +638,6 @@ int main(int argc, char** argv) {
708638
if (avb_version) property_set("ro.boot.avb_version", avb_version);
709639

710640
// Clean up our environment.
711-
unsetenv("SELINUX_INITIALIZED");
712641
unsetenv("INIT_STARTED_AT");
713642
unsetenv("INIT_SELINUX_TOOK");
714643
unsetenv("INIT_AVB_VERSION");

init/init.h

+1-1
Original file line numberDiff line numberDiff line change
@@ -50,7 +50,7 @@ void DumpState();
5050

5151
void ResetWaitForProp();
5252

53-
int main(int argc, char** argv);
53+
int SecondStageMain(int argc, char** argv);
5454

5555
} // namespace init
5656
} // namespace android

init/main.cpp

+63-1
Original file line numberDiff line numberDiff line change
@@ -14,8 +14,70 @@
1414
* limitations under the License.
1515
*/
1616

17+
#include "builtins.h"
18+
#include "first_stage_init.h"
1719
#include "init.h"
20+
#include "selinux.h"
21+
#include "subcontext.h"
22+
#include "ueventd.h"
23+
24+
#include <android-base/logging.h>
25+
26+
#if __has_feature(address_sanitizer)
27+
#include <sanitizer/asan_interface.h>
28+
#endif
29+
30+
#if __has_feature(address_sanitizer)
31+
// Load asan.options if it exists since these are not yet in the environment.
32+
// Always ensure detect_container_overflow=0 as there are false positives with this check.
33+
// Always ensure abort_on_error=1 to ensure we reboot to bootloader for development builds.
34+
extern "C" const char* __asan_default_options() {
35+
return "include_if_exists=/system/asan.options:detect_container_overflow=0:abort_on_error=1";
36+
}
37+
38+
__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) extern "C" void
39+
__sanitizer_report_error_summary(const char* summary) {
40+
LOG(ERROR) << "Init (error summary): " << summary;
41+
}
42+
43+
__attribute__((no_sanitize("address", "memory", "thread", "undefined"))) static void
44+
AsanReportCallback(const char* str) {
45+
LOG(ERROR) << "Init: " << str;
46+
}
47+
#endif
48+
49+
using namespace android::init;
1850

1951
int main(int argc, char** argv) {
20-
android::init::main(argc, argv);
52+
#if __has_feature(address_sanitizer)
53+
__asan_set_error_report_callback(AsanReportCallback);
54+
#endif
55+
56+
if (!strcmp(basename(argv[0]), "ueventd")) {
57+
return ueventd_main(argc, argv);
58+
}
59+
60+
if (argc < 2) {
61+
return FirstStageMain(argc, argv);
62+
}
63+
64+
if (!strcmp(argv[1], "subcontext")) {
65+
android::base::InitLogging(argv, &android::base::KernelLogger);
66+
const BuiltinFunctionMap function_map;
67+
68+
return SubcontextMain(argc, argv, &function_map);
69+
}
70+
71+
if (!strcmp(argv[1], "selinux_setup")) {
72+
return SetupSelinux(argv);
73+
}
74+
75+
if (!strcmp(argv[1], "second_stage")) {
76+
return SecondStageMain(argc, argv);
77+
}
78+
79+
android::base::InitLogging(argv, &android::base::KernelLogger);
80+
81+
LOG(ERROR) << "Unknown argument passed to init '" << argv[1] << "'";
82+
return 1;
2183
}

0 commit comments

Comments
 (0)