[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;