decrypt: AOSP 10 requires the use of fscrypt

fscrypt aosp doc: https://source.android.com/security/encryption/file-based
kernel fscrypt doc: https://www.kernel.org/doc/html/v4.18/filesystems/fscrypt.html

This commit implements the ability for TWRP to use fscrypt to decrypt
files on the fscrypt implementation. It has been implemented mostly
in a new successor library to e4crypt called libtwrpfscrypt. Most of the
code was ported from AOSP vold.

Notable updates include:
 - updated policy storage by libtar
 - lookup of fbe policies by libtwrpfscrypt
 - threaded keystore operations

Big thanks to Dees_Troy for the initial trailblazing
of encryption in TWRP.

Change-Id: I69cd2eba3693a9914e00213d4943229635d0cdae
diff --git a/partition.cpp b/partition.cpp
index 2d61964..183283d 100755
--- a/partition.cpp
+++ b/partition.cpp
@@ -1,5 +1,5 @@
 /*
-	Copyright 2013 to 2017 TeamWin
+	Copyright 2013 to 2020 TeamWin
 	This file is part of TWRP/TeamWin Recovery Project.
 
 	TWRP is free software: you can redistribute it and/or modify
@@ -19,17 +19,21 @@
 #include <stdio.h>
 #include <stdlib.h>
 #include <string.h>
-#include <sys/stat.h>
-#include <sys/vfs.h>
+
 #include <sys/mount.h>
+#include <sys/param.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+#include <sys/vfs.h>
 #include <unistd.h>
 #include <dirent.h>
-#include <libgen.h>
-#include <zlib.h>
-#include <iostream>
-#include <sstream>
-#include <sys/param.h>
 #include <fcntl.h>
+#include <grp.h>
+#include <iostream>
+#include <libgen.h>
+#include <pwd.h>
+#include <zlib.h>
+#include <sstream>
 
 #include "cutils/properties.h"
 #include "libblkid/include/blkid.h"
@@ -138,7 +142,6 @@
 	TWFLAG_LENGTH,
 	TWFLAG_MOUNTTODECRYPT,
 	TWFLAG_REMOVABLE,
-	TWFLAG_RETAINLAYOUTVERSION,
 	TWFLAG_SETTINGSSTORAGE,
 	TWFLAG_STORAGE,
 	TWFLAG_STORAGENAME,
@@ -183,7 +186,6 @@
 	{ "length=",                TWFLAG_LENGTH },
 	{ "mounttodecrypt",         TWFLAG_MOUNTTODECRYPT },
 	{ "removable",              TWFLAG_REMOVABLE },
-	{ "retainlayoutversion",    TWFLAG_RETAINLAYOUTVERSION },
 	{ "settingsstorage",        TWFLAG_SETTINGSSTORAGE },
 	{ "storage",                TWFLAG_STORAGE },
 	{ "storagename=",           TWFLAG_STORAGENAME },
@@ -259,7 +261,6 @@
 	Mount_Options = "";
 	Format_Block_Size = 0;
 	Ignore_Blkid = false;
-	Retain_Layout_Version = false;
 	Crypto_Key_Location = "";
 	MTP_Storage_ID = 0;
 	Can_Flash_Img = false;
@@ -665,16 +666,10 @@
 	char crypto_blkdev[255];
 	property_get("ro.crypto.fs_crypto_blkdev", crypto_blkdev, "error");
 	if (strcmp(crypto_blkdev, "error") != 0) {
-		DataManager::SetValue(TW_IS_DECRYPTED, 1);
-		Is_Encrypted = true;
-		Is_Decrypted = true;
-		if (Key_Directory.empty())
-			Is_FBE = false;
-		else
-			Is_FBE = true;
-		DataManager::SetValue(TW_IS_FBE, 0);
+		Set_FBE_Status();
 		Decrypted_Block_Device = crypto_blkdev;
 		LOGINFO("Data already decrypted, new block device: '%s'\n", crypto_blkdev);
+		DataManager::SetValue(TW_IS_ENCRYPTED, 0);
 	} else if (!Mount(false)) {
 		if (Is_Present) {
 			if (Key_Directory.empty()) {
@@ -685,7 +680,6 @@
 					Can_Be_Mounted = false;
 					Current_File_System = "emmc";
 					Setup_Image();
-					DataManager::SetValue(TW_IS_ENCRYPTED, 1);
 					DataManager::SetValue(TW_CRYPTO_PWTYPE, cryptfs_get_password_type());
 					DataManager::SetValue(TW_CRYPTO_PASSWORD, "");
 					DataManager::SetValue("tw_crypto_display", "");
@@ -700,7 +694,7 @@
 			LOGERR("Primary block device '%s' for mount point '%s' is not present!\n", Primary_Block_Device.c_str(), Mount_Point.c_str());
 		}
 	} else {
-
+		Set_FBE_Status();
 		if (!Decrypt_FBE_DE()) {
 			char wrappedvalue[PROPERTY_VALUE_MAX];
 			property_get("fbe.data.wrappedkey", wrappedvalue, "");
@@ -715,10 +709,12 @@
 				}
 			}
 		}
+		DataManager::SetValue(TW_IS_ENCRYPTED, 0);
 	}
 	if (datamedia && (!Is_Encrypted || (Is_Encrypted && Is_Decrypted))) {
 		Setup_Data_Media();
-		Recreate_Media_Folder();
+		if (!TWFunc::Is_Mount_Wiped("/data"))
+			Recreate_Media_Folder();
 	}
 #else
 	if (datamedia) {
@@ -728,8 +724,22 @@
 #endif
 }
 
+void TWPartition::Set_FBE_Status() {
+	DataManager::SetValue(TW_IS_DECRYPTED, 1);
+	Is_Encrypted = true;
+	Is_Decrypted = true;
+	LOGINFO("Setup_Data_Partition::Key_Directory::%s\n", Key_Directory.c_str());
+	if (Key_Directory.empty()) {
+		Is_FBE = false;
+		DataManager::SetValue(TW_IS_FBE, 0);
+	} else {
+		Is_FBE = true;
+		DataManager::SetValue(TW_IS_FBE, 1);
+	}
+}
+
 bool TWPartition::Decrypt_FBE_DE() {
-if (TWFunc::Path_Exists("/data/unencrypted/key/version")) {
+	if (TWFunc::Path_Exists("/data/unencrypted/key/version")) {
 		DataManager::SetValue(TW_IS_FBE, 1);
 		LOGINFO("File Based Encryption is present\n");
 #ifdef TW_INCLUDE_FBE
@@ -737,6 +747,7 @@
 		ExcludeAll(Mount_Point + "/unencrypted");
 		//ExcludeAll(Mount_Point + "/system/users/0"); // we WILL need to retain some of this if multiple users are present or we just need to delete more folders for the extra users somewhere else
 		ExcludeAll(Mount_Point + "/misc/vold/user_keys");
+		ExcludeAll(Mount_Point + "/misc/vold/volume_keys");
 		//ExcludeAll(Mount_Point + "/system_ce");
 		//ExcludeAll(Mount_Point + "/system_de");
 		//ExcludeAll(Mount_Point + "/misc_ce");
@@ -752,6 +763,8 @@
 		ExcludeAll(Mount_Point + "/misc/keystore");
 		ExcludeAll(Mount_Point + "/drm/kek.dat");
 		ExcludeAll(Mount_Point + "/system_de/0/spblob"); // contains data needed to decrypt pixel 2
+		ExcludeAll(Mount_Point + "/per_boot"); // removed each boot by init 
+
 		int retry_count = 3;
 		while (!Decrypt_DE() && --retry_count)
 			usleep(2000);
@@ -761,7 +774,6 @@
 			Is_Decrypted = false;
 			Is_FBE = true;
 			DataManager::SetValue(TW_IS_FBE, 1);
-			DataManager::SetValue(TW_IS_ENCRYPTED, 1);
 			string filename;
 			int pwd_type = Get_Password_Type(0, filename);
 			if (pwd_type < 0) {
@@ -936,9 +948,6 @@
 		case TWFLAG_REMOVABLE:
 			Removable = val;
 			break;
-		case TWFLAG_RETAINLAYOUTVERSION:
-			Retain_Layout_Version = val;
-			break;
 		case TWFLAG_SETTINGSSTORAGE:
 			Is_Settings_Storage = val;
 			if (Is_Settings_Storage)
@@ -1182,7 +1191,6 @@
 		DataManager::SetValue("tw_has_data_media", 1);
 		backup_exclusions.add_absolute_dir("/data/data/com.google.android.music/files");
 		wipe_exclusions.add_absolute_dir(Mount_Point + "/misc/vold"); // adopted storage keys
-		ExcludeAll(Mount_Point + "/.layout_version");
 		ExcludeAll(Mount_Point + "/system/storage.xml");
 	} else {
 		if (Mount(true) && TWFunc::Path_Exists(Mount_Point + "/media/0")) {
@@ -1583,7 +1591,7 @@
 		mkdir("/system", 0755);
 		mount("/system_root/system", "/system", "auto", MS_BIND, NULL);
 	}
- #endif
+#endif
 	return true;
 }
 
@@ -1650,7 +1658,7 @@
 bool TWPartition::Wipe(string New_File_System) {
 	bool wiped = false, update_crypt = false, recreate_media = true;
 	int check;
-	string Layout_Filename = Mount_Point + "/.layout_version";
+	fscrypt_encryption_policy policy;
 
 	if (!Can_Be_Wiped) {
 		gui_msg(Msg(msg::kError, "cannot_wipe=Partition {1} cannot be wiped.")(Display_Name));
@@ -1660,13 +1668,13 @@
 	if (Mount_Point == "/cache")
 		Log_Offset = 0;
 
-	if (Retain_Layout_Version && Mount(false) && TWFunc::Path_Exists(Layout_Filename))
-		TWFunc::copy_file(Layout_Filename, "/.layout_version", 0600);
-	else
-		unlink("/.layout_version");
-
 	if (Has_Data_Media && Current_File_System == New_File_System) {
 		wiped = Wipe_Data_Without_Wiping_Media();
+		if (Mount_Point == "/data" && TWFunc::get_cache_dir() == AB_CACHE_DIR && !TWFunc::Is_Mount_Wiped("/data")) {
+			bool created = Recreate_AB_Cache_Dir(policy);
+			if (created)
+				gui_msg(Msg(msg::kWarning, "fbe_wipe_msg=WARNING: {1} wiped. FBE device should be booted into Android and not Recovery to set initial FBE policy after wipe.")(TWFunc::get_cache_dir()));
+		}
 		recreate_media = false;
 	} else {
 		DataManager::GetValue(TW_RM_RF_VAR, check);
@@ -1689,19 +1697,13 @@
 			wiped = Wipe_NTFS();
 		else {
 			LOGERR("Unable to wipe '%s' -- unknown file system '%s'\n", Mount_Point.c_str(), New_File_System.c_str());
-			unlink("/.layout_version");
 			return false;
 		}
 		update_crypt = wiped;
+		update_crypt = false;
 	}
 
 	if (wiped) {
-		if (Mount_Point == "/cache")
-			DataManager::Output_Version();
-
-		if (TWFunc::Path_Exists("/.layout_version") && Mount(false))
-			TWFunc::copy_file("/.layout_version", Layout_Filename, 0600);
-
 		if (update_crypt) {
 			Setup_File_System(false);
 			if (Is_Encrypted && !Is_Decrypted) {
@@ -1716,11 +1718,8 @@
 			}
 		}
 
-		if (Has_Data_Media && recreate_media) {
-			Recreate_Media_Folder();
-		}
-		if (Is_Storage && Mount(false))
-			PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
+		// if (Is_Storage && Mount(false))
+			// PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
 	}
 
 	return wiped;
@@ -2010,10 +2009,10 @@
 		gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
 		return false;
 	}
-	if (!UnMount(true))
-		goto exit;
 
 #ifdef TW_INCLUDE_CRYPTO
+	if (!UnMount(true))
+		return false;
 	if (Is_Decrypted && !Decrypted_Block_Device.empty()) {
 		if (delete_crypto_blk_dev((char*)("userdata")) != 0) {
 			LOGERR("Error deleting crypto block device, continuing anyway.\n");
@@ -2026,14 +2025,16 @@
 	Is_Encrypted = false;
 	if (Wipe(Fstab_File_System)) {
 		Has_Data_Media = Save_Data_Media;
-		if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
-			Recreate_Media_Folder();
-			if (Mount(false))
-				PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
-		}
+		// if (Has_Data_Media && !Symlink_Mount_Point.empty()) {
+		// 	if (Mount(false))
+		// 		PartitionManager.Add_MTP_Storage(MTP_Storage_ID);
+		// }
 		DataManager::SetValue(TW_IS_ENCRYPTED, 0);
 #ifndef TW_OEM_BUILD
-		gui_msg("format_data_msg=You may need to reboot recovery to be able to use /data again.");
+		if (Is_FBE)
+			gui_msg(Msg(msg::kWarning, "fbe_wipe_msg=WARNING: {1} wiped. FBE device should be booted into Android and not Recovery to set initial FBE policy after wipe.")(TWFunc::get_cache_dir()));
+		else
+			gui_msg("format_data_msg=You may need to reboot recovery to be able to use /data again.");
 #endif
 		ret = true;
 		if (!Key_Directory.empty())
@@ -2099,6 +2100,9 @@
 }
 
 bool TWPartition::Wipe_EXTFS(string File_System) {
+	if (!UnMount(true))
+		return false;
+
 #if PLATFORM_SDK_VERSION < 28
 	if (!TWFunc::Path_Exists("/sbin/mke2fs"))
 #else
@@ -2115,8 +2119,6 @@
 		gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
 		return false;
 	}
-	if (!UnMount(true))
-		return false;
 
 	/**
 	 * On decrypted devices, IOCTL_Get_Block_Size calculates size on device mapper,
@@ -2184,14 +2186,15 @@
 	int ret;
 	bool NeedPreserveFooter = true;
 
+	if (!UnMount(true))
+		return false;
+
 	Find_Actual_Block_Device();
 	if (!Is_Present) {
 		LOGINFO("Block device not present, cannot wipe %s.\n", Display_Name.c_str());
 		gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
 		return false;
 	}
-	if (!UnMount(true))
-		return false;
 
 	/**
 	 * On decrypted devices, IOCTL_Get_Block_Size calculates size on device mapper,
@@ -2239,10 +2242,10 @@
 bool TWPartition::Wipe_FAT() {
 	string command;
 
-	if (TWFunc::Path_Exists("/sbin/mkfs.fat")) {
-		if (!UnMount(true))
-			return false;
+	if (!UnMount(true))
+		return false;
 
+	if (TWFunc::Path_Exists("/sbin/mkfs.fat")) {
 		gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.fat"));
 		Find_Actual_Block_Device();
 		command = "mkfs.fat " + Actual_Block_Device;
@@ -2266,10 +2269,9 @@
 bool TWPartition::Wipe_EXFAT() {
 	string command;
 
+	if (!UnMount(true))
+		return false;
 	if (TWFunc::Path_Exists("/sbin/mkexfatfs")) {
-		if (!UnMount(true))
-			return false;
-
 		gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkexfatfs"));
 		Find_Actual_Block_Device();
 		command = "mkexfatfs " + Actual_Block_Device;
@@ -2335,92 +2337,73 @@
 }
 
 bool TWPartition::Wipe_F2FS() {
-	string command;
+	std::string command;
+	std::string f2fs_bin;
 
-	if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) {
-		bool NeedPreserveFooter = true;
+	if (!UnMount(true))
+		return false;
 
-		Find_Actual_Block_Device();
-		if (!Is_Present) {
-			LOGINFO("Block device not present, cannot wipe %s.\n", Display_Name.c_str());
-			gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
-			return false;
-		}
-		if (!UnMount(true))
-			return false;
-
-		/**
-		 * On decrypted devices, IOCTL_Get_Block_Size calculates size on device mapper,
-		 * so there's no need to preserve footer.
-		 */
-		if ((Is_Decrypted && !Decrypted_Block_Device.empty()) ||
-				Crypto_Key_Location != "footer") {
-			NeedPreserveFooter = false;
-		}
-
-		gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.f2fs"));
-		// First determine if we have the old mkfs.f2fs that uses "-r reserved_bytes"
-		// or the new mkfs.f2fs that expects the number of sectors as the optional last argument
-		// Note: some 7.1 trees have the old and some have the new.
-		command = "mkfs.f2fs | grep \"reserved\" > /tmp/f2fsversiontest";
-		TWFunc::Exec_Cmd(command, false); // no help argument so printing usage exits with an error code
-		if (!TWFunc::Path_Exists("/tmp/f2fsversiontest")) {
-			LOGINFO("Error determining mkfs.f2fs version\n");
-			return false;
-		}
-		if (TWFunc::Get_File_Size("/tmp/f2fsversiontest") <= 0) {
-			LOGINFO("Using newer mkfs.f2fs\n");
-			unsigned long long dev_sz = TWFunc::IOCTL_Get_Block_Size(Actual_Block_Device.c_str());
-			if (!dev_sz)
-				return false;
-
-			if (NeedPreserveFooter)
-				Length < 0 ? dev_sz += Length : dev_sz -= CRYPT_FOOTER_OFFSET;
-
-			char dev_sz_str[48];
-			sprintf(dev_sz_str, "%llu", (dev_sz / 4096));
-			command = "mkfs.f2fs -d1 -f -O encrypt -O quota -O verity -w 4096 " + Actual_Block_Device + " " + dev_sz_str;
-			if (TWFunc::Path_Exists("/sbin/sload.f2fs")) {
-				command += " && sload.f2fs -t /data " + Actual_Block_Device;
-			}
-		} else {
-			LOGINFO("Using older mkfs.f2fs\n");
-			command = "mkfs.f2fs -t 0";
-			if (NeedPreserveFooter) {
-				// Only use length if we're not decrypted
-				char len[32];
-				int mod_length = Length;
-				if (Length < 0)
-					mod_length *= -1;
-				sprintf(len, "%i", mod_length);
-				command += " -r ";
-				command += len;
-			}
-			command += " " + Actual_Block_Device;
-		}
-		LOGINFO("mkfs.f2fs command: %s\n", command.c_str());
-		if (TWFunc::Exec_Cmd(command) == 0) {
-			if (NeedPreserveFooter)
-				Wipe_Crypto_Key();
-			Recreate_AndSec_Folder();
-			gui_msg("done=Done.");
-			return true;
-		} else {
-			gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
-			return false;
-		}
-		return true;
-	} else {
+	if (TWFunc::Path_Exists("/sbin/mkfs.f2fs"))
+		f2fs_bin = "/sbin/mkfs.f2fs";
+	else if (TWFunc::Path_Exists("/sbin/make_f2fs"))
+		f2fs_bin = "/sbin/make_f2fs";
+	else {
 		LOGINFO("mkfs.f2fs binary not found, using rm -rf to wipe.\n");
 		return Wipe_RMRF();
 	}
-	return false;
+
+	bool NeedPreserveFooter = true;
+
+	Find_Actual_Block_Device();
+	if (!Is_Present) {
+		LOGINFO("Block device not present, cannot wipe %s.\n", Display_Name.c_str());
+		gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
+		return false;
+	}
+	
+	unsigned long long dev_sz = TWFunc::IOCTL_Get_Block_Size(Actual_Block_Device.c_str());
+	if (!dev_sz)
+		return false;
+
+	if (NeedPreserveFooter)
+		Length < 0 ? dev_sz += Length : dev_sz -= CRYPT_FOOTER_OFFSET;
+
+	char dev_sz_str[48];
+	sprintf(dev_sz_str, "%llu", (dev_sz / 4096));
+	command = f2fs_bin + " -d1 -f -O encrypt -O quota -O verity -w 4096 " + Actual_Block_Device + " " + dev_sz_str;
+	if (TWFunc::Path_Exists("/sbin/sload.f2fs")) {
+		command += " && sload.f2fs -t /data " + Actual_Block_Device;
+	}
+
+	/**
+	 * On decrypted devices, IOCTL_Get_Block_Size calculates size on device mapper,
+	 * so there's no need to preserve footer.
+	 */
+	if ((Is_Decrypted && !Decrypted_Block_Device.empty()) ||
+			Crypto_Key_Location != "footer") {
+		NeedPreserveFooter = false;
+	}
+	LOGINFO("mkfs.f2fs command: %s\n", f2fs_bin.c_str());
+	if (TWFunc::Exec_Cmd(command) == 0) {
+		if (NeedPreserveFooter)
+			Wipe_Crypto_Key();
+		Recreate_AndSec_Folder();
+		gui_msg("done=Done.");
+		return true;
+	} else {
+		gui_msg(Msg(msg::kError, "unable_to_wipe=Unable to wipe {1}.")(Display_Name));
+		return false;
+	}
+	return true;
 }
 
 bool TWPartition::Wipe_NTFS() {
 	string command;
 	string Ntfsmake_Binary;
 
+	if (!UnMount(true))
+		return false;
+
 	if (TWFunc::Path_Exists("/sbin/mkntfs"))
 		Ntfsmake_Binary = "mkntfs";
 	else if (TWFunc::Path_Exists("/sbin/mkfs.ntfs"))
@@ -2428,9 +2411,6 @@
 	else
 		return false;
 
-	if (!UnMount(true))
-		return false;
-
 	gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)(Ntfsmake_Binary));
 	Find_Actual_Block_Device();
 	command = "/sbin/" + Ntfsmake_Binary + " " + Actual_Block_Device;
