Merge "If enablefilecrypto or init_user0 fails, reboot into recovery."

This commit is contained in:
Treehugger Robot 2018-02-15 21:16:42 +00:00 committed by Gerrit Code Review
commit 851803d3cf
4 changed files with 41 additions and 19 deletions

View file

@ -285,11 +285,8 @@ static Result<Success> do_mkdir(const BuiltinArguments& args) {
if (e4crypt_is_native()) {
if (e4crypt_set_directory_policy(args[1].c_str())) {
const std::vector<std::string> options = {
"--prompt_and_wipe_data",
"--reason=set_policy_failed:"s + args[1]};
reboot_into_recovery(options);
return Success();
reboot_into_recovery(
{"--prompt_and_wipe_data", "--reason=set_policy_failed:"s + args[1]});
}
}
return Success();
@ -987,6 +984,24 @@ static bool is_file_crypto() {
return android::base::GetProperty("ro.crypto.type", "") == "file";
}
static Result<Success> ExecWithRebootOnFailure(const std::string& reboot_reason,
const std::vector<std::string>& args) {
auto service = Service::MakeTemporaryOneshotService(args);
if (!service) {
return Error() << "Could not create exec service";
}
service->AddReapCallback([reboot_reason](const siginfo_t& siginfo) {
if (siginfo.si_code != CLD_EXITED || siginfo.si_status != 0) {
reboot_into_recovery({"--prompt_and_wipe_data", "--reason="s + reboot_reason});
}
});
if (auto result = service->ExecStart(); !result) {
return Error() << "Could not start exec service: " << result.error();
}
ServiceList::GetInstance().AddService(std::move(service));
return Success();
}
static Result<Success> do_installkey(const BuiltinArguments& args) {
if (!is_file_crypto()) return Success();
@ -994,15 +1009,13 @@ static Result<Success> do_installkey(const BuiltinArguments& args) {
if (!make_dir(unencrypted_dir, 0700) && errno != EEXIST) {
return ErrnoError() << "Failed to create " << unencrypted_dir;
}
std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
"enablefilecrypto"};
return do_exec({std::move(exec_args), args.context});
return ExecWithRebootOnFailure("enablefilecrypto_failed", {"exec", "/system/bin/vdc", "--wait",
"cryptfs", "enablefilecrypto"});
}
static Result<Success> do_init_user0(const BuiltinArguments& args) {
std::vector<std::string> exec_args = {"exec", "/system/bin/vdc", "--wait", "cryptfs",
"init_user0"};
return do_exec({std::move(exec_args), args.context});
return ExecWithRebootOnFailure("init_user0_failed",
{"exec", "/system/bin/vdc", "--wait", "cryptfs", "init_user0"});
}
const BuiltinFunctionMap::Map& BuiltinFunctionMap::map() const {

View file

@ -298,7 +298,7 @@ void Service::SetProcessAttributes() {
}
}
void Service::Reap() {
void Service::Reap(const siginfo_t& siginfo) {
if (!(flags_ & SVC_ONESHOT) || (flags_ & SVC_RESTART)) {
KillProcessGroup(SIGKILL);
}
@ -307,6 +307,10 @@ void Service::Reap() {
std::for_each(descriptors_.begin(), descriptors_.end(),
std::bind(&DescriptorInfo::Clean, std::placeholders::_1));
for (const auto& f : reap_callbacks_) {
f(siginfo);
}
if (flags_ & SVC_EXEC) UnSetExec();
if (flags_ & SVC_TEMPORARY) return;

View file

@ -17,6 +17,7 @@
#ifndef _INIT_SERVICE_H
#define _INIT_SERVICE_H
#include <signal.h>
#include <sys/resource.h>
#include <sys/types.h>
@ -81,7 +82,7 @@ class Service {
void Stop();
void Terminate();
void Restart();
void Reap();
void Reap(const siginfo_t& siginfo);
void DumpState() const;
void SetShutdownCritical() { flags_ |= SVC_SHUTDOWN_CRITICAL; }
bool IsShutdownCritical() const { return (flags_ & SVC_SHUTDOWN_CRITICAL) != 0; }
@ -89,6 +90,9 @@ class Service {
is_exec_service_running_ = false;
flags_ &= ~SVC_EXEC;
}
void AddReapCallback(std::function<void(const siginfo_t& siginfo)> callback) {
reap_callbacks_.emplace_back(std::move(callback));
}
static bool is_exec_service_running() { return is_exec_service_running_; }
@ -210,6 +214,8 @@ class Service {
std::vector<std::pair<int, rlimit>> rlimits_;
std::vector<std::string> args_;
std::vector<std::function<void(const siginfo_t& siginfo)>> reap_callbacks_;
};
class ServiceList {

View file

@ -84,16 +84,15 @@ static bool ReapOneProcess() {
}
}
auto status = siginfo.si_status;
if (WIFEXITED(status)) {
LOG(INFO) << name << " exited with status " << WEXITSTATUS(status) << wait_string;
} else if (WIFSIGNALED(status)) {
LOG(INFO) << name << " killed by signal " << WTERMSIG(status) << wait_string;
if (siginfo.si_code == CLD_EXITED) {
LOG(INFO) << name << " exited with status " << siginfo.si_status << wait_string;
} else {
LOG(INFO) << name << " received signal " << siginfo.si_status << wait_string;
}
if (!service) return true;
service->Reap();
service->Reap(siginfo);
if (service->flags() & SVC_TEMPORARY) {
ServiceList::GetInstance().RemoveService(*service);