Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 4f23d5a2 authored by Jooyung Han's avatar Jooyung Han
Browse files

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
parent 3447cdc7
Loading
Loading
Loading
Loading
+21 −4
Original line number Original line Diff line number Diff line
@@ -1221,6 +1221,20 @@ static Result<void> GenerateLinkerConfiguration() {
    return {};
    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 IsApexUpdatable() {
    static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
    static bool updatable = android::sysprop::ApexProperties::updatable().value_or(false);
    return updatable;
    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) {
static Result<void> do_enter_default_mount_ns(const BuiltinArguments& args) {
    if (SwitchToDefaultMountNamespace()) {
    if (auto result = SwitchToMountNamespaceIfNeeded(NS_DEFAULT); !result.ok()) {
        return {};
        return result.error();
    } else {
    }
        return Error() << "Failed to enter into default mount namespace";
    if (auto result = MountLinkerConfigForDefaultNamespace(); !result.ok()) {
        return result.error();
    }
    }
    LOG(INFO) << "Switched to default mount namespace";
    return {};
}
}


// Builtin-function-map start
// Builtin-function-map start
+11 −45
Original line number Original line Diff line number Diff line
@@ -176,20 +176,6 @@ static bool ActivateFlattenedApexesIfPossible() {
    return true;
    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 bootstrap_ns_fd;
static android::base::unique_fd default_ns_fd;
static android::base::unique_fd default_ns_fd;


@@ -290,40 +276,20 @@ bool SetupMountNamespaces() {
    return success;
    return success;
}
}


bool SwitchToDefaultMountNamespace() {
Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace) {
    if (IsRecoveryMode()) {
    if (IsRecoveryMode() || !IsApexUpdatable()) {
        // we don't have multiple namespaces in recovery mode
        // we don't have multiple namespaces in recovery mode or if apex is not updatable
        return true;
        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;
        }
    }

    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 &&
    const auto& ns_id = target_mount_namespace == NS_BOOTSTRAP ? bootstrap_ns_id : default_ns_id;
        IsApexUpdatable()) {
    const auto& ns_fd = target_mount_namespace == NS_BOOTSTRAP ? bootstrap_ns_fd : default_ns_fd;
        if (setns(bootstrap_ns_fd.get(), CLONE_NEWNS) == -1) {
    const auto& ns_name = target_mount_namespace == NS_BOOTSTRAP ? "bootstrap" : "default";
            PLOG(ERROR) << "Failed to switch to bootstrap mount namespace.";
    if (ns_id != GetMountNamespaceId() && ns_fd.get() != -1) {
            return false;
        if (setns(ns_fd.get(), CLONE_NEWNS) == -1) {
            return ErrnoError() << "Failed to switch to " << ns_name << " mount namespace.";
        }
        }
    }
    }
    return true;
    return {};
}
}


}  // namespace init
}  // namespace init
+5 −2
Original line number Original line Diff line number Diff line
@@ -16,12 +16,15 @@


#pragma once
#pragma once


#include <android-base/result.h>

namespace android {
namespace android {
namespace init {
namespace init {


enum MountNamespace { NS_BOOTSTRAP, NS_DEFAULT };

bool SetupMountNamespaces();
bool SetupMountNamespaces();
bool SwitchToDefaultMountNamespace();
base::Result<void> SwitchToMountNamespaceIfNeeded(MountNamespace target_mount_namespace);
bool SwitchToBootstrapMountNamespaceIfNeeded();


}  // namespace init
}  // namespace init
}  // namespace android
}  // namespace android
+1 −1
Original line number Original line Diff line number Diff line
@@ -831,7 +831,7 @@ static Result<void> DoUserspaceReboot() {
        sub_reason = "apex";
        sub_reason = "apex";
        return result;
        return result;
    }
    }
    if (!SwitchToBootstrapMountNamespaceIfNeeded()) {
    if (!SwitchToMountNamespaceIfNeeded(NS_BOOTSTRAP)) {
        sub_reason = "ns_switch";
        sub_reason = "ns_switch";
        return Error() << "Failed to switch to bootstrap namespace";
        return Error() << "Failed to switch to bootstrap namespace";
    }
    }
+12 −1
Original line number Original line Diff line number Diff line
@@ -465,6 +465,16 @@ Result<void> Service::Start() {
        pre_apexd_ = true;
        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();
    post_data_ = ServiceList::GetInstance().IsPostData();


    LOG(INFO) << "starting service '" << name_ << "'...";
    LOG(INFO) << "starting service '" << name_ << "'...";
@@ -496,7 +506,8 @@ Result<void> Service::Start() {
    if (pid == 0) {
    if (pid == 0) {
        umask(077);
        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_
            LOG(FATAL) << "Service '" << name_
                       << "' failed to set up namespaces: " << result.error();
                       << "' failed to set up namespaces: " << result.error();
        }
        }
Loading