From 5f2a0b71856f329547aecd0b9ab3f927cc1c20f6 Mon Sep 17 00:00:00 2001 From: Mohd Faraz Date: Wed, 1 Nov 2023 08:58:40 +0700 Subject: [PATCH] partitionmanager: allow skipping additional fstab processing * Set 'TW_SKIP_ADDITIONAL_FSTAB := true' to skip additional fstab processing * Set 'keymaster_ver' prop in device tree if you want to use a specific keymaster version regardless of what may be found in ramdisk manifest (if version can't be determined by checking device manifest) * Set above prop and add 'TW_FORCE_KEYMASTER_VER := true' if you want to enforce keymaster_ver set in device tree and skip checking on device In current state, if additional fstab cannot be found, then keymaster_ver never gets set. This breaks devices using twrp-common as the correct service will never start for decryption, resulting in a hang at the TWRP splash. Separating fstab processing allows keymaster to be found on device and keymaster_ver to be set regardless of fstab availability. If keymaster_ver cannot be determined by checking vendor on device, use default keymaster version set in device tree, or if not present, set from TWRP ramdisk based on binaries found, unless values are forced as mentioned above. Change-Id: Ic498b82a2ff2a5461493ce4ad304f1a6679291df Signed-off-by: Mohd Faraz --- Android.mk | 6 +++ partitionmanager.cpp | 87 +++++++++++++++++++++++++++------ twrp-functions.cpp | 112 ++++++++++++++++++++++++++----------------- twrp-functions.hpp | 3 +- variables.h | 4 +- 5 files changed, 150 insertions(+), 62 deletions(-) diff --git a/Android.mk b/Android.mk index d5036a70e..c775454d6 100644 --- a/Android.mk +++ b/Android.mk @@ -459,6 +459,12 @@ endif ifeq ($(TW_ENABLE_BLKDISCARD), true) LOCAL_CFLAGS += -DTW_ENABLE_BLKDISCARD endif +ifeq ($(TW_SKIP_ADDITIONAL_FSTAB), true) + LOCAL_CFLAGS += -DTW_SKIP_ADDITIONAL_FSTAB +endif +ifeq ($(TW_FORCE_KEYMASTER_VER), true) + LOCAL_CFLAGS += -DTW_FORCE_KEYMASTER_VER +endif LOCAL_C_INCLUDES += system/vold \ diff --git a/partitionmanager.cpp b/partitionmanager.cpp index da3bd105f..f0bf4dd8a 100755 --- a/partitionmanager.cpp +++ b/partitionmanager.cpp @@ -212,6 +212,62 @@ void inline Reset_Prop_From_Partition(std::string prop, std::string def, TWParti } } +void inline Process_ResetProps(TWPartition *ven, TWPartition *odm) { + // Reset the crypto volume props according to os. + Reset_Prop_From_Partition("ro.crypto.dm_default_key.options_format.version", "", ven, odm); + Reset_Prop_From_Partition("ro.crypto.volume.metadata.method", "", ven, odm); + Reset_Prop_From_Partition("ro.crypto.volume.options", "", ven, odm); + Reset_Prop_From_Partition("external_storage.projid.enabled", "", ven, odm); + Reset_Prop_From_Partition("external_storage.casefold.enabled", "", ven, odm); + Reset_Prop_From_Partition("external_storage.sdcardfs.enabled", "", ven, odm); +} + +static inline std::string KM_Ver_From_Manifest(std::string ver) { + TWFunc::Get_Service_From_Manifest("/vendor", "android.hardware.keymaster", ver); + if (strstr(ver.c_str(), "4")) { + ver = "4.x"; + } + return ver; +} + +void inline Process_Keymaster_Version(TWPartition *ven, bool Display_Error) { + // Fetch the Keymaster Service version to be started + std::string version; +#ifndef TW_FORCE_KEYMASTER_VER + version = KM_Ver_From_Manifest(version); + + /* If we are unable to get the version from device vendor then + * set the version from the keymaster_ver prop if set + */ + if (version.empty()) { + // unmount partition(s) + if (ven) ven->UnMount(Display_Error); + + // Use keymaster_ver prop set from device tree (if exists) + version = android::base::GetProperty(TW_KEYMASTER_VERSION_PROP, version); + if (version.empty()) { + LOGINFO("Keymaster_Ver::Unable to find vendor manifest on the device, and no default value set. Checking the ramdisk manifest\n"); + version = KM_Ver_From_Manifest(version); + } else { + LOGINFO("Keymaster_Ver::Unable to find vendor manifest on the device. Setting to default value.\n"); + } + } else { + if (ven) ven->UnMount(Display_Error); + } +#else + if (ven) ven->UnMount(Display_Error); + + version = android::base::GetProperty(TW_KEYMASTER_VERSION_PROP, version); + if (version.empty()) { + LOGINFO("Keymaster_Ver::Force Keymaster_Ver flag found, but keymaster_ver prop not set.\n"); + } else { + LOGINFO("Keymaster_Ver::Force Keymaster_Ver flag found.\n"); + } +#endif + LOGINFO("Keymaster_Ver::Using keymaster version '%s' for decryption\n", version.c_str()); + android::base::SetProperty(TW_KEYMASTER_VERSION_PROP, version.c_str()); +} + int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error, bool recovery_mode) { FILE* fstabFile; char fstab_line[MAX_FSTAB_LINE_LENGTH]; @@ -279,7 +335,9 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error, } TWPartition *data = NULL; TWPartition *meta = NULL; +#ifndef TW_SKIP_ADDITIONAL_FSTAB parse: +#endif fstabFile = fopen(Fstab_Filename.c_str(), "rt"); if (!parse_userdata && fstabFile == NULL) { LOGERR("Critical Error: Unable to open fstab at '%s'.\n", Fstab_Filename.c_str()); @@ -355,33 +413,32 @@ int TWPartitionManager::Process_Fstab(string Fstab_Filename, bool Display_Error, if (recovery_mode && !parse_userdata) { if (ven) ven->Mount(Display_Error); if (odm) odm->Mount(Display_Error); + + Process_ResetProps(ven, odm); + parse_userdata = true; + +#ifndef TW_SKIP_ADDITIONAL_FSTAB + // Now Fetch the additional fstab if (TWFunc::Find_Fstab(Fstab_Filename)) { - string service; LOGINFO("Fstab: %s\n", Fstab_Filename.c_str()); TWFunc::copy_file(Fstab_Filename, additional_fstab, 0600, false); Fstab_Filename = additional_fstab; property_set("fstab.additional", "1"); - TWFunc::Get_Service_From(ven, "keymaster", service); - LOGINFO("Keymaster version: '%s'\n", TWFunc::Get_Version_From_Service(service).c_str()); - property_set("keymaster_ver", TWFunc::Get_Version_From_Service(service).c_str()); - parse_userdata = true; - Reset_Prop_From_Partition("ro.crypto.dm_default_key.options_format.version", "", ven, odm); - Reset_Prop_From_Partition("ro.crypto.volume.metadata.method", "", ven, odm); - Reset_Prop_From_Partition("ro.crypto.volume.options", "", ven, odm); - Reset_Prop_From_Partition("external_storage.projid.enabled", "", ven, odm); - Reset_Prop_From_Partition("external_storage.casefold.enabled", "", ven, odm); - Reset_Prop_From_Partition("external_storage.sdcardfs.enabled", "", ven, odm); - if (ven) ven->UnMount(Display_Error); - if (odm) odm->UnMount(Display_Error); goto parse; } else { - if (ven) ven->UnMount(Display_Error); - if (odm) odm->UnMount(Display_Error); LOGINFO("Unable to parse vendor fstab\n"); } } LOGINFO("Done processing fstab files\n"); +#else + LOGINFO("Skipping Additional Fstab Processing\n"); + property_set("fstab.additional", "0"); + } +#endif + if (odm) odm->UnMount(Display_Error); + Process_Keymaster_Version(ven, false); + if (ven) ven->UnMount(Display_Error); return true; } diff --git a/twrp-functions.cpp b/twrp-functions.cpp index beb950276..9759d83c1 100644 --- a/twrp-functions.cpp +++ b/twrp-functions.cpp @@ -56,6 +56,10 @@ #include "cutils/properties.h" #include "cutils/android_reboot.h" #include +#ifdef TW_INCLUDE_CRYPTO +#include "gui/rapidxml.hpp" +#include "gui/pages.hpp" +#endif #endif // ndef BUILD_TWRPTAR_MAIN #ifndef TW_EXCLUDE_ENCRYPTED_BACKUPS #include "openaes/inc/oaes_lib.h" @@ -2290,54 +2294,74 @@ bool TWFunc::Find_Fstab(string &fstab) { return true; } -bool TWFunc::Get_Service_From(TWPartition *Partition, std::string Service, std::string &Res) { - Partition->Mount(true); - std::string Path = Partition->Get_Mount_Point() + "/etc/init/"; - std::string Name; - std::vector Data; - bool Found = false, ret = false; - DIR* dir; - struct dirent* der; - dir = opendir(Path.c_str()); - while ((der = readdir(dir)) != NULL) - { - Name = der->d_name; - if (Name.find(Service) != string::npos) { - Found = true; - Path += Name; - break; - } - } - closedir(dir); - - if (!Found) { - LOGINFO("Unable to locate service RC\n"); - goto finish; - } - - if (read_file(Path, Data) != 0) { - LOGINFO("Unable to read file '%s'\n", Path.c_str()); - goto finish; - } +static inline std::string Get_Version_From_FQ(std::string name) { + int start, end; + start = name.find('@') + 1; + end = name.find(":") - start; + return name.substr(start, end); +} - for (int index = 0; index < Data.size(); index++) { - Name = Data.at(index); - if (Name.find("service") != string::npos) { - Res = Name.substr(Name.find_last_of('/')+1); - ret = true; - goto finish; +bool TWFunc::Get_Service_From_Manifest(std::string basepath, std::string service, std::string &res) { + std::string manifestpath, filename, platform; + manifestpath = basepath + "/etc/vintf/"; + bool ret = false; + + // Prefer using ro.boot.product.vendor.sku property, following AOSP VintfObject::fetchVendorHalManifest + // If not set, also try ro.board.platform. + platform = android::base::GetProperty("ro.boot.product.vendor.sku", ""); + if (platform.empty()) { + LOGINFO("Property ro.boot.product.vendor.sku not found, trying to get vintf manifest file name from ro.board.platform\n"); + platform = android::base::GetProperty("ro.board.platform", ""); + } + + // Let's find the service xml if exists + Exec_Cmd("find " + manifestpath + "manifest/ -type f -name *" + service + "*", filename, false); + if (filename.empty()) { + LOGINFO("Separate manifest doesn't exist for '%s'\n", service.c_str()); + // Look for manifest_PLATFORM.xml + filename = manifestpath + "manifest_" + platform + ".xml"; + if (!Path_Exists(filename)) { + // Use legacy manifest path if platform manifest is not found. + LOGINFO("%s not found. Using default path for manifest.xml\n", filename.c_str()); + filename = manifestpath + "manifest.xml"; + } + } + + if (Path_Exists(filename)) { + char* manifest = PageManager::LoadFileToBuffer(filename, NULL); + LOGINFO("Looking for '%s' service in manifest\n", service.c_str()); + xml_document<>* vintfManifest = new xml_document<>(); + vintfManifest->parse<0>(manifest); + xml_node<>* manifestNode = vintfManifest->first_node("manifest"); + std::string version; + if (manifestNode) { + for (xml_node<>* child = manifestNode->first_node(); child; child = child->next_sibling()) { + std::string type = child->name(); + if (type == "hal") { + xml_node<>* nameNode = child->first_node("name"); + type = nameNode->value(); + if (type == service) { + xml_node<> *versionNode = child->first_node("version"); + if (versionNode != nullptr) { + LOGINFO("Found version in manifest: %s\n", versionNode->value()); + } else { + versionNode = child->first_node("fqname"); + if (versionNode == nullptr) return ret; + LOGINFO("Found fqname in manifest: %s\n", versionNode->value()); + } + version = versionNode->value(); + if (version.find('@') == std::string::npos) { + res = version; + } else { + res = Get_Version_From_FQ(version); + } + ret = true; + } + } + } } } - -finish: - Partition->UnMount(true); return ret; } -std::string TWFunc::Get_Version_From_Service(std::string name) { - int start, end; - start = name.find('@') + 1; - end = name.find("-") - start; - return name.substr(start, end); -} #endif // ndef BUILD_TWRPTAR_MAIN diff --git a/twrp-functions.hpp b/twrp-functions.hpp index 839564e51..94472b111 100644 --- a/twrp-functions.hpp +++ b/twrp-functions.hpp @@ -141,8 +141,7 @@ class TWFunc static string Check_For_TwrpFolder(); // Gets user defined path on storage where backups should be stored static bool Check_Xml_Format(const std::string filename); // Return whether a xml is in plain xml or ABX format static bool Find_Fstab(string &fstab); - static bool Get_Service_From(TWPartition *Partition, std::string Service, std::string &Ret); - static std::string Get_Version_From_Service(std::string name); + static bool Get_Service_From_Manifest(std::string basepath, std::string service, std::string &ret); private: static void Copy_Log(string Source, string Destination); diff --git a/variables.h b/variables.h index e4086e5aa..4fbabd74b 100755 --- a/variables.h +++ b/variables.h @@ -153,9 +153,11 @@ #define TW_VIRTUAL_AB_ENABLED "tw_virtual_ab.enabled" #define TW_AUTO_REFLASHTWRP_VAR "tw_auto_reflashtwrp" -// Custome Props +// BUILD PROPS #define TW_FASTBOOT_MODE_PROP "ro.twrp.fastbootd" #define TW_MODULES_MOUNTED_PROP "twrp.modules.loaded" // property for successfully mounted modules +#define TW_KEYMASTER_VERSION_PROP "keymaster_ver" + // Theme versioning // version 2 requires theme to handle power button as action togglebacklight // version 4 adds listbox support to reboot page