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
(cherry picked from commit 7896e7adcc
)
This commit is contained in:
parent
4ca51f2e08
commit
f66b74f820
3 changed files with 56 additions and 23 deletions
|
@ -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,34 +1063,59 @@ 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) {
|
||||
// TODO (b/122850122): support this in gsi
|
||||
if (fscrypt_is_native() && !android::gsi::IsGsiRunning()) {
|
||||
LOG(ERROR) << "Rebooting into recovery, reason: " << reboot_reason;
|
||||
if (auto result = reboot_into_recovery(
|
||||
{"--prompt_and_wipe_data", "--reason="s + reboot_reason});
|
||||
!result) {
|
||||
LOG(FATAL) << "Could not reboot into recovery: " << result.error();
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
|
||||
}
|
||||
function(StringPrintf("Exec service failed, status %d", siginfo.si_status));
|
||||
}
|
||||
});
|
||||
if (auto result = (*service)->ExecStart(); !result) {
|
||||
return Error() << "Could not start exec service: " << result.error();
|
||||
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) << message << ": Rebooting into recovery, reason: " << reboot_reason;
|
||||
if (auto result = reboot_into_recovery(
|
||||
{"--prompt_and_wipe_data", "--reason="s + reboot_reason});
|
||||
!result) {
|
||||
LOG(FATAL) << "Could not reboot into recovery: " << result.error();
|
||||
}
|
||||
} else {
|
||||
LOG(ERROR) << "Failure (reboot suppressed): " << reboot_reason;
|
||||
}
|
||||
};
|
||||
|
||||
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) {
|
||||
if (!is_file_crypto()) return {};
|
||||
|
||||
|
@ -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}}},
|
||||
|
|
|
@ -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();
|
||||
|
|
|
@ -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);
|
||||
|
|
Loading…
Reference in a new issue