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

Commit 7896e7ad authored by Tom Cherry's avatar Tom Cherry
Browse files

init: add exec_reboot_on_failure builtin

Add exec_reboot_on_failure builtin and refactor the VDC commands that
had similar functionality.  These will now also reboot in the case
that the program cannot be found or run for any reason.

Test: boots normally, reboots if command is not found or if command
      returns status '1'

Change-Id: I1c99498c2b741512a50188e1a325c25e9ec8fba0
parent a9ffef27
Loading
Loading
Loading
Loading
+46 −23
Original line number Diff line number Diff line
@@ -80,6 +80,7 @@
using namespace std::literals::string_literals;

using android::base::Basename;
using android::base::StringPrintf;
using android::base::unique_fd;
using android::fs_mgr::Fstab;
using android::fs_mgr::ReadFstabFromFile;
@@ -1062,17 +1063,45 @@ static bool is_file_crypto() {
    return android::base::GetProperty("ro.crypto.type", "") == "file";
}

static Result<void> ExecWithRebootOnFailure(const std::string& reboot_reason,
                                            const BuiltinArguments& args) {
    auto service = Service::MakeTemporaryOneshotService(args.args);
static Result<void> ExecWithFunctionOnFailure(const std::vector<std::string>& args,
                                              std::function<void(const std::string&)> function) {
    auto service = Service::MakeTemporaryOneshotService(args);
    if (!service) {
        return Error() << "Could not create exec service: " << service.error();
        function("MakeTemporaryOneshotService failed: " + service.error().message());
    }
    (*service)->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
    (*service)->AddReapCallback([function](const siginfo_t& siginfo) {
        if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
            function(StringPrintf("Exec service failed, status %d", siginfo.si_status));
        }
    });
    if (auto result = (*service)->ExecStart(); !result) {
        function("ExecStart failed: " + result.error().message());
    }
    ServiceList::GetInstance().AddService(std::move(*service));
    return {};
}

static Result<void> do_exec_reboot_on_failure(const BuiltinArguments& args) {
    auto reboot_reason = args[1];
    auto reboot = [reboot_reason](const std::string& message) {
        property_set(LAST_REBOOT_REASON_PROPERTY, reboot_reason);
        sync();
        LOG(FATAL) << message << ": rebooting into bootloader, reason: " << reboot_reason;
    };

    std::vector<std::string> remaining_args(args.begin() + 1, args.end());
    remaining_args[0] = args[0];

    return ExecWithFunctionOnFailure(remaining_args, reboot);
}

static Result<void> ExecVdcRebootOnFailure(const std::string& vdc_arg) {
    auto reboot_reason = vdc_arg + "_failed";

    auto reboot = [reboot_reason](const std::string& message) {
        // TODO (b/122850122): support this in gsi
        if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
                LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
            LOG(ERROR) << message << ": Rebooting into recovery, reason: " << reboot_reason;
            if (auto result = reboot_into_recovery(
                        {"--prompt_and_wipe_data", "--reason="s + reboot_reason});
                !result) {
@@ -1081,13 +1110,10 @@ static Result<void> ExecWithRebootOnFailure(const std::string& reboot_reason,
        } else {
            LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
        }
        }
    });
    if (auto result = (*service)->ExecStart(); !result) {
        return Error() << "Could not start exec service: " << result.error();
    }
    ServiceList::GetInstance().AddService(std::move(*service));
    return {};
    };

    std::vector<std::string> args = {"exec", "/system/bin/vdc", "--wait", "cryptfs", vdc_arg};
    return ExecWithFunctionOnFailure(args, reboot);
}

static Result<void> do_installkey(const BuiltinArguments& args) {
@@ -1097,15 +1123,11 @@ static Result<void> do_installkey(const BuiltinArguments& args) {
    if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
        return ErrnoError() << "Failed to create " << unencrypted_dir;
    }
    return ExecWithRebootOnFailure(
        "enablefilecrypto_failed",
        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "enablefilecrypto"}, args.context});
    return ExecVdcRebootOnFailure("enablefilecrypto");
}

static Result<void> do_init_user0(const BuiltinArguments& args) {
    return ExecWithRebootOnFailure(
        "init_user0_failed",
        {{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"}, args.context});
    return ExecVdcRebootOnFailure("init_user0");
}

static Result<void> do_mark_post_data(const BuiltinArguments& args) {
@@ -1180,6 +1202,7 @@ const BuiltinFunctionMap& GetBuiltinFunctionMap() {
        {"enable",                  {1,     1,    {false,  do_enable}}},
        {"exec",                    {1,     kMax, {false,  do_exec}}},
        {"exec_background",         {1,     kMax, {false,  do_exec_background}}},
        {"exec_reboot_on_failure",  {2,     kMax, {false,  do_exec_reboot_on_failure}}},
        {"exec_start",              {1,     1,    {false,  do_exec_start}}},
        {"export",                  {2,     2,    {false,  do_export}}},
        {"hostname",                {1,     1,    {true,   do_hostname}}},
+9 −0
Original line number Diff line number Diff line
@@ -81,6 +81,15 @@ Result<void> check_exec_background(const BuiltinArguments& args) {
    return check_exec(std::move(args));
}

Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args) {
    BuiltinArguments remaining_args(args.context);

    remaining_args.args = std::vector<std::string>(args.begin() + 1, args.end());
    remaining_args.args[0] = args[0];

    return check_exec(remaining_args);
}

Result<void> check_interface_restart(const BuiltinArguments& args) {
    if (auto result = IsKnownInterface(args[1]); !result) {
        return result.error();
+1 −0
Original line number Diff line number Diff line
@@ -25,6 +25,7 @@ namespace init {
Result<void> check_chown(const BuiltinArguments& args);
Result<void> check_exec(const BuiltinArguments& args);
Result<void> check_exec_background(const BuiltinArguments& args);
Result<void> check_exec_reboot_on_failure(const BuiltinArguments& args);
Result<void> check_interface_restart(const BuiltinArguments& args);
Result<void> check_interface_start(const BuiltinArguments& args);
Result<void> check_interface_stop(const BuiltinArguments& args);