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

Commit e9f4339d authored by Jiyong Park's avatar Jiyong Park Committed by android-build-merger
Browse files

Merge changes from topic "revert_move_bionic_to_apex" am: e0c7a8bb

am: 555b7ead

Change-Id: Ibdd191f5e6e4c7fc953bc39a050afa7b23c4335e
parents aec9eb01 555b7ead
Loading
Loading
Loading
Loading
+0 −82
Original line number Diff line number Diff line
@@ -1098,86 +1098,6 @@ static Result<Success> do_parse_apex_configs(const BuiltinArguments& args) {
    }
}

static Result<Success> bind_mount_file(const char* source, const char* mount_point,
                                       bool remount_private) {
    if (remount_private && mount(nullptr, mount_point, nullptr, MS_PRIVATE, nullptr) == -1) {
        return ErrnoError() << "Could not change " << mount_point << " to a private mount point";
    }
    if (mount(source, mount_point, nullptr, MS_BIND, nullptr) == -1) {
        return ErrnoError() << "Could not bind-mount " << source << " to " << mount_point;
    }
    return Success();
}

static Result<Success> bind_mount_bionic(const char* linker_source, const char* lib_dir_source,
                                         const char* linker_mount_point, const char* lib_mount_dir,
                                         bool remount_private) {
    if (access(linker_source, F_OK) != 0) {
        return Success();
    }
    if (auto result = bind_mount_file(linker_source, linker_mount_point, remount_private);
        !result) {
        return result;
    }
    for (auto libname : kBionicLibFileNames) {
        std::string mount_point = lib_mount_dir + libname;
        std::string source = lib_dir_source + libname;
        if (auto result = bind_mount_file(source.c_str(), mount_point.c_str(), remount_private);
            !result) {
            return result;
        }
    }
    return Success();
}

// The bootstrap bionic libs and the bootstrap linker are bind-mounted to
// the mount points for pre-apexd processes.
static Result<Success> do_prepare_bootstrap_bionic(const BuiltinArguments& args) {
    static bool prepare_bootstrap_bionic_done = false;
    if (prepare_bootstrap_bionic_done) {
        return Error() << "prepare_bootstrap_bionic was already executed. Cannot be executed again";
    }
    if (auto result = bind_mount_bionic(kBootstrapLinkerPath, kBootstrapBionicLibsDir,
                                        kLinkerMountPoint, kBionicLibsMountPointDir, false);
        !result) {
        return result;
    }
    if (auto result = bind_mount_bionic(kBootstrapLinkerPath64, kBootstrapBionicLibsDir64,
                                        kLinkerMountPoint64, kBionicLibsMountPointDir64, false);
        !result) {
        return result;
    }

    LOG(INFO) << "prepare_bootstrap_bionic done";
    prepare_bootstrap_bionic_done = true;
    return Success();
}

// The bionic libs and the dynamic linker from the runtime APEX are bind-mounted
// to the mount points. As a result, the previous mounts done by
// prepare_bootstrap_bionic become hidden.
static Result<Success> do_setup_runtime_bionic(const BuiltinArguments& args) {
    static bool setup_runtime_bionic_done = false;
    if (setup_runtime_bionic_done) {
        return Error() << "setup_runtime_bionic was already executed. Cannot be executed again";
    }
    if (auto result = bind_mount_bionic(kRuntimeLinkerPath, kRuntimeBionicLibsDir,
                                        kLinkerMountPoint, kBionicLibsMountPointDir, true);
        !result) {
        return result;
    }
    if (auto result = bind_mount_bionic(kRuntimeLinkerPath64, kRuntimeBionicLibsDir64,
                                        kLinkerMountPoint64, kBionicLibsMountPointDir64, true);
        !result) {
        return result;
    }

    ServiceList::GetInstance().MarkRuntimeAvailable();
    LOG(INFO) << "setup_runtime_bionic done";
    setup_runtime_bionic_done = true;
    return Success();
}

// Builtin-function-map start
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
    constexpr std::size_t kMax = std::numeric_limits<std::size_t>::max();
