summaryrefslogtreecommitdiff
path: root/init/builtins.cpp
diff options
context:
space:
mode:
authorJiyong Park <jiyong@google.com>2019-01-02 23:37:15 +0900
committerJiyong Park <jiyong@google.com>2019-01-11 15:17:04 +0900
commit2599088ff67c10c66a70d3741c41529d3e11c7f5 (patch)
tree623d47c09265617401de9d1084292863f122a2a5 /init/builtins.cpp
parentd220cdc71ff1bb3ec433f1051f1612348510f8ad (diff)
Bionic libs and the dynamic linker are bind mounted
This change makes the bionic libs and the dynamic linker from the runtime APEX (com.android.runtime) available to all processes started after apexd finishes activating APEXes. Specifically, the device has two sets of bionic libs and the dynamic linker: one in the system partition for pre-apexd processes and another in the runtime APEX for post-apexd processes. The former is referred as the 'bootstrap' bionic and are located at /system/lib/{libc|libdl|libm}.so and /system/bin/linker. The latter is referred as the 'runtime' bionic and are located at /apex/com.android.runtime/lib/bionic/{libc|libdl|libm}.so and /apex/com.android.runtime/bin/linker. Although the two sets are located in different directories, at runtime, they are accessed via the same path: /system/lib/* and /system/bin/linker ... for both pre/post-apexd processes. This is done by bind-mounting the bootstrap or the runtime bionic to the same path. Keeping the same path is necessary because there are many modules and apps that explicitly or implicitly depend on the fact that bionic libs are located in /system/lib and are loaded into the default linker namespace (which has /system/lib in its search paths). Before the apexd is started, init executes a built-in action 'prepare_bootstrap_bionic' that bind-mounts the bootstrap bionic to the mount points. Processes started during this time are provided with the bootstrap bionic. Then after the apexd is finished, init executes another built-in action 'setup_runtime_bionic' which again mounts the runtime bionic to the same mount points, thus hiding the previous mounts that target the bootstrap bionic. The mounting of the runtime bionic (which is only for post-apexd processes) is hidden from pre-apexd processes by changing propagation type of the mount points to 'private' and execute the pre-apexd processes with a new mount namespace using unshare(2). If a pre-apexd process crashes and re-launched after the apexd is on, the process still gets the bootstrap bionic by unmounting the runtime bionic which effectively un-hides the previous bind-mounts targeting the bootstrap bionic. Bug: 120266448 Test: device boots Test: cat /proc/`pidof zygote`/mountinfo shows that /system/lib/{libc|libdl|libm}.so and /system/bin/linker are from the runtime APEX Test: cat /proc/'pidof vold`/mountinfo shows that the same mount points are from system partition. Change-Id: I7ca67755dc0656c0f0c834ba94bf23ba9b1aca68
Diffstat (limited to 'init/builtins.cpp')
-rw-r--r--init/builtins.cpp82
1 files changed, 82 insertions, 0 deletions
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 52828c00d..4a66e46f1 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1093,6 +1093,86 @@ static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
}
}
+static Result<Success> bind_mount_file(const char* source, const char* mount_point,
+ bool remount_private) {
+ if (remount_private && mount(nullptr, mount_point, nullptr, MS_PRIVATE, nullptr) == -1) {
+ return ErrnoError() << "Could not change " << mount_point << " to a private mount point";
+ }
+ if (mount(source, mount_point, nullptr, MS_BIND, nullptr) == -1) {
+ return ErrnoError() << "Could not bind-mount " << source << " to " << mount_point;
+ }
+ return Success();
+}
+
+static Result<Success> bind_mount_bionic(const char* linker_source, const char* lib_dir_source,
+ const char* linker_mount_point, const char* lib_mount_dir,
+ bool remount_private) {
+ if (access(linker_source, F_OK) != 0) {
+ return Success();
+ }
+ if (auto result = bind_mount_file(linker_source, linker_mount_point, remount_private);
+ !result) {
+ return result;
+ }
+ for (auto libname : kBionicLibFileNames) {
+ std::string mount_point = lib_mount_dir + libname;
+ std::string source = lib_dir_source + libname;
+ if (auto result = bind_mount_file(source.c_str(), mount_point.c_str(), remount_private);
+ !result) {
+ return result;
+ }
+ }
+ return Success();
+}
+
+// The bootstrap bionic libs and the bootstrap linker are bind-mounted to
+// the mount points for pre-apexd processes.
+static Result<Success> do_prepare_bootstrap_bionic(const BuiltinArguments& args) {
+ static bool prepare_bootstrap_bionic_done = false;
+ if (prepare_bootstrap_bionic_done) {
+ return Error() << "prepare_bootstrap_bionic was already executed. Cannot be executed again";
+ }
+ if (auto result = bind_mount_bionic(kBootstrapLinkerPath, kBootstrapBionicLibsDir,
+ kLinkerMountPoint, kBionicLibsMountPointDir, false);
+ !result) {
+ return result;
+ }
+ if (auto result = bind_mount_bionic(kBootstrapLinkerPath64, kBootstrapBionicLibsDir64,
+ kLinkerMountPoint64, kBionicLibsMountPointDir64, false);
+ !result) {
+ return result;
+ }
+
+ LOG(INFO) << "prepare_bootstrap_bionic done";
+ prepare_bootstrap_bionic_done = true;
+ return Success();
+}
+
+// The bionic libs and the dynamic linker from the runtime APEX are bind-mounted
+// to the mount points. As a result, the previous mounts done by
+// prepare_bootstrap_bionic become hidden.
+static Result<Success> do_setup_runtime_bionic(const BuiltinArguments& args) {
+ static bool setup_runtime_bionic_done = false;
+ if (setup_runtime_bionic_done) {
+ return Error() << "setup_runtime_bionic was already executed. Cannot be executed again";
+ }
+ if (auto result = bind_mount_bionic(kRuntimeLinkerPath, kRuntimeBionicLibsDir,
+ kLinkerMountPoint, kBionicLibsMountPointDir, true);
+ !result) {
+ return result;
+ }
+ if (auto result = bind_mount_bionic(kRuntimeLinkerPath64, kRuntimeBionicLibsDir64,
+ kLinkerMountPoint64, kBionicLibsMountPointDir64, true);
+ !result) {
+ return result;
+ }
+
+ ServiceList::GetInstance().MarkRuntimeAvailable();
+ LOG(INFO) << "setup_runtime_bionic done";
+ setup_runtime_bionic_done = true;
+ return Success();
+}
+
// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
@@ -1131,6 +1211,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
{"mount_all", {1, kMax, {false, do_mount_all}}},
{"mount", {3, kMax, {false, do_mount}}},
{"parse_apex_configs", {0, 0, {false, do_parse_apex_configs}}},
+ {"prepare_bootstrap_bionic",{0, 0, {false, do_prepare_bootstrap_bionic}}},
{"umount", {1, 1, {false, do_umount}}},
{"readahead", {1, 2, {true, do_readahead}}},
{"restart", {1, 1, {false, do_restart}}},
@@ -1139,6 +1220,7 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
{"rm", {1, 1, {true, do_rm}}},
{"rmdir", {1, 1, {true, do_rmdir}}},
{"setprop", {2, 2, {true, do_setprop}}},
+ {"setup_runtime_bionic", {0, 0, {false, do_setup_runtime_bionic}}},
{"setrlimit", {3, 3, {false, do_setrlimit}}},
{"start", {1, 1, {false, do_start}}},
{"stop", {1, 1, {false, do_stop}}},