Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit ddb63e27 authored by Ethan Yonker's avatar Ethan Yonker
Browse files

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
parent a9dd9f03
Loading
Loading
Loading
Loading
+20 −3
Original line number Diff line number Diff line
@@ -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;
	}

	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 pwret = cryptfs_check_passwd(cPassword);
		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++) {
+35 −0
Original line number Diff line number Diff line
@@ -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;
+1 −0
Original line number Diff line number Diff line
@@ -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