[automerger skipped] KeyStorage: don't request rollback resistance for wrapped storage keys am: e11788d0f0 -s ours
am skip reason: Merged-In I648a1af9e16787dfcfeefa2b2f2e4a72cac2c6a6 with SHA-1 2d30b890d2 is already in history
Original change: https://googleplex-android-review.googlesource.com/c/platform/system/vold/+/19499522
Change-Id: I4f23a56ba26c4a2531524b51f278079dd04215fe
Signed-off-by: Automerger Merge Worker <android-build-automerger-merge-worker@system.gserviceaccount.com>
diff --git a/Android.bp b/Android.bp
index 8f413c4..6fb9c6c 100644
--- a/Android.bp
+++ b/Android.bp
@@ -19,8 +19,9 @@
"clang-analyzer-security*",
"android-*",
],
- tidy_flags: [
- "-warnings-as-errors=clang-analyzer-security*,cert-*",
+ tidy_checks_as_errors: [
+ "clang-analyzer-security*",
+ "cert-*",
],
}
@@ -42,6 +43,8 @@
],
shared_libs: [
"android.hardware.boot@1.0",
+ "android.hardware.boot-V1-ndk",
+ "libboot_control_client",
"libbase",
"libbinder",
"libcrypto",
@@ -187,7 +190,7 @@
required: [
"mke2fs",
"vold_prepare_subdirs",
- "fuse_media.o",
+ "fuseMedia.o",
],
shared_libs: [
diff --git a/Checkpoint.cpp b/Checkpoint.cpp
index 755f0e3..948231d 100644
--- a/Checkpoint.cpp
+++ b/Checkpoint.cpp
@@ -26,12 +26,12 @@
#include <thread>
#include <vector>
+#include <BootControlClient.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/parseint.h>
#include <android-base/properties.h>
#include <android-base/unique_fd.h>
-#include <android/hardware/boot/1.0/IBootControl.h>
#include <cutils/android_reboot.h>
#include <fcntl.h>
#include <fs_mgr.h>
@@ -48,11 +48,7 @@
using android::binder::Status;
using android::fs_mgr::Fstab;
using android::fs_mgr::ReadFstabFromFile;
-using android::hardware::hidl_string;
-using android::hardware::boot::V1_0::BoolResult;
-using android::hardware::boot::V1_0::CommandResult;
-using android::hardware::boot::V1_0::IBootControl;
-using android::hardware::boot::V1_0::Slot;
+using android::hal::BootControlClient;
namespace android {
namespace vold {
@@ -128,11 +124,10 @@
if (retry < -1) return error(EINVAL, "Retry count must be more than -1");
std::string content = std::to_string(retry + 1);
if (retry == -1) {
- sp<IBootControl> module = IBootControl::getService();
+ auto module = BootControlClient::WaitForService();
if (module) {
- std::string suffix;
- auto cb = [&suffix](hidl_string s) { suffix = s; };
- if (module->getSuffix(module->getCurrentSlot(), cb).isOk()) content += " " + suffix;
+ std::string suffix = module->GetSuffix(module->GetCurrentSlot());
+ if (!suffix.empty()) content += " " + suffix;
}
}
if (!android::base::WriteStringToFile(content, kMetadataCPFile))
@@ -162,10 +157,9 @@
<< "NOT COMMITTING CHECKPOINT BECAUSE persist.vold.dont_commit_checkpoint IS 1";
return Status::ok();
}
- sp<IBootControl> module = IBootControl::getService();
+ auto module = BootControlClient::WaitForService();
if (module) {
- CommandResult cr;
- module->markBootSuccessful([&cr](CommandResult result) { cr = result; });
+ auto cr = module->MarkBootSuccessful();
if (!cr.success)
return error(EINVAL, "Error marking booted successfully: " + std::string(cr.errMsg));
LOG(INFO) << "Marked slot as booted successfully.";
@@ -173,6 +167,8 @@
if (!SetProperty("ota.warm_reset", "0")) {
LOG(WARNING) << "Failed to reset the warm reset flag";
}
+ } else {
+ LOG(ERROR) << "Failed to get BootControl HAL, not marking slot as successful.";
}
// Must take action for list of mounted checkpointed things here
// To do this, we walk the list of mounted file systems.
@@ -254,12 +250,11 @@
if (content == "0") return true;
if (content.substr(0, 3) == "-1 ") {
std::string oldSuffix = content.substr(3);
- sp<IBootControl> module = IBootControl::getService();
+ auto module = BootControlClient::WaitForService();
std::string newSuffix;
if (module) {
- auto cb = [&newSuffix](hidl_string s) { newSuffix = s; };
- module->getSuffix(module->getCurrentSlot(), cb);
+ newSuffix = module->GetSuffix(module->GetCurrentSlot());
if (oldSuffix == newSuffix) return true;
}
}
@@ -276,11 +271,11 @@
bool ret;
std::string content;
- sp<IBootControl> module = IBootControl::getService();
+ auto module = BootControlClient::WaitForService();
if (isCheckpointing) return isCheckpointing;
-
- if (module && module->isSlotMarkedSuccessful(module->getCurrentSlot()) == BoolResult::FALSE) {
+ // In case of INVALID slot or other failures, we do not perform checkpoint.
+ if (module && !module->IsSlotMarkedSuccessful(module->GetCurrentSlot()).value_or(true)) {
isCheckpointing = true;
return true;
}
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 6c08177..5bc55d0 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -33,7 +33,6 @@
#include <errno.h>
#include <fcntl.h>
#include <limits.h>
-#include <selinux/android.h>
#include <sys/mount.h>
#include <sys/stat.h>
#include <sys/types.h>
@@ -44,7 +43,6 @@
#include "android/os/IVold.h"
-#define EMULATED_USES_SELINUX 0
#define MANAGE_MISC_DIRS 0
#include <cutils/fs.h>
@@ -94,9 +92,16 @@
const std::string systemwide_volume_key_dir =
std::string() + DATA_MNT_POINT + "/misc/vold/volume_keys";
+const std::string data_data_dir = std::string() + DATA_MNT_POINT + "/data";
+const std::string data_user_0_dir = std::string() + DATA_MNT_POINT + "/user/0";
+const std::string media_obb_dir = std::string() + DATA_MNT_POINT + "/media/obb";
+
// Some users are ephemeral, don't try to wipe their keys from disk
std::set<userid_t> s_ephemeral_users;
+// The system DE encryption policy
+EncryptionPolicy s_device_policy;
+
// Map user ids to encryption policies
std::map<userid_t, EncryptionPolicy> s_de_policies;
std::map<userid_t, EncryptionPolicy> s_ce_policies;
@@ -108,10 +113,6 @@
return KeyGeneration{FSCRYPT_MAX_KEY_SIZE, true, options.use_hw_wrapped_key};
}
-static bool fscrypt_is_emulated() {
- return property_get_bool("persist.sys.emulate_fbe", false);
-}
-
static const char* escape_empty(const std::string& value) {
return value.empty() ? "null" : value.c_str();
}
@@ -307,15 +308,26 @@
return true;
}
+// Prepare a directory without assigning it an encryption policy. The directory
+// will inherit the encryption policy of its parent directory, or will be
+// unencrypted if the parent directory is unencrypted.
static bool prepare_dir(const std::string& dir, mode_t mode, uid_t uid, gid_t gid) {
LOG(DEBUG) << "Preparing: " << dir;
- if (fs_prepare_dir(dir.c_str(), mode, uid, gid) != 0) {
+ if (android::vold::PrepareDir(dir, mode, uid, gid, 0) != 0) {
PLOG(ERROR) << "Failed to prepare " << dir;
return false;
}
return true;
}
+// Prepare a directory and assign it the given encryption policy.
+static bool prepare_dir_with_policy(const std::string& dir, mode_t mode, uid_t uid, gid_t gid,
+ const EncryptionPolicy& policy) {
+ if (!prepare_dir(dir, mode, uid, gid)) return false;
+ if (IsFbeEnabled() && !EnsurePolicy(policy, dir)) return false;
+ return true;
+}
+
static bool destroy_dir(const std::string& dir) {
LOG(DEBUG) << "Destroying: " << dir;
if (rmdir(dir.c_str()) != 0 && errno != ENOENT) {
@@ -365,7 +377,6 @@
EncryptionPolicy* policy) {
auto refi = key_map.find(user_id);
if (refi == key_map.end()) {
- LOG(DEBUG) << "Cannot find key for " << user_id;
return false;
}
*policy = refi->second;
@@ -443,11 +454,12 @@
makeGen(options), &device_key))
return false;
- EncryptionPolicy device_policy;
- if (!install_storage_key(DATA_MNT_POINT, options, device_key, &device_policy)) return false;
+ // This initializes s_device_policy, which is a global variable so that
+ // fscrypt_init_user0() can access it later.
+ if (!install_storage_key(DATA_MNT_POINT, options, device_key, &s_device_policy)) return false;
std::string options_string;
- if (!OptionsToString(device_policy.options, &options_string)) {
+ if (!OptionsToString(s_device_policy.options, &options_string)) {
LOG(ERROR) << "Unable to serialize options";
return false;
}
@@ -455,7 +467,7 @@
if (!android::vold::writeStringToFile(options_string, options_filename)) return false;
std::string ref_filename = std::string(DATA_MNT_POINT) + fscrypt_key_ref;
- if (!android::vold::writeStringToFile(device_policy.key_raw_ref, ref_filename)) return false;
+ if (!android::vold::writeStringToFile(s_device_policy.key_raw_ref, ref_filename)) return false;
LOG(INFO) << "Wrote system DE key reference to:" << ref_filename;
KeyBuffer per_boot_key;
@@ -470,11 +482,58 @@
return true;
}
+static bool prepare_special_dirs() {
+ // Ensure that /data/data and its "alias" /data/user/0 exist, and create the
+ // bind mount of /data/data onto /data/user/0. This *should* happen in
+ // fscrypt_prepare_user_storage(). However, it actually must be done early,
+ // before the rest of user 0's CE storage is prepared. This is because
+ // zygote may need to set up app data isolation before then, which requires
+ // mounting a tmpfs over /data/data to ensure it remains hidden. This issue
+ // arises due to /data/data being in the top-level directory.
+
+ // /data/user/0 used to be a symlink to /data/data, so we must first delete
+ // the old symlink if present.
+ if (android::vold::IsSymlink(data_user_0_dir) && android::vold::Unlink(data_user_0_dir) != 0)
+ return false;
+ // On first boot, we'll be creating /data/data for the first time, and user
+ // 0's CE key will be installed already since it was just created. Take the
+ // opportunity to also set the encryption policy of /data/data right away.
+ EncryptionPolicy ce_policy;
+ if (lookup_policy(s_ce_policies, 0, &ce_policy)) {
+ if (!prepare_dir_with_policy(data_data_dir, 0771, AID_SYSTEM, AID_SYSTEM, ce_policy))
+ return false;
+ } else {
+ if (!prepare_dir(data_data_dir, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
+ // EnsurePolicy() will have to happen later, in fscrypt_prepare_user_storage().
+ }
+ if (!prepare_dir(data_user_0_dir, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
+ if (android::vold::BindMount(data_data_dir, data_user_0_dir) != 0) return false;
+
+ // If /data/media/obb doesn't exist, create it and encrypt it with the
+ // device policy. Normally, device-policy-encrypted directories are created
+ // and encrypted by init; /data/media/obb is special because it is located
+ // in /data/media. Since /data/media also contains per-user encrypted
+ // directories, by design only vold can write to it. As a side effect of
+ // that, vold must create /data/media/obb.
+ //
+ // We must tolerate /data/media/obb being unencrypted if it already exists
+ // on-disk, since it used to be unencrypted (b/64566063).
+ if (android::vold::pathExists(media_obb_dir)) {
+ if (!prepare_dir(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
+ } else {
+ if (!prepare_dir_with_policy(media_obb_dir, 0770, AID_MEDIA_RW, AID_MEDIA_RW,
+ s_device_policy))
+ return false;
+ }
+ return true;
+}
+
bool fscrypt_init_user0_done;
bool fscrypt_init_user0() {
LOG(DEBUG) << "fscrypt_init_user0";
- if (fscrypt_is_native()) {
+
+ if (IsFbeEnabled()) {
if (!prepare_dir(user_key_dir, 0700, AID_ROOT, AID_ROOT)) return false;
if (!prepare_dir(user_key_dir + "/ce", 0700, AID_ROOT, AID_ROOT)) return false;
if (!prepare_dir(user_key_dir + "/de", 0700, AID_ROOT, AID_ROOT)) return false;
@@ -485,24 +544,23 @@
// explicit calls to install DE keys for secondary users
if (!load_all_de_keys()) return false;
}
- // We can only safely prepare DE storage here, since CE keys are probably
- // entangled with user credentials. The framework will always prepare CE
- // storage once CE keys are installed.
+
+ // Now that user 0's CE key has been created, we can prepare /data/data.
+ if (!prepare_special_dirs()) return false;
+
+ // With the exception of what is done by prepare_special_dirs() above, we
+ // only prepare DE storage here, since user 0's CE key won't be installed
+ // yet unless it was just created. The framework will prepare the user's CE
+ // storage later, once their CE key is installed.
if (!fscrypt_prepare_user_storage("", 0, 0, android::os::IVold::STORAGE_FLAG_DE)) {
LOG(ERROR) << "Failed to prepare user 0 storage";
return false;
}
- // If this is a non-FBE device that recently left an emulated mode,
- // restore user data directories to known-good state.
- if (!fscrypt_is_native() && !fscrypt_is_emulated()) {
- fscrypt_unlock_user_key(0, 0, "!");
- }
-
// In some scenarios (e.g. userspace reboot) we might unmount userdata
// without doing a hard reboot. If CE keys were stored in fs keyring then
// they will be lost after unmount. Attempt to re-install them.
- if (fscrypt_is_native() && android::vold::isFsKeyringSupported()) {
+ if (IsFbeEnabled() && android::vold::isFsKeyringSupported()) {
if (!try_reload_ce_keys()) return false;
}
@@ -512,7 +570,7 @@
bool fscrypt_vold_create_user_key(userid_t user_id, int serial, bool ephemeral) {
LOG(DEBUG) << "fscrypt_vold_create_user_key for " << user_id << " serial " << serial;
- if (!fscrypt_is_native()) {
+ if (!IsFbeEnabled()) {
return true;
}
// FIXME test for existence of key that is not loaded yet
@@ -563,7 +621,7 @@
bool fscrypt_destroy_user_key(userid_t user_id) {
LOG(DEBUG) << "fscrypt_destroy_user_key(" << user_id << ")";
- if (!fscrypt_is_native()) {
+ if (!IsFbeEnabled()) {
return true;
}
bool success = true;
@@ -592,36 +650,6 @@
return success;
}
-static bool emulated_lock(const std::string& path) {
- if (chmod(path.c_str(), 0000) != 0) {
- PLOG(ERROR) << "Failed to chmod " << path;
- return false;
- }
-#if EMULATED_USES_SELINUX
- if (setfilecon(path.c_str(), "u:object_r:storage_stub_file:s0") != 0) {
- PLOG(WARNING) << "Failed to setfilecon " << path;
- return false;
- }
-#endif
- return true;
-}
-
-static bool emulated_unlock(const std::string& path, mode_t mode) {
- if (chmod(path.c_str(), mode) != 0) {
- PLOG(ERROR) << "Failed to chmod " << path;
- // FIXME temporary workaround for b/26713622
- if (fscrypt_is_emulated()) return false;
- }
-#if EMULATED_USES_SELINUX
- if (selinux_android_restorecon(path.c_str(), SELINUX_ANDROID_RESTORECON_FORCE) != 0) {
- PLOG(WARNING) << "Failed to restorecon " << path;
- // FIXME temporary workaround for b/26713622
- if (fscrypt_is_emulated()) return false;
- }
-#endif
- return true;
-}
-
static bool parse_hex(const std::string& hex, std::string* result) {
if (hex == "!") {
*result = "";
@@ -712,7 +740,7 @@
bool fscrypt_add_user_key_auth(userid_t user_id, int serial, const std::string& secret_hex) {
LOG(DEBUG) << "fscrypt_add_user_key_auth " << user_id << " serial=" << serial;
- if (!fscrypt_is_native()) return true;
+ if (!IsFbeEnabled()) return true;
auto auth = authentication_from_hex(secret_hex);
if (!auth) return false;
return fscrypt_rewrap_user_key(user_id, serial, kEmptyAuthentication, *auth);
@@ -720,7 +748,7 @@
bool fscrypt_clear_user_key_auth(userid_t user_id, int serial, const std::string& secret_hex) {
LOG(DEBUG) << "fscrypt_clear_user_key_auth " << user_id << " serial=" << serial;
- if (!fscrypt_is_native()) return true;
+ if (!IsFbeEnabled()) return true;
auto auth = authentication_from_hex(secret_hex);
if (!auth) return false;
return fscrypt_rewrap_user_key(user_id, serial, *auth, kEmptyAuthentication);
@@ -728,7 +756,7 @@
bool fscrypt_fixate_newest_user_key_auth(userid_t user_id) {
LOG(DEBUG) << "fscrypt_fixate_newest_user_key_auth " << user_id;
- if (!fscrypt_is_native()) return true;
+ if (!IsFbeEnabled()) return true;
if (s_ephemeral_users.count(user_id) != 0) return true;
auto const directory_path = get_ce_key_directory_path(user_id);
auto const paths = get_ce_key_paths(directory_path);
@@ -751,7 +779,7 @@
// TODO: rename to 'install' for consistency, and take flags to know which keys to install
bool fscrypt_unlock_user_key(userid_t user_id, int serial, const std::string& secret_hex) {
LOG(DEBUG) << "fscrypt_unlock_user_key " << user_id << " serial=" << serial;
- if (fscrypt_is_native()) {
+ if (IsFbeEnabled()) {
if (s_ce_policies.count(user_id) != 0) {
LOG(WARNING) << "Tried to unlock already-unlocked key for user " << user_id;
return true;
@@ -762,17 +790,6 @@
LOG(ERROR) << "Couldn't read key for " << user_id;
return false;
}
- } else {
- // When in emulation mode, we just use chmod. However, we also
- // unlock directories when not in emulation mode, to bring devices
- // 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::BuildDataMediaCePath("", user_id), 0770) ||
- !emulated_unlock(android::vold::BuildDataUserCePath("", user_id), 0771)) {
- LOG(ERROR) << "Failed to unlock user " << user_id;
- return false;
- }
}
return true;
}
@@ -780,19 +797,9 @@
// TODO: rename to 'evict' for consistency
bool fscrypt_lock_user_key(userid_t user_id) {
LOG(DEBUG) << "fscrypt_lock_user_key " << user_id;
- if (fscrypt_is_native()) {
+ if (IsFbeEnabled()) {
return evict_ce_key(user_id);
- } else if (fscrypt_is_emulated()) {
- // 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::BuildDataMediaCePath("", user_id)) ||
- !emulated_lock(android::vold::BuildDataUserCePath("", user_id))) {
- LOG(ERROR) << "Failed to lock user " << user_id;
- return false;
- }
}
-
return true;
}
@@ -836,11 +843,26 @@
auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
// DE_n key
+ EncryptionPolicy de_policy;
auto system_de_path = android::vold::BuildDataSystemDePath(user_id);
auto misc_de_path = android::vold::BuildDataMiscDePath(volume_uuid, user_id);
auto vendor_de_path = android::vold::BuildDataVendorDePath(user_id);
auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
+ if (IsFbeEnabled()) {
+ if (volume_uuid.empty()) {
+ if (!lookup_policy(s_de_policies, user_id, &de_policy)) {
+ LOG(ERROR) << "Cannot find DE policy for user " << user_id;
+ return false;
+ }
+ } else {
+ auto misc_de_empty_volume_path = android::vold::BuildDataMiscDePath("", user_id);
+ if (!read_or_create_volkey(misc_de_empty_volume_path, volume_uuid, &de_policy)) {
+ return false;
+ }
+ }
+ }
+
if (volume_uuid.empty()) {
if (!prepare_dir(system_legacy_path, 0700, AID_SYSTEM, AID_SYSTEM)) return false;
#if MANAGE_MISC_DIRS
@@ -850,43 +872,49 @@
#endif
if (!prepare_dir(profiles_de_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
- if (!prepare_dir(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
- if (!prepare_dir(vendor_de_path, 0771, AID_ROOT, AID_ROOT)) return false;
+ if (!prepare_dir_with_policy(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM, de_policy))
+ return false;
+ if (!prepare_dir_with_policy(vendor_de_path, 0771, AID_ROOT, AID_ROOT, de_policy))
+ 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 (fscrypt_is_native()) {
- EncryptionPolicy de_policy;
- if (volume_uuid.empty()) {
- if (!lookup_policy(s_de_policies, user_id, &de_policy)) return false;
- if (!EnsurePolicy(de_policy, system_de_path)) return false;
- if (!EnsurePolicy(de_policy, vendor_de_path)) return false;
- } else {
- auto misc_de_empty_volume_path = android::vold::BuildDataMiscDePath("", user_id);
- if (!read_or_create_volkey(misc_de_empty_volume_path, volume_uuid, &de_policy)) {
- return false;
- }
- }
- if (!EnsurePolicy(de_policy, misc_de_path)) return false;
- if (!EnsurePolicy(de_policy, user_de_path)) return false;
- }
+ if (!prepare_dir_with_policy(misc_de_path, 01771, AID_SYSTEM, AID_MISC, de_policy))
+ return false;
+ if (!prepare_dir_with_policy(user_de_path, 0771, AID_SYSTEM, AID_SYSTEM, de_policy))
+ return false;
}
if (flags & android::os::IVold::STORAGE_FLAG_CE) {
// CE_n key
+ EncryptionPolicy ce_policy;
auto system_ce_path = android::vold::BuildDataSystemCePath(user_id);
auto misc_ce_path = android::vold::BuildDataMiscCePath(volume_uuid, user_id);
auto vendor_ce_path = android::vold::BuildDataVendorCePath(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.empty()) {
- if (!prepare_dir(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM)) return false;
- if (!prepare_dir(vendor_ce_path, 0771, AID_ROOT, AID_ROOT)) return false;
+ if (IsFbeEnabled()) {
+ if (volume_uuid.empty()) {
+ if (!lookup_policy(s_ce_policies, user_id, &ce_policy)) {
+ LOG(ERROR) << "Cannot find CE policy for user " << user_id;
+ return false;
+ }
+ } else {
+ auto misc_ce_empty_volume_path = android::vold::BuildDataMiscCePath("", user_id);
+ if (!read_or_create_volkey(misc_ce_empty_volume_path, volume_uuid, &ce_policy)) {
+ return false;
+ }
+ }
}
- if (!prepare_dir(media_ce_path, 02770, AID_MEDIA_RW, AID_MEDIA_RW)) return false;
+
+ if (volume_uuid.empty()) {
+ if (!prepare_dir_with_policy(system_ce_path, 0770, AID_SYSTEM, AID_SYSTEM, ce_policy))
+ return false;
+ if (!prepare_dir_with_policy(vendor_ce_path, 0771, AID_ROOT, AID_ROOT, ce_policy))
+ return false;
+ }
+ if (!prepare_dir_with_policy(media_ce_path, 02770, AID_MEDIA_RW, AID_MEDIA_RW, ce_policy))
+ return false;
// On devices without sdcardfs (kernel 5.4+), the path permissions aren't fixed
// up automatically; therefore, use a default ACL, to ensure apps with MEDIA_RW
// can keep reading external storage; in particular, this allows app cloning
@@ -895,26 +923,10 @@
if (ret != android::OK) {
return false;
}
-
- if (!prepare_dir(misc_ce_path, 01771, AID_SYSTEM, AID_MISC)) return false;
- if (!prepare_dir(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM)) return false;
-
- if (fscrypt_is_native()) {
- EncryptionPolicy ce_policy;
- if (volume_uuid.empty()) {
- if (!lookup_policy(s_ce_policies, user_id, &ce_policy)) return false;
- if (!EnsurePolicy(ce_policy, system_ce_path)) return false;
- if (!EnsurePolicy(ce_policy, vendor_ce_path)) return false;
- } else {
- auto misc_ce_empty_volume_path = android::vold::BuildDataMiscCePath("", user_id);
- if (!read_or_create_volkey(misc_ce_empty_volume_path, volume_uuid, &ce_policy)) {
- return false;
- }
- }
- if (!EnsurePolicy(ce_policy, media_ce_path)) return false;
- if (!EnsurePolicy(ce_policy, misc_ce_path)) return false;
- if (!EnsurePolicy(ce_policy, user_ce_path)) return false;
- }
+ if (!prepare_dir_with_policy(misc_ce_path, 01771, AID_SYSTEM, AID_MISC, ce_policy))
+ return false;
+ if (!prepare_dir_with_policy(user_ce_path, 0771, AID_SYSTEM, AID_SYSTEM, ce_policy))
+ return false;
if (volume_uuid.empty()) {
// Now that credentials have been installed, we can run restorecon
@@ -952,7 +964,7 @@
res &= destroy_dir(system_ce_path);
res &= destroy_dir(vendor_ce_path);
} else {
- if (fscrypt_is_native()) {
+ if (IsFbeEnabled()) {
auto misc_ce_empty_volume_path = android::vold::BuildDataMiscCePath("", user_id);
res &= destroy_volkey(misc_ce_empty_volume_path, volume_uuid);
}
@@ -982,7 +994,7 @@
res &= destroy_dir(system_de_path);
res &= destroy_dir(vendor_de_path);
} else {
- if (fscrypt_is_native()) {
+ if (IsFbeEnabled()) {
auto misc_de_empty_volume_path = android::vold::BuildDataMiscDePath("", user_id);
res &= destroy_volkey(misc_de_empty_volume_path, volume_uuid);
}
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index 9d3450a..0c6b115 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -86,7 +86,6 @@
static const int GC_TIMEOUT_SEC = 420;
static const int DEVGC_TIMEOUT_SEC = 120;
static const int KBYTES_IN_SEGMENT = 2048;
-static const int MIN_GC_URGENT_SLEEP_TIME = 500;
static const int ONE_MINUTE_IN_MS = 60000;
static const int GC_NORMAL_MODE = 0;
static const int GC_URGENT_MID_MODE = 3;
@@ -509,9 +508,10 @@
}
void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
- float reclaimWeight, int32_t gcPeriod) {
+ float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime,
+ int32_t targetDirtyRatio) {
std::list<std::string> paths;
- bool needGC = true;
+ bool needGC = false;
int32_t sleepTime;
addFromFstab(&paths, PathTypes::kBlkDevice, true);
@@ -554,25 +554,36 @@
int32_t reservedBlocks = std::stoi(ovpSegmentsStr) + std::stoi(reservedBlocksStr);
freeSegments = freeSegments > reservedBlocks ? freeSegments - reservedBlocks : 0;
- neededSegments *= reclaimWeight;
- if (freeSegments >= neededSegments) {
- LOG(INFO) << "Enough free segments: " << freeSegments
- << ", needed segments: " << neededSegments;
- needGC = false;
- } else if (freeSegments + dirtySegments < minSegmentThreshold) {
+ int32_t totalSegments = freeSegments + dirtySegments;
+ int32_t finalTargetSegments = 0;
+
+ if (totalSegments < minSegmentThreshold) {
LOG(INFO) << "The sum of free segments: " << freeSegments
- << ", dirty segments: " << dirtySegments << " is under " << minSegmentThreshold;
- needGC = false;
+ << ", dirty segments: " << dirtySegments << " is under " << minSegmentThreshold;
} else {
- neededSegments -= freeSegments;
- neededSegments = std::min(neededSegments, (int32_t)(dirtySegments * dirtyReclaimRate));
- if (neededSegments == 0) {
- LOG(INFO) << "Low dirty segments: " << dirtySegments;
- needGC = false;
+ int32_t dirtyRatio = dirtySegments * 100 / totalSegments;
+ int32_t neededForTargetRatio =
+ (dirtyRatio > targetDirtyRatio)
+ ? totalSegments * (dirtyRatio - targetDirtyRatio) / 100
+ : 0;
+ neededSegments *= reclaimWeight;
+ neededSegments = (neededSegments > freeSegments) ? neededSegments - freeSegments : 0;
+
+ finalTargetSegments = std::max(neededSegments, neededForTargetRatio);
+ if (finalTargetSegments == 0) {
+ LOG(INFO) << "Enough free segments: " << freeSegments;
} else {
- sleepTime = gcPeriod * ONE_MINUTE_IN_MS / neededSegments;
- if (sleepTime < MIN_GC_URGENT_SLEEP_TIME) {
- sleepTime = MIN_GC_URGENT_SLEEP_TIME;
+ finalTargetSegments =
+ std::min(finalTargetSegments, (int32_t)(dirtySegments * dirtyReclaimRate));
+ if (finalTargetSegments == 0) {
+ LOG(INFO) << "Low dirty segments: " << dirtySegments;
+ } else if (neededSegments >= neededForTargetRatio) {
+ LOG(INFO) << "Trigger GC, because of needed segments exceeding free segments";
+ needGC = true;
+ } else {
+ LOG(INFO) << "Trigger GC for target dirty ratio diff of: "
+ << dirtyRatio - targetDirtyRatio;
+ needGC = true;
}
}
}
@@ -584,6 +595,11 @@
return;
}
+ sleepTime = gcPeriod * ONE_MINUTE_IN_MS / finalTargetSegments;
+ if (sleepTime < minGCSleepTime) {
+ sleepTime = minGCSleepTime;
+ }
+
if (!WriteStringToFile(std::to_string(sleepTime), gcSleepTimePath)) {
PLOG(WARNING) << "Writing failed in " << gcSleepTimePath;
return;
@@ -595,8 +611,8 @@
}
LOG(INFO) << "Successfully set gc urgent mode: "
- << "free segments: " << freeSegments << ", reclaim target: " << neededSegments
- << ", sleep time: " << sleepTime;
+ << "free segments: " << freeSegments << ", reclaim target: " << finalTargetSegments
+ << ", sleep time: " << sleepTime;
}
static int32_t getLifeTimeWrite() {
diff --git a/IdleMaint.h b/IdleMaint.h
index 9a2af4a..a28cde2 100644
--- a/IdleMaint.h
+++ b/IdleMaint.h
@@ -27,7 +27,8 @@
int AbortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
int32_t GetStorageLifeTime();
void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
- float reclaimWeight, int32_t gcPeriod);
+ float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime,
+ int32_t targetDirtyRatio);
void RefreshLatestWrite();
int32_t GetWriteAmount();
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index 5c9e644..4152e25 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -63,6 +63,7 @@
};
static const std::string kDmNameUserdata = "userdata";
+static const std::string kDmNameUserdataZoned = "userdata_zoned";
// The first entry in this table is the default crypto type.
constexpr CryptoType supported_crypto_types[] = {aes_256_xts, adiantum};
@@ -238,10 +239,11 @@
bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::string& mount_point,
bool needs_encrypt, bool should_format,
- const std::string& fs_type) {
+ const std::string& fs_type, const std::string& zoned_device) {
LOG(DEBUG) << "fscrypt_mount_metadata_encrypted: " << mount_point
<< " encrypt: " << needs_encrypt << " format: " << should_format << " with "
- << fs_type;
+ << fs_type << " block device: " << blk_device
+ << " and zoned device: " << zoned_device;
auto encrypted_state = android::base::GetProperty("ro.crypto.state", "");
if (encrypted_state != "" && encrypted_state != "encrypted") {
LOG(ERROR) << "fscrypt_mount_metadata_encrypted got unexpected starting state: "
@@ -280,9 +282,13 @@
return false;
}
+ auto default_metadata_key_dir = data_rec->metadata_key_dir;
+ if (!zoned_device.empty()) {
+ default_metadata_key_dir = default_metadata_key_dir + "/default";
+ }
auto gen = needs_encrypt ? makeGen(options) : neverGen();
KeyBuffer key;
- if (!read_key(data_rec->metadata_key_dir, gen, &key)) {
+ if (!read_key(default_metadata_key_dir, gen, &key)) {
LOG(ERROR) << "read_key failed in mountFstab";
return false;
}
@@ -295,6 +301,23 @@
return false;
}
+ // create dm-default-key for zoned device
+ std::string crypto_zoned_blkdev;
+ if (!zoned_device.empty()) {
+ auto zoned_metadata_key_dir = data_rec->metadata_key_dir + "/zoned";
+
+ if (!read_key(zoned_metadata_key_dir, gen, &key)) {
+ LOG(ERROR) << "read_key failed with zoned device: " << zoned_device;
+ return false;
+ }
+ if (!create_crypto_blk_dev(kDmNameUserdataZoned, zoned_device, key, options,
+ &crypto_zoned_blkdev, &nr_sec)) {
+ LOG(ERROR) << "fscrypt_mount_metadata_encrypted: failed with zoned device: "
+ << zoned_device;
+ return false;
+ }
+ }
+
if (needs_encrypt) {
if (should_format) {
status_t error;
@@ -302,7 +325,7 @@
if (fs_type == "ext4") {
error = ext4::Format(crypto_blkdev, 0, mount_point);
} else if (fs_type == "f2fs") {
- error = f2fs::Format(crypto_blkdev);
+ error = f2fs::Format(crypto_blkdev, crypto_zoned_blkdev);
} else {
LOG(ERROR) << "Unknown filesystem type: " << fs_type;
return false;
@@ -314,6 +337,10 @@
}
LOG(DEBUG) << "Format of " << crypto_blkdev << " for " << mount_point << " succeeded.";
} else {
+ if (!zoned_device.empty()) {
+ LOG(ERROR) << "encrypt_inplace cannot support zoned device; should format it.";
+ return false;
+ }
if (!encrypt_inplace(crypto_blkdev, blk_device, nr_sec)) {
LOG(ERROR) << "encrypt_inplace failed in mountFstab";
return false;
diff --git a/MetadataCrypt.h b/MetadataCrypt.h
index 06131ad..f6d6b8e 100644
--- a/MetadataCrypt.h
+++ b/MetadataCrypt.h
@@ -28,7 +28,8 @@
void defaultkey_precreate_dm_device();
bool fscrypt_mount_metadata_encrypted(const std::string& block_device,
const std::string& mount_point, bool needs_encrypt,
- bool should_format, const std::string& fs_type);
+ bool should_format, const std::string& fs_type,
+ const std::string& zoned_device);
bool defaultkey_volume_keygen(KeyGeneration* gen);
diff --git a/Utils.cpp b/Utils.cpp
index e8049ed..9e77a9e 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1160,14 +1160,6 @@
std::string BuildDataUserCePath(const std::string& volumeUuid, userid_t userId) {
// TODO: unify with installd path generation logic
std::string data(BuildDataPath(volumeUuid));
- if (volumeUuid.empty() && userId == 0) {
- std::string legacy = StringPrintf("%s/data", data.c_str());
- struct stat sb;
- if (lstat(legacy.c_str(), &sb) == 0 && S_ISDIR(sb.st_mode)) {
- /* /data/data is dir, return /data/data for legacy system */
- return legacy;
- }
- }
return StringPrintf("%s/user/%u", data.c_str(), userId);
}
@@ -1187,6 +1179,12 @@
}
}
+// Returns true if |path| exists and is a symlink.
+bool IsSymlink(const std::string& path) {
+ struct stat stbuf;
+ return lstat(path.c_str(), &stbuf) == 0 && S_ISLNK(stbuf.st_mode);
+}
+
// Returns true if |path1| names the same existing file or directory as |path2|.
bool IsSameFile(const std::string& path1, const std::string& path2) {
struct stat stbuf1, stbuf2;
diff --git a/Utils.h b/Utils.h
index 429669b..fbd0f30 100644
--- a/Utils.h
+++ b/Utils.h
@@ -162,6 +162,8 @@
dev_t GetDevice(const std::string& path);
+bool IsSymlink(const std::string& path);
+
bool IsSameFile(const std::string& path1, const std::string& path2);
status_t EnsureDirExists(const std::string& path, mode_t mode, uid_t uid, gid_t gid);
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 8ba3aaf..ea2c98c 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -495,11 +495,13 @@
binder::Status VoldNativeService::setGCUrgentPace(int32_t neededSegments,
int32_t minSegmentThreshold,
float dirtyReclaimRate, float reclaimWeight,
- int32_t gcPeriod) {
+ int32_t gcPeriod, int32_t minGCSleepTime,
+ int32_t targetDirtyRatio) {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
- SetGCUrgentPace(neededSegments, minSegmentThreshold, dirtyReclaimRate, reclaimWeight, gcPeriod);
+ SetGCUrgentPace(neededSegments, minSegmentThreshold, dirtyReclaimRate, reclaimWeight, gcPeriod,
+ minGCSleepTime, targetDirtyRatio);
return Ok();
}
@@ -566,22 +568,24 @@
}
binder::Status VoldNativeService::mountFstab(const std::string& blkDevice,
- const std::string& mountPoint) {
+ const std::string& mountPoint,
+ const std::string& zonedDevice) {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
- return translateBool(
- fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false, false, "null"));
+ return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false, false,
+ "null", zonedDevice));
}
binder::Status VoldNativeService::encryptFstab(const std::string& blkDevice,
const std::string& mountPoint, bool shouldFormat,
- const std::string& fsType) {
+ const std::string& fsType,
+ const std::string& zonedDevice) {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
- return translateBool(
- fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true, shouldFormat, fsType));
+ return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true, shouldFormat,
+ fsType, zonedDevice));
}
binder::Status VoldNativeService::setStorageBindingSeed(const std::vector<uint8_t>& seed) {
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 423e8f9..37a988b 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -90,7 +90,8 @@
binder::Status abortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
binder::Status getStorageLifeTime(int32_t* _aidl_return);
binder::Status setGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold,
- float dirtyReclaimRate, float reclaimWeight, int32_t gcPeriod);
+ float dirtyReclaimRate, float reclaimWeight, int32_t gcPeriod,
+ int32_t minGCSleepTime, int32_t targetDirtyRatio);
binder::Status refreshLatestWrite();
binder::Status getWriteAmount(int32_t* _aidl_return);
@@ -103,9 +104,11 @@
binder::Status fbeEnable();
binder::Status initUser0();
- binder::Status mountFstab(const std::string& blkDevice, const std::string& mountPoint);
+ binder::Status mountFstab(const std::string& blkDevice, const std::string& mountPoint,
+ const std::string& zonedDevice);
binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint,
- bool shouldFormat, const std::string& fsType);
+ bool shouldFormat, const std::string& fsType,
+ const std::string& zonedDevice);
binder::Status setStorageBindingSeed(const std::vector<uint8_t>& seed);
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index a7d39c1..5cef239 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -358,7 +358,7 @@
LOG(ERROR) << "Failed to unlink " << keyPath;
success = false;
}
- if (fscrypt_is_native()) {
+ if (IsFbeEnabled()) {
if (!fscrypt_destroy_volume_keys(fsUuid)) {
success = false;
}
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index d77c7da..77478d9 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -69,7 +69,8 @@
int getStorageLifeTime();
void setGCUrgentPace(int neededSegments, int minSegmentThreshold,
float dirtyReclaimRate, float reclaimWeight,
- int gcPeriod);
+ int gcPeriod, int minGCSleepTime,
+ int targetDirtyRatio);
void refreshLatestWrite();
int getWriteAmount();
@@ -79,8 +80,8 @@
void fbeEnable();
void initUser0();
- void mountFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint);
- void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean shouldFormat, @utf8InCpp String fsType);
+ void mountFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, @utf8InCpp String zonedDevice);
+ void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean shouldFormat, @utf8InCpp String fsType, @utf8InCpp String zonedDevice);
void setStorageBindingSeed(in byte[] seed);
diff --git a/cryptfs.cpp b/cryptfs.cpp
index ab8f3ec..5213c18 100644
--- a/cryptfs.cpp
+++ b/cryptfs.cpp
@@ -156,7 +156,7 @@
key_ascii, 0, real_blkdev, 0);
target->AllowDiscards();
- if (fscrypt_is_native() &&
+ if (IsFbeEnabled() &&
android::base::GetBoolProperty("ro.crypto.allow_encrypt_override", false)) {
target->AllowEncryptOverride();
}
diff --git a/fs/Ext4.cpp b/fs/Ext4.cpp
index 52f6772..293efc4 100644
--- a/fs/Ext4.cpp
+++ b/fs/Ext4.cpp
@@ -182,7 +182,7 @@
if (android::base::GetBoolProperty("vold.has_quota", false)) {
options += ",quota";
}
- if (fscrypt_is_native()) {
+ if (IsFbeEnabled()) {
options += ",encrypt";
}
if (needs_casefold) {
diff --git a/fs/F2fs.cpp b/fs/F2fs.cpp
index 55b0823..23363e3 100644
--- a/fs/F2fs.cpp
+++ b/fs/F2fs.cpp
@@ -71,7 +71,7 @@
return res;
}
-status_t Format(const std::string& source) {
+status_t Format(const std::string& source, const std::string& zoned_device) {
std::vector<char const*> cmd;
cmd.emplace_back(kMkfsPath);
@@ -96,6 +96,11 @@
cmd.emplace_back("-C");
cmd.emplace_back("utf8");
}
+ if (!zoned_device.empty()) {
+ cmd.emplace_back("-c");
+ cmd.emplace_back(zoned_device.c_str());
+ cmd.emplace_back("-m");
+ }
cmd.emplace_back(source.c_str());
return logwrap_fork_execvp(cmd.size(), cmd.data(), nullptr, false, LOG_KLOG,
false, nullptr);
diff --git a/fs/F2fs.h b/fs/F2fs.h
index f710212..cdad581 100644
--- a/fs/F2fs.h
+++ b/fs/F2fs.h
@@ -29,7 +29,7 @@
status_t Check(const std::string& source);
status_t Mount(const std::string& source, const std::string& target);
-status_t Format(const std::string& source);
+status_t Format(const std::string& source, const std::string& zoned_device = "");
} // namespace f2fs
} // namespace vold
diff --git a/vdc.cpp b/vdc.cpp
index 740e246..b63abbb 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -124,14 +124,14 @@
checkStatus(args, vold->reset());
} else if (args[0] == "cryptfs" && args[1] == "bindkeys") {
bindkeys(args, vold);
- } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 4) {
- checkStatus(args, vold->mountFstab(args[2], args[3]));
- } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 6) {
+ } else if (args[0] == "cryptfs" && args[1] == "mountFstab" && args.size() == 5) {
+ checkStatus(args, vold->mountFstab(args[2], args[3], args[4]));
+ } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 7) {
auto shouldFormat = android::base::ParseBool(args[4]);
if (shouldFormat == android::base::ParseBoolResult::kError) exit(EINVAL);
checkStatus(args, vold->encryptFstab(args[2], args[3],
shouldFormat == android::base::ParseBoolResult::kTrue,
- args[5]));
+ args[5], args[6]));
} else if (args[0] == "checkpoint" && args[1] == "supportsCheckpoint" && args.size() == 2) {
bool supported = false;
checkStatus(args, vold->supportsCheckpoint(&supported));