Merge "Generate linkerconfig per mount namespaces"
diff --git a/init/builtins.cpp b/init/builtins.cpp
index 62a19ab..3c32d8b 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -59,6 +59,7 @@
#include <fs_mgr.h>
#include <fscrypt/fscrypt.h>
#include <libgsi/libgsi.h>
+#include <logwrap/logwrap.h>
#include <selinux/android.h>
#include <selinux/label.h>
#include <selinux/selinux.h>
@@ -1176,6 +1177,42 @@
return {};
}
+static Result<void> GenerateLinkerConfiguration() {
+ const char* linkerconfig_binary = "/system/bin/linkerconfig";
+ const char* linkerconfig_target = "/linkerconfig/ld.config.txt";
+ const char* arguments[] = {linkerconfig_binary, "--target", linkerconfig_target};
+
+ if (logwrap_fork_execvp(arraysize(arguments), arguments, nullptr, false, LOG_KLOG, false,
+ nullptr) != 0) {
+ return ErrnoError() << "failed to execute linkerconfig";
+ }
+
+ mode_t mode = get_mode("0444");
+ if (fchmodat(AT_FDCWD, linkerconfig_target, mode, AT_SYMLINK_NOFOLLOW) < 0) {
+ return ErrnoErrorIgnoreEnoent() << "fchmodat() failed";
+ }
+
+ LOG(INFO) << "linkerconfig generated " << linkerconfig_target
+ << " with mounted APEX modules info";
+
+ return {};
+}
+
+static bool IsApexUpdatable() {
+ static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
+ return updatable;
+}
+
+static Result<void> do_update_linker_config(const BuiltinArguments&) {
+ // If APEX is not updatable, then all APEX information are already included in the first
+ // linker config generation, so there is no need to update linker configuration again.
+ if (IsApexUpdatable()) {
+ return GenerateLinkerConfiguration();
+ }
+
+ return {};
+}
+
static Result<void> parse_apex_configs() {
glob_t glob_result;
static constexpr char glob_pattern[] = "/apex/*/etc/*.rc";
@@ -1251,6 +1288,12 @@
if (!parse_configs) {
return parse_configs.error();
}
+
+ auto update_linker_config = do_update_linker_config(args);
+ if (!update_linker_config) {
+ return update_linker_config.error();
+ }
+
return {};
}
@@ -1317,6 +1360,7 @@
{"perform_apex_config", {0, 0, {false, do_perform_apex_config}}},
{"umount", {1, 1, {false, do_umount}}},
{"umount_all", {1, 1, {false, do_umount_all}}},
+ {"update_linker_config", {0, 0, {false, do_update_linker_config}}},
{"readahead", {1, 2, {true, do_readahead}}},
{"remount_userdata", {0, 0, {false, do_remount_userdata}}},
{"restart", {1, 1, {false, do_restart}}},
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index 648b3bb..93eb244 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -151,6 +151,20 @@
return true;
}
+static Result<void> MountLinkerConfigForDefaultNamespace() {
+ // No need to mount linkerconfig for default mount namespace if the path does not exist (which
+ // would mean it is already mounted)
+ if (access("/linkerconfig/default", 0) != 0) {
+ return {};
+ }
+
+ if (mount("/linkerconfig/default", "/linkerconfig", nullptr, MS_BIND | MS_REC, nullptr) != 0) {
+ return ErrnoError() << "Failed to mount linker configuration for default mount namespace.";
+ }
+
+ return {};
+}
+
static android::base::unique_fd bootstrap_ns_fd;
static android::base::unique_fd default_ns_fd;
@@ -222,6 +236,11 @@
PLOG(ERROR) << "Failed to switch back to the default mount namespace.";
return false;
}
+
+ if (auto result = MountLinkerConfigForDefaultNamespace(); !result) {
+ LOG(ERROR) << result.error();
+ return false;
+ }
}
LOG(INFO) << "Switched to default mount namespace";
diff --git a/rootdir/init.rc b/rootdir/init.rc
index 803d44a..9cf11a4 100644
--- a/rootdir/init.rc
+++ b/rootdir/init.rc
@@ -38,9 +38,18 @@
# Allow up to 32K FDs per process
setrlimit nofile 32768 32768
+ # Set up linker config subdirectories based on mount namespaces
+ mkdir /linkerconfig/bootstrap 0755
+ mkdir /linkerconfig/default 0755
+
# Generate ld.config.txt for early executed processes
- exec -- /system/bin/linkerconfig --target /linkerconfig/ld.config.txt
- chmod 444 /linkerconfig/ld.config.txt
+ exec -- /system/bin/linkerconfig --target /linkerconfig/bootstrap/ld.config.txt
+ chmod 644 /linkerconfig/bootstrap/ld.config.txt
+ copy /linkerconfig/bootstrap/ld.config.txt /linkerconfig/default/ld.config.txt
+ chmod 644 /linkerconfig/default/ld.config.txt
+
+ # Mount bootstrap linker configuration as current
+ mount none /linkerconfig/bootstrap /linkerconfig bind rec
start ueventd
@@ -49,6 +58,9 @@
# the libraries are available to the processes started after this statement.
exec_start apexd-bootstrap
+ # Generate linker config based on apex mounted in bootstrap namespace
+ update_linker_config
+
# These must already exist by the time boringssl_self_test32 / boringssl_self_test64 run.
mkdir /dev/boringssl 0755 root root
mkdir /dev/boringssl/selftest 0755 root root