Merge "Add timeout for fsck on untrusted media"

This commit is contained in:
Treehugger Robot 2022-01-26 08:55:08 +00:00 committed by Gerrit Code Review
commit 313e8556a6
4 changed files with 70 additions and 6 deletions

View file

@ -754,7 +754,53 @@ status_t ForkExecvp(const std::vector<std::string>& args, std::vector<std::strin
return OK; return OK;
} }
pid_t ForkExecvpAsync(const std::vector<std::string>& args) { status_t ForkExecvpTimeout(const std::vector<std::string>& args, std::chrono::seconds timeout,
char* context) {
int status;
pid_t wait_timeout_pid = fork();
if (wait_timeout_pid == 0) {
pid_t pid = ForkExecvpAsync(args, context);
if (pid == -1) {
_exit(EXIT_FAILURE);
}
pid_t timer_pid = fork();
if (timer_pid == 0) {
sleep(timeout.count());
_exit(ETIMEDOUT);
}
if (timer_pid == -1) {
PLOG(ERROR) << "fork in ForkExecvpAsync_timeout";
kill(pid, SIGTERM);
_exit(EXIT_FAILURE);
}
pid_t finished = wait(&status);
if (finished == pid) {
kill(timer_pid, SIGTERM);
} else {
kill(pid, SIGTERM);
}
if (!WIFEXITED(status)) {
_exit(ECHILD);
}
_exit(WEXITSTATUS(status));
}
if (waitpid(wait_timeout_pid, &status, 0) == -1) {
PLOG(ERROR) << "waitpid in ForkExecvpAsync_timeout";
return -errno;
}
if (!WIFEXITED(status)) {
LOG(ERROR) << "Process did not exit normally, status: " << status;
return -ECHILD;
}
if (WEXITSTATUS(status)) {
LOG(ERROR) << "Process exited with code: " << WEXITSTATUS(status);
return WEXITSTATUS(status);
}
return OK;
}
pid_t ForkExecvpAsync(const std::vector<std::string>& args, char* context) {
auto argv = ConvertToArgv(args); auto argv = ConvertToArgv(args);
pid_t pid = fork(); pid_t pid = fork();
@ -762,6 +808,12 @@ pid_t ForkExecvpAsync(const std::vector<std::string>& args) {
close(STDIN_FILENO); close(STDIN_FILENO);
close(STDOUT_FILENO); close(STDOUT_FILENO);
close(STDERR_FILENO); close(STDERR_FILENO);
if (context) {
if (setexeccon(context)) {
LOG(ERROR) << "Failed to setexeccon in ForkExecvpAsync";
abort();
}
}
execvp(argv[0], const_cast<char**>(argv.data())); execvp(argv[0], const_cast<char**>(argv.data()));
PLOG(ERROR) << "exec in ForkExecvpAsync"; PLOG(ERROR) << "exec in ForkExecvpAsync";

View file

@ -38,6 +38,8 @@ static const char* kVoldAppDataIsolationEnabled = "persist.sys.vold_app_data_iso
static const char* kExternalStorageSdcardfs = "external_storage.sdcardfs.enabled"; static const char* kExternalStorageSdcardfs = "external_storage.sdcardfs.enabled";
static const char* kFuseBpfEnabled = "persist.sys.fuse.bpf.enable"; static const char* kFuseBpfEnabled = "persist.sys.fuse.bpf.enable";
static constexpr std::chrono::seconds kUntrustedFsckSleepTime(45);
/* SELinux contexts used depending on the block device type */ /* SELinux contexts used depending on the block device type */
extern char* sBlkidContext; extern char* sBlkidContext;
extern char* sBlkidUntrustedContext; extern char* sBlkidUntrustedContext;
@ -107,8 +109,10 @@ status_t ReadMetadataUntrusted(const std::string& path, std::string* fsType, std
/* Returns either WEXITSTATUS() status, or a negative errno */ /* Returns either WEXITSTATUS() status, or a negative errno */
status_t ForkExecvp(const std::vector<std::string>& args, status_t ForkExecvp(const std::vector<std::string>& args,
std::vector<std::string>* output = nullptr, char* context = nullptr); std::vector<std::string>* output = nullptr, char* context = nullptr);
status_t ForkExecvpTimeout(const std::vector<std::string>& args, std::chrono::seconds timeout,
char* context = nullptr);
pid_t ForkExecvpAsync(const std::vector<std::string>& args); pid_t ForkExecvpAsync(const std::vector<std::string>& args, char* context = nullptr);
/* Gets block device size in bytes */ /* Gets block device size in bytes */
status_t GetBlockDevSize(int fd, uint64_t* size); status_t GetBlockDevSize(int fd, uint64_t* size);

View file

@ -44,7 +44,7 @@ status_t Check(const std::string& source) {
cmd.push_back("-y"); cmd.push_back("-y");
cmd.push_back(source); cmd.push_back(source);
int rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext); int rc = ForkExecvpTimeout(cmd, kUntrustedFsckSleepTime, sFsckUntrustedContext);
if (rc == 0) { if (rc == 0) {
LOG(INFO) << "Check OK"; LOG(INFO) << "Check OK";
return 0; return 0;

View file

@ -68,10 +68,9 @@ status_t Check(const std::string& source) {
cmd.push_back(source); cmd.push_back(source);
// Fat devices are currently always untrusted // Fat devices are currently always untrusted
rc = ForkExecvp(cmd, nullptr, sFsckUntrustedContext); rc = ForkExecvpTimeout(cmd, kUntrustedFsckSleepTime, sFsckUntrustedContext);
if (rc < 0) { if (rc < 0) {
LOG(ERROR) << "Filesystem check failed due to logwrap error"; LOG(ERROR) << "Filesystem check failed due to fork error";
errno = EIO; errno = EIO;
return -1; return -1;
} }
@ -81,6 +80,10 @@ status_t Check(const std::string& source) {
LOG(INFO) << "Filesystem check completed OK"; LOG(INFO) << "Filesystem check completed OK";
return 0; return 0;
case 1:
LOG(INFO) << "Failed to check filesystem";
return -1;
case 2: case 2:
LOG(ERROR) << "Filesystem check failed (not a FAT filesystem)"; LOG(ERROR) << "Filesystem check failed (not a FAT filesystem)";
errno = ENODATA; errno = ENODATA;
@ -100,6 +103,11 @@ status_t Check(const std::string& source) {
errno = ENODATA; errno = ENODATA;
return -1; return -1;
case ETIMEDOUT:
LOG(ERROR) << "Filesystem check timed out";
errno = ETIMEDOUT;
return -1;
default: default:
LOG(ERROR) << "Filesystem check failed (unknown exit code " << rc << ")"; LOG(ERROR) << "Filesystem check failed (unknown exit code " << rc << ")";
errno = EIO; errno = EIO;