Mark ab/7061308 as merged in stage.
Bug: 180401296
Merged-In: I7124285f41c6a854ad5c86677bc94d78ddca5a97
Change-Id: Icf8db3d8557a3835e0834eec134bb4b111ec3af0
diff --git a/Android.bp b/Android.bp
index 1c0ed17..fa8f249 100644
--- a/Android.bp
+++ b/Android.bp
@@ -1,3 +1,7 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
cc_defaults {
name: "vold_default_flags",
@@ -90,7 +94,7 @@
export_aidl_headers: true,
},
whole_static_libs: [
- "libincremental_aidl-unstable-cpp",
+ "libincremental_aidl-cpp",
],
}
@@ -149,12 +153,22 @@
"model/VolumeEncryption.cpp",
],
product_variables: {
+ arc: {
+ exclude_srcs: [
+ "model/StubVolume.cpp",
+ ],
+ static_libs: [
+ "libarcvolume",
+ ],
+ },
debuggable: {
cppflags: ["-D__ANDROID_DEBUGGABLE__"],
},
},
shared_libs: [
"android.hardware.health.storage@1.0",
+ "android.hardware.health.storage-V1-ndk_platform",
+ "libbinder_ndk",
],
whole_static_libs: [
"com.android.sysprop.apex",
@@ -184,7 +198,20 @@
shared_libs: [
"android.hardware.health.storage@1.0",
+ "android.hardware.health.storage-V1-ndk_platform",
+ "libbinder_ndk",
],
+
+ product_variables: {
+ arc: {
+ exclude_srcs: [
+ "model/StubVolume.cpp",
+ ],
+ static_libs: [
+ "libarcvolume",
+ ],
+ },
+ },
}
cc_binary {
diff --git a/FsCrypt.cpp b/FsCrypt.cpp
index 8f6ba9c..82a2012 100644
--- a/FsCrypt.cpp
+++ b/FsCrypt.cpp
@@ -462,7 +462,6 @@
return false;
LOG(INFO) << "Wrote per boot key reference to:" << per_boot_ref_filename;
- if (!android::vold::FsyncDirectory(device_key_dir)) return false;
return true;
}
@@ -652,18 +651,12 @@
if (!android::vold::readSecdiscardable(secdiscardable_path, &secdiscardable_hash))
return false;
} else {
- if (fs_mkdirs(secdiscardable_path.c_str(), 0700) != 0) {
- PLOG(ERROR) << "Creating directories for: " << secdiscardable_path;
- return false;
- }
+ if (!android::vold::MkdirsSync(secdiscardable_path, 0700)) return false;
if (!android::vold::createSecdiscardable(secdiscardable_path, &secdiscardable_hash))
return false;
}
auto key_path = volkey_path(misc_path, volume_uuid);
- if (fs_mkdirs(key_path.c_str(), 0700) != 0) {
- PLOG(ERROR) << "Creating directories for: " << key_path;
- return false;
- }
+ if (!android::vold::MkdirsSync(key_path, 0700)) return false;
android::vold::KeyAuthentication auth("", secdiscardable_hash);
EncryptionOptions options;
@@ -704,7 +697,6 @@
if (!get_ce_key_new_path(directory_path, paths, &ce_key_path)) return false;
if (!android::vold::storeKeyAtomically(ce_key_path, user_key_temp, store_auth, ce_key))
return false;
- if (!android::vold::FsyncDirectory(directory_path)) return false;
return true;
}
@@ -794,11 +786,6 @@
static bool prepare_subdirs(const std::string& action, const std::string& volume_uuid,
userid_t user_id, int flags) {
- // TODO(b/141677108): Remove this & make it the default behavior
- if (android::base::GetProperty("ro.vold.level_from_user", "1") == "1") {
- flags |= android::os::IVold::STORAGE_FLAG_LEVEL_FROM_USER;
- }
-
if (0 != android::vold::ForkExecvp(
std::vector<std::string>{prepare_subdirs_path, action, volume_uuid,
std::to_string(user_id), std::to_string(flags)})) {
diff --git a/IdleMaint.cpp b/IdleMaint.cpp
index e4a1806..4c3041b 100644
--- a/IdleMaint.cpp
+++ b/IdleMaint.cpp
@@ -22,12 +22,16 @@
#include "model/PrivateVolume.h"
#include <thread>
+#include <utility>
+#include <aidl/android/hardware/health/storage/BnGarbageCollectCallback.h>
+#include <aidl/android/hardware/health/storage/IStorage.h>
#include <android-base/chrono_utils.h>
#include <android-base/file.h>
#include <android-base/logging.h>
#include <android-base/stringprintf.h>
#include <android-base/strings.h>
+#include <android/binder_manager.h>
#include <android/hardware/health/storage/1.0/IStorage.h>
#include <fs_mgr.h>
#include <private/android_filesystem_config.h>
@@ -48,9 +52,14 @@
using android::base::WriteStringToFile;
using android::hardware::Return;
using android::hardware::Void;
-using android::hardware::health::storage::V1_0::IStorage;
-using android::hardware::health::storage::V1_0::IGarbageCollectCallback;
-using android::hardware::health::storage::V1_0::Result;
+using AStorage = aidl::android::hardware::health::storage::IStorage;
+using ABnGarbageCollectCallback =
+ aidl::android::hardware::health::storage::BnGarbageCollectCallback;
+using AResult = aidl::android::hardware::health::storage::Result;
+using HStorage = android::hardware::health::storage::V1_0::IStorage;
+using HGarbageCollectCallback = android::hardware::health::storage::V1_0::IGarbageCollectCallback;
+using HResult = android::hardware::health::storage::V1_0::Result;
+using std::string_literals::operator""s;
namespace android {
namespace vold {
@@ -300,26 +309,33 @@
return;
}
-class GcCallback : public IGarbageCollectCallback {
- public:
- Return<void> onFinish(Result result) override {
+enum class IDL { HIDL, AIDL };
+std::ostream& operator<<(std::ostream& os, IDL idl) {
+ return os << (idl == IDL::HIDL ? "HIDL" : "AIDL");
+}
+
+template <IDL idl, typename Result>
+class GcCallbackImpl {
+ protected:
+ void onFinishInternal(Result result) {
std::unique_lock<std::mutex> lock(mMutex);
mFinished = true;
mResult = result;
lock.unlock();
mCv.notify_all();
- return Void();
}
+
+ public:
void wait(uint64_t seconds) {
std::unique_lock<std::mutex> lock(mMutex);
mCv.wait_for(lock, std::chrono::seconds(seconds), [this] { return mFinished; });
if (!mFinished) {
- LOG(WARNING) << "Dev GC on HAL timeout";
+ LOG(WARNING) << "Dev GC on " << idl << " HAL timeout";
} else if (mResult != Result::SUCCESS) {
- LOG(WARNING) << "Dev GC on HAL failed with " << toString(mResult);
+ LOG(WARNING) << "Dev GC on " << idl << " HAL failed with " << toString(mResult);
} else {
- LOG(INFO) << "Dev GC on HAL successful";
+ LOG(INFO) << "Dev GC on " << idl << " HAL successful";
}
}
@@ -330,25 +346,57 @@
Result mResult{Result::UNKNOWN_ERROR};
};
-static void runDevGcOnHal(sp<IStorage> service) {
- LOG(DEBUG) << "Start Dev GC on HAL";
- sp<GcCallback> cb = new GcCallback();
+class AGcCallbackImpl : public ABnGarbageCollectCallback,
+ public GcCallbackImpl<IDL::AIDL, AResult> {
+ ndk::ScopedAStatus onFinish(AResult result) override {
+ onFinishInternal(result);
+ return ndk::ScopedAStatus::ok();
+ }
+};
+
+class HGcCallbackImpl : public HGarbageCollectCallback, public GcCallbackImpl<IDL::HIDL, HResult> {
+ Return<void> onFinish(HResult result) override {
+ onFinishInternal(result);
+ return Void();
+ }
+};
+
+template <IDL idl, typename Service, typename GcCallbackImpl, typename GetDescription>
+static void runDevGcOnHal(Service service, GcCallbackImpl cb, GetDescription get_description) {
+ LOG(DEBUG) << "Start Dev GC on " << idl << " HAL";
auto ret = service->garbageCollect(DEVGC_TIMEOUT_SEC, cb);
if (!ret.isOk()) {
- LOG(WARNING) << "Cannot start Dev GC on HAL: " << ret.description();
+ LOG(WARNING) << "Cannot start Dev GC on " << idl
+ << " HAL: " << std::invoke(get_description, ret);
return;
}
cb->wait(DEVGC_TIMEOUT_SEC);
}
static void runDevGc(void) {
- auto service = IStorage::getService();
- if (service != nullptr) {
- runDevGcOnHal(service);
- } else {
- // fallback to legacy code path
- runDevGcFstab();
+ auto aidl_service_name = AStorage::descriptor + "/default"s;
+ if (AServiceManager_isDeclared(aidl_service_name.c_str())) {
+ ndk::SpAIBinder binder(AServiceManager_waitForService(aidl_service_name.c_str()));
+ if (binder.get() != nullptr) {
+ std::shared_ptr<AStorage> aidl_service = AStorage::fromBinder(binder);
+ if (aidl_service != nullptr) {
+ runDevGcOnHal<IDL::AIDL>(aidl_service, ndk::SharedRefBase::make<AGcCallbackImpl>(),
+ &ndk::ScopedAStatus::getDescription);
+ return;
+ }
+ }
+ LOG(WARNING) << "Device declares " << aidl_service_name
+ << " but it is not running, skip dev GC on AIDL HAL";
+ return;
}
+ auto hidl_service = HStorage::getService();
+ if (hidl_service != nullptr) {
+ runDevGcOnHal<IDL::HIDL>(hidl_service, sp<HGcCallbackImpl>(new HGcCallbackImpl()),
+ &Return<void>::description);
+ return;
+ }
+ // fallback to legacy code path
+ runDevGcFstab();
}
int RunIdleMaint(const android::sp<android::os::IVoldTaskListener>& listener) {
diff --git a/KeyStorage.cpp b/KeyStorage.cpp
index 8147827..457bb66 100644
--- a/KeyStorage.cpp
+++ b/KeyStorage.cpp
@@ -22,6 +22,8 @@
#include "Utils.h"
#include <algorithm>
+#include <memory>
+#include <mutex>
#include <thread>
#include <vector>
@@ -82,6 +84,31 @@
static const char* kFn_stretching = "stretching";
static const char* kFn_version = "version";
+namespace {
+
+// Storage binding info for ensuring key encryption keys include a
+// platform-provided seed in their derivation.
+struct StorageBindingInfo {
+ enum class State {
+ UNINITIALIZED,
+ IN_USE, // key storage keys are bound to seed
+ NOT_USED, // key storage keys are NOT bound to seed
+ };
+
+ // Binding seed mixed into all key storage keys.
+ std::vector<uint8_t> seed;
+
+ // State tracker for the key storage key binding.
+ State state = State::UNINITIALIZED;
+
+ std::mutex guard;
+};
+
+// Never freed as the dtor is non-trivial.
+StorageBindingInfo& storage_binding_info = *new StorageBindingInfo;
+
+} // namespace
+
static bool checkSize(const std::string& kind, size_t actual, size_t expected) {
if (actual != expected) {
LOG(ERROR) << "Wrong number of bytes in " << kind << ", expected " << expected << " got "
@@ -456,6 +483,20 @@
std::string stretched;
if (!stretchSecret(stretching, auth.secret, salt, &stretched)) return false;
*appId = secdiscardable_hash + stretched;
+
+ const std::lock_guard<std::mutex> scope_lock(storage_binding_info.guard);
+ switch (storage_binding_info.state) {
+ case StorageBindingInfo::State::UNINITIALIZED:
+ storage_binding_info.state = StorageBindingInfo::State::NOT_USED;
+ break;
+ case StorageBindingInfo::State::IN_USE:
+ appId->append(storage_binding_info.seed.begin(), storage_binding_info.seed.end());
+ break;
+ case StorageBindingInfo::State::NOT_USED:
+ // noop
+ break;
+ }
+
return true;
}
@@ -565,10 +606,6 @@
return true;
}
-bool pathExists(const std::string& path) {
- return access(path.c_str(), F_OK) == 0;
-}
-
bool storeKey(const std::string& dir, const KeyAuthentication& auth, const KeyBuffer& key) {
if (TEMP_FAILURE_RETRY(mkdir(dir.c_str(), 0700)) == -1) {
PLOG(ERROR) << "key mkdir " << dir;
@@ -624,6 +661,7 @@
PLOG(ERROR) << "Unable to move new key to location: " << key_path;
return false;
}
+ if (!FsyncParentDirectory(key_path)) return false;
LOG(DEBUG) << "Created key: " << key_path;
return true;
}
@@ -715,5 +753,22 @@
return success;
}
+bool setKeyStorageBindingSeed(const std::vector<uint8_t>& seed) {
+ const std::lock_guard<std::mutex> scope_lock(storage_binding_info.guard);
+ switch (storage_binding_info.state) {
+ case StorageBindingInfo::State::UNINITIALIZED:
+ storage_binding_info.state = StorageBindingInfo::State::IN_USE;
+ storage_binding_info.seed = seed;
+ return true;
+ case StorageBindingInfo::State::IN_USE:
+ LOG(ERROR) << "key storage binding seed already set";
+ return false;
+ case StorageBindingInfo::State::NOT_USED:
+ LOG(ERROR) << "key storage already in use without binding";
+ return false;
+ }
+ return false;
+}
+
} // namespace vold
} // namespace android
diff --git a/KeyStorage.h b/KeyStorage.h
index 1eb26ae..5fded41 100644
--- a/KeyStorage.h
+++ b/KeyStorage.h
@@ -19,7 +19,9 @@
#include "KeyBuffer.h"
+#include <cstdint>
#include <string>
+#include <vector>
namespace android {
namespace vold {
@@ -41,9 +43,6 @@
extern const KeyAuthentication kEmptyAuthentication;
-// Checks if path "path" exists.
-bool pathExists(const std::string& path);
-
bool createSecdiscardable(const std::string& path, std::string* hash);
bool readSecdiscardable(const std::string& path, std::string* hash);
@@ -56,7 +55,8 @@
// Create a directory at the named path, and store "key" in it as storeKey
// This version creates the key in "tmp_path" then atomically renames "tmp_path"
// to "key_path" thereby ensuring that the key is either stored entirely or
-// not at all.
+// not at all. All the needed files and directories are also fsync'ed to ensure
+// that the key is actually persisted to disk.
bool storeKeyAtomically(const std::string& key_path, const std::string& tmp_path,
const KeyAuthentication& auth, const KeyBuffer& key);
@@ -72,6 +72,9 @@
bool generateWrappedStorageKey(KeyBuffer* key);
// Export the per-boot boot wrapped storage key using keymaster.
bool exportWrappedStorageKey(const KeyBuffer& kmKey, KeyBuffer* key);
+
+// Set a seed to be mixed into all key storage encryption keys.
+bool setKeyStorageBindingSeed(const std::vector<uint8_t>& seed);
} // namespace vold
} // namespace android
diff --git a/MetadataCrypt.cpp b/MetadataCrypt.cpp
index cf7c5f7..dc50679 100644
--- a/MetadataCrypt.cpp
+++ b/MetadataCrypt.cpp
@@ -41,6 +41,8 @@
#include "Keymaster.h"
#include "Utils.h"
#include "VoldUtil.h"
+#include "fs/Ext4.h"
+#include "fs/F2fs.h"
namespace android {
namespace vold {
@@ -109,10 +111,7 @@
std::string sKey;
auto dir = metadata_key_dir + "/key";
LOG(DEBUG) << "metadata_key_dir/key: " << dir;
- if (fs_mkdirs(dir.c_str(), 0700)) {
- PLOG(ERROR) << "Creating directories: " << dir;
- return false;
- }
+ if (!MkdirsSync(dir, 0700)) return false;
auto temp = metadata_key_dir + "/tmp";
return retrieveOrGenerateKey(dir, temp, kEmptyAuthentication, gen, key);
}
@@ -202,8 +201,11 @@
}
bool fscrypt_mount_metadata_encrypted(const std::string& blk_device, const std::string& mount_point,
- bool needs_encrypt) {
- LOG(DEBUG) << "fscrypt_mount_metadata_encrypted: " << mount_point << " " << needs_encrypt;
+ bool needs_encrypt, bool should_format,
+ const std::string& fs_type) {
+ LOG(DEBUG) << "fscrypt_mount_metadata_encrypted: " << mount_point
+ << " encrypt: " << needs_encrypt << " format: " << should_format << " with "
+ << fs_type;
auto encrypted_state = android::base::GetProperty("ro.crypto.state", "");
if (encrypted_state != "" && encrypted_state != "encrypted") {
LOG(DEBUG) << "fscrypt_enable_crypto got unexpected starting state: " << encrypted_state;
@@ -250,8 +252,24 @@
if (!create_crypto_blk_dev(kDmNameUserdata, blk_device, key, options, &crypto_blkdev, &nr_sec))
return false;
- // FIXME handle the corrupt case
- if (needs_encrypt && !encrypt_inplace(crypto_blkdev, blk_device, nr_sec, false)) return false;
+ if (needs_encrypt) {
+ if (should_format) {
+ status_t error;
+
+ if (fs_type == "ext4") {
+ error = ext4::Format(crypto_blkdev, 0, mount_point);
+ } else if (fs_type == "f2fs") {
+ error = f2fs::Format(crypto_blkdev);
+ } else {
+ LOG(ERROR) << "Unknown filesystem type: " << fs_type;
+ return false;
+ }
+ LOG(DEBUG) << "Format (err=" << error << ") " << crypto_blkdev << " on " << mount_point;
+ if (error != 0) return false;
+ } else {
+ if (!encrypt_inplace(crypto_blkdev, blk_device, nr_sec, false)) return false;
+ }
+ }
LOG(DEBUG) << "Mounting metadata-encrypted filesystem:" << mount_point;
mount_via_fs_mgr(mount_point.c_str(), crypto_blkdev.c_str());
diff --git a/MetadataCrypt.h b/MetadataCrypt.h
index 7341a08..e482765 100644
--- a/MetadataCrypt.h
+++ b/MetadataCrypt.h
@@ -26,7 +26,8 @@
namespace vold {
bool fscrypt_mount_metadata_encrypted(const std::string& block_device,
- const std::string& mount_point, bool needs_encrypt);
+ const std::string& mount_point, bool needs_encrypt,
+ bool should_format, const std::string& fs_type);
bool defaultkey_volume_keygen(KeyGeneration* gen);
diff --git a/Utils.cpp b/Utils.cpp
index d5648f7..973908a 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -1349,6 +1349,10 @@
return -1;
}
+bool pathExists(const std::string& path) {
+ return access(path.c_str(), F_OK) == 0;
+}
+
bool FsyncDirectory(const std::string& dirname) {
android::base::unique_fd fd(TEMP_FAILURE_RETRY(open(dirname.c_str(), O_RDONLY | O_CLOEXEC)));
if (fd == -1) {
@@ -1367,6 +1371,40 @@
return true;
}
+bool FsyncParentDirectory(const std::string& path) {
+ return FsyncDirectory(android::base::Dirname(path));
+}
+
+// Creates all parent directories of |path| that don't already exist. Assigns
+// the specified |mode| to any new directories, and also fsync()s their parent
+// directories so that the new directories get written to disk right away.
+bool MkdirsSync(const std::string& path, mode_t mode) {
+ if (path[0] != '/') {
+ LOG(ERROR) << "MkdirsSync() needs an absolute path, but got " << path;
+ return false;
+ }
+ std::vector<std::string> components = android::base::Split(android::base::Dirname(path), "/");
+
+ std::string current_dir = "/";
+ for (const std::string& component : components) {
+ if (component.empty()) continue;
+
+ std::string parent_dir = current_dir;
+ if (current_dir != "/") current_dir += "/";
+ current_dir += component;
+
+ if (!pathExists(current_dir)) {
+ if (mkdir(current_dir.c_str(), mode) != 0) {
+ PLOG(ERROR) << "Failed to create " << current_dir;
+ return false;
+ }
+ if (!FsyncDirectory(parent_dir)) return false;
+ LOG(DEBUG) << "Created directory " << current_dir;
+ }
+ }
+ return true;
+}
+
bool writeStringToFile(const std::string& payload, const std::string& filename) {
android::base::unique_fd fd(TEMP_FAILURE_RETRY(
open(filename.c_str(), O_WRONLY | O_CREAT | O_NOFOLLOW | O_TRUNC | O_CLOEXEC, 0666)));
diff --git a/Utils.h b/Utils.h
index cf3fd9b..53e09ba 100644
--- a/Utils.h
+++ b/Utils.h
@@ -34,7 +34,6 @@
namespace android {
namespace vold {
-static const char* kPropFuse = "persist.sys.fuse";
static const char* kVoldAppDataIsolationEnabled = "persist.sys.vold_app_data_isolation_enabled";
static const char* kExternalStorageSdcardfs = "external_storage.sdcardfs.enabled";
@@ -177,8 +176,14 @@
status_t WaitForFile(const char* filename, std::chrono::nanoseconds timeout);
+bool pathExists(const std::string& path);
+
bool FsyncDirectory(const std::string& dirname);
+bool FsyncParentDirectory(const std::string& path);
+
+bool MkdirsSync(const std::string& path, mode_t mode);
+
bool writeStringToFile(const std::string& payload, const std::string& filename);
void ConfigureMaxDirtyRatioForFuse(const std::string& fuse_mount, unsigned int max_ratio);
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 864a6f0..b7f1749 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -33,6 +33,7 @@
#include "Checkpoint.h"
#include "FsCrypt.h"
#include "IdleMaint.h"
+#include "KeyStorage.h"
#include "Keymaster.h"
#include "MetadataCrypt.h"
#include "MoveStorage.h"
@@ -282,12 +283,6 @@
return translate(res);
}
- if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
- res = VolumeManager::Instance()->setPrimary(vol);
- if (res != OK) {
- return translate(res);
- }
- }
return translate(OK);
}
@@ -383,7 +378,17 @@
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
- return translate(VolumeManager::Instance()->remountAppStorageDirs(uid, pid, packageNames));
+ return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid,
+ false /* doUnmount */, packageNames));
+}
+
+binder::Status VoldNativeService::unmountAppStorageDirs(int uid, int pid,
+ const std::vector<std::string>& packageNames) {
+ ENFORCE_SYSTEM_OR_ROOT;
+ ACQUIRE_LOCK;
+
+ return translate(VolumeManager::Instance()->handleAppStorageDirs(uid, pid,
+ true /* doUnmount */, packageNames));
}
binder::Status VoldNativeService::setupAppDir(const std::string& path, int32_t appUid) {
@@ -681,15 +686,25 @@
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
- return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false));
+ return translateBool(
+ fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false, false, "null"));
}
binder::Status VoldNativeService::encryptFstab(const std::string& blkDevice,
- const std::string& mountPoint) {
+ const std::string& mountPoint, bool shouldFormat,
+ const std::string& fsType) {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
- return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true));
+ return translateBool(
+ fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true, shouldFormat, fsType));
+}
+
+binder::Status VoldNativeService::setStorageBindingSeed(const std::vector<uint8_t>& seed) {
+ ENFORCE_SYSTEM_OR_ROOT;
+ ACQUIRE_CRYPT_LOCK;
+
+ return translateBool(setKeyStorageBindingSeed(seed));
}
binder::Status VoldNativeService::createUserKey(int32_t userId, int32_t userSerial,
@@ -888,10 +903,16 @@
return Ok();
}
+static void initializeIncFs() {
+ // Obtaining IncFS features triggers initialization of IncFS.
+ incfs::features();
+}
+
binder::Status VoldNativeService::earlyBootEnded() {
ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
+ initializeIncFs();
Keymaster::earlyBootEnded();
return Ok();
}
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 0a55af4..123f127 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -66,6 +66,8 @@
binder::Status remountUid(int32_t uid, int32_t remountMode);
binder::Status remountAppStorageDirs(int uid, int pid,
const std::vector<std::string>& packageNames);
+ binder::Status unmountAppStorageDirs(int uid, int pid,
+ const std::vector<std::string>& packageNames);
binder::Status ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid);
binder::Status setupAppDir(const std::string& path, int32_t appUid);
@@ -111,7 +113,10 @@
binder::Status initUser0();
binder::Status isConvertibleToFbe(bool* _aidl_return);
binder::Status mountFstab(const std::string& blkDevice, const std::string& mountPoint);
- binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint);
+ binder::Status encryptFstab(const std::string& blkDevice, const std::string& mountPoint,
+ bool shouldFormat, const std::string& fsType);
+
+ binder::Status setStorageBindingSeed(const std::vector<uint8_t>& seed);
binder::Status createUserKey(int32_t userId, int32_t userSerial, bool ephemeral);
binder::Status destroyUserKey(int32_t userId);
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 714122d..f97397d 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -369,21 +369,6 @@
return success ? 0 : -1;
}
-int VolumeManager::linkPrimary(userid_t userId) {
- if (!GetBoolProperty(android::vold::kPropFuse, false)) {
- std::string source(mPrimary->getPath());
- if (mPrimary->isEmulated()) {
- source = StringPrintf("%s/%d", source.c_str(), userId);
- fs_prepare_dir(source.c_str(), 0755, AID_ROOT, AID_ROOT);
- }
-
- std::string target(StringPrintf("/mnt/user/%d/primary", userId));
- LOG(DEBUG) << "Linking " << source << " to " << target;
- Symlink(source, target);
- }
- return 0;
-}
-
void VolumeManager::destroyEmulatedVolumesForUser(userid_t userId) {
// Destroy and remove all unstacked EmulatedVolumes for the user
auto i = mInternalEmulatedVolumes.begin();
@@ -464,18 +449,6 @@
createEmulatedVolumesForUser(userId);
}
- if (!GetBoolProperty(android::vold::kPropFuse, false)) {
- // Note that sometimes the system will spin up processes from Zygote
- // before actually starting the user, so we're okay if Zygote
- // already created this directory.
- std::string path(StringPrintf("%s/%d", kPathUserMount, userId));
- fs_prepare_dir(path.c_str(), 0755, AID_ROOT, AID_ROOT);
-
- if (mPrimary) {
- linkPrimary(userId);
- }
- }
-
mStartedUsers.insert(userId);
createPendingDisksIfNeeded();
@@ -512,14 +485,6 @@
return 0;
}
-int VolumeManager::setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol) {
- mPrimary = vol;
- for (userid_t userId : mStartedUsers) {
- linkPrimary(userId);
- }
- return 0;
-}
-
// This code is executed after a fork so it's very important that the set of
// methods we call here is strictly limited.
//
@@ -718,15 +683,42 @@
return true;
}
-int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
- if (GetBoolProperty(android::vold::kPropFuse, false)) {
- // TODO(135341433): Implement fuse specific logic.
- return 0;
+// In each app's namespace, unmount obb and data dirs
+static bool umountStorageDirs(int nsFd, const char* android_data_dir, const char* android_obb_dir,
+ int uid, const char* targets[], int size) {
+ // This code is executed after a fork so it's very important that the set of
+ // methods we call here is strictly limited.
+ if (setns(nsFd, CLONE_NEWNS) != 0) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to setns %s", strerror(errno));
+ return false;
}
- return scanProcProcesses(uid, static_cast<userid_t>(-1),
- forkAndRemountChild, &mountMode) ? 0 : -1;
-}
+ // Unmount of Android/data/foo needs to be done before Android/data below.
+ bool result = true;
+ for (int i = 0; i < size; i++) {
+ if (TEMP_FAILURE_RETRY(umount2(targets[i], MNT_DETACH)) < 0 && errno != EINVAL &&
+ errno != ENOENT) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s: %s",
+ targets[i], strerror(errno));
+ result = false;
+ }
+ }
+
+ // Mount tmpfs on Android/data and Android/obb
+ if (TEMP_FAILURE_RETRY(umount2(android_data_dir, MNT_DETACH)) < 0 && errno != EINVAL &&
+ errno != ENOENT) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s",
+ android_data_dir, strerror(errno));
+ result = false;
+ }
+ if (TEMP_FAILURE_RETRY(umount2(android_obb_dir, MNT_DETACH)) < 0 && errno != EINVAL &&
+ errno != ENOENT) {
+ async_safe_format_log(ANDROID_LOG_ERROR, "vold", "Failed to umount %s :%s",
+ android_obb_dir, strerror(errno));
+ result = false;
+ }
+ return result;
+}
// In each app's namespace, mount tmpfs on obb and data dir, and bind mount obb and data
// package dirs.
@@ -786,8 +778,8 @@
userId, dirName.c_str(), packageName.c_str());
}
-// Fork the process and remount storage
-bool VolumeManager::forkAndRemountStorage(int uid, int pid,
+// Fork the process and remount / unmount app data and obb dirs
+bool VolumeManager::forkAndRemountStorage(int uid, int pid, bool doUnmount,
const std::vector<std::string>& packageNames) {
userid_t userId = multiuser_get_user_id(uid);
std::string mnt_path = StringPrintf("/proc/%d/ns/mnt", pid);
@@ -821,17 +813,18 @@
}
for (int i = 0; i < size; i++) {
- auto status = EnsureDirExists(sources_cstr[i], 0771, AID_MEDIA_RW, AID_MEDIA_RW);
- if (status != OK) {
- PLOG(ERROR) << "Failed to create dir: " << sources_cstr[i];
- return false;
- }
// Make sure /storage/emulated/... paths are setup correctly
- status = setupAppDir(targets_cstr[i], uid, false /* fixupExistingOnly */);
+ // This needs to be done before EnsureDirExists to ensure Android/ is created.
+ auto status = setupAppDir(targets_cstr[i], uid, false /* fixupExistingOnly */);
if (status != OK) {
PLOG(ERROR) << "Failed to create dir: " << targets_cstr[i];
return false;
}
+ status = EnsureDirExists(sources_cstr[i], 0771, AID_MEDIA_RW, AID_MEDIA_RW);
+ if (status != OK) {
+ PLOG(ERROR) << "Failed to create dir: " << sources_cstr[i];
+ return false;
+ }
}
char android_data_dir[PATH_MAX];
@@ -843,11 +836,20 @@
// Fork a child to mount Android/obb android Android/data dirs, as we don't want it to affect
// original vold process mount namespace.
if (!(child = fork())) {
- if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
- sources_cstr, targets_cstr, size)) {
- _exit(0);
+ if (doUnmount) {
+ if (umountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
+ targets_cstr, size)) {
+ _exit(0);
+ } else {
+ _exit(1);
+ }
} else {
- _exit(1);
+ if (remountStorageDirs(nsFd, android_data_dir, android_obb_dir, uid,
+ sources_cstr, targets_cstr, size)) {
+ _exit(0);
+ } else {
+ _exit(1);
+ }
}
}
@@ -872,11 +874,8 @@
return true;
}
-int VolumeManager::remountAppStorageDirs(int uid, int pid,
- const std::vector<std::string>& packageNames) {
- if (!GetBoolProperty(android::vold::kPropFuse, false)) {
- return 0;
- }
+int VolumeManager::handleAppStorageDirs(int uid, int pid,
+ bool doUnmount, const std::vector<std::string>& packageNames) {
// Only run the remount if fuse is mounted for that user.
userid_t userId = multiuser_get_user_id(uid);
bool fuseMounted = false;
@@ -890,7 +889,7 @@
}
}
if (fuseMounted) {
- forkAndRemountStorage(uid, pid, packageNames);
+ forkAndRemountStorage(uid, pid, doUnmount, packageNames);
}
return 0;
}
@@ -985,11 +984,6 @@
}
int VolumeManager::ensureAppDirsCreated(const std::vector<std::string>& paths, int32_t appUid) {
- if (IsSdcardfsUsed()) {
- // sdcardfs magically does this for us
- return OK;
- }
-
int size = paths.size();
for (int i = 0; i < size; i++) {
int result = setupAppDir(paths[i], appUid, false /* fixupExistingOnly */,
@@ -1145,9 +1139,14 @@
auto vol = std::shared_ptr<android::vold::StubVolume>(
new android::vold::StubVolume(stubId, sourcePath, mountPath, fsType, fsUuid, fsLabel));
- int32_t passedFlags = android::vold::Disk::Flags::kStub;
+ int32_t passedFlags = 0;
passedFlags |= (flags & android::vold::Disk::Flags::kUsb);
passedFlags |= (flags & android::vold::Disk::Flags::kSd);
+ if (flags & android::vold::Disk::Flags::kStubVisible) {
+ passedFlags |= (flags & android::vold::Disk::Flags::kStubVisible);
+ } else {
+ passedFlags |= (flags & android::vold::Disk::Flags::kStubInvisible);
+ }
// StubDisk doesn't have device node corresponds to it. So, a fake device
// number is used.
auto disk = std::shared_ptr<android::vold::Disk>(
diff --git a/VolumeManager.h b/VolumeManager.h
index 932b81c..3573b1a 100644
--- a/VolumeManager.h
+++ b/VolumeManager.h
@@ -114,10 +114,9 @@
void createPendingDisksIfNeeded();
int onSecureKeyguardStateChanged(bool isShowing);
- int setPrimary(const std::shared_ptr<android::vold::VolumeBase>& vol);
-
- int remountUid(uid_t uid, int32_t remountMode);
- int remountAppStorageDirs(int uid, int pid, const std::vector<std::string>& packageNames);
+ int remountUid(uid_t uid, int32_t remountMode) { return 0; }
+ int handleAppStorageDirs(int uid, int pid,
+ bool doUnmount, const std::vector<std::string>& packageNames);
/* Aborts all FUSE filesystems, in case the FUSE daemon is no longer up. */
int abortFuse();
@@ -131,7 +130,8 @@
int updateVirtualDisk();
int setDebug(bool enable);
- bool forkAndRemountStorage(int uid, int pid, const std::vector<std::string>& packageNames);
+ bool forkAndRemountStorage(int uid, int pid, bool doUnmount,
+ const std::vector<std::string>& packageNames);
static VolumeManager* Instance();
diff --git a/bench/inodeop_bench/Android.bp b/bench/inodeop_bench/Android.bp
index a01ddd1..3d1769e 100644
--- a/bench/inodeop_bench/Android.bp
+++ b/bench/inodeop_bench/Android.bp
@@ -13,6 +13,10 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
cc_binary {
name: "inodeop_bench",
srcs: ["inodeop_bench.cpp"],
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index ef4f89a..24a3b38 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -54,6 +54,7 @@
void remountUid(int uid, int remountMode);
void remountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames);
+ void unmountAppStorageDirs(int uid, int pid, in @utf8InCpp String[] packageNames);
void setupAppDir(@utf8InCpp String path, int appUid);
void fixupAppDir(@utf8InCpp String path, int appUid);
@@ -88,7 +89,9 @@
void initUser0();
boolean isConvertibleToFbe();
void mountFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint);
- void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint);
+ void encryptFstab(@utf8InCpp String blkDevice, @utf8InCpp String mountPoint, boolean shouldFormat, @utf8InCpp String fsType);
+
+ void setStorageBindingSeed(in byte[] seed);
void createUserKey(int userId, int userSerial, boolean ephemeral);
void destroyUserKey(int userId);
@@ -168,7 +171,6 @@
const int STORAGE_FLAG_DE = 1;
const int STORAGE_FLAG_CE = 2;
- const int STORAGE_FLAG_LEVEL_FROM_USER = 4;
const int REMOUNT_MODE_NONE = 0;
const int REMOUNT_MODE_DEFAULT = 1;
diff --git a/model/Disk.h b/model/Disk.h
index 99c98fc..16476dc 100644
--- a/model/Disk.h
+++ b/model/Disk.h
@@ -53,9 +53,12 @@
kUsb = 1 << 3,
/* Flag that disk is EMMC internal */
kEmmc = 1 << 4,
- /* Flag that disk is Stub disk, i.e., disk that is managed from outside
- * Android (e.g., ARC++). */
- kStub = 1 << 5,
+ /* Flag that disk is an invisible Stub disk, i.e., disk that is managed from outside
+ * Android (e.g., ARC++) and invisible to apps. */
+ kStubInvisible = 1 << 5,
+ /* Flag that disk is a visible Stub disk, i.e., disk that is managed from outside
+ * Android (e.g., ARC++) and visible to apps. */
+ kStubVisible = 1 << 6,
};
const std::string& getId() const { return mId; }
@@ -120,7 +123,7 @@
int getMaxMinors();
- bool isStub() { return mFlags & kStub; }
+ bool isStub() { return (mFlags & kStubInvisible) || (mFlags & kStubVisible); }
DISALLOW_COPY_AND_ASSIGN(Disk);
};
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index db93bc2..4a77846 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -301,8 +301,6 @@
dev_t before = GetDevice(mSdcardFsFull);
- bool isFuse = base::GetBoolProperty(kPropFuse, false);
-
// Mount sdcardfs regardless of FUSE, since we need it to bind-mount on top of the
// FUSE volume for various reasons.
if (mUseSdcardFs && getMountUserId() == 0) {
@@ -350,7 +348,7 @@
sdcardFsPid = 0;
}
- if (isFuse && isVisible) {
+ if (isVisible) {
// Make sure we unmount sdcardfs if we bail out with an error below
auto sdcardfs_unmounter = [&]() {
LOG(INFO) << "sdcardfs_unmounter scope_guard running";
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index d40e3e3..12e31ff 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -227,39 +227,36 @@
TEMP_FAILURE_RETRY(waitpid(sdcardFsPid, nullptr, 0));
}
- bool isFuse = base::GetBoolProperty(kPropFuse, false);
- if (isFuse) {
- // We need to mount FUSE *after* sdcardfs, since the FUSE daemon may depend
- // on sdcardfs being up.
- LOG(INFO) << "Mounting public fuse volume";
- android::base::unique_fd fd;
- int user_id = getMountUserId();
- int result = MountUserFuse(user_id, getInternalPath(), stableName, &fd);
+ // We need to mount FUSE *after* sdcardfs, since the FUSE daemon may depend
+ // on sdcardfs being up.
+ LOG(INFO) << "Mounting public fuse volume";
+ android::base::unique_fd fd;
+ int user_id = getMountUserId();
+ int result = MountUserFuse(user_id, getInternalPath(), stableName, &fd);
- if (result != 0) {
- LOG(ERROR) << "Failed to mount public fuse volume";
- doUnmount();
- return -result;
- }
-
- mFuseMounted = true;
- auto callback = getMountCallback();
- if (callback) {
- bool is_ready = false;
- callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
- if (!is_ready) {
- LOG(ERROR) << "Failed to complete public volume mount";
- doUnmount();
- return -EIO;
- }
- }
-
- ConfigureReadAheadForFuse(GetFuseMountPathForUser(user_id, stableName), 256u);
-
- // See comment in model/EmulatedVolume.cpp
- ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
+ if (result != 0) {
+ LOG(ERROR) << "Failed to mount public fuse volume";
+ doUnmount();
+ return -result;
}
+ mFuseMounted = true;
+ auto callback = getMountCallback();
+ if (callback) {
+ bool is_ready = false;
+ callback->onVolumeChecking(std::move(fd), getPath(), getInternalPath(), &is_ready);
+ if (!is_ready) {
+ LOG(ERROR) << "Failed to complete public volume mount";
+ doUnmount();
+ return -EIO;
+ }
+ }
+
+ ConfigureReadAheadForFuse(GetFuseMountPathForUser(user_id, stableName), 256u);
+
+ // See comment in model/EmulatedVolume.cpp
+ ConfigureMaxDirtyRatioForFuse(GetFuseMountPathForUser(user_id, stableName), 40u);
+
return OK;
}
diff --git a/tests/Android.bp b/tests/Android.bp
index b90de3a..cad96fd 100644
--- a/tests/Android.bp
+++ b/tests/Android.bp
@@ -1,3 +1,7 @@
+package {
+ default_applicable_licenses: ["Android-Apache-2.0"],
+}
+
cc_test {
name: "vold_tests",
defaults: [
diff --git a/tests/Utils_test.cpp b/tests/Utils_test.cpp
index d18dc67..35b40cd 100644
--- a/tests/Utils_test.cpp
+++ b/tests/Utils_test.cpp
@@ -14,6 +14,7 @@
* limitations under the License.
*/
+#include <android-base/file.h>
#include <gtest/gtest.h>
#include "../Utils.h"
@@ -43,5 +44,23 @@
ASSERT_EQ("QUUX", tmp);
}
+TEST_F(UtilsTest, MkdirsSyncTest) {
+ TemporaryDir temp_dir;
+ std::string temp_dir_path;
+
+ ASSERT_TRUE(android::base::Realpath(temp_dir.path, &temp_dir_path));
+
+ ASSERT_FALSE(pathExists(temp_dir_path + "/a"));
+ ASSERT_TRUE(MkdirsSync(temp_dir_path + "/a/b/c", 0700));
+ ASSERT_TRUE(pathExists(temp_dir_path + "/a"));
+ ASSERT_TRUE(pathExists(temp_dir_path + "/a/b"));
+ // The final component of the path should not be created; only the previous
+ // components should be.
+ ASSERT_FALSE(pathExists(temp_dir_path + "/a/b/c"));
+
+ // Currently, MkdirsSync() only supports absolute paths.
+ ASSERT_FALSE(MkdirsSync("foo", 0700));
+}
+
} // namespace vold
} // namespace android
diff --git a/vdc.cpp b/vdc.cpp
index 1aaeb5a..47d98de 100644
--- a/vdc.cpp
+++ b/vdc.cpp
@@ -31,9 +31,10 @@
#include "android/os/IVold.h"
#include <android-base/logging.h>
+#include <android-base/parsebool.h>
#include <android-base/parseint.h>
-#include <android-base/strings.h>
#include <android-base/stringprintf.h>
+#include <android-base/strings.h>
#include <binder/IServiceManager.h>
#include <binder/Status.h>
@@ -107,8 +108,12 @@
checkStatus(args, vold->reset());
} 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() == 4) {
- checkStatus(args, vold->encryptFstab(args[2], args[3]));
+ } else if (args[0] == "cryptfs" && args[1] == "encryptFstab" && args.size() == 6) {
+ 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]));
} else if (args[0] == "checkpoint" && args[1] == "supportsCheckpoint" && args.size() == 2) {
bool supported = false;
checkStatus(args, vold->supportsCheckpoint(&supported));
diff --git a/vold_prepare_subdirs.cpp b/vold_prepare_subdirs.cpp
index 0283614..e2afb81 100644
--- a/vold_prepare_subdirs.cpp
+++ b/vold_prepare_subdirs.cpp
@@ -166,13 +166,9 @@
static bool prepare_subdirs(const std::string& volume_uuid, int user_id, int flags) {
struct selabel_handle* sehandle = selinux_android_file_context_handle();
- const uid_t user_for_level =
- (flags & android::os::IVold::STORAGE_FLAG_LEVEL_FROM_USER) ? user_id : -1;
-
if (flags & android::os::IVold::STORAGE_FLAG_DE) {
auto user_de_path = android::vold::BuildDataUserDePath(volume_uuid, user_id);
- if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_de_path,
- user_for_level)) {
+ if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_de_path, user_id)) {
return false;
}
@@ -187,7 +183,7 @@
auto profiles_de_path = android::vold::BuildDataProfilesDePath(user_id);
if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, profiles_de_path,
- user_for_level)) {
+ user_id)) {
return false;
}
@@ -203,8 +199,7 @@
}
if (flags & android::os::IVold::STORAGE_FLAG_CE) {
auto user_ce_path = android::vold::BuildDataUserCePath(volume_uuid, user_id);
- if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_ce_path,
- user_for_level)) {
+ if (!prepare_dir_for_user(sehandle, 0771, AID_SYSTEM, AID_SYSTEM, user_ce_path, user_id)) {
return false;
}