Update linker configuration when loading apex

On ctl.apex_load <apex_name> control message, init invokes linkerconfig
to update linker configuration for the updated apex.

Bug: 232173613
Test: CtsInitTestCases
Test: VendorApexHostTestCases
Change-Id: I01d975849c3f4efe74205a7b04ebbd6864ba1121
diff --git a/init/init.cpp b/init/init.cpp
index e40627f..535033d 100644
--- a/init/init.cpp
+++ b/init/init.cpp
@@ -54,6 +54,7 @@
 #include <libavb/libavb.h>
 #include <libgsi/libgsi.h>
 #include <libsnapshot/snapshot.h>
+#include <logwrap/logwrap.h>
 #include <processgroup/processgroup.h>
 #include <processgroup/setup.h>
 #include <selinux/android.h>
@@ -450,9 +451,33 @@
     return {};
 }
 
+static Result<void> UpdateApexLinkerConfig(const std::string& apex_name) {
+    // Do not invoke linkerconfig when there's no bin/ in the apex.
+    const std::string bin_path = "/apex/" + apex_name + "/bin";
+    if (access(bin_path.c_str(), R_OK) != 0) {
+        return {};
+    }
+    const char* linkerconfig_binary = "/apex/com.android.runtime/bin/linkerconfig";
+    const char* linkerconfig_target = "/linkerconfig";
+    const char* arguments[] = {linkerconfig_binary, "--target", linkerconfig_target, "--apex",
+                               apex_name.c_str(),   "--strict"};
+
+    if (logwrap_fork_execvp(arraysize(arguments), arguments, nullptr, false, LOG_KLOG, false,
+                            nullptr) != 0) {
+        return ErrnoError() << "failed to execute linkerconfig";
+    }
+    LOG(INFO) << "Generated linker configuration for " << apex_name;
+    return {};
+}
+
 static Result<void> DoLoadApex(const std::string& apex_name) {
     std::string prop_name = "init.apex." + apex_name;
     // TODO(b/232799709) read .rc files from the apex
+
+    if (auto result = UpdateApexLinkerConfig(apex_name); !result.ok()) {
+        return result.error();
+    }
+
     SetProperty(prop_name, "loaded");
     return {};
 }