Skip to content

Commit

Permalink
partitionmanager: allow skipping additional fstab processing
Browse files Browse the repository at this point in the history
* 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 <[email protected]>
  • Loading branch information
AndroiableDroid authored and rezaadi0105 committed Nov 1, 2023
1 parent 05c6978 commit 5f2a0b7
Show file tree
Hide file tree
Showing 5 changed files with 150 additions and 62 deletions.
6 changes: 6 additions & 0 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -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 \

Expand Down
87 changes: 72 additions & 15 deletions partitionmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down Expand Up @@ -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());
Expand Down Expand Up @@ -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;
}

Expand Down
112 changes: 68 additions & 44 deletions twrp-functions.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,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"
Expand Down Expand Up @@ -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<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;
}
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
3 changes: 1 addition & 2 deletions twrp-functions.hpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down
4 changes: 3 additions & 1 deletion variables.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down

0 comments on commit 5f2a0b7

Please sign in to comment.