Merge "Add timeout for fsck on untrusted media"
This commit is contained in:
commit
313e8556a6
4 changed files with 70 additions and 6 deletions
54
Utils.cpp
54
Utils.cpp
|
@ -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";
|
||||||
|
|
6
Utils.h
6
Utils.h
|
@ -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);
|
||||||
|
|
|
@ -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;
|
||||||
|
|
14
fs/Vfat.cpp
14
fs/Vfat.cpp
|
@ -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;
|
||||||
|
|
Loading…
Reference in a new issue