Merge "Revert "Reduce AppFuse max read size."" into main
diff --git a/Android.bp b/Android.bp
index 6d70d4d..00d1382 100644
--- a/Android.bp
+++ b/Android.bp
@@ -62,7 +62,6 @@
"libincfs",
"libhidlbase",
"libkeymint_support",
- "libkeyutils",
"liblog",
"liblogwrap",
"libselinux",
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 9f6403c..51b35c5 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -44,13 +44,10 @@
#include "android/os/IVold.h"
-#define MANAGE_MISC_DIRS 0
-
#include <cutils/fs.h>
#include <cutils/properties.h>
#include <fscrypt/fscrypt.h>
-#include <keyutils.h>
#include <libdm/dm.h>
#include <android-base/file.h>
@@ -76,7 +73,6 @@
using android::vold::SetDefaultAcl;
using android::vold::SetQuotaInherit;
using android::vold::SetQuotaProjectId;
-using android::vold::writeStringToFile;
using namespace android::fscrypt;
using namespace android::dm;
@@ -605,7 +601,7 @@
// 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)) {
+ if (!fscrypt_prepare_user_storage("", 0, android::os::IVold::STORAGE_FLAG_DE)) {
LOG(ERROR) << "Failed to prepare user 0 storage";
return false;
}
@@ -615,14 +611,14 @@
}
// Creates the CE and DE keys for a new user.
-bool fscrypt_create_user_keys(userid_t user_id, int serial, bool ephemeral) {
- LOG(DEBUG) << "fscrypt_create_user_keys for " << user_id << " serial " << serial;
+bool fscrypt_create_user_keys(userid_t user_id, bool ephemeral) {
+ LOG(DEBUG) << "fscrypt_create_user_keys for " << user_id;
if (!IsFbeEnabled()) {
return true;
}
// FIXME test for existence of key that is not loaded yet
if (s_ce_policies.count(user_id) != 0) {
- LOG(ERROR) << "Already exists, can't create keys for " << user_id << " serial " << serial;
+ LOG(ERROR) << "Already exists, can't create keys for " << user_id;
// FIXME should we fail the command?
return true;
}
@@ -632,27 +628,6 @@
return true;
}
-// "Lock" all encrypted directories whose key has been removed. This is needed
-// in the case where the keys are being put in the session keyring (rather in
-// the newer filesystem-level keyrings), because removing a key from the session
-// keyring doesn't affect inodes in the kernel's inode cache whose per-file key
-// was already set up. So to remove the per-file keys and make the files
-// "appear encrypted", these inodes must be evicted.
-//
-// To do this, sync() to clean all dirty inodes, then drop all reclaimable slab
-// objects systemwide. This is overkill, but it's the best available method
-// currently. Don't use drop_caches mode "3" because that also evicts pagecache
-// for in-use files; all files relevant here are already closed and sync'ed.
-static void drop_caches_if_needed() {
- if (android::vold::isFsKeyringSupported()) {
- return;
- }
- sync();
- if (!writeStringToFile("2", "/proc/sys/vm/drop_caches")) {
- PLOG(ERROR) << "Failed to drop caches during key eviction";
- }
-}
-
// Evicts all the user's keys of one type from all volumes (internal and adoptable).
// This evicts either CE keys or DE keys, depending on which map is passed.
static bool evict_user_keys(std::map<userid_t, UserPolicies>& policy_map, userid_t user_id) {
@@ -665,7 +640,6 @@
success &= android::vold::evictKey(BuildDataPath(volume_uuid), policy);
}
policy_map.erase(it);
- drop_caches_if_needed();
}
return success;
}
@@ -871,8 +845,8 @@
// Unlocks internal CE storage for the given user. This only unlocks internal storage, since
// fscrypt_prepare_user_storage() has to be called for each adoptable storage volume anyway (since
// the volume might have been absent when the user was created), and that handles the unlocking.
-bool fscrypt_unlock_ce_storage(userid_t user_id, int serial, const std::string& secret_hex) {
- LOG(DEBUG) << "fscrypt_unlock_ce_storage " << user_id << " serial=" << serial;
+bool fscrypt_unlock_ce_storage(userid_t user_id, const std::string& secret_hex) {
+ LOG(DEBUG) << "fscrypt_unlock_ce_storage " << user_id;
if (!IsFbeEnabled()) return true;
if (s_ce_policies.count(user_id) != 0) {
LOG(WARNING) << "CE storage for user " << user_id << " is already unlocked";
@@ -907,10 +881,9 @@
return true;
}
-bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
- int flags) {
+bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int flags) {
LOG(DEBUG) << "fscrypt_prepare_user_storage for volume " << escape_empty(volume_uuid)
- << ", user " << user_id << ", serial " << serial << ", flags " << flags;
+ << ", user " << user_id << ", flags " << flags;
// Internal storage must be prepared before adoptable storage, since the
// user's volume keys are stored in their internal storage.
@@ -932,7 +905,6 @@
if (flags & android::os::IVold::STORAGE_FLAG_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);
// DE_n key
@@ -962,11 +934,6 @@
if (volume_uuid.empty()) {
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_with_policy(system_de_path, 0770, AID_SYSTEM, AID_SYSTEM, de_policy))
@@ -1075,7 +1042,6 @@
if (flags & android::os::IVold::STORAGE_FLAG_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);
// DE_n key
@@ -1088,9 +1054,6 @@
res &= destroy_dir(misc_de_path);
if (volume_uuid.empty()) {
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(system_de_path);
res &= destroy_dir(vendor_de_path);
diff --git a/FsCrypt.h b/FsCrypt.h
index f5c367c..afcedfb 100644
--- a/FsCrypt.h
+++ b/FsCrypt.h
@@ -23,17 +23,16 @@
bool fscrypt_init_user0();
extern bool fscrypt_init_user0_done;
-bool fscrypt_create_user_keys(userid_t user_id, int serial, bool ephemeral);
+bool fscrypt_create_user_keys(userid_t user_id, bool ephemeral);
bool fscrypt_destroy_user_keys(userid_t user_id);
bool fscrypt_set_ce_key_protection(userid_t user_id, const std::string& secret);
void fscrypt_deferred_fixate_ce_keys();
std::vector<int> fscrypt_get_unlocked_users();
-bool fscrypt_unlock_ce_storage(userid_t user_id, int serial, const std::string& secret);
+bool fscrypt_unlock_ce_storage(userid_t user_id, const std::string& secret);
bool fscrypt_lock_ce_storage(userid_t user_id);
-bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int serial,
- int flags);
+bool fscrypt_prepare_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
bool fscrypt_destroy_user_storage(const std::string& volume_uuid, userid_t user_id, int flags);
bool fscrypt_destroy_volume_keys(const std::string& volume_uuid);
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index 7d3eaf4..fafa280 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -507,6 +507,30 @@
return -1;
}
+int32_t GetStorageRemainingLifetime() {
+ std::string path = getDevSysfsPath();
+ if (path.empty()) {
+ return -1;
+ }
+
+ std::string lifeTimeBasePath = path + "/health_descriptor/life_time_estimation_";
+
+ int32_t lifeTime = getLifeTime(lifeTimeBasePath + "c");
+ if (lifeTime == -1) {
+ int32_t lifeTimeA = getLifeTime(lifeTimeBasePath + "a");
+ int32_t lifeTimeB = getLifeTime(lifeTimeBasePath + "b");
+ lifeTime = std::max(lifeTimeA, lifeTimeB);
+ if (lifeTime <= 0) {
+ return -1;
+ }
+
+ // 1 = 0-10% used, 10 = 90-100% used. Subtract 1 so that a brand new
+ // device looks 0% used.
+ lifeTime = (lifeTime - 1) * 10;
+ }
+ return 100 - std::clamp(lifeTime, 0, 100);
+}
+
void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime,
int32_t targetDirtyRatio) {
diff --git a/IdleMaint.h b/IdleMaint.h
index a28cde2..a1387b3 100644
--- a/IdleMaint.h
+++ b/IdleMaint.h
@@ -26,6 +26,7 @@
int RunIdleMaint(bool needGC, const android::sp<android::os::IVoldTaskListener>& listener);
int AbortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
int32_t GetStorageLifeTime();
+int32_t GetStorageRemainingLifetime();
void SetGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold, float dirtyReclaimRate,
float reclaimWeight, int32_t gcPeriod, int32_t minGCSleepTime,
int32_t targetDirtyRatio);
diff --git a/KeyBuffer.h b/KeyBuffer.h
index 3275255..619cb27 100644
--- a/KeyBuffer.h
+++ b/KeyBuffer.h
@@ -28,7 +28,7 @@
// Allocator that delegates useful work to standard one but zeroes data before deallocating.
class ZeroingAllocator : public std::allocator<char> {
public:
- void deallocate(pointer p, size_type n) {
+ void deallocate(value_type* p, size_type n) {
memset_explicit(p, 0, n);
std::allocator<char>::deallocate(p, n);
}
diff --git a/KeyUtil.cpp b/KeyUtil.cpp
index 9e8920d..bd2ccdd 100644
--- a/KeyUtil.cpp
+++ b/KeyUtil.cpp
@@ -28,7 +28,6 @@
#include <android-base/file.h>
#include <android-base/logging.h>
-#include <keyutils.h>
#include "KeyStorage.h"
#include "Utils.h"
@@ -75,39 +74,6 @@
}
}
-static bool isFsKeyringSupportedImpl() {
- android::base::unique_fd fd(open("/data", O_RDONLY | O_DIRECTORY | O_CLOEXEC));
-
- // FS_IOC_ADD_ENCRYPTION_KEY with a NULL argument will fail with ENOTTY if
- // the ioctl isn't supported. Otherwise it will fail with another error
- // code such as EFAULT.
- //
- // Note that there's no need to check for FS_IOC_REMOVE_ENCRYPTION_KEY,
- // since it's guaranteed to be available if FS_IOC_ADD_ENCRYPTION_KEY is.
- // There's also no need to check for support on external volumes separately
- // from /data, since either the kernel supports the ioctls on all
- // fscrypt-capable filesystems or it doesn't.
- errno = 0;
- (void)ioctl(fd, FS_IOC_ADD_ENCRYPTION_KEY, NULL);
- if (errno == ENOTTY) {
- LOG(INFO) << "Kernel doesn't support FS_IOC_ADD_ENCRYPTION_KEY. Falling back to "
- "session keyring";
- return false;
- }
- if (errno != EFAULT) {
- PLOG(WARNING) << "Unexpected error from FS_IOC_ADD_ENCRYPTION_KEY";
- }
- LOG(DEBUG) << "Detected support for FS_IOC_ADD_ENCRYPTION_KEY";
- return true;
-}
-
-// Return true if the kernel supports the ioctls to add/remove fscrypt keys
-// directly to/from the filesystem.
-bool isFsKeyringSupported(void) {
- static bool supported = isFsKeyringSupportedImpl();
- return supported;
-}
-
// Get raw keyref - used to make keyname and to pass to ioctl
static std::string generateKeyRef(const uint8_t* key, int length) {
SHA512_CTX c;
@@ -127,20 +93,6 @@
return std::string((char*)key_ref2, FSCRYPT_KEY_DESCRIPTOR_SIZE);
}
-static bool fillKey(const KeyBuffer& key, fscrypt_key* fs_key) {
- if (key.size() != FSCRYPT_MAX_KEY_SIZE) {
- LOG(ERROR) << "Wrong size key " << key.size();
- return false;
- }
- static_assert(FSCRYPT_MAX_KEY_SIZE == sizeof(fs_key->raw), "Mismatch of max key sizes");
- fs_key->mode = 0; // unused by kernel
- memcpy(fs_key->raw, key.data(), key.size());
- fs_key->size = key.size();
- return true;
-}
-
-static char const* const NAME_PREFIXES[] = {"ext4", "f2fs", "fscrypt", nullptr};
-
static std::string keyrefstring(const std::string& raw_ref) {
std::ostringstream o;
for (unsigned char i : raw_ref) {
@@ -149,44 +101,6 @@
return o.str();
}
-static std::string buildLegacyKeyName(const std::string& prefix, const std::string& raw_ref) {
- return prefix + ":" + keyrefstring(raw_ref);
-}
-
-// Get the ID of the keyring we store all fscrypt keys in when the kernel is too
-// old to support FS_IOC_ADD_ENCRYPTION_KEY and FS_IOC_REMOVE_ENCRYPTION_KEY.
-static bool fscryptKeyring(key_serial_t* device_keyring) {
- *device_keyring = keyctl_search(KEY_SPEC_SESSION_KEYRING, "keyring", "fscrypt", 0);
- if (*device_keyring == -1) {
- PLOG(ERROR) << "Unable to find device keyring";
- return false;
- }
- return true;
-}
-
-// Add an encryption key to the legacy global session keyring.
-static bool installKeyLegacy(const KeyBuffer& key, const std::string& raw_ref) {
- // Place fscrypt_key into automatically zeroing buffer.
- KeyBuffer fsKeyBuffer(sizeof(fscrypt_key));
- fscrypt_key& fs_key = *reinterpret_cast<fscrypt_key*>(fsKeyBuffer.data());
-
- if (!fillKey(key, &fs_key)) return false;
- key_serial_t device_keyring;
- if (!fscryptKeyring(&device_keyring)) return false;
- for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
- auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
- key_serial_t key_id =
- add_key("logon", ref.c_str(), (void*)&fs_key, sizeof(fs_key), device_keyring);
- if (key_id == -1) {
- PLOG(ERROR) << "Failed to insert key into keyring " << device_keyring;
- return false;
- }
- LOG(DEBUG) << "Added key " << key_id << " (" << ref << ") to keyring " << device_keyring
- << " in process " << getpid();
- }
- return true;
-}
-
// Build a struct fscrypt_key_specifier for use in the key management ioctls.
static bool buildKeySpecifier(fscrypt_key_specifier* spec, const EncryptionPolicy& policy) {
switch (policy.options.version) {
@@ -230,9 +144,6 @@
// "descriptor", which must be provided by userspace. We use the
// first 8 bytes from the double SHA-512 of the key itself.
policy->key_raw_ref = generateKeyRef((const uint8_t*)key.data(), key.size());
- if (!isFsKeyringSupported()) {
- return installKeyLegacy(key, policy->key_raw_ref);
- }
if (!buildKeySpecifier(&arg->key_spec, *policy)) {
return false;
}
@@ -276,29 +187,6 @@
return true;
}
-// Remove an encryption key from the legacy global session keyring.
-static bool evictKeyLegacy(const std::string& raw_ref) {
- key_serial_t device_keyring;
- if (!fscryptKeyring(&device_keyring)) return false;
- bool success = true;
- for (char const* const* name_prefix = NAME_PREFIXES; *name_prefix != nullptr; name_prefix++) {
- auto ref = buildLegacyKeyName(*name_prefix, raw_ref);
- auto key_serial = keyctl_search(device_keyring, "logon", ref.c_str(), 0);
-
- // Unlink the key from the keyring. Prefer unlinking to revoking or
- // invalidating, since unlinking is actually no less secure currently, and
- // it avoids bugs in certain kernel versions where the keyring key is
- // referenced from places it shouldn't be.
- if (keyctl_unlink(key_serial, device_keyring) != 0) {
- PLOG(ERROR) << "Failed to unlink key with serial " << key_serial << " ref " << ref;
- success = false;
- } else {
- LOG(DEBUG) << "Unlinked key with serial " << key_serial << " ref " << ref;
- }
- }
- return success;
-}
-
static void waitForBusyFiles(const struct fscrypt_key_specifier key_spec, const std::string ref,
const std::string mountpoint) {
android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
@@ -359,9 +247,6 @@
bool evictKey(const std::string& mountpoint, const EncryptionPolicy& policy) {
const std::lock_guard<std::mutex> lock(fscrypt_keyring_mutex);
- if (policy.options.version == 1 && !isFsKeyringSupported()) {
- return evictKeyLegacy(policy.key_raw_ref);
- }
android::base::unique_fd fd(open(mountpoint.c_str(), O_RDONLY | O_DIRECTORY | O_CLOEXEC));
if (fd == -1) {
diff --git a/KeyUtil.h b/KeyUtil.h
index 17a234e..cc1a1f9 100644
--- a/KeyUtil.h
+++ b/KeyUtil.h
@@ -43,28 +43,15 @@
// be generated.
const KeyGeneration neverGen();
-bool isFsKeyringSupported(void);
-
// Install a file-based encryption key to the kernel, for use by encrypted files
// on the specified filesystem using the specified encryption policy version.
//
-// For v1 policies, we use FS_IOC_ADD_ENCRYPTION_KEY if the kernel supports it.
-// Otherwise we add the key to the legacy global session keyring.
-//
-// For v2 policies, we always use FS_IOC_ADD_ENCRYPTION_KEY; it's the only way
-// the kernel supports.
-//
// Returns %true on success, %false on failure. On success also sets *policy
// to the EncryptionPolicy used to refer to this key.
bool installKey(const std::string& mountpoint, const android::fscrypt::EncryptionOptions& options,
const KeyBuffer& key, android::fscrypt::EncryptionPolicy* policy);
// Evict a file-based encryption key from the kernel.
-//
-// We use FS_IOC_REMOVE_ENCRYPTION_KEY if the kernel supports it. Otherwise we
-// remove the key from the legacy global session keyring.
-//
-// In the latter case, the caller is responsible for dropping caches.
bool evictKey(const std::string& mountpoint, const android::fscrypt::EncryptionPolicy& policy);
// Retrieves the key from the named directory, or generates it if it doesn't
diff --git a/TEST_MAPPING b/TEST_MAPPING
index a535181..93938b6 100644
--- a/TEST_MAPPING
+++ b/TEST_MAPPING
@@ -10,6 +10,15 @@
"name": "CtsScopedStorageDeviceOnlyTest"
},
{
+ "name": "CtsScopedStorageBypassDatabaseOperationsTest"
+ },
+ {
+ "name": "CtsScopedStorageGeneralTest"
+ },
+ {
+ "name": "CtsScopedStorageRedactUriTest"
+ },
+ {
"name": "AdoptableHostTest"
}
],
@@ -24,6 +33,15 @@
"name": "CtsScopedStorageDeviceOnlyTest"
},
{
+ "name": "CtsScopedStorageBypassDatabaseOperationsTest"
+ },
+ {
+ "name": "CtsScopedStorageGeneralTest"
+ },
+ {
+ "name": "CtsScopedStorageRedactUriTest"
+ },
+ {
"name": "AdoptableHostTest"
}
]
diff --git a/Utils.cpp b/Utils.cpp
index 40a182b..696b0b4 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1116,10 +1116,6 @@
return StringPrintf("%s/system_de/%u", BuildDataPath("").c_str(), userId);
}
-std::string BuildDataMiscLegacyPath(userid_t userId) {
- return StringPrintf("%s/misc/user/%u", BuildDataPath("").c_str(), userId);
-}
-
// Keep in sync with installd (frameworks/native/cmds/installd/utils.h)
std::string BuildDataProfilesDePath(userid_t userId) {
return StringPrintf("%s/misc/profiles/cur/%u", BuildDataPath("").c_str(), userId);
diff --git a/Utils.h b/Utils.h
index fbd0f30..690f79e 100644
--- a/Utils.h
+++ b/Utils.h
@@ -148,7 +148,6 @@
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 BuildDataProfilesDePath(userid_t userid);
std::string BuildDataVendorCePath(userid_t userid);
std::string BuildDataVendorDePath(userid_t userid);
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index c39604b..96f4eaf 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -504,6 +504,14 @@
return Ok();
}
+binder::Status VoldNativeService::getStorageRemainingLifetime(int32_t* _aidl_return) {
+ ENFORCE_SYSTEM_OR_ROOT;
+ ACQUIRE_LOCK;
+
+ *_aidl_return = GetStorageRemainingLifetime();
+ return Ok();
+}
+
binder::Status VoldNativeService::setGCUrgentPace(int32_t neededSegments,
int32_t minSegmentThreshold,
float dirtyReclaimRate, float reclaimWeight,
@@ -607,12 +615,11 @@
return translateBool(setKeyStorageBindingSeed(seed));
}
-binder::Status VoldNativeService::createUserStorageKeys(int32_t userId, int32_t userSerial,
- bool ephemeral) {
+binder::Status VoldNativeService::createUserStorageKeys(int32_t userId, bool ephemeral) {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
- return translateBool(fscrypt_create_user_keys(userId, userSerial, ephemeral));
+ return translateBool(fscrypt_create_user_keys(userId, ephemeral));
}
binder::Status VoldNativeService::destroyUserStorageKeys(int32_t userId) {
@@ -638,12 +645,11 @@
return Ok();
}
-binder::Status VoldNativeService::unlockCeStorage(int32_t userId, int32_t userSerial,
- const std::string& secret) {
+binder::Status VoldNativeService::unlockCeStorage(int32_t userId, const std::string& secret) {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
- return translateBool(fscrypt_unlock_ce_storage(userId, userSerial, secret));
+ return translateBool(fscrypt_unlock_ce_storage(userId, secret));
}
binder::Status VoldNativeService::lockCeStorage(int32_t userId) {
@@ -654,15 +660,14 @@
}
binder::Status VoldNativeService::prepareUserStorage(const std::optional<std::string>& uuid,
- int32_t userId, int32_t userSerial,
- int32_t flags) {
+ int32_t userId, int32_t flags) {
ENFORCE_SYSTEM_OR_ROOT;
std::string empty_string = "";
auto uuid_ = uuid ? *uuid : empty_string;
CHECK_ARGUMENT_HEX(uuid_);
ACQUIRE_CRYPT_LOCK;
- return translateBool(fscrypt_prepare_user_storage(uuid_, userId, userSerial, flags));
+ return translateBool(fscrypt_prepare_user_storage(uuid_, userId, flags));
}
binder::Status VoldNativeService::destroyUserStorage(const std::optional<std::string>& uuid,
diff --git a/VoldNativeService.h b/VoldNativeService.h
index e98aea8..bb00d35 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -89,6 +89,7 @@
const android::sp<android::os::IVoldTaskListener>& listener);
binder::Status abortIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener);
binder::Status getStorageLifeTime(int32_t* _aidl_return);
+ binder::Status getStorageRemainingLifetime(int32_t* _aidl_return);
binder::Status setGCUrgentPace(int32_t neededSegments, int32_t minSegmentThreshold,
float dirtyReclaimRate, float reclaimWeight, int32_t gcPeriod,
int32_t minGCSleepTime, int32_t targetDirtyRatio);
@@ -112,17 +113,17 @@
binder::Status setStorageBindingSeed(const std::vector<uint8_t>& seed);
- binder::Status createUserStorageKeys(int32_t userId, int32_t userSerial, bool ephemeral);
+ binder::Status createUserStorageKeys(int32_t userId, bool ephemeral);
binder::Status destroyUserStorageKeys(int32_t userId);
binder::Status setCeStorageProtection(int32_t userId, const std::string& secret);
binder::Status getUnlockedUsers(std::vector<int>* _aidl_return);
- binder::Status unlockCeStorage(int32_t userId, int32_t userSerial, const std::string& secret);
+ binder::Status unlockCeStorage(int32_t userId, const std::string& secret);
binder::Status lockCeStorage(int32_t userId);
binder::Status prepareUserStorage(const std::optional<std::string>& uuid, int32_t userId,
- int32_t userSerial, int32_t flags);
+ int32_t flags);
binder::Status destroyUserStorage(const std::optional<std::string>& uuid, int32_t userId,
int32_t flags);
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index c981f2d..a1ac20d 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -921,25 +921,34 @@
int VolumeManager::reset() {
// Tear down all existing disks/volumes and start from a blank slate so
// newly connected framework hears all events.
+
+ // Destroy StubVolume disks. This needs to be done before destroying
+ // EmulatedVolumes because in ARC (Android on ChromeOS), ChromeOS Downloads
+ // directory (which is in a StubVolume) is bind-mounted to
+ // /data/media/0/Download.
+ // We do not recreate StubVolumes here because they are managed from outside
+ // Android (e.g. from ChromeOS) and their disk recreation on reset events
+ // should be handled from outside by calling createStubVolume() again.
+ for (const auto& disk : mDisks) {
+ if (disk->isStub()) {
+ disk->destroy();
+ }
+ }
+ // Remove StubVolume from both mDisks and mPendingDisks.
+ const auto isStub = [](const auto& disk) { return disk->isStub(); };
+ mDisks.remove_if(isStub);
+ mPendingDisks.remove_if(isStub);
+
for (const auto& vol : mInternalEmulatedVolumes) {
vol->destroy();
}
mInternalEmulatedVolumes.clear();
- // Destroy and recreate all disks except that StubVolume disks are just
- // destroyed and removed from both mDisks and mPendingDisks.
- // StubVolumes are managed from outside Android (e.g. from Chrome OS) and
- // their disk recreation on reset events should be handled from outside by
- // calling createStubVolume() again.
+ // Destroy and recreate non-StubVolume disks.
for (const auto& disk : mDisks) {
disk->destroy();
- if (!disk->isStub()) {
- disk->create();
- }
+ disk->create();
}
- const auto isStub = [](const auto& disk) { return disk->isStub(); };
- mDisks.remove_if(isStub);
- mPendingDisks.remove_if(isStub);
updateVirtualDisk();
mAddedUsers.clear();
@@ -958,11 +967,20 @@
return 0; // already shutdown
}
android::vold::sSleepOnUnmount = false;
+ // Destroy StubVolume disks before destroying EmulatedVolumes (see the
+ // comment in VolumeManager::reset()).
+ for (const auto& disk : mDisks) {
+ if (disk->isStub()) {
+ disk->destroy();
+ }
+ }
for (const auto& vol : mInternalEmulatedVolumes) {
vol->destroy();
}
for (const auto& disk : mDisks) {
- disk->destroy();
+ if (!disk->isStub()) {
+ disk->destroy();
+ }
}
mInternalEmulatedVolumes.clear();
@@ -978,11 +996,20 @@
ATRACE_NAME("VolumeManager::unmountAll()");
// First, try gracefully unmounting all known devices
+ // Unmount StubVolume disks before unmounting EmulatedVolumes (see the
+ // comment in VolumeManager::reset()).
+ for (const auto& disk : mDisks) {
+ if (disk->isStub()) {
+ disk->unmountAll();
+ }
+ }
for (const auto& vol : mInternalEmulatedVolumes) {
vol->unmount();
}
for (const auto& disk : mDisks) {
- disk->unmountAll();
+ if (!disk->isStub()) {
+ disk->unmountAll();
+ }
}
// Worst case we might have some stale mounts lurking around, so
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 852e8af..d121dee 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -66,6 +66,8 @@
void fstrim(int fstrimFlags, IVoldTaskListener listener);
void runIdleMaint(boolean needGC, IVoldTaskListener listener);
void abortIdleMaint(IVoldTaskListener listener);
+ // Returns the amount of storage lifetime used, as a percentage.
+ // (eg, 10 indicates 10% of lifetime used), or -1 on failure.
int getStorageLifeTime();
void setGCUrgentPace(int neededSegments, int minSegmentThreshold,
float dirtyReclaimRate, float reclaimWeight,
@@ -85,17 +87,16 @@
void setStorageBindingSeed(in byte[] seed);
- void createUserStorageKeys(int userId, int userSerial, boolean ephemeral);
+ void createUserStorageKeys(int userId, boolean ephemeral);
void destroyUserStorageKeys(int userId);
void setCeStorageProtection(int userId, @utf8InCpp String secret);
int[] getUnlockedUsers();
- void unlockCeStorage(int userId, int userSerial, @utf8InCpp String secret);
+ void unlockCeStorage(int userId, @utf8InCpp String secret);
void lockCeStorage(int userId);
- void prepareUserStorage(@nullable @utf8InCpp String uuid, int userId, int userSerial,
- int storageFlags);
+ void prepareUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
void destroyUserStorage(@nullable @utf8InCpp String uuid, int userId, int storageFlags);
void prepareSandboxForApp(in @utf8InCpp String packageName, int appId,
@@ -136,6 +137,11 @@
long getStorageSize();
+ // Returns the remaining storage lifetime as a percentage, rounded up as
+ // needed when the underlying hardware reports low precision. Returns -1
+ // on failure.
+ int getStorageRemainingLifetime();
+
const int FSTRIM_FLAG_DEEP_TRIM = 1;
const int MOUNT_FLAG_PRIMARY = 1;
diff --git a/fs/Vfat.cpp b/fs/Vfat.cpp
index f3f04d8..c0cd918 100644
--- a/fs/Vfat.cpp
+++ b/fs/Vfat.cpp
@@ -20,6 +20,7 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
+#include <time.h>
#include <unistd.h>
#include <linux/fs.h>
@@ -118,6 +119,16 @@
return 0;
}
+int16_t currentUtcOffsetMinutes() {
+ time_t now = time(NULL);
+
+ struct tm nowTm;
+ localtime_r(&now, &nowTm);
+
+ int32_t utcOffsetSeconds = nowTm.tm_gmtoff;
+ return (int16_t)(utcOffsetSeconds / 60);
+}
+
status_t Mount(const std::string& source, const std::string& target, bool ro, bool remount,
bool executable, int ownerUid, int ownerGid, int permMask, bool createLost) {
int rc;
@@ -136,6 +147,33 @@
android::base::StringPrintf("utf8,uid=%d,gid=%d,fmask=%o,dmask=%o,shortname=mixed",
ownerUid, ownerGid, permMask, permMask);
+ // b/315058275: Set this to false if you don't want to use a fixed offset
+ // determined at mount time. When this is false, the vfat driver will fall
+ // back to using sys_tz, which Android does not set by default, then assume
+ // local time == UTC.
+ if (true) {
+ // Calculate the offset to use to adjust FAT timestamps to convert them
+ // from "local time" into unix epoch time. This assumes the current UTC
+ // offset of this device is the same as the device that wrote them. User
+ // space code, e.g. ls -l, will then apply the UTC offset for the UTC
+ // time to convert times from unix epoch time to local time for display.
+ // Before Android U (b/246256335), Android platform code informed the
+ // Linux kernel about the UTC offset under some circumstances, but not
+ // for all, e.g. DST changes. The kernel vfat driver is one of the few
+ // things in the kernel that tries to use kernel UTC offset information.
+ // Setting time zone offset in the Linux kernel is discouraged and so
+ // Android no longer informs the kernel. Instead, the offset for vfat
+ // to use is now set at volume mount time. This means that if the time
+ // zone offset changes while the device is mounted, or if files were
+ // written in opposing daylight saving time, then incorrect file times
+ // will be displayed until the volume is remounted. Even then, the vfat
+ // driver has to assume a fixed offset to apply to all files, so files
+ // written at different times of the year can have incorrect times
+ // calculated, e.g. offset incorrectly by one hour.
+ int16_t timeOffsetArg = currentUtcOffsetMinutes();
+ mountData += android::base::StringPrintf(",time_offset=%d", timeOffsetArg);
+ }
+
rc = mount(c_source, c_target, "vfat", flags, mountData.c_str());
if (rc && errno == EROFS) {