init: start ueventd in the default mount namespace
Init starts ueventd in the default mount namespace to support loading firmware from APEXes. Bug: 155023652 Test: devices boots adb$ nsenter -t (pid of ueventd) -m ls /apex => shows all APEXes Change-Id: Ibb8b33a07eb014752275e3bca4541b8b694dc64b
This commit is contained in:
parent
3447cdc741
commit
4f23d5a236
|
@ -1221,6 +1221,20 @@ static Result<void> GenerateLinkerConfiguration() {
|
|||
return {};
|
||||
}
|
||||
|
||||
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 bool IsApexUpdatable() {
|
||||
static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
|
||||
return updatable;
|
||||
|
@ -1319,11 +1333,14 @@ static Result<void> do_perform_apex_config(const BuiltinArguments& args) {
|
|||
}
|
||||
|
||||
static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) {
|
||||
if (SwitchToDefaultMountNamespace()) {
|
||||
return {};
|
||||
} else {
|
||||
return Error() << "Failed to enter into default mount namespace";
|
||||
if (auto result = SwitchToMountNamespaceIfNeeded(NS_DEFAULT); !result.ok()) {
|
||||
return result.error();
|
||||
}
|
||||
if (auto result = MountLinkerConfigForDefaultNamespace(); !result.ok()) {
|
||||
return result.error();
|
||||
}
|
||||
LOG(INFO) << "Switched to default mount namespace";
|
||||
return {};
|
||||
}
|
||||
|
||||
// Builtin-function-map start
|
||||
|
|
|
@ -176,20 +176,6 @@ static bool ActivateFlattenedApexesIfPossible() {
|
|||
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;
|
||||
|
||||
|
@ -290,40 +276,20 @@ bool SetupMountNamespaces() {
|
|||
return success;
|
||||
}
|
||||
|
||||
bool SwitchToDefaultMountNamespace() {
|
||||
if (IsRecoveryMode()) {
|
||||
// we don't have multiple namespaces in recovery mode
|
||||
return true;
|
||||
Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace) {
|
||||
if (IsRecoveryMode() || !IsApexUpdatable()) {
|
||||
// we don't have multiple namespaces in recovery mode or if apex is not updatable
|
||||
return {};
|
||||
}
|
||||
if (default_ns_id != GetMountNamespaceId()) {
|
||||
if (setns(default_ns_fd.get(), CLONE_NEWNS) == -1) {
|
||||
PLOG(ERROR) << "Failed to switch back to the default mount namespace.";
|
||||
return false;
|
||||
}
|
||||
|
||||
if (auto result = MountLinkerConfigForDefaultNamespace(); !result.ok()) {
|
||||
LOG(ERROR) << result.error();
|
||||
return false;
|
||||
const auto& ns_id = target_mount_namespace == NS_BOOTSTRAP ? bootstrap_ns_id : default_ns_id;
|
||||
const auto& ns_fd = target_mount_namespace == NS_BOOTSTRAP ? bootstrap_ns_fd : default_ns_fd;
|
||||
const auto& ns_name = target_mount_namespace == NS_BOOTSTRAP ? "bootstrap" : "default";
|
||||
if (ns_id != GetMountNamespaceId() && ns_fd.get() != -1) {
|
||||
if (setns(ns_fd.get(), CLONE_NEWNS) == -1) {
|
||||
return ErrnoError() << "Failed to switch to " << ns_name << " mount namespace.";
|
||||
}
|
||||
}
|
||||
|
||||
LOG(INFO) << "Switched to default mount namespace";
|
||||
return true;
|
||||
}
|
||||
|
||||
bool SwitchToBootstrapMountNamespaceIfNeeded() {
|
||||
if (IsRecoveryMode()) {
|
||||
// we don't have multiple namespaces in recovery mode
|
||||
return true;
|
||||
}
|
||||
if (bootstrap_ns_id != GetMountNamespaceId() && bootstrap_ns_fd.get() != -1 &&
|
||||
IsApexUpdatable()) {
|
||||
if (setns(bootstrap_ns_fd.get(), CLONE_NEWNS) == -1) {
|
||||
PLOG(ERROR) << "Failed to switch to bootstrap mount namespace.";
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
return {};
|
||||
}
|
||||
|
||||
} // namespace init
|
||||
|
|
|
@ -16,12 +16,15 @@
|
|||
|
||||
#pragma once
|
||||
|
||||
#include <android-base/result.h>
|
||||
|
||||
namespace android {
|
||||
namespace init {
|
||||
|
||||
enum MountNamespace { NS_BOOTSTRAP, NS_DEFAULT };
|
||||
|
||||
bool SetupMountNamespaces();
|
||||
bool SwitchToDefaultMountNamespace();
|
||||
bool SwitchToBootstrapMountNamespaceIfNeeded();
|
||||
base::Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace);
|
||||
|
||||
} // namespace init
|
||||
} // namespace android
|
||||
|
|
|
@ -831,7 +831,7 @@ static Result<void> DoUserspaceReboot() {
|
|||
sub_reason = "apex";
|
||||
return result;
|
||||
}
|
||||
if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
|
||||
if (!SwitchToMountNamespaceIfNeeded(NS_BOOTSTRAP)) {
|
||||
sub_reason = "ns_switch";
|
||||
return Error() << "Failed to switch to bootstrap namespace";
|
||||
}
|
||||
|
|
|
@ -465,6 +465,16 @@ Result<void> Service::Start() {
|
|||
pre_apexd_ = true;
|
||||
}
|
||||
|
||||
// For pre-apexd services, override mount namespace as "bootstrap" one before starting.
|
||||
// Note: "ueventd" is supposed to be run in "default" mount namespace even if it's pre-apexd
|
||||
// to support loading firmwares from APEXes.
|
||||
std::optional<MountNamespace> override_mount_namespace;
|
||||
if (name_ == "ueventd") {
|
||||
override_mount_namespace = NS_DEFAULT;
|
||||
} else if (pre_apexd_) {
|
||||
override_mount_namespace = NS_BOOTSTRAP;
|
||||
}
|
||||
|
||||
post_data_ = ServiceList::GetInstance().IsPostData();
|
||||
|
||||
LOG(INFO) << "starting service '" << name_ << "'...";
|
||||
|
@ -496,7 +506,8 @@ Result<void> Service::Start() {
|
|||
if (pid == 0) {
|
||||
umask(077);
|
||||
|
||||
if (auto result = EnterNamespaces(namespaces_, name_, pre_apexd_); !result.ok()) {
|
||||
if (auto result = EnterNamespaces(namespaces_, name_, override_mount_namespace);
|
||||
!result.ok()) {
|
||||
LOG(FATAL) << "Service '" << name_
|
||||
<< "' failed to set up namespaces: " << result.error();
|
||||
}
|
||||
|
|
|
@ -194,7 +194,8 @@ Result<Descriptor> FileDescriptor::Create() const {
|
|||
return Descriptor(ANDROID_FILE_ENV_PREFIX + name, std::move(fd));
|
||||
}
|
||||
|
||||
Result<void> EnterNamespaces(const NamespaceInfo& info, const std::string& name, bool pre_apexd) {
|
||||
Result<void> EnterNamespaces(const NamespaceInfo& info, const std::string& name,
|
||||
std::optional<MountNamespace> override_mount_namespace) {
|
||||
for (const auto& [nstype, path] : info.namespaces_to_enter) {
|
||||
if (auto result = EnterNamespace(nstype, path.c_str()); !result.ok()) {
|
||||
return result;
|
||||
|
@ -202,9 +203,10 @@ Result<void> EnterNamespaces(const NamespaceInfo& info, const std::string& name,
|
|||
}
|
||||
|
||||
#if defined(__ANDROID__)
|
||||
if (pre_apexd) {
|
||||
if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
|
||||
return Error() << "could not enter into the bootstrap mount namespace";
|
||||
if (override_mount_namespace.has_value()) {
|
||||
if (auto result = SwitchToMountNamespaceIfNeeded(override_mount_namespace.value());
|
||||
!result.ok()) {
|
||||
return result;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
|
|
@ -19,12 +19,14 @@
|
|||
#include <sys/resource.h>
|
||||
#include <sys/types.h>
|
||||
|
||||
#include <optional>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include <android-base/unique_fd.h>
|
||||
#include <cutils/iosched_policy.h>
|
||||
|
||||
#include "mount_namespace.h"
|
||||
#include "result.h"
|
||||
|
||||
namespace android {
|
||||
|
@ -66,7 +68,8 @@ struct NamespaceInfo {
|
|||
// Pair of namespace type, path to name.
|
||||
std::vector<std::pair<int, std::string>> namespaces_to_enter;
|
||||
};
|
||||
Result<void> EnterNamespaces(const NamespaceInfo& info, const std::string& name, bool pre_apexd);
|
||||
Result<void> EnterNamespaces(const NamespaceInfo& info, const std::string& name,
|
||||
std::optional<MountNamespace> override_mount_namespace);
|
||||
|
||||
struct ProcessAttributes {
|
||||
std::string console;
|
||||
|
|
Loading…
Reference in New Issue