@@ -2463,6 +2443,59 @@
 #endif // ifdef TW_OEM_BUILD
 }
 
+bool TWPartition::Recreate_AB_Cache_Dir(const fscrypt_encryption_policy &policy) {
+	struct passwd pd;
+	struct passwd *pwdptr = &pd;
+	struct passwd *tempPd;
+	char pwdBuf[512];
+	int uid = 0, gid = 0;
+
+	if ((getpwnam_r("system", pwdptr, pwdBuf, sizeof(pwdBuf), &tempPd)) != 0) {
+		LOGERR("unable to get system user id\n");
+		return false;
+	} else {
+		struct group grp;
+		struct group *grpptr = &grp;
+		struct group *tempGrp;
+		char grpBuf[512];
+
+		if ((getgrnam_r("cache", grpptr, grpBuf, sizeof(grpBuf), &tempGrp)) != 0) {
+			LOGERR("unable to get cache group id\n");
+			return false;
+		} else {
+			uid = pd.pw_uid;
+			gid = grp.gr_gid;
+
+			if (!TWFunc::Create_Dir_Recursive(AB_CACHE_DIR, S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP, uid, gid)) {
+				LOGERR("Unable to recreate %s\n", AB_CACHE_DIR);
+				return false;
+			}
+			if (setfilecon(AB_CACHE_DIR, "u:object_r:cache_file:s0") != 0) {	
+				LOGERR("Unable to set contexts for %s\n", AB_CACHE_DIR);
+				return false;
+			}
+			char policy_hex[FS_KEY_DESCRIPTOR_SIZE_HEX];
+			policy_to_hex(policy.master_key_descriptor, policy_hex);
+			LOGINFO("setting policy for %s: %s\n", policy_hex, AB_CACHE_DIR);
+			if (sizeof(policy.master_key_descriptor) > 0) {
+				if (!TWFunc::Set_Encryption_Policy(AB_CACHE_DIR, policy)) {
+					LOGERR("Unable to set encryption policy for %s\n", AB_CACHE_DIR);
+					LOGINFO("Removing %s\n", AB_CACHE_DIR);
+					int ret = TWFunc::removeDir(AB_CACHE_DIR, true);
+					if (ret == -1) {
+						LOGERR("Unable to remove %s\n", AB_CACHE_DIR);
+					}
+					return false;
+				}
+			} else {
+				LOGERR("Not setting empty policy to %s\n", AB_CACHE_DIR);
+				return false;
+			}
+		}
+	}
+	return true;
+}
+
 bool TWPartition::Wipe_Data_Without_Wiping_Media_Func(const string& parent __unused) {
 	string dir;
 
@@ -3331,7 +3364,6 @@
 					PartitionManager.Remove_Partition_By_Path("/sd-ext");
 				}
 				Setup_Data_Media();
-				Recreate_Media_Folder();
 				Wipe_Available_in_GUI = true;
 				Wipe_During_Factory_Reset = true;
 				Can_Be_Backed_Up = true;