[automerger skipped] Merge "Merge Coral/Flame into AOSP master" am: be4ff998ac -s ours am: c21f19338e -s ours am: a69c584aaa -s ours
am: da152fccb0 -s ours
am skip reason: change_id I7191bd73d8621831c5802e02817f459f1da32754 with SHA1 a2c2182b65 is in history
Change-Id: Ic687ebd01c5357d1f06b4f968bb76a8377258961
diff --git a/Android.bp b/Android.bp
index b621f35..a3f09b3 100644
--- a/Android.bp
+++ b/Android.bp
@@ -229,6 +229,7 @@
"libhardware_legacy",
"libhidlbase",
"libkeymaster4support",
+ "libutils",
],
}
diff --git a/Keymaster.h b/Keymaster.h
index 42a2b5d..9a0616d 100644
--- a/Keymaster.h
+++ b/Keymaster.h
@@ -115,7 +115,7 @@
bool isSecure();
private:
- std::unique_ptr<KmDevice> mDevice;
+ sp<KmDevice> mDevice;
DISALLOW_COPY_AND_ASSIGN(Keymaster);
static bool hmacKeyGenerated;
};
diff --git a/Utils.cpp b/Utils.cpp
index 1616d80..e5bf33d 100644
--- a/Utils.cpp
+++ b/Utils.cpp
@@ -165,7 +165,7 @@
if (!umount2(cpath, UMOUNT_NOFOLLOW) || errno == EINVAL || errno == ENOENT) {
return OK;
}
-
+ PLOG(INFO) << "ForceUnmount failed";
return -errno;
}
@@ -985,5 +985,52 @@
return true;
}
+int MountUserFuse(userid_t user_id, const std::string& relative_path,
+ android::base::unique_fd* fuse_fd) {
+ std::string path(StringPrintf("/mnt/user/%d/%s", user_id, relative_path.c_str()));
+
+ // Force remove the existing mount before we attempt to prepare the
+ // directory. If we have a dangling mount, then PrepareDir may fail if the
+ // indirection to FUSE doesn't work.
+ android::status_t result = android::vold::ForceUnmount(path);
+ if (result != android::OK) {
+ PLOG(ERROR) << "Failed to unmount " << path;
+ return -1;
+ }
+
+ // Create directories.
+ result = android::vold::PrepareDir(path, 0700, AID_ROOT, AID_ROOT);
+ if (result != android::OK) {
+ PLOG(ERROR) << "Failed to prepare directory " << path;
+ return -1;
+ }
+
+ // Open fuse fd.
+ fuse_fd->reset(open("/dev/fuse", O_RDWR | O_CLOEXEC));
+ if (fuse_fd->get() == -1) {
+ PLOG(ERROR) << "Failed to open /dev/fuse";
+ return -1;
+ }
+
+ // Note: leaving out default_permissions since we don't want kernel to do lower filesystem
+ // permission checks before routing to FUSE daemon.
+ const auto opts = StringPrintf(
+ "fd=%i,"
+ "rootmode=40000,"
+ "allow_other,"
+ "user_id=0,group_id=0,",
+ fuse_fd->get());
+
+ const int result_int =
+ TEMP_FAILURE_RETRY(mount("/dev/fuse", path.c_str(), "fuse",
+ MS_NOSUID | MS_NODEV | MS_NOEXEC | MS_NOATIME | MS_LAZYTIME,
+ opts.c_str()));
+ if (result_int != 0) {
+ PLOG(ERROR) << "Failed to mount " << path;
+ return -errno;
+ }
+ return 0;
+}
+
} // namespace vold
} // namespace android
diff --git a/Utils.h b/Utils.h
index af4e401..f607c81 100644
--- a/Utils.h
+++ b/Utils.h
@@ -20,6 +20,7 @@
#include "KeyBuffer.h"
#include <android-base/macros.h>
+#include <android-base/unique_fd.h>
#include <cutils/multiuser.h>
#include <selinux/selinux.h>
#include <utils/Errors.h>
@@ -33,6 +34,8 @@
namespace android {
namespace vold {
+static const char* kPropFuseSnapshot = "sys.fuse_snapshot";
+
/* SELinux contexts used depending on the block device type */
extern security_context_t sBlkidContext;
extern security_context_t sBlkidUntrustedContext;
@@ -147,6 +150,10 @@
bool FsyncDirectory(const std::string& dirname);
bool writeStringToFile(const std::string& payload, const std::string& filename);
+
+int MountUserFuse(userid_t user_id, const std::string& relative_path,
+ android::base::unique_fd* fuse_fd);
+
} // namespace vold
} // namespace android
diff --git a/VoldNativeService.cpp b/VoldNativeService.cpp
index 0afbab9..20e1290 100644
--- a/VoldNativeService.cpp
+++ b/VoldNativeService.cpp
@@ -92,7 +92,7 @@
}
}
-binder::Status checkUid(uid_t expectedUid) {
+binder::Status checkUidOrRoot(uid_t expectedUid) {
uid_t uid = IPCThreadState::self()->getCallingUid();
if (uid == expectedUid || uid == AID_ROOT) {
return ok();
@@ -147,12 +147,12 @@
return ok();
}
-#define ENFORCE_UID(uid) \
- { \
- binder::Status status = checkUid((uid)); \
- if (!status.isOk()) { \
- return status; \
- } \
+#define ENFORCE_SYSTEM_OR_ROOT \
+ { \
+ binder::Status status = checkUidOrRoot(AID_SYSTEM); \
+ if (!status.isOk()) { \
+ return status; \
+ } \
}
#define CHECK_ARGUMENT_ID(id) \
@@ -217,7 +217,7 @@
binder::Status VoldNativeService::setListener(
const android::sp<android::os::IVoldListener>& listener) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
VolumeManager::Instance()->setListener(listener);
@@ -225,7 +225,7 @@
}
binder::Status VoldNativeService::monitor() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
// Simply acquire/release each lock for watchdog
{ ACQUIRE_LOCK; }
@@ -235,42 +235,42 @@
}
binder::Status VoldNativeService::reset() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->reset());
}
binder::Status VoldNativeService::shutdown() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->shutdown());
}
binder::Status VoldNativeService::onUserAdded(int32_t userId, int32_t userSerial) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->onUserAdded(userId, userSerial));
}
binder::Status VoldNativeService::onUserRemoved(int32_t userId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->onUserRemoved(userId));
}
binder::Status VoldNativeService::onUserStarted(int32_t userId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->onUserStarted(userId));
}
binder::Status VoldNativeService::onUserStopped(int32_t userId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->onUserStopped(userId));
@@ -287,7 +287,7 @@
}
binder::Status VoldNativeService::onSecureKeyguardStateChanged(bool isShowing) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->onSecureKeyguardStateChanged(isShowing));
@@ -295,7 +295,7 @@
binder::Status VoldNativeService::partition(const std::string& diskId, int32_t partitionType,
int32_t ratio) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(diskId);
ACQUIRE_LOCK;
@@ -317,7 +317,7 @@
binder::Status VoldNativeService::forgetPartition(const std::string& partGuid,
const std::string& fsUuid) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_HEX(partGuid);
CHECK_ARGUMENT_HEX(fsUuid);
ACQUIRE_LOCK;
@@ -326,8 +326,9 @@
}
binder::Status VoldNativeService::mount(const std::string& volId, int32_t mountFlags,
- int32_t mountUserId) {
- ENFORCE_UID(AID_SYSTEM);
+ int32_t mountUserId,
+ android::base::unique_fd* _aidl_return) {
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
@@ -343,6 +344,14 @@
if (res != OK) {
return translate(res);
}
+
+ _aidl_return->reset(dup(vol->getFuseFd().get()));
+ if (_aidl_return->get() == -1) {
+ // Let's not return invalid fd since binder will not allow null fds. Instead give it a
+ // default value.
+ _aidl_return->reset(open("/dev/null", O_RDONLY | O_CLOEXEC));
+ }
+
if ((mountFlags & MOUNT_FLAG_PRIMARY) != 0) {
res = VolumeManager::Instance()->setPrimary(vol);
if (res != OK) {
@@ -353,7 +362,7 @@
}
binder::Status VoldNativeService::unmount(const std::string& volId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
@@ -365,7 +374,7 @@
}
binder::Status VoldNativeService::format(const std::string& volId, const std::string& fsType) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
@@ -400,7 +409,7 @@
binder::Status VoldNativeService::benchmark(
const std::string& volId, const android::sp<android::os::IVoldTaskListener>& listener) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
@@ -413,7 +422,7 @@
}
binder::Status VoldNativeService::checkEncryption(const std::string& volId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
@@ -426,7 +435,7 @@
binder::Status VoldNativeService::moveStorage(
const std::string& fromVolId, const std::string& toVolId,
const android::sp<android::os::IVoldTaskListener>& listener) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(fromVolId);
CHECK_ARGUMENT_ID(toVolId);
ACQUIRE_LOCK;
@@ -444,14 +453,14 @@
}
binder::Status VoldNativeService::remountUid(int32_t uid, int32_t remountMode) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->remountUid(uid, remountMode));
}
binder::Status VoldNativeService::mkdirs(const std::string& path) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_PATH(path);
ACQUIRE_LOCK;
@@ -461,7 +470,7 @@
binder::Status VoldNativeService::createObb(const std::string& sourcePath,
const std::string& sourceKey, int32_t ownerGid,
std::string* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_PATH(sourcePath);
CHECK_ARGUMENT_HEX(sourceKey);
ACQUIRE_LOCK;
@@ -471,7 +480,7 @@
}
binder::Status VoldNativeService::destroyObb(const std::string& volId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
@@ -481,7 +490,7 @@
binder::Status VoldNativeService::createStubVolume(
const std::string& sourcePath, const std::string& mountPath, const std::string& fsType,
const std::string& fsUuid, const std::string& fsLabel, std::string* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_PATH(sourcePath);
CHECK_ARGUMENT_PATH(mountPath);
CHECK_ARGUMENT_HEX(fsUuid);
@@ -494,7 +503,7 @@
}
binder::Status VoldNativeService::destroyStubVolume(const std::string& volId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_ID(volId);
ACQUIRE_LOCK;
@@ -503,7 +512,7 @@
binder::Status VoldNativeService::fstrim(
int32_t fstrimFlags, const android::sp<android::os::IVoldTaskListener>& listener) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
std::thread([=]() { android::vold::Trim(listener); }).detach();
@@ -512,7 +521,7 @@
binder::Status VoldNativeService::runIdleMaint(
const android::sp<android::os::IVoldTaskListener>& listener) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
std::thread([=]() { android::vold::RunIdleMaint(listener); }).detach();
@@ -521,7 +530,7 @@
binder::Status VoldNativeService::abortIdleMaint(
const android::sp<android::os::IVoldTaskListener>& listener) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
std::thread([=]() { android::vold::AbortIdleMaint(listener); }).detach();
@@ -530,14 +539,14 @@
binder::Status VoldNativeService::mountAppFuse(int32_t uid, int32_t mountId,
android::base::unique_fd* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->mountAppFuse(uid, mountId, _aidl_return));
}
binder::Status VoldNativeService::unmountAppFuse(int32_t uid, int32_t mountId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translate(VolumeManager::Instance()->unmountAppFuse(uid, mountId));
@@ -546,7 +555,7 @@
binder::Status VoldNativeService::openAppFuseFile(int32_t uid, int32_t mountId, int32_t fileId,
int32_t flags,
android::base::unique_fd* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
int fd = VolumeManager::Instance()->openAppFuseFile(uid, mountId, fileId, flags);
@@ -561,14 +570,14 @@
}
binder::Status VoldNativeService::fdeCheckPassword(const std::string& password) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_check_passwd(password.c_str()));
}
binder::Status VoldNativeService::fdeRestart() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
// Spawn as thread so init can issue commands back to vold without
@@ -578,7 +587,7 @@
}
binder::Status VoldNativeService::fdeComplete(int32_t* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
*_aidl_return = cryptfs_crypto_complete();
@@ -609,7 +618,7 @@
binder::Status VoldNativeService::fdeEnable(int32_t passwordType, const std::string& password,
int32_t encryptionFlags) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
LOG(DEBUG) << "fdeEnable(" << passwordType << ", *, " << encryptionFlags << ")";
@@ -627,21 +636,21 @@
binder::Status VoldNativeService::fdeChangePassword(int32_t passwordType,
const std::string& password) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_changepw(passwordType, password.c_str()));
}
binder::Status VoldNativeService::fdeVerifyPassword(const std::string& password) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_verify_passwd(password.c_str()));
}
binder::Status VoldNativeService::fdeGetField(const std::string& key, std::string* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
char buf[PROPERTY_VALUE_MAX];
@@ -654,14 +663,14 @@
}
binder::Status VoldNativeService::fdeSetField(const std::string& key, const std::string& value) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translate(cryptfs_setfield(key.c_str(), value.c_str()));
}
binder::Status VoldNativeService::fdeGetPasswordType(int32_t* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
*_aidl_return = cryptfs_get_password_type();
@@ -669,7 +678,7 @@
}
binder::Status VoldNativeService::fdeGetPassword(std::string* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
const char* res = cryptfs_get_password();
@@ -680,7 +689,7 @@
}
binder::Status VoldNativeService::fdeClearPassword() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
cryptfs_clear_password();
@@ -688,14 +697,14 @@
}
binder::Status VoldNativeService::fbeEnable() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_initialize_systemwide_keys());
}
binder::Status VoldNativeService::mountDefaultEncrypted() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
if (!fscrypt_is_native()) {
@@ -707,14 +716,14 @@
}
binder::Status VoldNativeService::initUser0() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_init_user0());
}
binder::Status VoldNativeService::isConvertibleToFbe(bool* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
*_aidl_return = cryptfs_isConvertibleToFBE() != 0;
@@ -723,7 +732,7 @@
binder::Status VoldNativeService::mountFstab(const std::string& blkDevice,
const std::string& mountPoint) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, false));
@@ -731,21 +740,21 @@
binder::Status VoldNativeService::encryptFstab(const std::string& blkDevice,
const std::string& mountPoint) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return translateBool(fscrypt_mount_metadata_encrypted(blkDevice, mountPoint, true));
}
binder::Status VoldNativeService::createUserKey(int32_t userId, int32_t userSerial, bool ephemeral) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_vold_create_user_key(userId, userSerial, ephemeral));
}
binder::Status VoldNativeService::destroyUserKey(int32_t userId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_destroy_user_key(userId));
@@ -754,14 +763,14 @@
binder::Status VoldNativeService::addUserKeyAuth(int32_t userId, int32_t userSerial,
const std::string& token,
const std::string& secret) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_add_user_key_auth(userId, userSerial, token, secret));
}
binder::Status VoldNativeService::fixateNewestUserKeyAuth(int32_t userId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_fixate_newest_user_key_auth(userId));
@@ -770,14 +779,14 @@
binder::Status VoldNativeService::unlockUserKey(int32_t userId, int32_t userSerial,
const std::string& token,
const std::string& secret) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_unlock_user_key(userId, userSerial, token, secret));
}
binder::Status VoldNativeService::lockUserKey(int32_t userId) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_CRYPT_LOCK;
return translateBool(fscrypt_lock_user_key(userId));
@@ -786,7 +795,7 @@
binder::Status VoldNativeService::prepareUserStorage(const std::unique_ptr<std::string>& uuid,
int32_t userId, int32_t userSerial,
int32_t flags) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
std::string empty_string = "";
auto uuid_ = uuid ? *uuid : empty_string;
CHECK_ARGUMENT_HEX(uuid_);
@@ -797,7 +806,7 @@
binder::Status VoldNativeService::destroyUserStorage(const std::unique_ptr<std::string>& uuid,
int32_t userId, int32_t flags) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
std::string empty_string = "";
auto uuid_ = uuid ? *uuid : empty_string;
CHECK_ARGUMENT_HEX(uuid_);
@@ -819,14 +828,14 @@
}
binder::Status VoldNativeService::startCheckpoint(int32_t retry) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return cp_startCheckpoint(retry);
}
binder::Status VoldNativeService::needsRollback(bool* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
*_aidl_return = cp_needsRollback();
@@ -834,7 +843,7 @@
}
binder::Status VoldNativeService::needsCheckpoint(bool* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
*_aidl_return = cp_needsCheckpoint();
@@ -842,21 +851,21 @@
}
binder::Status VoldNativeService::commitChanges() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return cp_commitChanges();
}
binder::Status VoldNativeService::prepareCheckpoint() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return cp_prepareCheckpoint();
}
binder::Status VoldNativeService::restoreCheckpoint(const std::string& mountPoint) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_PATH(mountPoint);
ACQUIRE_LOCK;
@@ -864,7 +873,7 @@
}
binder::Status VoldNativeService::restoreCheckpointPart(const std::string& mountPoint, int count) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
CHECK_ARGUMENT_PATH(mountPoint);
ACQUIRE_LOCK;
@@ -872,14 +881,14 @@
}
binder::Status VoldNativeService::markBootAttempt() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return cp_markBootAttempt();
}
binder::Status VoldNativeService::abortChanges(const std::string& message, bool retry) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
cp_abortChanges(message, retry);
@@ -887,28 +896,28 @@
}
binder::Status VoldNativeService::supportsCheckpoint(bool* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return cp_supportsCheckpoint(*_aidl_return);
}
binder::Status VoldNativeService::supportsBlockCheckpoint(bool* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return cp_supportsBlockCheckpoint(*_aidl_return);
}
binder::Status VoldNativeService::supportsFileCheckpoint(bool* _aidl_return) {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
return cp_supportsFileCheckpoint(*_aidl_return);
}
binder::Status VoldNativeService::resetCheckpoint() {
- ENFORCE_UID(AID_SYSTEM);
+ ENFORCE_SYSTEM_OR_ROOT;
ACQUIRE_LOCK;
cp_resetCheckpoint();
diff --git a/VoldNativeService.h b/VoldNativeService.h
index 13137c5..744ff84 100644
--- a/VoldNativeService.h
+++ b/VoldNativeService.h
@@ -52,7 +52,8 @@
binder::Status partition(const std::string& diskId, int32_t partitionType, int32_t ratio);
binder::Status forgetPartition(const std::string& partGuid, const std::string& fsUuid);
- binder::Status mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId);
+ binder::Status mount(const std::string& volId, int32_t mountFlags, int32_t mountUserId,
+ android::base::unique_fd* _aidl_return);
binder::Status unmount(const std::string& volId);
binder::Status format(const std::string& volId, const std::string& fsType);
binder::Status benchmark(const std::string& volId,
diff --git a/VolumeManager.cpp b/VolumeManager.cpp
index 44bff5a..b0e0b23 100644
--- a/VolumeManager.cpp
+++ b/VolumeManager.cpp
@@ -31,6 +31,7 @@
#include <sys/wait.h>
#include <unistd.h>
#include <array>
+#include <thread>
#include <linux/kdev_t.h>
@@ -100,6 +101,22 @@
VolumeManager* VolumeManager::sInstance = NULL;
+static void* symlinkPrimary(void* data) {
+ std::unique_ptr<std::pair<std::string, std::string>> linkInfo(
+ static_cast<std::pair<std::string, std::string>*>(data));
+ std::string* source = &linkInfo->first;
+ std::string* target = &linkInfo->second;
+
+ fs_prepare_dir(source->c_str(), 0755, AID_ROOT, AID_ROOT);
+ fs_prepare_dir(target->c_str(), 0755, AID_ROOT, AID_ROOT);
+ *target = *target + "/primary";
+
+ // Link source to target
+ LOG(DEBUG) << "Linking " << *source << " to " << *target;
+ Symlink(*source, *target);
+ return nullptr;
+}
+
VolumeManager* VolumeManager::Instance() {
if (!sInstance) sInstance = new VolumeManager();
return sInstance;
@@ -365,6 +382,22 @@
}
int VolumeManager::linkPrimary(userid_t userId) {
+ bool isFuse = GetBoolProperty(android::vold::kPropFuseSnapshot, false);
+
+ if (isFuse) {
+ // Here we have to touch /mnt/user/userid>/<volumeid> which was already mounted as part of
+ // the boot sequence, requiring waiting till a fuse handler is available. If we do this work
+ // in foreground we could hang the caller, i.e. system server, which needs to start the fuse
+ // handler. So do it in the background.
+ std::string source(
+ StringPrintf("/mnt/user/%d/%s/%d", userId, mPrimary->getId().c_str(), userId));
+ std::string target(StringPrintf("/mnt/user/%d/self", userId));
+
+ auto symlinkInfo = new std::pair<std::string, std::string>(source, target);
+ std::thread(symlinkPrimary, symlinkInfo).detach();
+ return 0;
+ }
+
std::string source(mPrimary->getPath());
if (mPrimary->isEmulated()) {
source = StringPrintf("%s/%d", source.c_str(), userId);
@@ -431,6 +464,10 @@
}
int VolumeManager::remountUid(uid_t uid, int32_t mountMode) {
+ if (GetBoolProperty(android::vold::kPropFuseSnapshot, false)) {
+ // TODO(135341433): Implement fuse specific logic.
+ return 0;
+ }
std::string mode;
switch (mountMode) {
case VoldNativeService::REMOUNT_MODE_NONE:
@@ -450,6 +487,9 @@
case VoldNativeService::REMOUNT_MODE_FULL:
mode = "full";
break;
+ case VoldNativeService::REMOUNT_MODE_PASS_THROUGH:
+ mode = "pass_through";
+ break;
default:
PLOG(ERROR) << "Unknown mode " << std::to_string(mountMode);
return -1;
diff --git a/binder/android/os/IVold.aidl b/binder/android/os/IVold.aidl
index 8e5c53d..91c0172 100644
--- a/binder/android/os/IVold.aidl
+++ b/binder/android/os/IVold.aidl
@@ -40,7 +40,7 @@
void partition(@utf8InCpp String diskId, int partitionType, int ratio);
void forgetPartition(@utf8InCpp String partGuid, @utf8InCpp String fsUuid);
- void mount(@utf8InCpp String volId, int mountFlags, int mountUserId);
+ FileDescriptor mount(@utf8InCpp String volId, int mountFlags, int mountUserId);
void unmount(@utf8InCpp String volId);
void format(@utf8InCpp String volId, @utf8InCpp String fsType);
void benchmark(@utf8InCpp String volId, IVoldTaskListener listener);
@@ -158,6 +158,7 @@
const int REMOUNT_MODE_LEGACY = 4;
const int REMOUNT_MODE_INSTALLER = 5;
const int REMOUNT_MODE_FULL = 6;
+ const int REMOUNT_MODE_PASS_THROUGH = 7;
const int VOLUME_STATE_UNMOUNTED = 0;
const int VOLUME_STATE_CHECKING = 1;
diff --git a/model/EmulatedVolume.cpp b/model/EmulatedVolume.cpp
index 552fe2f..c84fbb7 100644
--- a/model/EmulatedVolume.cpp
+++ b/model/EmulatedVolume.cpp
@@ -15,10 +15,13 @@
*/
#include "EmulatedVolume.h"
+
+#include "AppFuseUtil.h"
#include "Utils.h"
#include "VolumeManager.h"
#include <android-base/logging.h>
+#include <android-base/properties.h>
#include <android-base/stringprintf.h>
#include <cutils/fs.h>
#include <private/android_filesystem_config.h>
@@ -81,7 +84,27 @@
dev_t before = GetDevice(mFuseFull);
+ bool isFuse = base::GetBoolProperty(kPropFuseSnapshot, false);
+
+ if (isFuse) {
+ LOG(INFO) << "Mounting emulated fuse volume";
+ android::base::unique_fd fd;
+ int user_id = getMountUserId();
+ int result = MountUserFuse(user_id, label, &fd);
+
+ if (result != 0) {
+ PLOG(ERROR) << "Failed to mount emulated fuse volume";
+ return -result;
+ }
+ setFuseFd(std::move(fd));
+
+ std::string pass_through_path(StringPrintf("/mnt/pass_through/%d/%s",
+ user_id, label.c_str()));
+ return BindMount(getInternalPath(), pass_through_path);
+ }
+
if (!(mFusePid = fork())) {
+ LOG(INFO) << "Executing sdcardfs";
// clang-format off
if (execl(kFusePath, kFusePath,
"-u", "1023", // AID_MEDIA_RW
@@ -131,6 +154,31 @@
// ENOTCONN until the unmount completes. This is an exotic and unusual
// error code and might cause broken behaviour in applications.
KillProcessesUsingPath(getPath());
+
+ bool isFuse = base::GetBoolProperty(kPropFuseSnapshot, false);
+ if (isFuse) {
+ // We could have migrated storage to an adopted private volume, so always
+ // call primary storage "emulated" to avoid media rescans.
+ std::string label = mLabel;
+ if (getMountFlags() & MountFlags::kPrimary) {
+ label = "emulated";
+ }
+ std::string path(StringPrintf("/mnt/user/%d/%s", getMountUserId(), label.c_str()));
+ status_t result = ForceUnmount(path);
+ if (result != OK) {
+ // TODO(135341433): MNT_DETACH is needed for fuse because umount2 can fail with EBUSY.
+ // Figure out why we get EBUSY and remove this special casing if possible.
+ if (!umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) || errno == EINVAL ||
+ errno == ENOENT) {
+ PLOG(INFO) << "ForceUnmount failed on emulated fuse volume";
+ }
+ }
+
+ rmdir(path.c_str());
+ setFuseFd(android::base::unique_fd());
+ return OK;
+ }
+
ForceUnmount(mFuseDefault);
ForceUnmount(mFuseRead);
ForceUnmount(mFuseWrite);
diff --git a/model/PublicVolume.cpp b/model/PublicVolume.cpp
index 0a6b351..7b8a21f 100644
--- a/model/PublicVolume.cpp
+++ b/model/PublicVolume.cpp
@@ -15,6 +15,8 @@
*/
#include "PublicVolume.h"
+
+#include "AppFuseUtil.h"
#include "Utils.h"
#include "VolumeManager.h"
#include "fs/Exfat.h"
@@ -167,6 +169,25 @@
dev_t before = GetDevice(mFuseFull);
+ bool isFuse = base::GetBoolProperty(kPropFuseSnapshot, false);
+
+ if (isFuse) {
+ LOG(INFO) << "Mounting public fuse volume";
+ android::base::unique_fd fd;
+ int user_id = getMountUserId();
+ int result = MountUserFuse(user_id, stableName, &fd);
+
+ if (result != 0) {
+ LOG(ERROR) << "Failed to mount public fuse volume";
+ return -result;
+ }
+ setFuseFd(std::move(fd));
+
+ std::string pass_through_path(StringPrintf("/mnt/pass_through/%d/%s",
+ user_id, stableName.c_str()));
+ return BindMount(getInternalPath(), pass_through_path);
+ }
+
if (!(mFusePid = fork())) {
if (getMountFlags() & MountFlags::kPrimary) {
// clang-format off
@@ -229,6 +250,30 @@
// error code and might cause broken behaviour in applications.
KillProcessesUsingPath(getPath());
+ bool isFuse = base::GetBoolProperty(kPropFuseSnapshot, false);
+ if (isFuse) {
+ // Use UUID as stable name, if available
+ std::string stableName = getId();
+ if (!mFsUuid.empty()) {
+ stableName = mFsUuid;
+ }
+
+ std::string path(StringPrintf("/mnt/user/%d/%s", getMountUserId(), stableName.c_str()));
+ status_t result = ForceUnmount(path);
+ if (result != OK) {
+ // TODO(135341433): MNT_DETACH is needed for fuse because umount2 can fail with EBUSY.
+ // Figure out why we get EBUSY and remove this special casing if possible.
+ if (!umount2(path.c_str(), UMOUNT_NOFOLLOW | MNT_DETACH) || errno == EINVAL ||
+ errno == ENOENT) {
+ PLOG(INFO) << "ForceUnmount failed on public fuse volume";
+ }
+ }
+
+ rmdir(path.c_str());
+ setFuseFd(android::base::unique_fd());
+ return OK;
+ }
+
ForceUnmount(kAsecPath);
ForceUnmount(mFuseDefault);
diff --git a/model/VolumeBase.cpp b/model/VolumeBase.cpp
index ffc7900..08da8f6 100644
--- a/model/VolumeBase.cpp
+++ b/model/VolumeBase.cpp
@@ -143,6 +143,16 @@
return OK;
}
+status_t VolumeBase::setFuseFd(android::base::unique_fd fuseFd) {
+ if ((mState != State::kChecking) && (mState != State::kEjecting)) {
+ LOG(WARNING) << getId() << " fuse fd change requires state checking or ejecting";
+ return -EBUSY;
+ }
+
+ mFuseFd = std::move(fuseFd);
+ return OK;
+}
+
android::sp<android::os::IVoldListener> VolumeBase::getListener() const {
if (mSilent) {
return nullptr;
diff --git a/model/VolumeBase.h b/model/VolumeBase.h
index 53eeb6f..5deecdb 100644
--- a/model/VolumeBase.h
+++ b/model/VolumeBase.h
@@ -87,6 +87,7 @@
State getState() const { return mState; }
const std::string& getPath() const { return mPath; }
const std::string& getInternalPath() const { return mInternalPath; }
+ const android::base::unique_fd& getFuseFd() const { return mFuseFd; }
status_t setDiskId(const std::string& diskId);
status_t setPartGuid(const std::string& partGuid);
@@ -121,6 +122,8 @@
status_t setId(const std::string& id);
status_t setPath(const std::string& path);
status_t setInternalPath(const std::string& internalPath);
+ // Takes ownership of the fd passed in.
+ status_t setFuseFd(android::base::unique_fd fuseFd);
android::sp<android::os::IVoldListener> getListener() const;
@@ -147,6 +150,8 @@
std::string mInternalPath;
/* Flag indicating that volume should emit no events */
bool mSilent;
+ /* The filedescriptor for the fuse device, if the volume uses fuse, or -1 otherwise */
+ android::base::unique_fd mFuseFd;
/* Volumes stacked on top of this volume */
std::list<std::shared_ptr<VolumeBase>> mVolumes;