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

Commit e4d3f212 authored by Kiyoung Kim's avatar Kiyoung Kim
Browse files

Generate linkerconfig per mount namespaces

There are two namespaces from init - bootstrap and default - and those
will have different set of APEX modules. To support difference between
two namespaces, linker config should be generated per namespace and each
namespace should use its own linker configuration. As a first step of
the work, this change will create different mount point for each
namespace, and re-generate linker config after APEX mount from each
namespaces.

Bug: 144664390
Test: m -j passed & tested from cuttlefish
Change-Id: Iac2e222376ec4b0ced6c29eed18b21d39ff0b1ba
parent 1cdcc5f7
Loading
Loading
Loading
Loading
+44 −0
Original line number Diff line number Diff line
@@ -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 @@ static Result<void> do_mark_post_data(const BuiltinArguments& args) {
    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 @@ static Result<void> do_perform_apex_config(const BuiltinArguments& args) {
    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 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() {
        {"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}}},
+19 −0
Original line number Diff line number Diff line
@@ -151,6 +151,20 @@ 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;

@@ -222,6 +236,11 @@ bool SwitchToDefaultMountNamespace() {
            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";
+14 −2
Original line number Diff line number Diff line
@@ -38,9 +38,18 @@ on early-init
    # 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 @@ on early-init
    # 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