Check if service is executed before APEX is ready
Any service which is executed when Runtime apex is mounted, but
linkerconfig is not updated can fail to be executed due to missing
information in ld.config.txt. This change updates init to have a status
variable which contains if current mount namespace is default
and APEX is not ready from ld.config.txt, and use bootstrap namespace if
it is not ready.
Bug: 181348374
Test: cuttlefish boot succeeded
Change-Id: Ia574b1fad2110d4e68586680dacbe6137186546e
diff --git a/init/builtins.cpp b/init/builtins.cpp
index dcc9582..035038f 100644
--- a/init/builtins.cpp
+++ b/init/builtins.cpp
@@ -1278,6 +1278,14 @@
return ErrnoError() << "failed to execute linkerconfig";
}
+ auto current_mount_ns = GetCurrentMountNamespace();
+ if (!current_mount_ns.ok()) {
+ return current_mount_ns.error();
+ }
+ if (*current_mount_ns == NS_DEFAULT) {
+ SetDefaultMountNamespaceReady();
+ }
+
LOG(INFO) << "linkerconfig generated " << linkerconfig_target
<< " with mounted APEX modules info";
diff --git a/init/mount_namespace.cpp b/init/mount_namespace.cpp
index ec48cde..15252a6 100644
--- a/init/mount_namespace.cpp
+++ b/init/mount_namespace.cpp
@@ -301,5 +301,20 @@
return {};
}
+base::Result<MountNamespace> GetCurrentMountNamespace() {
+ std::string current_namespace_id = GetMountNamespaceId();
+ if (current_namespace_id == "") {
+ return Error() << "Failed to get current mount namespace ID";
+ }
+
+ if (current_namespace_id == bootstrap_ns_id) {
+ return NS_BOOTSTRAP;
+ } else if (current_namespace_id == default_ns_id) {
+ return NS_DEFAULT;
+ }
+
+ return Error() << "Failed to find current mount namespace";
+}
+
} // namespace init
} // namespace android
diff --git a/init/mount_namespace.h b/init/mount_namespace.h
index d4d6f82..5e3dab2 100644
--- a/init/mount_namespace.h
+++ b/init/mount_namespace.h
@@ -26,5 +26,7 @@
bool SetupMountNamespaces();
base::Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace);
+base::Result<MountNamespace> GetCurrentMountNamespace();
+
} // namespace init
} // namespace android
diff --git a/init/service.cpp b/init/service.cpp
index cfb8284..836dc47 100644
--- a/init/service.cpp
+++ b/init/service.cpp
@@ -125,11 +125,6 @@
return execv(c_strings[0], c_strings.data()) == 0;
}
-static bool AreRuntimeApexesReady() {
- struct stat buf;
- return stat("/apex/com.android.runtime/", &buf) == 0;
-}
-
unsigned long Service::next_start_order_ = 1;
bool Service::is_exec_service_running_ = false;
@@ -312,7 +307,7 @@
#else
static bool is_apex_updatable = false;
#endif
- const bool is_process_updatable = !pre_apexd_ && is_apex_updatable;
+ const bool is_process_updatable = !use_bootstrap_ns_ && is_apex_updatable;
// If we crash > 4 times in 'fatal_crash_window_' minutes or before boot_completed,
// reboot into bootloader or set crashing property
@@ -465,12 +460,12 @@
scon = *result;
}
- if (!AreRuntimeApexesReady() && !pre_apexd_) {
- // If this service is started before the Runtime and ART APEXes get
- // available, mark it as pre-apexd one. Note that this marking is
+ if (!IsDefaultMountNamespaceReady() && name_ != "apexd") {
+ // If this service is started before APEXes and corresponding linker configuration
+ // get available, mark it as pre-apexd one. Note that this marking is
// permanent. So for example, if the service is re-launched (e.g., due
// to crash), it is still recognized as pre-apexd... for consistency.
- pre_apexd_ = true;
+ use_bootstrap_ns_ = true;
}
// For pre-apexd services, override mount namespace as "bootstrap" one before starting.
@@ -479,7 +474,7 @@
std::optional<MountNamespace> override_mount_namespace;
if (name_ == "ueventd") {
override_mount_namespace = NS_DEFAULT;
- } else if (pre_apexd_) {
+ } else if (use_bootstrap_ns_) {
override_mount_namespace = NS_BOOTSTRAP;
}
diff --git a/init/service.h b/init/service.h
index aee1e5d..043555f 100644
--- a/init/service.h
+++ b/init/service.h
@@ -207,7 +207,7 @@
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
- bool pre_apexd_ = false;
+ bool use_bootstrap_ns_ = false;
bool post_data_ = false;
diff --git a/init/util.cpp b/init/util.cpp
index e69b43f..eab99d4 100644
--- a/init/util.cpp
+++ b/init/util.cpp
@@ -735,5 +735,16 @@
return access("/system/bin/recovery", F_OK) == 0;
}
+// Check if default mount namespace is ready to be used with APEX modules
+static bool is_default_mount_namespace_ready = false;
+
+bool IsDefaultMountNamespaceReady() {
+ return is_default_mount_namespace_ready;
+}
+
+void SetDefaultMountNamespaceReady() {
+ is_default_mount_namespace_ready = true;
+}
+
} // namespace init
} // namespace android
diff --git a/init/util.h b/init/util.h
index 7745d77..daba852 100644
--- a/init/util.h
+++ b/init/util.h
@@ -100,5 +100,8 @@
void SetStdioToDevNull(char** argv);
void InitKernelLogging(char** argv);
bool IsRecoveryMode();
+
+bool IsDefaultMountNamespaceReady();
+void SetDefaultMountNamespaceReady();
} // namespace init
} // namespace android