Skip to content

Commit

Permalink
factory reset: restore ext4 policy on /data/cache
Browse files Browse the repository at this point in the history
If ext4 policy is not restored, system won't boot properly
after a factory reset.

When /data is formatted by the user, we need to make sure we
do not create the /data/cache directory so that Android can
create it with the new policy for /data.

This also removes extraneous umount calls, and places them
in the specific wipe function for each filesystem.

Change-Id: I71ff39d8660fbf4aa6fe8a8309e291166359da72
  • Loading branch information
bigbiff committed May 14, 2020
1 parent 1db9432 commit a2bd7b7
Show file tree
Hide file tree
Showing 12 changed files with 167 additions and 41 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
.*.swp
*~
tags
.vscode
8 changes: 5 additions & 3 deletions Android.mk
Original file line number Diff line number Diff line change
Expand Up @@ -177,7 +177,11 @@ endif
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -lt 28; echo $$?),0)
LOCAL_CFLAGS += -DUSE_EXT4
LOCAL_C_INCLUDES += system/extras/ext4_utils
endif
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -le 28; echo $$?),0)
LOCAL_C_INCLUDES += system/extras/ext4_utils \
system/extras/ext4_utils/include \
bootable/recovery/crypto/ext4crypt
LOCAL_SHARED_LIBRARIES += libext4_utils
ifneq ($(wildcard external/lz4/Android.mk),)
#LOCAL_STATIC_LIBRARIES += liblz4
Expand Down Expand Up @@ -206,8 +210,6 @@ else
LOCAL_STATIC_LIBRARIES += $(TARGET_RECOVERY_TWRP_LIB)
endif

LOCAL_C_INCLUDES += system/extras/ext4_utils

tw_git_revision := $(shell git -C $(LOCAL_PATH) rev-parse --short=8 HEAD 2>/dev/null)
ifeq ($(shell git -C $(LOCAL_PATH) diff --quiet; echo $$?),1)
tw_git_revision := $(tw_git_revision)-dirty
Expand Down
3 changes: 1 addition & 2 deletions crypto/ext4crypt/e4policyget.cpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -23,13 +23,12 @@
#define EXT4_KEY_DESCRIPTOR_SIZE_HEX 17

