diff --git a/CryptCommandListener.cpp b/CryptCommandListener.cpp index 798a912..f4ced43 100644 --- a/CryptCommandListener.cpp +++ b/CryptCommandListener.cpp @@ -405,6 +405,11 @@ int CryptCommandListener::CryptfsCmd::runCommand(SocketClient *cli, return sendGenericOkFailOnBool(cli, e4crypt_prepare_user_storage( parseNull(argv[2]), atoi(argv[3]), atoi(argv[4]), atoi(argv[5]))); + } else if (subcommand == "destroy_user_storage") { + if (!check_argc(cli, subcommand, argc, 5, " ")) return 0; + return sendGenericOkFailOnBool(cli, + e4crypt_destroy_user_storage(parseNull(argv[2]), atoi(argv[3]), atoi(argv[4]))); + } else { dumpArgs(argc, argv, -1); cli->sendMsg(ResponseCode::CommandSyntaxError, "Unknown cryptfs subcommand", false); diff --git a/Ext4Crypt.cpp b/Ext4Crypt.cpp index 11f104a..309a1f2 100644 --- a/Ext4Crypt.cpp +++ b/Ext4Crypt.cpp @@ -43,6 +43,7 @@ #include "key_control.h" #define EMULATED_USES_SELINUX 0 +#define MANAGE_MISC_DIRS 0 #include @@ -209,6 +210,15 @@ static bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gi return true; } +static bool destroy_dir(const std::string& dir) { + LOG(DEBUG) << "Destroying: " << dir; + if (rmdir(dir.c_str()) != 0 && errno != ENOENT) { + PLOG(ERROR) << "Failed to destroy " << dir; + return false; + } + return true; +} + static bool random_key(std::string* key) { if (android::vold::ReadRandomBytes(EXT4_AES_256_XTS_KEY_SIZE, *key) != 0) { // TODO status_t plays badly with PLOG, fix it. @@ -558,8 +568,8 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token_hex // back into a known-good state. if (!emulated_unlock(android::vold::BuildDataSystemCePath(user_id), 0771) || !emulated_unlock(android::vold::BuildDataMiscCePath(user_id), 01771) || - !emulated_unlock(android::vold::BuildDataMediaPath(nullptr, user_id), 0770) || - !emulated_unlock(android::vold::BuildDataUserPath(nullptr, user_id), 0771)) { + !emulated_unlock(android::vold::BuildDataMediaCePath(nullptr, user_id), 0770) || + !emulated_unlock(android::vold::BuildDataUserCePath(nullptr, user_id), 0771)) { LOG(ERROR) << "Failed to unlock user " << user_id; return false; } @@ -575,8 +585,8 @@ bool e4crypt_lock_user_key(userid_t user_id) { // When in emulation mode, we just use chmod if (!emulated_lock(android::vold::BuildDataSystemCePath(user_id)) || !emulated_lock(android::vold::BuildDataMiscCePath(user_id)) || - !emulated_lock(android::vold::BuildDataMediaPath(nullptr, user_id)) || - !emulated_lock(android::vold::BuildDataUserPath(nullptr, user_id))) { + !emulated_lock(android::vold::BuildDataMediaCePath(nullptr, user_id)) || + !emulated_lock(android::vold::BuildDataUserCePath(nullptr, user_id))) { LOG(ERROR) << "Failed to lock user " << user_id; return false; } @@ -586,54 +596,58 @@ bool e4crypt_lock_user_key(userid_t user_id) { } bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial, - int flags) { + int flags) { LOG(DEBUG) << "e4crypt_prepare_user_storage for volume " << escape_null(volume_uuid) << ", user " << user_id << ", serial " << serial << ", flags " << flags; if (flags & FLAG_STORAGE_DE) { + // DE_sys key + auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); + auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); + auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); + auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id); + + // DE_n key auto system_de_path = android::vold::BuildDataSystemDePath(user_id); auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); + if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false; +#if MANAGE_MISC_DIRS + if (!prepare_dir(misc_legacy_path, 0750, multiuser_get_uid(user_id, AID_SYSTEM), + multiuser_get_uid(user_id, AID_EVERYBODY))) return false; +#endif + if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; + if (!prepare_dir(foreign_de_path, 0773, AID_SYSTEM, AID_SYSTEM)) return false; + if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; if (!prepare_dir(misc_de_path, 01771, AID_SYSTEM, AID_MISC)) return false; if (!prepare_dir(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - if (volume_uuid == nullptr) { - // Prepare profile directories only for the internal storage. - // For now, we do not store profiles on the adopted storage. - auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); - auto foreign_dex_profiles_de_path = - android::vold::BuildDataProfilesForeignDexDePath(user_id); - if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - if (!prepare_dir(foreign_dex_profiles_de_path, 0773, AID_SYSTEM, AID_SYSTEM)) { - return false; - } - } - - if (e4crypt_is_native()) { + // For now, FBE is only supported on internal storage + if (e4crypt_is_native() && volume_uuid == nullptr) { std::string de_raw_ref; if (!lookup_key_ref(s_de_key_raw_refs, user_id, &de_raw_ref)) return false; if (!ensure_policy(de_raw_ref, system_de_path)) return false; if (!ensure_policy(de_raw_ref, misc_de_path)) return false; if (!ensure_policy(de_raw_ref, user_de_path)) return false; - // No need to set the policy for profiles_de_path. The parent directory (/data/misc) - // already has a DE_sys policy set. } } if (flags & FLAG_STORAGE_CE) { + // CE_n key auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); - auto media_ce_path = android::vold::BuildDataMediaPath(volume_uuid, user_id); - auto user_ce_path = android::vold::BuildDataUserPath(volume_uuid, user_id); + auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id); + auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false; if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false; if (!prepare_dir(media_ce_path, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false; if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false; - if (e4crypt_is_native()) { + // For now, FBE is only supported on internal storage + if (e4crypt_is_native() && volume_uuid == nullptr) { std::string ce_raw_ref; if (!lookup_key_ref(s_ce_key_raw_refs, user_id, &ce_raw_ref)) return false; if (!ensure_policy(ce_raw_ref, system_ce_path)) return false; @@ -645,3 +659,51 @@ bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int return true; } + +bool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags) { + LOG(DEBUG) << "e4crypt_destroy_user_storage for volume " << escape_null(volume_uuid) + << ", user " << user_id << ", flags " << flags; + bool res = true; + + if (flags & FLAG_STORAGE_DE) { + // DE_sys key + auto system_legacy_path = android::vold::BuildDataSystemLegacyPath(user_id); + auto misc_legacy_path = android::vold::BuildDataMiscLegacyPath(user_id); + auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id); + auto foreign_de_path = android::vold::BuildDataProfilesForeignDexDePath(user_id); + + // DE_n key + auto system_de_path = android::vold::BuildDataSystemDePath(user_id); + auto misc_de_path = android::vold::BuildDataMiscDePath(user_id); + auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id); + + if (volume_uuid == nullptr) { + res &= destroy_dir(system_legacy_path); +#if MANAGE_MISC_DIRS + res &= destroy_dir(misc_legacy_path); +#endif + res &= destroy_dir(profiles_de_path); + res &= destroy_dir(foreign_de_path); + res &= destroy_dir(system_de_path); + res &= destroy_dir(misc_de_path); + } + res &= destroy_dir(user_de_path); + } + + if (flags & FLAG_STORAGE_CE) { + // CE_n key + auto system_ce_path = android::vold::BuildDataSystemCePath(user_id); + auto misc_ce_path = android::vold::BuildDataMiscCePath(user_id); + auto media_ce_path = android::vold::BuildDataMediaCePath(volume_uuid, user_id); + auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id); + + if (volume_uuid == nullptr) { + res &= destroy_dir(system_ce_path); + res &= destroy_dir(misc_ce_path); + } + res &= destroy_dir(media_ce_path); + res &= destroy_dir(user_ce_path); + } + + return res; +} diff --git a/Ext4Crypt.h b/Ext4Crypt.h index dff2953..89cfbab 100644 --- a/Ext4Crypt.h +++ b/Ext4Crypt.h @@ -35,5 +35,6 @@ bool e4crypt_unlock_user_key(userid_t user_id, int serial, const char* token, co bool e4crypt_lock_user_key(userid_t user_id); bool e4crypt_prepare_user_storage(const char* volume_uuid, userid_t user_id, int serial, int flags); +bool e4crypt_destroy_user_storage(const char* volume_uuid, userid_t user_id, int flags); __END_DECLS diff --git a/Utils.cpp b/Utils.cpp index 9d5f168..7ae22c5 100644 --- a/Utils.cpp +++ b/Utils.cpp @@ -560,6 +560,10 @@ std::string BuildKeyPath(const std::string& partGuid) { return StringPrintf("%s/expand_%s.key", kKeyPath, partGuid.c_str()); } +std::string BuildDataSystemLegacyPath(userid_t userId) { + return StringPrintf("%s/system/users/%u", BuildDataPath(nullptr).c_str(), userId); +} + std::string BuildDataSystemCePath(userid_t userId) { return StringPrintf("%s/system_ce/%u", BuildDataPath(nullptr).c_str(), userId); } @@ -568,6 +572,10 @@ std::string BuildDataSystemDePath(userid_t userId) { return StringPrintf("%s/system_de/%u", BuildDataPath(nullptr).c_str(), userId); } +std::string BuildDataMiscLegacyPath(userid_t userId) { + return StringPrintf("%s/misc/user/%u", BuildDataPath(nullptr).c_str(), userId); +} + std::string BuildDataMiscCePath(userid_t userId) { return StringPrintf("%s/misc_ce/%u", BuildDataPath(nullptr).c_str(), userId); } @@ -596,13 +604,13 @@ std::string BuildDataPath(const char* volumeUuid) { } } -std::string BuildDataMediaPath(const char* volumeUuid, userid_t userId) { +std::string BuildDataMediaCePath(const char* volumeUuid, userid_t userId) { // TODO: unify with installd path generation logic std::string data(BuildDataPath(volumeUuid)); return StringPrintf("%s/media/%u", data.c_str(), userId); } -std::string BuildDataUserPath(const char* volumeUuid, userid_t userId) { +std::string BuildDataUserCePath(const char* volumeUuid, userid_t userId) { // TODO: unify with installd path generation logic std::string data(BuildDataPath(volumeUuid)); if (volumeUuid == nullptr) { diff --git a/Utils.h b/Utils.h index d2970e7..9abd322 100644 --- a/Utils.h +++ b/Utils.h @@ -96,16 +96,18 @@ status_t WipeBlockDevice(const std::string& path); std::string BuildKeyPath(const std::string& partGuid); +std::string BuildDataSystemLegacyPath(userid_t userid); std::string BuildDataSystemCePath(userid_t userid); std::string BuildDataSystemDePath(userid_t userid); +std::string BuildDataMiscLegacyPath(userid_t userid); std::string BuildDataMiscCePath(userid_t userid); std::string BuildDataMiscDePath(userid_t userid); std::string BuildDataProfilesDePath(userid_t userid); std::string BuildDataProfilesForeignDexDePath(userid_t userid); std::string BuildDataPath(const char* volumeUuid); -std::string BuildDataMediaPath(const char* volumeUuid, userid_t userid); -std::string BuildDataUserPath(const char* volumeUuid, userid_t userid); +std::string BuildDataMediaCePath(const char* volumeUuid, userid_t userid); +std::string BuildDataUserCePath(const char* volumeUuid, userid_t userid); std::string BuildDataUserDePath(const char* volumeUuid, userid_t userid); dev_t GetDevice(const std::string& path);