Timeout for decrypt
Sometimes, usually because of proprietary binaries related to keymaster, decrypt will hang waiting for the keymaster to initialize forever. This patch enables a timeout so that we don't get stuck trying to decrypt forever. A timeout is especially important when dealing with the default password because the user has no option to cancel when TWRP tries to decrypt. NOTE: This patch only adds a timeout for FDE. FBE will require some special handling because we need access to some static data and that data is not available across a fork. Special thanks to nkk71 for cleaning up some issues in my patch set. Change-Id: Iccf2fe769ac27a7dcd6bfebfe7d2e9eddd034308
This commit is contained in:
+20
-3
@@ -1513,7 +1513,7 @@ void TWPartitionManager::Post_Decrypt(const string& Block_Device) {
|
||||
|
||||
int TWPartitionManager::Decrypt_Device(string Password) {
|
||||
#ifdef TW_INCLUDE_CRYPTO
|
||||
char crypto_state[PROPERTY_VALUE_MAX], crypto_blkdev[PROPERTY_VALUE_MAX], cPassword[255];
|
||||
char crypto_state[PROPERTY_VALUE_MAX], crypto_blkdev[PROPERTY_VALUE_MAX];
|
||||
std::vector<TWPartition*>::iterator iter;
|
||||
|
||||
// Mount any partitions that need to be mounted for decrypt
|
||||
@@ -1549,8 +1549,25 @@ int TWPartitionManager::Decrypt_Device(string Password) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
strcpy(cPassword, Password.c_str());
|
||||
int pwret = cryptfs_check_passwd(cPassword);
|
||||
int pwret = -1;
|
||||
pid_t pid = fork();
|
||||
if (pid < 0) {
|
||||
LOGERR("fork failed\n");
|
||||
return -1;
|
||||
} else if (pid == 0) {
|
||||
// Child process
|
||||
char cPassword[255];
|
||||
strcpy(cPassword, Password.c_str());
|
||||
int ret = cryptfs_check_passwd(cPassword);
|
||||
exit(ret);
|
||||
} else {
|
||||
// Parent
|
||||
int status;
|
||||
if (TWFunc::Wait_For_Child_Timeout(pid, &status, "Decrypt", 30))
|
||||
pwret = -1;
|
||||
else
|
||||
pwret = WEXITSTATUS(status) ? -1 : 0;
|
||||
}
|
||||
|
||||
// Unmount any partitions that were needed for decrypt
|
||||
for (iter = Partitions.begin(); iter != Partitions.end(); iter++) {
|
||||
|
||||
@@ -142,6 +142,41 @@ int TWFunc::Wait_For_Child(pid_t pid, int *status, string Child_Name) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
int TWFunc::Wait_For_Child_Timeout(pid_t pid, int *status, const string& Child_Name, int timeout) {
|
||||
pid_t retpid = waitpid(pid, status, WNOHANG);
|
||||
for (; retpid == 0 && timeout; --timeout) {
|
||||
sleep(1);
|
||||
retpid = waitpid(pid, status, WNOHANG);
|
||||
}
|
||||
if (retpid == 0 && timeout == 0) {
|
||||
LOGERR("%s took too long, killing process\n", Child_Name.c_str());
|
||||
kill(pid, SIGKILL);
|
||||
int died = 0;
|
||||
for (timeout = 5; retpid == 0 && timeout; --timeout) {
|
||||
sleep(1);
|
||||
retpid = waitpid(pid, status, WNOHANG);
|
||||
}
|
||||
if (retpid)
|
||||
LOGINFO("Child process killed successfully\n");
|
||||
else
|
||||
LOGINFO("Child process took too long to kill, may be a zombie process\n");
|
||||
return -1;
|
||||
} else if (retpid > 0) {
|
||||
if (WIFSIGNALED(*status)) {
|
||||
gui_msg(Msg(msg::kError, "pid_signal={1} process ended with signal: {2}")(Child_Name)(WTERMSIG(*status))); // Seg fault or some other non-graceful termination
|
||||
return -1;
|
||||
}
|
||||
} else if (retpid < 0) { // no PID returned
|
||||
if (errno == ECHILD)
|
||||
LOGERR("%s no child process exist\n", Child_Name.c_str());
|
||||
else {
|
||||
LOGERR("%s Unexpected error %d\n", Child_Name.c_str(), errno);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
bool TWFunc::Path_Exists(string Path) {
|
||||
// Check to see if the Path exists
|
||||
struct stat st;
|
||||
|
||||
@@ -52,6 +52,7 @@ public:
|
||||
static int Exec_Cmd(const string& cmd, string &result); //execute a command and return the result as a string by reference
|
||||
static int Exec_Cmd(const string& cmd); //execute a command
|
||||
static int Wait_For_Child(pid_t pid, int *status, string Child_Name); // Waits for pid to exit and checks exit status
|
||||
static int Wait_For_Child_Timeout(pid_t pid, int *status, const string& Child_Name, int timeout); // Waits for a pid to exit until the timeout is hit. If timeout is hit, kill the chilld.
|
||||
static bool Path_Exists(string Path); // Returns true if the path exists
|
||||
static Archive_Type Get_File_Type(string fn); // Determines file type, 0 for unknown, 1 for gzip, 2 for OAES encrypted
|
||||
static int Try_Decrypting_File(string fn, string password); // -1 for some error, 0 for failed to decrypt, 1 for decrypted, 3 for decrypted and found gzip format
|
||||
|
||||
Reference in New Issue
Block a user