@@ -1216,7 +1136,6 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
        {"mount_all",               {1,     kMax, {false,  do_mount_all}}},
        {"mount",                   {3,     kMax, {false,  do_mount}}},
        {"parse_apex_configs",      {0,     0,    {false,  do_parse_apex_configs}}},
        {"prepare_bootstrap_bionic",{0,     0,    {false,  do_prepare_bootstrap_bionic}}},
        {"umount",                  {1,     1,    {false,  do_umount}}},
        {"readahead",               {1,     2,    {true,   do_readahead}}},
        {"restart",                 {1,     1,    {false,  do_restart}}},
@@ -1225,7 +1144,6 @@ const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {
        {"rm",                      {1,     1,    {true,   do_rm}}},
        {"rmdir",                   {1,     1,    {true,   do_rmdir}}},
        {"setprop",                 {2,     2,    {true,   do_setprop}}},
        {"setup_runtime_bionic",    {0,     0,    {false,  do_setup_runtime_bionic}}},
        {"setrlimit",               {3,     3,    {false,  do_setrlimit}}},
        {"start",                   {1,     1,    {false,  do_start}}},
        {"stop",                    {1,     1,    {false,  do_stop}}},
+1 −89
Original line number Diff line number Diff line
@@ -140,43 +140,6 @@ Result<Success> Service::SetUpMountNamespace() const {
    return Success();
}

Result<Success> Service::SetUpPreApexdMounts() const {
    // If a pre-apexd service is 're' launched after the runtime APEX is
    // available, unmount the linker and bionic libs which are currently
    // bind mounted to the files in the runtime APEX. This will reveal
    // the hidden mount points (targetting the bootstrap ones in the
    // system partition) which were setup before the runtime APEX was
    // started. Note that these unmounts are done in a separate mount namespace
    // for the process. It does not affect other processes including the init.
    if (pre_apexd_ && ServiceList::GetInstance().IsRuntimeAvailable()) {
        if (access(kLinkerMountPoint, F_OK) == 0) {
            if (umount(kLinkerMountPoint) == -1) {
                return ErrnoError() << "Could not umount " << kLinkerMountPoint;
            }
            for (const auto& libname : kBionicLibFileNames) {
                std::string mount_point = kBionicLibsMountPointDir + libname;
                if (umount(mount_point.c_str()) == -1) {
                    return ErrnoError() << "Could not umount " << mount_point;
                }
            }
        }

        if (access(kLinkerMountPoint64, F_OK) == 0) {
            if (umount(kLinkerMountPoint64) == -1) {
                return ErrnoError() << "Could not umount " << kLinkerMountPoint64;
            }
            for (const auto& libname : kBionicLibFileNames) {
                std::string mount_point = kBionicLibsMountPointDir64 + libname;
                std::string source = kBootstrapBionicLibsDir64 + libname;
                if (umount(mount_point.c_str()) == -1) {
                    return ErrnoError() << "Could not umount " << mount_point;
                }
            }
        }
    }
    return Success();
}

Result<Success> Service::SetUpPidNamespace() const {
    if (prctl(PR_SET_NAME, name_.c_str()) == -1) {
        return ErrnoError() << "Could not set name";
@@ -406,7 +369,7 @@ void Service::Reap(const siginfo_t& siginfo) {

    // If we crash > 4 times in 4 minutes, reboot into bootloader or set crashing property
    boot_clock::time_point now = boot_clock::now();
    if (((flags_ & SVC_CRITICAL) || !pre_apexd_) && !(flags_ & SVC_RESTART)) {
    if (((flags_ & SVC_CRITICAL) || classnames_.count("updatable")) && !(flags_ & SVC_RESTART)) {
        if (now < time_crashed_ + 4min) {
            if (++crash_count_ > 4) {
                if (flags_ & SVC_CRITICAL) {
@@ -966,14 +929,6 @@ Result<Success> Service::Start() {
        scon = *result;
    }

    if (!ServiceList::GetInstance().IsRuntimeAvailable() && !pre_apexd_) {
        // If this service is started before the runtime APEX gets 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;
    }

    LOG(INFO) << "starting service '" << name_ << "'...";

    pid_t pid = -1;
@@ -990,37 +945,6 @@ Result<Success> Service::Start() {
            LOG(FATAL) << "Service '" << name_ << "' could not enter namespaces: " << result.error();
        }

        // b/122559956: mount namespace is not cloned for the devices that don't support
        // the update of bionic libraries via APEX. In that case, because the bionic
        // libraries in the runtime APEX and the bootstrap bionic libraries are
        // identical, it doesn't matter which libs are used. This is also to avoid the
        // bug in sdcardfs which is triggered when we have multiple mount namespaces
        // across vold and the others. BIONIC_UPDATABLE shall be true only for the
        // devices where kernel has the fix for the sdcardfs bug (see the commit message
        // for the fix).
        static bool bionic_updatable =
                android::base::GetBoolProperty("ro.apex.bionic_updatable", false);

        if (bionic_updatable && pre_apexd_) {
            // pre-apexd process gets a private copy of the mount namespace.
            // However, this does not mean that mount/unmount events are not
            // shared across pre-apexd processes and post-apexd processes.
            // *Most* of the events are still shared because the propagation
            // type of / is set to 'shared'. (see `mount rootfs rootfs /shared
            // rec` in init.rc)
            //
            // This unsharing is required to not propagate the mount events
            // under /system/lib/{libc|libdl|libm}.so and /system/bin/linker(64)
            // whose propagation type is set to private. With this,
            // bind-mounting the bionic libs and the dynamic linker from the
            // runtime APEX to the mount points does not affect pre-apexd
            // processes which should use the bootstrap ones.
            if (unshare(CLONE_NEWNS) != 0) {
                LOG(FATAL) << "Creating a new mount namespace for service"
                           << " '" << name_ << "' failed: " << strerror(errno);
            }
        }

        if (namespace_flags_ & CLONE_NEWNS) {
            if (auto result = SetUpMountNamespace(); !result) {
                LOG(FATAL) << "Service '" << name_
@@ -1028,14 +952,6 @@ Result<Success> Service::Start() {
            }
        }

        // b/122559956: same as above
        if (bionic_updatable && pre_apexd_ && ServiceList::GetInstance().IsRuntimeAvailable()) {
            if (auto result = SetUpPreApexdMounts(); !result) {
                LOG(FATAL) << "Pre-apexd service '" << name_
                           << "' could not setup the mount points: " << result.error();
            }
        }

        if (namespace_flags_ & CLONE_NEWPID) {
            // This will fork again to run an init process inside the PID
            // namespace.
@@ -1408,10 +1324,6 @@ void ServiceList::MarkServicesUpdate() {
    delayed_service_names_.clear();
}

void ServiceList::MarkRuntimeAvailable() {
    runtime_available_ = true;
}

void ServiceList::DelayService(const Service& service) {
    if (services_update_finished_) {
        LOG(ERROR) << "Cannot delay the start of service '" << service.name()
+0 −25
Original line number Diff line number Diff line
@@ -62,24 +62,6 @@
namespace android {
namespace init {

static constexpr const char* kLinkerMountPoint = "/system/bin/linker";
static constexpr const char* kBootstrapLinkerPath = "/system/bin/linker";
static constexpr const char* kRuntimeLinkerPath = "/apex/com.android.runtime/bin/linker";

static constexpr const char* kBionicLibsMountPointDir = "/system/lib/";
static constexpr const char* kBootstrapBionicLibsDir = "/system/lib/";
static constexpr const char* kRuntimeBionicLibsDir = "/apex/com.android.runtime/lib/bionic/";

static constexpr const char* kLinkerMountPoint64 = "/system/bin/linker64";
static constexpr const char* kBootstrapLinkerPath64 = "/system/bin/linker64";
static constexpr const char* kRuntimeLinkerPath64 = "/apex/com.android.runtime/bin/linker64";

static constexpr const char* kBionicLibsMountPointDir64 = "/system/lib64/";
static constexpr const char* kBootstrapBionicLibsDir64 = "/system/lib64/";
static constexpr const char* kRuntimeBionicLibsDir64 = "/apex/com.android.runtime/lib64/bionic/";

static const std::vector<std::string> kBionicLibFileNames = {"libc.so", "libm.so", "libdl.so"};

class Service {
  public:
    Service(const std::string& name, Subcontext* subcontext_for_restart_commands,
@@ -142,7 +124,6 @@ class Service {
    std::optional<std::chrono::seconds> timeout_period() const { return timeout_period_; }
    const std::vector<std::string>& args() const { return args_; }
    bool is_updatable() const { return updatable_; }
    bool is_pre_apexd() const { return pre_apexd_; }

  private:
    using OptionParser = Result<Success> (Service::*)(std::vector<std::string>&& args);
@@ -151,7 +132,6 @@ class Service {
    Result<Success> SetUpMountNamespace() const;
    Result<Success> SetUpPidNamespace() const;
    Result<Success> EnterNamespaces() const;
    Result<Success> SetUpPreApexdMounts() const;
    void NotifyStateChange(const std::string& new_state) const;
    void StopOrReset(int how);
    void ZapStdio() const;
@@ -262,8 +242,6 @@ class Service {
    std::vector<std::string> args_;

    std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;

    bool pre_apexd_ = false;
};

class ServiceList {
@@ -306,16 +284,13 @@ class ServiceList {
    const std::vector<Service*> services_in_shutdown_order() const;

    void MarkServicesUpdate();
    void MarkRuntimeAvailable();
    bool IsServicesUpdated() const { return services_update_finished_; }
    bool IsRuntimeAvailable() const { return runtime_available_; }
    void DelayService(const Service& service);

  private:
    std::vector<std::unique_ptr<Service>> services_;

    bool services_update_finished_ = false;
    bool runtime_available_ = false;
    std::vector<std::string> delayed_service_names_;
};

+5 −16
Original line number Diff line number Diff line
@@ -12,12 +12,6 @@ import /init.usb.configfs.rc
import /init.${ro.zygote}.rc

on early-init
    # Mount shared so changes propagate into child namespaces
    # Do this before other processes are started from init. Otherwise,
    # processes launched while the propagation type of / is 'private'
    # won't get mount events from others.
    mount rootfs rootfs / shared rec

    # Set init and its forked children's oom_adj.
    write /proc/1/oom_score_adj -1000

@@ -46,8 +40,6 @@ on early-init
    # cgroup for system_server and surfaceflinger
    mkdir /dev/memcg/system 0550 system system

    prepare_bootstrap_bionic

    start ueventd

on init
@@ -352,6 +344,8 @@ on post-fs
    # Once everything is setup, no need to modify /.
    # The bind+remount combination allows this to work in containers.
    mount rootfs rootfs / remount bind ro nodev
    # Mount shared so changes propagate into child namespaces
    mount rootfs rootfs / shared rec
    # Mount default storage into root namespace
    mount none /mnt/runtime/default /storage bind rec
    mount none none /storage slave rec
@@ -587,14 +581,6 @@ on post-fs-data
    # Check any timezone data in /data is newer than the copy in the runtime module, delete if not.
    exec - system system -- /system/bin/tzdatacheck /apex/com.android.runtime/etc/tz /data/misc/zoneinfo

    # Wait for apexd to finish activating APEXes before starting more processes.
    # This certainly reduces the parallelism but is required to make as many processes
    # as possible to use the bionic libs from the runtime APEX. This takes less than 50ms
    # so the impact on the booting time is not significant.
    wait_for_prop apexd.status ready
    setup_runtime_bionic
    parse_apex_configs

    # If there is no post-fs-data action in the init.<device>.rc file, you
    # must uncomment this line, otherwise encrypted filesystems
    # won't work.
@@ -816,3 +802,6 @@ on property:ro.debuggable=1
service flash_recovery /system/bin/install-recovery.sh
    class main
    oneshot

on property:apexd.status=ready
    parse_apex_configs