int main(int argc, char *argv[]) {
bool ret = false;
if (argc != 2) {
printf("Must specify a path\n");
return -1;
} else {
ext4_encryption_policy eep;
if (e4crypt_policy_get_struct(argv[1], &eep, sizeof(eep))) {
if (e4crypt_policy_get_struct(argv[1], &eep)) {
char policy_hex[EXT4_KEY_DESCRIPTOR_SIZE_HEX];
policy_to_hex(eep.master_key_descriptor, policy_hex);
printf("%s\n", policy_hex);
Expand Down
8 changes: 1 addition & 7 deletions data.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1064,13 +1064,7 @@ void DataManager::Output_Version(void)
return;
}
}
if (!TWFunc::Path_Exists(recoveryCacheDir)) {
LOGINFO("Recreating %s folder.\n", recoveryCacheDir.c_str());
if (!TWFunc::Create_Dir_Recursive(recoveryCacheDir.c_str(), S_IRWXU | S_IRWXG | S_IWGRP | S_IXGRP, 0, 0)) {
LOGERR("DataManager::Output_Version -- Unable to make %s: %s\n", recoveryCacheDir.c_str(), strerror(errno));
return;
}
}

std::string verPath = recoveryCacheDir + ".version";
if (TWFunc::Path_Exists(verPath)) {
unlink(verPath.c_str());
Expand Down
9 changes: 9 additions & 0 deletions gui/Android.mk
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,15 @@ else
LOCAL_SHARED_LIBRARIES += libminzip
LOCAL_CFLAGS += -DUSE_MINZIP
endif
ifeq ($(TARGET_USERIMAGES_USE_EXT4), true)
ifeq ($(shell test $(PLATFORM_SDK_VERSION) -le 28; echo $$?),0)
LOCAL_C_INCLUDES += system/extras/ext4_utils \
system/extras/ext4_utils/include \
bootable/recovery/crypto/ext4crypt
LOCAL_SHARED_LIBRARIES += libext4_utils
endif
endif

LOCAL_MODULE := libguitwrp

#TWRP_EVENT_LOGGING := true
Expand Down
1 change: 1 addition & 0 deletions gui/theme/common/languages/en.xml
Original file line number Diff line number Diff line change
Expand Up @@ -722,5 +722,6 @@
<string name="unmount_sys_install">Unmount System before installing a ZIP</string>
<string name="unmount_system">Unmounting System...</string>
<string name="unmount_system_err">Failed unmounting System</string>
<string name="fbe_wipe_msg">WARNING: {1} wiped. FBE device should be booted into Android and not Recovery to set initial FBE policy after wipe.</string>
</resources>
</language>
112 changes: 89 additions & 23 deletions partition.cpp
100644 → 100755
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -19,17 +19,20 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/mount.h>
#include <sys/param.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/vfs.h>
#include <sys/mount.h>
#include <unistd.h>
#include <dirent.h>
#include <fcntl.h>
#include <grp.h>
#include <iostream>
#include <libgen.h>
#include <pwd.h>
#include <zlib.h>
#include <iostream>
#include <sstream>
#include <sys/param.h>
#include <fcntl.h>

#include "cutils/properties.h"
#include "libblkid/include/blkid.h"
Expand Down Expand Up @@ -1632,6 +1635,11 @@ 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";
ext4_encryption_policy policy;

if (Mount_Point == "/data" && TWFunc::get_cache_dir() == AB_CACHE_DIR && Is_Decrypted) {
TWFunc::Get_Encryption_Policy(policy, AB_CACHE_DIR);
}

if (!Can_Be_Wiped) {
gui_msg(Msg(msg::kError, "cannot_wipe=Partition {1} cannot be wiped.")(Display_Name));
Expand All @@ -1648,6 +1656,11 @@ bool TWPartition::Wipe(string New_File_System) {

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) {
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);
Expand Down Expand Up @@ -1677,9 +1690,6 @@ bool TWPartition::Wipe(string New_File_System) {
}

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);

Expand Down Expand Up @@ -1991,10 +2001,10 @@ bool TWPartition::Wipe_Encryption() {
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");
Expand All @@ -2014,7 +2024,10 @@ bool TWPartition::Wipe_Encryption() {
}
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())
Expand Down Expand Up @@ -2080,6 +2093,9 @@ void TWPartition::Check_FS_Type() {
}

bool TWPartition::Wipe_EXTFS(string File_System) {
if (!UnMount(true))
return false;

#if PLATFORM_SDK_VERSION < 28
if (!TWFunc::Path_Exists("/sbin/mke2fs"))
#else
Expand Down Expand Up @@ -2219,11 +2235,10 @@ bool TWPartition::Wipe_EXT4() {

bool TWPartition::Wipe_FAT() {
string command;
if (!UnMount(true))
return false;

if (TWFunc::Path_Exists("/sbin/mkfs.fat")) {
if (!UnMount(true))
return false;

gui_msg(Msg("formatting_using=Formatting {1} using {2}...")(Display_Name)("mkfs.fat"));
Find_Actual_Block_Device();
command = "mkfs.fat " + Actual_Block_Device;
Expand All @@ -2246,11 +2261,10 @@ bool TWPartition::Wipe_FAT() {

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;
Expand Down Expand Up @@ -2317,6 +2331,8 @@ bool TWPartition::Wipe_RMRF() {

bool TWPartition::Wipe_F2FS() {
string command;
if (!UnMount(true))
return false;

if (TWFunc::Path_Exists("/sbin/mkfs.f2fs")) {
bool NeedPreserveFooter = true;
Expand All @@ -2327,8 +2343,6 @@ bool TWPartition::Wipe_F2FS() {
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,
Expand Down Expand Up @@ -2402,16 +2416,16 @@ 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"))
Ntfsmake_Binary = "mkfs.ntfs";
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;
Expand All @@ -2435,7 +2449,6 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media() {

if (!Mount(true))
return false;

gui_msg("wiping_data=Wiping data without wiping /data/media ...");
ret = Wipe_Data_Without_Wiping_Media_Func(Mount_Point + "/");
if (ret)
Expand All @@ -2444,6 +2457,59 @@ bool TWPartition::Wipe_Data_Without_Wiping_Media() {
#endif // ifdef TW_OEM_BUILD
}

bool TWPartition::Recreate_AB_Cache_Dir(const ext4_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[EXT4_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;

Expand Down
3 changes: 0 additions & 3 deletions partitionmanager.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -1487,9 +1487,6 @@ int TWPartitionManager::Format_Data(void) {
TWPartition* dat = Find_Partition_By_Path("/data");

if (dat != NULL) {
if (!dat->UnMount(true))
return false;

return dat->Wipe_Encryption();
} else {
gui_msg(Msg(msg::kError, "unable_to_locate=Unable to locate {1}.")("/data"));
Expand Down
4 changes: 3 additions & 1 deletion partitions.hpp
100644 → 100755
Original file line number Diff line number Diff line change
Expand Up @@ -26,6 +26,7 @@
#include "exclude.hpp"
#include "tw_atomic.hpp"
#include "progresstracking.hpp"
#include "ext4crypt_tar.h"

#define MAX_FSTAB_LINE_LENGTH 2048

Expand Down Expand Up @@ -207,6 +208,7 @@ class TWPartition
bool Wipe_NTFS(); // Uses mkntfs to wipe
bool Wipe_Data_Without_Wiping_Media(); // Uses rm -rf to wipe but does not wipe /data/media
bool Wipe_Data_Without_Wiping_Media_Func(const string& parent); // Uses rm -rf to wipe but does not wipe /data/media
bool Recreate_AB_Cache_Dir(const ext4_encryption_policy &policy); // Recreate AB_CACHE_DIR after wipe
void Wipe_Crypto_Key(); // Wipe crypto key from either footer or block device
bool Backup_Tar(PartitionSettings *part_settings, pid_t *tar_fork_pid); // Backs up using tar for file systems
bool Backup_Image(PartitionSettings *part_settings); // Backs up using raw read/write for emmc memory types
Expand Down Expand Up @@ -281,7 +283,7 @@ class TWPartition
bool SlotSelect; // Partition has A/B slots
TWExclude backup_exclusions; // Exclusions for file based backups
TWExclude wipe_exclusions; // Exclusions for file based wipes (data/media devices only)
string Key_Directory; // Metadata key directory needed for mounting FBE encrypted data partitions using metadata encryption
string Key_Directory; // Metadata key directory needed for mounting FBE encrypted data partitions using metadata encryption

struct partition_fs_flags_struct { // This struct is used to store mount flags and options for different file systems for the same partition
string File_System;
Expand Down
Loading

0 comments on commit a2bd7b7

Please sign in to comment.