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 <androiabledroid@gmail.com>
diff --git a/Android.mk b/Android.mk
index 9d363a1..cc6c5ad 100644
--- a/Android.mk
+++ b/Android.mk
@@ -441,6 +441,12 @@
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 f741cb3..ca7e232 100755
--- a/partitionmanager.cpp
+++ b/partitionmanager.cpp
@@ -208,6 +208,62 @@
}
}
+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];
@@ -275,7 +331,9 @@
}
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());
@@ -356,34 +414,32 @@
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 0695611..27e73c2 100644
--- a/twrp-functions.cpp
+++ b/twrp-functions.cpp
@@ -57,6 +57,10 @@
#include "cutils/properties.h"
#include "cutils/android_reboot.h"
#include <sys/reboot.h>
+#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"
@@ -1584,55 +1588,73 @@
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<std::string> 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;
- }
-
- 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;
- }
- }
-
-finish:
- Partition->UnMount(true);
- return ret;
-}
-
-std::string TWFunc::Get_Version_From_Service(std::string name) {
+static inline std::string Get_Version_From_FQ(std::string name) {
int start, end;
start = name.find('@') + 1;
- end = name.find("-") - start;
+ end = name.find(":") - start;
return name.substr(start, end);
}
+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;
+ }
+ }
+ }
+ }
+ }
+ return ret;
+}
+
#endif // ndef BUILD_TWRPTAR_MAIN
diff --git a/twrp-functions.hpp b/twrp-functions.hpp
index a66f3e0..203638a 100644
--- a/twrp-functions.hpp
+++ b/twrp-functions.hpp
@@ -121,8 +121,7 @@
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);
static bool abx_to_xml(const std::string path, std::string &result); // could we convert abx to xml (if so, return the full path to the converted file)
private:
diff --git a/variables.h b/variables.h
index f481b2e..0482ced 100755
--- a/variables.h
+++ b/variables.h
@@ -153,6 +153,7 @@
// 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